]> git.zerfleddert.de Git - proxmark3-svn/blame - client/emv/emv_pki.c
added SoloKey certificate (#778)
[proxmark3-svn] / client / emv / emv_pki.c
CommitLineData
d03fb293
OM
1/*
2 * libopenemv - a library to work with EMV family of smart cards
3 * Copyright (C) 2015 Dmitry Eremin-Solenikov
4 *
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.
9 *
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.
14 */
15
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20#include "emv_pki.h"
21#include "crypto.h"
22#include "dump.h"
23#include "util.h"
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <stdarg.h>
29
95b697f0
OM
30static bool strictExecution = true;
31void PKISetStrictExecution(bool se) {
32 strictExecution = se;
33}
34
d03fb293
OM
35static const unsigned char empty_tlv_value[] = {};
36static const struct tlv empty_tlv = {.tag = 0x0, .len = 0, .value = empty_tlv_value};
37
38static size_t emv_pki_hash_psn[256] = { 0, 0, 11, 2, 17, 2, };
39
40static unsigned char *emv_pki_decode_message(const struct emv_pk *enc_pk,
41 uint8_t msgtype,
42 size_t *len,
43 const struct tlv *cert_tlv,
44 ... /* A list of tlv pointers, end with NULL */
45 )
46{
47 struct crypto_pk *kcp;
48 unsigned char *data;
49 size_t data_len;
50 va_list vl;
51
52 if (!enc_pk)
53 return NULL;
54
55 if (!cert_tlv) {
56 printf("ERROR: Can't find certificate\n");
57 return NULL;
58 }
59
60 if (cert_tlv->len != enc_pk->mlen) {
b838c4ff 61 printf("ERROR: Certificate length (%zd) not equal key length (%zd)\n", cert_tlv->len, enc_pk->mlen);
d03fb293
OM
62 return NULL;
63 }
64 kcp = crypto_pk_open(enc_pk->pk_algo,
65 enc_pk->modulus, enc_pk->mlen,
66 enc_pk->exp, enc_pk->elen);
67 if (!kcp)
68 return NULL;
69
70 data = crypto_pk_encrypt(kcp, cert_tlv->value, cert_tlv->len, &data_len);
71 crypto_pk_close(kcp);
72
73/* if (true){
74 printf("Recovered data:\n");
75 dump_buffer(data, data_len, stdout, 0);
76 }*/
77
78 if (data[data_len-1] != 0xbc || data[0] != 0x6a || data[1] != msgtype) {
79 printf("ERROR: Certificate format\n");
80 free(data);
81 return NULL;
82 }
83
84 size_t hash_pos = emv_pki_hash_psn[msgtype];
85 if (hash_pos == 0 || hash_pos > data_len){
86 printf("ERROR: Cant get hash position in the certificate\n");
87 free(data);
88 return NULL;
89 }
90
91 struct crypto_hash *ch;
92 ch = crypto_hash_open(data[hash_pos]);
93 if (!ch) {
94 printf("ERROR: Cant do hash\n");
95 free(data);
96 return NULL;
97 }
98
99 size_t hash_len = crypto_hash_get_size(ch);
100 crypto_hash_write(ch, data + 1, data_len - 2 - hash_len);
101
102 va_start(vl, cert_tlv);
103 while (true) {
104 const struct tlv *add_tlv = va_arg(vl, const struct tlv *);
105 if (!add_tlv)
106 break;
107
108 crypto_hash_write(ch, add_tlv->value, add_tlv->len);
109 }
110 va_end(vl);
111
112 if (memcmp(data + data_len - 1 - hash_len, crypto_hash_read(ch), hash_len)) {
113 printf("ERROR: Calculated wrong hash\n");
114 printf("decoded: %s\n",sprint_hex(data + data_len - 1 - hash_len, hash_len));
115 printf("calculated: %s\n",sprint_hex(crypto_hash_read(ch), hash_len));
95b697f0
OM
116
117 if (strictExecution) {
118 crypto_hash_close(ch);
119 free(data);
120 return NULL;
121 }
d03fb293
OM
122 }
123
124 crypto_hash_close(ch);
125
126 *len = data_len - hash_len - 1;
127
128 return data;
129}
130
131static unsigned emv_cn_length(const struct tlv *tlv)
132{
133 int i;
134
135 for (i = 0; i < tlv->len; i++) {
136 unsigned char c = tlv->value[i];
137
138 if (c >> 4 == 0xf)
139 return 2 * i;
140
141 if ((c & 0xf) == 0xf)
142 return 2 * i + 1;
143 }
144
145 return 2 * tlv->len;
146}
147
148static unsigned char emv_cn_get(const struct tlv *tlv, unsigned pos)
149{
150 if (pos > tlv->len * 2)
151 return 0xf;
152
153 unsigned char c = tlv->value[pos / 2];
154
155 if (pos % 2)
156 return c & 0xf;
157 else
158 return c >> 4;
159}
160
161static struct emv_pk *emv_pki_decode_key_ex(const struct emv_pk *enc_pk,
162 unsigned char msgtype,
163 const struct tlv *pan_tlv,
164 const struct tlv *cert_tlv,
165 const struct tlv *exp_tlv,
166 const struct tlv *rem_tlv,
167 const struct tlv *add_tlv,
168 bool showData
169 )
170{
171 size_t pan_length;
172 unsigned char *data;
173 size_t data_len;
174 size_t pk_len;
175
176 if (!cert_tlv || !exp_tlv || !pan_tlv)
177 return NULL;
178
179 if (!rem_tlv)
180 rem_tlv = &empty_tlv;
181
182 if (msgtype == 2)
183 pan_length = 4;
184 else if (msgtype == 4)
185 pan_length = 10;
186 else {
187 printf("ERROR: Message type must be 2 or 4\n");
188 return NULL;
189 }
190
191 data = emv_pki_decode_message(enc_pk, msgtype, &data_len,
192 cert_tlv,
193 rem_tlv,
194 exp_tlv,
195 add_tlv,
196 NULL);
197 if (!data || data_len < 11 + pan_length) {
198 printf("ERROR: Can't decode message\n");
199 return NULL;
200 }
201
202 if (showData){
203 printf("Recovered data:\n");
204 dump_buffer(data, data_len, stdout, 0);
205 }
206
207 /* Perform the rest of checks here */
208
209 struct tlv pan2_tlv = {
210 .tag = 0x5a,
211 .len = pan_length,
212 .value = &data[2],
213 };
214 unsigned pan_len = emv_cn_length(pan_tlv);
215 unsigned pan2_len = emv_cn_length(&pan2_tlv);
216
217 if (((msgtype == 2) && (pan2_len < 4 || pan2_len > pan_len)) ||
218 ((msgtype == 4) && (pan2_len != pan_len))) {
219 printf("ERROR: Invalid PAN lengths\n");
220 free(data);
221
222 return NULL;
223 }
224
225 unsigned i;
226 for (i = 0; i < pan2_len; i++)
227 if (emv_cn_get(pan_tlv, i) != emv_cn_get(&pan2_tlv, i)) {
228 printf("ERROR: PAN data mismatch\n");
229 printf("tlv pan=%s\n", sprint_hex(pan_tlv->value, pan_tlv->len));
230 printf("cert pan=%s\n", sprint_hex(pan2_tlv.value, pan2_tlv.len));
231 free(data);
232
233 return NULL;
234 }
235
236 pk_len = data[9 + pan_length];
237 if (pk_len > data_len - 11 - pan_length + rem_tlv->len) {
238 printf("ERROR: Invalid pk length\n");
239 free(data);
240 return NULL;
241 }
242
243 if (exp_tlv->len != data[10 + pan_length]) {
244 free(data);
245 return NULL;
246 }
247
248 struct emv_pk *pk = emv_pk_new(pk_len, exp_tlv->len);
249
250 memcpy(pk->rid, enc_pk->rid, 5);
251 pk->index = enc_pk->index;
252
253 pk->hash_algo = data[7 + pan_length];
254 pk->pk_algo = data[8 + pan_length];
255 pk->expire = (data[3 + pan_length] << 16) | (data[2 + pan_length] << 8) | 0x31;
256 memcpy(pk->serial, data + 4 + pan_length, 3);
257 memcpy(pk->pan, data + 2, pan_length);
258 memset(pk->pan + pan_length, 0xff, 10 - pan_length);
259
260 memcpy(pk->modulus, data + 11 + pan_length,
261 pk_len < data_len - (11 + pan_length) ?
262 pk_len :
263 data_len - (11 + pan_length));
264 memcpy(pk->modulus + data_len - (11 + pan_length), rem_tlv->value, rem_tlv->len);
265 memcpy(pk->exp, exp_tlv->value, exp_tlv->len);
266
267 free(data);
268
269 return pk;
270}
271
272static struct emv_pk *emv_pki_decode_key(const struct emv_pk *enc_pk,
273 unsigned char msgtype,
274 const struct tlv *pan_tlv,
275 const struct tlv *cert_tlv,
276 const struct tlv *exp_tlv,
277 const struct tlv *rem_tlv,
278 const struct tlv *add_tlv
279 ) {
280 return emv_pki_decode_key_ex(enc_pk, msgtype, pan_tlv, cert_tlv, exp_tlv, rem_tlv, add_tlv, false);
281}
282
283struct emv_pk *emv_pki_recover_issuer_cert(const struct emv_pk *pk, struct tlvdb *db)
284{
285 return emv_pki_decode_key(pk, 2,
286 tlvdb_get(db, 0x5a, NULL),
287 tlvdb_get(db, 0x90, NULL),
288 tlvdb_get(db, 0x9f32, NULL),
289 tlvdb_get(db, 0x92, NULL),
290 NULL);
291}
292
293struct emv_pk *emv_pki_recover_icc_cert(const struct emv_pk *pk, struct tlvdb *db, const struct tlv *sda_tlv)
294{
295 return emv_pki_decode_key(pk, 4,
296 tlvdb_get(db, 0x5a, NULL),
297 tlvdb_get(db, 0x9f46, NULL),
298 tlvdb_get(db, 0x9f47, NULL),
299 tlvdb_get(db, 0x9f48, NULL),
300 sda_tlv);
301}
302
303struct emv_pk *emv_pki_recover_icc_pe_cert(const struct emv_pk *pk, struct tlvdb *db)
304{
305 return emv_pki_decode_key(pk, 4,
306 tlvdb_get(db, 0x5a, NULL),
307 tlvdb_get(db, 0x9f2d, NULL),
308 tlvdb_get(db, 0x9f2e, NULL),
309 tlvdb_get(db, 0x9f2f, NULL),
310 NULL);
311}
312
313struct tlvdb *emv_pki_recover_dac_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *sda_tlv, bool showData)
314{
315 size_t data_len;
316 unsigned char *data = emv_pki_decode_message(enc_pk, 3, &data_len,
317 tlvdb_get(db, 0x93, NULL),
318 sda_tlv,
319 NULL);
320
321 if (!data || data_len < 5)
322 return NULL;
323
324 if (showData){
325 printf("Recovered data:\n");
326 dump_buffer(data, data_len, stdout, 0);
327 }
328
329 struct tlvdb *dac_db = tlvdb_fixed(0x9f45, 2, data+3);
330
331 free(data);
332
333 return dac_db;
334}
335struct tlvdb *emv_pki_recover_dac(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *sda_tlv) {
336 return emv_pki_recover_dac_ex(enc_pk, db, sda_tlv, false);
337}
338
339struct tlvdb *emv_pki_recover_idn(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *dyn_tlv) {
340 return emv_pki_recover_idn_ex(enc_pk, db, dyn_tlv, false);
341}
342
343struct tlvdb *emv_pki_recover_idn_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *dyn_tlv, bool showData)
344{
345 size_t data_len;
346 unsigned char *data = emv_pki_decode_message(enc_pk, 5, &data_len,
347 tlvdb_get(db, 0x9f4b, NULL),
348 dyn_tlv,
349 NULL);
350
351 if (!data || data_len < 3)
352 return NULL;
353
354 if (data[3] < 2 || data[3] > data_len - 3) {
355 free(data);
356 return NULL;
357 }
358
359 if (showData){
360 printf("Recovered data:\n");
361 dump_buffer(data, data_len, stdout, 0);
362 }
363
364 size_t idn_len = data[4];
365 if (idn_len > data[3] - 1) {
366 free(data);
367 return NULL;
368 }
369
370 // 9f4c ICC Dynamic Number
371 struct tlvdb *idn_db = tlvdb_fixed(0x9f4c, idn_len, data + 5);
372
373 free(data);
374
375 return idn_db;
376}
377
378struct tlvdb *emv_pki_recover_atc_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, bool showData)
379{
380 size_t data_len;
381 unsigned char *data = emv_pki_decode_message(enc_pk, 5, &data_len,
382 tlvdb_get(db, 0x9f4b, NULL),
383 tlvdb_get(db, 0x9f37, NULL),
384 tlvdb_get(db, 0x9f02, NULL),
385 tlvdb_get(db, 0x5f2a, NULL),
386 tlvdb_get(db, 0x9f69, NULL),
387 NULL);
388
389 if (!data || data_len < 3)
390 return NULL;
391
392 if (data[3] < 2 || data[3] > data_len - 3) {
393 free(data);
394 return NULL;
395 }
396
397 if (showData){
398 printf("Recovered data:\n");
399 dump_buffer(data, data_len, stdout, 0);
400 }
401
402 size_t idn_len = data[4];
403 if (idn_len > data[3] - 1) {
404 free(data);
405 return NULL;
406 }
407
408 // 9f36 Application Transaction Counter (ATC)
409 struct tlvdb *atc_db = tlvdb_fixed(0x9f36, idn_len, data + 5);
410
411 free(data);
412
413 return atc_db;
414}
415
416static bool tlv_hash(void *data, const struct tlv *tlv, int level, bool is_leaf)
417{
418 struct crypto_hash *ch = data;
419 size_t tag_len;
420 unsigned char *tag;
421
422 if (tlv_is_constructed(tlv))
423 return true;
424
425 if (tlv->tag == 0x9f4b)
426 return true;
427
428 tag = tlv_encode(tlv, &tag_len);
429 crypto_hash_write(ch, tag, tag_len);
430 free(tag);
431
432 return true;
433}
434
435struct tlvdb *emv_pki_perform_cda(const struct emv_pk *enc_pk, const struct tlvdb *db,
436 const struct tlvdb *this_db,
437 const struct tlv *pdol_data_tlv,
438 const struct tlv *crm1_tlv,
439 const struct tlv *crm2_tlv)
440{
441 return emv_pki_perform_cda_ex(enc_pk, db, this_db, pdol_data_tlv, crm1_tlv, crm2_tlv, false);
442}
443struct tlvdb *emv_pki_perform_cda_ex(const struct emv_pk *enc_pk, const struct tlvdb *db,
444 const struct tlvdb *this_db, // AC TLV result
445 const struct tlv *pdol_data_tlv, // PDOL
446 const struct tlv *crm1_tlv, // CDOL1
447 const struct tlv *crm2_tlv, // CDOL2
448 bool showData)
449{
450 const struct tlv *un_tlv = tlvdb_get(db, 0x9f37, NULL);
451 const struct tlv *cid_tlv = tlvdb_get(this_db, 0x9f27, NULL);
452
453 if (!un_tlv || !cid_tlv)
454 return NULL;
455
456 size_t data_len = 0;
457 unsigned char *data = emv_pki_decode_message(enc_pk, 5, &data_len,
458 tlvdb_get(this_db, 0x9f4b, NULL),
459 un_tlv,
460 NULL);
461 if (!data || data_len < 3) {
b838c4ff 462 printf("ERROR: can't decode message. len %zd\n", data_len);
d03fb293
OM
463 return NULL;
464 }
465
466 if (showData){
467 printf("Recovered data:\n");
468 dump_buffer(data, data_len, stdout, 0);
469 }
470
471 if (data[3] < 30 || data[3] > data_len - 4) {
472 printf("ERROR: Invalid data length\n");
473 free(data);
474 return NULL;
475 }
476
477 if (!cid_tlv || cid_tlv->len != 1 || cid_tlv->value[0] != data[5 + data[4]]) {
478 printf("ERROR: CID mismatch\n");
479 free(data);
480 return NULL;
481 }
482
483 struct crypto_hash *ch;
484 ch = crypto_hash_open(enc_pk->hash_algo);
485 if (!ch) {
486 printf("ERROR: can't create hash\n");
487 free(data);
488 return NULL;
489 }
490
491 if (pdol_data_tlv)
492 crypto_hash_write(ch, pdol_data_tlv->value, pdol_data_tlv->len);
493 if (crm1_tlv)
494 crypto_hash_write(ch, crm1_tlv->value, crm1_tlv->len);
495 if (crm2_tlv)
496 crypto_hash_write(ch, crm2_tlv->value, crm2_tlv->len);
497
498 tlvdb_visit(this_db, tlv_hash, ch, 0);
499
500 if (memcmp(data + 5 + data[4] + 1 + 8, crypto_hash_read(ch), 20)) {
501 printf("ERROR: calculated hash error\n");
502 crypto_hash_close(ch);
503 free(data);
504 return NULL;
505 }
506 crypto_hash_close(ch);
507
508 size_t idn_len = data[4];
509 if (idn_len > data[3] - 1) {
510 printf("ERROR: Invalid IDN length\n");
511 free(data);
512 return NULL;
513 }
514
515 struct tlvdb *idn_db = tlvdb_fixed(0x9f4c, idn_len, data + 5);
516 free(data);
517
518 return idn_db;
519}
Impressum, Datenschutz