]>
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
;
100 return TLV_LEN_INVALID
;
109 bool tlv_parse_tl(const unsigned char **buf
, size_t *len
, struct tlv
*tlv
)
113 tlv
->tag
= tlv_parse_tag(buf
, len
);
114 if (tlv
->tag
== TLV_TAG_INVALID
)
117 tlv
->len
= tlv_parse_len(buf
, len
);
118 if (tlv
->len
== TLV_LEN_INVALID
)
124 static struct tlvdb
*tlvdb_parse_children(struct tlvdb
*parent
);
126 static bool tlvdb_parse_one(struct tlvdb
*tlvdb
,
127 struct tlvdb
*parent
,
128 const unsigned char **tmp
,
131 tlvdb
->next
= tlvdb
->children
= NULL
;
132 tlvdb
->parent
= parent
;
134 tlvdb
->tag
.tag
= tlv_parse_tag(tmp
, left
);
135 if (tlvdb
->tag
.tag
== TLV_TAG_INVALID
)
138 tlvdb
->tag
.len
= tlv_parse_len(tmp
, left
);
139 if (tlvdb
->tag
.len
== TLV_LEN_INVALID
)
142 if (tlvdb
->tag
.len
> *left
)
145 tlvdb
->tag
.value
= *tmp
;
147 *tmp
+= tlvdb
->tag
.len
;
148 *left
-= tlvdb
->tag
.len
;
150 if (tlv_is_constructed(&tlvdb
->tag
) && (tlvdb
->tag
.len
!= 0)) {
151 tlvdb
->children
= tlvdb_parse_children(tlvdb
);
152 if (!tlvdb
->children
)
155 tlvdb
->children
= NULL
;
164 static struct tlvdb
*tlvdb_parse_children(struct tlvdb
*parent
)
166 const unsigned char *tmp
= parent
->tag
.value
;
167 size_t left
= parent
->tag
.len
;
168 struct tlvdb
*tlvdb
, *first
= NULL
, *prev
= NULL
;
171 tlvdb
= malloc(sizeof(*tlvdb
));
178 if (!tlvdb_parse_one(tlvdb
, parent
, &tmp
, &left
))
181 tlvdb
->parent
= parent
;
192 struct tlvdb
*tlvdb_parse(const unsigned char *buf
, size_t len
)
194 struct tlvdb_root
*root
;
195 const unsigned char *tmp
;
201 root
= malloc(sizeof(*root
) + len
);
203 memcpy(root
->buf
, buf
, len
);
208 if (!tlvdb_parse_one(&root
->db
, NULL
, &tmp
, &left
))
217 tlvdb_free(&root
->db
);
222 struct tlvdb
*tlvdb_parse_multi(const unsigned char *buf
, size_t len
)
224 struct tlvdb_root
*root
;
225 const unsigned char *tmp
;
231 root
= malloc(sizeof(*root
) + len
);
233 memcpy(root
->buf
, buf
, len
);
238 if (!tlvdb_parse_one(&root
->db
, NULL
, &tmp
, &left
))
242 struct tlvdb
*db
= malloc(sizeof(*db
));
243 if (!tlvdb_parse_one(db
, NULL
, &tmp
, &left
)) {
248 tlvdb_add(&root
->db
, db
);
254 tlvdb_free(&root
->db
);
259 struct tlvdb
*tlvdb_fixed(tlv_tag_t tag
, size_t len
, const unsigned char *value
)
261 struct tlvdb_root
*root
= malloc(sizeof(*root
) + len
);
264 memcpy(root
->buf
, value
, len
);
266 root
->db
.parent
= root
->db
.next
= root
->db
.children
= NULL
;
267 root
->db
.tag
.tag
= tag
;
268 root
->db
.tag
.len
= len
;
269 root
->db
.tag
.value
= root
->buf
;
274 struct tlvdb
*tlvdb_external(tlv_tag_t tag
, size_t len
, const unsigned char *value
)
276 struct tlvdb_root
*root
= malloc(sizeof(*root
));
280 root
->db
.parent
= root
->db
.next
= root
->db
.children
= NULL
;
281 root
->db
.tag
.tag
= tag
;
282 root
->db
.tag
.len
= len
;
283 root
->db
.tag
.value
= value
;
288 void tlvdb_free(struct tlvdb
*tlvdb
)
290 struct tlvdb
*next
= NULL
;
295 for (; tlvdb
; tlvdb
= next
) {
297 tlvdb_free(tlvdb
->children
);
302 struct tlvdb
*tlvdb_find_next(struct tlvdb
*tlvdb
, tlv_tag_t tag
) {
306 return tlvdb_find(tlvdb
->next
, tag
);
309 struct tlvdb
*tlvdb_find(struct tlvdb
*tlvdb
, tlv_tag_t tag
) {
313 for (; tlvdb
; tlvdb
= tlvdb
->next
) {
314 if (tlvdb
->tag
.tag
== tag
)
321 struct tlvdb
*tlvdb_find_path(struct tlvdb
*tlvdb
, tlv_tag_t tag
[]) {
323 struct tlvdb
*tnext
= tlvdb
;
325 while (tnext
&& tag
[i
]) {
326 tnext
= tlvdb_find(tnext
, tag
[i
]);
328 if (tag
[i
] && tnext
) {
329 tnext
= tnext
->children
;
336 void tlvdb_add(struct tlvdb
*tlvdb
, struct tlvdb
*other
)
338 while (tlvdb
->next
) {
345 void tlvdb_visit(const struct tlvdb
*tlvdb
, tlv_cb cb
, void *data
, int level
)
347 struct tlvdb
*next
= NULL
;
352 for (; tlvdb
; tlvdb
= next
) {
354 cb(data
, &tlvdb
->tag
, level
, (tlvdb
->children
== NULL
));
355 tlvdb_visit(tlvdb
->children
, cb
, data
, level
+ 1);
359 static const struct tlvdb
*tlvdb_next(const struct tlvdb
*tlvdb
)
362 return tlvdb
->children
;
368 tlvdb
= tlvdb
->parent
;
374 const struct tlv
*tlvdb_get(const struct tlvdb
*tlvdb
, tlv_tag_t tag
, const struct tlv
*prev
)
377 // tlvdb = tlvdb_next(container_of(prev, struct tlvdb, tag));
378 tlvdb
= tlvdb_next((struct tlvdb
*)prev
);
383 if (tlvdb
->tag
.tag
== tag
)
386 tlvdb
= tlvdb_next(tlvdb
);
392 const struct tlv
*tlvdb_get_inchild(const struct tlvdb
*tlvdb
, tlv_tag_t tag
, const struct tlv
*prev
) {
393 tlvdb
= tlvdb
->children
;
394 return tlvdb_get(tlvdb
, tag
, prev
);
397 unsigned char *tlv_encode(const struct tlv
*tlv
, size_t *len
)
399 size_t size
= tlv
->len
;
403 if (tlv
->tag
> 0x100)
421 if (tlv
->tag
> 0x100) {
422 data
[pos
++] = tlv
->tag
>> 8;
423 data
[pos
++] = tlv
->tag
& 0xff;
425 data
[pos
++] = tlv
->tag
;
427 if (tlv
->len
> 0x7f) {
429 data
[pos
++] = tlv
->len
;
431 data
[pos
++] = tlv
->len
;
433 memcpy(data
+ pos
, tlv
->value
, tlv
->len
);
440 bool tlv_is_constructed(const struct tlv
*tlv
)
442 return (tlv
->tag
< 0x100 ? tlv
->tag
: tlv
->tag
>> 8) & TLV_TAG_COMPLEX
;
445 bool tlv_equal(const struct tlv
*a
, const struct tlv
*b
)
453 return a
->tag
== b
->tag
&& a
->len
== b
->len
&& !memcmp(a
->value
, b
->value
, a
->len
);