1 //-----------------------------------------------------------------------------
2 // Borrowed initially from https://github.com/lumag/emv-tools/
3 // Copyright (C) 2012, 2015 Dmitry Eremin-Solenikov
4 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // See LICENSE.txt for the text of the license.
17 //-----------------------------------------------------------------------------
18 // libopenemv - a library to work with EMV family of smart cards
19 //-----------------------------------------------------------------------------
32 #define TLV_TAG_CLASS_MASK 0xC0
33 #define TLV_TAG_COMPLEX 0x20
34 #define TLV_TAG_VALUE_MASK 0x1F
35 #define TLV_TAG_VALUE_CONT 0x1F
36 #define TLV_TAG_INVALID 0
38 #define TLV_LEN_LONG 0x80
39 #define TLV_LEN_MASK 0x7F
40 #define TLV_LEN_INVALID (~0)
42 // http://radek.io/2012/11/10/magical-container_of-macro/
43 //#define container_of(ptr, type, member) ({
44 // const typeof( ((type *)0)->member ) *__mptr = (ptr);
45 // (type *)( (char *)__mptr - offsetof(type,member) );})
47 static tlv_tag_t
tlv_parse_tag(const unsigned char **buf
, size_t *len
) {
51 return TLV_TAG_INVALID
;
55 if ((tag
& TLV_TAG_VALUE_MASK
) != TLV_TAG_VALUE_CONT
)
59 return TLV_TAG_INVALID
;
69 static size_t tlv_parse_len(const unsigned char **buf
, size_t *len
) {
73 return TLV_LEN_INVALID
;
79 if (!(l
& TLV_LEN_LONG
))
82 size_t ll
= l
& ~ TLV_LEN_LONG
;
84 return TLV_LEN_INVALID
;
87 for (int i
= 1; i
<= ll
; i
++) {
96 bool tlv_parse_tl(const unsigned char **buf
, size_t *len
, struct tlv
*tlv
) {
99 tlv
->tag
= tlv_parse_tag(buf
, len
);
100 if (tlv
->tag
== TLV_TAG_INVALID
)
103 tlv
->len
= tlv_parse_len(buf
, len
);
104 if (tlv
->len
== TLV_LEN_INVALID
)
110 static struct tlvdb
*tlvdb_parse_children(struct tlvdb
*parent
);
112 static bool tlvdb_parse_one(struct tlvdb
*tlvdb
,
113 struct tlvdb
*parent
,
114 const unsigned char **tmp
,
116 tlvdb
->next
= tlvdb
->children
= NULL
;
117 tlvdb
->parent
= parent
;
119 tlvdb
->tag
.tag
= tlv_parse_tag(tmp
, left
);
120 if (tlvdb
->tag
.tag
== TLV_TAG_INVALID
)
123 tlvdb
->tag
.len
= tlv_parse_len(tmp
, left
);
124 if (tlvdb
->tag
.len
== TLV_LEN_INVALID
)
127 if (tlvdb
->tag
.len
> *left
)
130 tlvdb
->tag
.value
= *tmp
;
132 *tmp
+= tlvdb
->tag
.len
;
133 *left
-= tlvdb
->tag
.len
;
135 if (tlv_is_constructed(&tlvdb
->tag
) && (tlvdb
->tag
.len
!= 0)) {
136 tlvdb
->children
= tlvdb_parse_children(tlvdb
);
137 if (!tlvdb
->children
)
140 tlvdb
->children
= NULL
;
149 static struct tlvdb
*tlvdb_parse_children(struct tlvdb
*parent
) {
150 const unsigned char *tmp
= parent
->tag
.value
;
151 size_t left
= parent
->tag
.len
;
152 struct tlvdb
*tlvdb
, *first
= NULL
, *prev
= NULL
;
155 tlvdb
= calloc(1, sizeof(*tlvdb
));
162 if (!tlvdb_parse_one(tlvdb
, parent
, &tmp
, &left
))
165 tlvdb
->parent
= parent
;
176 struct tlvdb
*tlvdb_parse(const unsigned char *buf
, size_t len
) {
177 struct tlvdb_root
*root
;
178 const unsigned char *tmp
;
184 root
= calloc(1, sizeof(*root
) + len
);
186 memcpy(root
->buf
, buf
, len
);
191 if (!tlvdb_parse_one(&root
->db
, NULL
, &tmp
, &left
))
200 tlvdb_root_free(root
);
204 struct tlvdb
*tlvdb_parse_multi(const unsigned char *buf
, size_t len
) {
205 struct tlvdb_root
*root
;
206 const unsigned char *tmp
;
209 if (len
== 0 || buf
== NULL
) {
213 root
= calloc(1, sizeof(*root
) + len
);
219 memcpy(root
->buf
, buf
, len
);
224 if (tlvdb_parse_one(&root
->db
, NULL
, &tmp
, &left
) == false) {
229 struct tlvdb
*db
= calloc(1, sizeof(*db
));
234 if (tlvdb_parse_one(db
, NULL
, &tmp
, &left
) == false) {
239 tlvdb_add(&root
->db
, db
);
245 tlvdb_root_free(root
);
249 bool tlvdb_parse_root(struct tlvdb_root
*root
) {
250 if (root
== NULL
|| root
->len
== 0) {
259 if (tlvdb_parse_one(&root
->db
, NULL
, &tmp
, &left
) == true) {
267 bool tlvdb_parse_root_multi(struct tlvdb_root
*root
) {
268 if (root
== NULL
|| root
->len
== 0) {
277 if (tlvdb_parse_one(&root
->db
, NULL
, &tmp
, &left
) == true) {
279 struct tlvdb
*db
= calloc(1, sizeof(*db
));
280 if (tlvdb_parse_one(db
, NULL
, &tmp
, &left
) == true) {
281 tlvdb_add(&root
->db
, db
);
292 struct tlvdb
*tlvdb_fixed(tlv_tag_t tag
, size_t len
, const unsigned char *value
) {
293 struct tlvdb_root
*root
= calloc(1, sizeof(*root
) + len
);
296 memcpy(root
->buf
, value
, len
);
298 root
->db
.parent
= root
->db
.next
= root
->db
.children
= NULL
;
299 root
->db
.tag
.tag
= tag
;
300 root
->db
.tag
.len
= len
;
301 root
->db
.tag
.value
= root
->buf
;
306 struct tlvdb
*tlvdb_external(tlv_tag_t tag
, size_t len
, const unsigned char *value
) {
307 struct tlvdb_root
*root
= calloc(1, sizeof(*root
));
311 root
->db
.parent
= root
->db
.next
= root
->db
.children
= NULL
;
312 root
->db
.tag
.tag
= tag
;
313 root
->db
.tag
.len
= len
;
314 root
->db
.tag
.value
= value
;
319 void tlvdb_free(struct tlvdb
*tlvdb
) {
320 struct tlvdb
*next
= NULL
;
326 for (; tlvdb
; tlvdb
= next
) {
328 tlvdb_free(tlvdb
->children
);
333 void tlvdb_root_free(struct tlvdb_root
*root
) {
337 if (root
->db
.children
) {
338 tlvdb_free(root
->db
.children
);
339 root
->db
.children
= NULL
;
342 tlvdb_free(root
->db
.next
);
343 root
->db
.next
= NULL
;
348 struct tlvdb
*tlvdb_find_next(struct tlvdb
*tlvdb
, tlv_tag_t tag
) {
353 return tlvdb_find(tlvdb
->next
, tag
);
356 struct tlvdb
*tlvdb_find(struct tlvdb
*tlvdb
, tlv_tag_t tag
) {
361 for (; tlvdb
; tlvdb
= tlvdb
->next
) {
362 if (tlvdb
->tag
.tag
== tag
) {
370 struct tlvdb
*tlvdb_find_full(struct tlvdb
*tlvdb
, tlv_tag_t tag
) {
375 for (; tlvdb
; tlvdb
= tlvdb
->next
) {
376 if (tlvdb
->tag
.tag
== tag
) {
380 if (tlvdb
->children
) {
381 struct tlvdb
*ch
= tlvdb_find_full(tlvdb
->children
, tag
);
391 struct tlvdb
*tlvdb_find_path(struct tlvdb
*tlvdb
, tlv_tag_t tag
[]) {
393 struct tlvdb
*tnext
= tlvdb
;
395 while (tnext
&& tag
[i
]) {
396 tnext
= tlvdb_find(tnext
, tag
[i
]);
398 if (tag
[i
] && tnext
) {
399 tnext
= tnext
->children
;
406 void tlvdb_add(struct tlvdb
*tlvdb
, struct tlvdb
*other
) {
407 if (tlvdb
== other
) {
411 while (tlvdb
->next
) {
412 if (tlvdb
->next
== other
) {
422 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
) {
424 struct tlvdb
*telm
= tlvdb_find_full(tlvdb
, tag
);
427 struct tlvdb
*elm
= tlvdb_fixed(tag
, len
, value
);
428 tlvdb_add(tlvdb
, elm
);
434 // the same tlv structure
435 if (telm
->tag
.tag
== tag
&& telm
->tag
.len
== len
&& !memcmp(telm
->tag
.value
, value
, len
)) {
439 // replace tlv element
440 struct tlvdb
*tnewelm
= tlvdb_fixed(tag
, len
, value
);
441 bool tnewelm_linked
= false;
442 tnewelm
->next
= telm
->next
;
443 tnewelm
->parent
= telm
->parent
;
445 // if telm stayed first in children chain
446 if (telm
->parent
&& telm
->parent
->children
== telm
) {
447 telm
->parent
->children
= tnewelm
;
448 tnewelm_linked
= true;
451 // if telm have previous element
454 struct tlvdb
*celm
= tlvdb
;
455 // elm in child list of node
456 if (telm
->parent
&& telm
->parent
->children
) {
457 celm
= telm
->parent
->children
;
460 // find previous element
461 for (; celm
; celm
= celm
->next
) {
462 if (celm
->next
== telm
) {
463 celm
->next
= tnewelm
;
464 tnewelm_linked
= true;
470 // free old element with childrens
475 *tlvdb_elm
= tnewelm
;
476 tnewelm_linked
= true;
479 if (!tnewelm_linked
) {
487 void tlvdb_change_or_add_node(struct tlvdb
*tlvdb
, tlv_tag_t tag
, size_t len
, const unsigned char *value
) {
488 tlvdb_change_or_add_node_ex(tlvdb
, tag
, len
, value
, NULL
);
491 void tlvdb_visit(const struct tlvdb
*tlvdb
, tlv_cb cb
, void *data
, int level
) {
492 struct tlvdb
*next
= NULL
;
498 for (; tlvdb
; tlvdb
= next
) {
500 cb(data
, &tlvdb
->tag
, level
, (tlvdb
->children
== NULL
));
501 tlvdb_visit(tlvdb
->children
, cb
, data
, level
+ 1);
505 static const struct tlvdb
*tlvdb_next(const struct tlvdb
*tlvdb
) {
506 if (tlvdb
->children
) {
507 return tlvdb
->children
;
515 tlvdb
= tlvdb
->parent
;
521 const struct tlv
*tlvdb_get(const struct tlvdb
*tlvdb
, tlv_tag_t tag
, const struct tlv
*prev
) {
523 // tlvdb = tlvdb_next(container_of(prev, struct tlvdb, tag));
524 tlvdb
= tlvdb_next((struct tlvdb
*)prev
);
529 if (tlvdb
->tag
.tag
== tag
) {
533 tlvdb
= tlvdb_next(tlvdb
);
539 const struct tlv
*tlvdb_get_inchild(const struct tlvdb
*tlvdb
, tlv_tag_t tag
, const struct tlv
*prev
) {
540 tlvdb
= tlvdb
->children
;
541 return tlvdb_get(tlvdb
, tag
, prev
);
544 const struct tlv
*tlvdb_get_tlv(const struct tlvdb
*tlvdb
) {
551 unsigned char *tlv_encode(const struct tlv
*tlv
, size_t *len
) {
552 size_t size
= tlv
->len
;
556 if (tlv
->tag
> 0x100)
566 data
= calloc(1, size
);
574 if (tlv
->tag
> 0x100) {
575 data
[pos
++] = tlv
->tag
>> 8;
576 data
[pos
++] = tlv
->tag
& 0xff;
578 data
[pos
++] = tlv
->tag
;
580 if (tlv
->len
> 0x7f) {
582 data
[pos
++] = tlv
->len
;
584 data
[pos
++] = tlv
->len
;
586 memcpy(data
+ pos
, tlv
->value
, tlv
->len
);
593 bool tlv_is_constructed(const struct tlv
*tlv
) {
594 return (((tlv
->tag
< 0x100 ? tlv
->tag
: tlv
->tag
>> 8) & TLV_TAG_COMPLEX
) == TLV_TAG_COMPLEX
);
597 bool tlv_equal(const struct tlv
*a
, const struct tlv
*b
) {
598 if (a
== NULL
&& b
== NULL
) {
602 if (a
== NULL
|| b
== NULL
) {
606 return a
->tag
== b
->tag
&& a
->len
== b
->len
&& !memcmp(a
->value
, b
->value
, a
->len
);
609 struct tlvdb
*tlvdb_elm_get_next(struct tlvdb
*tlvdb
) {
613 struct tlvdb
*tlvdb_elm_get_children(struct tlvdb
*tlvdb
) {
614 return tlvdb
->children
;
617 struct tlvdb
*tlvdb_elm_get_parent(struct tlvdb
*tlvdb
) {
618 return tlvdb
->parent
;
621 bool tlvdb_get_uint8(struct tlvdb
*tlvRoot
, tlv_tag_t tag
, uint8_t *value
) {
622 const struct tlv
*tlvelm
= tlvdb_get(tlvRoot
, tag
, NULL
);
623 return tlv_get_uint8(tlvelm
, value
);
626 bool tlv_get_uint8(const struct tlv
*etlv
, uint8_t *value
) {
629 if (etlv
->len
== 0) {
633 if (etlv
->len
== 1) {
634 *value
= etlv
->value
[0];
641 bool tlv_get_int(const struct tlv
*etlv
, int *value
) {
644 if (etlv
->len
== 0) {
648 if (etlv
->len
<= 4) {
649 for (int i
= 0; i
< etlv
->len
; i
++) {
650 *value
+= etlv
->value
[i
] * (1 << (i
* 8));