Fixed data asn1 - now handles bad input better by doing correct root free of obj

This commit is contained in:
Christian Herrmann 2023-03-11 18:59:33 +01:00
commit 2e8bacb00f
4 changed files with 66 additions and 34 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Fixed `data asn1` - now handles bad input better (@iceman1001)
- Added new public key for signature MIFARE Plus Troika (@iceman100)
- Fixed the client build on Android (@wh201906)
- Added TCP connection support on Windows (@wh201906)

View file

@ -576,7 +576,8 @@ static int PivGetData(Iso7816CommandChannel channel, const uint8_t tag[], size_t
struct tlvdb_root *new_root = realloc(root, sizeof(*root) + capacity);
if (new_root == NULL) {
PrintAndLogEx(FAILED, "Running out of memory while re-allocating buffer");
free(root);
//free(root);
tlvdb_root_free(root);
return PM3_EMALLOC;
}
root = new_root;

View file

@ -177,7 +177,7 @@ bool TLVPrintFromBuffer(uint8_t *data, int datalen) {
}
void TLVPrintFromTLVLev(struct tlvdb *tlv, int level) {
if (!tlv)
if (tlv == NULL)
return;
tlvdb_visit(tlv, emv_print_cb, NULL, level);
@ -193,15 +193,16 @@ void TLVPrintAIDlistFromSelectTLV(struct tlvdb *tlv) {
PrintAndLogEx(INFO, "|------------------+--------+-------------------------|");
struct tlvdb *ttmp = tlvdb_find(tlv, 0x6f);
if (!ttmp)
if (ttmp == NULL)
PrintAndLogEx(INFO, "| none |");
while (ttmp) {
const struct tlv *tgAID = tlvdb_get_inchild(ttmp, 0x84, NULL);
const struct tlv *tgName = tlvdb_get_inchild(ttmp, 0x50, NULL);
const struct tlv *tgPrio = tlvdb_get_inchild(ttmp, 0x87, NULL);
if (!tgAID)
if (!tgAID) {
break;
}
PrintAndLogEx(INFO, "| %s| %s | %s|",
sprint_hex_inrow_ex(tgAID->value, tgAID->len, 17),
(tgPrio) ? sprint_hex(tgPrio->value, 1) : " ",

View file

@ -197,9 +197,7 @@ struct tlvdb *tlvdb_parse(const unsigned char *buf, size_t len) {
return &root->db;
err:
tlvdb_free(&root->db);
free(root);
tlvdb_root_free(root);
return NULL;
}
@ -208,22 +206,32 @@ struct tlvdb *tlvdb_parse_multi(const unsigned char *buf, size_t len) {
const unsigned char *tmp;
size_t left;
if (!len || !buf)
if (len == 0 || buf == NULL) {
return NULL;
}
root = calloc(1, sizeof(*root) + len);
if (root == NULL) {
return NULL;
}
root->len = len;
memcpy(root->buf, buf, len);
tmp = root->buf;
left = len;
if (!tlvdb_parse_one(&root->db, NULL, &tmp, &left))
if (tlvdb_parse_one(&root->db, NULL, &tmp, &left) == false) {
goto err;
}
while (left != 0) {
struct tlvdb *db = calloc(1, sizeof(*db));
if (!tlvdb_parse_one(db, NULL, &tmp, &left)) {
if (db == NULL ) {
goto err;
}
if (tlvdb_parse_one(db, NULL, &tmp, &left) == false) {
free(db);
goto err;
}
@ -234,9 +242,7 @@ struct tlvdb *tlvdb_parse_multi(const unsigned char *buf, size_t len) {
return &root->db;
err:
tlvdb_free(&root->db);
free(root);
tlvdb_root_free(root);
return NULL;
}
@ -313,8 +319,9 @@ struct tlvdb *tlvdb_external(tlv_tag_t tag, size_t len, const unsigned char *val
void tlvdb_free(struct tlvdb *tlvdb) {
struct tlvdb *next = NULL;
if (!tlvdb)
if (tlvdb == NULL) {
return;
}
for (; tlvdb; tlvdb = next) {
next = tlvdb->next;
@ -339,36 +346,42 @@ void tlvdb_root_free(struct tlvdb_root *root) {
}
struct tlvdb *tlvdb_find_next(struct tlvdb *tlvdb, tlv_tag_t tag) {
if (!tlvdb)
if (tlvdb == NULL) {
return NULL;
}
return tlvdb_find(tlvdb->next, tag);
}
struct tlvdb *tlvdb_find(struct tlvdb *tlvdb, tlv_tag_t tag) {
if (!tlvdb)
if (tlvdb == NULL) {
return NULL;
}
for (; tlvdb; tlvdb = tlvdb->next) {
if (tlvdb->tag.tag == tag)
if (tlvdb->tag.tag == tag) {
return tlvdb;
}
}
return NULL;
}
struct tlvdb *tlvdb_find_full(struct tlvdb *tlvdb, tlv_tag_t tag) {
if (!tlvdb)
if (tlvdb == NULL) {
return NULL;
}
for (; tlvdb; tlvdb = tlvdb->next) {
if (tlvdb->tag.tag == tag)
if (tlvdb->tag.tag == tag) {
return tlvdb;
}
if (tlvdb->children) {
struct tlvdb *ch = tlvdb_find_full(tlvdb->children, tag);
if (ch)
if (ch) {
return ch;
}
}
}
@ -391,12 +404,14 @@ struct tlvdb *tlvdb_find_path(struct tlvdb *tlvdb, tlv_tag_t tag[]) {
}
void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other) {
if (tlvdb == other)
if (tlvdb == other) {
return;
}
while (tlvdb->next) {
if (tlvdb->next == other)
if (tlvdb->next == other) {
return;
}
tlvdb = tlvdb->next;
}
@ -405,17 +420,21 @@ void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other) {
}
void tlvdb_change_or_add_node_ex(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, const unsigned char *value, struct tlvdb **tlvdb_elm) {
struct tlvdb *telm = tlvdb_find_full(tlvdb, tag);
if (telm == NULL) {
// new tlv element
struct tlvdb *elm = tlvdb_fixed(tag, len, value);
tlvdb_add(tlvdb, elm);
if (tlvdb_elm)
if (tlvdb_elm) {
*tlvdb_elm = elm;
}
} else {
// the same tlv structure
if (telm->tag.tag == tag && telm->tag.len == len && !memcmp(telm->tag.value, value, len))
if (telm->tag.tag == tag && telm->tag.len == len && !memcmp(telm->tag.value, value, len)) {
return;
}
// replace tlv element
struct tlvdb *tnewelm = tlvdb_fixed(tag, len, value);
@ -434,8 +453,9 @@ void tlvdb_change_or_add_node_ex(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len,
// elm in root
struct tlvdb *celm = tlvdb;
// elm in child list of node
if (telm->parent && telm->parent->children)
if (telm->parent && telm->parent->children) {
celm = telm->parent->children;
}
// find previous element
for (; celm; celm = celm->next) {
@ -455,7 +475,8 @@ void tlvdb_change_or_add_node_ex(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len,
*tlvdb_elm = tnewelm;
tnewelm_linked = true;
}
if (! tnewelm_linked) {
if (!tnewelm_linked) {
tlvdb_free(tnewelm);
}
}
@ -470,8 +491,9 @@ void tlvdb_change_or_add_node(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, co
void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data, int level) {
struct tlvdb *next = NULL;
if (!tlvdb)
if (tlvdb == NULL) {
return;
}
for (; tlvdb; tlvdb = next) {
next = tlvdb->next;
@ -481,12 +503,14 @@ void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data, int level) {
}
static const struct tlvdb *tlvdb_next(const struct tlvdb *tlvdb) {
if (tlvdb->children)
if (tlvdb->children) {
return tlvdb->children;
}
while (tlvdb) {
if (tlvdb->next)
if (tlvdb->next) {
return tlvdb->next;
}
tlvdb = tlvdb->parent;
}
@ -502,8 +526,9 @@ const struct tlv *tlvdb_get(const struct tlvdb *tlvdb, tlv_tag_t tag, const stru
while (tlvdb) {
if (tlvdb->tag.tag == tag)
if (tlvdb->tag.tag == tag) {
return &tlvdb->tag;
}
tlvdb = tlvdb_next(tlvdb);
}
@ -570,11 +595,13 @@ bool tlv_is_constructed(const struct tlv *tlv) {
}
bool tlv_equal(const struct tlv *a, const struct tlv *b) {
if (!a && !b)
if (a == NULL && b == NULL) {
return true;
}
if (!a || !b)
if (a == NULL || b == NULL) {
return false;
}
return a->tag == b->tag && a->len == b->len && !memcmp(a->value, b->value, a->len);
}
@ -599,8 +626,9 @@ bool tlvdb_get_uint8(struct tlvdb *tlvRoot, tlv_tag_t tag, uint8_t *value) {
bool tlv_get_uint8(const struct tlv *etlv, uint8_t *value) {
*value = 0;
if (etlv) {
if (etlv->len == 0)
if (etlv->len == 0) {
return true;
}
if (etlv->len == 1) {
*value = etlv->value[0];
@ -613,8 +641,9 @@ bool tlv_get_uint8(const struct tlv *etlv, uint8_t *value) {
bool tlv_get_int(const struct tlv *etlv, int *value) {
*value = 0;
if (etlv) {
if (etlv->len == 0)
if (etlv->len == 0) {
return true;
}
if (etlv->len <= 4) {
for (int i = 0; i < etlv->len; i++) {