mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-02-13 02:34:48 +08:00
CHG: (@pwpiwi) d940ebfbad
This commit is contained in:
parent
25b173ea20
commit
02af3b9e1d
7 changed files with 47 additions and 25 deletions
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#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)
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
#define DUMP_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#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,
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,6 @@
|
|||
#include "tlv.h"
|
||||
#include <stdio.h>
|
||||
|
||||
bool emv_tag_dump(const struct tlv *tlv, FILE *f);
|
||||
bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,9 +10,11 @@
|
|||
|
||||
#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, bool is_leaf) {
|
||||
emv_tag_dump(tlv, stdout, level);
|
||||
if (is_leaf) {
|
||||
dump_buffer(tlv->value, tlv->len, stdout, level);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -23,7 +25,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.");
|
||||
|
|
|
@ -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,9 @@ 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);
|
||||
bool is_leaf = (tlvdb->children == NULL);
|
||||
cb(data, &tlvdb->tag, level, is_leaf);
|
||||
tlvdb_visit(tlvdb->children, cb, data, level+1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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, bool is_leaf);
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue