1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2017, 2018 Merlok
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
7 //-----------------------------------------------------------------------------
9 //-----------------------------------------------------------------------------
14 #include "proxmark3.h"
15 #include "cmdparser.h"
20 #include "test/cryptotest.h"
21 #include "cliparser/cliparser.h"
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
47 int CmdEMVSelect(const char *cmd
) {
48 uint8_t data
[APDU_DATA_LEN
] = {0};
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");
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"),
62 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
64 arg_strx0(NULL
, NULL
, "<HEX applet AID>", NULL
),
67 CLIExecWithReturn(cmd
, argtable
, true);
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
;
76 channel
= ECC_CONTACT
;
77 CLIGetHexWithReturn(6, data
, &datalen
);
79 CLIGetHexWithReturn(5, data
, &datalen
);
83 SetAPDULogging(APDULogging
);
86 uint8_t buf
[APDU_RESPONSE_LEN
] = {0};
89 int res
= EMVSelect(channel
, activateField
, leaveSignalON
, data
, datalen
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
92 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
98 TLVPrintFromBuffer(buf
, len
);
103 int CmdEMVSearch(const char *cmd
) {
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");
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."),
120 CLIExecWithReturn(cmd
, argtable
, true);
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
129 channel
= ECC_CONTACT
;
133 SetAPDULogging(APDULogging
);
135 struct tlvdb
*t
= NULL
;
136 const char *al
= "Applets list";
137 t
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
139 if (EMVSearch(channel
, activateField
, leaveSignalON
, decodeTLV
, t
)) {
144 PrintAndLogEx(SUCCESS
, "Search completed.");
148 TLVPrintAIDlistFromSelectTLV(t
);
156 int CmdEMVPPSE(const char *cmd
) {
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");
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."),
175 CLIExecWithReturn(cmd
, argtable
, true);
177 bool activateField
= arg_get_lit(1);
178 bool leaveSignalON
= arg_get_lit(2);
184 bool APDULogging
= arg_get_lit(5);
185 bool decodeTLV
= arg_get_lit(6);
186 EMVCommandChannel channel
= ECC_CONTACTLESS
;
187 #ifdef WITH_SMARTCARD
189 channel
= ECC_CONTACT
;
193 SetAPDULogging(APDULogging
);
196 uint8_t buf
[APDU_RESPONSE_LEN
] = {0};
199 int res
= EMVSelectPSE(channel
, activateField
, leaveSignalON
, PSENum
, buf
, sizeof(buf
), &len
, &sw
);
202 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
209 TLVPrintFromBuffer(buf
, len
);
214 int CmdEMVGPO(const char *cmd
) {
215 uint8_t data
[APDU_RESPONSE_LEN
] = {0};
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");
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."),
234 arg_strx0(NULL
, NULL
, "<HEX PDOLdata/PDOL>", NULL
),
237 CLIExecWithReturn(cmd
, argtable
, true);
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
247 channel
= ECC_CONTACT
;
248 CLIGetHexWithReturn(7, data
, &datalen
);
250 CLIGetHexWithReturn(6, data
, &datalen
);
254 SetAPDULogging(APDULogging
);
257 const char *alr
= "Root terminal TLV tree";
258 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
261 struct tlv
*pdol_data_tlv
= NULL
;
262 struct tlv data_tlv
= {
265 .value
= (uint8_t *)data
,
267 if (dataMakeFromPDOL
) {
268 ParamLoadDefaults(tlvRoot
);
270 if (paramsLoadFromFile
) {
271 PrintAndLogEx(INFO
, "Params loading from file...");
272 ParamLoadFromJson(tlvRoot
);
275 pdol_data_tlv
= dol_process((const struct tlv
*)tlvdb_external(0x9f38, datalen
, data
), tlvRoot
, 0x83);
277 PrintAndLogEx(ERR
, "Can't create PDOL TLV.");
282 if (paramsLoadFromFile
) {
283 PrintAndLogEx(WARNING
, "Don't need to load parameters. Sending plain PDOL data...");
285 pdol_data_tlv
= &data_tlv
;
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.");
295 PrintAndLogEx(INFO
, "PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
298 uint8_t buf
[APDU_RESPONSE_LEN
] = {0};
301 int res
= EMVGPO(channel
, leaveSignalON
, pdol_data_tlv_data
, pdol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
303 if (pdol_data_tlv
!= &data_tlv
)
308 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
314 TLVPrintFromBuffer(buf
, len
);
319 int CmdEMVReadRecord(const char *cmd
) {
320 uint8_t data
[APDU_RESPONSE_LEN
] = {0};
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");
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
),
336 CLIExecWithReturn(cmd
, argtable
, true);
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
344 channel
= ECC_CONTACT
;
345 CLIGetHexWithReturn(5, data
, &datalen
);
347 CLIGetHexWithReturn(4, data
, &datalen
);
352 PrintAndLogEx(ERR
, "Command needs to have 2 bytes of data");
356 SetAPDULogging(APDULogging
);
359 uint8_t buf
[APDU_RESPONSE_LEN
] = {0};
362 int res
= EMVReadRecord(channel
, leaveSignalON
, data
[0], data
[1], buf
, sizeof(buf
), &len
, &sw
, NULL
);
365 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
372 TLVPrintFromBuffer(buf
, len
);
377 int CmdEMVAC(const char *cmd
) {
378 uint8_t data
[APDU_RESPONSE_LEN
] = {0};
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");
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."),
400 arg_strx1(NULL
, NULL
, "<HEX CDOLdata/CDOL>", NULL
),
403 CLIExecWithReturn(cmd
, argtable
, false);
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
;
416 if (termDecision
== 0xff) {
417 PrintAndLog("ERROR: can't find terminal decision '%s'", arg_get_str(3)->sval
[0]);
421 termDecision
= EMVAC_TC
;
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
432 channel
= ECC_CONTACT
;
433 CLIGetHexWithReturn(9, data
, &datalen
);
435 CLIGetHexWithReturn(8, data
, &datalen
);
439 SetAPDULogging(APDULogging
);
442 const char *alr
= "Root terminal TLV tree";
443 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
446 struct tlv
*cdol_data_tlv
= NULL
;
447 struct tlv data_tlv
= {
450 .value
= (uint8_t *)data
,
453 if (dataMakeFromCDOL
) {
454 ParamLoadDefaults(tlvRoot
);
456 if (paramsLoadFromFile
) {
457 PrintAndLogEx(INFO
, "Params loading from file...");
458 ParamLoadFromJson(tlvRoot
);
461 cdol_data_tlv
= dol_process((const struct tlv
*)tlvdb_external(0x8c, datalen
, data
), tlvRoot
, 0x01); // 0x01 - dummy tag
463 PrintAndLogEx(ERR
, "Can't create CDOL TLV.");
468 if (paramsLoadFromFile
) {
469 PrintAndLogEx(WARNING
, "Don't need to load parameters. Sending plain CDOL data...");
471 cdol_data_tlv
= &data_tlv
;
474 PrintAndLogEx(INFO
, "CDOL data[%d]: %s", cdol_data_tlv
->len
, sprint_hex(cdol_data_tlv
->value
, cdol_data_tlv
->len
));
477 uint8_t buf
[APDU_RESPONSE_LEN
] = {0};
480 int res
= EMVAC(channel
, leaveSignalON
, termDecision
, (uint8_t *)cdol_data_tlv
->value
, cdol_data_tlv
->len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
482 if (cdol_data_tlv
!= &data_tlv
)
487 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
493 TLVPrintFromBuffer(buf
, len
);
498 int CmdEMVGenerateChallenge(const char *cmd
) {
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");
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."),
513 CLIExecWithReturn(cmd
, argtable
, true);
515 bool leaveSignalON
= arg_get_lit(1);
516 bool APDULogging
= arg_get_lit(2);
517 EMVCommandChannel channel
= ECC_CONTACTLESS
;
518 #ifdef WITH_SMARTCARD
520 channel
= ECC_CONTACT
;
524 SetAPDULogging(APDULogging
);
527 uint8_t buf
[APDU_RESPONSE_LEN
] = {0};
530 int res
= EMVGenerateChallenge(channel
, leaveSignalON
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
533 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
538 PrintAndLogEx(SUCCESS
, "Challenge: %s", sprint_hex(buf
, len
));
540 if (len
!= 4 && len
!= 8)
541 PrintAndLogEx(WARNING
, "Length of challenge must be 4 or 8, but it %d", len
);
546 int CmdEMVInternalAuthenticate(const char *cmd
) {
547 uint8_t data
[APDU_RESPONSE_LEN
] = {0};
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.",
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");
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."),
569 arg_strx1(NULL
, NULL
, "<HEX DDOLdata/DDOL>", NULL
),
572 CLIExecWithReturn(cmd
, argtable
, false);
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
582 channel
= ECC_CONTACT
;
583 CLIGetHexWithReturn(7, data
, &datalen
);
585 CLIGetHexWithReturn(6, data
, &datalen
);
589 SetAPDULogging(APDULogging
);
592 const char *alr
= "Root terminal TLV tree";
593 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
596 struct tlv
*ddol_data_tlv
= NULL
;
597 struct tlv data_tlv
= {
600 .value
= (uint8_t *)data
,
603 if (dataMakeFromDDOL
) {
604 ParamLoadDefaults(tlvRoot
);
606 if (paramsLoadFromFile
) {
607 PrintAndLogEx(INFO
, "Params loading from file...");
608 ParamLoadFromJson(tlvRoot
);
611 ddol_data_tlv
= dol_process((const struct tlv
*)tlvdb_external(0x9f49, datalen
, data
), tlvRoot
, 0x01); // 0x01 - dummy tag
613 PrintAndLogEx(ERR
, "Can't create DDOL TLV.");
618 if (paramsLoadFromFile
) {
619 PrintAndLogEx(WARNING
, "Don't need to load parameters. Sending plain DDOL data...");
621 ddol_data_tlv
= &data_tlv
;
624 PrintAndLogEx(INFO
, "DDOL data[%d]: %s", ddol_data_tlv
->len
, sprint_hex(ddol_data_tlv
->value
, ddol_data_tlv
->len
));
627 uint8_t buf
[APDU_RESPONSE_LEN
] = {0};
630 int res
= EMVInternalAuthenticate(channel
, leaveSignalON
, data
, datalen
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
632 if (ddol_data_tlv
!= &data_tlv
)
637 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
643 TLVPrintFromBuffer(buf
, len
);
648 #define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;}
650 void InitTransactionParameters(struct tlvdb
*tlvRoot
, bool paramLoadJSON
, enum TransactionType TrType
, bool GenACGPO
) {
652 ParamLoadDefaults(tlvRoot
);
655 PrintAndLog("* * Transaction parameters loading from JSON...");
656 ParamLoadFromJson(tlvRoot
);
659 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
660 char *qVSDC
= "\x26\x00\x00\x00";
662 qVSDC
= "\x26\x80\x00\x00";
666 TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD
668 // not standard for contactless. just for test.
670 TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC
673 TLV_ADD(0x9F66, qVSDC
); // qVSDC
676 TLV_ADD(0x9F66, qVSDC
); // qVSDC (VISA CDA not enabled)
683 void ProcessGPOResponseFormat1(struct tlvdb
*tlvRoot
, uint8_t *buf
, size_t len
, bool decodeTLV
) {
684 if (buf
[0] == 0x80) {
686 PrintAndLog("GPO response format1:");
687 TLVPrintFromBuffer(buf
, len
);
690 if (len
< 4 || (len
- 4) % 4) {
691 PrintAndLogEx(ERR
, "GPO response format1 parsing error. length=%d", len
);
694 struct tlvdb
* f1AIP
= tlvdb_fixed(0x82, 2, buf
+ 2);
695 tlvdb_add(tlvRoot
, f1AIP
);
697 PrintAndLogEx(INFO
, "\n* * Decode response format 1 (0x80) AIP and AFL:");
698 TLVPrintFromTLV(f1AIP
);
702 struct tlvdb
* f1AFL
= tlvdb_fixed(0x94, len
- 4, buf
+ 2 + 2);
703 tlvdb_add(tlvRoot
, f1AFL
);
705 TLVPrintFromTLV(f1AFL
);
709 TLVPrintFromBuffer(buf
, len
);
713 int CmdEMVExec(const char *cmd
) {
714 uint8_t buf
[APDU_RESPONSE_LEN
] = {0};
717 uint8_t AID
[APDU_DATA_LEN
] = {0};
719 uint8_t ODAiList
[4096];
720 size_t ODAiListLen
= 0;
724 struct tlvdb
*tlvSelect
= NULL
;
725 struct tlvdb
*tlvRoot
= NULL
;
726 struct tlv
*pdol_data_tlv
= NULL
;
728 CLIParserInit("emv exec",
729 "Executes EMV contactless transaction",
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");
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."),
749 CLIExecWithReturn(cmd
, argtable
, true);
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);
757 enum TransactionType TrType
= TT_MSD
;
759 TrType
= TT_QVSDCMCHIP
;
765 bool GenACGPO
= arg_get_lit(10);
766 EMVCommandChannel channel
= ECC_CONTACTLESS
;
767 #ifdef WITH_SMARTCARD
769 channel
= ECC_CONTACT
;
771 uint8_t psenum
= (channel
== ECC_CONTACT
) ? 1 : 2;
772 char *PSE_or_PPSE
= psenum
== 1 ? "PSE" : "PPSE";
776 SetAPDULogging(showAPDU
);
778 // init applets list tree
779 const char *al
= "Applets list";
780 tlvSelect
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
782 // Application Selection
783 // https://www.openscdp.org/scripts/tutorial/emv/applicationselection.html
786 PrintAndLogEx(NORMAL
, "\n* %s.", PSE_or_PPSE
);
787 SetAPDULogging(showAPDU
);
788 res
= EMVSearchPSE(channel
, activateField
, true, psenum
, decodeTLV
, tlvSelect
);
790 // check PPSE / PSE and select application id
792 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
793 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
799 PrintAndLogEx(NORMAL
, "\n* Search AID in list.");
800 SetAPDULogging(false);
801 if (EMVSearch(channel
, activateField
, true, decodeTLV
, tlvSelect
)) {
805 // check search and select application id
806 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
807 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
811 const char *alr
= "Root terminal TLV tree";
812 tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
814 // check if we found EMV application on card
816 PrintAndLogEx(WARNING
, "Can't select AID. EMV AID not found");
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
);
826 PrintAndLogEx(WARNING
, "Can't select AID (%d). Exit...", res
);
831 TLVPrintFromBuffer(buf
, len
);
832 PrintAndLogEx(INFO
, "* Selected.");
834 PrintAndLogEx(INFO
, "\n* Init transaction parameters.");
835 InitTransactionParameters(tlvRoot
, paramLoadJSON
, TrType
, GenACGPO
);
836 TLVPrintFromTLV(tlvRoot
); // TODO delete!!!
838 PrintAndLogEx(NORMAL
, "\n* Calc PDOL.");
839 pdol_data_tlv
= dol_process(tlvdb_get(tlvRoot
, 0x9f38, NULL
), tlvRoot
, 0x83);
841 PrintAndLogEx(WARNING
, "Error: can't create PDOL TLV.");
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.");
851 PrintAndLogEx(NORMAL
, "PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
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
);
856 free(pdol_data_tlv_data
);
857 //free(pdol_data_tlv); --- free on exit.
860 PrintAndLogEx(NORMAL
, "GPO error(%d): %4x. Exit...", res
, sw
);
864 // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
865 ProcessGPOResponseFormat1(tlvRoot
, buf
, len
, decodeTLV
);
867 // extract PAN from track2
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
);
873 tlvdb_add(tlvRoot
, pan
);
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
));
878 PrintAndLogEx(NORMAL
, "\n* * WARNING: Can't extract PAN from track2.");
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.");
889 while(AFL
&& AFL
->len
) {
891 PrintAndLogEx(WARNING
, "Error: Wrong AFL length: %d", AFL
->len
);
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];
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...");
907 for(int n
= SFIstart
; n
<= SFIend
; n
++) {
908 PrintAndLogEx(NORMAL
, "* * * SFI[%02x] %d", SFI
, n
);
910 res
= EMVReadRecord(channel
, true, SFI
, n
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
912 PrintAndLogEx(WARNING
, "Error SFI[%02x]. APDU error %4x", SFI
, sw
);
917 TLVPrintFromBuffer(buf
, len
);
918 PrintAndLogEx(NORMAL
, "");
921 // Build Input list for Offline Data Authentication
922 // EMV 4.3 book3 10.3, page 96
925 const unsigned char *abuf
= buf
;
928 if (tlv_parse_tl(&abuf
, &elmlen
, &e
)) {
929 memcpy(&ODAiList
[ODAiListLen
], &buf
[len
- elmlen
], elmlen
);
930 ODAiListLen
+= elmlen
;
932 PrintAndLogEx(WARNING
, "Error SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI
);
935 memcpy(&ODAiList
[ODAiListLen
], buf
, len
);
945 // copy Input list for Offline Data Authentication
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
);
954 const struct tlv
*AIPtlv
= tlvdb_get(tlvRoot
, 0x82, NULL
);
956 AIP
= AIPtlv
->value
[0] + AIPtlv
->value
[1] * 0x100;
957 PrintAndLogEx(NORMAL
, "* * AIP=%04x", AIP
);
959 PrintAndLogEx(ERR
, "Can't found AIP.");
964 PrintAndLogEx(NORMAL
, "\n* SDA");
970 PrintAndLogEx(NORMAL
, "\n* DDA");
971 trDDA(channel
, decodeTLV
, tlvRoot
);
977 if (TrType
== TT_QVSDCMCHIP
|| TrType
== TT_CDA
){
978 // 9F26: Application Cryptogram
979 const struct tlv
*AC
= tlvdb_get(tlvRoot
, 0x9F26, NULL
);
981 PrintAndLogEx(NORMAL
, "\n--> qVSDC transaction.");
982 PrintAndLogEx(NORMAL
, "* AC path");
984 // 9F36: Application Transaction Counter (ATC)
985 const struct tlv
*ATC
= tlvdb_get(tlvRoot
, 0x9F36, NULL
);
988 // 9F10: Issuer Application Data - optional
989 const struct tlv
*IAD
= tlvdb_get(tlvRoot
, 0x9F10, NULL
);
992 PrintAndLogEx(NORMAL
, "ATC: %s", sprint_hex(ATC
->value
, ATC
->len
));
993 PrintAndLogEx(NORMAL
, "AC: %s", sprint_hex(AC
->value
, AC
->len
));
995 PrintAndLogEx(NORMAL
, "IAD: %s", sprint_hex(IAD
->value
, IAD
->len
));
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);
1005 PrintAndLogEx(WARNING
, "IAD not found.");
1009 PrintAndLogEx(ERR
, "AC: Application Transaction Counter (ATC) not found.");
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.");
1020 PrintAndLogEx(NORMAL
, "* * Generate challenge");
1021 res
= EMVGenerateChallenge(channel
, true, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1023 PrintAndLogEx(WARNING
, "GetChallenge. APDU error %4x", sw
);
1027 PrintAndLogEx(WARNING
, "GetChallenge. Wrong challenge length %d", len
);
1031 // ICC Dynamic Number
1032 struct tlvdb
* ICCDynN
= tlvdb_fixed(0x9f4c, len
, buf
);
1033 tlvdb_add(tlvRoot
, ICCDynN
);
1035 PrintAndLogEx(NORMAL
, "\n* * ICC Dynamic Number:");
1036 TLVPrintFromTLV(ICCDynN
);
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.");
1045 PrintAndLogEx(NORMAL
, "CDOL1 data[%d]: %s", cdol_data_tlv
->len
, sprint_hex(cdol_data_tlv
->value
, cdol_data_tlv
->len
));
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
);
1052 PrintAndLogEx(NORMAL
, "AC1 error(%d): %4x. Exit...", res
, sw
);
1057 TLVPrintFromBuffer(buf
, len
);
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
);
1064 PrintAndLogEx(NORMAL
, "CDA error (%d)", res
);
1067 free(cdol_data_tlv
);
1069 PrintAndLogEx(NORMAL
, "\n* M/Chip transaction result:");
1070 // 9F27: Cryptogram Information Data (CID)
1071 const struct tlv
*CID
= tlvdb_get(tlvRoot
, 0x9F27, NULL
);
1073 emv_tag_dump(CID
, stdout
, 0);
1074 PrintAndLogEx(NORMAL
, "------------------------------");
1076 switch(CID
->value
[0] & EMVAC_AC_MASK
){
1078 PrintAndLogEx(NORMAL
, "Transaction DECLINED.");
1081 PrintAndLogEx(NORMAL
, "Transaction approved OFFLINE.");
1084 PrintAndLogEx(NORMAL
, "Transaction approved ONLINE.");
1087 PrintAndLogEx(WARNING
, "Error: CID transaction code error %2x", CID
->value
[0] & EMVAC_AC_MASK
);
1091 PrintAndLogEx(WARNING
, "Wrong CID length %d", CID
->len
);
1094 PrintAndLogEx(WARNING
, "CID(9F27) not found.");
1101 if (AIP
& 0x8000 && TrType
== TT_MSD
) {
1102 PrintAndLogEx(NORMAL
, "\n--> MSD transaction.");
1104 PrintAndLogEx(NORMAL
, "* MSD dCVV path. Check dCVV");
1106 const struct tlv
*track2
= tlvdb_get(tlvRoot
, 0x57, NULL
);
1108 PrintAndLogEx(NORMAL
, "Track2: %s", sprint_hex(track2
->value
, track2
->len
));
1110 struct tlvdb
*dCVV
= GetdCVVRawFromTrack2(track2
);
1111 PrintAndLogEx(NORMAL
, "dCVV raw data:");
1112 TLVPrintFromTLV(dCVV
);
1114 if (GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
) {
1115 PrintAndLogEx(NORMAL
, "\n* Mastercard calculate UDOL");
1118 const struct tlv
*UDOL
= tlvdb_get(tlvRoot
, 0x9F69, NULL
);
1119 // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
1120 const struct tlv defUDOL
= {
1123 .value
= (uint8_t *)"\x9f\x6a\x04",
1126 PrintAndLogEx(NORMAL
, "Use default UDOL.");
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.");
1134 PrintAndLogEx(NORMAL
, "UDOL data[%d]: %s", udol_data_tlv
->len
, sprint_hex(udol_data_tlv
->value
, udol_data_tlv
->len
));
1136 PrintAndLogEx(NORMAL
, "\n* Mastercard compute cryptographic checksum(UDOL)");
1138 res
= MSCComputeCryptoChecksum(channel
, true, (uint8_t *)udol_data_tlv
->value
, udol_data_tlv
->len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1140 PrintAndLogEx(WARNING
, "Compute Crypto Checksum. APDU error %4x", sw
);
1141 free(udol_data_tlv
);
1145 // Mastercard compute cryptographic checksum result
1146 TLVPrintFromBuffer(buf
, len
);
1147 PrintAndLogEx(NORMAL
, "");
1149 free(udol_data_tlv
);
1153 PrintAndLogEx(WARNING
, "MSD: Track2 data not found.");
1157 if (channel
== ECC_CONTACTLESS
) {
1162 free(pdol_data_tlv
);
1163 tlvdb_free(tlvSelect
);
1164 tlvdb_free(tlvRoot
);
1166 PrintAndLogEx(NORMAL
, "\n* Transaction completed.");
1170 int CmdEMVScan(const char *cmd
) {
1171 uint8_t AID
[APDU_DATA_LEN
] = {0};
1173 uint8_t buf
[APDU_RESPONSE_LEN
] = {0};
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");
1186 void* argtable
[] = {
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."),
1201 arg_str1(NULL
, NULL
, "output.json", "JSON output file name"),
1204 CLIExecWithReturn(cmd
, argtable
, true);
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);
1211 enum TransactionType TrType
= TT_MSD
;
1213 TrType
= TT_QVSDCMCHIP
;
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
;
1229 CLIGetStrWithReturn(12, relfname
, &relfnamelen
);
1231 CLIGetStrWithReturn(11, relfname
, &relfnamelen
);
1233 uint8_t psenum
= (channel
== ECC_CONTACT
) ? 1 : 2;
1236 SetAPDULogging(showAPDU
);
1239 if (channel
== ECC_CONTACT
) {
1240 PrintAndLogEx(ERR
, "Do not use contact interface. Exit.");
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
);
1252 root
= json_load_file(fname
, 0, &error
);
1254 PrintAndLogEx(ERR
, "json error on line %d: %s", error
.line
, error
.text
);
1258 if (!json_is_object(root
)) {
1259 PrintAndLogEx(ERR
, "Invalid json format. root must be an object.");
1263 root
= json_object();
1266 // drop field at start
1267 if (channel
== ECC_CONTACTLESS
) {
1272 PrintAndLogEx(NORMAL
, "--> GET UID, ATS.");
1274 iso14a_card_select_t card
;
1275 if (Hf14443_4aGetCardData(&card
)) {
1279 JsonSaveStr(root
, "$.File.Created", "proxmark3 `emv scan`");
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
);
1287 // init applets list tree
1288 const char *al
= "Applets list";
1289 struct tlvdb
*tlvSelect
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
1292 PrintAndLogEx(NORMAL
, "--> PPSE.");
1293 res
= EMVSelectPSE(channel
, true, true, 2, buf
, sizeof(buf
), &len
, &sw
);
1295 if (!res
&& sw
== 0x9000){
1297 TLVPrintFromBuffer(buf
, len
);
1299 JsonSaveBufAsHex(root
, "$.PPSE.AID", (uint8_t *)"2PAY.SYS.DDF01", 14);
1301 struct tlvdb
*fci
= tlvdb_parse_multi(buf
, len
);
1302 if (extractTLVElements
)
1303 JsonSaveTLVTree(root
, root
, "$.PPSE.FCITemplate", fci
);
1305 JsonSaveTLVTreeElm(root
, "$.PPSE.FCITemplate", fci
, true, true, false);
1306 JsonSaveTLVValue(root
, "$.Application.KernelID", tlvdb_find_full(fci
, 0x9f2a));
1310 res
= EMVSearchPSE(channel
, false, true, psenum
, decodeTLV
, tlvSelect
);
1312 // check PPSE and select application id
1314 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
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
);
1326 // check search and select application id
1327 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
1330 // EMV SELECT application
1331 SetAPDULogging(showAPDU
);
1332 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
1334 tlvdb_free(tlvSelect
);
1337 PrintAndLogEx(INFO
, "Can't select AID. EMV AID not found. Exit...");
1338 if (channel
== ECC_CONTACTLESS
) {
1344 JsonSaveBufAsHex(root
, "$.Application.AID", AID
, AIDlen
);
1347 const char *alr
= "Root terminal TLV tree";
1348 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
1350 // EMV SELECT applet
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
);
1357 PrintAndLogEx(ERR
, "Can't select AID (%d). Exit...", res
);
1358 tlvdb_free(tlvRoot
);
1364 TLVPrintFromBuffer(buf
, len
);
1367 if (tlvdb_get(tlvRoot
, 0x9f38, NULL
)) {
1368 JsonSaveStr(root
, "$.Application.Mode", TransactionTypeStr
[TrType
]);
1371 struct tlvdb
*fci
= tlvdb_parse_multi(buf
, len
);
1372 if (extractTLVElements
)
1373 JsonSaveTLVTree(root
, root
, "$.Application.FCITemplate", fci
);
1375 JsonSaveTLVTreeElm(root
, "$.Application.FCITemplate", fci
, true, true, false);
1378 // create transaction parameters
1379 PrintAndLogEx(NORMAL
, "-->Init transaction parameters.");
1380 InitTransactionParameters(tlvRoot
, paramLoadJSON
, TrType
, GenACGPO
);
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
) {
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
);
1401 PrintAndLogEx(INFO
, "PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
1403 PrintAndLogEx(INFO
, "-->GPO.");
1404 res
= EMVGPO(channel
, true, pdol_data_tlv_data
, pdol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1406 free(pdol_data_tlv_data
);
1407 free(pdol_data_tlv
);
1410 PrintAndLogEx(ERR
, "GPO error(%d): %4x. Exit...", res
, sw
);
1411 tlvdb_free(tlvRoot
);
1412 if (channel
== ECC_CONTACTLESS
) {
1417 ProcessGPOResponseFormat1(tlvRoot
, buf
, len
, decodeTLV
);
1419 struct tlvdb
*gpofci
= tlvdb_parse_multi(buf
, len
);
1420 if (extractTLVElements
)
1421 JsonSaveTLVTree(root
, root
, "$.Application.GPO", gpofci
);
1423 JsonSaveTLVTreeElm(root
, "$.Application.GPO", gpofci
, true, true, false);
1425 JsonSaveTLVValue(root
, "$.ApplicationData.AIP", tlvdb_find_full(gpofci
, 0x82));
1426 JsonSaveTLVValue(root
, "$.ApplicationData.AFL", tlvdb_find_full(gpofci
, 0x94));
1430 PrintAndLogEx(INFO
, "-->Read records from AFL.");
1431 const struct tlv
*AFL
= tlvdb_get(tlvRoot
, 0x94, NULL
);
1433 while(AFL
&& AFL
->len
) {
1435 PrintAndLogEx(ERR
, "Wrong AFL length: %d", AFL
->len
);
1439 json_t
*sfijson
= json_path_get(root
, "$.Application.Records");
1441 json_t
*app
= json_path_get(root
, "$.Application");
1442 json_object_set_new(app
, "Records", json_array());
1444 sfijson
= json_path_get(root
, "$.Application.Records");
1446 if (!json_is_array(sfijson
)) {
1447 PrintAndLogEx(ERR
, "Internal logic error. `$.Application.Records` is not an array.");
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];
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...");
1462 for(int n
= SFIstart
; n
<= SFIend
; n
++) {
1463 PrintAndLogEx(INFO
, "---->SFI[%02x] %d", SFI
, n
);
1465 res
= EMVReadRecord(channel
, true, SFI
, n
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1467 PrintAndLogEx(ERR
, "SFI[%02x]. APDU error %4x", SFI
, sw
);
1472 TLVPrintFromBuffer(buf
, len
);
1473 PrintAndLogEx(NORMAL
, "");
1476 json_t
*jsonelm
= json_object();
1477 json_array_append_new(sfijson
, jsonelm
);
1479 JsonSaveHex(jsonelm
, "SFI", SFI
, 1);
1480 JsonSaveHex(jsonelm
, "RecordNum", n
, 1);
1481 JsonSaveHex(jsonelm
, "Offline", SFIoffline
, 1);
1483 struct tlvdb
*rsfi
= tlvdb_parse_multi(buf
, len
);
1484 if (extractTLVElements
)
1485 JsonSaveTLVTree(root
, jsonelm
, "$.Data", rsfi
);
1487 JsonSaveTLVTreeElm(jsonelm
, "$.Data", rsfi
, true, true, false);
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);
1504 tlvdb_free(tlvRoot
);
1506 if (channel
== ECC_CONTACTLESS
) {
1510 res
= json_dump_file(root
, fname
, JSON_INDENT(2));
1512 PrintAndLogEx(ERR
, "Can't save the file: %s", fname
);
1515 PrintAndLogEx(SUCCESS
, "File `%s` saved.", fname
);
1523 int CmdEMVTest(const char *cmd
) {
1524 return ExecuteCryptoTests(true);
1527 int CmdEMVRoca(const char *cmd
) {
1528 uint8_t AID
[APDU_DATA_LEN
] = {0};
1530 uint8_t buf
[APDU_RESPONSE_LEN
] = {0};
1535 CLIParserInit("emv roca",
1536 "Tries to extract public keys and run the ROCA test against them.\n",
1538 "\temv roca -w -> select CONTACT card and run test\n\temv roca -> select CONTACTLESS card and run test\n");
1540 void* argtable
[] = {
1542 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
1545 CLIExecWithReturn(cmd
, argtable
, true);
1547 EMVCommandChannel channel
= ECC_CONTACTLESS
;
1549 channel
= ECC_CONTACT
;
1552 uint8_t psenum
= (channel
== ECC_CONTACT
) ? 1 : 2;
1554 SetAPDULogging(false);
1556 // init applets list tree
1557 const char *al
= "Applets list";
1558 struct tlvdb
*tlvSelect
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
1561 PrintAndLogEx(NORMAL
, "--> PPSE.");
1562 res
= EMVSearchPSE(channel
, false, true, psenum
, false, tlvSelect
);
1564 // check PPSE and select application id
1566 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
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
);
1577 // check search and select application id
1578 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
1581 // EMV SELECT application
1582 SetAPDULogging(false);
1583 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
1585 tlvdb_free(tlvSelect
);
1588 PrintAndLogEx(INFO
, "Can't select AID. EMV AID not found. Exit...");
1589 if (channel
== ECC_CONTACTLESS
) {
1596 const char *alr
= "Root terminal TLV tree";
1597 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
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
);
1604 PrintAndLogEx(ERR
, "Can't select AID (%d). Exit...", res
);
1605 tlvdb_free(tlvRoot
);
1606 if (channel
== ECC_CONTACTLESS
) {
1612 PrintAndLog("\n* Init transaction parameters.");
1613 InitTransactionParameters(tlvRoot
, true, TT_QVSDCMCHIP
, false);
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
) {
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
);
1634 PrintAndLogEx(INFO
, "PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
1636 PrintAndLogEx(INFO
, "-->GPO.");
1637 res
= EMVGPO(channel
, true, pdol_data_tlv_data
, pdol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1639 free(pdol_data_tlv_data
);
1640 free(pdol_data_tlv
);
1643 PrintAndLogEx(ERR
, "GPO error(%d): %4x. Exit...", res
, sw
);
1644 tlvdb_free(tlvRoot
);
1645 if (channel
== ECC_CONTACTLESS
) {
1650 ProcessGPOResponseFormat1(tlvRoot
, buf
, len
, false);
1652 PrintAndLogEx(INFO
, "-->Read records from AFL.");
1653 const struct tlv
*AFL
= tlvdb_get(tlvRoot
, 0x94, NULL
);
1655 while(AFL
&& AFL
->len
) {
1657 PrintAndLogEx(ERR
, "Wrong AFL length: %d", AFL
->len
);
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];
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...");
1673 for(int n
= SFIstart
; n
<= SFIend
; n
++) {
1674 PrintAndLogEx(INFO
, "---->SFI[%02x] %d", SFI
, n
);
1676 res
= EMVReadRecord(channel
, true, SFI
, n
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1678 PrintAndLogEx(ERR
, "SFI[%02x]. APDU error %4x", SFI
, sw
);
1687 // getting certificates
1688 if (tlvdb_get(tlvRoot
, 0x90, NULL
)) {
1689 PrintAndLogEx(INFO
, "-->Recovering certificates.");
1690 PKISetStrictExecution(false);
1692 struct emv_pk
*pk
= get_ca_pk(tlvRoot
);
1694 PrintAndLogEx(ERR
, "ERROR: Key not found. Exit.");
1698 struct emv_pk
*issuer_pk
= emv_pki_recover_issuer_cert(pk
, tlvRoot
);
1701 PrintAndLogEx(WARNING
, "WARNING: Issuer certificate not found. Exit.");
1705 PrintAndLogEx(SUCCESS
, "Issuer PK recovered. RID %s IDX %02hhx CSN %s",
1706 sprint_hex(issuer_pk
->rid
, 5),
1708 sprint_hex(issuer_pk
->serial
, 3)
1712 struct emv_pk
*icc_pk
= emv_pki_recover_icc_cert(issuer_pk
, tlvRoot
, NULL
);
1715 emv_pk_free(issuer_pk
);
1716 PrintAndLogEx(WARNING
, "WARNING: ICC certificate not found. Exit.");
1719 PrintAndLogEx(SUCCESS
, "ICC PK recovered. RID %s IDX %02hhx CSN %s\n",
1720 sprint_hex(icc_pk
->rid
, 5),
1722 sprint_hex(icc_pk
->serial
, 3)
1725 PrintAndLogEx(INFO
, "ICC pk modulus: %s", sprint_hex_inrow(icc_pk
->modulus
, icc_pk
->mlen
));
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..");
1733 PrintAndLogEx(INFO
, "ICC pk is OK(");
1737 PKISetStrictExecution(true);
1743 tlvdb_free(tlvRoot
);
1745 if (channel
== ECC_CONTACTLESS
) {
1752 int CmdHelp(const char *Cmd
);
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
}
1771 int CmdEMV(const char *Cmd
) {
1772 CmdsParse(CommandTable
, Cmd
);
1776 int CmdHelp(const char *Cmd
) {
1777 CmdsHelp(CommandTable
);