Adding support for standard USB Smartcard Readers (#769)
[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_DATA_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_RESPONSE_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_RESPONSE_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_RESPONSE_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_RESPONSE_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_RESPONSE_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_RESPONSE_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_RESPONSE_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_RESPONSE_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_RESPONSE_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_RESPONSE_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_RESPONSE_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_RESPONSE_LEN] = {0};
715 size_t len = 0;
716 uint16_t sw = 0;
717 uint8_t AID[APDU_DATA_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 char *PSE_or_PPSE = psenum == 1 ? "PSE" : "PPSE";
773
774 CLIParserFree();
775
776 SetAPDULogging(showAPDU);
777
778 // init applets list tree
779 const char *al = "Applets list";
780 tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
781
782 // Application Selection
783 // https://www.openscdp.org/scripts/tutorial/emv/applicationselection.html
784 if (!forceSearch) {
785 // PPSE / PSE
786 PrintAndLogEx(NORMAL, "\n* %s.", PSE_or_PPSE);
787 SetAPDULogging(showAPDU);
788 res = EMVSearchPSE(channel, activateField, true, psenum, decodeTLV, tlvSelect);
789
790 // check PPSE / PSE and select application id
791 if (!res) {
792 TLVPrintAIDlistFromSelectTLV(tlvSelect);
793 EMVSelectApplication(tlvSelect, AID, &AIDlen);
794 }
795 }
796
797 // Search
798 if (!AIDlen) {
799 PrintAndLogEx(NORMAL, "\n* Search AID in list.");
800 SetAPDULogging(false);
801 if (EMVSearch(channel, activateField, true, decodeTLV, tlvSelect)) {
802 dreturn(2);
803 }
804
805 // check search and select application id
806 TLVPrintAIDlistFromSelectTLV(tlvSelect);
807 EMVSelectApplication(tlvSelect, AID, &AIDlen);
808 }
809
810 // Init TLV tree
811 const char *alr = "Root terminal TLV tree";
812 tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
813
814 // check if we found EMV application on card
815 if (!AIDlen) {
816 PrintAndLogEx(WARNING, "Can't select AID. EMV AID not found");
817 dreturn(2);
818 }
819
820 // Select
821 PrintAndLogEx(NORMAL, "\n* Selecting AID:%s", sprint_hex_inrow(AID, AIDlen));
822 SetAPDULogging(showAPDU);
823 res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
824
825 if (res) {
826 PrintAndLogEx(WARNING, "Can't select AID (%d). Exit...", res);
827 dreturn(3);
828 }
829
830 if (decodeTLV)
831 TLVPrintFromBuffer(buf, len);
832 PrintAndLogEx(INFO, "* Selected.");
833
834 PrintAndLogEx(INFO, "\n* Init transaction parameters.");
835 InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO);
836 TLVPrintFromTLV(tlvRoot); // TODO delete!!!
837
838 PrintAndLogEx(NORMAL, "\n* Calc PDOL.");
839 pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
840 if (!pdol_data_tlv){
841 PrintAndLogEx(WARNING, "Error: can't create PDOL TLV.");
842 dreturn(4);
843 }
844
845 size_t pdol_data_tlv_data_len;
846 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
847 if (!pdol_data_tlv_data) {
848 PrintAndLogEx(WARNING, "Error: can't create PDOL data.");
849 dreturn(4);
850 }
851 PrintAndLogEx(NORMAL, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
852
853 PrintAndLogEx(NORMAL, "\n* GPO.");
854 res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
855
856 free(pdol_data_tlv_data);
857 //free(pdol_data_tlv); --- free on exit.
858
859 if (res) {
860 PrintAndLogEx(NORMAL, "GPO error(%d): %4x. Exit...", res, sw);
861 dreturn(5);
862 }
863
864 // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
865 ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV);
866
867 // extract PAN from track2
868 {
869 const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
870 if (!tlvdb_get(tlvRoot, 0x5a, NULL) && track2 && track2->len >= 8) {
871 struct tlvdb *pan = GetPANFromTrack2(track2);
872 if (pan) {
873 tlvdb_add(tlvRoot, pan);
874
875 const struct tlv *pantlv = tlvdb_get(tlvRoot, 0x5a, NULL);
876 PrintAndLogEx(NORMAL, "\n* * Extracted PAN from track2: %s", sprint_hex(pantlv->value, pantlv->len));
877 } else {
878 PrintAndLogEx(NORMAL, "\n* * WARNING: Can't extract PAN from track2.");
879 }
880 }
881 }
882
883 PrintAndLogEx(NORMAL, "\n* Read records from AFL.");
884 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
885 if (!AFL || !AFL->len) {
886 PrintAndLogEx(WARNING, "AFL not found.");
887 }
888
889 while(AFL && AFL->len) {
890 if (AFL->len % 4) {
891 PrintAndLogEx(WARNING, "Error: Wrong AFL length: %d", AFL->len);
892 break;
893 }
894
895 for (int i = 0; i < AFL->len / 4; i++) {
896 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
897 uint8_t SFIstart = AFL->value[i * 4 + 1];
898 uint8_t SFIend = AFL->value[i * 4 + 2];
899 uint8_t SFIoffline = AFL->value[i * 4 + 3];
900
901 PrintAndLogEx(NORMAL, "* * SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
902 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
903 PrintAndLogEx(NORMAL, "SFI ERROR! Skipped...");
904 continue;
905 }
906
907 for(int n = SFIstart; n <= SFIend; n++) {
908 PrintAndLogEx(NORMAL, "* * * SFI[%02x] %d", SFI, n);
909
910 res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
911 if (res) {
912 PrintAndLogEx(WARNING, "Error SFI[%02x]. APDU error %4x", SFI, sw);
913 continue;
914 }
915
916 if (decodeTLV) {
917 TLVPrintFromBuffer(buf, len);
918 PrintAndLogEx(NORMAL, "");
919 }
920
921 // Build Input list for Offline Data Authentication
922 // EMV 4.3 book3 10.3, page 96
923 if (SFIoffline) {
924 if (SFI < 11) {
925 const unsigned char *abuf = buf;
926 size_t elmlen = len;
927 struct tlv e;
928 if (tlv_parse_tl(&abuf, &elmlen, &e)) {
929 memcpy(&ODAiList[ODAiListLen], &buf[len - elmlen], elmlen);
930 ODAiListLen += elmlen;
931 } else {
932 PrintAndLogEx(WARNING, "Error SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI);
933 }
934 } else {
935 memcpy(&ODAiList[ODAiListLen], buf, len);
936 ODAiListLen += len;
937 }
938 }
939 }
940 }
941
942 break;
943 }
944
945 // copy Input list for Offline Data Authentication
946 if (ODAiListLen) {
947 struct tlvdb *oda = tlvdb_fixed(0x21, ODAiListLen, ODAiList); // not a standard tag
948 tlvdb_add(tlvRoot, oda);
949 PrintAndLogEx(NORMAL, "* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen);
950 }
951
952 // get AIP
953 uint16_t AIP = 0;
954 const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL);
955 if (AIPtlv) {
956 AIP = AIPtlv->value[0] + AIPtlv->value[1] * 0x100;
957 PrintAndLogEx(NORMAL, "* * AIP=%04x", AIP);
958 } else {
959 PrintAndLogEx(ERR, "Can't found AIP.");
960 }
961
962 // SDA
963 if (AIP & 0x0040) {
964 PrintAndLogEx(NORMAL, "\n* SDA");
965 trSDA(tlvRoot);
966 }
967
968 // DDA
969 if (AIP & 0x0020) {
970 PrintAndLogEx(NORMAL, "\n* DDA");
971 trDDA(channel, decodeTLV, tlvRoot);
972 }
973
974 // transaction check
975
976 // qVSDC
977 if (TrType == TT_QVSDCMCHIP|| TrType == TT_CDA){
978 // 9F26: Application Cryptogram
979 const struct tlv *AC = tlvdb_get(tlvRoot, 0x9F26, NULL);
980 if (AC) {
981 PrintAndLogEx(NORMAL, "\n--> qVSDC transaction.");
982 PrintAndLogEx(NORMAL, "* AC path");
983
984 // 9F36: Application Transaction Counter (ATC)
985 const struct tlv *ATC = tlvdb_get(tlvRoot, 0x9F36, NULL);
986 if (ATC) {
987
988 // 9F10: Issuer Application Data - optional
989 const struct tlv *IAD = tlvdb_get(tlvRoot, 0x9F10, NULL);
990
991 // print AC data
992 PrintAndLogEx(NORMAL, "ATC: %s", sprint_hex(ATC->value, ATC->len));
993 PrintAndLogEx(NORMAL, "AC: %s", sprint_hex(AC->value, AC->len));
994 if (IAD){
995 PrintAndLogEx(NORMAL, "IAD: %s", sprint_hex(IAD->value, IAD->len));
996
997 if (IAD->len >= IAD->value[0] + 1) {
998 PrintAndLogEx(NORMAL, "\tKey index: 0x%02x", IAD->value[1]);
999 PrintAndLogEx(NORMAL, "\tCrypto ver: 0x%02x(%03d)", IAD->value[2], IAD->value[2]);
1000 PrintAndLogEx(NORMAL, "\tCVR:", sprint_hex(&IAD->value[3], IAD->value[0] - 2));
1001 struct tlvdb * cvr = tlvdb_fixed(0x20, IAD->value[0] - 2, &IAD->value[3]);
1002 TLVPrintFromTLVLev(cvr, 1);
1003 }
1004 } else {
1005 PrintAndLogEx(WARNING, "IAD not found.");
1006 }
1007
1008 } else {
1009 PrintAndLogEx(ERR, "AC: Application Transaction Counter (ATC) not found.");
1010 }
1011 }
1012 }
1013
1014 // Mastercard M/CHIP
1015 if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD && (TrType == TT_QVSDCMCHIP || TrType == TT_CDA)){
1016 const struct tlv *CDOL1 = tlvdb_get(tlvRoot, 0x8c, NULL);
1017 if (CDOL1 && GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) { // and m/chip transaction flag
1018 PrintAndLogEx(NORMAL, "\n--> Mastercard M/Chip transaction.");
1019
1020 PrintAndLogEx(NORMAL, "* * Generate challenge");
1021 res = EMVGenerateChallenge(channel, true, buf, sizeof(buf), &len, &sw, tlvRoot);
1022 if (res) {
1023 PrintAndLogEx(WARNING, "GetChallenge. APDU error %4x", sw);
1024 dreturn(6);
1025 }
1026 if (len < 4) {
1027 PrintAndLogEx(WARNING, "GetChallenge. Wrong challenge length %d", len);
1028 dreturn(6);
1029 }
1030
1031 // ICC Dynamic Number
1032 struct tlvdb * ICCDynN = tlvdb_fixed(0x9f4c, len, buf);
1033 tlvdb_add(tlvRoot, ICCDynN);
1034 if (decodeTLV){
1035 PrintAndLogEx(NORMAL, "\n* * ICC Dynamic Number:");
1036 TLVPrintFromTLV(ICCDynN);
1037 }
1038
1039 PrintAndLogEx(NORMAL, "* * Calc CDOL1");
1040 struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
1041 if (!cdol_data_tlv){
1042 PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV.");
1043 dreturn(6);
1044 }
1045 PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len));
1046
1047 PrintAndLogEx(NORMAL, "* * AC1");
1048 // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
1049 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);
1050
1051 if (res) {
1052 PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw);
1053 dreturn(7);
1054 }
1055
1056 if (decodeTLV)
1057 TLVPrintFromBuffer(buf, len);
1058
1059 // CDA
1060 PrintAndLogEx(NORMAL, "\n* CDA:");
1061 struct tlvdb *ac_tlv = tlvdb_parse_multi(buf, len);
1062 res = trCDA(tlvRoot, ac_tlv, pdol_data_tlv, cdol_data_tlv);
1063 if (res) {
1064 PrintAndLogEx(NORMAL, "CDA error (%d)", res);
1065 }
1066 free(ac_tlv);
1067 free(cdol_data_tlv);
1068
1069 PrintAndLogEx(NORMAL, "\n* M/Chip transaction result:");
1070 // 9F27: Cryptogram Information Data (CID)
1071 const struct tlv *CID = tlvdb_get(tlvRoot, 0x9F27, NULL);
1072 if (CID) {
1073 emv_tag_dump(CID, stdout, 0);
1074 PrintAndLogEx(NORMAL, "------------------------------");
1075 if (CID->len > 0) {
1076 switch(CID->value[0] & EMVAC_AC_MASK){
1077 case EMVAC_AAC:
1078 PrintAndLogEx(NORMAL, "Transaction DECLINED.");
1079 break;
1080 case EMVAC_TC:
1081 PrintAndLogEx(NORMAL, "Transaction approved OFFLINE.");
1082 break;
1083 case EMVAC_ARQC:
1084 PrintAndLogEx(NORMAL, "Transaction approved ONLINE.");
1085 break;
1086 default:
1087 PrintAndLogEx(WARNING, "Error: CID transaction code error %2x", CID->value[0] & EMVAC_AC_MASK);
1088 break;
1089 }
1090 } else {
1091 PrintAndLogEx(WARNING, "Wrong CID length %d", CID->len);
1092 }
1093 } else {
1094 PrintAndLogEx(WARNING, "CID(9F27) not found.");
1095 }
1096
1097 }
1098 }
1099
1100 // MSD
1101 if (AIP & 0x8000 && TrType == TT_MSD) {
1102 PrintAndLogEx(NORMAL, "\n--> MSD transaction.");
1103
1104 PrintAndLogEx(NORMAL, "* MSD dCVV path. Check dCVV");
1105
1106 const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
1107 if (track2) {
1108 PrintAndLogEx(NORMAL, "Track2: %s", sprint_hex(track2->value, track2->len));
1109
1110 struct tlvdb *dCVV = GetdCVVRawFromTrack2(track2);
1111 PrintAndLogEx(NORMAL, "dCVV raw data:");
1112 TLVPrintFromTLV(dCVV);
1113
1114 if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) {
1115 PrintAndLogEx(NORMAL, "\n* Mastercard calculate UDOL");
1116
1117 // UDOL (9F69)
1118 const struct tlv *UDOL = tlvdb_get(tlvRoot, 0x9F69, NULL);
1119 // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
1120 const struct tlv defUDOL = {
1121 .tag = 0x01,
1122 .len = 3,
1123 .value = (uint8_t *)"\x9f\x6a\x04",
1124 };
1125 if (!UDOL)
1126 PrintAndLogEx(NORMAL, "Use default UDOL.");
1127
1128 struct tlv *udol_data_tlv = dol_process(UDOL ? UDOL : &defUDOL, tlvRoot, 0x01); // 0x01 - dummy tag
1129 if (!udol_data_tlv){
1130 PrintAndLogEx(WARNING, "can't create UDOL TLV.");
1131 dreturn(8);
1132 }
1133
1134 PrintAndLogEx(NORMAL, "UDOL data[%d]: %s", udol_data_tlv->len, sprint_hex(udol_data_tlv->value, udol_data_tlv->len));
1135
1136 PrintAndLogEx(NORMAL, "\n* Mastercard compute cryptographic checksum(UDOL)");
1137
1138 res = MSCComputeCryptoChecksum(channel, true, (uint8_t *)udol_data_tlv->value, udol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
1139 if (res) {
1140 PrintAndLogEx(WARNING, "Compute Crypto Checksum. APDU error %4x", sw);
1141 free(udol_data_tlv);
1142 dreturn(9);
1143 }
1144
1145 // Mastercard compute cryptographic checksum result
1146 TLVPrintFromBuffer(buf, len);
1147 PrintAndLogEx(NORMAL, "");
1148
1149 free(udol_data_tlv);
1150
1151 }
1152 } else {
1153 PrintAndLogEx(WARNING, "MSD: Track2 data not found.");
1154 }
1155 }
1156
1157 if (channel == ECC_CONTACTLESS) {
1158 DropField();
1159 }
1160
1161 // Destroy TLV's
1162 free(pdol_data_tlv);
1163 tlvdb_free(tlvSelect);
1164 tlvdb_free(tlvRoot);
1165
1166 PrintAndLogEx(NORMAL, "\n* Transaction completed.");
1167 return 0;
1168 }
1169
1170 int CmdEMVScan(const char *cmd) {
1171 uint8_t AID[APDU_DATA_LEN] = {0};
1172 size_t AIDlen = 0;
1173 uint8_t buf[APDU_RESPONSE_LEN] = {0};
1174 size_t len = 0;
1175 uint16_t sw = 0;
1176 int res;
1177 json_t *root;
1178 json_error_t error;
1179
1180 CLIParserInit("emv scan",
1181 "Scan EMV card and save it contents to a file.",
1182 "It executes EMV contactless transaction and saves result to a file which can be used for emulation\n"
1183 "Usage:\n\temv scan -at -> scan MSD transaction mode and show APDU and TLV\n"
1184 "\temv scan -c -> scan CDA transaction mode\n");
1185
1186 void* argtable[] = {
1187 arg_param_begin,
1188 arg_lit0("aA", "apdu", "show APDU reqests and responses."),
1189 arg_lit0("tT", "tlv", "TLV decode results."),
1190 arg_lit0("eE", "extract", "Extract TLV elements and fill Application Data"),
1191 arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."),
1192 arg_rem("By default:", "Transaction type - MSD"),
1193 arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."),
1194 arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."),
1195 arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."),
1196 arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
1197 arg_lit0("mM", "merge", "Merge output file with card's data. (warning: the file may be corrupted!)"),
1198 #ifdef WITH_SMARTCARD
1199 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
1200 #endif
1201 arg_str1(NULL, NULL, "output.json", "JSON output file name"),
1202 arg_param_end
1203 };
1204 CLIExecWithReturn(cmd, argtable, true);
1205
1206 bool showAPDU = arg_get_lit(1);
1207 bool decodeTLV = arg_get_lit(2);
1208 bool extractTLVElements = arg_get_lit(3);
1209 bool paramLoadJSON = arg_get_lit(4);
1210
1211 enum TransactionType TrType = TT_MSD;
1212 if (arg_get_lit(6))
1213 TrType = TT_QVSDCMCHIP;
1214 if (arg_get_lit(7))
1215 TrType = TT_CDA;
1216 if (arg_get_lit(8))
1217 TrType = TT_VSDC;
1218
1219 bool GenACGPO = arg_get_lit(9);
1220 bool MergeJSON = arg_get_lit(10);
1221 EMVCommandChannel channel = ECC_CONTACTLESS;
1222 uint8_t relfname[250] = {0};
1223 char *crelfname = (char *)relfname;
1224 int relfnamelen = 0;
1225 #ifdef WITH_SMARTCARD
1226 if (arg_get_lit(11)) {
1227 channel = ECC_CONTACT;
1228 }
1229 CLIGetStrWithReturn(12, relfname, &relfnamelen);
1230 #else
1231 CLIGetStrWithReturn(11, relfname, &relfnamelen);
1232 #endif
1233 uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
1234 CLIParserFree();
1235
1236 SetAPDULogging(showAPDU);
1237
1238 // TODO
1239 if (channel == ECC_CONTACT) {
1240 PrintAndLogEx(ERR, "Do not use contact interface. Exit.");
1241 return 1;
1242 }
1243
1244 // current path + file name
1245 if (!strstr(crelfname, ".json"))
1246 strcat(crelfname, ".json");
1247 char fname[strlen(get_my_executable_directory()) + strlen(crelfname) + 1];
1248 strcpy(fname, get_my_executable_directory());
1249 strcat(fname, crelfname);
1250
1251 if (MergeJSON) {
1252 root = json_load_file(fname, 0, &error);
1253 if (!root) {
1254 PrintAndLogEx(ERR, "json error on line %d: %s", error.line, error.text);
1255 return 1;
1256 }
1257
1258 if (!json_is_object(root)) {
1259 PrintAndLogEx(ERR, "Invalid json format. root must be an object.");
1260 return 1;
1261 }
1262 } else {
1263 root = json_object();
1264 }
1265
1266 // drop field at start
1267 if (channel == ECC_CONTACTLESS) {
1268 DropField();
1269 }
1270
1271 // iso 14443 select
1272 PrintAndLogEx(NORMAL, "--> GET UID, ATS.");
1273
1274 iso14a_card_select_t card;
1275 if (Hf14443_4aGetCardData(&card)) {
1276 return 2;
1277 }
1278
1279 JsonSaveStr(root, "$.File.Created", "proxmark3 `emv scan`");
1280
1281 JsonSaveStr(root, "$.Card.Communication", "iso14443-4a");
1282 JsonSaveBufAsHex(root, "$.Card.UID", (uint8_t *)&card.uid, card.uidlen);
1283 JsonSaveHex(root, "$.Card.ATQA", card.atqa[0] + (card.atqa[1] << 2), 2);
1284 JsonSaveHex(root, "$.Card.SAK", card.sak, 0);
1285 JsonSaveBufAsHex(root, "$.Card.ATS", (uint8_t *)card.ats, card.ats_len);
1286
1287 // init applets list tree
1288 const char *al = "Applets list";
1289 struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
1290
1291 // EMV PPSE
1292 PrintAndLogEx(NORMAL, "--> PPSE.");
1293 res = EMVSelectPSE(channel, true, true, 2, buf, sizeof(buf), &len, &sw);
1294
1295 if (!res && sw == 0x9000){
1296 if (decodeTLV)
1297 TLVPrintFromBuffer(buf, len);
1298
1299 JsonSaveBufAsHex(root, "$.PPSE.AID", (uint8_t *)"2PAY.SYS.DDF01", 14);
1300
1301 struct tlvdb *fci = tlvdb_parse_multi(buf, len);
1302 if (extractTLVElements)
1303 JsonSaveTLVTree(root, root, "$.PPSE.FCITemplate", fci);
1304 else
1305 JsonSaveTLVTreeElm(root, "$.PPSE.FCITemplate", fci, true, true, false);
1306 JsonSaveTLVValue(root, "$.Application.KernelID", tlvdb_find_full(fci, 0x9f2a));
1307 tlvdb_free(fci);
1308 }
1309
1310 res = EMVSearchPSE(channel, false, true, psenum, decodeTLV, tlvSelect);
1311
1312 // check PPSE and select application id
1313 if (!res) {
1314 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1315 } else {
1316 // EMV SEARCH with AID list
1317 SetAPDULogging(false);
1318 PrintAndLogEx(NORMAL, "--> AID search.");
1319 if (EMVSearch(channel, false, true, decodeTLV, tlvSelect)) {
1320 PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit...");
1321 tlvdb_free(tlvSelect);
1322 DropField();
1323 return 3;
1324 }
1325
1326 // check search and select application id
1327 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1328 }
1329
1330 // EMV SELECT application
1331 SetAPDULogging(showAPDU);
1332 EMVSelectApplication(tlvSelect, AID, &AIDlen);
1333
1334 tlvdb_free(tlvSelect);
1335
1336 if (!AIDlen) {
1337 PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit...");
1338 if (channel == ECC_CONTACTLESS) {
1339 DropField();
1340 }
1341 return 4;
1342 }
1343
1344 JsonSaveBufAsHex(root, "$.Application.AID", AID, AIDlen);
1345
1346 // Init TLV tree
1347 const char *alr = "Root terminal TLV tree";
1348 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
1349
1350 // EMV SELECT applet
1351
1352 PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen));
1353 SetAPDULogging(showAPDU);
1354 res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
1355
1356 if (res) {
1357 PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res);
1358 tlvdb_free(tlvRoot);
1359 DropField();
1360 return 5;
1361 }
1362
1363 if (decodeTLV)
1364 TLVPrintFromBuffer(buf, len);
1365
1366 // save mode
1367 if (tlvdb_get(tlvRoot, 0x9f38, NULL)) {
1368 JsonSaveStr(root, "$.Application.Mode", TransactionTypeStr[TrType]);
1369 }
1370
1371 struct tlvdb *fci = tlvdb_parse_multi(buf, len);
1372 if (extractTLVElements)
1373 JsonSaveTLVTree(root, root, "$.Application.FCITemplate", fci);
1374 else
1375 JsonSaveTLVTreeElm(root, "$.Application.FCITemplate", fci, true, true, false);
1376 tlvdb_free(fci);
1377
1378 // create transaction parameters
1379 PrintAndLogEx(NORMAL, "-->Init transaction parameters.");
1380 InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO);
1381
1382 PrintAndLogEx(NORMAL, "-->Calc PDOL.");
1383 struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
1384 if (!pdol_data_tlv){
1385 PrintAndLogEx(ERR, "Can't create PDOL TLV.");
1386 tlvdb_free(tlvRoot);
1387 if (channel == ECC_CONTACTLESS) {
1388 DropField();
1389 }
1390 return 6;
1391 }
1392
1393 size_t pdol_data_tlv_data_len;
1394 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
1395 if (!pdol_data_tlv_data) {
1396 PrintAndLogEx(ERR, "Can't create PDOL data.");
1397 tlvdb_free(tlvRoot);
1398 DropField();
1399 return 6;
1400 }
1401 PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
1402
1403 PrintAndLogEx(INFO, "-->GPO.");
1404 res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
1405
1406 free(pdol_data_tlv_data);
1407 free(pdol_data_tlv);
1408
1409 if (res) {
1410 PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw);
1411 tlvdb_free(tlvRoot);
1412 if (channel == ECC_CONTACTLESS) {
1413 DropField();
1414 }
1415 return 7;
1416 }
1417 ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV);
1418
1419 struct tlvdb *gpofci = tlvdb_parse_multi(buf, len);
1420 if (extractTLVElements)
1421 JsonSaveTLVTree(root, root, "$.Application.GPO", gpofci);
1422 else
1423 JsonSaveTLVTreeElm(root, "$.Application.GPO", gpofci, true, true, false);
1424
1425 JsonSaveTLVValue(root, "$.ApplicationData.AIP", tlvdb_find_full(gpofci, 0x82));
1426 JsonSaveTLVValue(root, "$.ApplicationData.AFL", tlvdb_find_full(gpofci, 0x94));
1427
1428 tlvdb_free(gpofci);
1429
1430 PrintAndLogEx(INFO, "-->Read records from AFL.");
1431 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
1432
1433 while(AFL && AFL->len) {
1434 if (AFL->len % 4) {
1435 PrintAndLogEx(ERR, "Wrong AFL length: %d", AFL->len);
1436 break;
1437 }
1438
1439 json_t *sfijson = json_path_get(root, "$.Application.Records");
1440 if (!sfijson) {
1441 json_t *app = json_path_get(root, "$.Application");
1442 json_object_set_new(app, "Records", json_array());
1443
1444 sfijson = json_path_get(root, "$.Application.Records");
1445 }
1446 if (!json_is_array(sfijson)) {
1447 PrintAndLogEx(ERR, "Internal logic error. `$.Application.Records` is not an array.");
1448 break;
1449 }
1450 for (int i = 0; i < AFL->len / 4; i++) {
1451 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
1452 uint8_t SFIstart = AFL->value[i * 4 + 1];
1453 uint8_t SFIend = AFL->value[i * 4 + 2];
1454 uint8_t SFIoffline = AFL->value[i * 4 + 3];
1455
1456 PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
1457 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
1458 PrintAndLogEx(ERR, "SFI ERROR! Skipped...");
1459 continue;
1460 }
1461
1462 for(int n = SFIstart; n <= SFIend; n++) {
1463 PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n);
1464
1465 res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
1466 if (res) {
1467 PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw);
1468 continue;
1469 }
1470
1471 if (decodeTLV) {
1472 TLVPrintFromBuffer(buf, len);
1473 PrintAndLogEx(NORMAL, "");
1474 }
1475
1476 json_t *jsonelm = json_object();
1477 json_array_append_new(sfijson, jsonelm);
1478
1479 JsonSaveHex(jsonelm, "SFI", SFI, 1);
1480 JsonSaveHex(jsonelm, "RecordNum", n, 1);
1481 JsonSaveHex(jsonelm, "Offline", SFIoffline, 1);
1482
1483 struct tlvdb *rsfi = tlvdb_parse_multi(buf, len);
1484 if (extractTLVElements)
1485 JsonSaveTLVTree(root, jsonelm, "$.Data", rsfi);
1486 else
1487 JsonSaveTLVTreeElm(jsonelm, "$.Data", rsfi, true, true, false);
1488 tlvdb_free(rsfi);
1489 }
1490 }
1491
1492 break;
1493 }
1494
1495 // getting certificates
1496 if (tlvdb_get(tlvRoot, 0x90, NULL)) {
1497 PrintAndLogEx(INFO, "-->Recovering certificates.");
1498 PKISetStrictExecution(false);
1499 RecoveryCertificates(tlvRoot, root);
1500 PKISetStrictExecution(true);
1501 }
1502
1503 // free tlv object
1504 tlvdb_free(tlvRoot);
1505
1506 if (channel == ECC_CONTACTLESS) {
1507 DropField();
1508 }
1509
1510 res = json_dump_file(root, fname, JSON_INDENT(2));
1511 if (res) {
1512 PrintAndLogEx(ERR, "Can't save the file: %s", fname);
1513 return 200;
1514 }
1515 PrintAndLogEx(SUCCESS, "File `%s` saved.", fname);
1516
1517 // free json object
1518 json_decref(root);
1519
1520 return 0;
1521 }
1522
1523 int CmdEMVTest(const char *cmd) {
1524 return ExecuteCryptoTests(true);
1525 }
1526
1527 int CmdEMVRoca(const char *cmd) {
1528 uint8_t AID[APDU_DATA_LEN] = {0};
1529 size_t AIDlen = 0;
1530 uint8_t buf[APDU_RESPONSE_LEN] = {0};
1531 size_t len = 0;
1532 uint16_t sw = 0;
1533 int res;
1534
1535 CLIParserInit("emv roca",
1536 "Tries to extract public keys and run the ROCA test against them.\n",
1537 "Usage:\n"
1538 "\temv roca -w -> select CONTACT card and run test\n\temv roca -> select CONTACTLESS card and run test\n");
1539
1540 void* argtable[] = {
1541 arg_param_begin,
1542 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
1543 arg_param_end
1544 };
1545 CLIExecWithReturn(cmd, argtable, true);
1546
1547 EMVCommandChannel channel = ECC_CONTACTLESS;
1548 if (arg_get_lit(1))
1549 channel = ECC_CONTACT;
1550
1551 // select card
1552 uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
1553
1554 SetAPDULogging(false);
1555
1556 // init applets list tree
1557 const char *al = "Applets list";
1558 struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
1559
1560 // EMV PPSE
1561 PrintAndLogEx(NORMAL, "--> PPSE.");
1562 res = EMVSearchPSE(channel, false, true, psenum, false, tlvSelect);
1563
1564 // check PPSE and select application id
1565 if (!res) {
1566 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1567 } else {
1568 // EMV SEARCH with AID list
1569 PrintAndLogEx(NORMAL, "--> AID search.");
1570 if (EMVSearch(channel, false, true, false, tlvSelect)) {
1571 PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit...");
1572 tlvdb_free(tlvSelect);
1573 DropField();
1574 return 3;
1575 }
1576
1577 // check search and select application id
1578 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1579 }
1580
1581 // EMV SELECT application
1582 SetAPDULogging(false);
1583 EMVSelectApplication(tlvSelect, AID, &AIDlen);
1584
1585 tlvdb_free(tlvSelect);
1586
1587 if (!AIDlen) {
1588 PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit...");
1589 if (channel == ECC_CONTACTLESS) {
1590 DropField();
1591 }
1592 return 4;
1593 }
1594
1595 // Init TLV tree
1596 const char *alr = "Root terminal TLV tree";
1597 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
1598
1599 // EMV SELECT applet
1600 PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen));
1601 res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
1602
1603 if (res) {
1604 PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res);
1605 tlvdb_free(tlvRoot);
1606 if (channel == ECC_CONTACTLESS) {
1607 DropField();
1608 }
1609 return 5;
1610 }
1611
1612 PrintAndLog("\n* Init transaction parameters.");
1613 InitTransactionParameters(tlvRoot, true, TT_QVSDCMCHIP, false);
1614
1615 PrintAndLogEx(NORMAL, "-->Calc PDOL.");
1616 struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
1617 if (!pdol_data_tlv){
1618 PrintAndLogEx(ERR, "Can't create PDOL TLV.");
1619 tlvdb_free(tlvRoot);
1620 if (channel == ECC_CONTACTLESS) {
1621 DropField();
1622 }
1623 return 6;
1624 }
1625
1626 size_t pdol_data_tlv_data_len;
1627 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
1628 if (!pdol_data_tlv_data) {
1629 PrintAndLogEx(ERR, "Can't create PDOL data.");
1630 tlvdb_free(tlvRoot);
1631 DropField();
1632 return 6;
1633 }
1634 PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
1635
1636 PrintAndLogEx(INFO, "-->GPO.");
1637 res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
1638
1639 free(pdol_data_tlv_data);
1640 free(pdol_data_tlv);
1641
1642 if (res) {
1643 PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw);
1644 tlvdb_free(tlvRoot);
1645 if (channel == ECC_CONTACTLESS) {
1646 DropField();
1647 }
1648 return 7;
1649 }
1650 ProcessGPOResponseFormat1(tlvRoot, buf, len, false);
1651
1652 PrintAndLogEx(INFO, "-->Read records from AFL.");
1653 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
1654
1655 while(AFL && AFL->len) {
1656 if (AFL->len % 4) {
1657 PrintAndLogEx(ERR, "Wrong AFL length: %d", AFL->len);
1658 break;
1659 }
1660
1661 for (int i = 0; i < AFL->len / 4; i++) {
1662 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
1663 uint8_t SFIstart = AFL->value[i * 4 + 1];
1664 uint8_t SFIend = AFL->value[i * 4 + 2];
1665 uint8_t SFIoffline = AFL->value[i * 4 + 3];
1666
1667 PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
1668 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
1669 PrintAndLogEx(ERR, "SFI ERROR! Skipped...");
1670 continue;
1671 }
1672
1673 for(int n = SFIstart; n <= SFIend; n++) {
1674 PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n);
1675
1676 res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
1677 if (res) {
1678 PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw);
1679 continue;
1680 }
1681 }
1682 }
1683
1684 break;
1685 }
1686
1687 // getting certificates
1688 if (tlvdb_get(tlvRoot, 0x90, NULL)) {
1689 PrintAndLogEx(INFO, "-->Recovering certificates.");
1690 PKISetStrictExecution(false);
1691
1692 struct emv_pk *pk = get_ca_pk(tlvRoot);
1693 if (!pk) {
1694 PrintAndLogEx(ERR, "ERROR: Key not found. Exit.");
1695 goto out;
1696 }
1697
1698 struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlvRoot);
1699 if (!issuer_pk) {
1700 emv_pk_free(pk);
1701 PrintAndLogEx(WARNING, "WARNING: Issuer certificate not found. Exit.");
1702 goto out;
1703 }
1704
1705 PrintAndLogEx(SUCCESS, "Issuer PK recovered. RID %s IDX %02hhx CSN %s",
1706 sprint_hex(issuer_pk->rid, 5),
1707 issuer_pk->index,
1708 sprint_hex(issuer_pk->serial, 3)
1709 );
1710
1711
1712 struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlvRoot, NULL);
1713 if (!icc_pk) {
1714 emv_pk_free(pk);
1715 emv_pk_free(issuer_pk);
1716 PrintAndLogEx(WARNING, "WARNING: ICC certificate not found. Exit.");
1717 goto out;
1718 }
1719 PrintAndLogEx(SUCCESS, "ICC PK recovered. RID %s IDX %02hhx CSN %s\n",
1720 sprint_hex(icc_pk->rid, 5),
1721 icc_pk->index,
1722 sprint_hex(icc_pk->serial, 3)
1723 );
1724
1725 PrintAndLogEx(INFO, "ICC pk modulus: %s", sprint_hex_inrow(icc_pk->modulus, icc_pk->mlen));
1726
1727 // icc_pk->exp, icc_pk->elen
1728 // icc_pk->modulus, icc_pk->mlen
1729 if (icc_pk->elen > 0 && icc_pk->mlen > 0) {
1730 if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen, true)) {
1731 PrintAndLogEx(INFO, "ICC pk is a subject to ROCA vulnerability, insecure..");
1732 } else {
1733 PrintAndLogEx(INFO, "ICC pk is OK(");
1734 }
1735 }
1736
1737 PKISetStrictExecution(true);
1738 }
1739
1740 out:
1741
1742 // free tlv object
1743 tlvdb_free(tlvRoot);
1744
1745 if (channel == ECC_CONTACTLESS) {
1746 DropField();
1747 }
1748
1749 return 0;
1750 }
1751
1752 int CmdHelp(const char *Cmd);
1753
1754 static command_t CommandTable[] = {
1755 {"help", CmdHelp, 1, "This help"},
1756 {"exec", CmdEMVExec, 1, "Executes EMV contactless transaction."},
1757 {"pse", CmdEMVPPSE, 1, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."},
1758 {"search", CmdEMVSearch, 1, "Try to select all applets from applets list and print installed applets."},
1759 {"select", CmdEMVSelect, 1, "Select applet."},
1760 {"gpo", CmdEMVGPO, 1, "Execute GetProcessingOptions."},
1761 {"readrec", CmdEMVReadRecord, 1, "Read files from card."},
1762 {"genac", CmdEMVAC, 1, "Generate ApplicationCryptogram."},
1763 {"challenge", CmdEMVGenerateChallenge, 1, "Generate challenge."},
1764 {"intauth", CmdEMVInternalAuthenticate, 1, "Internal authentication."},
1765 {"scan", CmdEMVScan, 1, "Scan EMV card and save it contents to json file for emulator."},
1766 {"test", CmdEMVTest, 1, "Crypto logic test."},
1767 {"roca", CmdEMVRoca, 1, "Extract public keys and run ROCA test"},
1768 {NULL, NULL, 0, NULL}
1769 };
1770
1771 int CmdEMV(const char *Cmd) {
1772 CmdsParse(CommandTable, Cmd);
1773 return 0;
1774 }
1775
1776 int CmdHelp(const char *Cmd) {
1777 CmdsHelp(CommandTable);
1778 return 0;
1779 }
Impressum, Datenschutz