]>
cvs.zerfleddert.de Git - proxmark3-svn/blob - client/emv/emv_pki.c
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 const unsigned char empty_tlv_value
[] = {};
31 static const struct tlv empty_tlv
= {.tag
= 0x0, .len
= 0, .value
= empty_tlv_value
};
33 static size_t emv_pki_hash_psn
[256] = { 0, 0, 11, 2, 17, 2, };
35 static unsigned char *emv_pki_decode_message(const struct emv_pk
*enc_pk
,
38 const struct tlv
*cert_tlv
,
39 ... /* A list of tlv pointers, end with NULL */
42 struct crypto_pk
*kcp
;
51 printf("ERROR: Can't find certificate\n");
55 if (cert_tlv
->len
!= enc_pk
->mlen
) {
56 printf("ERROR: Certificate length (%zd) not equal key length (%zd)\n", cert_tlv
->len
, enc_pk
->mlen
);
59 kcp
= crypto_pk_open(enc_pk
->pk_algo
,
60 enc_pk
->modulus
, enc_pk
->mlen
,
61 enc_pk
->exp
, enc_pk
->elen
);
65 data
= crypto_pk_encrypt(kcp
, cert_tlv
->value
, cert_tlv
->len
, &data_len
);
69 printf("Recovered data:\n");
70 dump_buffer(data, data_len, stdout, 0);
73 if (data
[data_len
-1] != 0xbc || data
[0] != 0x6a || data
[1] != msgtype
) {
74 printf("ERROR: Certificate format\n");
79 size_t hash_pos
= emv_pki_hash_psn
[msgtype
];
80 if (hash_pos
== 0 || hash_pos
> data_len
){
81 printf("ERROR: Cant get hash position in the certificate\n");
86 struct crypto_hash
*ch
;
87 ch
= crypto_hash_open(data
[hash_pos
]);
89 printf("ERROR: Cant do hash\n");
94 size_t hash_len
= crypto_hash_get_size(ch
);
95 crypto_hash_write(ch
, data
+ 1, data_len
- 2 - hash_len
);
97 va_start(vl
, cert_tlv
);
99 const struct tlv
*add_tlv
= va_arg(vl
, const struct tlv
*);
103 crypto_hash_write(ch
, add_tlv
->value
, add_tlv
->len
);
107 if (memcmp(data
+ data_len
- 1 - hash_len
, crypto_hash_read(ch
), hash_len
)) {
108 printf("ERROR: Calculated wrong hash\n");
109 printf("decoded: %s\n",sprint_hex(data
+ data_len
- 1 - hash_len
, hash_len
));
110 printf("calculated: %s\n",sprint_hex(crypto_hash_read(ch
), hash_len
));
111 crypto_hash_close(ch
);
116 crypto_hash_close(ch
);
118 *len
= data_len
- hash_len
- 1;
123 static unsigned emv_cn_length(const struct tlv
*tlv
)
127 for (i
= 0; i
< tlv
->len
; i
++) {
128 unsigned char c
= tlv
->value
[i
];
133 if ((c
& 0xf) == 0xf)
140 static unsigned char emv_cn_get(const struct tlv
*tlv
, unsigned pos
)
142 if (pos
> tlv
->len
* 2)
145 unsigned char c
= tlv
->value
[pos
/ 2];
153 static struct emv_pk
*emv_pki_decode_key_ex(const struct emv_pk
*enc_pk
,
154 unsigned char msgtype
,
155 const struct tlv
*pan_tlv
,
156 const struct tlv
*cert_tlv
,
157 const struct tlv
*exp_tlv
,
158 const struct tlv
*rem_tlv
,
159 const struct tlv
*add_tlv
,
168 if (!cert_tlv
|| !exp_tlv
|| !pan_tlv
)
172 rem_tlv
= &empty_tlv
;
176 else if (msgtype
== 4)
179 printf("ERROR: Message type must be 2 or 4\n");
183 data
= emv_pki_decode_message(enc_pk
, msgtype
, &data_len
,
189 if (!data
|| data_len
< 11 + pan_length
) {
190 printf("ERROR: Can't decode message\n");
195 printf("Recovered data:\n");
196 dump_buffer(data
, data_len
, stdout
, 0);
199 /* Perform the rest of checks here */
201 struct tlv pan2_tlv
= {
206 unsigned pan_len
= emv_cn_length(pan_tlv
);
207 unsigned pan2_len
= emv_cn_length(&pan2_tlv
);
209 if (((msgtype
== 2) && (pan2_len
< 4 || pan2_len
> pan_len
)) ||
210 ((msgtype
== 4) && (pan2_len
!= pan_len
))) {
211 printf("ERROR: Invalid PAN lengths\n");
218 for (i
= 0; i
< pan2_len
; i
++)
219 if (emv_cn_get(pan_tlv
, i
) != emv_cn_get(&pan2_tlv
, i
)) {
220 printf("ERROR: PAN data mismatch\n");
221 printf("tlv pan=%s\n", sprint_hex(pan_tlv
->value
, pan_tlv
->len
));
222 printf("cert pan=%s\n", sprint_hex(pan2_tlv
.value
, pan2_tlv
.len
));
228 pk_len
= data
[9 + pan_length
];
229 if (pk_len
> data_len
- 11 - pan_length
+ rem_tlv
->len
) {
230 printf("ERROR: Invalid pk length\n");
235 if (exp_tlv
->len
!= data
[10 + pan_length
]) {
240 struct emv_pk
*pk
= emv_pk_new(pk_len
, exp_tlv
->len
);
242 memcpy(pk
->rid
, enc_pk
->rid
, 5);
243 pk
->index
= enc_pk
->index
;
245 pk
->hash_algo
= data
[7 + pan_length
];
246 pk
->pk_algo
= data
[8 + pan_length
];
247 pk
->expire
= (data
[3 + pan_length
] << 16) | (data
[2 + pan_length
] << 8) | 0x31;
248 memcpy(pk
->serial
, data
+ 4 + pan_length
, 3);
249 memcpy(pk
->pan
, data
+ 2, pan_length
);
250 memset(pk
->pan
+ pan_length
, 0xff, 10 - pan_length
);
252 memcpy(pk
->modulus
, data
+ 11 + pan_length
,
253 pk_len
< data_len
- (11 + pan_length
) ?
255 data_len
- (11 + pan_length
));
256 memcpy(pk
->modulus
+ data_len
- (11 + pan_length
), rem_tlv
->value
, rem_tlv
->len
);
257 memcpy(pk
->exp
, exp_tlv
->value
, exp_tlv
->len
);
264 static struct emv_pk
*emv_pki_decode_key(const struct emv_pk
*enc_pk
,
265 unsigned char msgtype
,
266 const struct tlv
*pan_tlv
,
267 const struct tlv
*cert_tlv
,
268 const struct tlv
*exp_tlv
,
269 const struct tlv
*rem_tlv
,
270 const struct tlv
*add_tlv
272 return emv_pki_decode_key_ex(enc_pk
, msgtype
, pan_tlv
, cert_tlv
, exp_tlv
, rem_tlv
, add_tlv
, false);
275 struct emv_pk
*emv_pki_recover_issuer_cert(const struct emv_pk
*pk
, struct tlvdb
*db
)
277 return emv_pki_decode_key(pk
, 2,
278 tlvdb_get(db
, 0x5a, NULL
),
279 tlvdb_get(db
, 0x90, NULL
),
280 tlvdb_get(db
, 0x9f32, NULL
),
281 tlvdb_get(db
, 0x92, NULL
),
285 struct emv_pk
*emv_pki_recover_icc_cert(const struct emv_pk
*pk
, struct tlvdb
*db
, const struct tlv
*sda_tlv
)
287 return emv_pki_decode_key(pk
, 4,
288 tlvdb_get(db
, 0x5a, NULL
),
289 tlvdb_get(db
, 0x9f46, NULL
),
290 tlvdb_get(db
, 0x9f47, NULL
),
291 tlvdb_get(db
, 0x9f48, NULL
),
295 struct emv_pk
*emv_pki_recover_icc_pe_cert(const struct emv_pk
*pk
, struct tlvdb
*db
)
297 return emv_pki_decode_key(pk
, 4,
298 tlvdb_get(db
, 0x5a, NULL
),
299 tlvdb_get(db
, 0x9f2d, NULL
),
300 tlvdb_get(db
, 0x9f2e, NULL
),
301 tlvdb_get(db
, 0x9f2f, NULL
),
305 struct tlvdb
*emv_pki_recover_dac_ex(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
, const struct tlv
*sda_tlv
, bool showData
)
308 unsigned char *data
= emv_pki_decode_message(enc_pk
, 3, &data_len
,
309 tlvdb_get(db
, 0x93, NULL
),
313 if (!data
|| data_len
< 5)
317 printf("Recovered data:\n");
318 dump_buffer(data
, data_len
, stdout
, 0);
321 struct tlvdb
*dac_db
= tlvdb_fixed(0x9f45, 2, data
+3);
327 struct tlvdb
*emv_pki_recover_dac(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
, const struct tlv
*sda_tlv
) {
328 return emv_pki_recover_dac_ex(enc_pk
, db
, sda_tlv
, false);
331 struct tlvdb
*emv_pki_recover_idn(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
, const struct tlv
*dyn_tlv
) {
332 return emv_pki_recover_idn_ex(enc_pk
, db
, dyn_tlv
, false);
335 struct tlvdb
*emv_pki_recover_idn_ex(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
, const struct tlv
*dyn_tlv
, bool showData
)
338 unsigned char *data
= emv_pki_decode_message(enc_pk
, 5, &data_len
,
339 tlvdb_get(db
, 0x9f4b, NULL
),
343 if (!data
|| data_len
< 3)
346 if (data
[3] < 2 || data
[3] > data_len
- 3) {
352 printf("Recovered data:\n");
353 dump_buffer(data
, data_len
, stdout
, 0);
356 size_t idn_len
= data
[4];
357 if (idn_len
> data
[3] - 1) {
362 // 9f4c ICC Dynamic Number
363 struct tlvdb
*idn_db
= tlvdb_fixed(0x9f4c, idn_len
, data
+ 5);
370 struct tlvdb
*emv_pki_recover_atc_ex(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
, bool showData
)
373 unsigned char *data
= emv_pki_decode_message(enc_pk
, 5, &data_len
,
374 tlvdb_get(db
, 0x9f4b, NULL
),
375 tlvdb_get(db
, 0x9f37, NULL
),
376 tlvdb_get(db
, 0x9f02, NULL
),
377 tlvdb_get(db
, 0x5f2a, NULL
),
378 tlvdb_get(db
, 0x9f69, NULL
),
381 if (!data
|| data_len
< 3)
384 if (data
[3] < 2 || data
[3] > data_len
- 3) {
390 printf("Recovered data:\n");
391 dump_buffer(data
, data_len
, stdout
, 0);
394 size_t idn_len
= data
[4];
395 if (idn_len
> data
[3] - 1) {
400 // 9f36 Application Transaction Counter (ATC)
401 struct tlvdb
*atc_db
= tlvdb_fixed(0x9f36, idn_len
, data
+ 5);
408 static bool tlv_hash(void *data
, const struct tlv
*tlv
, int level
, bool is_leaf
)
410 struct crypto_hash
*ch
= data
;
414 if (tlv_is_constructed(tlv
))
417 if (tlv
->tag
== 0x9f4b)
420 tag
= tlv_encode(tlv
, &tag_len
);
421 crypto_hash_write(ch
, tag
, tag_len
);
427 struct tlvdb
*emv_pki_perform_cda(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
,
428 const struct tlvdb
*this_db
,
429 const struct tlv
*pdol_data_tlv
,
430 const struct tlv
*crm1_tlv
,
431 const struct tlv
*crm2_tlv
)
433 return emv_pki_perform_cda_ex(enc_pk
, db
, this_db
, pdol_data_tlv
, crm1_tlv
, crm2_tlv
, false);
435 struct tlvdb
*emv_pki_perform_cda_ex(const struct emv_pk
*enc_pk
, const struct tlvdb
*db
,
436 const struct tlvdb
*this_db
, // AC TLV result
437 const struct tlv
*pdol_data_tlv
, // PDOL
438 const struct tlv
*crm1_tlv
, // CDOL1
439 const struct tlv
*crm2_tlv
, // CDOL2
442 const struct tlv
*un_tlv
= tlvdb_get(db
, 0x9f37, NULL
);
443 const struct tlv
*cid_tlv
= tlvdb_get(this_db
, 0x9f27, NULL
);
445 if (!un_tlv
|| !cid_tlv
)
449 unsigned char *data
= emv_pki_decode_message(enc_pk
, 5, &data_len
,
450 tlvdb_get(this_db
, 0x9f4b, NULL
),
453 if (!data
|| data_len
< 3) {
454 printf("ERROR: can't decode message. len %zd\n", data_len
);
459 printf("Recovered data:\n");
460 dump_buffer(data
, data_len
, stdout
, 0);
463 if (data
[3] < 30 || data
[3] > data_len
- 4) {
464 printf("ERROR: Invalid data length\n");
469 if (!cid_tlv
|| cid_tlv
->len
!= 1 || cid_tlv
->value
[0] != data
[5 + data
[4]]) {
470 printf("ERROR: CID mismatch\n");
475 struct crypto_hash
*ch
;
476 ch
= crypto_hash_open(enc_pk
->hash_algo
);
478 printf("ERROR: can't create hash\n");
484 crypto_hash_write(ch
, pdol_data_tlv
->value
, pdol_data_tlv
->len
);
486 crypto_hash_write(ch
, crm1_tlv
->value
, crm1_tlv
->len
);
488 crypto_hash_write(ch
, crm2_tlv
->value
, crm2_tlv
->len
);
490 tlvdb_visit(this_db
, tlv_hash
, ch
, 0);
492 if (memcmp(data
+ 5 + data
[4] + 1 + 8, crypto_hash_read(ch
), 20)) {
493 printf("ERROR: calculated hash error\n");
494 crypto_hash_close(ch
);
498 crypto_hash_close(ch
);
500 size_t idn_len
= data
[4];
501 if (idn_len
> data
[3] - 1) {
502 printf("ERROR: Invalid IDN length\n");
507 struct tlvdb
*idn_db
= tlvdb_fixed(0x9f4c, idn_len
, data
+ 5);