Cleanup armsrc/string.c and string.h (#964)
[legacy-proxmark3.git] / client / emv / cmdemv.c
blob0e84260a87a548dce4c8a74b865be628f228467e
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 //-----------------------------------------------------------------------------
11 #include "cmdemv.h"
13 #include <ctype.h>
14 #include <string.h>
15 #include "proxmark3.h"
16 #include "cmdparser.h"
17 #include "ui.h"
18 #include "util.h"
19 #include "mifare.h"
20 #include "emvjson.h"
21 #include "emv_pki.h"
22 #include "emvcore.h"
23 #include "test/cryptotest.h"
24 #include "cliparser/cliparser.h"
25 #include "jansson.h"
26 #include "emv_roca.h"
27 #include "pcsc.h"
28 #include "apduinfo.h"
29 #include "dol.h"
30 #include "emv_tags.h"
31 #include "cmdhf14a.h"
32 #include "cmdsmartcard.h"
34 #define TLV_ADD(tag, value)( tlvdb_change_or_add_node(tlvRoot, tag, sizeof(value) - 1, (const unsigned char *)value) )
35 void ParamLoadDefaults(struct tlvdb *tlvRoot) {
36 //9F02:(Amount, authorized (Numeric)) len:6
37 TLV_ADD(0x9F02, "\x00\x00\x00\x00\x01\x00");
38 //9F1A:(Terminal Country Code) len:2
39 TLV_ADD(0x9F1A, "ru");
40 //5F2A:(Transaction Currency Code) len:2
41 // USD 840, EUR 978, RUR 810, RUB 643, RUR 810(old), UAH 980, AZN 031, n/a 999
42 TLV_ADD(0x5F2A, "\x09\x80");
43 //9A:(Transaction Date) len:3
44 TLV_ADD(0x9A, "\x00\x00\x00");
45 //9C:(Transaction Type) len:1 | 00 => Goods and service #01 => Cash
46 TLV_ADD(0x9C, "\x00");
47 // 9F37 Unpredictable Number len:4
48 TLV_ADD(0x9F37, "\x01\x02\x03\x04");
49 // 9F6A Unpredictable Number (MSD for UDOL) len:4
50 TLV_ADD(0x9F6A, "\x01\x02\x03\x04");
51 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
52 TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC
53 //95:(Terminal Verification Results) len:5
54 // all OK TVR
55 TLV_ADD(0x95, "\x00\x00\x00\x00\x00");
58 void PrintChannel(EMVCommandChannel channel) {
59 switch(channel) {
60 case ECC_CONTACTLESS:
61 PrintAndLogEx(INFO, "Channel: CONTACTLESS");
62 break;
63 case ECC_CONTACT:
64 PrintAndLogEx(INFO, "Channel: CONTACT, using %s", getAlternativeSmartcardReader());
65 break;
69 int CmdEMVSelect(const char *cmd) {
70 uint8_t data[APDU_DATA_LEN] = {0};
71 int datalen = 0;
73 CLIParserInit("emv select",
74 "Executes select applet command",
75 "Usage:\n\temv select -s a00000000101 -> select card, select applet\n\temv select -st a00000000101 -> select card, select applet, show result in TLV\n");
77 void* argtable[] = {
78 arg_param_begin,
79 arg_lit0("sS", "select", "activate field and select card"),
80 arg_lit0("kK", "keep", "keep field for next command"),
81 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
82 arg_lit0("tT", "tlv", "TLV decode results"),
83 #ifdef WITH_SMARTCARD
84 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
85 #endif
86 arg_strx0(NULL, NULL, "<HEX applet AID>", NULL),
87 arg_param_end
89 CLIExecWithReturn(cmd, argtable, true);
91 bool activateField = arg_get_lit(1);
92 bool leaveSignalON = arg_get_lit(2);
93 bool APDULogging = arg_get_lit(3);
94 bool decodeTLV = arg_get_lit(4);
95 EMVCommandChannel channel = ECC_CONTACTLESS;
96 #ifdef WITH_SMARTCARD
97 if (arg_get_lit(5))
98 channel = ECC_CONTACT;
99 PrintChannel(channel);
100 CLIGetHexWithReturn(6, data, &datalen);
101 #else
102 CLIGetHexWithReturn(5, data, &datalen);
103 #endif
104 CLIParserFree();
106 SetAPDULogging(APDULogging);
108 // exec
109 uint8_t buf[APDU_RESPONSE_LEN] = {0};
110 size_t len = 0;
111 uint16_t sw = 0;
112 int res = EMVSelect(channel, activateField, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL);
114 if (sw)
115 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
117 if (res)
118 return res;
120 if (decodeTLV)
121 TLVPrintFromBuffer(buf, len);
123 return 0;
126 int CmdEMVSearch(const char *cmd) {
128 CLIParserInit("emv search",
129 "Tries to select all applets from applet list:\n",
130 "Usage:\n\temv search -s -> select card and search\n\temv search -st -> select card, search and show result in TLV\n");
132 void* argtable[] = {
133 arg_param_begin,
134 arg_lit0("sS", "select", "activate field and select card"),
135 arg_lit0("kK", "keep", "keep field ON for next command"),
136 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
137 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
138 #ifdef WITH_SMARTCARD
139 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
140 #endif
141 arg_param_end
143 CLIExecWithReturn(cmd, argtable, true);
145 bool activateField = arg_get_lit(1);
146 bool leaveSignalON = arg_get_lit(2);
147 bool APDULogging = arg_get_lit(3);
148 bool decodeTLV = arg_get_lit(4);
149 EMVCommandChannel channel = ECC_CONTACTLESS;
150 #ifdef WITH_SMARTCARD
151 if (arg_get_lit(5))
152 channel = ECC_CONTACT;
153 #endif
154 PrintChannel(channel);
155 CLIParserFree();
157 SetAPDULogging(APDULogging);
159 struct tlvdb *t = NULL;
160 const char *al = "Applets list";
161 t = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
163 if (EMVSearch(channel, activateField, leaveSignalON, decodeTLV, t)) {
164 tlvdb_free(t);
165 return 2;
168 PrintAndLogEx(SUCCESS, "Search completed.");
170 // print list here
171 if (!decodeTLV) {
172 TLVPrintAIDlistFromSelectTLV(t);
175 tlvdb_free(t);
177 return 0;
180 int CmdEMVPPSE(const char *cmd) {
182 CLIParserInit("emv pse",
183 "Executes PSE/PPSE select command. It returns list of applet on the card:\n",
184 "Usage:\n\temv pse -s1 -> select, get pse\n\temv pse -st2 -> select, get ppse, show result in TLV\n");
186 void* argtable[] = {
187 arg_param_begin,
188 arg_lit0("sS", "select", "activate field and select card"),
189 arg_lit0("kK", "keep", "keep field ON for next command"),
190 arg_lit0("1", "pse", "pse (1PAY.SYS.DDF01) mode"),
191 arg_lit0("2", "ppse", "ppse (2PAY.SYS.DDF01) mode (default mode)"),
192 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
193 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
194 #ifdef WITH_SMARTCARD
195 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
196 #endif
197 arg_param_end
199 CLIExecWithReturn(cmd, argtable, true);
201 bool activateField = arg_get_lit(1);
202 bool leaveSignalON = arg_get_lit(2);
203 uint8_t PSENum = 2;
204 if (arg_get_lit(3))
205 PSENum = 1;
206 if (arg_get_lit(4))
207 PSENum = 2;
208 bool APDULogging = arg_get_lit(5);
209 bool decodeTLV = arg_get_lit(6);
210 EMVCommandChannel channel = ECC_CONTACTLESS;
211 #ifdef WITH_SMARTCARD
212 if (arg_get_lit(7))
213 channel = ECC_CONTACT;
214 #endif
215 PrintChannel(channel);
216 CLIParserFree();
218 SetAPDULogging(APDULogging);
220 // exec
221 uint8_t buf[APDU_RESPONSE_LEN] = {0};
222 size_t len = 0;
223 uint16_t sw = 0;
224 int res = EMVSelectPSE(channel, activateField, leaveSignalON, PSENum, buf, sizeof(buf), &len, &sw);
226 if (sw)
227 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
229 if (res)
230 return res;
233 if (decodeTLV)
234 TLVPrintFromBuffer(buf, len);
236 return 0;
239 int CmdEMVGPO(const char *cmd) {
240 uint8_t data[APDU_RESPONSE_LEN] = {0};
241 int datalen = 0;
243 CLIParserInit("emv gpo",
244 "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.",
245 "Usage:\n\temv gpo -k -> execute GPO\n"
246 "\temv gpo -t 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n"
247 "\temv gpo -pmt 9F 37 04 -> load params from file, make PDOL data from PDOL, execute GPO with PDOL, show result in TLV\n");
249 void* argtable[] = {
250 arg_param_begin,
251 arg_lit0("kK", "keep", "keep field ON for next command"),
252 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for PDOLdata making from PDOL and parameters"),
253 arg_lit0("mM", "make", "make PDOLdata from PDOL (tag 9F38) and parameters (by default uses default parameters)"),
254 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
255 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
256 #ifdef WITH_SMARTCARD
257 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
258 #endif
259 arg_strx0(NULL, NULL, "<HEX PDOLdata/PDOL>", NULL),
260 arg_param_end
262 CLIExecWithReturn(cmd, argtable, true);
264 bool leaveSignalON = arg_get_lit(1);
265 bool paramsLoadFromFile = arg_get_lit(2);
266 bool dataMakeFromPDOL = arg_get_lit(3);
267 bool APDULogging = arg_get_lit(4);
268 bool decodeTLV = arg_get_lit(5);
269 EMVCommandChannel channel = ECC_CONTACTLESS;
270 #ifdef WITH_SMARTCARD
271 if (arg_get_lit(6))
272 channel = ECC_CONTACT;
273 CLIGetHexWithReturn(7, data, &datalen);
274 #else
275 CLIGetHexWithReturn(6, data, &datalen);
276 #endif
277 PrintChannel(channel);
278 CLIParserFree();
280 SetAPDULogging(APDULogging);
282 // Init TLV tree
283 const char *alr = "Root terminal TLV tree";
284 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
286 // calc PDOL
287 struct tlv *pdol_data_tlv = NULL;
288 struct tlv data_tlv = {
289 .tag = 0x83,
290 .len = datalen,
291 .value = (uint8_t *)data,
293 if (dataMakeFromPDOL) {
294 ParamLoadDefaults(tlvRoot);
296 if (paramsLoadFromFile) {
297 PrintAndLogEx(INFO, "Params loading from file...");
298 ParamLoadFromJson(tlvRoot);
301 pdol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x9f38, datalen, data), tlvRoot, 0x83);
302 if (!pdol_data_tlv){
303 PrintAndLogEx(ERR, "Can't create PDOL TLV.");
304 tlvdb_free(tlvRoot);
305 return 4;
307 } else {
308 if (paramsLoadFromFile) {
309 PrintAndLogEx(WARNING, "Don't need to load parameters. Sending plain PDOL data...");
311 pdol_data_tlv = &data_tlv;
314 size_t pdol_data_tlv_data_len = 0;
315 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
316 if (!pdol_data_tlv_data) {
317 PrintAndLogEx(ERR, "Can't create PDOL data.");
318 tlvdb_free(tlvRoot);
319 return 4;
321 PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
323 // exec
324 uint8_t buf[APDU_RESPONSE_LEN] = {0};
325 size_t len = 0;
326 uint16_t sw = 0;
327 int res = EMVGPO(channel, leaveSignalON, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
329 if (pdol_data_tlv != &data_tlv)
330 free(pdol_data_tlv);
331 tlvdb_free(tlvRoot);
333 if (sw)
334 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
336 if (res)
337 return res;
339 if (decodeTLV)
340 TLVPrintFromBuffer(buf, len);
342 return 0;
345 int CmdEMVReadRecord(const char *cmd) {
346 uint8_t data[APDU_RESPONSE_LEN] = {0};
347 int datalen = 0;
349 CLIParserInit("emv readrec",
350 "Executes Read Record command. It returns data in TLV format.\nNeeds a bank applet to be selected and sometimes needs GPO to be executed.",
351 "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");
353 void* argtable[] = {
354 arg_param_begin,
355 arg_lit0("kK", "keep", "keep field ON for next command"),
356 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
357 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
358 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
359 arg_strx1(NULL, NULL, "<SFI 1byte HEX><SFIrecord 1byte HEX>", NULL),
360 arg_param_end
362 CLIExecWithReturn(cmd, argtable, true);
364 bool leaveSignalON = arg_get_lit(1);
365 bool APDULogging = arg_get_lit(2);
366 bool decodeTLV = arg_get_lit(3);
367 EMVCommandChannel channel = ECC_CONTACTLESS;
368 #ifdef WITH_SMARTCARD
369 if (arg_get_lit(4))
370 channel = ECC_CONTACT;
371 CLIGetHexWithReturn(5, data, &datalen);
372 #else
373 CLIGetHexWithReturn(4, data, &datalen);
374 #endif
375 PrintChannel(channel);
376 CLIParserFree();
378 if (datalen != 2) {
379 PrintAndLogEx(ERR, "Command needs to have 2 bytes of data");
380 return 1;
383 SetAPDULogging(APDULogging);
385 // exec
386 uint8_t buf[APDU_RESPONSE_LEN] = {0};
387 size_t len = 0;
388 uint16_t sw = 0;
389 int res = EMVReadRecord(channel, leaveSignalON, data[0], data[1], buf, sizeof(buf), &len, &sw, NULL);
391 if (sw)
392 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
394 if (res)
395 return res;
398 if (decodeTLV)
399 TLVPrintFromBuffer(buf, len);
401 return 0;
404 int CmdEMVAC(const char *cmd) {
405 uint8_t data[APDU_RESPONSE_LEN] = {0};
406 int datalen = 0;
408 CLIParserInit("emv genac",
409 "Generate Application Cryptogram command. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.",
410 "Usage:\n\temv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n"
411 "\temv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n"
412 "\temv genac -Daac 01020304 -> generate AC with 4-byte CDOL data and terminal decision 'declined'\n"
413 "\temv genac -pmt 9F 37 04 -> load params from file, make CDOL data from CDOL, generate AC with CDOL, show result in TLV");
415 void* argtable[] = {
416 arg_param_begin,
417 arg_lit0("kK", "keep", "keep field ON for next command"),
418 arg_lit0("cC", "cda", "executes CDA transaction. Needs to get SDAD in results."),
419 arg_str0("dD", "decision", "<aac|tc|arqc>", "Terminal decision. aac - declined, tc - approved, arqc - online authorisation requested"),
420 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for CDOLdata making from CDOL and parameters"),
421 arg_lit0("mM", "make", "make CDOLdata from CDOL (tag 8C and 8D) and parameters (by default uses default parameters)"),
422 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
423 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
424 #ifdef WITH_SMARTCARD
425 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
426 #endif
427 arg_strx1(NULL, NULL, "<HEX CDOLdata/CDOL>", NULL),
428 arg_param_end
430 CLIExecWithReturn(cmd, argtable, false);
432 bool leaveSignalON = arg_get_lit(1);
433 bool trTypeCDA = arg_get_lit(2);
434 uint8_t termDecision = 0xff;
435 if (arg_get_str_len(3)) {
436 if (!strncmp(arg_get_str(3)->sval[0], "aac", 4))
437 termDecision = EMVAC_AAC;
438 if (!strncmp(arg_get_str(3)->sval[0], "tc", 4))
439 termDecision = EMVAC_TC;
440 if (!strncmp(arg_get_str(3)->sval[0], "arqc", 4))
441 termDecision = EMVAC_ARQC;
443 if (termDecision == 0xff) {
444 PrintAndLog("ERROR: can't find terminal decision '%s'", arg_get_str(3)->sval[0]);
445 return 1;
447 } else {
448 termDecision = EMVAC_TC;
450 if (trTypeCDA)
451 termDecision = termDecision | EMVAC_CDAREQ;
452 bool paramsLoadFromFile = arg_get_lit(4);
453 bool dataMakeFromCDOL = arg_get_lit(5);
454 bool APDULogging = arg_get_lit(6);
455 bool decodeTLV = arg_get_lit(7);
456 EMVCommandChannel channel = ECC_CONTACTLESS;
457 #ifdef WITH_SMARTCARD
458 if (arg_get_lit(8))
459 channel = ECC_CONTACT;
460 CLIGetHexWithReturn(9, data, &datalen);
461 #else
462 CLIGetHexWithReturn(8, data, &datalen);
463 #endif
464 PrintChannel(channel);
465 CLIParserFree();
467 SetAPDULogging(APDULogging);
469 // Init TLV tree
470 const char *alr = "Root terminal TLV tree";
471 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
473 // calc CDOL
474 struct tlv *cdol_data_tlv = NULL;
475 struct tlv data_tlv = {
476 .tag = 0x01,
477 .len = datalen,
478 .value = (uint8_t *)data,
481 if (dataMakeFromCDOL) {
482 ParamLoadDefaults(tlvRoot);
484 if (paramsLoadFromFile) {
485 PrintAndLogEx(INFO, "Params loading from file...");
486 ParamLoadFromJson(tlvRoot);
489 cdol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x8c, datalen, data), tlvRoot, 0x01); // 0x01 - dummy tag
490 if (!cdol_data_tlv){
491 PrintAndLogEx(ERR, "Can't create CDOL TLV.");
492 tlvdb_free(tlvRoot);
493 return 4;
495 } else {
496 if (paramsLoadFromFile) {
497 PrintAndLogEx(WARNING, "Don't need to load parameters. Sending plain CDOL data...");
499 cdol_data_tlv = &data_tlv;
502 PrintAndLogEx(INFO, "CDOL data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len));
504 // exec
505 uint8_t buf[APDU_RESPONSE_LEN] = {0};
506 size_t len = 0;
507 uint16_t sw = 0;
508 int res = EMVAC(channel, leaveSignalON, termDecision, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
510 if (cdol_data_tlv != &data_tlv)
511 free(cdol_data_tlv);
512 tlvdb_free(tlvRoot);
514 if (sw)
515 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
517 if (res)
518 return res;
520 if (decodeTLV)
521 TLVPrintFromBuffer(buf, len);
523 return 0;
526 int CmdEMVGenerateChallenge(const char *cmd) {
528 CLIParserInit("emv challenge",
529 "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.",
530 "Usage:\n\temv challenge -> get challenge\n\temv challenge -k -> get challenge, keep fileld ON\n");
532 void* argtable[] = {
533 arg_param_begin,
534 arg_lit0("kK", "keep", "keep field ON for next command"),
535 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
536 #ifdef WITH_SMARTCARD
537 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
538 #endif
539 arg_param_end
541 CLIExecWithReturn(cmd, argtable, true);
543 bool leaveSignalON = arg_get_lit(1);
544 bool APDULogging = arg_get_lit(2);
545 EMVCommandChannel channel = ECC_CONTACTLESS;
546 #ifdef WITH_SMARTCARD
547 if (arg_get_lit(3))
548 channel = ECC_CONTACT;
549 #endif
550 PrintChannel(channel);
551 CLIParserFree();
553 SetAPDULogging(APDULogging);
555 // exec
556 uint8_t buf[APDU_RESPONSE_LEN] = {0};
557 size_t len = 0;
558 uint16_t sw = 0;
559 int res = EMVGenerateChallenge(channel, leaveSignalON, buf, sizeof(buf), &len, &sw, NULL);
561 if (sw)
562 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
564 if (res)
565 return res;
567 PrintAndLogEx(SUCCESS, "Challenge: %s", sprint_hex(buf, len));
569 if (len != 4 && len != 8)
570 PrintAndLogEx(WARNING, "Length of challenge must be 4 or 8, but it %d", len);
572 return 0;
575 int CmdEMVInternalAuthenticate(const char *cmd) {
576 uint8_t data[APDU_RESPONSE_LEN] = {0};
577 int datalen = 0;
579 CLIParserInit("emv intauth",
580 "Generate Internal Authenticate command. Usually needs 4-byte random number. It returns data in TLV format .\n"
581 "Needs a EMV applet to be selected and GPO to be executed.",
583 "Usage:\n"
584 "\temv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n"
585 "\temv intauth -t 01020304 -> execute Internal Authenticate with 4-byte DDOL data, show result in TLV\n"
586 "\temv intauth -pmt 9F 37 04 -> load params from file, make DDOL data from DDOL, Internal Authenticate with DDOL, show result in TLV");
588 void* argtable[] = {
589 arg_param_begin,
590 arg_lit0("kK", "keep", "keep field ON for next command"),
591 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for DDOLdata making from DDOL and parameters"),
592 arg_lit0("mM", "make", "make DDOLdata from DDOL (tag 9F49) and parameters (by default uses default parameters)"),
593 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
594 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
595 #ifdef WITH_SMARTCARD
596 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
597 #endif
598 arg_strx1(NULL, NULL, "<HEX DDOLdata/DDOL>", NULL),
599 arg_param_end
601 CLIExecWithReturn(cmd, argtable, false);
603 bool leaveSignalON = arg_get_lit(1);
604 bool paramsLoadFromFile = arg_get_lit(2);
605 bool dataMakeFromDDOL = arg_get_lit(3);
606 bool APDULogging = arg_get_lit(4);
607 bool decodeTLV = arg_get_lit(5);
608 EMVCommandChannel channel = ECC_CONTACTLESS;
609 #ifdef WITH_SMARTCARD
610 if (arg_get_lit(6))
611 channel = ECC_CONTACT;
612 CLIGetHexWithReturn(7, data, &datalen);
613 #else
614 CLIGetHexWithReturn(6, data, &datalen);
615 #endif
616 PrintChannel(channel);
617 CLIParserFree();
619 SetAPDULogging(APDULogging);
621 // Init TLV tree
622 const char *alr = "Root terminal TLV tree";
623 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
625 // calc DDOL
626 struct tlv *ddol_data_tlv = NULL;
627 struct tlv data_tlv = {
628 .tag = 0x01,
629 .len = datalen,
630 .value = (uint8_t *)data,
633 if (dataMakeFromDDOL) {
634 ParamLoadDefaults(tlvRoot);
636 if (paramsLoadFromFile) {
637 PrintAndLogEx(INFO, "Params loading from file...");
638 ParamLoadFromJson(tlvRoot);
641 ddol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x9f49, datalen, data), tlvRoot, 0x01); // 0x01 - dummy tag
642 if (!ddol_data_tlv){
643 PrintAndLogEx(ERR, "Can't create DDOL TLV.");
644 tlvdb_free(tlvRoot);
645 return 4;
647 } else {
648 if (paramsLoadFromFile) {
649 PrintAndLogEx(WARNING, "Don't need to load parameters. Sending plain DDOL data...");
651 ddol_data_tlv = &data_tlv;
654 PrintAndLogEx(INFO, "DDOL data[%d]: %s", ddol_data_tlv->len, sprint_hex(ddol_data_tlv->value, ddol_data_tlv->len));
656 // exec
657 uint8_t buf[APDU_RESPONSE_LEN] = {0};
658 size_t len = 0;
659 uint16_t sw = 0;
660 int res = EMVInternalAuthenticate(channel, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL);
662 if (ddol_data_tlv != &data_tlv)
663 free(ddol_data_tlv);
664 tlvdb_free(tlvRoot);
666 if (sw)
667 PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
669 if (res)
670 return res;
672 if (decodeTLV)
673 TLVPrintFromBuffer(buf, len);
675 return 0;
678 #define dreturn(n) {free(pdol_data_tlv); tlvdb_free(tlvSelect); tlvdb_free(tlvRoot); DropFieldEx( channel ); return n;}
680 void InitTransactionParameters(struct tlvdb *tlvRoot, bool paramLoadJSON, enum TransactionType TrType, bool GenACGPO) {
682 ParamLoadDefaults(tlvRoot);
684 if (paramLoadJSON) {
685 PrintAndLog("* * Transaction parameters loading from JSON...");
686 ParamLoadFromJson(tlvRoot);
689 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
690 char *qVSDC = "\x26\x00\x00\x00";
691 if (GenACGPO) {
692 qVSDC = "\x26\x80\x00\x00";
694 switch(TrType) {
695 case TT_MSD:
696 TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD
697 break;
698 // not standard for contactless. just for test.
699 case TT_VSDC:
700 TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC
701 break;
702 case TT_QVSDCMCHIP:
703 TLV_ADD(0x9F66, qVSDC); // qVSDC
704 break;
705 case TT_CDA:
706 TLV_ADD(0x9F66, qVSDC); // qVSDC (VISA CDA not enabled)
707 break;
708 default:
709 break;
713 void ProcessGPOResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, bool decodeTLV) {
714 if (buf[0] == 0x80) {
715 if (decodeTLV){
716 PrintAndLog("GPO response format1:");
717 TLVPrintFromBuffer(buf, len);
720 if (len < 4 || (len - 4) % 4) {
721 PrintAndLogEx(ERR, "GPO response format1 parsing error. length=%d", len);
722 } else {
723 // AIP
724 struct tlvdb * f1AIP = tlvdb_fixed(0x82, 2, buf + 2);
725 tlvdb_add(tlvRoot, f1AIP);
726 if (decodeTLV){
727 PrintAndLogEx(INFO, "\n* * Decode response format 1 (0x80) AIP and AFL:");
728 TLVPrintFromTLV(f1AIP);
731 // AFL
732 struct tlvdb * f1AFL = tlvdb_fixed(0x94, len - 4, buf + 2 + 2);
733 tlvdb_add(tlvRoot, f1AFL);
734 if (decodeTLV)
735 TLVPrintFromTLV(f1AFL);
737 } else {
738 if (decodeTLV)
739 TLVPrintFromBuffer(buf, len);
743 void ProcessACResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, bool decodeTLV) {
744 if (buf[0] == 0x80) {
745 if (decodeTLV){
746 PrintAndLog("GPO response format1:");
747 TLVPrintFromBuffer(buf, len);
750 uint8_t elmlen = len - 2; // wo 0x80XX
752 if (len < 4 + 2 || (elmlen - 2) % 4 || elmlen != buf[1]) {
753 PrintAndLogEx(ERR, "GPO response format1 parsing error. length=%d", len);
754 } else {
755 struct tlvdb *tlvElm = NULL;
756 if (decodeTLV)
757 PrintAndLog("\n------------ Format1 decoded ------------");
759 // CID (Cryptogram Information Data)
760 tlvdb_change_or_add_node_ex(tlvRoot, 0x9f27, 1, &buf[2], &tlvElm);
761 if (decodeTLV)
762 TLVPrintFromTLV(tlvElm);
764 // ATC (Application Transaction Counter)
765 tlvdb_change_or_add_node_ex(tlvRoot, 0x9f36, 2, &buf[3], &tlvElm);
766 if (decodeTLV)
767 TLVPrintFromTLV(tlvElm);
769 // AC (Application Cryptogram)
770 tlvdb_change_or_add_node_ex(tlvRoot, 0x9f26, MIN(8, elmlen - 3), &buf[5], &tlvElm);
771 if (decodeTLV)
772 TLVPrintFromTLV(tlvElm);
774 // IAD (Issuer Application Data) - optional
775 if (len > 11 + 2) {
776 tlvdb_change_or_add_node_ex(tlvRoot, 0x9f10, elmlen - 11, &buf[13], &tlvElm);
777 if (decodeTLV)
778 TLVPrintFromTLV(tlvElm);
781 } else {
782 if (decodeTLV)
783 TLVPrintFromBuffer(buf, len);
787 int CmdEMVExec(const char *cmd) {
788 uint8_t buf[APDU_RESPONSE_LEN] = {0};
789 size_t len = 0;
790 uint16_t sw = 0;
791 uint8_t AID[APDU_DATA_LEN] = {0};
792 size_t AIDlen = 0;
793 uint8_t ODAiList[4096];
794 size_t ODAiListLen = 0;
796 int res;
798 struct tlvdb *tlvSelect = NULL;
799 struct tlvdb *tlvRoot = NULL;
800 struct tlv *pdol_data_tlv = NULL;
802 CLIParserInit("emv exec",
803 "Executes EMV contactless transaction",
804 "Usage:\n"
805 "\temv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n"
806 "\temv exec -satc -> select card, execute CDA transaction, show APDU and TLV\n");
808 void* argtable[] = {
809 arg_param_begin,
810 arg_lit0("sS", "select", "activate field and select card."),
811 arg_lit0("aA", "apdu", "show APDU reqests and responses."),
812 arg_lit0("tT", "tlv", "TLV decode results."),
813 arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."),
814 arg_lit0("fF", "forceaid", "Force search AID. Search AID instead of execute PPSE."),
815 arg_rem("By default:", "Transaction type - MSD"),
816 arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."),
817 arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."),
818 arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."),
819 arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
820 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
821 arg_param_end
823 CLIExecWithReturn(cmd, argtable, true);
825 bool activateField = arg_get_lit(1);
826 bool showAPDU = arg_get_lit(2);
827 bool decodeTLV = arg_get_lit(3);
828 bool paramLoadJSON = arg_get_lit(4);
829 bool forceSearch = arg_get_lit(5);
831 enum TransactionType TrType = TT_MSD;
832 if (arg_get_lit(7))
833 TrType = TT_QVSDCMCHIP;
834 if (arg_get_lit(8))
835 TrType = TT_CDA;
836 if (arg_get_lit(9))
837 TrType = TT_VSDC;
839 bool GenACGPO = arg_get_lit(10);
840 EMVCommandChannel channel = ECC_CONTACTLESS;
841 #ifdef WITH_SMARTCARD
842 if (arg_get_lit(11))
843 channel = ECC_CONTACT;
844 #endif
845 PrintChannel(channel);
846 uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
847 char *PSE_or_PPSE = psenum == 1 ? "PSE" : "PPSE";
849 CLIParserFree();
851 SetAPDULogging(showAPDU);
853 // init applets list tree
854 const char *al = "Applets list";
855 tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
857 // Application Selection
858 // https://www.openscdp.org/scripts/tutorial/emv/applicationselection.html
859 if (!forceSearch) {
860 // PPSE / PSE
861 PrintAndLogEx(NORMAL, "\n* %s.", PSE_or_PPSE);
862 SetAPDULogging(showAPDU);
863 res = EMVSearchPSE(channel, activateField, true, psenum, decodeTLV, tlvSelect);
865 // check PPSE / PSE and select application id
866 if (!res) {
867 TLVPrintAIDlistFromSelectTLV(tlvSelect);
868 EMVSelectApplication(tlvSelect, AID, &AIDlen);
872 // Search
873 if (!AIDlen) {
874 PrintAndLogEx(NORMAL, "\n* Search AID in list.");
875 SetAPDULogging(false);
876 if (EMVSearch(channel, activateField, true, decodeTLV, tlvSelect)) {
877 dreturn(2);
880 // check search and select application id
881 TLVPrintAIDlistFromSelectTLV(tlvSelect);
882 EMVSelectApplication(tlvSelect, AID, &AIDlen);
885 // Init TLV tree
886 const char *alr = "Root terminal TLV tree";
887 tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
889 // check if we found EMV application on card
890 if (!AIDlen) {
891 PrintAndLogEx(WARNING, "Can't select AID. EMV AID not found");
892 dreturn(2);
895 // Select
896 PrintAndLogEx(NORMAL, "\n* Selecting AID:%s", sprint_hex_inrow(AID, AIDlen));
897 SetAPDULogging(showAPDU);
898 res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
900 if (res) {
901 PrintAndLogEx(WARNING, "Can't select AID (%d). Exit...", res);
902 dreturn(3);
905 if (decodeTLV)
906 TLVPrintFromBuffer(buf, len);
907 PrintAndLogEx(INFO, "* Selected.");
909 PrintAndLogEx(INFO, "\n* Init transaction parameters.");
910 InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO);
911 TLVPrintFromTLV(tlvRoot); // TODO delete!!!
913 PrintAndLogEx(NORMAL, "\n* Calc PDOL.");
914 pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
915 if (!pdol_data_tlv){
916 PrintAndLogEx(WARNING, "Error: can't create PDOL TLV.");
917 dreturn(4);
920 size_t pdol_data_tlv_data_len;
921 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
922 if (!pdol_data_tlv_data) {
923 PrintAndLogEx(WARNING, "Error: can't create PDOL data.");
924 dreturn(4);
926 PrintAndLogEx(NORMAL, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
928 PrintAndLogEx(NORMAL, "\n* GPO.");
929 res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
931 free(pdol_data_tlv_data);
932 //free(pdol_data_tlv); --- free on exit.
934 if (res) {
935 PrintAndLogEx(NORMAL, "GPO error(%d): %4x. Exit...", res, sw);
936 dreturn(5);
939 // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
940 ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV);
942 // extract PAN from track2
944 const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
945 if (!tlvdb_get(tlvRoot, 0x5a, NULL) && track2 && track2->len >= 8) {
946 struct tlvdb *pan = GetPANFromTrack2(track2);
947 if (pan) {
948 tlvdb_add(tlvRoot, pan);
950 const struct tlv *pantlv = tlvdb_get(tlvRoot, 0x5a, NULL);
951 PrintAndLogEx(NORMAL, "\n* * Extracted PAN from track2: %s", sprint_hex(pantlv->value, pantlv->len));
952 } else {
953 PrintAndLogEx(NORMAL, "\n* * WARNING: Can't extract PAN from track2.");
958 PrintAndLogEx(NORMAL, "\n* Read records from AFL.");
959 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
960 if (!AFL || !AFL->len) {
961 PrintAndLogEx(WARNING, "AFL not found.");
964 while(AFL && AFL->len) {
965 if (AFL->len % 4) {
966 PrintAndLogEx(WARNING, "Error: Wrong AFL length: %d", AFL->len);
967 break;
970 for (int i = 0; i < AFL->len / 4; i++) {
971 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
972 uint8_t SFIstart = AFL->value[i * 4 + 1];
973 uint8_t SFIend = AFL->value[i * 4 + 2];
974 uint8_t SFIoffline = AFL->value[i * 4 + 3];
976 PrintAndLogEx(NORMAL, "* * SFI[%02x] start:%02x end:%02x offline count:%02x", SFI, SFIstart, SFIend, SFIoffline);
977 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
978 PrintAndLogEx(NORMAL, "SFI ERROR! Skipped...");
979 continue;
982 for(int n = SFIstart; n <= SFIend; n++) {
983 PrintAndLogEx(NORMAL, "* * * SFI[%02x] %d", SFI, n);
985 res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
986 if (res) {
987 PrintAndLogEx(WARNING, "Error SFI[%02x]. APDU error %4x", SFI, sw);
988 continue;
991 if (decodeTLV) {
992 TLVPrintFromBuffer(buf, len);
993 PrintAndLogEx(NORMAL, "");
996 // Build Input list for Offline Data Authentication
997 // EMV 4.3 book3 10.3, page 96
998 if (SFIoffline > 0) {
999 if (SFI < 11) {
1000 const unsigned char *abuf = buf;
1001 size_t elmlen = len;
1002 struct tlv e;
1003 if (tlv_parse_tl(&abuf, &elmlen, &e)) {
1004 memcpy(&ODAiList[ODAiListLen], &buf[len - elmlen], elmlen);
1005 ODAiListLen += elmlen;
1006 } else {
1007 PrintAndLogEx(WARNING, "Error SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI);
1009 } else {
1010 memcpy(&ODAiList[ODAiListLen], buf, len);
1011 ODAiListLen += len;
1014 SFIoffline--;
1019 break;
1022 // copy Input list for Offline Data Authentication
1023 if (ODAiListLen) {
1024 struct tlvdb *oda = tlvdb_fixed(0x21, ODAiListLen, ODAiList); // not a standard tag
1025 tlvdb_add(tlvRoot, oda);
1026 PrintAndLogEx(NORMAL, "* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen);
1029 // get AIP
1030 uint16_t AIP = 0;
1031 const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL);
1032 if (AIPtlv) {
1033 AIP = AIPtlv->value[0] + AIPtlv->value[1] * 0x100;
1034 PrintAndLogEx(NORMAL, "* * AIP=%04x", AIP);
1035 } else {
1036 PrintAndLogEx(ERR, "Can't found AIP.");
1039 // SDA
1040 if (AIP & 0x0040) {
1041 PrintAndLogEx(NORMAL, "\n* SDA");
1042 trSDA(tlvRoot);
1045 // DDA
1046 if (AIP & 0x0020) {
1047 PrintAndLogEx(NORMAL, "\n* DDA");
1048 trDDA(channel, decodeTLV, tlvRoot);
1051 // transaction check
1053 // qVSDC
1054 if (TrType == TT_QVSDCMCHIP|| TrType == TT_CDA){
1055 // 9F26: Application Cryptogram
1056 const struct tlv *AC = tlvdb_get(tlvRoot, 0x9F26, NULL);
1057 if (AC) {
1058 PrintAndLogEx(NORMAL, "\n--> qVSDC transaction.");
1059 PrintAndLogEx(NORMAL, "* AC path");
1061 // 9F36: Application Transaction Counter (ATC)
1062 const struct tlv *ATC = tlvdb_get(tlvRoot, 0x9F36, NULL);
1063 if (ATC) {
1065 // 9F10: Issuer Application Data - optional
1066 const struct tlv *IAD = tlvdb_get(tlvRoot, 0x9F10, NULL);
1068 // print AC data
1069 PrintAndLogEx(NORMAL, "ATC: %s", sprint_hex(ATC->value, ATC->len));
1070 PrintAndLogEx(NORMAL, "AC: %s", sprint_hex(AC->value, AC->len));
1071 if (IAD){
1072 PrintAndLogEx(NORMAL, "IAD: %s", sprint_hex(IAD->value, IAD->len));
1074 if (IAD->len >= IAD->value[0] + 1) {
1075 PrintAndLogEx(NORMAL, "\tKey index: 0x%02x", IAD->value[1]);
1076 PrintAndLogEx(NORMAL, "\tCrypto ver: 0x%02x(%03d)", IAD->value[2], IAD->value[2]);
1077 PrintAndLogEx(NORMAL, "\tCVR:", sprint_hex(&IAD->value[3], IAD->value[0] - 2));
1078 struct tlvdb * cvr = tlvdb_fixed(0x20, IAD->value[0] - 2, &IAD->value[3]);
1079 TLVPrintFromTLVLev(cvr, 1);
1081 } else {
1082 PrintAndLogEx(WARNING, "IAD not found.");
1085 } else {
1086 PrintAndLogEx(ERR, "AC: Application Transaction Counter (ATC) not found.");
1091 // Mastercard M/CHIP
1092 if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD && (TrType == TT_QVSDCMCHIP || TrType == TT_CDA)){
1093 const struct tlv *CDOL1 = tlvdb_get(tlvRoot, 0x8c, NULL);
1094 if (CDOL1 && GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) { // and m/chip transaction flag
1095 PrintAndLogEx(NORMAL, "\n--> Mastercard M/Chip transaction.");
1097 PrintAndLogEx(NORMAL, "* * Generate challenge");
1098 res = EMVGenerateChallenge(channel, true, buf, sizeof(buf), &len, &sw, tlvRoot);
1099 if (res) {
1100 PrintAndLogEx(WARNING, "GetChallenge. APDU error %4x", sw);
1101 dreturn(6);
1103 if (len < 4) {
1104 PrintAndLogEx(WARNING, "GetChallenge. Wrong challenge length %d", len);
1105 dreturn(6);
1108 // ICC Dynamic Number
1109 struct tlvdb * ICCDynN = tlvdb_fixed(0x9f4c, len, buf);
1110 tlvdb_add(tlvRoot, ICCDynN);
1111 if (decodeTLV){
1112 PrintAndLogEx(NORMAL, "\n* * ICC Dynamic Number:");
1113 TLVPrintFromTLV(ICCDynN);
1116 PrintAndLogEx(NORMAL, "* * Calc CDOL1");
1117 struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
1118 if (!cdol_data_tlv){
1119 PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV.");
1120 dreturn(6);
1122 PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len));
1124 PrintAndLogEx(NORMAL, "* * AC1");
1125 // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
1126 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);
1128 if (res) {
1129 PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw);
1130 dreturn(7);
1133 if (decodeTLV)
1134 TLVPrintFromBuffer(buf, len);
1136 // CDA
1137 PrintAndLogEx(NORMAL, "\n* CDA:");
1138 struct tlvdb *ac_tlv = tlvdb_parse_multi(buf, len);
1139 res = trCDA(tlvRoot, ac_tlv, pdol_data_tlv, cdol_data_tlv);
1140 if (res) {
1141 PrintAndLogEx(NORMAL, "CDA error (%d)", res);
1143 free(ac_tlv);
1144 free(cdol_data_tlv);
1146 PrintAndLogEx(NORMAL, "\n* M/Chip transaction result:");
1147 // 9F27: Cryptogram Information Data (CID)
1148 const struct tlv *CID = tlvdb_get(tlvRoot, 0x9F27, NULL);
1149 if (CID) {
1150 emv_tag_dump(CID, stdout, 0);
1151 PrintAndLogEx(NORMAL, "------------------------------");
1152 if (CID->len > 0) {
1153 switch(CID->value[0] & EMVAC_AC_MASK){
1154 case EMVAC_AAC:
1155 PrintAndLogEx(NORMAL, "Transaction DECLINED.");
1156 break;
1157 case EMVAC_TC:
1158 PrintAndLogEx(NORMAL, "Transaction approved OFFLINE.");
1159 break;
1160 case EMVAC_ARQC:
1161 PrintAndLogEx(NORMAL, "Transaction approved ONLINE.");
1162 break;
1163 default:
1164 PrintAndLogEx(WARNING, "Error: CID transaction code error %2x", CID->value[0] & EMVAC_AC_MASK);
1165 break;
1167 } else {
1168 PrintAndLogEx(WARNING, "Wrong CID length %d", CID->len);
1170 } else {
1171 PrintAndLogEx(WARNING, "CID(9F27) not found.");
1177 // MSD
1178 if (AIP & 0x8000 && TrType == TT_MSD) {
1179 PrintAndLogEx(NORMAL, "\n--> MSD transaction.");
1181 PrintAndLogEx(NORMAL, "* MSD dCVV path. Check dCVV");
1183 const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
1184 if (track2) {
1185 PrintAndLogEx(NORMAL, "Track2: %s", sprint_hex(track2->value, track2->len));
1187 struct tlvdb *dCVV = GetdCVVRawFromTrack2(track2);
1188 PrintAndLogEx(NORMAL, "dCVV raw data:");
1189 TLVPrintFromTLV(dCVV);
1191 if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) {
1192 PrintAndLogEx(NORMAL, "\n* Mastercard calculate UDOL");
1194 // UDOL (9F69)
1195 const struct tlv *UDOL = tlvdb_get(tlvRoot, 0x9F69, NULL);
1196 // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
1197 const struct tlv defUDOL = {
1198 .tag = 0x01,
1199 .len = 3,
1200 .value = (uint8_t *)"\x9f\x6a\x04",
1202 if (!UDOL)
1203 PrintAndLogEx(NORMAL, "Use default UDOL.");
1205 struct tlv *udol_data_tlv = dol_process(UDOL ? UDOL : &defUDOL, tlvRoot, 0x01); // 0x01 - dummy tag
1206 if (!udol_data_tlv){
1207 PrintAndLogEx(WARNING, "can't create UDOL TLV.");
1208 dreturn(8);
1211 PrintAndLogEx(NORMAL, "UDOL data[%d]: %s", udol_data_tlv->len, sprint_hex(udol_data_tlv->value, udol_data_tlv->len));
1213 PrintAndLogEx(NORMAL, "\n* Mastercard compute cryptographic checksum(UDOL)");
1215 res = MSCComputeCryptoChecksum(channel, true, (uint8_t *)udol_data_tlv->value, udol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
1216 if (res) {
1217 PrintAndLogEx(WARNING, "Compute Crypto Checksum. APDU error %4x", sw);
1218 free(udol_data_tlv);
1219 dreturn(9);
1222 // Mastercard compute cryptographic checksum result
1223 TLVPrintFromBuffer(buf, len);
1224 PrintAndLogEx(NORMAL, "");
1226 free(udol_data_tlv);
1229 } else {
1230 PrintAndLogEx(WARNING, "MSD: Track2 data not found.");
1234 // VSDC
1235 if (GetCardPSVendor(AID, AIDlen) == CV_VISA && (TrType == TT_VSDC || TrType == TT_CDA)){
1236 PrintAndLogEx(NORMAL, "\n--> VSDC transaction.");
1238 PrintAndLogEx(NORMAL, "* * Calc CDOL1");
1239 struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
1240 if (!cdol_data_tlv) {
1241 PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV.");
1242 dreturn(6);
1245 PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len));
1247 PrintAndLogEx(NORMAL, "* * AC1");
1248 // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
1249 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);
1251 if (res) {
1252 PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw);
1253 dreturn(7);
1256 // process Format1 (0x80) and print Format2 (0x77)
1257 ProcessACResponseFormat1(tlvRoot, buf, len, decodeTLV);
1259 uint8_t CID = 0;
1260 tlvdb_get_uint8(tlvRoot, 0x9f27, &CID);
1262 // AC1 print result
1263 PrintAndLog("");
1264 if ((CID & EMVAC_AC_MASK) == EMVAC_AAC) PrintAndLogEx(INFO, "AC1 result: AAC (Transaction declined)");
1265 if ((CID & EMVAC_AC_MASK) == EMVAC_TC) PrintAndLogEx(INFO, "AC1 result: TC (Transaction approved)");
1266 if ((CID & EMVAC_AC_MASK) == EMVAC_ARQC) PrintAndLogEx(INFO, "AC1 result: ARQC (Online authorisation requested)");
1267 if ((CID & EMVAC_AC_MASK) == EMVAC_AC_MASK) PrintAndLogEx(INFO, "AC1 result: RFU");
1269 // decode Issuer Application Data (IAD)
1270 uint8_t CryptoVersion = 0;
1271 const struct tlv *IAD = tlvdb_get(tlvRoot, 0x9f10, NULL);
1272 if (IAD && (IAD->len > 1)) {
1273 PrintAndLogEx(NORMAL, "\n* * Issuer Application Data (IAD):");
1274 uint8_t VDDlen = IAD->value[0]; // Visa discretionary data length
1275 uint8_t IDDlen = 0; // Issuer discretionary data length
1276 PrintAndLogEx(NORMAL, "IAD length: %d", IAD->len);
1277 PrintAndLogEx(NORMAL, "VDDlen: %d", VDDlen);
1278 if (VDDlen < IAD->len - 1)
1279 IDDlen = IAD->value[VDDlen + 1];
1280 PrintAndLogEx(NORMAL, "IDDlen: %d", IDDlen);
1282 uint8_t DerivKeyIndex = IAD->value[1];
1283 CryptoVersion = IAD->value[2];
1285 PrintAndLogEx(NORMAL, "CryptoVersion: %d", CryptoVersion);
1286 PrintAndLogEx(NORMAL, "DerivKeyIndex: %d", DerivKeyIndex);
1288 // Card Verification Results (CVR) decode
1289 if ((VDDlen - 2) > 0) {
1290 uint8_t CVRlen = IAD->value[3];
1291 if (CVRlen == (VDDlen - 2 - 1)) {
1292 PrintAndLogEx(NORMAL, "CVR length: %d", CVRlen);
1293 PrintAndLogEx(NORMAL, "CVR: %s", sprint_hex(&IAD->value[4], CVRlen));
1294 } else {
1295 PrintAndLogEx(NORMAL, "Wrong CVR length! CVR: %s", sprint_hex(&IAD->value[3], VDDlen - 2));
1298 if (IDDlen)
1299 PrintAndLogEx(NORMAL, "IDD: %s", sprint_hex(&IAD->value[VDDlen + 1], IDDlen));
1300 } else {
1301 PrintAndLogEx(NORMAL, "Issuer Application Data (IAD) not found.");
1304 PrintAndLogEx(NORMAL, "\n* * Processing online request");
1306 // authorization response code from acquirer
1307 const char HostResponse[] = "00"; // 0x3030
1308 size_t HostResponseLen = sizeof(HostResponse) - 1;
1309 PrintAndLogEx(NORMAL, "Host Response: `%s`", HostResponse);
1310 tlvdb_change_or_add_node(tlvRoot, 0x8a, HostResponseLen, (const unsigned char *)HostResponse);
1312 if (CryptoVersion == 10) {
1313 PrintAndLogEx(NORMAL, "\n* * Generate ARPC");
1315 // Application Cryptogram (AC)
1316 const struct tlv *AC = tlvdb_get(tlvRoot, 0x9f26, NULL);
1317 if (AC && (AC->len > 0)) {
1318 PrintAndLogEx(NORMAL, "AC: %s", sprint_hex(AC->value, AC->len));
1320 size_t rawARPClen = AC->len;
1321 uint8_t rawARPC[rawARPClen];
1322 memcpy(rawARPC, AC->value, AC->len);
1323 for (int i = 0; (i < HostResponseLen) && (i < rawARPClen); i++)
1324 rawARPC[i] ^= HostResponse[i];
1325 PrintAndLogEx(NORMAL, "raw ARPC: %s", sprint_hex(rawARPC, rawARPClen));
1327 // here must be calculation of ARPC, but we dont know a bank keys.
1328 PrintAndLogEx(NORMAL, "ARPC: n/a");
1330 } else {
1331 PrintAndLogEx(NORMAL, "Application Cryptogram (AC) not found.");
1334 // here must be external authenticate, but we dont know ARPC
1339 // needs to send AC2 command (res == ARQC)
1340 if ((CID & EMVAC_AC_MASK) == EMVAC_ARQC) {
1341 PrintAndLogEx(NORMAL, "\n* * Calc CDOL2");
1342 struct tlv *cdol2_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8d, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
1343 if (!cdol2_data_tlv) {
1344 PrintAndLogEx(WARNING, "Error: can't create CDOL2 TLV.");
1345 dreturn(6);
1348 PrintAndLogEx(NORMAL, "CDOL2 data[%d]: %s", cdol2_data_tlv->len, sprint_hex(cdol2_data_tlv->value, cdol2_data_tlv->len));
1350 //PrintAndLogEx(NORMAL, "* * AC2");
1353 // here must be AC2, but we dont make external authenticate (
1355 /* // AC2
1356 PRINT_INDENT(level);
1357 if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) fprintf(f, "\tAC2: AAC (Transaction declined)\n");
1358 if ((CID & EMVAC_AC2_MASK) == EMVAC_TC2) fprintf(f, "\tAC2: TC (Transaction approved)\n");
1359 if ((CID & EMVAC_AC2_MASK) == EMVAC_ARQC2) fprintf(f, "\tAC2: not requested (ARQC)\n");
1360 if ((CID & EMVAC_AC2_MASK) == EMVAC_AC2_MASK) fprintf(f, "\tAC2: RFU\n");
1366 DropFieldEx( channel );
1368 // Destroy TLV's
1369 free(pdol_data_tlv);
1370 tlvdb_free(tlvSelect);
1371 tlvdb_free(tlvRoot);
1373 PrintAndLogEx(NORMAL, "\n* Transaction completed.");
1374 return 0;
1377 int CmdEMVScan(const char *cmd) {
1378 uint8_t AID[APDU_DATA_LEN] = {0};
1379 size_t AIDlen = 0;
1380 uint8_t buf[APDU_RESPONSE_LEN] = {0};
1381 size_t len = 0;
1382 uint16_t sw = 0;
1383 int res;
1384 json_t *root;
1385 json_error_t error;
1387 CLIParserInit("emv scan",
1388 "Scan EMV card and save it contents to a file.",
1389 "It executes EMV contactless transaction and saves result to a file which can be used for emulation\n"
1390 "Usage:\n\temv scan -at -> scan MSD transaction mode and show APDU and TLV\n"
1391 "\temv scan -c -> scan CDA transaction mode\n");
1393 void* argtable[] = {
1394 arg_param_begin,
1395 arg_lit0("aA", "apdu", "show APDU reqests and responses."),
1396 arg_lit0("tT", "tlv", "TLV decode results."),
1397 arg_lit0("eE", "extract", "Extract TLV elements and fill Application Data"),
1398 arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."),
1399 arg_rem("By default:", "Transaction type - MSD"),
1400 arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."),
1401 arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."),
1402 arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."),
1403 arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
1404 arg_lit0("mM", "merge", "Merge output file with card's data. (warning: the file may be corrupted!)"),
1405 #ifdef WITH_SMARTCARD
1406 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
1407 #endif
1408 arg_str1(NULL, NULL, "output.json", "JSON output file name"),
1409 arg_param_end
1411 CLIExecWithReturn(cmd, argtable, true);
1413 bool showAPDU = arg_get_lit(1);
1414 bool decodeTLV = arg_get_lit(2);
1415 bool extractTLVElements = arg_get_lit(3);
1416 bool paramLoadJSON = arg_get_lit(4);
1418 enum TransactionType TrType = TT_MSD;
1419 if (arg_get_lit(6))
1420 TrType = TT_QVSDCMCHIP;
1421 if (arg_get_lit(7))
1422 TrType = TT_CDA;
1423 if (arg_get_lit(8))
1424 TrType = TT_VSDC;
1426 bool GenACGPO = arg_get_lit(9);
1427 bool MergeJSON = arg_get_lit(10);
1428 EMVCommandChannel channel = ECC_CONTACTLESS;
1429 uint8_t relfname[250] = {0};
1430 char *crelfname = (char *)relfname;
1431 int relfnamelen = 0;
1432 #ifdef WITH_SMARTCARD
1433 if (arg_get_lit(11)) {
1434 channel = ECC_CONTACT;
1436 CLIGetStrWithReturn(12, relfname, &relfnamelen);
1437 #else
1438 CLIGetStrWithReturn(11, relfname, &relfnamelen);
1439 #endif
1440 PrintChannel(channel);
1441 uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
1442 CLIParserFree();
1444 SetAPDULogging(showAPDU);
1446 // current path + file name
1447 if (!strstr(crelfname, ".json"))
1448 strcat(crelfname, ".json");
1449 char fname[strlen(get_my_executable_directory()) + strlen(crelfname) + 1];
1450 strcpy(fname, get_my_executable_directory());
1451 strcat(fname, crelfname);
1453 if (MergeJSON) {
1454 root = json_load_file(fname, 0, &error);
1455 if (!root) {
1456 PrintAndLogEx(ERR, "json error on line %d: %s", error.line, error.text);
1457 return 1;
1460 if (!json_is_object(root)) {
1461 PrintAndLogEx(ERR, "Invalid json format. root must be an object.");
1462 return 1;
1464 } else {
1465 root = json_object();
1468 // drop field at start
1469 DropFieldEx( channel );
1471 JsonSaveStr(root, "$.File.Created", "proxmark3 `emv scan`");
1473 if (channel == ECC_CONTACTLESS) {
1474 // iso 14443 select
1475 PrintAndLogEx(NORMAL, "--> GET UID, ATS.");
1477 iso14a_card_select_t card;
1478 if (Hf14443_4aGetCardData(&card)) {
1479 return 2;
1481 if (!card.uidlen) {
1482 PrintAndLogEx(ERR, "get ATS error");
1483 return 2;
1486 JsonSaveStr(root, "$.Card.Contactless.Communication", "iso14443-4a");
1487 JsonSaveBufAsHex(root, "$.Card.Contactless.UID", (uint8_t *)&card.uid, card.uidlen);
1488 JsonSaveHex(root, "$.Card.Contactless.ATQA", card.atqa[0] + (card.atqa[1] << 2), 2);
1489 JsonSaveHex(root, "$.Card.Contactless.SAK", card.sak, 0);
1490 JsonSaveBufAsHex(root, "$.Card.Contactless.ATS", (uint8_t *)card.ats, card.ats_len);
1491 } else {
1492 PrintAndLogEx(NORMAL, "--> GET ATR.");
1494 smart_card_atr_t ccard;
1495 smart_getATR(&ccard);
1497 if (!ccard.atr_len) {
1498 PrintAndLogEx(ERR, "get ATR error");
1499 return 2;
1502 JsonSaveStr(root, "$.Card.Contact.Communication", "iso7816");
1503 JsonSaveBufAsHex(root, "$.Card.Contact.ATR", (uint8_t *)ccard.atr, ccard.atr_len);
1506 // init applets list tree
1507 const char *al = "Applets list";
1508 struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
1510 // EMV PPSE
1511 PrintAndLogEx(NORMAL, "--> PPSE.");
1512 res = EMVSelectPSE(channel, true, true, 2, buf, sizeof(buf), &len, &sw);
1514 if (!res && sw == 0x9000){
1515 if (decodeTLV)
1516 TLVPrintFromBuffer(buf, len);
1518 JsonSaveBufAsHex(root, "$.PPSE.AID", (uint8_t *)"2PAY.SYS.DDF01", 14);
1520 struct tlvdb *fci = tlvdb_parse_multi(buf, len);
1521 if (extractTLVElements)
1522 JsonSaveTLVTree(root, root, "$.PPSE.FCITemplate", fci);
1523 else
1524 JsonSaveTLVTreeElm(root, "$.PPSE.FCITemplate", fci, true, true, false);
1525 JsonSaveTLVValue(root, "$.Application.KernelID", tlvdb_find_full(fci, 0x9f2a));
1526 tlvdb_free(fci);
1529 res = EMVSearchPSE(channel, false, true, psenum, decodeTLV, tlvSelect);
1531 // check PPSE and select application id
1532 if (!res) {
1533 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1534 } else {
1535 // EMV SEARCH with AID list
1536 SetAPDULogging(false);
1537 PrintAndLogEx(NORMAL, "--> AID search.");
1538 if (EMVSearch(channel, false, true, decodeTLV, tlvSelect)) {
1539 PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit...");
1540 tlvdb_free(tlvSelect);
1541 DropFieldEx( channel );
1542 return 3;
1545 // check search and select application id
1546 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1549 // EMV SELECT application
1550 SetAPDULogging(showAPDU);
1551 EMVSelectApplication(tlvSelect, AID, &AIDlen);
1553 tlvdb_free(tlvSelect);
1555 if (!AIDlen) {
1556 PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit...");
1557 DropFieldEx( channel );
1558 return 4;
1561 JsonSaveBufAsHex(root, "$.Application.AID", AID, AIDlen);
1563 // Init TLV tree
1564 const char *alr = "Root terminal TLV tree";
1565 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
1567 // EMV SELECT applet
1569 PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen));
1570 SetAPDULogging(showAPDU);
1571 res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
1573 if (res) {
1574 PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res);
1575 tlvdb_free(tlvRoot);
1576 DropFieldEx( channel );
1577 return 5;
1580 if (decodeTLV)
1581 TLVPrintFromBuffer(buf, len);
1583 // save mode
1584 if (tlvdb_get(tlvRoot, 0x9f38, NULL)) {
1585 JsonSaveStr(root, "$.Application.Mode", TransactionTypeStr[TrType]);
1588 struct tlvdb *fci = tlvdb_parse_multi(buf, len);
1589 if (extractTLVElements)
1590 JsonSaveTLVTree(root, root, "$.Application.FCITemplate", fci);
1591 else
1592 JsonSaveTLVTreeElm(root, "$.Application.FCITemplate", fci, true, true, false);
1593 tlvdb_free(fci);
1595 // create transaction parameters
1596 PrintAndLogEx(NORMAL, "-->Init transaction parameters.");
1597 InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO);
1599 PrintAndLogEx(NORMAL, "-->Calc PDOL.");
1600 struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
1601 if (!pdol_data_tlv){
1602 PrintAndLogEx(ERR, "Can't create PDOL TLV.");
1603 tlvdb_free(tlvRoot);
1604 DropFieldEx( channel );
1605 return 6;
1608 size_t pdol_data_tlv_data_len;
1609 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
1610 if (!pdol_data_tlv_data) {
1611 PrintAndLogEx(ERR, "Can't create PDOL data.");
1612 tlvdb_free(tlvRoot);
1613 DropFieldEx( channel );
1614 return 6;
1616 PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
1618 PrintAndLogEx(INFO, "-->GPO.");
1619 res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
1621 free(pdol_data_tlv_data);
1622 free(pdol_data_tlv);
1624 if (res) {
1625 PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw);
1626 tlvdb_free(tlvRoot);
1627 DropFieldEx( channel );
1628 return 7;
1630 ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV);
1632 struct tlvdb *gpofci = tlvdb_parse_multi(buf, len);
1633 if (extractTLVElements)
1634 JsonSaveTLVTree(root, root, "$.Application.GPO", gpofci);
1635 else
1636 JsonSaveTLVTreeElm(root, "$.Application.GPO", gpofci, true, true, false);
1638 JsonSaveTLVValue(root, "$.ApplicationData.AIP", tlvdb_find_full(gpofci, 0x82));
1639 JsonSaveTLVValue(root, "$.ApplicationData.AFL", tlvdb_find_full(gpofci, 0x94));
1641 tlvdb_free(gpofci);
1643 PrintAndLogEx(INFO, "-->Read records from AFL.");
1644 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
1646 while(AFL && AFL->len) {
1647 if (AFL->len % 4) {
1648 PrintAndLogEx(ERR, "Wrong AFL length: %d", AFL->len);
1649 break;
1652 json_t *sfijson = json_path_get(root, "$.Application.Records");
1653 if (!sfijson) {
1654 json_t *app = json_path_get(root, "$.Application");
1655 json_object_set_new(app, "Records", json_array());
1657 sfijson = json_path_get(root, "$.Application.Records");
1659 if (!json_is_array(sfijson)) {
1660 PrintAndLogEx(ERR, "Internal logic error. `$.Application.Records` is not an array.");
1661 break;
1663 for (int i = 0; i < AFL->len / 4; i++) {
1664 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
1665 uint8_t SFIstart = AFL->value[i * 4 + 1];
1666 uint8_t SFIend = AFL->value[i * 4 + 2];
1667 uint8_t SFIoffline = AFL->value[i * 4 + 3];
1669 PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
1670 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
1671 PrintAndLogEx(ERR, "SFI ERROR! Skipped...");
1672 continue;
1675 for(int n = SFIstart; n <= SFIend; n++) {
1676 PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n);
1678 res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
1679 if (res) {
1680 PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw);
1681 continue;
1684 if (decodeTLV) {
1685 TLVPrintFromBuffer(buf, len);
1686 PrintAndLogEx(NORMAL, "");
1689 json_t *jsonelm = json_object();
1690 json_array_append_new(sfijson, jsonelm);
1692 JsonSaveHex(jsonelm, "SFI", SFI, 1);
1693 JsonSaveHex(jsonelm, "RecordNum", n, 1);
1694 JsonSaveHex(jsonelm, "Offline", SFIoffline, 1);
1696 struct tlvdb *rsfi = tlvdb_parse_multi(buf, len);
1697 if (extractTLVElements)
1698 JsonSaveTLVTree(root, jsonelm, "$.Data", rsfi);
1699 else
1700 JsonSaveTLVTreeElm(jsonelm, "$.Data", rsfi, true, true, false);
1701 tlvdb_free(rsfi);
1705 break;
1708 // getting certificates
1709 if (tlvdb_get(tlvRoot, 0x90, NULL)) {
1710 PrintAndLogEx(INFO, "-->Recovering certificates.");
1711 PKISetStrictExecution(false);
1712 RecoveryCertificates(tlvRoot, root);
1713 PKISetStrictExecution(true);
1716 // free tlv object
1717 tlvdb_free(tlvRoot);
1719 DropFieldEx( channel );
1721 res = json_dump_file(root, fname, JSON_INDENT(2));
1722 if (res) {
1723 PrintAndLogEx(ERR, "Can't save the file: %s", fname);
1724 return 200;
1726 PrintAndLogEx(SUCCESS, "File `%s` saved.", fname);
1728 // free json object
1729 json_decref(root);
1731 return 0;
1734 int CmdEMVTest(const char *cmd) {
1735 return ExecuteCryptoTests(true);
1738 int CmdEMVRoca(const char *cmd) {
1739 uint8_t AID[APDU_DATA_LEN] = {0};
1740 size_t AIDlen = 0;
1741 uint8_t buf[APDU_RESPONSE_LEN] = {0};
1742 size_t len = 0;
1743 uint16_t sw = 0;
1744 int res;
1745 uint8_t ODAiList[4096];
1746 size_t ODAiListLen = 0;
1748 CLIParserInit("emv roca",
1749 "Tries to extract public keys and run the ROCA test against them.\n",
1750 "Usage:\n"
1751 "\temv roca -w -> select --CONTACT-- card and run test\n"
1752 "\temv roca -> select --CONTACTLESS-- card and run test\n"
1755 void* argtable[] = {
1756 arg_param_begin,
1757 arg_lit0("tT", "selftest", "self test"),
1758 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
1759 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
1760 arg_param_end
1762 CLIExecWithReturn(cmd, argtable, true);
1764 if (arg_get_lit(1))
1765 return roca_self_test();
1766 bool showAPDU = arg_get_lit(2);
1768 EMVCommandChannel channel = ECC_CONTACTLESS;
1769 #ifdef WITH_SMARTCARD
1770 if (arg_get_lit(3))
1771 channel = ECC_CONTACT;
1772 #endif
1773 PrintChannel(channel);
1774 CLIParserFree();
1776 // select card
1777 uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
1778 char *PSE_or_PPSE = psenum == 1 ? "PSE" : "PPSE";
1780 SetAPDULogging(showAPDU);
1782 // init applets list tree
1783 const char *al = "Applets list";
1784 struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
1786 // EMV PSE/PPSE
1787 PrintAndLogEx(NORMAL, "--> %s.", PSE_or_PPSE);
1788 res = EMVSearchPSE(channel, true, true, psenum, false, tlvSelect);
1790 // check PSE/PPSE and select application id
1791 if (!res) {
1792 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1793 } else {
1794 // EMV SEARCH with AID list
1795 PrintAndLogEx(NORMAL, "--> AID search.");
1796 if (EMVSearch(channel, false, true, false, tlvSelect)) {
1797 PrintAndLogEx(ERR, "Couldn't find any known EMV AID. Exit...");
1798 tlvdb_free(tlvSelect);
1799 DropFieldEx( channel );
1800 return 3;
1803 // check search and select application id
1804 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1807 // EMV SELECT application
1808 EMVSelectApplication(tlvSelect, AID, &AIDlen);
1810 tlvdb_free(tlvSelect);
1812 if (!AIDlen) {
1813 PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit...");
1814 DropFieldEx( channel );
1815 return 4;
1818 // Init TLV tree
1819 const char *alr = "Root terminal TLV tree";
1820 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
1822 // EMV SELECT applet
1823 PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen));
1824 res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
1826 if (res) {
1827 PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res);
1828 tlvdb_free(tlvRoot);
1829 DropFieldEx( channel );
1830 return 5;
1833 PrintAndLog("\n* Init transaction parameters.");
1834 InitTransactionParameters(tlvRoot, true, TT_QVSDCMCHIP, false);
1836 PrintAndLogEx(NORMAL, "-->Calc PDOL.");
1837 struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
1838 if (!pdol_data_tlv){
1839 PrintAndLogEx(ERR, "Can't create PDOL TLV.");
1840 tlvdb_free(tlvRoot);
1841 DropFieldEx( channel );
1842 return 6;
1845 size_t pdol_data_tlv_data_len;
1846 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
1847 if (!pdol_data_tlv_data) {
1848 PrintAndLogEx(ERR, "Can't create PDOL data.");
1849 tlvdb_free(tlvRoot);
1850 DropFieldEx( channel );
1851 return 6;
1853 PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
1855 PrintAndLogEx(INFO, "-->GPO.");
1856 res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
1858 free(pdol_data_tlv_data);
1859 free(pdol_data_tlv);
1861 if (res) {
1862 PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw);
1863 tlvdb_free(tlvRoot);
1864 DropFieldEx( channel );
1865 return 7;
1867 ProcessGPOResponseFormat1(tlvRoot, buf, len, false);
1869 PrintAndLogEx(INFO, "-->Read records from AFL.");
1870 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
1872 while(AFL && AFL->len) {
1873 if (AFL->len % 4) {
1874 PrintAndLogEx(ERR, "Wrong AFL length: %d", AFL->len);
1875 break;
1878 for (int i = 0; i < AFL->len / 4; i++) {
1879 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
1880 uint8_t SFIstart = AFL->value[i * 4 + 1];
1881 uint8_t SFIend = AFL->value[i * 4 + 2];
1882 uint8_t SFIoffline = AFL->value[i * 4 + 3];
1884 PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
1885 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
1886 PrintAndLogEx(ERR, "SFI ERROR! Skipped...");
1887 continue;
1890 for(int n = SFIstart; n <= SFIend; n++) {
1891 PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n);
1893 res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
1894 if (res) {
1895 PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw);
1896 continue;
1899 // Build Input list for Offline Data Authentication
1900 // EMV 4.3 book3 10.3, page 96
1901 if (SFIoffline > 0) {
1902 if (SFI < 11) {
1903 const unsigned char *abuf = buf;
1904 size_t elmlen = len;
1905 struct tlv e;
1906 if (tlv_parse_tl(&abuf, &elmlen, &e)) {
1907 memcpy(&ODAiList[ODAiListLen], &buf[len - elmlen], elmlen);
1908 ODAiListLen += elmlen;
1909 } else {
1910 PrintAndLogEx(WARNING, "Error SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI);
1912 } else {
1913 memcpy(&ODAiList[ODAiListLen], buf, len);
1914 ODAiListLen += len;
1917 SFIoffline--;
1922 break;
1925 // copy Input list for Offline Data Authentication
1926 if (ODAiListLen) {
1927 struct tlvdb *oda = tlvdb_fixed(0x21, ODAiListLen, ODAiList); // not a standard tag
1928 tlvdb_add(tlvRoot, oda);
1929 PrintAndLogEx(NORMAL, "* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen);
1932 // getting certificates
1933 if (tlvdb_get(tlvRoot, 0x90, NULL)) {
1934 PrintAndLogEx(INFO, "-->Recovering certificates.");
1935 PKISetStrictExecution(false);
1937 struct emv_pk *pk = get_ca_pk(tlvRoot);
1938 if (!pk) {
1939 PrintAndLogEx(ERR, "CA Public Key not found. Exit.");
1940 goto out;
1943 struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlvRoot);
1944 if (!issuer_pk) {
1945 emv_pk_free(pk);
1946 PrintAndLogEx(WARNING, "WARNING: Issuer certificate not found. Exit.");
1947 goto out;
1950 char RID[15] = {0};
1951 memcpy(RID, sprint_hex(issuer_pk->rid, 5), 14);
1952 PrintAndLogEx(SUCCESS, "Issuer Public Key recovered. RID %s IDX %02hhx CSN %s",
1953 RID,
1954 issuer_pk->index,
1955 sprint_hex(issuer_pk->serial, 3)
1958 const struct tlv *sda_tlv = tlvdb_get(tlvRoot, 0x21, NULL);
1959 struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlvRoot, sda_tlv);
1960 if (!icc_pk) {
1961 emv_pk_free(pk);
1962 emv_pk_free(issuer_pk);
1963 PrintAndLogEx(WARNING, "WARNING: ICC certificate not found. Exit.");
1964 goto out;
1967 memcpy(RID, sprint_hex(icc_pk->rid, 5), 14);
1968 PrintAndLogEx(SUCCESS, "ICC Public Key recovered. RID %s IDX %02hhx CSN %s\n",
1969 RID,
1970 icc_pk->index,
1971 sprint_hex(icc_pk->serial, 3)
1974 PrintAndLogEx(INFO, "ICC Public Key modulus: %s\n", sprint_hex_inrow(icc_pk->modulus, icc_pk->mlen));
1976 // icc_pk->exp, icc_pk->elen
1977 // icc_pk->modulus, icc_pk->mlen
1978 if (icc_pk->elen > 0 && icc_pk->mlen > 0) {
1979 if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen, false)) {
1980 PrintAndLogEx(INFO, "ICC Public Key is subject to ROCA vulnerability (it is NOT secure).");
1981 } else {
1982 PrintAndLogEx(INFO, "ICC Public Key is not subject to ROCA vulnerability (it is secure)");
1986 PKISetStrictExecution(true);
1989 out:
1991 // free tlv object
1992 tlvdb_free(tlvRoot);
1994 DropFieldEx( channel );
1995 return 0;
1998 int CmdHelp(const char *Cmd);
2000 static command_t CommandTable[] = {
2001 {"help", CmdHelp, 1, "This help"},
2002 {"exec", CmdEMVExec, 1, "Executes EMV contactless transaction."},
2003 {"pse", CmdEMVPPSE, 1, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."},
2004 {"search", CmdEMVSearch, 1, "Try to select all applets from applets list and print installed applets."},
2005 {"select", CmdEMVSelect, 1, "Select applet."},
2006 {"gpo", CmdEMVGPO, 1, "Execute GetProcessingOptions."},
2007 {"readrec", CmdEMVReadRecord, 1, "Read files from card."},
2008 {"genac", CmdEMVAC, 1, "Generate ApplicationCryptogram."},
2009 {"challenge", CmdEMVGenerateChallenge, 1, "Generate challenge."},
2010 {"intauth", CmdEMVInternalAuthenticate, 1, "Internal authentication."},
2011 {"scan", CmdEMVScan, 1, "Scan EMV card and save it contents to json file for emulator."},
2012 {"test", CmdEMVTest, 1, "Crypto logic test."},
2013 {"roca", CmdEMVRoca, 1, "Extract public keys and run ROCA test"},
2014 {NULL, NULL, 0, NULL}
2017 int CmdEMV(const char *Cmd) {
2018 CmdsParse(CommandTable, Cmd);
2019 return 0;
2022 int CmdHelp(const char *Cmd) {
2023 CmdsHelp(CommandTable);
2024 return 0;