Add ROCA vulnerability test (RRG repository PR 76 by @merlokk) (#762)
[proxmark3-svn] / client / emv / cmdemv.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2017, 2018 Merlok
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // EMV commands
9 //-----------------------------------------------------------------------------
10
11 #include "cmdemv.h"
12
13 #include <ctype.h>
14 #include "proxmark3.h"
15 #include "cmdparser.h"
16 #include "mifare.h"
17 #include "emvjson.h"
18 #include "emv_pki.h"
19 #include "emvcore.h"
20 #include "test/cryptotest.h"
21 #include "cliparser/cliparser.h"
22 #include "jansson.h"
23 #include "emv_roca.h"
24
25
26 #define TLV_ADD(tag, value)( tlvdb_change_or_add_node(tlvRoot, tag, sizeof(value) - 1, (const unsigned char *)value) )
27 void ParamLoadDefaults(struct tlvdb *tlvRoot) {
28 //9F02:(Amount, authorized (Numeric)) len:6
29 TLV_ADD(0x9F02, "\x00\x00\x00\x00\x01\x00");
30 //9F1A:(Terminal Country Code) len:2
31 TLV_ADD(0x9F1A, "ru");
32 //5F2A:(Transaction Currency Code) len:2
33 // USD 840, EUR 978, RUR 810, RUB 643, RUR 810(old), UAH 980, AZN 031, n/a 999
34 TLV_ADD(0x5F2A, "\x09\x80");
35 //9A:(Transaction Date) len:3
36 TLV_ADD(0x9A, "\x00\x00\x00");
37 //9C:(Transaction Type) len:1 | 00 => Goods and service #01 => Cash
38 TLV_ADD(0x9C, "\x00");
39 // 9F37 Unpredictable Number len:4
40 TLV_ADD(0x9F37, "\x01\x02\x03\x04");
41 // 9F6A Unpredictable Number (MSD for UDOL) len:4
42 TLV_ADD(0x9F6A, "\x01\x02\x03\x04");
43 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
44 TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC
45 }
46
47 int CmdEMVSelect(const char *cmd) {
48 uint8_t data[APDU_AID_LEN] = {0};
49 int datalen = 0;
50
51 CLIParserInit("emv select",
52 "Executes select applet command",
53 "Usage:\n\temv select -s a00000000101 -> select card, select applet\n\temv select -st a00000000101 -> select card, select applet, show result in TLV\n");
54
55 void* argtable[] = {
56 arg_param_begin,
57 arg_lit0("sS", "select", "activate field and select card"),
58 arg_lit0("kK", "keep", "keep field for next command"),
59 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
60 arg_lit0("tT", "tlv", "TLV decode results"),
61 #ifdef WITH_SMARTCARD
62 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
63 #endif
64 arg_strx0(NULL, NULL, "<HEX applet AID>", NULL),
65 arg_param_end
66 };
67 CLIExecWithReturn(cmd, argtable, true);
68
69 bool activateField = arg_get_lit(1);
70 bool leaveSignalON = arg_get_lit(2);
71 bool APDULogging = arg_get_lit(3);
72 bool decodeTLV = arg_get_lit(4);
73 EMVCommandChannel channel = ECC_CONTACTLESS;
74 #ifdef WITH_SMARTCARD
75 if (arg_get_lit(5))
76 channel = ECC_CONTACT;
77 CLIGetHexWithReturn(6, data, &datalen);
78 #else
79 CLIGetHexWithReturn(5, data, &datalen);
80 #endif
81 CLIParserFree();
82
83 SetAPDULogging(APDULogging);
84
85 // exec
86 uint8_t buf[APDU_RES_LEN] = {0};
87 size_t len = 0;
88 uint16_t sw = 0;
89 int res = EMVSelect(channel, activateField, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL);
90
91 if (sw)
92 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
93
94 if (res)
95 return res;
96
97 if (decodeTLV)
98 TLVPrintFromBuffer(buf, len);
99
100 return 0;
101 }
102
103 int CmdEMVSearch(const char *cmd) {
104
105 CLIParserInit("emv search",
106 "Tries to select all applets from applet list:\n",
107 "Usage:\n\temv search -s -> select card and search\n\temv search -st -> select card, search and show result in TLV\n");
108
109 void* argtable[] = {
110 arg_param_begin,
111 arg_lit0("sS", "select", "activate field and select card"),
112 arg_lit0("kK", "keep", "keep field ON for next command"),
113 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
114 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
115 #ifdef WITH_SMARTCARD
116 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
117 #endif
118 arg_param_end
119 };
120 CLIExecWithReturn(cmd, argtable, true);
121
122 bool activateField = arg_get_lit(1);
123 bool leaveSignalON = arg_get_lit(2);
124 bool APDULogging = arg_get_lit(3);
125 bool decodeTLV = arg_get_lit(4);
126 EMVCommandChannel channel = ECC_CONTACTLESS;
127 #ifdef WITH_SMARTCARD
128 if (arg_get_lit(5))
129 channel = ECC_CONTACT;
130 #endif
131 CLIParserFree();
132
133 SetAPDULogging(APDULogging);
134
135 struct tlvdb *t = NULL;
136 const char *al = "Applets list";
137 t = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
138
139 if (EMVSearch(channel, activateField, leaveSignalON, decodeTLV, t)) {
140 tlvdb_free(t);
141 return 2;
142 }
143
144 PrintAndLogEx(SUCCESS, "Search completed.");
145
146 // print list here
147 if (!decodeTLV) {
148 TLVPrintAIDlistFromSelectTLV(t);
149 }
150
151 tlvdb_free(t);
152
153 return 0;
154 }
155
156 int CmdEMVPPSE(const char *cmd) {
157
158 CLIParserInit("emv pse",
159 "Executes PSE/PPSE select command. It returns list of applet on the card:\n",
160 "Usage:\n\temv pse -s1 -> select, get pse\n\temv pse -st2 -> select, get ppse, show result in TLV\n");
161
162 void* argtable[] = {
163 arg_param_begin,
164 arg_lit0("sS", "select", "activate field and select card"),
165 arg_lit0("kK", "keep", "keep field ON for next command"),
166 arg_lit0("1", "pse", "pse (1PAY.SYS.DDF01) mode"),
167 arg_lit0("2", "ppse", "ppse (2PAY.SYS.DDF01) mode (default mode)"),
168 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
169 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
170 #ifdef WITH_SMARTCARD
171 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
172 #endif
173 arg_param_end
174 };
175 CLIExecWithReturn(cmd, argtable, true);
176
177 bool activateField = arg_get_lit(1);
178 bool leaveSignalON = arg_get_lit(2);
179 uint8_t PSENum = 2;
180 if (arg_get_lit(3))
181 PSENum = 1;
182 if (arg_get_lit(4))
183 PSENum = 2;
184 bool APDULogging = arg_get_lit(5);
185 bool decodeTLV = arg_get_lit(6);
186 EMVCommandChannel channel = ECC_CONTACTLESS;
187 #ifdef WITH_SMARTCARD
188 if (arg_get_lit(7))
189 channel = ECC_CONTACT;
190 #endif
191 CLIParserFree();
192
193 SetAPDULogging(APDULogging);
194
195 // exec
196 uint8_t buf[APDU_RES_LEN] = {0};
197 size_t len = 0;
198 uint16_t sw = 0;
199 int res = EMVSelectPSE(channel, activateField, leaveSignalON, PSENum, buf, sizeof(buf), &len, &sw);
200
201 if (sw)
202 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
203
204 if (res)
205 return res;
206
207
208 if (decodeTLV)
209 TLVPrintFromBuffer(buf, len);
210
211 return 0;
212 }
213
214 int CmdEMVGPO(const char *cmd) {
215 uint8_t data[APDU_RES_LEN] = {0};
216 int datalen = 0;
217
218 CLIParserInit("emv gpo",
219 "Executes Get Processing Options command. It returns data in TLV format (0x77 - format2) or plain format (0x80 - format1).\nNeeds a EMV applet to be selected.",
220 "Usage:\n\temv gpo -k -> execute GPO\n"
221 "\temv gpo -t 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n"
222 "\temv gpo -pmt 9F 37 04 -> load params from file, make PDOL data from PDOL, execute GPO with PDOL, show result in TLV\n");
223
224 void* argtable[] = {
225 arg_param_begin,
226 arg_lit0("kK", "keep", "keep field ON for next command"),
227 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for PDOLdata making from PDOL and parameters"),
228 arg_lit0("mM", "make", "make PDOLdata from PDOL (tag 9F38) and parameters (by default uses default parameters)"),
229 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
230 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
231 #ifdef WITH_SMARTCARD
232 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
233 #endif
234 arg_strx0(NULL, NULL, "<HEX PDOLdata/PDOL>", NULL),
235 arg_param_end
236 };
237 CLIExecWithReturn(cmd, argtable, true);
238
239 bool leaveSignalON = arg_get_lit(1);
240 bool paramsLoadFromFile = arg_get_lit(2);
241 bool dataMakeFromPDOL = arg_get_lit(3);
242 bool APDULogging = arg_get_lit(4);
243 bool decodeTLV = arg_get_lit(5);
244 EMVCommandChannel channel = ECC_CONTACTLESS;
245 #ifdef WITH_SMARTCARD
246 if (arg_get_lit(6))
247 channel = ECC_CONTACT;
248 CLIGetHexWithReturn(7, data, &datalen);
249 #else
250 CLIGetHexWithReturn(6, data, &datalen);
251 #endif
252 CLIParserFree();
253
254 SetAPDULogging(APDULogging);
255
256 // Init TLV tree
257 const char *alr = "Root terminal TLV tree";
258 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
259
260 // calc PDOL
261 struct tlv *pdol_data_tlv = NULL;
262 struct tlv data_tlv = {
263 .tag = 0x83,
264 .len = datalen,
265 .value = (uint8_t *)data,
266 };
267 if (dataMakeFromPDOL) {
268 ParamLoadDefaults(tlvRoot);
269
270 if (paramsLoadFromFile) {
271 PrintAndLogEx(INFO, "Params loading from file...");
272 ParamLoadFromJson(tlvRoot);
273 };
274
275 pdol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x9f38, datalen, data), tlvRoot, 0x83);
276 if (!pdol_data_tlv){
277 PrintAndLogEx(ERR, "Can't create PDOL TLV.");
278 tlvdb_free(tlvRoot);
279 return 4;
280 }
281 } else {
282 if (paramsLoadFromFile) {
283 PrintAndLogEx(WARNING, "Don't need to load parameters. Sending plain PDOL data...");
284 }
285 pdol_data_tlv = &data_tlv;
286 }
287
288 size_t pdol_data_tlv_data_len = 0;
289 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
290 if (!pdol_data_tlv_data) {
291 PrintAndLogEx(ERR, "Can't create PDOL data.");
292 tlvdb_free(tlvRoot);
293 return 4;
294 }
295 PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
296
297 // exec
298 uint8_t buf[APDU_RES_LEN] = {0};
299 size_t len = 0;
300 uint16_t sw = 0;
301 int res = EMVGPO(channel, leaveSignalON, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
302
303 if (pdol_data_tlv != &data_tlv)
304 free(pdol_data_tlv);
305 tlvdb_free(tlvRoot);
306
307 if (sw)
308 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
309
310 if (res)
311 return res;
312
313 if (decodeTLV)
314 TLVPrintFromBuffer(buf, len);
315
316 return 0;
317 }
318
319 int CmdEMVReadRecord(const char *cmd) {
320 uint8_t data[APDU_RES_LEN] = {0};
321 int datalen = 0;
322
323 CLIParserInit("emv readrec",
324 "Executes Read Record command. It returns data in TLV format.\nNeeds a bank applet to be selected and sometimes needs GPO to be executed.",
325 "Usage:\n\temv readrec -k 0101 -> read file SFI=01, SFIrec=01\n\temv readrec -kt 0201-> read file 0201 and show result in TLV\n");
326
327 void* argtable[] = {
328 arg_param_begin,
329 arg_lit0("kK", "keep", "keep field ON for next command"),
330 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
331 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
332 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
333 arg_strx1(NULL, NULL, "<SFI 1byte HEX><SFIrecord 1byte HEX>", NULL),
334 arg_param_end
335 };
336 CLIExecWithReturn(cmd, argtable, true);
337
338 bool leaveSignalON = arg_get_lit(1);
339 bool APDULogging = arg_get_lit(2);
340 bool decodeTLV = arg_get_lit(3);
341 EMVCommandChannel channel = ECC_CONTACTLESS;
342 #ifdef WITH_SMARTCARD
343 if (arg_get_lit(4))
344 channel = ECC_CONTACT;
345 CLIGetHexWithReturn(5, data, &datalen);
346 #else
347 CLIGetHexWithReturn(4, data, &datalen);
348 #endif
349 CLIParserFree();
350
351 if (datalen != 2) {
352 PrintAndLogEx(ERR, "Command needs to have 2 bytes of data");
353 return 1;
354 }
355
356 SetAPDULogging(APDULogging);
357
358 // exec
359 uint8_t buf[APDU_RES_LEN] = {0};
360 size_t len = 0;
361 uint16_t sw = 0;
362 int res = EMVReadRecord(channel, leaveSignalON, data[0], data[1], buf, sizeof(buf), &len, &sw, NULL);
363
364 if (sw)
365 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
366
367 if (res)
368 return res;
369
370
371 if (decodeTLV)
372 TLVPrintFromBuffer(buf, len);
373
374 return 0;
375 }
376
377 int CmdEMVAC(const char *cmd) {
378 uint8_t data[APDU_RES_LEN] = {0};
379 int datalen = 0;
380
381 CLIParserInit("emv genac",
382 "Generate Application Cryptogram command. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.",
383 "Usage:\n\temv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n"
384 "\temv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n"
385 "\temv genac -Daac 01020304 -> generate AC with 4-byte CDOL data and terminal decision 'declined'\n"
386 "\temv genac -pmt 9F 37 04 -> load params from file, make CDOL data from CDOL, generate AC with CDOL, show result in TLV");
387
388 void* argtable[] = {
389 arg_param_begin,
390 arg_lit0("kK", "keep", "keep field ON for next command"),
391 arg_lit0("cC", "cda", "executes CDA transaction. Needs to get SDAD in results."),
392 arg_str0("dD", "decision", "<aac|tc|arqc>", "Terminal decision. aac - declined, tc - approved, arqc - online authorisation requested"),
393 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for CDOLdata making from CDOL and parameters"),
394 arg_lit0("mM", "make", "make CDOLdata from CDOL (tag 8C and 8D) and parameters (by default uses default parameters)"),
395 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
396 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
397 #ifdef WITH_SMARTCARD
398 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
399 #endif
400 arg_strx1(NULL, NULL, "<HEX CDOLdata/CDOL>", NULL),
401 arg_param_end
402 };
403 CLIExecWithReturn(cmd, argtable, false);
404
405 bool leaveSignalON = arg_get_lit(1);
406 bool trTypeCDA = arg_get_lit(2);
407 uint8_t termDecision = 0xff;
408 if (arg_get_str_len(3)) {
409 if (!strncmp(arg_get_str(3)->sval[0], "aac", 4))
410 termDecision = EMVAC_AAC;
411 if (!strncmp(arg_get_str(3)->sval[0], "tc", 4))
412 termDecision = EMVAC_TC;
413 if (!strncmp(arg_get_str(3)->sval[0], "arqc", 4))
414 termDecision = EMVAC_ARQC;
415
416 if (termDecision == 0xff) {
417 PrintAndLog("ERROR: can't find terminal decision '%s'", arg_get_str(3)->sval[0]);
418 return 1;
419 }
420 } else {
421 termDecision = EMVAC_TC;
422 }
423 if (trTypeCDA)
424 termDecision = termDecision | EMVAC_CDAREQ;
425 bool paramsLoadFromFile = arg_get_lit(4);
426 bool dataMakeFromCDOL = arg_get_lit(5);
427 bool APDULogging = arg_get_lit(6);
428 bool decodeTLV = arg_get_lit(7);
429 EMVCommandChannel channel = ECC_CONTACTLESS;
430 #ifdef WITH_SMARTCARD
431 if (arg_get_lit(8))
432 channel = ECC_CONTACT;
433 CLIGetHexWithReturn(9, data, &datalen);
434 #else
435 CLIGetHexWithReturn(8, data, &datalen);
436 #endif
437 CLIParserFree();
438
439 SetAPDULogging(APDULogging);
440
441 // Init TLV tree
442 const char *alr = "Root terminal TLV tree";
443 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
444
445 // calc CDOL
446 struct tlv *cdol_data_tlv = NULL;
447 struct tlv data_tlv = {
448 .tag = 0x01,
449 .len = datalen,
450 .value = (uint8_t *)data,
451 };
452
453 if (dataMakeFromCDOL) {
454 ParamLoadDefaults(tlvRoot);
455
456 if (paramsLoadFromFile) {
457 PrintAndLogEx(INFO, "Params loading from file...");
458 ParamLoadFromJson(tlvRoot);
459 };
460
461 cdol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x8c, datalen, data), tlvRoot, 0x01); // 0x01 - dummy tag
462 if (!cdol_data_tlv){
463 PrintAndLogEx(ERR, "Can't create CDOL TLV.");
464 tlvdb_free(tlvRoot);
465 return 4;
466 }
467 } else {
468 if (paramsLoadFromFile) {
469 PrintAndLogEx(WARNING, "Don't need to load parameters. Sending plain CDOL data...");
470 }
471 cdol_data_tlv = &data_tlv;
472 }
473
474 PrintAndLogEx(INFO, "CDOL data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len));
475
476 // exec
477 uint8_t buf[APDU_RES_LEN] = {0};
478 size_t len = 0;
479 uint16_t sw = 0;
480 int res = EMVAC(channel, leaveSignalON, termDecision, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
481
482 if (cdol_data_tlv != &data_tlv)
483 free(cdol_data_tlv);
484 tlvdb_free(tlvRoot);
485
486 if (sw)
487 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
488
489 if (res)
490 return res;
491
492 if (decodeTLV)
493 TLVPrintFromBuffer(buf, len);
494
495 return 0;
496 }
497
498 int CmdEMVGenerateChallenge(const char *cmd) {
499
500 CLIParserInit("emv challenge",
501 "Executes Generate Challenge command. It returns 4 or 8-byte random number from card.\nNeeds a EMV applet to be selected and GPO to be executed.",
502 "Usage:\n\temv challenge -> get challenge\n\temv challenge -k -> get challenge, keep fileld ON\n");
503
504 void* argtable[] = {
505 arg_param_begin,
506 arg_lit0("kK", "keep", "keep field ON for next command"),
507 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
508 #ifdef WITH_SMARTCARD
509 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
510 #endif
511 arg_param_end
512 };
513 CLIExecWithReturn(cmd, argtable, true);
514
515 bool leaveSignalON = arg_get_lit(1);
516 bool APDULogging = arg_get_lit(2);
517 EMVCommandChannel channel = ECC_CONTACTLESS;
518 #ifdef WITH_SMARTCARD
519 if (arg_get_lit(3))
520 channel = ECC_CONTACT;
521 #endif
522 CLIParserFree();
523
524 SetAPDULogging(APDULogging);
525
526 // exec
527 uint8_t buf[APDU_RES_LEN] = {0};
528 size_t len = 0;
529 uint16_t sw = 0;
530 int res = EMVGenerateChallenge(channel, leaveSignalON, buf, sizeof(buf), &len, &sw, NULL);
531
532 if (sw)
533 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
534
535 if (res)
536 return res;
537
538 PrintAndLogEx(SUCCESS, "Challenge: %s", sprint_hex(buf, len));
539
540 if (len != 4 && len != 8)
541 PrintAndLogEx(WARNING, "Length of challenge must be 4 or 8, but it %d", len);
542
543 return 0;
544 }
545
546 int CmdEMVInternalAuthenticate(const char *cmd) {
547 uint8_t data[APDU_RES_LEN] = {0};
548 int datalen = 0;
549
550 CLIParserInit("emv intauth",
551 "Generate Internal Authenticate command. Usually needs 4-byte random number. It returns data in TLV format .\n"
552 "Needs a EMV applet to be selected and GPO to be executed.",
553
554 "Usage:\n"
555 "\temv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n"
556 "\temv intauth -t 01020304 -> execute Internal Authenticate with 4-byte DDOL data, show result in TLV\n"
557 "\temv intauth -pmt 9F 37 04 -> load params from file, make DDOL data from DDOL, Internal Authenticate with DDOL, show result in TLV");
558
559 void* argtable[] = {
560 arg_param_begin,
561 arg_lit0("kK", "keep", "keep field ON for next command"),
562 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for DDOLdata making from DDOL and parameters"),
563 arg_lit0("mM", "make", "make DDOLdata from DDOL (tag 9F49) and parameters (by default uses default parameters)"),
564 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
565 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
566 #ifdef WITH_SMARTCARD
567 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
568 #endif
569 arg_strx1(NULL, NULL, "<HEX DDOLdata/DDOL>", NULL),
570 arg_param_end
571 };
572 CLIExecWithReturn(cmd, argtable, false);
573
574 bool leaveSignalON = arg_get_lit(1);
575 bool paramsLoadFromFile = arg_get_lit(2);
576 bool dataMakeFromDDOL = arg_get_lit(3);
577 bool APDULogging = arg_get_lit(4);
578 bool decodeTLV = arg_get_lit(5);
579 EMVCommandChannel channel = ECC_CONTACTLESS;
580 #ifdef WITH_SMARTCARD
581 if (arg_get_lit(6))
582 channel = ECC_CONTACT;
583 CLIGetHexWithReturn(7, data, &datalen);
584 #else
585 CLIGetHexWithReturn(6, data, &datalen);
586 #endif
587 CLIParserFree();
588
589 SetAPDULogging(APDULogging);
590
591 // Init TLV tree
592 const char *alr = "Root terminal TLV tree";
593 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
594
595 // calc DDOL
596 struct tlv *ddol_data_tlv = NULL;
597 struct tlv data_tlv = {
598 .tag = 0x01,
599 .len = datalen,
600 .value = (uint8_t *)data,
601 };
602
603 if (dataMakeFromDDOL) {
604 ParamLoadDefaults(tlvRoot);
605
606 if (paramsLoadFromFile) {
607 PrintAndLogEx(INFO, "Params loading from file...");
608 ParamLoadFromJson(tlvRoot);
609 };
610
611 ddol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x9f49, datalen, data), tlvRoot, 0x01); // 0x01 - dummy tag
612 if (!ddol_data_tlv){
613 PrintAndLogEx(ERR, "Can't create DDOL TLV.");
614 tlvdb_free(tlvRoot);
615 return 4;
616 }
617 } else {
618 if (paramsLoadFromFile) {
619 PrintAndLogEx(WARNING, "Don't need to load parameters. Sending plain DDOL data...");
620 }
621 ddol_data_tlv = &data_tlv;
622 }
623
624 PrintAndLogEx(INFO, "DDOL data[%d]: %s", ddol_data_tlv->len, sprint_hex(ddol_data_tlv->value, ddol_data_tlv->len));
625
626 // exec
627 uint8_t buf[APDU_RES_LEN] = {0};
628 size_t len = 0;
629 uint16_t sw = 0;
630 int res = EMVInternalAuthenticate(channel, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL);
631
632 if (ddol_data_tlv != &data_tlv)
633 free(ddol_data_tlv);
634 tlvdb_free(tlvRoot);
635
636 if (sw)
637 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
638
639 if (res)
640 return res;
641
642 if (decodeTLV)
643 TLVPrintFromBuffer(buf, len);
644
645 return 0;
646 }
647
648 #define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;}
649
650 void InitTransactionParameters(struct tlvdb *tlvRoot, bool paramLoadJSON, enum TransactionType TrType, bool GenACGPO) {
651
652 ParamLoadDefaults(tlvRoot);
653
654 if (paramLoadJSON) {
655 PrintAndLog("* * Transaction parameters loading from JSON...");
656 ParamLoadFromJson(tlvRoot);
657 }
658
659 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
660 char *qVSDC = "\x26\x00\x00\x00";
661 if (GenACGPO) {
662 qVSDC = "\x26\x80\x00\x00";
663 }
664 switch(TrType) {
665 case TT_MSD:
666 TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD
667 break;
668 // not standard for contactless. just for test.
669 case TT_VSDC:
670 TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC
671 break;
672 case TT_QVSDCMCHIP:
673 TLV_ADD(0x9F66, qVSDC); // qVSDC
674 break;
675 case TT_CDA:
676 TLV_ADD(0x9F66, qVSDC); // qVSDC (VISA CDA not enabled)
677 break;
678 default:
679 break;
680 }
681 }
682
683 void ProcessGPOResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, bool decodeTLV) {
684 if (buf[0] == 0x80) {
685 if (decodeTLV){
686 PrintAndLog("GPO response format1:");
687 TLVPrintFromBuffer(buf, len);
688 }
689
690 if (len < 4 || (len - 4) % 4) {
691 PrintAndLogEx(ERR, "GPO response format1 parsing error. length=%d", len);
692 } else {
693 // AIP
694 struct tlvdb * f1AIP = tlvdb_fixed(0x82, 2, buf + 2);
695 tlvdb_add(tlvRoot, f1AIP);
696 if (decodeTLV){
697 PrintAndLogEx(INFO, "\n* * Decode response format 1 (0x80) AIP and AFL:");
698 TLVPrintFromTLV(f1AIP);
699 }
700
701 // AFL
702 struct tlvdb * f1AFL = tlvdb_fixed(0x94, len - 4, buf + 2 + 2);
703 tlvdb_add(tlvRoot, f1AFL);
704 if (decodeTLV)
705 TLVPrintFromTLV(f1AFL);
706 }
707 } else {
708 if (decodeTLV)
709 TLVPrintFromBuffer(buf, len);
710 }
711 }
712
713 int CmdEMVExec(const char *cmd) {
714 uint8_t buf[APDU_RES_LEN] = {0};
715 size_t len = 0;
716 uint16_t sw = 0;
717 uint8_t AID[APDU_AID_LEN] = {0};
718 size_t AIDlen = 0;
719 uint8_t ODAiList[4096];
720 size_t ODAiListLen = 0;
721
722 int res;
723
724 struct tlvdb *tlvSelect = NULL;
725 struct tlvdb *tlvRoot = NULL;
726 struct tlv *pdol_data_tlv = NULL;
727
728 CLIParserInit("emv exec",
729 "Executes EMV contactless transaction",
730 "Usage:\n"
731 "\temv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n"
732 "\temv exec -satc -> select card, execute CDA transaction, show APDU and TLV\n");
733
734 void* argtable[] = {
735 arg_param_begin,
736 arg_lit0("sS", "select", "activate field and select card."),
737 arg_lit0("aA", "apdu", "show APDU reqests and responses."),
738 arg_lit0("tT", "tlv", "TLV decode results."),
739 arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."),
740 arg_lit0("fF", "forceaid", "Force search AID. Search AID instead of execute PPSE."),
741 arg_rem("By default:", "Transaction type - MSD"),
742 arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."),
743 arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."),
744 arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."),
745 arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
746 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
747 arg_param_end
748 };
749 CLIExecWithReturn(cmd, argtable, true);
750
751 bool activateField = arg_get_lit(1);
752 bool showAPDU = arg_get_lit(2);
753 bool decodeTLV = arg_get_lit(3);
754 bool paramLoadJSON = arg_get_lit(4);
755 bool forceSearch = arg_get_lit(5);
756
757 enum TransactionType TrType = TT_MSD;
758 if (arg_get_lit(7))
759 TrType = TT_QVSDCMCHIP;
760 if (arg_get_lit(8))
761 TrType = TT_CDA;
762 if (arg_get_lit(9))
763 TrType = TT_VSDC;
764
765 bool GenACGPO = arg_get_lit(10);
766 EMVCommandChannel channel = ECC_CONTACTLESS;
767 #ifdef WITH_SMARTCARD
768 if (arg_get_lit(11))
769 channel = ECC_CONTACT;
770 #endif
771 uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
772 CLIParserFree();
773
774 SetAPDULogging(showAPDU);
775
776 // init applets list tree
777 const char *al = "Applets list";
778 tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
779
780 // Application Selection
781 // https://www.openscdp.org/scripts/tutorial/emv/applicationselection.html
782 if (!forceSearch) {
783 // PPSE
784 PrintAndLogEx(NORMAL, "\n* PPSE.");
785 SetAPDULogging(showAPDU);
786 res = EMVSearchPSE(channel, activateField, true, psenum, decodeTLV, tlvSelect);
787
788 // check PPSE and select application id
789 if (!res) {
790 TLVPrintAIDlistFromSelectTLV(tlvSelect);
791 EMVSelectApplication(tlvSelect, AID, &AIDlen);
792 }
793 }
794
795 // Search
796 if (!AIDlen) {
797 PrintAndLogEx(NORMAL, "\n* Search AID in list.");
798 SetAPDULogging(false);
799 if (EMVSearch(channel, activateField, true, decodeTLV, tlvSelect)) {
800 dreturn(2);
801 }
802
803 // check search and select application id
804 TLVPrintAIDlistFromSelectTLV(tlvSelect);
805 EMVSelectApplication(tlvSelect, AID, &AIDlen);
806 }
807
808 // Init TLV tree
809 const char *alr = "Root terminal TLV tree";
810 tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
811
812 // check if we found EMV application on card
813 if (!AIDlen) {
814 PrintAndLogEx(WARNING, "Can't select AID. EMV AID not found");
815 dreturn(2);
816 }
817
818 // Select
819 PrintAndLogEx(NORMAL, "\n* Selecting AID:%s", sprint_hex_inrow(AID, AIDlen));
820 SetAPDULogging(showAPDU);
821 res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
822
823 if (res) {
824 PrintAndLogEx(WARNING, "Can't select AID (%d). Exit...", res);
825 dreturn(3);
826 }
827
828 if (decodeTLV)
829 TLVPrintFromBuffer(buf, len);
830 PrintAndLogEx(INFO, "* Selected.");
831
832 PrintAndLogEx(INFO, "\n* Init transaction parameters.");
833 InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO);
834 TLVPrintFromTLV(tlvRoot); // TODO delete!!!
835
836 PrintAndLogEx(NORMAL, "\n* Calc PDOL.");
837 pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
838 if (!pdol_data_tlv){
839 PrintAndLogEx(WARNING, "Error: can't create PDOL TLV.");
840 dreturn(4);
841 }
842
843 size_t pdol_data_tlv_data_len;
844 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
845 if (!pdol_data_tlv_data) {
846 PrintAndLogEx(WARNING, "Error: can't create PDOL data.");
847 dreturn(4);
848 }
849 PrintAndLogEx(NORMAL, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
850
851 PrintAndLogEx(NORMAL, "\n* GPO.");
852 res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
853
854 free(pdol_data_tlv_data);
855 //free(pdol_data_tlv); --- free on exit.
856
857 if (res) {
858 PrintAndLogEx(NORMAL, "GPO error(%d): %4x. Exit...", res, sw);
859 dreturn(5);
860 }
861
862 // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
863 ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV);
864
865 // extract PAN from track2
866 {
867 const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
868 if (!tlvdb_get(tlvRoot, 0x5a, NULL) && track2 && track2->len >= 8) {
869 struct tlvdb *pan = GetPANFromTrack2(track2);
870 if (pan) {
871 tlvdb_add(tlvRoot, pan);
872
873 const struct tlv *pantlv = tlvdb_get(tlvRoot, 0x5a, NULL);
874 PrintAndLogEx(NORMAL, "\n* * Extracted PAN from track2: %s", sprint_hex(pantlv->value, pantlv->len));
875 } else {
876 PrintAndLogEx(NORMAL, "\n* * WARNING: Can't extract PAN from track2.");
877 }
878 }
879 }
880
881 PrintAndLogEx(NORMAL, "\n* Read records from AFL.");
882 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
883 if (!AFL || !AFL->len) {
884 PrintAndLogEx(WARNING, "AFL not found.");
885 }
886
887 while(AFL && AFL->len) {
888 if (AFL->len % 4) {
889 PrintAndLogEx(WARNING, "Error: Wrong AFL length: %d", AFL->len);
890 break;
891 }
892
893 for (int i = 0; i < AFL->len / 4; i++) {
894 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
895 uint8_t SFIstart = AFL->value[i * 4 + 1];
896 uint8_t SFIend = AFL->value[i * 4 + 2];
897 uint8_t SFIoffline = AFL->value[i * 4 + 3];
898
899 PrintAndLogEx(NORMAL, "* * SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
900 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
901 PrintAndLogEx(NORMAL, "SFI ERROR! Skipped...");
902 continue;
903 }
904
905 for(int n = SFIstart; n <= SFIend; n++) {
906 PrintAndLogEx(NORMAL, "* * * SFI[%02x] %d", SFI, n);
907
908 res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
909 if (res) {
910 PrintAndLogEx(WARNING, "Error SFI[%02x]. APDU error %4x", SFI, sw);
911 continue;
912 }
913
914 if (decodeTLV) {
915 TLVPrintFromBuffer(buf, len);
916 PrintAndLogEx(NORMAL, "");
917 }
918
919 // Build Input list for Offline Data Authentication
920 // EMV 4.3 book3 10.3, page 96
921 if (SFIoffline) {
922 if (SFI < 11) {
923 const unsigned char *abuf = buf;
924 size_t elmlen = len;
925 struct tlv e;
926 if (tlv_parse_tl(&abuf, &elmlen, &e)) {
927 memcpy(&ODAiList[ODAiListLen], &buf[len - elmlen], elmlen);
928 ODAiListLen += elmlen;
929 } else {
930 PrintAndLogEx(WARNING, "Error SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI);
931 }
932 } else {
933 memcpy(&ODAiList[ODAiListLen], buf, len);
934 ODAiListLen += len;
935 }
936 }
937 }
938 }
939
940 break;
941 }
942
943 // copy Input list for Offline Data Authentication
944 if (ODAiListLen) {
945 struct tlvdb *oda = tlvdb_fixed(0x21, ODAiListLen, ODAiList); // not a standard tag
946 tlvdb_add(tlvRoot, oda);
947 PrintAndLogEx(NORMAL, "* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen);
948 }
949
950 // get AIP
951 uint16_t AIP = 0;
952 const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL);
953 if (AIPtlv) {
954 AIP = AIPtlv->value[0] + AIPtlv->value[1] * 0x100;
955 PrintAndLogEx(NORMAL, "* * AIP=%04x", AIP);
956 } else {
957 PrintAndLogEx(ERR, "Can't found AIP.");
958 }
959
960 // SDA
961 if (AIP & 0x0040) {
962 PrintAndLogEx(NORMAL, "\n* SDA");
963 trSDA(tlvRoot);
964 }
965
966 // DDA
967 if (AIP & 0x0020) {
968 PrintAndLogEx(NORMAL, "\n* DDA");
969 trDDA(channel, decodeTLV, tlvRoot);
970 }
971
972 // transaction check
973
974 // qVSDC
975 if (TrType == TT_QVSDCMCHIP|| TrType == TT_CDA){
976 // 9F26: Application Cryptogram
977 const struct tlv *AC = tlvdb_get(tlvRoot, 0x9F26, NULL);
978 if (AC) {
979 PrintAndLogEx(NORMAL, "\n--> qVSDC transaction.");
980 PrintAndLogEx(NORMAL, "* AC path");
981
982 // 9F36: Application Transaction Counter (ATC)
983 const struct tlv *ATC = tlvdb_get(tlvRoot, 0x9F36, NULL);
984 if (ATC) {
985
986 // 9F10: Issuer Application Data - optional
987 const struct tlv *IAD = tlvdb_get(tlvRoot, 0x9F10, NULL);
988
989 // print AC data
990 PrintAndLogEx(NORMAL, "ATC: %s", sprint_hex(ATC->value, ATC->len));
991 PrintAndLogEx(NORMAL, "AC: %s", sprint_hex(AC->value, AC->len));
992 if (IAD){
993 PrintAndLogEx(NORMAL, "IAD: %s", sprint_hex(IAD->value, IAD->len));
994
995 if (IAD->len >= IAD->value[0] + 1) {
996 PrintAndLogEx(NORMAL, "\tKey index: 0x%02x", IAD->value[1]);
997 PrintAndLogEx(NORMAL, "\tCrypto ver: 0x%02x(%03d)", IAD->value[2], IAD->value[2]);
998 PrintAndLogEx(NORMAL, "\tCVR:", sprint_hex(&IAD->value[3], IAD->value[0] - 2));
999 struct tlvdb * cvr = tlvdb_fixed(0x20, IAD->value[0] - 2, &IAD->value[3]);
1000 TLVPrintFromTLVLev(cvr, 1);
1001 }
1002 } else {
1003 PrintAndLogEx(WARNING, "IAD not found.");
1004 }
1005
1006 } else {
1007 PrintAndLogEx(ERR, "AC: Application Transaction Counter (ATC) not found.");
1008 }
1009 }
1010 }
1011
1012 // Mastercard M/CHIP
1013 if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD && (TrType == TT_QVSDCMCHIP || TrType == TT_CDA)){
1014 const struct tlv *CDOL1 = tlvdb_get(tlvRoot, 0x8c, NULL);
1015 if (CDOL1 && GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) { // and m/chip transaction flag
1016 PrintAndLogEx(NORMAL, "\n--> Mastercard M/Chip transaction.");
1017
1018 PrintAndLogEx(NORMAL, "* * Generate challenge");
1019 res = EMVGenerateChallenge(channel, true, buf, sizeof(buf), &len, &sw, tlvRoot);
1020 if (res) {
1021 PrintAndLogEx(WARNING, "GetChallenge. APDU error %4x", sw);
1022 dreturn(6);
1023 }
1024 if (len < 4) {
1025 PrintAndLogEx(WARNING, "GetChallenge. Wrong challenge length %d", len);
1026 dreturn(6);
1027 }
1028
1029 // ICC Dynamic Number
1030 struct tlvdb * ICCDynN = tlvdb_fixed(0x9f4c, len, buf);
1031 tlvdb_add(tlvRoot, ICCDynN);
1032 if (decodeTLV){
1033 PrintAndLogEx(NORMAL, "\n* * ICC Dynamic Number:");
1034 TLVPrintFromTLV(ICCDynN);
1035 }
1036
1037 PrintAndLogEx(NORMAL, "* * Calc CDOL1");
1038 struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
1039 if (!cdol_data_tlv){
1040 PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV.");
1041 dreturn(6);
1042 }
1043 PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len));
1044
1045 PrintAndLogEx(NORMAL, "* * AC1");
1046 // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
1047 res = EMVAC(channel, true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
1048
1049 if (res) {
1050 PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw);
1051 dreturn(7);
1052 }
1053
1054 if (decodeTLV)
1055 TLVPrintFromBuffer(buf, len);
1056
1057 // CDA
1058 PrintAndLogEx(NORMAL, "\n* CDA:");
1059 struct tlvdb *ac_tlv = tlvdb_parse_multi(buf, len);
1060 res = trCDA(tlvRoot, ac_tlv, pdol_data_tlv, cdol_data_tlv);
1061 if (res) {
1062 PrintAndLogEx(NORMAL, "CDA error (%d)", res);
1063 }
1064 free(ac_tlv);
1065 free(cdol_data_tlv);
1066
1067 PrintAndLogEx(NORMAL, "\n* M/Chip transaction result:");
1068 // 9F27: Cryptogram Information Data (CID)
1069 const struct tlv *CID = tlvdb_get(tlvRoot, 0x9F27, NULL);
1070 if (CID) {
1071 emv_tag_dump(CID, stdout, 0);
1072 PrintAndLogEx(NORMAL, "------------------------------");
1073 if (CID->len > 0) {
1074 switch(CID->value[0] & EMVAC_AC_MASK){
1075 case EMVAC_AAC:
1076 PrintAndLogEx(NORMAL, "Transaction DECLINED.");
1077 break;
1078 case EMVAC_TC:
1079 PrintAndLogEx(NORMAL, "Transaction approved OFFLINE.");
1080 break;
1081 case EMVAC_ARQC:
1082 PrintAndLogEx(NORMAL, "Transaction approved ONLINE.");
1083 break;
1084 default:
1085 PrintAndLogEx(WARNING, "Error: CID transaction code error %2x", CID->value[0] & EMVAC_AC_MASK);
1086 break;
1087 }
1088 } else {
1089 PrintAndLogEx(WARNING, "Wrong CID length %d", CID->len);
1090 }
1091 } else {
1092 PrintAndLogEx(WARNING, "CID(9F27) not found.");
1093 }
1094
1095 }
1096 }
1097
1098 // MSD
1099 if (AIP & 0x8000 && TrType == TT_MSD) {
1100 PrintAndLogEx(NORMAL, "\n--> MSD transaction.");
1101
1102 PrintAndLogEx(NORMAL, "* MSD dCVV path. Check dCVV");
1103
1104 const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
1105 if (track2) {
1106 PrintAndLogEx(NORMAL, "Track2: %s", sprint_hex(track2->value, track2->len));
1107
1108 struct tlvdb *dCVV = GetdCVVRawFromTrack2(track2);
1109 PrintAndLogEx(NORMAL, "dCVV raw data:");
1110 TLVPrintFromTLV(dCVV);
1111
1112 if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) {
1113 PrintAndLogEx(NORMAL, "\n* Mastercard calculate UDOL");
1114
1115 // UDOL (9F69)
1116 const struct tlv *UDOL = tlvdb_get(tlvRoot, 0x9F69, NULL);
1117 // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
1118 const struct tlv defUDOL = {
1119 .tag = 0x01,
1120 .len = 3,
1121 .value = (uint8_t *)"\x9f\x6a\x04",
1122 };
1123 if (!UDOL)
1124 PrintAndLogEx(NORMAL, "Use default UDOL.");
1125
1126 struct tlv *udol_data_tlv = dol_process(UDOL ? UDOL : &defUDOL, tlvRoot, 0x01); // 0x01 - dummy tag
1127 if (!udol_data_tlv){
1128 PrintAndLogEx(WARNING, "can't create UDOL TLV.");
1129 dreturn(8);
1130 }
1131
1132 PrintAndLogEx(NORMAL, "UDOL data[%d]: %s", udol_data_tlv->len, sprint_hex(udol_data_tlv->value, udol_data_tlv->len));
1133
1134 PrintAndLogEx(NORMAL, "\n* Mastercard compute cryptographic checksum(UDOL)");
1135
1136 res = MSCComputeCryptoChecksum(channel, true, (uint8_t *)udol_data_tlv->value, udol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
1137 if (res) {
1138 PrintAndLogEx(WARNING, "Compute Crypto Checksum. APDU error %4x", sw);
1139 free(udol_data_tlv);
1140 dreturn(9);
1141 }
1142
1143 // Mastercard compute cryptographic checksum result
1144 TLVPrintFromBuffer(buf, len);
1145 PrintAndLogEx(NORMAL, "");
1146
1147 free(udol_data_tlv);
1148
1149 }
1150 } else {
1151 PrintAndLogEx(WARNING, "MSD: Track2 data not found.");
1152 }
1153 }
1154
1155 DropField();
1156
1157 // Destroy TLV's
1158 free(pdol_data_tlv);
1159 tlvdb_free(tlvSelect);
1160 tlvdb_free(tlvRoot);
1161
1162 PrintAndLogEx(NORMAL, "\n* Transaction completed.");
1163 return 0;
1164 }
1165
1166 int CmdEMVScan(const char *cmd) {
1167 uint8_t AID[APDU_AID_LEN] = {0};
1168 size_t AIDlen = 0;
1169 uint8_t buf[APDU_RES_LEN] = {0};
1170 size_t len = 0;
1171 uint16_t sw = 0;
1172 int res;
1173 json_t *root;
1174 json_error_t error;
1175
1176 CLIParserInit("emv scan",
1177 "Scan EMV card and save it contents to a file.",
1178 "It executes EMV contactless transaction and saves result to a file which can be used for emulation\n"
1179 "Usage:\n\temv scan -at -> scan MSD transaction mode and show APDU and TLV\n"
1180 "\temv scan -c -> scan CDA transaction mode\n");
1181
1182 void* argtable[] = {
1183 arg_param_begin,
1184 arg_lit0("aA", "apdu", "show APDU reqests and responses."),
1185 arg_lit0("tT", "tlv", "TLV decode results."),
1186 arg_lit0("eE", "extract", "Extract TLV elements and fill Application Data"),
1187 arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."),
1188 arg_rem("By default:", "Transaction type - MSD"),
1189 arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."),
1190 arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."),
1191 arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."),
1192 arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
1193 arg_lit0("mM", "merge", "Merge output file with card's data. (warning: the file may be corrupted!)"),
1194 #ifdef WITH_SMARTCARD
1195 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
1196 #endif
1197 arg_str1(NULL, NULL, "output.json", "JSON output file name"),
1198 arg_param_end
1199 };
1200 CLIExecWithReturn(cmd, argtable, true);
1201
1202 bool showAPDU = arg_get_lit(1);
1203 bool decodeTLV = arg_get_lit(2);
1204 bool extractTLVElements = arg_get_lit(3);
1205 bool paramLoadJSON = arg_get_lit(4);
1206
1207 enum TransactionType TrType = TT_MSD;
1208 if (arg_get_lit(6))
1209 TrType = TT_QVSDCMCHIP;
1210 if (arg_get_lit(7))
1211 TrType = TT_CDA;
1212 if (arg_get_lit(8))
1213 TrType = TT_VSDC;
1214
1215 bool GenACGPO = arg_get_lit(9);
1216 bool MergeJSON = arg_get_lit(10);
1217 EMVCommandChannel channel = ECC_CONTACTLESS;
1218 uint8_t relfname[250] = {0};
1219 char *crelfname = (char *)relfname;
1220 int relfnamelen = 0;
1221 #ifdef WITH_SMARTCARD
1222 if (arg_get_lit(11)) {
1223 channel = ECC_CONTACT;
1224 }
1225 CLIGetStrWithReturn(12, relfname, &relfnamelen);
1226 #else
1227 CLIGetStrWithReturn(11, relfname, &relfnamelen);
1228 #endif
1229 uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
1230 CLIParserFree();
1231
1232 SetAPDULogging(showAPDU);
1233
1234 // TODO
1235 if (channel == ECC_CONTACT) {
1236 PrintAndLogEx(ERR, "Do not use contact interface. Exit.");
1237 return 1;
1238 }
1239
1240 // current path + file name
1241 if (!strstr(crelfname, ".json"))
1242 strcat(crelfname, ".json");
1243 char fname[strlen(get_my_executable_directory()) + strlen(crelfname) + 1];
1244 strcpy(fname, get_my_executable_directory());
1245 strcat(fname, crelfname);
1246
1247 if (MergeJSON) {
1248 root = json_load_file(fname, 0, &error);
1249 if (!root) {
1250 PrintAndLogEx(ERR, "json error on line %d: %s", error.line, error.text);
1251 return 1;
1252 }
1253
1254 if (!json_is_object(root)) {
1255 PrintAndLogEx(ERR, "Invalid json format. root must be an object.");
1256 return 1;
1257 }
1258 } else {
1259 root = json_object();
1260 }
1261
1262 // drop field at start
1263 DropField();
1264
1265 // iso 14443 select
1266 PrintAndLogEx(NORMAL, "--> GET UID, ATS.");
1267
1268 iso14a_card_select_t card;
1269 if (Hf14443_4aGetCardData(&card)) {
1270 return 2;
1271 }
1272
1273 JsonSaveStr(root, "$.File.Created", "proxmark3 `emv scan`");
1274
1275 JsonSaveStr(root, "$.Card.Communication", "iso14443-4a");
1276 JsonSaveBufAsHex(root, "$.Card.UID", (uint8_t *)&card.uid, card.uidlen);
1277 JsonSaveHex(root, "$.Card.ATQA", card.atqa[0] + (card.atqa[1] << 2), 2);
1278 JsonSaveHex(root, "$.Card.SAK", card.sak, 0);
1279 JsonSaveBufAsHex(root, "$.Card.ATS", (uint8_t *)card.ats, card.ats_len);
1280
1281 // init applets list tree
1282 const char *al = "Applets list";
1283 struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
1284
1285 // EMV PPSE
1286 PrintAndLogEx(NORMAL, "--> PPSE.");
1287 res = EMVSelectPSE(channel, true, true, 2, buf, sizeof(buf), &len, &sw);
1288
1289 if (!res && sw == 0x9000){
1290 if (decodeTLV)
1291 TLVPrintFromBuffer(buf, len);
1292
1293 JsonSaveBufAsHex(root, "$.PPSE.AID", (uint8_t *)"2PAY.SYS.DDF01", 14);
1294
1295 struct tlvdb *fci = tlvdb_parse_multi(buf, len);
1296 if (extractTLVElements)
1297 JsonSaveTLVTree(root, root, "$.PPSE.FCITemplate", fci);
1298 else
1299 JsonSaveTLVTreeElm(root, "$.PPSE.FCITemplate", fci, true, true, false);
1300 JsonSaveTLVValue(root, "$.Application.KernelID", tlvdb_find_full(fci, 0x9f2a));
1301 tlvdb_free(fci);
1302 }
1303
1304 res = EMVSearchPSE(channel, false, true, psenum, decodeTLV, tlvSelect);
1305
1306 // check PPSE and select application id
1307 if (!res) {
1308 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1309 } else {
1310 // EMV SEARCH with AID list
1311 SetAPDULogging(false);
1312 PrintAndLogEx(NORMAL, "--> AID search.");
1313 if (EMVSearch(channel, false, true, decodeTLV, tlvSelect)) {
1314 PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit...");
1315 tlvdb_free(tlvSelect);
1316 DropField();
1317 return 3;
1318 }
1319
1320 // check search and select application id
1321 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1322 }
1323
1324 // EMV SELECT application
1325 SetAPDULogging(showAPDU);
1326 EMVSelectApplication(tlvSelect, AID, &AIDlen);
1327
1328 tlvdb_free(tlvSelect);
1329
1330 if (!AIDlen) {
1331 PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit...");
1332 DropField();
1333 return 4;
1334 }
1335
1336 JsonSaveBufAsHex(root, "$.Application.AID", AID, AIDlen);
1337
1338 // Init TLV tree
1339 const char *alr = "Root terminal TLV tree";
1340 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
1341
1342 // EMV SELECT applet
1343
1344 PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen));
1345 SetAPDULogging(showAPDU);
1346 res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
1347
1348 if (res) {
1349 PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res);
1350 tlvdb_free(tlvRoot);
1351 DropField();
1352 return 5;
1353 }
1354
1355 if (decodeTLV)
1356 TLVPrintFromBuffer(buf, len);
1357
1358 // save mode
1359 if (tlvdb_get(tlvRoot, 0x9f38, NULL)) {
1360 JsonSaveStr(root, "$.Application.Mode", TransactionTypeStr[TrType]);
1361 }
1362
1363 struct tlvdb *fci = tlvdb_parse_multi(buf, len);
1364 if (extractTLVElements)
1365 JsonSaveTLVTree(root, root, "$.Application.FCITemplate", fci);
1366 else
1367 JsonSaveTLVTreeElm(root, "$.Application.FCITemplate", fci, true, true, false);
1368 tlvdb_free(fci);
1369
1370 // create transaction parameters
1371 PrintAndLogEx(NORMAL, "-->Init transaction parameters.");
1372 InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO);
1373
1374 PrintAndLogEx(NORMAL, "-->Calc PDOL.");
1375 struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
1376 if (!pdol_data_tlv){
1377 PrintAndLogEx(ERR, "Can't create PDOL TLV.");
1378 tlvdb_free(tlvRoot);
1379 DropField();
1380 return 6;
1381 }
1382
1383 size_t pdol_data_tlv_data_len;
1384 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
1385 if (!pdol_data_tlv_data) {
1386 PrintAndLogEx(ERR, "Can't create PDOL data.");
1387 tlvdb_free(tlvRoot);
1388 DropField();
1389 return 6;
1390 }
1391 PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
1392
1393 PrintAndLogEx(INFO, "-->GPO.");
1394 res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
1395
1396 free(pdol_data_tlv_data);
1397 free(pdol_data_tlv);
1398
1399 if (res) {
1400 PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw);
1401 tlvdb_free(tlvRoot);
1402 DropField();
1403 return 7;
1404 }
1405 ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV);
1406
1407 struct tlvdb *gpofci = tlvdb_parse_multi(buf, len);
1408 if (extractTLVElements)
1409 JsonSaveTLVTree(root, root, "$.Application.GPO", gpofci);
1410 else
1411 JsonSaveTLVTreeElm(root, "$.Application.GPO", gpofci, true, true, false);
1412
1413 JsonSaveTLVValue(root, "$.ApplicationData.AIP", tlvdb_find_full(gpofci, 0x82));
1414 JsonSaveTLVValue(root, "$.ApplicationData.AFL", tlvdb_find_full(gpofci, 0x94));
1415
1416 tlvdb_free(gpofci);
1417
1418 PrintAndLogEx(INFO, "-->Read records from AFL.");
1419 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
1420
1421 while(AFL && AFL->len) {
1422 if (AFL->len % 4) {
1423 PrintAndLogEx(ERR, "Wrong AFL length: %d", AFL->len);
1424 break;
1425 }
1426
1427 json_t *sfijson = json_path_get(root, "$.Application.Records");
1428 if (!sfijson) {
1429 json_t *app = json_path_get(root, "$.Application");
1430 json_object_set_new(app, "Records", json_array());
1431
1432 sfijson = json_path_get(root, "$.Application.Records");
1433 }
1434 if (!json_is_array(sfijson)) {
1435 PrintAndLogEx(ERR, "Internal logic error. `$.Application.Records` is not an array.");
1436 break;
1437 }
1438 for (int i = 0; i < AFL->len / 4; i++) {
1439 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
1440 uint8_t SFIstart = AFL->value[i * 4 + 1];
1441 uint8_t SFIend = AFL->value[i * 4 + 2];
1442 uint8_t SFIoffline = AFL->value[i * 4 + 3];
1443
1444 PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
1445 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
1446 PrintAndLogEx(ERR, "SFI ERROR! Skipped...");
1447 continue;
1448 }
1449
1450 for(int n = SFIstart; n <= SFIend; n++) {
1451 PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n);
1452
1453 res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
1454 if (res) {
1455 PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw);
1456 continue;
1457 }
1458
1459 if (decodeTLV) {
1460 TLVPrintFromBuffer(buf, len);
1461 PrintAndLogEx(NORMAL, "");
1462 }
1463
1464 json_t *jsonelm = json_object();
1465 json_array_append_new(sfijson, jsonelm);
1466
1467 JsonSaveHex(jsonelm, "SFI", SFI, 1);
1468 JsonSaveHex(jsonelm, "RecordNum", n, 1);
1469 JsonSaveHex(jsonelm, "Offline", SFIoffline, 1);
1470
1471 struct tlvdb *rsfi = tlvdb_parse_multi(buf, len);
1472 if (extractTLVElements)
1473 JsonSaveTLVTree(root, jsonelm, "$.Data", rsfi);
1474 else
1475 JsonSaveTLVTreeElm(jsonelm, "$.Data", rsfi, true, true, false);
1476 tlvdb_free(rsfi);
1477 }
1478 }
1479
1480 break;
1481 }
1482
1483 // getting certificates
1484 if (tlvdb_get(tlvRoot, 0x90, NULL)) {
1485 PrintAndLogEx(INFO, "-->Recovering certificates.");
1486 PKISetStrictExecution(false);
1487 RecoveryCertificates(tlvRoot, root);
1488 PKISetStrictExecution(true);
1489 }
1490
1491 // free tlv object
1492 tlvdb_free(tlvRoot);
1493
1494 // DropField
1495 DropField();
1496
1497 res = json_dump_file(root, fname, JSON_INDENT(2));
1498 if (res) {
1499 PrintAndLogEx(ERR, "Can't save the file: %s", fname);
1500 return 200;
1501 }
1502 PrintAndLogEx(SUCCESS, "File `%s` saved.", fname);
1503
1504 // free json object
1505 json_decref(root);
1506
1507 return 0;
1508 }
1509
1510 int CmdEMVTest(const char *cmd) {
1511 return ExecuteCryptoTests(true);
1512 }
1513
1514 int CmdEMVRoca(const char *cmd) {
1515 uint8_t AID[APDU_AID_LEN] = {0};
1516 size_t AIDlen = 0;
1517 uint8_t buf[APDU_RES_LEN] = {0};
1518 size_t len = 0;
1519 uint16_t sw = 0;
1520 int res;
1521
1522 CLIParserInit("emv roca",
1523 "Tries to extract public keys and run the ROCA test against them.\n",
1524 "Usage:\n"
1525 "\temv roca -w -> select CONTACT card and run test\n\temv roca -> select CONTACTLESS card and run test\n");
1526
1527 void* argtable[] = {
1528 arg_param_begin,
1529 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
1530 arg_param_end
1531 };
1532 CLIExecWithReturn(cmd, argtable, true);
1533
1534 EMVCommandChannel channel = ECC_CONTACTLESS;
1535 if (arg_get_lit(1))
1536 channel = ECC_CONTACT;
1537
1538 // select card
1539 uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
1540
1541 SetAPDULogging(false);
1542
1543 // init applets list tree
1544 const char *al = "Applets list";
1545 struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
1546
1547 // EMV PPSE
1548 PrintAndLogEx(NORMAL, "--> PPSE.");
1549 res = EMVSearchPSE(channel, false, true, psenum, false, tlvSelect);
1550
1551 // check PPSE and select application id
1552 if (!res) {
1553 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1554 } else {
1555 // EMV SEARCH with AID list
1556 PrintAndLogEx(NORMAL, "--> AID search.");
1557 if (EMVSearch(channel, false, true, false, tlvSelect)) {
1558 PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit...");
1559 tlvdb_free(tlvSelect);
1560 DropField();
1561 return 3;
1562 }
1563
1564 // check search and select application id
1565 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1566 }
1567
1568 // EMV SELECT application
1569 SetAPDULogging(false);
1570 EMVSelectApplication(tlvSelect, AID, &AIDlen);
1571
1572 tlvdb_free(tlvSelect);
1573
1574 if (!AIDlen) {
1575 PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit...");
1576 DropField();
1577 return 4;
1578 }
1579
1580 // Init TLV tree
1581 const char *alr = "Root terminal TLV tree";
1582 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
1583
1584 // EMV SELECT applet
1585 PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen));
1586 res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
1587
1588 if (res) {
1589 PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res);
1590 tlvdb_free(tlvRoot);
1591 DropField();
1592 return 5;
1593 }
1594
1595 PrintAndLog("\n* Init transaction parameters.");
1596 InitTransactionParameters(tlvRoot, true, TT_QVSDCMCHIP, false);
1597
1598 PrintAndLogEx(NORMAL, "-->Calc PDOL.");
1599 struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
1600 if (!pdol_data_tlv){
1601 PrintAndLogEx(ERR, "Can't create PDOL TLV.");
1602 tlvdb_free(tlvRoot);
1603 DropField();
1604 return 6;
1605 }
1606
1607 size_t pdol_data_tlv_data_len;
1608 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
1609 if (!pdol_data_tlv_data) {
1610 PrintAndLogEx(ERR, "Can't create PDOL data.");
1611 tlvdb_free(tlvRoot);
1612 DropField();
1613 return 6;
1614 }
1615 PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
1616
1617 PrintAndLogEx(INFO, "-->GPO.");
1618 res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
1619
1620 free(pdol_data_tlv_data);
1621 free(pdol_data_tlv);
1622
1623 if (res) {
1624 PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw);
1625 tlvdb_free(tlvRoot);
1626 DropField();
1627 return 7;
1628 }
1629 ProcessGPOResponseFormat1(tlvRoot, buf, len, false);
1630
1631 PrintAndLogEx(INFO, "-->Read records from AFL.");
1632 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
1633
1634 while(AFL && AFL->len) {
1635 if (AFL->len % 4) {
1636 PrintAndLogEx(ERR, "Wrong AFL length: %d", AFL->len);
1637 break;
1638 }
1639
1640 for (int i = 0; i < AFL->len / 4; i++) {
1641 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
1642 uint8_t SFIstart = AFL->value[i * 4 + 1];
1643 uint8_t SFIend = AFL->value[i * 4 + 2];
1644 uint8_t SFIoffline = AFL->value[i * 4 + 3];
1645
1646 PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
1647 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
1648 PrintAndLogEx(ERR, "SFI ERROR! Skipped...");
1649 continue;
1650 }
1651
1652 for(int n = SFIstart; n <= SFIend; n++) {
1653 PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n);
1654
1655 res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
1656 if (res) {
1657 PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw);
1658 continue;
1659 }
1660 }
1661 }
1662
1663 break;
1664 }
1665
1666 // getting certificates
1667 if (tlvdb_get(tlvRoot, 0x90, NULL)) {
1668 PrintAndLogEx(INFO, "-->Recovering certificates.");
1669 PKISetStrictExecution(false);
1670
1671 struct emv_pk *pk = get_ca_pk(tlvRoot);
1672 if (!pk) {
1673 PrintAndLogEx(ERR, "ERROR: Key not found. Exit.");
1674 goto out;
1675 }
1676
1677 struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlvRoot);
1678 if (!issuer_pk) {
1679 emv_pk_free(pk);
1680 PrintAndLogEx(WARNING, "WARNING: Issuer certificate not found. Exit.");
1681 goto out;
1682 }
1683
1684 PrintAndLogEx(SUCCESS, "Issuer PK recovered. RID %s IDX %02hhx CSN %s",
1685 sprint_hex(issuer_pk->rid, 5),
1686 issuer_pk->index,
1687 sprint_hex(issuer_pk->serial, 3)
1688 );
1689
1690
1691 struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlvRoot, NULL);
1692 if (!icc_pk) {
1693 emv_pk_free(pk);
1694 emv_pk_free(issuer_pk);
1695 PrintAndLogEx(WARNING, "WARNING: ICC certificate not found. Exit.");
1696 goto out;
1697 }
1698 PrintAndLogEx(SUCCESS, "ICC PK recovered. RID %s IDX %02hhx CSN %s\n",
1699 sprint_hex(icc_pk->rid, 5),
1700 icc_pk->index,
1701 sprint_hex(icc_pk->serial, 3)
1702 );
1703
1704 PrintAndLogEx(INFO, "ICC pk modulus: %s", sprint_hex_inrow(icc_pk->modulus, icc_pk->mlen));
1705
1706 // icc_pk->exp, icc_pk->elen
1707 // icc_pk->modulus, icc_pk->mlen
1708 if (icc_pk->elen > 0 && icc_pk->mlen > 0) {
1709 if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen, true)) {
1710 PrintAndLogEx(INFO, "ICC pk is a subject to ROCA vulnerability, insecure..");
1711 } else {
1712 PrintAndLogEx(INFO, "ICC pk is OK(");
1713 }
1714 }
1715
1716 PKISetStrictExecution(true);
1717 }
1718
1719 out:
1720
1721 // free tlv object
1722 tlvdb_free(tlvRoot);
1723
1724 if ( channel == ECC_CONTACTLESS)
1725 DropField();
1726
1727
1728 return 0;
1729 }
1730
1731 int CmdHelp(const char *Cmd);
1732
1733 static command_t CommandTable[] = {
1734 {"help", CmdHelp, 1, "This help"},
1735 {"exec", CmdEMVExec, 0, "Executes EMV contactless transaction."},
1736 {"pse", CmdEMVPPSE, 0, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."},
1737 {"search", CmdEMVSearch, 0, "Try to select all applets from applets list and print installed applets."},
1738 {"select", CmdEMVSelect, 0, "Select applet."},
1739 {"gpo", CmdEMVGPO, 0, "Execute GetProcessingOptions."},
1740 {"readrec", CmdEMVReadRecord, 0, "Read files from card."},
1741 {"genac", CmdEMVAC, 0, "Generate ApplicationCryptogram."},
1742 {"challenge", CmdEMVGenerateChallenge, 0, "Generate challenge."},
1743 {"intauth", CmdEMVInternalAuthenticate, 0, "Internal authentication."},
1744 {"scan", CmdEMVScan, 0, "Scan EMV card and save it contents to json file for emulator."},
1745 {"test", CmdEMVTest, 0, "Crypto logic test."},
1746 {"roca", CmdEMVRoca, 0, "Extract public keys and run ROCA test"},
1747 {NULL, NULL, 0, NULL}
1748 };
1749
1750 int CmdEMV(const char *Cmd) {
1751 CmdsParse(CommandTable, Cmd);
1752 return 0;
1753 }
1754
1755 int CmdHelp(const char *Cmd) {
1756 CmdsHelp(CommandTable);
1757 return 0;
1758 }
Impressum, Datenschutz