From 43912d6349ce08bb5d299b1602fba30e0354eaaa Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Fri, 10 Nov 2017 21:39:10 +0100 Subject: [PATCH] add: proper indentation when printing TLV objects --- client/emv/dump.c | 5 ++++- client/emv/dump.h | 2 +- client/emv/emv_tags.c | 41 ++++++++++++++++++++++++++++------------- client/emv/emv_tags.h | 2 +- client/emv/emvcore.c | 8 ++++---- client/emv/tlv.c | 6 +++--- client/emv/tlv.h | 4 ++-- 7 files changed, 43 insertions(+), 25 deletions(-) diff --git a/client/emv/dump.c b/client/emv/dump.c index 9915ad73..41d7c9fd 100644 --- a/client/emv/dump.c +++ b/client/emv/dump.c @@ -21,6 +21,8 @@ #include +#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, "\t");} + void dump_buffer_simple(const unsigned char *ptr, size_t len, FILE *f) { int i; @@ -32,7 +34,7 @@ void dump_buffer_simple(const unsigned char *ptr, size_t len, FILE *f) fprintf(f, "%s%02hhX", i ? " " : "", ptr[i]); } -void dump_buffer(const unsigned char *ptr, size_t len, FILE *f) +void dump_buffer(const unsigned char *ptr, size_t len, FILE *f, int level) { int i, j; @@ -40,6 +42,7 @@ void dump_buffer(const unsigned char *ptr, size_t len, FILE *f) f = stdout; for (i = 0; i < len; i += 16) { + PRINT_INDENT(level); fprintf(f, "\t%02x:", i); for (j = 0; j < 16; j++) { if (i + j < len) diff --git a/client/emv/dump.h b/client/emv/dump.h index 5976da44..ad69ea83 100644 --- a/client/emv/dump.h +++ b/client/emv/dump.h @@ -19,6 +19,6 @@ #include void dump_buffer_simple(const unsigned char *ptr, size_t len, FILE *f); -void dump_buffer(const unsigned char *ptr, size_t len, FILE *f); +void dump_buffer(const unsigned char *ptr, size_t len, FILE *f, int level); #endif diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index 1aae847a..d91685c4 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -22,6 +22,8 @@ #include +#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, "\t");} + enum emv_tag_t { EMV_TAG_GENERIC, EMV_TAG_BITMASK, @@ -230,16 +232,18 @@ static const char *bitstrings[] = { "1.......", }; -static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *tag, FILE *f) +static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { const struct emv_tag_bit *bits = tag->data; unsigned bit, byte; for (byte = 1; byte <= tlv->len; byte ++) { unsigned char val = tlv->value[byte - 1]; + PRINT_INDENT(level); fprintf(f, "\tByte %u (%02x)\n", byte, val); for (bit = 8; bit > 0; bit--, val <<= 1) { if (val & 0x80) + PRINT_INDENT(level); fprintf(f, "\t\t%s - '%s'\n", bitstrings[bit - 1], bits->bit == EMV_BIT(byte, bit) ? bits->name : "Unknown"); if (bits->bit == EMV_BIT(byte, bit)) @@ -248,7 +252,7 @@ static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *ta } } -static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, FILE *f) +static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { const unsigned char *buf = tlv->value; size_t left = tlv->len; @@ -258,20 +262,24 @@ static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, F const struct emv_tag *doltag; if (!tlv_parse_tl(&buf, &left, &doltlv)) { + PRINT_INDENT(level); fprintf(f, "Invalid Tag-Len\n"); continue; } doltag = emv_get_tag(&doltlv); + PRINT_INDENT(level); fprintf(f, "\tTag %4hx len %02zx ('%s')\n", doltlv.tag, doltlv.len, doltag->name); } } -static void emv_tag_dump_string(const struct tlv *tlv, const struct emv_tag *tag, FILE *f) +static void emv_tag_dump_string(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { + PRINT_INDENT(level); fprintf(f, "\tString value '"); fwrite(tlv->value, 1, tlv->len, f); + PRINT_INDENT(level); fprintf(f, "'\n"); } @@ -306,13 +314,15 @@ static unsigned long emv_value_numeric(const struct tlv *tlv, unsigned start, un return ret; } -static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *tag, FILE *f) +static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { + PRINT_INDENT(level); fprintf(f, "\tNumeric value %lu\n", emv_value_numeric(tlv, 0, tlv->len * 2)); } -static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, FILE *f) +static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { + PRINT_INDENT(level); fprintf(f, "\tDate: 20%02ld.%ld.%ld\n", emv_value_numeric(tlv, 0, 2), emv_value_numeric(tlv, 2, 4), @@ -324,12 +334,13 @@ static uint32_t emv_get_binary(const unsigned char *S) return (S[0] << 24) | (S[1] << 16) | (S[2] << 8) | (S[3] << 0); } -static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *tag, FILE *f) +static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { uint32_t X, Y; int i; if (tlv->len < 10 || tlv->len % 2) { + PRINT_INDENT(level); fprintf(f, "\tINVALID!\n"); return; } @@ -337,7 +348,9 @@ static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *t X = emv_get_binary(tlv->value); Y = emv_get_binary(tlv->value + 4); + PRINT_INDENT(level); fprintf(f, "\tX: %d\n", X); + PRINT_INDENT(level); fprintf(f, "\tY: %d\n", Y); for (i = 8; i < tlv->len; i+= 2) { @@ -413,13 +426,14 @@ static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *t break; } + PRINT_INDENT(level); fprintf(f, "\t%02x %02x: '%s' '%s' and '%s' if this CVM is unsuccessful\n", tlv->value[i], tlv->value[i+1], method, condition, (tlv->value[i] & 0x40) ? "continue" : "fail"); } } -bool emv_tag_dump(const struct tlv *tlv, FILE *f) +bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level) { if (!tlv) { fprintf(f, "NULL\n"); @@ -428,28 +442,29 @@ bool emv_tag_dump(const struct tlv *tlv, FILE *f) const struct emv_tag *tag = emv_get_tag(tlv); + PRINT_INDENT(level); fprintf(f, "--%2hx[%02zx] '%s':\n", tlv->tag, tlv->len, tag->name); switch (tag->type) { case EMV_TAG_GENERIC: break; case EMV_TAG_BITMASK: - emv_tag_dump_bitmask(tlv, tag, f); + emv_tag_dump_bitmask(tlv, tag, f, level); break; case EMV_TAG_DOL: - emv_tag_dump_dol(tlv, tag, f); + emv_tag_dump_dol(tlv, tag, f, level); break; case EMV_TAG_CVM_LIST: - emv_tag_dump_cvm_list(tlv, tag, f); + emv_tag_dump_cvm_list(tlv, tag, f, level); break; case EMV_TAG_STRING: - emv_tag_dump_string(tlv, tag, f); + emv_tag_dump_string(tlv, tag, f, level); break; case EMV_TAG_NUMERIC: - emv_tag_dump_numeric(tlv, tag, f); + emv_tag_dump_numeric(tlv, tag, f, level); break; case EMV_TAG_YYMMDD: - emv_tag_dump_yymmdd(tlv, tag, f); + emv_tag_dump_yymmdd(tlv, tag, f, level); break; }; diff --git a/client/emv/emv_tags.h b/client/emv/emv_tags.h index de6d9d1e..8dbd9e00 100644 --- a/client/emv/emv_tags.h +++ b/client/emv/emv_tags.h @@ -19,6 +19,6 @@ #include "tlv.h" #include -bool emv_tag_dump(const struct tlv *tlv, FILE *f); +bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level); #endif diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 9264b110..8dc93259 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -10,9 +10,9 @@ #include "emvcore.h" -static bool print_cb(void *data, const struct tlv *tlv) { - emv_tag_dump(tlv, stdout); - dump_buffer(tlv->value, tlv->len, stdout); +static bool print_cb(void *data, const struct tlv *tlv, int level) { + emv_tag_dump(tlv, stdout, level); + dump_buffer(tlv->value, tlv->len, stdout, level); return true; } @@ -23,7 +23,7 @@ void TLVPrintFromBuffer(uint8_t *data, int datalen) { if (t) { PrintAndLog("TLV decoded:"); - tlvdb_visit(t, print_cb, NULL); + tlvdb_visit(t, print_cb, NULL, 0); tlvdb_free(t); } else { PrintAndLog("TLV ERROR: Can't parse response as TLV tree."); diff --git a/client/emv/tlv.c b/client/emv/tlv.c index d78f049e..7feaa9aa 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -308,7 +308,7 @@ void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other) tlvdb->next = other; } -void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data) +void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data, int level) { struct tlvdb *next = NULL; @@ -317,8 +317,8 @@ void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data) for (; tlvdb; tlvdb = next) { next = tlvdb->next; - cb(data, &tlvdb->tag); - tlvdb_visit(tlvdb->children, cb, data); + cb(data, &tlvdb->tag, level); + tlvdb_visit(tlvdb->children, cb, data, level+1); } } diff --git a/client/emv/tlv.h b/client/emv/tlv.h index 3fd3f347..187781f8 100644 --- a/client/emv/tlv.h +++ b/client/emv/tlv.h @@ -31,7 +31,7 @@ struct tlv { }; struct tlvdb; -typedef bool (*tlv_cb)(void *data, const struct tlv *tlv); +typedef bool (*tlv_cb)(void *data, const struct tlv *tlv, int level); struct tlvdb *tlvdb_fixed(tlv_tag_t tag, size_t len, const unsigned char *value); struct tlvdb *tlvdb_external(tlv_tag_t tag, size_t len, const unsigned char *value); @@ -41,7 +41,7 @@ void tlvdb_free(struct tlvdb *tlvdb); void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other); -void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data); +void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data, int level); const struct tlv *tlvdb_get(const struct tlvdb *tlvdb, tlv_tag_t tag, const struct tlv *prev); bool tlv_parse_tl(const unsigned char **buf, size_t *len, struct tlv *tlv); -- 2.39.2