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 //-----------------------------------------------------------------------------
16 #include "test/cryptotest.h"
17 #include "cliparser/cliparser.h"
20 #define TLV_ADD(tag, value)( tlvdb_change_or_add_node(tlvRoot, tag, sizeof(value) - 1, (const unsigned char *)value) )
21 void ParamLoadDefaults(struct tlvdb
*tlvRoot
) {
22 //9F02:(Amount, authorized (Numeric)) len:6
23 TLV_ADD(0x9F02, "\x00\x00\x00\x00\x01\x00");
24 //9F1A:(Terminal Country Code) len:2
25 TLV_ADD(0x9F1A, "ru");
26 //5F2A:(Transaction Currency Code) len:2
27 // USD 840, EUR 978, RUR 810, RUB 643, RUR 810(old), UAH 980, AZN 031, n/a 999
28 TLV_ADD(0x5F2A, "\x09\x80");
29 //9A:(Transaction Date) len:3
30 TLV_ADD(0x9A, "\x00\x00\x00");
31 //9C:(Transaction Type) len:1 | 00 => Goods and service #01 => Cash
32 TLV_ADD(0x9C, "\x00");
33 // 9F37 Unpredictable Number len:4
34 TLV_ADD(0x9F37, "\x01\x02\x03\x04");
35 // 9F6A Unpredictable Number (MSD for UDOL) len:4
36 TLV_ADD(0x9F6A, "\x01\x02\x03\x04");
37 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
38 TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC
41 int CmdEMVSelect(const char *cmd
) {
42 uint8_t data
[APDU_AID_LEN
] = {0};
45 CLIParserInit("emv select",
46 "Executes select applet command",
47 "Usage:\n\temv select -s a00000000101 -> select card, select applet\n\temv select -st a00000000101 -> select card, select applet, show result in TLV\n");
51 arg_lit0("sS", "select", "activate field and select card"),
52 arg_lit0("kK", "keep", "keep field for next command"),
53 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
54 arg_lit0("tT", "tlv", "TLV decode results"),
56 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
58 arg_strx0(NULL
, NULL
, "<HEX applet AID>", NULL
),
61 CLIExecWithReturn(cmd
, argtable
, true);
63 bool activateField
= arg_get_lit(1);
64 bool leaveSignalON
= arg_get_lit(2);
65 bool APDULogging
= arg_get_lit(3);
66 bool decodeTLV
= arg_get_lit(4);
67 EMVCommandChannel channel
= ECC_CONTACTLESS
;
70 channel
= ECC_CONTACT
;
71 CLIGetHexWithReturn(6, data
, &datalen
);
73 CLIGetHexWithReturn(5, data
, &datalen
);
77 SetAPDULogging(APDULogging
);
80 uint8_t buf
[APDU_RES_LEN
] = {0};
83 int res
= EMVSelect(channel
, activateField
, leaveSignalON
, data
, datalen
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
86 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
92 TLVPrintFromBuffer(buf
, len
);
97 int CmdEMVSearch(const char *cmd
) {
99 CLIParserInit("emv search",
100 "Tries to select all applets from applet list:\n",
101 "Usage:\n\temv search -s -> select card and search\n\temv search -st -> select card, search and show result in TLV\n");
105 arg_lit0("sS", "select", "activate field and select card"),
106 arg_lit0("kK", "keep", "keep field ON for next command"),
107 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
108 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
109 #ifdef WITH_SMARTCARD
110 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
114 CLIExecWithReturn(cmd
, argtable
, true);
116 bool activateField
= arg_get_lit(1);
117 bool leaveSignalON
= arg_get_lit(2);
118 bool APDULogging
= arg_get_lit(3);
119 bool decodeTLV
= arg_get_lit(4);
120 EMVCommandChannel channel
= ECC_CONTACTLESS
;
121 #ifdef WITH_SMARTCARD
123 channel
= ECC_CONTACT
;
127 SetAPDULogging(APDULogging
);
129 struct tlvdb
*t
= NULL
;
130 const char *al
= "Applets list";
131 t
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
133 if (EMVSearch(channel
, activateField
, leaveSignalON
, decodeTLV
, t
)) {
138 PrintAndLogEx(SUCCESS
, "Search completed.");
142 TLVPrintAIDlistFromSelectTLV(t
);
150 int CmdEMVPPSE(const char *cmd
) {
152 CLIParserInit("emv pse",
153 "Executes PSE/PPSE select command. It returns list of applet on the card:\n",
154 "Usage:\n\temv pse -s1 -> select, get pse\n\temv pse -st2 -> select, get ppse, show result in TLV\n");
158 arg_lit0("sS", "select", "activate field and select card"),
159 arg_lit0("kK", "keep", "keep field ON for next command"),
160 arg_lit0("1", "pse", "pse (1PAY.SYS.DDF01) mode"),
161 arg_lit0("2", "ppse", "ppse (2PAY.SYS.DDF01) mode (default mode)"),
162 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
163 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
164 #ifdef WITH_SMARTCARD
165 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
169 CLIExecWithReturn(cmd
, argtable
, true);
171 bool activateField
= arg_get_lit(1);
172 bool leaveSignalON
= arg_get_lit(2);
178 bool APDULogging
= arg_get_lit(5);
179 bool decodeTLV
= arg_get_lit(6);
180 EMVCommandChannel channel
= ECC_CONTACTLESS
;
181 #ifdef WITH_SMARTCARD
183 channel
= ECC_CONTACT
;
187 SetAPDULogging(APDULogging
);
190 uint8_t buf
[APDU_RES_LEN
] = {0};
193 int res
= EMVSelectPSE(channel
, activateField
, leaveSignalON
, PSENum
, buf
, sizeof(buf
), &len
, &sw
);
196 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
203 TLVPrintFromBuffer(buf
, len
);
208 int CmdEMVGPO(const char *cmd
) {
209 uint8_t data
[APDU_RES_LEN
] = {0};
212 CLIParserInit("emv gpo",
213 "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.",
214 "Usage:\n\temv gpo -k -> execute GPO\n"
215 "\temv gpo -t 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n"
216 "\temv gpo -pmt 9F 37 04 -> load params from file, make PDOL data from PDOL, execute GPO with PDOL, show result in TLV\n");
220 arg_lit0("kK", "keep", "keep field ON for next command"),
221 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for PDOLdata making from PDOL and parameters"),
222 arg_lit0("mM", "make", "make PDOLdata from PDOL (tag 9F38) and parameters (by default uses default parameters)"),
223 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
224 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
225 #ifdef WITH_SMARTCARD
226 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
228 arg_strx0(NULL
, NULL
, "<HEX PDOLdata/PDOL>", NULL
),
231 CLIExecWithReturn(cmd
, argtable
, true);
233 bool leaveSignalON
= arg_get_lit(1);
234 bool paramsLoadFromFile
= arg_get_lit(2);
235 bool dataMakeFromPDOL
= arg_get_lit(3);
236 bool APDULogging
= arg_get_lit(4);
237 bool decodeTLV
= arg_get_lit(5);
238 EMVCommandChannel channel
= ECC_CONTACTLESS
;
239 #ifdef WITH_SMARTCARD
241 channel
= ECC_CONTACT
;
242 CLIGetHexWithReturn(7, data
, &datalen
);
244 CLIGetHexWithReturn(6, data
, &datalen
);
248 SetAPDULogging(APDULogging
);
251 const char *alr
= "Root terminal TLV tree";
252 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
255 struct tlv
*pdol_data_tlv
= NULL
;
256 struct tlv data_tlv
= {
259 .value
= (uint8_t *)data
,
261 if (dataMakeFromPDOL
) {
262 ParamLoadDefaults(tlvRoot
);
264 if (paramsLoadFromFile
) {
265 PrintAndLogEx(INFO
, "Params loading from file...");
266 ParamLoadFromJson(tlvRoot
);
269 pdol_data_tlv
= dol_process((const struct tlv
*)tlvdb_external(0x9f38, datalen
, data
), tlvRoot
, 0x83);
271 PrintAndLogEx(ERR
, "Can't create PDOL TLV.");
276 if (paramsLoadFromFile
) {
277 PrintAndLogEx(WARNING
, "Don't need to load parameters. Sending plain PDOL data...");
279 pdol_data_tlv
= &data_tlv
;
282 size_t pdol_data_tlv_data_len
= 0;
283 unsigned char *pdol_data_tlv_data
= tlv_encode(pdol_data_tlv
, &pdol_data_tlv_data_len
);
284 if (!pdol_data_tlv_data
) {
285 PrintAndLogEx(ERR
, "Can't create PDOL data.");
289 PrintAndLogEx(INFO
, "PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
292 uint8_t buf
[APDU_RES_LEN
] = {0};
295 int res
= EMVGPO(channel
, leaveSignalON
, pdol_data_tlv_data
, pdol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
297 if (pdol_data_tlv
!= &data_tlv
)
302 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
308 TLVPrintFromBuffer(buf
, len
);
313 int CmdEMVReadRecord(const char *cmd
) {
314 uint8_t data
[APDU_RES_LEN
] = {0};
317 CLIParserInit("emv readrec",
318 "Executes Read Record command. It returns data in TLV format.\nNeeds a bank applet to be selected and sometimes needs GPO to be executed.",
319 "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");
323 arg_lit0("kK", "keep", "keep field ON for next command"),
324 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
325 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
326 #ifdef WITH_SMARTCARD
327 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
329 arg_strx1(NULL
, NULL
, "<SFI 1byte HEX><SFIrec 1byte HEX>", NULL
),
332 CLIExecWithReturn(cmd
, argtable
, true);
334 bool leaveSignalON
= arg_get_lit(1);
335 bool APDULogging
= arg_get_lit(2);
336 bool decodeTLV
= arg_get_lit(3);
337 EMVCommandChannel channel
= ECC_CONTACTLESS
;
338 #ifdef WITH_SMARTCARD
340 channel
= ECC_CONTACT
;
341 CLIGetHexWithReturn(5, data
, &datalen
);
343 CLIGetHexWithReturn(4, data
, &datalen
);
348 PrintAndLogEx(ERROR
, "Command needs to have 2 bytes of data");
352 SetAPDULogging(APDULogging
);
355 uint8_t buf
[APDU_RES_LEN
] = {0};
358 int res
= EMVReadRecord(channel
, leaveSignalON
, data
[0], data
[1], buf
, sizeof(buf
), &len
, &sw
, NULL
);
361 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
368 TLVPrintFromBuffer(buf
, len
);
373 int CmdEMVAC(const char *cmd
) {
374 uint8_t data
[APDU_RES_LEN
] = {0};
377 CLIParserInit("emv genac",
378 "Generate Application Cryptogram command. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.",
379 "Usage:\n\temv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n"
380 "\temv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n"
381 "\temv genac -Daac 01020304 -> generate AC with 4-byte CDOL data and terminal decision 'declined'\n"
382 "\temv genac -pmt 9F 37 04 -> load params from file, make CDOL data from CDOL, generate AC with CDOL, show result in TLV");
386 arg_lit0("kK", "keep", "keep field ON for next command"),
387 arg_lit0("cC", "cda", "executes CDA transaction. Needs to get SDAD in results."),
388 arg_str0("dD", "decision", "<aac|tc|arqc>", "Terminal decision. aac - declined, tc - approved, arqc - online authorisation requested"),
389 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for CDOLdata making from CDOL and parameters"),
390 arg_lit0("mM", "make", "make CDOLdata from CDOL (tag 8C and 8D) and parameters (by default uses default parameters)"),
391 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
392 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
393 #ifdef WITH_SMARTCARD
394 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
396 arg_strx1(NULL
, NULL
, "<HEX CDOLdata/CDOL>", NULL
),
399 CLIExecWithReturn(cmd
, argtable
, false);
401 bool leaveSignalON
= arg_get_lit(1);
402 bool trTypeCDA
= arg_get_lit(2);
403 uint8_t termDecision
= 0xff;
404 if (arg_get_str_len(3)) {
405 if (!strncmp(arg_get_str(3)->sval
[0], "aac", 4))
406 termDecision
= EMVAC_AAC
;
407 if (!strncmp(arg_get_str(3)->sval
[0], "tc", 4))
408 termDecision
= EMVAC_TC
;
409 if (!strncmp(arg_get_str(3)->sval
[0], "arqc", 4))
410 termDecision
= EMVAC_ARQC
;
412 if (termDecision
== 0xff) {
413 PrintAndLog("ERROR: can't find terminal decision '%s'", arg_get_str(3)->sval
[0]);
417 termDecision
= EMVAC_TC
;
420 termDecision
= termDecision
| EMVAC_CDAREQ
;
421 bool paramsLoadFromFile
= arg_get_lit(4);
422 bool dataMakeFromCDOL
= arg_get_lit(5);
423 bool APDULogging
= arg_get_lit(6);
424 bool decodeTLV
= arg_get_lit(7);
425 EMVCommandChannel channel
= ECC_CONTACTLESS
;
426 #ifdef WITH_SMARTCARD
428 channel
= ECC_CONTACT
;
429 CLIGetHexWithReturn(9, data
, &datalen
);
431 CLIGetHexWithReturn(8, data
, &datalen
);
435 SetAPDULogging(APDULogging
);
438 const char *alr
= "Root terminal TLV tree";
439 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
442 struct tlv
*cdol_data_tlv
= NULL
;
443 struct tlv data_tlv
= {
446 .value
= (uint8_t *)data
,
449 if (dataMakeFromCDOL
) {
450 ParamLoadDefaults(tlvRoot
);
452 if (paramsLoadFromFile
) {
453 PrintAndLogEx(INFO
, "Params loading from file...");
454 ParamLoadFromJson(tlvRoot
);
457 cdol_data_tlv
= dol_process((const struct tlv
*)tlvdb_external(0x8c, datalen
, data
), tlvRoot
, 0x01); // 0x01 - dummy tag
459 PrintAndLogEx(ERR
, "Can't create CDOL TLV.");
464 if (paramsLoadFromFile
) {
465 PrintAndLogEx(WARNING
, "Don't need to load parameters. Sending plain CDOL data...");
467 cdol_data_tlv
= &data_tlv
;
470 PrintAndLogEx(INFO
, "CDOL data[%d]: %s", cdol_data_tlv
->len
, sprint_hex(cdol_data_tlv
->value
, cdol_data_tlv
->len
));
473 uint8_t buf
[APDU_RES_LEN
] = {0};
476 int res
= EMVAC(channel
, leaveSignalON
, termDecision
, (uint8_t *)cdol_data_tlv
->value
, cdol_data_tlv
->len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
478 if (cdol_data_tlv
!= &data_tlv
)
483 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
489 TLVPrintFromBuffer(buf
, len
);
494 int CmdEMVGenerateChallenge(const char *cmd
) {
496 CLIParserInit("emv challenge",
497 "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.",
498 "Usage:\n\temv challenge -> get challenge\n\temv challenge -k -> get challenge, keep fileld ON\n");
502 arg_lit0("kK", "keep", "keep field ON for next command"),
503 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
504 #ifdef WITH_SMARTCARD
505 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
509 CLIExecWithReturn(cmd
, argtable
, true);
511 bool leaveSignalON
= arg_get_lit(1);
512 bool APDULogging
= arg_get_lit(2);
513 EMVCommandChannel channel
= ECC_CONTACTLESS
;
514 #ifdef WITH_SMARTCARD
516 channel
= ECC_CONTACT
;
520 SetAPDULogging(APDULogging
);
523 uint8_t buf
[APDU_RES_LEN
] = {0};
526 int res
= EMVGenerateChallenge(channel
, leaveSignalON
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
529 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
534 PrintAndLogEx(SUCCESS
, "Challenge: %s", sprint_hex(buf
, len
));
536 if (len
!= 4 && len
!= 8)
537 PrintAndLogEx(WARNING
, "Length of challenge must be 4 or 8, but it %d", len
);
542 int CmdEMVInternalAuthenticate(const char *cmd
) {
543 uint8_t data
[APDU_RES_LEN
] = {0};
546 CLIParserInit("emv intauth",
547 "Generate Internal Authenticate command. Usually needs 4-byte random number. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.",
548 "Usage:\n\temv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n"
549 "\temv intauth -t 01020304 -> execute Internal Authenticate with 4-byte DDOL data, show result in TLV\n"
550 "\temv intauth -pmt 9F 37 04 -> load params from file, make DDOL data from DDOL, Internal Authenticate with DDOL, show result in TLV");
554 arg_lit0("kK", "keep", "keep field ON for next command"),
555 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for DDOLdata making from DDOL and parameters"),
556 arg_lit0("mM", "make", "make DDOLdata from DDOL (tag 9F49) and parameters (by default uses default parameters)"),
557 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
558 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
559 #ifdef WITH_SMARTCARD
560 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
562 arg_strx1(NULL
, NULL
, "<HEX DDOLdata/DDOL>", NULL
),
565 CLIExecWithReturn(cmd
, argtable
, false);
567 bool leaveSignalON
= arg_get_lit(1);
568 bool paramsLoadFromFile
= arg_get_lit(2);
569 bool dataMakeFromDDOL
= arg_get_lit(3);
570 bool APDULogging
= arg_get_lit(4);
571 bool decodeTLV
= arg_get_lit(5);
572 EMVCommandChannel channel
= ECC_CONTACTLESS
;
573 #ifdef WITH_SMARTCARD
575 channel
= ECC_CONTACT
;
576 CLIGetHexWithReturn(7, data
, &datalen
);
578 CLIGetHexWithReturn(6, data
, &datalen
);
582 SetAPDULogging(APDULogging
);
585 const char *alr
= "Root terminal TLV tree";
586 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
589 struct tlv
*ddol_data_tlv
= NULL
;
590 struct tlv data_tlv
= {
593 .value
= (uint8_t *)data
,
596 if (dataMakeFromDDOL
) {
597 ParamLoadDefaults(tlvRoot
);
599 if (paramsLoadFromFile
) {
600 PrintAndLogEx(INFO
, "Params loading from file...");
601 ParamLoadFromJson(tlvRoot
);
604 ddol_data_tlv
= dol_process((const struct tlv
*)tlvdb_external(0x9f49, datalen
, data
), tlvRoot
, 0x01); // 0x01 - dummy tag
606 PrintAndLogEx(ERR
, "Can't create DDOL TLV.");
611 if (paramsLoadFromFile
) {
612 PrintAndLogEx(WARNING
, "Don't need to load parameters. Sending plain DDOL data...");
614 ddol_data_tlv
= &data_tlv
;
617 PrintAndLogEx(INFO
, "DDOL data[%d]: %s", ddol_data_tlv
->len
, sprint_hex(ddol_data_tlv
->value
, ddol_data_tlv
->len
));
620 uint8_t buf
[APDU_RES_LEN
] = {0};
623 int res
= EMVInternalAuthenticate(channel
, leaveSignalON
, data
, datalen
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
625 if (ddol_data_tlv
!= &data_tlv
)
630 PrintAndLogEx(INFO
, "APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
636 TLVPrintFromBuffer(buf
, len
);
641 #define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;}
643 void InitTransactionParameters(struct tlvdb
*tlvRoot
, bool paramLoadJSON
, enum TransactionType TrType
, bool GenACGPO
) {
645 ParamLoadDefaults(tlvRoot
);
648 PrintAndLog("* * Transaction parameters loading from JSON...");
649 ParamLoadFromJson(tlvRoot
);
652 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
653 char *qVSDC
= "\x26\x00\x00\x00";
655 qVSDC
= "\x26\x80\x00\x00";
659 TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD
661 // not standard for contactless. just for test.
663 TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC
666 TLV_ADD(0x9F66, qVSDC
); // qVSDC
669 TLV_ADD(0x9F66, qVSDC
); // qVSDC (VISA CDA not enabled)
676 void ProcessGPOResponseFormat1(struct tlvdb
*tlvRoot
, uint8_t *buf
, size_t len
, bool decodeTLV
) {
677 if (buf
[0] == 0x80) {
679 PrintAndLog("GPO response format1:");
680 TLVPrintFromBuffer(buf
, len
);
683 if (len
< 4 || (len
- 4) % 4) {
684 PrintAndLogEx(ERR
, "GPO response format1 parsing error. length=%d", len
);
687 struct tlvdb
* f1AIP
= tlvdb_fixed(0x82, 2, buf
+ 2);
688 tlvdb_add(tlvRoot
, f1AIP
);
690 PrintAndLogEx(INFO
, "\n* * Decode response format 1 (0x80) AIP and AFL:");
691 TLVPrintFromTLV(f1AIP
);
695 struct tlvdb
* f1AFL
= tlvdb_fixed(0x94, len
- 4, buf
+ 2 + 2);
696 tlvdb_add(tlvRoot
, f1AFL
);
698 TLVPrintFromTLV(f1AFL
);
702 TLVPrintFromBuffer(buf
, len
);
706 int CmdEMVExec(const char *cmd
) {
707 uint8_t buf
[APDU_RES_LEN
] = {0};
710 uint8_t AID
[APDU_AID_LEN
] = {0};
712 uint8_t ODAiList
[4096];
713 size_t ODAiListLen
= 0;
717 struct tlvdb
*tlvSelect
= NULL
;
718 struct tlvdb
*tlvRoot
= NULL
;
719 struct tlv
*pdol_data_tlv
= NULL
;
721 CLIParserInit("emv exec",
722 "Executes EMV contactless transaction",
723 "Usage:\n\temv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n"
724 "\temv exec -satc -> select card, execute CDA transaction, show APDU and TLV\n");
728 arg_lit0("sS", "select", "activate field and select card."),
729 arg_lit0("aA", "apdu", "show APDU reqests and responses."),
730 arg_lit0("tT", "tlv", "TLV decode results."),
731 arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."),
732 arg_lit0("fF", "forceaid", "Force search AID. Search AID instead of execute PPSE."),
733 arg_rem("By default:", "Transaction type - MSD"),
734 arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."),
735 arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."),
736 arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."),
737 arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
738 #ifdef WITH_SMARTCARD
739 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
743 CLIExecWithReturn(cmd
, argtable
, true);
745 bool activateField
= arg_get_lit(1);
746 bool showAPDU
= arg_get_lit(2);
747 bool decodeTLV
= arg_get_lit(3);
748 bool paramLoadJSON
= arg_get_lit(4);
749 bool forceSearch
= arg_get_lit(5);
751 enum TransactionType TrType
= TT_MSD
;
753 TrType
= TT_QVSDCMCHIP
;
759 bool GenACGPO
= arg_get_lit(10);
760 EMVCommandChannel channel
= ECC_CONTACTLESS
;
761 #ifdef WITH_SMARTCARD
763 channel
= ECC_CONTACT
;
767 SetAPDULogging(showAPDU
);
769 // init applets list tree
770 const char *al
= "Applets list";
771 tlvSelect
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
773 // Application Selection
774 // https://www.openscdp.org/scripts/tutorial/emv/applicationselection.html
777 PrintAndLogEx(NORMAL
, "\n* PPSE.");
778 SetAPDULogging(showAPDU
);
779 res
= EMVSearchPSE(channel
, activateField
, true, decodeTLV
, tlvSelect
);
781 // check PPSE and select application id
783 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
784 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
790 PrintAndLogEx(NORMAL
, "\n* Search AID in list.");
791 SetAPDULogging(false);
792 if (EMVSearch(channel
, activateField
, true, decodeTLV
, tlvSelect
)) {
796 // check search and select application id
797 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
798 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
802 const char *alr
= "Root terminal TLV tree";
803 tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
805 // check if we found EMV application on card
807 PrintAndLogEx(WARNING
, "Can't select AID. EMV AID not found");
812 PrintAndLogEx(NORMAL
, "\n* Selecting AID:%s", sprint_hex_inrow(AID
, AIDlen
));
813 SetAPDULogging(showAPDU
);
814 res
= EMVSelect(channel
, false, true, AID
, AIDlen
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
817 PrintAndLogEx(WARNING
, "Can't select AID (%d). Exit...", res
);
822 TLVPrintFromBuffer(buf
, len
);
823 PrintAndLogEx(INFO
, "* Selected.");
825 PrintAndLogEx(INFO
, "\n* Init transaction parameters.");
826 InitTransactionParameters(tlvRoot
, paramLoadJSON
, TrType
, GenACGPO
);
827 TLVPrintFromTLV(tlvRoot
); // TODO delete!!!
829 PrintAndLogEx(NORMAL
, "\n* Calc PDOL.");
830 pdol_data_tlv
= dol_process(tlvdb_get(tlvRoot
, 0x9f38, NULL
), tlvRoot
, 0x83);
832 PrintAndLogEx(WARNING
, "Error: can't create PDOL TLV.");
836 size_t pdol_data_tlv_data_len
;
837 unsigned char *pdol_data_tlv_data
= tlv_encode(pdol_data_tlv
, &pdol_data_tlv_data_len
);
838 if (!pdol_data_tlv_data
) {
839 PrintAndLogEx(WARNING
, "Error: can't create PDOL data.");
842 PrintAndLogEx(NORMAL
, "PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
844 PrintAndLogEx(NORMAL
, "\n* GPO.");
845 res
= EMVGPO(channel
, true, pdol_data_tlv_data
, pdol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
847 free(pdol_data_tlv_data
);
848 //free(pdol_data_tlv); --- free on exit.
851 PrintAndLogEx(NORMAL
, "GPO error(%d): %4x. Exit...", res
, sw
);
855 // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
856 ProcessGPOResponseFormat1(tlvRoot
, buf
, len
, decodeTLV
);
858 // extract PAN from track2
860 const struct tlv
*track2
= tlvdb_get(tlvRoot
, 0x57, NULL
);
861 if (!tlvdb_get(tlvRoot
, 0x5a, NULL
) && track2
&& track2
->len
>= 8) {
862 struct tlvdb
*pan
= GetPANFromTrack2(track2
);
864 tlvdb_add(tlvRoot
, pan
);
866 const struct tlv
*pantlv
= tlvdb_get(tlvRoot
, 0x5a, NULL
);
867 PrintAndLogEx(NORMAL
, "\n* * Extracted PAN from track2: %s", sprint_hex(pantlv
->value
, pantlv
->len
));
869 PrintAndLogEx(NORMAL
, "\n* * WARNING: Can't extract PAN from track2.");
874 PrintAndLogEx(NORMAL
, "\n* Read records from AFL.");
875 const struct tlv
*AFL
= tlvdb_get(tlvRoot
, 0x94, NULL
);
876 if (!AFL
|| !AFL
->len
) {
877 PrintAndLogEx(WARNING
, "AFL not found.");
880 while(AFL
&& AFL
->len
) {
882 PrintAndLogEx(WARNING
, "Error: Wrong AFL length: %d", AFL
->len
);
886 for (int i
= 0; i
< AFL
->len
/ 4; i
++) {
887 uint8_t SFI
= AFL
->value
[i
* 4 + 0] >> 3;
888 uint8_t SFIstart
= AFL
->value
[i
* 4 + 1];
889 uint8_t SFIend
= AFL
->value
[i
* 4 + 2];
890 uint8_t SFIoffline
= AFL
->value
[i
* 4 + 3];
892 PrintAndLogEx(NORMAL
, "* * SFI[%02x] start:%02x end:%02x offline:%02x", SFI
, SFIstart
, SFIend
, SFIoffline
);
893 if (SFI
== 0 || SFI
== 31 || SFIstart
== 0 || SFIstart
> SFIend
) {
894 PrintAndLogEx(NORMAL
, "SFI ERROR! Skipped...");
898 for(int n
= SFIstart
; n
<= SFIend
; n
++) {
899 PrintAndLogEx(NORMAL
, "* * * SFI[%02x] %d", SFI
, n
);
901 res
= EMVReadRecord(channel
, true, SFI
, n
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
903 PrintAndLogEx(WARNING
, "Error SFI[%02x]. APDU error %4x", SFI
, sw
);
908 TLVPrintFromBuffer(buf
, len
);
909 PrintAndLogEx(NORMAL
, "");
912 // Build Input list for Offline Data Authentication
913 // EMV 4.3 book3 10.3, page 96
916 const unsigned char *abuf
= buf
;
919 if (tlv_parse_tl(&abuf
, &elmlen
, &e
)) {
920 memcpy(&ODAiList
[ODAiListLen
], &buf
[len
- elmlen
], elmlen
);
921 ODAiListLen
+= elmlen
;
923 PrintAndLogEx(WARNING
, "Error SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI
);
926 memcpy(&ODAiList
[ODAiListLen
], buf
, len
);
936 // copy Input list for Offline Data Authentication
938 struct tlvdb
*oda
= tlvdb_fixed(0x21, ODAiListLen
, ODAiList
); // not a standard tag
939 tlvdb_add(tlvRoot
, oda
);
940 PrintAndLogEx(NORMAL
, "* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen
);
945 const struct tlv
*AIPtlv
= tlvdb_get(tlvRoot
, 0x82, NULL
);
947 AIP
= AIPtlv
->value
[0] + AIPtlv
->value
[1] * 0x100;
948 PrintAndLogEx(NORMAL
, "* * AIP=%04x", AIP
);
950 PrintAndLogEx(ERR
, "Can't found AIP.");
955 PrintAndLogEx(NORMAL
, "\n* SDA");
961 PrintAndLogEx(NORMAL
, "\n* DDA");
962 trDDA(channel
, decodeTLV
, tlvRoot
);
968 if (TrType
== TT_QVSDCMCHIP
|| TrType
== TT_CDA
){
969 // 9F26: Application Cryptogram
970 const struct tlv
*AC
= tlvdb_get(tlvRoot
, 0x9F26, NULL
);
972 PrintAndLogEx(NORMAL
, "\n--> qVSDC transaction.");
973 PrintAndLogEx(NORMAL
, "* AC path");
975 // 9F36: Application Transaction Counter (ATC)
976 const struct tlv
*ATC
= tlvdb_get(tlvRoot
, 0x9F36, NULL
);
979 // 9F10: Issuer Application Data - optional
980 const struct tlv
*IAD
= tlvdb_get(tlvRoot
, 0x9F10, NULL
);
983 PrintAndLogEx(NORMAL
, "ATC: %s", sprint_hex(ATC
->value
, ATC
->len
));
984 PrintAndLogEx(NORMAL
, "AC: %s", sprint_hex(AC
->value
, AC
->len
));
986 PrintAndLogEx(NORMAL
, "IAD: %s", sprint_hex(IAD
->value
, IAD
->len
));
988 if (IAD
->len
>= IAD
->value
[0] + 1) {
989 PrintAndLogEx(NORMAL
, "\tKey index: 0x%02x", IAD
->value
[1]);
990 PrintAndLogEx(NORMAL
, "\tCrypto ver: 0x%02x(%03d)", IAD
->value
[2], IAD
->value
[2]);
991 PrintAndLogEx(NORMAL
, "\tCVR:", sprint_hex(&IAD
->value
[3], IAD
->value
[0] - 2));
992 struct tlvdb
* cvr
= tlvdb_fixed(0x20, IAD
->value
[0] - 2, &IAD
->value
[3]);
993 TLVPrintFromTLVLev(cvr
, 1);
996 PrintAndLogEx(WARNING
, "IAD not found.");
1000 PrintAndLogEx(ERROR
, "AC: Application Transaction Counter (ATC) not found.");
1005 // Mastercard M/CHIP
1006 if (GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
&& (TrType
== TT_QVSDCMCHIP
|| TrType
== TT_CDA
)){
1007 const struct tlv
*CDOL1
= tlvdb_get(tlvRoot
, 0x8c, NULL
);
1008 if (CDOL1
&& GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
) { // and m/chip transaction flag
1009 PrintAndLogEx(NORMAL
, "\n--> Mastercard M/Chip transaction.");
1011 PrintAndLogEx(NORMAL
, "* * Generate challenge");
1012 res
= EMVGenerateChallenge(channel
, true, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1014 PrintAndLogEx(WARNING
, "GetChallenge. APDU error %4x", sw
);
1018 PrintAndLogEx(WARNING
, "GetChallenge. Wrong challenge length %d", len
);
1022 // ICC Dynamic Number
1023 struct tlvdb
* ICCDynN
= tlvdb_fixed(0x9f4c, len
, buf
);
1024 tlvdb_add(tlvRoot
, ICCDynN
);
1026 PrintAndLogEx(NORMAL
, "\n* * ICC Dynamic Number:");
1027 TLVPrintFromTLV(ICCDynN
);
1030 PrintAndLogEx(NORMAL
, "* * Calc CDOL1");
1031 struct tlv
*cdol_data_tlv
= dol_process(tlvdb_get(tlvRoot
, 0x8c, NULL
), tlvRoot
, 0x01); // 0x01 - dummy tag
1032 if (!cdol_data_tlv
){
1033 PrintAndLogEx(WARNING
, "Error: can't create CDOL1 TLV.");
1036 PrintAndLogEx(NORMAL
, "CDOL1 data[%d]: %s", cdol_data_tlv
->len
, sprint_hex(cdol_data_tlv
->value
, cdol_data_tlv
->len
));
1038 PrintAndLogEx(NORMAL
, "* * AC1");
1039 // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
1040 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
);
1043 PrintAndLogEx(NORMAL
, "AC1 error(%d): %4x. Exit...", res
, sw
);
1048 TLVPrintFromBuffer(buf
, len
);
1051 PrintAndLogEx(NORMAL
, "\n* CDA:");
1052 struct tlvdb
*ac_tlv
= tlvdb_parse_multi(buf
, len
);
1053 res
= trCDA(tlvRoot
, ac_tlv
, pdol_data_tlv
, cdol_data_tlv
);
1055 PrintAndLogEx(NORMAL
, "CDA error (%d)", res
);
1058 free(cdol_data_tlv
);
1060 PrintAndLogEx(NORMAL
, "\n* M/Chip transaction result:");
1061 // 9F27: Cryptogram Information Data (CID)
1062 const struct tlv
*CID
= tlvdb_get(tlvRoot
, 0x9F27, NULL
);
1064 emv_tag_dump(CID
, stdout
, 0);
1065 PrintAndLogEx(NORMAL
, "------------------------------");
1067 switch(CID
->value
[0] & EMVAC_AC_MASK
){
1069 PrintAndLogEx(NORMAL
, "Transaction DECLINED.");
1072 PrintAndLogEx(NORMAL
, "Transaction approved OFFLINE.");
1075 PrintAndLogEx(NORMAL
, "Transaction approved ONLINE.");
1078 PrintAndLogEx(WARNING
, "Error: CID transaction code error %2x", CID
->value
[0] & EMVAC_AC_MASK
);
1082 PrintAndLogEx(WARNING
, "Wrong CID length %d", CID
->len
);
1085 PrintAndLogEx(WARNING
, "CID(9F27) not found.");
1092 if (AIP
& 0x8000 && TrType
== TT_MSD
) {
1093 PrintAndLogEx(NORMAL
, "\n--> MSD transaction.");
1095 PrintAndLogEx(NORMAL
, "* MSD dCVV path. Check dCVV");
1097 const struct tlv
*track2
= tlvdb_get(tlvRoot
, 0x57, NULL
);
1099 PrintAndLogEx(NORMAL
, "Track2: %s", sprint_hex(track2
->value
, track2
->len
));
1101 struct tlvdb
*dCVV
= GetdCVVRawFromTrack2(track2
);
1102 PrintAndLogEx(NORMAL
, "dCVV raw data:");
1103 TLVPrintFromTLV(dCVV
);
1105 if (GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
) {
1106 PrintAndLogEx(NORMAL
, "\n* Mastercard calculate UDOL");
1109 const struct tlv
*UDOL
= tlvdb_get(tlvRoot
, 0x9F69, NULL
);
1110 // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
1111 const struct tlv defUDOL
= {
1114 .value
= (uint8_t *)"\x9f\x6a\x04",
1117 PrintAndLogEx(NORMAL
, "Use default UDOL.");
1119 struct tlv
*udol_data_tlv
= dol_process(UDOL
? UDOL
: &defUDOL
, tlvRoot
, 0x01); // 0x01 - dummy tag
1120 if (!udol_data_tlv
){
1121 PrintAndLogEx(WARNING
, "can't create UDOL TLV.");
1125 PrintAndLogEx(NORMAL
, "UDOL data[%d]: %s", udol_data_tlv
->len
, sprint_hex(udol_data_tlv
->value
, udol_data_tlv
->len
));
1127 PrintAndLogEx(NORMAL
, "\n* Mastercard compute cryptographic checksum(UDOL)");
1129 res
= MSCComputeCryptoChecksum(channel
, true, (uint8_t *)udol_data_tlv
->value
, udol_data_tlv
->len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1131 PrintAndLogEx(WARNING
, "Compute Crypto Checksum. APDU error %4x", sw
);
1132 free(udol_data_tlv
);
1136 // Mastercard compute cryptographic checksum result
1137 TLVPrintFromBuffer(buf
, len
);
1138 PrintAndLogEx(NORMAL
, "");
1140 free(udol_data_tlv
);
1144 PrintAndLogEx(WARNING
, "MSD: Track2 data not found.");
1151 free(pdol_data_tlv
);
1152 tlvdb_free(tlvSelect
);
1153 tlvdb_free(tlvRoot
);
1155 PrintAndLogEx(NORMAL
, "\n* Transaction completed.");
1159 int CmdEMVScan(const char *cmd
) {
1160 uint8_t AID
[APDU_AID_LEN
] = {0};
1162 uint8_t buf
[APDU_RES_LEN
] = {0};
1169 CLIParserInit("emv scan",
1170 "Scan EMV card and save it contents to a file.",
1171 "It executes EMV contactless transaction and saves result to a file which can be used for emulation\n"
1172 "Usage:\n\temv scan -at -> scan MSD transaction mode and show APDU and TLV\n"
1173 "\temv scan -c -> scan CDA transaction mode\n");
1175 void* argtable
[] = {
1177 arg_lit0("aA", "apdu", "show APDU reqests and responses."),
1178 arg_lit0("tT", "tlv", "TLV decode results."),
1179 arg_lit0("eE", "extract", "Extract TLV elements and fill Application Data"),
1180 arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."),
1181 arg_rem("By default:", "Transaction type - MSD"),
1182 arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."),
1183 arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."),
1184 arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."),
1185 arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
1186 arg_lit0("mM", "merge", "Merge output file with card's data. (warning: the file may be corrupted!)"),
1187 #ifdef WITH_SMARTCARD
1188 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
1190 arg_str1(NULL
, NULL
, "output.json", "JSON output file name"),
1193 CLIExecWithReturn(cmd
, argtable
, true);
1195 bool showAPDU
= arg_get_lit(1);
1196 bool decodeTLV
= arg_get_lit(2);
1197 bool extractTLVElements
= arg_get_lit(3);
1198 bool paramLoadJSON
= arg_get_lit(4);
1200 enum TransactionType TrType
= TT_MSD
;
1202 TrType
= TT_QVSDCMCHIP
;
1208 bool GenACGPO
= arg_get_lit(9);
1209 bool MergeJSON
= arg_get_lit(10);
1210 EMVCommandChannel channel
= ECC_CONTACTLESS
;
1211 uint8_t relfname
[250] = {0};
1212 char *crelfname
= (char *)relfname
;
1213 int relfnamelen
= 0;
1214 #ifdef WITH_SMARTCARD
1215 if (arg_get_lit(11))
1216 channel
= ECC_CONTACT
;
1217 CLIGetStrWithReturn(12, relfname
, &relfnamelen
);
1219 CLIGetStrWithReturn(11, relfname
, &relfnamelen
);
1223 SetAPDULogging(showAPDU
);
1226 if (channel
== ECC_CONTACT
) {
1227 PrintAndLogEx(ERR
, "Do not use contact interface. Exit.");
1231 // current path + file name
1232 if (!strstr(crelfname
, ".json"))
1233 strcat(crelfname
, ".json");
1234 char fname
[strlen(get_my_executable_directory()) + strlen(crelfname
) + 1];
1235 strcpy(fname
, get_my_executable_directory());
1236 strcat(fname
, crelfname
);
1239 root
= json_load_file(fname
, 0, &error
);
1241 PrintAndLogEx(ERROR
, "json error on line %d: %s", error
.line
, error
.text
);
1245 if (!json_is_object(root
)) {
1246 PrintAndLogEx(ERROR
, "Invalid json format. root must be an object.");
1250 root
= json_object();
1253 // drop field at start
1257 PrintAndLogEx(NORMAL
, "--> GET UID, ATS.");
1259 iso14a_card_select_t card
;
1260 if (Hf14443_4aGetCardData(&card
)) {
1264 JsonSaveStr(root
, "$.File.Created", "proxmark3 `emv scan`");
1266 JsonSaveStr(root
, "$.Card.Communication", "iso14443-4a");
1267 JsonSaveBufAsHex(root
, "$.Card.UID", (uint8_t *)&card
.uid
, card
.uidlen
);
1268 JsonSaveHex(root
, "$.Card.ATQA", card
.atqa
[0] + (card
.atqa
[1] << 2), 2);
1269 JsonSaveHex(root
, "$.Card.SAK", card
.sak
, 0);
1270 JsonSaveBufAsHex(root
, "$.Card.ATS", (uint8_t *)card
.ats
, card
.ats_len
);
1272 // init applets list tree
1273 const char *al
= "Applets list";
1274 struct tlvdb
*tlvSelect
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
1277 PrintAndLogEx(NORMAL
, "--> PPSE.");
1278 res
= EMVSelectPSE(channel
, true, true, 2, buf
, sizeof(buf
), &len
, &sw
);
1280 if (!res
&& sw
== 0x9000){
1282 TLVPrintFromBuffer(buf
, len
);
1284 JsonSaveBufAsHex(root
, "$.PPSE.AID", (uint8_t *)"2PAY.SYS.DDF01", 14);
1286 struct tlvdb
*fci
= tlvdb_parse_multi(buf
, len
);
1287 if (extractTLVElements
)
1288 JsonSaveTLVTree(root
, root
, "$.PPSE.FCITemplate", fci
);
1290 JsonSaveTLVTreeElm(root
, "$.PPSE.FCITemplate", fci
, true, true, false);
1291 JsonSaveTLVValue(root
, "$.Application.KernelID", tlvdb_find_full(fci
, 0x9f2a));
1295 res
= EMVSearchPSE(channel
, false, true, decodeTLV
, tlvSelect
);
1297 // check PPSE and select application id
1299 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
1301 // EMV SEARCH with AID list
1302 SetAPDULogging(false);
1303 PrintAndLogEx(NORMAL
, "--> AID search.");
1304 if (EMVSearch(channel
, false, true, decodeTLV
, tlvSelect
)) {
1305 PrintAndLogEx(ERROR
, "Can't found any of EMV AID. Exit...");
1306 tlvdb_free(tlvSelect
);
1311 // check search and select application id
1312 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
1315 // EMV SELECT application
1316 SetAPDULogging(showAPDU
);
1317 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
1319 tlvdb_free(tlvSelect
);
1322 PrintAndLogEx(INFO
, "Can't select AID. EMV AID not found. Exit...");
1327 JsonSaveBufAsHex(root
, "$.Application.AID", AID
, AIDlen
);
1330 const char *alr
= "Root terminal TLV tree";
1331 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
1333 // EMV SELECT applet
1335 PrintAndLogEx(NORMAL
, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID
, AIDlen
));
1336 SetAPDULogging(showAPDU
);
1337 res
= EMVSelect(channel
, false, true, AID
, AIDlen
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1340 PrintAndLogEx(ERROR
, "Can't select AID (%d). Exit...", res
);
1341 tlvdb_free(tlvRoot
);
1347 TLVPrintFromBuffer(buf
, len
);
1350 if (tlvdb_get(tlvRoot
, 0x9f38, NULL
)) {
1351 JsonSaveStr(root
, "$.Application.Mode", TransactionTypeStr
[TrType
]);
1354 struct tlvdb
*fci
= tlvdb_parse_multi(buf
, len
);
1355 if (extractTLVElements
)
1356 JsonSaveTLVTree(root
, root
, "$.Application.FCITemplate", fci
);
1358 JsonSaveTLVTreeElm(root
, "$.Application.FCITemplate", fci
, true, true, false);
1361 // create transaction parameters
1362 PrintAndLogEx(NORMAL
, "-->Init transaction parameters.");
1363 InitTransactionParameters(tlvRoot
, paramLoadJSON
, TrType
, GenACGPO
);
1365 PrintAndLogEx(NORMAL
, "-->Calc PDOL.");
1366 struct tlv
*pdol_data_tlv
= dol_process(tlvdb_get(tlvRoot
, 0x9f38, NULL
), tlvRoot
, 0x83);
1367 if (!pdol_data_tlv
){
1368 PrintAndLogEx(ERROR
, "Can't create PDOL TLV.");
1369 tlvdb_free(tlvRoot
);
1374 size_t pdol_data_tlv_data_len
;
1375 unsigned char *pdol_data_tlv_data
= tlv_encode(pdol_data_tlv
, &pdol_data_tlv_data_len
);
1376 if (!pdol_data_tlv_data
) {
1377 PrintAndLogEx(ERROR
, "Can't create PDOL data.");
1378 tlvdb_free(tlvRoot
);
1382 PrintAndLogEx(INFO
, "PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
1384 PrintAndLogEx(INFO
, "-->GPO.");
1385 res
= EMVGPO(channel
, true, pdol_data_tlv_data
, pdol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1387 free(pdol_data_tlv_data
);
1388 free(pdol_data_tlv
);
1391 PrintAndLogEx(ERROR
, "GPO error(%d): %4x. Exit...", res
, sw
);
1392 tlvdb_free(tlvRoot
);
1396 ProcessGPOResponseFormat1(tlvRoot
, buf
, len
, decodeTLV
);
1398 struct tlvdb
*gpofci
= tlvdb_parse_multi(buf
, len
);
1399 if (extractTLVElements
)
1400 JsonSaveTLVTree(root
, root
, "$.Application.GPO", gpofci
);
1402 JsonSaveTLVTreeElm(root
, "$.Application.GPO", gpofci
, true, true, false);
1404 JsonSaveTLVValue(root
, "$.ApplicationData.AIP", tlvdb_find_full(gpofci
, 0x82));
1405 JsonSaveTLVValue(root
, "$.ApplicationData.AFL", tlvdb_find_full(gpofci
, 0x94));
1409 PrintAndLogEx(INFO
, "-->Read records from AFL.");
1410 const struct tlv
*AFL
= tlvdb_get(tlvRoot
, 0x94, NULL
);
1412 while(AFL
&& AFL
->len
) {
1414 PrintAndLogEx(ERROR
, "Wrong AFL length: %d", AFL
->len
);
1418 json_t
*sfijson
= json_path_get(root
, "$.Application.Records");
1420 json_t
*app
= json_path_get(root
, "$.Application");
1421 json_object_set_new(app
, "Records", json_array());
1423 sfijson
= json_path_get(root
, "$.Application.Records");
1425 if (!json_is_array(sfijson
)) {
1426 PrintAndLogEx(ERROR
, "Internal logic error. `$.Application.Records` is not an array.");
1429 for (int i
= 0; i
< AFL
->len
/ 4; i
++) {
1430 uint8_t SFI
= AFL
->value
[i
* 4 + 0] >> 3;
1431 uint8_t SFIstart
= AFL
->value
[i
* 4 + 1];
1432 uint8_t SFIend
= AFL
->value
[i
* 4 + 2];
1433 uint8_t SFIoffline
= AFL
->value
[i
* 4 + 3];
1435 PrintAndLogEx(INFO
, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI
, SFIstart
, SFIend
, SFIoffline
);
1436 if (SFI
== 0 || SFI
== 31 || SFIstart
== 0 || SFIstart
> SFIend
) {
1437 PrintAndLogEx(ERROR
, "SFI ERROR! Skipped...");
1441 for(int n
= SFIstart
; n
<= SFIend
; n
++) {
1442 PrintAndLogEx(INFO
, "---->SFI[%02x] %d", SFI
, n
);
1444 res
= EMVReadRecord(channel
, true, SFI
, n
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1446 PrintAndLogEx(ERROR
, "SFI[%02x]. APDU error %4x", SFI
, sw
);
1451 TLVPrintFromBuffer(buf
, len
);
1452 PrintAndLogEx(NORMAL
, "");
1455 json_t
*jsonelm
= json_object();
1456 json_array_append_new(sfijson
, jsonelm
);
1458 JsonSaveHex(jsonelm
, "SFI", SFI
, 1);
1459 JsonSaveHex(jsonelm
, "RecordNum", n
, 1);
1460 JsonSaveHex(jsonelm
, "Offline", SFIoffline
, 1);
1462 struct tlvdb
*rsfi
= tlvdb_parse_multi(buf
, len
);
1463 if (extractTLVElements
)
1464 JsonSaveTLVTree(root
, jsonelm
, "$.Data", rsfi
);
1466 JsonSaveTLVTreeElm(jsonelm
, "$.Data", rsfi
, true, true, false);
1474 // getting certificates
1475 if (tlvdb_get(tlvRoot
, 0x90, NULL
)) {
1476 PrintAndLogEx(INFO
, "-->Recovering certificates.");
1477 PKISetStrictExecution(false);
1478 RecoveryCertificates(tlvRoot
, root
);
1479 PKISetStrictExecution(true);
1483 tlvdb_free(tlvRoot
);
1488 res
= json_dump_file(root
, fname
, JSON_INDENT(2));
1490 PrintAndLogEx(ERROR
, "Can't save the file: %s", fname
);
1493 PrintAndLogEx(SUCCESS
, "File `%s` saved.", fname
);
1501 int CmdEMVTest(const char *cmd
) {
1502 return ExecuteCryptoTests(true);
1505 int CmdHelp(const char *Cmd
);
1506 static command_t CommandTable
[] = {
1507 {"help", CmdHelp
, 1, "This help"},
1508 {"exec", CmdEMVExec
, 0, "Executes EMV contactless transaction."},
1509 {"pse", CmdEMVPPSE
, 0, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."},
1510 {"search", CmdEMVSearch
, 0, "Try to select all applets from applets list and print installed applets."},
1511 {"select", CmdEMVSelect
, 0, "Select applet."},
1512 {"gpo", CmdEMVGPO
, 0, "Execute GetProcessingOptions."},
1513 {"readrec", CmdEMVReadRecord
, 0, "Read files from card."},
1514 {"genac", CmdEMVAC
, 0, "Generate ApplicationCryptogram."},
1515 {"challenge", CmdEMVGenerateChallenge
, 0, "Generate challenge."},
1516 {"intauth", CmdEMVInternalAuthenticate
, 0, "Internal authentication."},
1517 {"scan", CmdEMVScan
, 0, "Scan EMV card and save it contents to json file for emulator."},
1518 {"test", CmdEMVTest
, 0, "Crypto logic test."},
1519 {NULL
, NULL
, 0, NULL
}
1522 int CmdEMV(const char *Cmd
) {
1523 CmdsParse(CommandTable
, Cmd
);
1527 int CmdHelp(const char *Cmd
) {
1528 CmdsHelp(CommandTable
);