#include <stdlib.h>
+#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, "\t");}
+
enum emv_tag_t {
EMV_TAG_GENERIC,
EMV_TAG_BITMASK,
"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))
}
}
-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;
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");
}
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),
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;
}
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) {
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");
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;
};