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 //-----------------------------------------------------------------------------
31 static size_t dol_calculate_len(const struct tlv
*tlv
, size_t data_len
) {
35 const unsigned char *buf
= tlv
->value
;
36 size_t left
= tlv
->len
;
41 if (!tlv_parse_tl(&buf
, &left
, &cur_tlv
))
46 /* Last tag can be of variable length */
47 if (cur_tlv
.len
== 0 && left
== 0)
54 struct tlv
*dol_process(const struct tlv
*tlv
, const struct tlvdb
*tlvdb
, tlv_tag_t tag
) {
56 if (!tlv
|| !(res_len
= dol_calculate_len(tlv
, 0))) {
57 struct tlv
*res_tlv
= calloc(1, sizeof(*res_tlv
));
61 res_tlv
->value
= NULL
;
66 struct tlv
*res_tlv
= calloc(1, sizeof(*res_tlv
) + res_len
);
70 const unsigned char *buf
= tlv
->value
;
71 size_t left
= tlv
->len
;
72 unsigned char *res
= (unsigned char *)(res_tlv
+ 1);
77 if (!tlv_parse_tl(&buf
, &left
, &cur_tlv
) || pos
+ cur_tlv
.len
> res_len
) {
83 const struct tlv
*tag_tlv
= tlvdb_get(tlvdb
, cur_tlv
.tag
, NULL
);
85 memset(res
+ pos
, 0, cur_tlv
.len
);
86 } else if (tag_tlv
->len
> cur_tlv
.len
) {
87 memcpy(res
+ pos
, tag_tlv
->value
, cur_tlv
.len
);
89 // FIXME: cn data should be padded with 0xFF !!!
90 memcpy(res
+ pos
, tag_tlv
->value
, tag_tlv
->len
);
91 memset(res
+ pos
+ tag_tlv
->len
, 0, cur_tlv
.len
- tag_tlv
->len
);
97 res_tlv
->len
= res_len
;
103 struct tlvdb
*dol_parse(const struct tlv
*tlv
, const unsigned char *data
, size_t data_len
) {
107 const unsigned char *buf
= tlv
->value
;
108 size_t left
= tlv
->len
;
109 size_t res_len
= dol_calculate_len(tlv
, data_len
);
111 struct tlvdb
*db
= NULL
;
113 if (res_len
!= data_len
)
118 if (!tlv_parse_tl(&buf
, &left
, &cur_tlv
) || pos
+ cur_tlv
.len
> res_len
) {
123 /* Last tag can be of variable length */
124 if (cur_tlv
.len
== 0 && left
== 0)
125 cur_tlv
.len
= res_len
- pos
;
127 struct tlvdb
*tag_db
= tlvdb_fixed(cur_tlv
.tag
, cur_tlv
.len
, data
+ pos
);
131 tlvdb_add(db
, tag_db
);