2 * libopenemv - a library to work with EMV family of smart cards
3 * Copyright (C) 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.
30 static bool strictExecution
= true;
31 void PKISetStrictExecution(bool se
) {
35 static const unsigned char empty_tlv_value
[] = {};
36 static const struct tlv empty_tlv
= {.tag
= 0x0, .len
= 0, .value
= empty_tlv_value
};
38 static size_t emv_pki_hash_psn
[256] = { 0, 0, 11, 2, 17, 2, };
40 static unsigned char *emv_pki_decode_message(const struct emv_pk
*enc_pk
,
43 const struct tlv
*cert_tlv
,
45 ... /* A list of tlv pointers */
47 struct crypto_pk
*kcp
;
56 PrintAndLogEx(WARNING
, "ERROR: Can't find certificate");
60 if (cert_tlv
->len
!= enc_pk
->mlen
) {
61 PrintAndLogEx(WARNING
, "ERROR: Certificate length (%zu) not equal key length (%zu)", cert_tlv
->len
, enc_pk
->mlen
);
64 kcp
= crypto_pk_open(enc_pk
->pk_algo
,
65 enc_pk
->modulus
, enc_pk
->mlen
,
66 enc_pk
->exp
, enc_pk
->elen
);
70 data
= crypto_pk_encrypt(kcp
, cert_tlv
->value
, cert_tlv
->len
, &data_len
);
74 PrintAndLogEx(SUCCESS, "Recovered data:\n");
75 print_buffer(data, data_len, 1);
78 if (data
[data_len
- 1] != 0xbc || data
[0] != 0x6a || data
[1] != msgtype
) {
79 PrintAndLogEx(WARNING
, "ERROR: Certificate format");
84 size_t hash_pos
= emv_pki_hash_psn
[msgtype
];
85 if (hash_pos
== 0 || hash_pos
> data_len
) {
86 PrintAndLogEx(WARNING
, "ERROR: Cant get hash position in the certificate");
91 struct crypto_hash
*ch
;
92 ch
= crypto_hash_open(data
[hash_pos
]);
94 PrintAndLogEx(WARNING
, "ERROR: Cant do hash");
99 size_t hash_len
= crypto_hash_get_size(ch
);
100 crypto_hash_write(ch
, data
+ 1, data_len
- 2 - hash_len
);
102 va_start(vl
, tlv_count
);
103 for (int i
= 0; i
< tlv_count
; i
++) {
104 const struct tlv
*add_tlv
= va_arg(vl
, const struct tlv
*);
108 crypto_hash_write(ch
, add_tlv
->value
, add_tlv
->len
);
112 uint8_t hash
[hash_len
];
113 memset(hash
, 0, hash_len
);
114 memcpy(hash
, crypto_hash_read(ch
), hash_len
);
115 if (memcmp(data
+ data_len
- 1 - hash_len
, hash
, hash_len
)) {
116 PrintAndLogEx(WARNING
, "ERROR: Calculated wrong hash");
117 PrintAndLogEx(WARNING
, "decoded: " _YELLOW_("%s"), sprint_hex(data
+ data_len
- 1 - hash_len
, hash_len
));
118 PrintAndLogEx(WARNING
, "calculated: " _YELLOW_("%s"), sprint_hex(hash
, hash_len
));
120 if (strictExecution
) {
121 crypto_hash_close(ch
);
127 crypto_hash_close(ch
);
128 *len
= data_len
- hash_len
- 1;
132 static unsigned emv_cn_length(const struct tlv
*tlv
) {
133 for (int i
= 0; i
< tlv
->len
; i
++) {
134 unsigned char c
= tlv
->value
[i
];
139 if ((c
& 0xf) == 0xf)
145 static unsigned char emv_cn_get(const struct tlv
*tlv
, unsigned pos
) {
146 if (pos
> tlv
->len
* 2)
149 unsigned char c
= tlv
->value
[pos
/ 2];
157 static struct emv_pk
*emv_pki_decode_key_ex(const struct emv_pk
*enc_pk
,
158 unsigned char msgtype
,
159 const struct tlv
*pan_tlv
,
160 const struct tlv
*cert_tlv
,
161 const struct tlv
*exp_tlv
,
162 const struct tlv
*rem_tlv
,
163 const struct tlv
*add_tlv
,
164 const struct tlv
*sdatl_tlv
,
172 if (!cert_tlv
|| !exp_tlv
|| !pan_tlv
)
176 rem_tlv
= &empty_tlv
;
180 else if (msgtype
== 4)
183 PrintAndLogEx(WARNING
, "ERROR: Message type must be 2 or 4");
187 data
= emv_pki_decode_message(enc_pk
, msgtype
, &data_len
,
195 if (!data
|| data_len
< 11 + pan_length
) {
196 PrintAndLogEx(WARNING
, "ERROR: Can't decode message");
201 PrintAndLogEx(SUCCESS
, "Recovered data:");
202 print_buffer(data
, data_len
, 1);
205 /* Perform the rest of checks here */
207 struct tlv pan2_tlv
= {
212 unsigned pan_len
= emv_cn_length(pan_tlv
);
213 unsigned pan2_len
= emv_cn_length(&pan2_tlv
);
215 if (((msgtype
== 2) && (pan2_len
< 4 || pan2_len
> pan_len
)) ||
216 ((msgtype
== 4) && (pan2_len
!= pan_len
))) {
217 PrintAndLogEx(WARNING
, "ERROR: Invalid PAN lengths");
224 for (i
= 0; i
< pan2_len
; i
++)
225 if (emv_cn_get(pan_tlv
, i
) != emv_cn_get(&pan2_tlv
, i
)) {
226 PrintAndLogEx(WARNING
, "ERROR: PAN data mismatch");
227 PrintAndLogEx(WARNING
, "tlv pan " _YELLOW_("%s"), sprint_hex(pan_tlv
->value
, pan_tlv
->len
));
228 PrintAndLogEx(WARNING
, "cert pan " _YELLOW_("%s"), sprint_hex(pan2_tlv
.value
, pan2_tlv
.len
));
234 pk_len
= data
[9 + pan_length
];
235 if (pk_len
> data_len
- 11 - pan_length
+ rem_tlv
->len
) {
236 PrintAndLogEx(WARNING
, "ERROR: Invalid pk length");
241 if (exp_tlv
->len
!= data
[10 + pan_length
]) {
246 struct emv_pk
*pk
= emv_pk_new(pk_len
, exp_tlv
->len
);
248 memcpy(pk
->rid
, enc_pk
->rid
, 5);
249 pk
->index
= enc_pk
->index
;
251 pk
->hash_algo
= data
[7 + pan_length
];
252 pk
->pk_algo
= data
[8 + pan_length
];
253 pk
->expire
= (data
[3 + pan_length
] << 16) | (data
[2 + pan_length
] << 8) | 0x31;
254 memcpy(pk
->serial
, data
+ 4 + pan_length
, 3);
255 memcpy(pk
->pan
, data
+ 2, pan_length
);
256 memset(pk
->pan
+ pan_length
, 0xff, 10 - pan_length
);
258 memcpy(pk
->modulus
, data
+ 11 + pan_length
,
259 pk_len
< data_len
- (11 + pan_length
) ?
261 data_len
- (11 + pan_length
));
262 memcpy(pk
->modulus
+ data_len
- (11 + pan_length
), rem_tlv
->value
, rem_tlv
->len
);
263 memcpy(pk
->exp
, exp_tlv
->value
, exp_tlv
->len
);
269 static struct emv_pk
*emv_pki_decode_key(const struct emv_pk
*enc_pk
,
270 unsigned char msgtype
,
271 const struct tlv
*pan_tlv
,
272 const struct tlv
*cert_tlv
,
273 const struct tlv
*exp_tlv
,
274 const struct tlv
*rem_tlv
,
275 const struct tlv
*add_tlv
,
276 const struct tlv
*sdatl_tlv
278 return emv_pki_decode_key_ex(enc_pk
, msgtype
, pan_tlv
, cert_tlv
, exp_tlv
, rem_tlv
, add_tlv
, sdatl_tlv
, false);
281 struct emv_pk
*emv_pki_recover_issuer_cert(const struct emv_pk
*pk
, struct tlvdb
*db
) {
282 return emv_pki_decode_key(pk
, 2,
283 tlvdb_get(db
, 0x5a, NULL
),
284 tlvdb_get(db
, 0x90, NULL
),
285 tlvdb_get(db
, 0x9f32, NULL
),
286 tlvdb_get(db
, 0x92, NULL
),
291 struct emv_pk
*emv_pki_recover_icc_cert(const struct emv_pk
*pk
, struct tlvdb
*db
, const struct tlv
*sda_tlv
) {
293 unsigned char *sdatl
= emv_pki_sdatl_fill(db
, &sdatl_len
);
294 struct tlv sda_tdata
= {
295 .tag
= 0x00, // dummy tag
300 struct emv_pk
*res
= emv_pki_decode_key(pk
, 4,
301 tlvdb_get(db
, 0x5a, NULL
),
302 tlvdb_get(db
, 0x9f46, NULL
),
303 tlvdb_get(db
, 0x9f47, NULL
),
304 tlvdb_get(db
, 0x9f48, NULL
),
308 free(sdatl
); // malloc here: emv_pki_sdatl_fill
312 struct emv_pk
*emv_pki_recover_icc_pe_cert(const struct emv_pk
*pk
, struct tlvdb
*db
) {
313 return emv_pki_decode_key(pk
, 4,
314 tlvdb_get(db
, 0x5a, NULL
),
315 tlvdb_get(db
, 0x9f2d, NULL
),
316 tlvdb_get(db
, 0x9f2e, NULL
),
317 tlvdb_get(db
, 0x9f2f, NULL
),
322 unsigned char *emv_pki_sdatl_fill(const struct tlvdb
*db
, size_t *sdatl_len
) {
323 uint8_t buf
[2048] = {0};
328 const struct tlv
*sda_tl
= tlvdb_get(db
, 0x9f4a, NULL
);
329 if (!sda_tl
|| sda_tl
->len
== 0)
332 for (int i
= 0; i
< sda_tl
->len
; i
++) {
333 uint32_t tag
= sda_tl
->value
[i
]; // here may be multibyte, but now not
334 const struct tlv
*elm
= tlvdb_get(db
, tag
, NULL
);
336 memcpy(&buf
[len
], elm
->value
, elm
->len
);
343 unsigned char *value
= malloc(len
);
344 memcpy(value
, buf
, len
);
351 struct tlvdb
*emv_pki_recover_dac_ex(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
, const struct tlv
*sda_tlv
, bool showData
) {
354 // Static Data Authentication Tag List
356 unsigned char *sdatl
= emv_pki_sdatl_fill(db
, &sdatl_len
);
357 struct tlv sda_tdata
= {
358 .tag
= 0x00, // dummy tag
363 unsigned char *data
= emv_pki_decode_message(enc_pk
, 3, &data_len
,
364 tlvdb_get(db
, 0x93, NULL
),
370 free(sdatl
); // malloc here: emv_pki_sdatl_fill
372 if (!data
|| data_len
< 5)
376 PrintAndLogEx(SUCCESS
, "Recovered data:");
377 print_buffer(data
, data_len
, 1);
380 struct tlvdb
*dac_db
= tlvdb_fixed(0x9f45, 2, data
+ 3);
385 struct tlvdb
*emv_pki_recover_dac(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
, const struct tlv
*sda_tlv
) {
386 return emv_pki_recover_dac_ex(enc_pk
, db
, sda_tlv
, false);
389 struct tlvdb
*emv_pki_recover_idn(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
, const struct tlv
*dyn_tlv
) {
390 return emv_pki_recover_idn_ex(enc_pk
, db
, dyn_tlv
, false);
393 struct tlvdb
*emv_pki_recover_idn_ex(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
, const struct tlv
*dyn_tlv
, bool showData
) {
395 unsigned char *data
= emv_pki_decode_message(enc_pk
, 5, &data_len
,
396 tlvdb_get(db
, 0x9f4b, NULL
),
401 if (!data
|| data_len
< 3)
404 if (data
[3] < 2 || data
[3] > data_len
- 3) {
410 PrintAndLogEx(SUCCESS
, "Recovered data:");
411 print_buffer(data
, data_len
, 1);
414 size_t idn_len
= data
[4];
415 if (idn_len
> data
[3] - 1) {
420 // 9f4c ICC Dynamic Number
421 struct tlvdb
*idn_db
= tlvdb_fixed(0x9f4c, idn_len
, data
+ 5);
426 struct tlvdb
*emv_pki_recover_atc_ex(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
, bool showData
) {
428 unsigned char *data
= emv_pki_decode_message(enc_pk
, 5, &data_len
,
429 tlvdb_get(db
, 0x9f4b, NULL
),
431 tlvdb_get(db
, 0x9f37, NULL
),
432 tlvdb_get(db
, 0x9f02, NULL
),
433 tlvdb_get(db
, 0x5f2a, NULL
),
434 tlvdb_get(db
, 0x9f69, NULL
),
437 if (!data
|| data_len
< 3)
440 if (data
[3] < 2 || data
[3] > data_len
- 3) {
446 PrintAndLogEx(SUCCESS
, "Recovered data:");
447 print_buffer(data
, data_len
, 1);
450 size_t idn_len
= data
[4];
451 if (idn_len
> data
[3] - 1) {
456 // 9f36 Application Transaction Counter (ATC)
457 struct tlvdb
*atc_db
= tlvdb_fixed(0x9f36, idn_len
, data
+ 5);
464 static void tlv_hash(void *data
, const struct tlv
*tlv
, int level
, bool is_leaf
) {
465 struct crypto_hash
*ch
= data
;
469 if (tlv_is_constructed(tlv
))
472 if (tlv
->tag
== 0x9f4b)
475 tag
= tlv_encode(tlv
, &tag_len
);
476 crypto_hash_write(ch
, tag
, tag_len
);
480 struct tlvdb
*emv_pki_perform_cda(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
,
481 const struct tlvdb
*this_db
,
482 const struct tlv
*pdol_data_tlv
,
483 const struct tlv
*crm1_tlv
,
484 const struct tlv
*crm2_tlv
) {
485 return emv_pki_perform_cda_ex(enc_pk
, db
, this_db
, pdol_data_tlv
, crm1_tlv
, crm2_tlv
, false);
488 struct tlvdb
*emv_pki_perform_cda_ex(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
,
489 const struct tlvdb
*this_db
, // AC TLV result
490 const struct tlv
*pdol_data_tlv
, // PDOL
491 const struct tlv
*crm1_tlv
, // CDOL1
492 const struct tlv
*crm2_tlv
, // CDOL2
494 const struct tlv
*un_tlv
= tlvdb_get(db
, 0x9f37, NULL
);
495 const struct tlv
*cid_tlv
= tlvdb_get(this_db
, 0x9f27, NULL
);
497 if (!un_tlv
|| !cid_tlv
)
501 unsigned char *data
= emv_pki_decode_message(enc_pk
, 5, &data_len
,
502 tlvdb_get(this_db
, 0x9f4b, NULL
),
506 if (!data
|| data_len
< 3) {
507 PrintAndLogEx(WARNING
, "ERROR: can't decode message. [%zu bytes]", data_len
);
512 PrintAndLogEx(SUCCESS
, "Recovered data:");
513 print_buffer(data
, data_len
, 1);
516 if (data
[3] < 30 || data
[3] > data_len
- 4) {
517 PrintAndLogEx(WARNING
, "ERROR: Invalid data length");
522 if (!cid_tlv
|| cid_tlv
->len
!= 1 || cid_tlv
->value
[0] != data
[5 + data
[4]]) {
523 PrintAndLogEx(WARNING
, "ERROR: CID mismatch");
528 struct crypto_hash
*ch
;
529 ch
= crypto_hash_open(enc_pk
->hash_algo
);
531 PrintAndLogEx(WARNING
, "ERROR: can't create hash");
537 crypto_hash_write(ch
, pdol_data_tlv
->value
, pdol_data_tlv
->len
);
539 crypto_hash_write(ch
, crm1_tlv
->value
, crm1_tlv
->len
);
541 crypto_hash_write(ch
, crm2_tlv
->value
, crm2_tlv
->len
);
543 tlvdb_visit(this_db
, tlv_hash
, ch
, 0);
545 if (memcmp(data
+ 5 + data
[4] + 1 + 8, crypto_hash_read(ch
), 20)) {
546 PrintAndLogEx(WARNING
, "ERROR: calculated hash error");
547 crypto_hash_close(ch
);
551 crypto_hash_close(ch
);
553 size_t idn_len
= data
[4];
554 if (idn_len
> data
[3] - 1) {
555 PrintAndLogEx(WARNING
, "ERROR: Invalid IDN length");
560 struct tlvdb
*idn_db
= tlvdb_fixed(0x9f4c, idn_len
, data
+ 5);