]>
git.zerfleddert.de Git - proxmark3-svn/blob - client/emv/tlv.c
2 * libopenemv - a library to work with EMV family of smart cards
3 * Copyright (C) 2012, 2015 Dmitry Eremin-Solenikov
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * https://github.com/lumag/emv-tools/blob/master/lib/tlv.c
29 #define TLV_TAG_CLASS_MASK 0xc0
30 #define TLV_TAG_COMPLEX 0x20
31 #define TLV_TAG_VALUE_MASK 0x1f
32 #define TLV_TAG_VALUE_CONT 0x1f
33 #define TLV_TAG_INVALID 0
35 #define TLV_LEN_LONG 0x80
36 #define TLV_LEN_MASK 0x7f
37 #define TLV_LEN_INVALID (~0)
39 // http://radek.io/2012/11/10/magical-container_of-macro/
40 //#define container_of(ptr, type, member) ({
41 // const typeof( ((type *)0)->member ) *__mptr = (ptr);
42 // (type *)( (char *)__mptr - offsetof(type,member) );})
48 struct tlvdb
*children
;
57 static tlv_tag_t
tlv_parse_tag(const unsigned char **buf
, size_t *len
)
62 return TLV_TAG_INVALID
;
66 if ((tag
& TLV_TAG_VALUE_MASK
) != TLV_TAG_VALUE_CONT
)
70 return TLV_TAG_INVALID
;
80 static size_t tlv_parse_len(const unsigned char **buf
, size_t *len
)
85 return TLV_LEN_INVALID
;
91 if (!(l
& TLV_LEN_LONG
))
94 size_t ll
= l
&~ TLV_LEN_LONG
;
96 return TLV_LEN_INVALID
;
99 for (int i
= 1; i
<= ll
; i
++) {
100 l
= (l
<< 8) + **buf
;
108 bool tlv_parse_tl(const unsigned char **buf
, size_t *len
, struct tlv
*tlv
)
112 tlv
->tag
= tlv_parse_tag(buf
, len
);
113 if (tlv
->tag
== TLV_TAG_INVALID
)
116 tlv
->len
= tlv_parse_len(buf
, len
);
117 if (tlv
->len
== TLV_LEN_INVALID
)
123 static struct tlvdb
*tlvdb_parse_children(struct tlvdb
*parent
);
125 static bool tlvdb_parse_one(struct tlvdb
*tlvdb
,
126 struct tlvdb
*parent
,
127 const unsigned char **tmp
,
130 tlvdb
->next
= tlvdb
->children
= NULL
;
131 tlvdb
->parent
= parent
;
133 tlvdb
->tag
.tag
= tlv_parse_tag(tmp
, left
);
134 if (tlvdb
->tag
.tag
== TLV_TAG_INVALID
)
137 tlvdb
->tag
.len
= tlv_parse_len(tmp
, left
);
138 if (tlvdb
->tag
.len
== TLV_LEN_INVALID
)
141 if (tlvdb
->tag
.len
> *left
)
144 tlvdb
->tag
.value
= *tmp
;
146 *tmp
+= tlvdb
->tag
.len
;
147 *left
-= tlvdb
->tag
.len
;
149 if (tlv_is_constructed(&tlvdb
->tag
) && (tlvdb
->tag
.len
!= 0)) {
150 tlvdb
->children
= tlvdb_parse_children(tlvdb
);
151 if (!tlvdb
->children
)
154 tlvdb
->children
= NULL
;
163 static struct tlvdb
*tlvdb_parse_children(struct tlvdb
*parent
)
165 const unsigned char *tmp
= parent
->tag
.value
;
166 size_t left
= parent
->tag
.len
;
167 struct tlvdb
*tlvdb
, *first
= NULL
, *prev
= NULL
;
170 tlvdb
= malloc(sizeof(*tlvdb
));
177 if (!tlvdb_parse_one(tlvdb
, parent
, &tmp
, &left
))
180 tlvdb
->parent
= parent
;
191 struct tlvdb
*tlvdb_parse(const unsigned char *buf
, size_t len
)
193 struct tlvdb_root
*root
;
194 const unsigned char *tmp
;
200 root
= malloc(sizeof(*root
) + len
);
202 memcpy(root
->buf
, buf
, len
);
207 if (!tlvdb_parse_one(&root
->db
, NULL
, &tmp
, &left
))
216 tlvdb_free(&root
->db
);
221 struct tlvdb
*tlvdb_parse_multi(const unsigned char *buf
, size_t len
)
223 struct tlvdb_root
*root
;
224 const unsigned char *tmp
;
230 root
= malloc(sizeof(*root
) + len
);
232 memcpy(root
->buf
, buf
, len
);
237 if (!tlvdb_parse_one(&root
->db
, NULL
, &tmp
, &left
))
241 struct tlvdb
*db
= malloc(sizeof(*db
));
242 if (!tlvdb_parse_one(db
, NULL
, &tmp
, &left
)) {
247 tlvdb_add(&root
->db
, db
);
253 tlvdb_free(&root
->db
);
258 struct tlvdb
*tlvdb_fixed(tlv_tag_t tag
, size_t len
, const unsigned char *value
)
260 struct tlvdb_root
*root
= malloc(sizeof(*root
) + len
);
263 memcpy(root
->buf
, value
, len
);
265 root
->db
.parent
= root
->db
.next
= root
->db
.children
= NULL
;
266 root
->db
.tag
.tag
= tag
;
267 root
->db
.tag
.len
= len
;
268 root
->db
.tag
.value
= root
->buf
;
273 struct tlvdb
*tlvdb_external(tlv_tag_t tag
, size_t len
, const unsigned char *value
)
275 struct tlvdb_root
*root
= malloc(sizeof(*root
));
279 root
->db
.parent
= root
->db
.next
= root
->db
.children
= NULL
;
280 root
->db
.tag
.tag
= tag
;
281 root
->db
.tag
.len
= len
;
282 root
->db
.tag
.value
= value
;
287 void tlvdb_free(struct tlvdb
*tlvdb
)
289 struct tlvdb
*next
= NULL
;
294 for (; tlvdb
; tlvdb
= next
) {
296 tlvdb_free(tlvdb
->children
);
301 struct tlvdb
*tlvdb_find_next(struct tlvdb
*tlvdb
, tlv_tag_t tag
) {
305 return tlvdb_find(tlvdb
->next
, tag
);
308 struct tlvdb
*tlvdb_find(struct tlvdb
*tlvdb
, tlv_tag_t tag
) {
312 for (; tlvdb
; tlvdb
= tlvdb
->next
) {
313 if (tlvdb
->tag
.tag
== tag
)
320 struct tlvdb
*tlvdb_find_full(struct tlvdb
*tlvdb
, tlv_tag_t tag
) {
324 for (; tlvdb
; tlvdb
= tlvdb
->next
) {
325 if (tlvdb
->tag
.tag
== tag
)
328 if (tlvdb
->children
) {
329 struct tlvdb
* ch
= tlvdb_find_full(tlvdb
->children
, tag
);
338 struct tlvdb
*tlvdb_find_path(struct tlvdb
*tlvdb
, tlv_tag_t tag
[]) {
340 struct tlvdb
*tnext
= tlvdb
;
342 while (tnext
&& tag
[i
]) {
343 tnext
= tlvdb_find(tnext
, tag
[i
]);
345 if (tag
[i
] && tnext
) {
346 tnext
= tnext
->children
;
353 void tlvdb_add(struct tlvdb
*tlvdb
, struct tlvdb
*other
)
358 while (tlvdb
->next
) {
359 if (tlvdb
->next
== other
)
368 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
)
370 struct tlvdb
*telm
= tlvdb_find_full(tlvdb
, tag
);
373 struct tlvdb
*elm
= tlvdb_fixed(tag
, len
, value
);
374 tlvdb_add(tlvdb
, elm
);
378 // the same tlv structure
379 if (telm
->tag
.tag
== tag
&& telm
->tag
.len
== len
&& !memcmp(telm
->tag
.value
, value
, len
))
382 // replace tlv element
383 struct tlvdb
*tnewelm
= tlvdb_fixed(tag
, len
, value
);
384 tnewelm
->next
= telm
->next
;
385 tnewelm
->parent
= telm
->parent
;
387 // if telm stayed first in children chain
388 if (telm
->parent
&& telm
->parent
->children
== telm
) {
389 telm
->parent
->children
= tnewelm
;
392 // if telm have previous element
395 struct tlvdb
*celm
= tlvdb
;
396 // elm in child list of node
397 if (telm
->parent
&& telm
->parent
->children
)
398 celm
= telm
->parent
->children
;
400 // find previous element
401 for (; celm
; celm
= celm
->next
) {
402 if (celm
->next
== telm
) {
403 celm
->next
= tnewelm
;
409 // free old element with childrens
414 *tlvdb_elm
= tnewelm
;
420 void tlvdb_change_or_add_node(struct tlvdb
*tlvdb
, tlv_tag_t tag
, size_t len
, const unsigned char *value
)
422 tlvdb_change_or_add_node_ex(tlvdb
, tag
, len
, value
, NULL
);
425 void tlvdb_visit(const struct tlvdb
*tlvdb
, tlv_cb cb
, void *data
, int level
)
427 struct tlvdb
*next
= NULL
;
432 for (; tlvdb
; tlvdb
= next
) {
434 cb(data
, &tlvdb
->tag
, level
, (tlvdb
->children
== NULL
));
435 tlvdb_visit(tlvdb
->children
, cb
, data
, level
+ 1);
439 static const struct tlvdb
*tlvdb_next(const struct tlvdb
*tlvdb
)
442 return tlvdb
->children
;
448 tlvdb
= tlvdb
->parent
;
454 const struct tlv
*tlvdb_get(const struct tlvdb
*tlvdb
, tlv_tag_t tag
, const struct tlv
*prev
)
457 // tlvdb = tlvdb_next(container_of(prev, struct tlvdb, tag));
458 tlvdb
= tlvdb_next((struct tlvdb
*)prev
);
463 if (tlvdb
->tag
.tag
== tag
)
466 tlvdb
= tlvdb_next(tlvdb
);
472 const struct tlv
*tlvdb_get_inchild(const struct tlvdb
*tlvdb
, tlv_tag_t tag
, const struct tlv
*prev
) {
473 tlvdb
= tlvdb
->children
;
474 return tlvdb_get(tlvdb
, tag
, prev
);
477 const struct tlv
*tlvdb_get_tlv(const struct tlvdb
*tlvdb
) {
481 unsigned char *tlv_encode(const struct tlv
*tlv
, size_t *len
)
483 size_t size
= tlv
->len
;
487 if (tlv
->tag
> 0x100)
505 if (tlv
->tag
> 0x100) {
506 data
[pos
++] = tlv
->tag
>> 8;
507 data
[pos
++] = tlv
->tag
& 0xff;
509 data
[pos
++] = tlv
->tag
;
511 if (tlv
->len
> 0x7f) {
513 data
[pos
++] = tlv
->len
;
515 data
[pos
++] = tlv
->len
;
517 memcpy(data
+ pos
, tlv
->value
, tlv
->len
);
524 bool tlv_is_constructed(const struct tlv
*tlv
)
526 return (tlv
->tag
< 0x100 ? tlv
->tag
: tlv
->tag
>> 8) & TLV_TAG_COMPLEX
;
529 bool tlv_equal(const struct tlv
*a
, const struct tlv
*b
)
537 return a
->tag
== b
->tag
&& a
->len
== b
->len
&& !memcmp(a
->value
, b
->value
, a
->len
);
540 struct tlvdb
*tlvdb_elm_get_next(struct tlvdb
*tlvdb
)
545 struct tlvdb
*tlvdb_elm_get_children(struct tlvdb
*tlvdb
)
547 return tlvdb
->children
;
550 struct tlvdb
*tlvdb_elm_get_parent(struct tlvdb
*tlvdb
)
552 return tlvdb
->parent
;
555 bool tlv_get_uint8(const struct tlv
*etlv
, uint8_t *value
)
565 *value
= etlv
->value
[0];
572 bool tlv_get_int(const struct tlv
*etlv
, int *value
)
582 for (int i
= 0; i
< etlv
->len
; i
++)
584 *value
+= etlv
->value
[i
] * (1 << (i
* 8));
592 bool tlvdb_get_uint8(struct tlvdb
*tlvRoot
, tlv_tag_t tag
, uint8_t *value
)
594 const struct tlv
*tlvelm
= tlvdb_get(tlvRoot
, tag
, NULL
);
595 return tlv_get_uint8(tlvelm
, value
);