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 CmdHFEMVSelect(const char *cmd
) {
42 uint8_t data
[APDU_AID_LEN
] = {0};
45 CLIParserInit("hf emv select",
46 "Executes select applet command",
47 "Usage:\n\thf emv select -s a00000000101 -> select card, select applet\n\thf emv 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"),
55 arg_strx0(NULL
, NULL
, "<HEX applet AID>", NULL
),
58 CLIExecWithReturn(cmd
, argtable
, true);
60 bool activateField
= arg_get_lit(1);
61 bool leaveSignalON
= arg_get_lit(2);
62 bool APDULogging
= arg_get_lit(3);
63 bool decodeTLV
= arg_get_lit(4);
64 CLIGetHexWithReturn(5, data
, &datalen
);
67 SetAPDULogging(APDULogging
);
70 uint8_t buf
[APDU_RES_LEN
] = {0};
73 int res
= EMVSelect(activateField
, leaveSignalON
, data
, datalen
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
76 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
82 TLVPrintFromBuffer(buf
, len
);
87 int CmdHFEMVSearch(const char *cmd
) {
89 CLIParserInit("hf emv search",
90 "Tries to select all applets from applet list:\n",
91 "Usage:\n\thf emv search -s -> select card and search\n\thf emv search -st -> select card, search and show result in TLV\n");
95 arg_lit0("sS", "select", "activate field and select card"),
96 arg_lit0("kK", "keep", "keep field ON for next command"),
97 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
98 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
101 CLIExecWithReturn(cmd
, argtable
, true);
103 bool activateField
= arg_get_lit(1);
104 bool leaveSignalON
= arg_get_lit(2);
105 bool APDULogging
= arg_get_lit(3);
106 bool decodeTLV
= arg_get_lit(4);
109 SetAPDULogging(APDULogging
);
111 struct tlvdb
*t
= NULL
;
112 const char *al
= "Applets list";
113 t
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
115 if (EMVSearch(activateField
, leaveSignalON
, decodeTLV
, t
)) {
120 PrintAndLog("Search completed.");
124 TLVPrintAIDlistFromSelectTLV(t
);
132 int CmdHFEMVPPSE(const char *cmd
) {
134 CLIParserInit("hf emv pse",
135 "Executes PSE/PPSE select command. It returns list of applet on the card:\n",
136 "Usage:\n\thf emv pse -s1 -> select, get pse\n\thf emv pse -st2 -> select, get ppse, show result in TLV\n");
140 arg_lit0("sS", "select", "activate field and select card"),
141 arg_lit0("kK", "keep", "keep field ON for next command"),
142 arg_lit0("1", "pse", "pse (1PAY.SYS.DDF01) mode"),
143 arg_lit0("2", "ppse", "ppse (2PAY.SYS.DDF01) mode (default mode)"),
144 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
145 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
148 CLIExecWithReturn(cmd
, argtable
, true);
150 bool activateField
= arg_get_lit(1);
151 bool leaveSignalON
= arg_get_lit(2);
157 bool APDULogging
= arg_get_lit(5);
158 bool decodeTLV
= arg_get_lit(6);
161 SetAPDULogging(APDULogging
);
164 uint8_t buf
[APDU_RES_LEN
] = {0};
167 int res
= EMVSelectPSE(activateField
, leaveSignalON
, PSENum
, buf
, sizeof(buf
), &len
, &sw
);
170 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
177 TLVPrintFromBuffer(buf
, len
);
182 int CmdHFEMVGPO(const char *cmd
) {
183 uint8_t data
[APDU_RES_LEN
] = {0};
186 CLIParserInit("hf emv gpo",
187 "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.",
188 "Usage:\n\thf emv gpo -k -> execute GPO\n"
189 "\thf emv gpo -t 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n"
190 "\thf emv gpo -pmt 9F 37 04 -> load params from file, make PDOL data from PDOL, execute GPO with PDOL, show result in TLV\n");
194 arg_lit0("kK", "keep", "keep field ON for next command"),
195 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for PDOLdata making from PDOL and parameters"),
196 arg_lit0("mM", "make", "make PDOLdata from PDOL (tag 9F38) and parameters (by default uses default parameters)"),
197 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
198 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
199 arg_strx0(NULL
, NULL
, "<HEX PDOLdata/PDOL>", NULL
),
202 CLIExecWithReturn(cmd
, argtable
, true);
204 bool leaveSignalON
= arg_get_lit(1);
205 bool paramsLoadFromFile
= arg_get_lit(2);
206 bool dataMakeFromPDOL
= arg_get_lit(3);
207 bool APDULogging
= arg_get_lit(4);
208 bool decodeTLV
= arg_get_lit(5);
209 CLIGetHexWithReturn(6, data
, &datalen
);
212 SetAPDULogging(APDULogging
);
215 const char *alr
= "Root terminal TLV tree";
216 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
219 struct tlv
*pdol_data_tlv
= NULL
;
220 struct tlv data_tlv
= {
223 .value
= (uint8_t *)data
,
225 if (dataMakeFromPDOL
) {
226 ParamLoadDefaults(tlvRoot
);
228 if (paramsLoadFromFile
) {
229 PrintAndLog("Params loading from file...");
230 ParamLoadFromJson(tlvRoot
);
233 pdol_data_tlv
= dol_process((const struct tlv
*)tlvdb_external(0x9f38, datalen
, data
), tlvRoot
, 0x83);
235 PrintAndLog("ERROR: can't create PDOL TLV.");
240 if (paramsLoadFromFile
) {
241 PrintAndLog("WARNING: don't need to load parameters. Sending plain PDOL data...");
243 pdol_data_tlv
= &data_tlv
;
246 size_t pdol_data_tlv_data_len
= 0;
247 unsigned char *pdol_data_tlv_data
= tlv_encode(pdol_data_tlv
, &pdol_data_tlv_data_len
);
248 if (!pdol_data_tlv_data
) {
249 PrintAndLog("ERROR: can't create PDOL data.");
253 PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
256 uint8_t buf
[APDU_RES_LEN
] = {0};
259 int res
= EMVGPO(leaveSignalON
, pdol_data_tlv_data
, pdol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
261 if (pdol_data_tlv
!= &data_tlv
)
266 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
272 TLVPrintFromBuffer(buf
, len
);
277 int CmdHFEMVReadRecord(const char *cmd
) {
278 uint8_t data
[APDU_RES_LEN
] = {0};
281 CLIParserInit("hf emv readrec",
282 "Executes Read Record command. It returns data in TLV format.\nNeeds a bank applet to be selected and sometimes needs GPO to be executed.",
283 "Usage:\n\thf emv readrec -k 0101 -> read file SFI=01, SFIrec=01\n\thf emv readrec -kt 0201-> read file 0201 and show result in TLV\n");
287 arg_lit0("kK", "keep", "keep field ON for next command"),
288 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
289 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
290 arg_strx1(NULL
, NULL
, "<SFI 1byte HEX><SFIrec 1byte HEX>", NULL
),
293 CLIExecWithReturn(cmd
, argtable
, true);
295 bool leaveSignalON
= arg_get_lit(1);
296 bool APDULogging
= arg_get_lit(2);
297 bool decodeTLV
= arg_get_lit(3);
298 CLIGetHexWithReturn(4, data
, &datalen
);
302 PrintAndLog("ERROR: Command needs to have 2 bytes of data");
306 SetAPDULogging(APDULogging
);
309 uint8_t buf
[APDU_RES_LEN
] = {0};
312 int res
= EMVReadRecord(leaveSignalON
, data
[0], data
[1], buf
, sizeof(buf
), &len
, &sw
, NULL
);
315 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
322 TLVPrintFromBuffer(buf
, len
);
327 int CmdHFEMVAC(const char *cmd
) {
328 uint8_t data
[APDU_RES_LEN
] = {0};
331 CLIParserInit("hf emv genac",
332 "Generate Application Cryptogram command. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.",
333 "Usage:\n\thf emv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n"
334 "\thf emv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n"
335 "\thf emv genac -Daac 01020304 -> generate AC with 4-byte CDOL data and terminal decision 'declined'\n"
336 "\thf emv genac -pmt 9F 37 04 -> load params from file, make CDOL data from CDOL, generate AC with CDOL, show result in TLV");
340 arg_lit0("kK", "keep", "keep field ON for next command"),
341 arg_lit0("cC", "cda", "executes CDA transaction. Needs to get SDAD in results."),
342 arg_str0("dD", "decision", "<aac|tc|arqc>", "Terminal decision. aac - declined, tc - approved, arqc - online authorisation requested"),
343 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for CDOLdata making from CDOL and parameters"),
344 arg_lit0("mM", "make", "make CDOLdata from CDOL (tag 8C and 8D) and parameters (by default uses default parameters)"),
345 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
346 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
347 arg_strx1(NULL
, NULL
, "<HEX CDOLdata/CDOL>", NULL
),
350 CLIExecWithReturn(cmd
, argtable
, false);
352 bool leaveSignalON
= arg_get_lit(1);
353 bool trTypeCDA
= arg_get_lit(2);
354 uint8_t termDecision
= 0xff;
355 if (arg_get_str_len(3)) {
356 if (!strncmp(arg_get_str(3)->sval
[0], "aac", 4))
357 termDecision
= EMVAC_AAC
;
358 if (!strncmp(arg_get_str(3)->sval
[0], "tc", 4))
359 termDecision
= EMVAC_TC
;
360 if (!strncmp(arg_get_str(3)->sval
[0], "arqc", 4))
361 termDecision
= EMVAC_ARQC
;
363 if (termDecision
== 0xff) {
364 PrintAndLog("ERROR: can't find terminal decision '%s'", arg_get_str(3)->sval
[0]);
368 termDecision
= EMVAC_TC
;
371 termDecision
= termDecision
| EMVAC_CDAREQ
;
372 bool paramsLoadFromFile
= arg_get_lit(4);
373 bool dataMakeFromCDOL
= arg_get_lit(5);
374 bool APDULogging
= arg_get_lit(6);
375 bool decodeTLV
= arg_get_lit(7);
376 CLIGetHexWithReturn(8, data
, &datalen
);
379 SetAPDULogging(APDULogging
);
382 const char *alr
= "Root terminal TLV tree";
383 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
386 struct tlv
*cdol_data_tlv
= NULL
;
387 struct tlv data_tlv
= {
390 .value
= (uint8_t *)data
,
393 if (dataMakeFromCDOL
) {
394 ParamLoadDefaults(tlvRoot
);
396 if (paramsLoadFromFile
) {
397 PrintAndLog("Params loading from file...");
398 ParamLoadFromJson(tlvRoot
);
401 cdol_data_tlv
= dol_process((const struct tlv
*)tlvdb_external(0x8c, datalen
, data
), tlvRoot
, 0x01); // 0x01 - dummy tag
403 PrintAndLog("ERROR: can't create CDOL TLV.");
408 if (paramsLoadFromFile
) {
409 PrintAndLog("WARNING: don't need to load parameters. Sending plain CDOL data...");
411 cdol_data_tlv
= &data_tlv
;
414 PrintAndLog("CDOL data[%d]: %s", cdol_data_tlv
->len
, sprint_hex(cdol_data_tlv
->value
, cdol_data_tlv
->len
));
417 uint8_t buf
[APDU_RES_LEN
] = {0};
420 int res
= EMVAC(leaveSignalON
, termDecision
, (uint8_t *)cdol_data_tlv
->value
, cdol_data_tlv
->len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
422 if (cdol_data_tlv
!= &data_tlv
)
427 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
433 TLVPrintFromBuffer(buf
, len
);
438 int CmdHFEMVGenerateChallenge(const char *cmd
) {
440 CLIParserInit("hf emv challenge",
441 "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.",
442 "Usage:\n\thf emv challenge -> get challenge\n\thf emv challenge -k -> get challenge, keep fileld ON\n");
446 arg_lit0("kK", "keep", "keep field ON for next command"),
447 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
450 CLIExecWithReturn(cmd
, argtable
, true);
452 bool leaveSignalON
= arg_get_lit(1);
453 bool APDULogging
= arg_get_lit(2);
456 SetAPDULogging(APDULogging
);
459 uint8_t buf
[APDU_RES_LEN
] = {0};
462 int res
= EMVGenerateChallenge(leaveSignalON
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
465 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
470 PrintAndLog("Challenge: %s", sprint_hex(buf
, len
));
472 if (len
!= 4 && len
!= 8)
473 PrintAndLog("WARNING: length of challenge must be 4 or 8, but it %d", len
);
478 int CmdHFEMVInternalAuthenticate(const char *cmd
) {
479 uint8_t data
[APDU_RES_LEN
] = {0};
482 CLIParserInit("hf emv intauth",
483 "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.",
484 "Usage:\n\thf emv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n"
485 "\thf emv intauth -t 01020304 -> execute Internal Authenticate with 4-byte DDOL data, show result in TLV\n"
486 "\thf emv intauth -pmt 9F 37 04 -> load params from file, make DDOL data from DDOL, Internal Authenticate with DDOL, show result in TLV");
490 arg_lit0("kK", "keep", "keep field ON for next command"),
491 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for DDOLdata making from DDOL and parameters"),
492 arg_lit0("mM", "make", "make DDOLdata from DDOL (tag 9F49) and parameters (by default uses default parameters)"),
493 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
494 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
495 arg_strx1(NULL
, NULL
, "<HEX DDOLdata/DDOL>", NULL
),
498 CLIExecWithReturn(cmd
, argtable
, false);
500 bool leaveSignalON
= arg_get_lit(1);
501 bool paramsLoadFromFile
= arg_get_lit(2);
502 bool dataMakeFromDDOL
= arg_get_lit(3);
503 bool APDULogging
= arg_get_lit(4);
504 bool decodeTLV
= arg_get_lit(5);
505 CLIGetHexWithReturn(6, data
, &datalen
);
508 SetAPDULogging(APDULogging
);
511 const char *alr
= "Root terminal TLV tree";
512 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
515 struct tlv
*ddol_data_tlv
= NULL
;
516 struct tlv data_tlv
= {
519 .value
= (uint8_t *)data
,
522 if (dataMakeFromDDOL
) {
523 ParamLoadDefaults(tlvRoot
);
525 if (paramsLoadFromFile
) {
526 PrintAndLog("Params loading from file...");
527 ParamLoadFromJson(tlvRoot
);
530 ddol_data_tlv
= dol_process((const struct tlv
*)tlvdb_external(0x9f49, datalen
, data
), tlvRoot
, 0x01); // 0x01 - dummy tag
532 PrintAndLog("ERROR: can't create DDOL TLV.");
537 if (paramsLoadFromFile
) {
538 PrintAndLog("WARNING: don't need to load parameters. Sending plain DDOL data...");
540 ddol_data_tlv
= &data_tlv
;
543 PrintAndLog("DDOL data[%d]: %s", ddol_data_tlv
->len
, sprint_hex(ddol_data_tlv
->value
, ddol_data_tlv
->len
));
546 uint8_t buf
[APDU_RES_LEN
] = {0};
549 int res
= EMVInternalAuthenticate(leaveSignalON
, data
, datalen
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
551 if (ddol_data_tlv
!= &data_tlv
)
556 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
562 TLVPrintFromBuffer(buf
, len
);
567 #define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;}
569 void InitTransactionParameters(struct tlvdb
*tlvRoot
, bool paramLoadJSON
, enum TransactionType TrType
, bool GenACGPO
) {
571 ParamLoadDefaults(tlvRoot
);
574 PrintAndLog("* * Transaction parameters loading from JSON...");
575 ParamLoadFromJson(tlvRoot
);
578 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
579 char *qVSDC
= "\x26\x00\x00\x00";
581 qVSDC
= "\x26\x80\x00\x00";
585 TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD
587 // not standard for contactless. just for test.
589 TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC
592 TLV_ADD(0x9F66, qVSDC
); // qVSDC
595 TLV_ADD(0x9F66, qVSDC
); // qVSDC (VISA CDA not enabled)
602 void ProcessGPOResponseFormat1(struct tlvdb
*tlvRoot
, uint8_t *buf
, size_t len
, bool decodeTLV
) {
603 if (buf
[0] == 0x80) {
605 PrintAndLog("GPO response format1:");
606 TLVPrintFromBuffer(buf
, len
);
609 if (len
< 4 || (len
- 4) % 4) {
610 PrintAndLog("ERROR: GPO response format1 parsing error. length=%d", len
);
613 struct tlvdb
* f1AIP
= tlvdb_fixed(0x82, 2, buf
+ 2);
614 tlvdb_add(tlvRoot
, f1AIP
);
616 PrintAndLog("\n* * Decode response format 1 (0x80) AIP and AFL:");
617 TLVPrintFromTLV(f1AIP
);
621 struct tlvdb
* f1AFL
= tlvdb_fixed(0x94, len
- 4, buf
+ 2 + 2);
622 tlvdb_add(tlvRoot
, f1AFL
);
624 TLVPrintFromTLV(f1AFL
);
628 TLVPrintFromBuffer(buf
, len
);
632 int CmdHFEMVExec(const char *cmd
) {
633 uint8_t buf
[APDU_RES_LEN
] = {0};
636 uint8_t AID
[APDU_AID_LEN
] = {0};
638 uint8_t ODAiList
[4096];
639 size_t ODAiListLen
= 0;
643 struct tlvdb
*tlvSelect
= NULL
;
644 struct tlvdb
*tlvRoot
= NULL
;
645 struct tlv
*pdol_data_tlv
= NULL
;
647 CLIParserInit("hf emv exec",
648 "Executes EMV contactless transaction",
649 "Usage:\n\thf emv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n"
650 "\thf emv exec -satc -> select card, execute CDA transaction, show APDU and TLV\n");
654 arg_lit0("sS", "select", "activate field and select card."),
655 arg_lit0("aA", "apdu", "show APDU reqests and responses."),
656 arg_lit0("tT", "tlv", "TLV decode results."),
657 arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."),
658 arg_lit0("fF", "forceaid", "Force search AID. Search AID instead of execute PPSE."),
659 arg_rem("By default:", "Transaction type - MSD"),
660 arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."),
661 arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."),
662 arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."),
663 arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
666 CLIExecWithReturn(cmd
, argtable
, true);
668 bool activateField
= arg_get_lit(1);
669 bool showAPDU
= arg_get_lit(2);
670 bool decodeTLV
= arg_get_lit(3);
671 bool paramLoadJSON
= arg_get_lit(4);
672 bool forceSearch
= arg_get_lit(5);
674 enum TransactionType TrType
= TT_MSD
;
676 TrType
= TT_QVSDCMCHIP
;
682 bool GenACGPO
= arg_get_lit(9);
685 SetAPDULogging(showAPDU
);
687 // init applets list tree
688 const char *al
= "Applets list";
689 tlvSelect
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
691 // Application Selection
692 // https://www.openscdp.org/scripts/tutorial/emv/applicationselection.html
695 PrintAndLog("\n* PPSE.");
696 SetAPDULogging(showAPDU
);
697 res
= EMVSearchPSE(activateField
, true, decodeTLV
, tlvSelect
);
699 // check PPSE and select application id
701 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
702 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
708 PrintAndLog("\n* Search AID in list.");
709 SetAPDULogging(false);
710 if (EMVSearch(activateField
, true, decodeTLV
, tlvSelect
)) {
714 // check search and select application id
715 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
716 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
720 const char *alr
= "Root terminal TLV tree";
721 tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
723 // check if we found EMV application on card
725 PrintAndLog("Can't select AID. EMV AID not found");
730 PrintAndLog("\n* Selecting AID:%s", sprint_hex_inrow(AID
, AIDlen
));
731 SetAPDULogging(showAPDU
);
732 res
= EMVSelect(false, true, AID
, AIDlen
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
735 PrintAndLog("Can't select AID (%d). Exit...", res
);
740 TLVPrintFromBuffer(buf
, len
);
741 PrintAndLog("* Selected.");
743 PrintAndLog("\n* Init transaction parameters.");
744 InitTransactionParameters(tlvRoot
, paramLoadJSON
, TrType
, GenACGPO
);
745 TLVPrintFromTLV(tlvRoot
); // TODO delete!!!
747 PrintAndLog("\n* Calc PDOL.");
748 pdol_data_tlv
= dol_process(tlvdb_get(tlvRoot
, 0x9f38, NULL
), tlvRoot
, 0x83);
750 PrintAndLog("ERROR: can't create PDOL TLV.");
754 size_t pdol_data_tlv_data_len
;
755 unsigned char *pdol_data_tlv_data
= tlv_encode(pdol_data_tlv
, &pdol_data_tlv_data_len
);
756 if (!pdol_data_tlv_data
) {
757 PrintAndLog("ERROR: can't create PDOL data.");
760 PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
762 PrintAndLog("\n* GPO.");
763 res
= EMVGPO(true, pdol_data_tlv_data
, pdol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
765 free(pdol_data_tlv_data
);
766 //free(pdol_data_tlv); --- free on exit.
769 PrintAndLog("GPO error(%d): %4x. Exit...", res
, sw
);
773 // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
774 ProcessGPOResponseFormat1(tlvRoot
, buf
, len
, decodeTLV
);
776 // extract PAN from track2
778 const struct tlv
*track2
= tlvdb_get(tlvRoot
, 0x57, NULL
);
779 if (!tlvdb_get(tlvRoot
, 0x5a, NULL
) && track2
&& track2
->len
>= 8) {
780 struct tlvdb
*pan
= GetPANFromTrack2(track2
);
782 tlvdb_add(tlvRoot
, pan
);
784 const struct tlv
*pantlv
= tlvdb_get(tlvRoot
, 0x5a, NULL
);
785 PrintAndLog("\n* * Extracted PAN from track2: %s", sprint_hex(pantlv
->value
, pantlv
->len
));
787 PrintAndLog("\n* * WARNING: Can't extract PAN from track2.");
792 PrintAndLog("\n* Read records from AFL.");
793 const struct tlv
*AFL
= tlvdb_get(tlvRoot
, 0x94, NULL
);
794 if (!AFL
|| !AFL
->len
) {
795 PrintAndLog("WARNING: AFL not found.");
798 while(AFL
&& AFL
->len
) {
800 PrintAndLog("ERROR: Wrong AFL length: %d", AFL
->len
);
804 for (int i
= 0; i
< AFL
->len
/ 4; i
++) {
805 uint8_t SFI
= AFL
->value
[i
* 4 + 0] >> 3;
806 uint8_t SFIstart
= AFL
->value
[i
* 4 + 1];
807 uint8_t SFIend
= AFL
->value
[i
* 4 + 2];
808 uint8_t SFIoffline
= AFL
->value
[i
* 4 + 3];
810 PrintAndLog("* * SFI[%02x] start:%02x end:%02x offline:%02x", SFI
, SFIstart
, SFIend
, SFIoffline
);
811 if (SFI
== 0 || SFI
== 31 || SFIstart
== 0 || SFIstart
> SFIend
) {
812 PrintAndLog("SFI ERROR! Skipped...");
816 for(int n
= SFIstart
; n
<= SFIend
; n
++) {
817 PrintAndLog("* * * SFI[%02x] %d", SFI
, n
);
819 res
= EMVReadRecord(true, SFI
, n
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
821 PrintAndLog("ERROR SFI[%02x]. APDU error %4x", SFI
, sw
);
826 TLVPrintFromBuffer(buf
, len
);
830 // Build Input list for Offline Data Authentication
831 // EMV 4.3 book3 10.3, page 96
834 const unsigned char *abuf
= buf
;
837 if (tlv_parse_tl(&abuf
, &elmlen
, &e
)) {
838 memcpy(&ODAiList
[ODAiListLen
], &buf
[len
- elmlen
], elmlen
);
839 ODAiListLen
+= elmlen
;
841 PrintAndLog("ERROR SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI
);
844 memcpy(&ODAiList
[ODAiListLen
], buf
, len
);
854 // copy Input list for Offline Data Authentication
856 struct tlvdb
*oda
= tlvdb_fixed(0x21, ODAiListLen
, ODAiList
); // not a standard tag
857 tlvdb_add(tlvRoot
, oda
);
858 PrintAndLog("* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen
);
862 const struct tlv
*AIPtlv
= tlvdb_get(tlvRoot
, 0x82, NULL
);
863 uint16_t AIP
= AIPtlv
->value
[0] + AIPtlv
->value
[1] * 0x100;
864 PrintAndLog("* * AIP=%04x", AIP
);
868 PrintAndLog("\n* SDA");
874 PrintAndLog("\n* DDA");
875 trDDA(decodeTLV
, tlvRoot
);
881 if (TrType
== TT_QVSDCMCHIP
|| TrType
== TT_CDA
){
882 // 9F26: Application Cryptogram
883 const struct tlv
*AC
= tlvdb_get(tlvRoot
, 0x9F26, NULL
);
885 PrintAndLog("\n--> qVSDC transaction.");
886 PrintAndLog("* AC path");
888 // 9F36: Application Transaction Counter (ATC)
889 const struct tlv
*ATC
= tlvdb_get(tlvRoot
, 0x9F36, NULL
);
892 // 9F10: Issuer Application Data - optional
893 const struct tlv
*IAD
= tlvdb_get(tlvRoot
, 0x9F10, NULL
);
896 PrintAndLog("ATC: %s", sprint_hex(ATC
->value
, ATC
->len
));
897 PrintAndLog("AC: %s", sprint_hex(AC
->value
, AC
->len
));
899 PrintAndLog("IAD: %s", sprint_hex(IAD
->value
, IAD
->len
));
901 if (IAD
->len
>= IAD
->value
[0] + 1) {
902 PrintAndLog("\tKey index: 0x%02x", IAD
->value
[1]);
903 PrintAndLog("\tCrypto ver: 0x%02x(%03d)", IAD
->value
[2], IAD
->value
[2]);
904 PrintAndLog("\tCVR:", sprint_hex(&IAD
->value
[3], IAD
->value
[0] - 2));
905 struct tlvdb
* cvr
= tlvdb_fixed(0x20, IAD
->value
[0] - 2, &IAD
->value
[3]);
906 TLVPrintFromTLVLev(cvr
, 1);
909 PrintAndLog("WARNING: IAD not found.");
913 PrintAndLog("ERROR AC: Application Transaction Counter (ATC) not found.");
919 if (GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
&& (TrType
== TT_QVSDCMCHIP
|| TrType
== TT_CDA
)){
920 const struct tlv
*CDOL1
= tlvdb_get(tlvRoot
, 0x8c, NULL
);
921 if (CDOL1
&& GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
) { // and m/chip transaction flag
922 PrintAndLog("\n--> Mastercard M/Chip transaction.");
924 PrintAndLog("* * Generate challenge");
925 res
= EMVGenerateChallenge(true, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
927 PrintAndLog("ERROR GetChallenge. APDU error %4x", sw
);
931 PrintAndLog("ERROR GetChallenge. Wrong challenge length %d", len
);
935 // ICC Dynamic Number
936 struct tlvdb
* ICCDynN
= tlvdb_fixed(0x9f4c, len
, buf
);
937 tlvdb_add(tlvRoot
, ICCDynN
);
939 PrintAndLog("\n* * ICC Dynamic Number:");
940 TLVPrintFromTLV(ICCDynN
);
943 PrintAndLog("* * Calc CDOL1");
944 struct tlv
*cdol_data_tlv
= dol_process(tlvdb_get(tlvRoot
, 0x8c, NULL
), tlvRoot
, 0x01); // 0x01 - dummy tag
946 PrintAndLog("ERROR: can't create CDOL1 TLV.");
949 PrintAndLog("CDOL1 data[%d]: %s", cdol_data_tlv
->len
, sprint_hex(cdol_data_tlv
->value
, cdol_data_tlv
->len
));
951 PrintAndLog("* * AC1");
952 // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
953 res
= EMVAC(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
);
956 PrintAndLog("AC1 error(%d): %4x. Exit...", res
, sw
);
961 TLVPrintFromBuffer(buf
, len
);
964 PrintAndLog("\n* CDA:");
965 struct tlvdb
*ac_tlv
= tlvdb_parse_multi(buf
, len
);
966 res
= trCDA(tlvRoot
, ac_tlv
, pdol_data_tlv
, cdol_data_tlv
);
968 PrintAndLog("CDA error (%d)", res
);
973 PrintAndLog("\n* M/Chip transaction result:");
974 // 9F27: Cryptogram Information Data (CID)
975 const struct tlv
*CID
= tlvdb_get(tlvRoot
, 0x9F27, NULL
);
977 emv_tag_dump(CID
, stdout
, 0);
978 PrintAndLog("------------------------------");
980 switch(CID
->value
[0] & EMVAC_AC_MASK
){
982 PrintAndLog("Transaction DECLINED.");
985 PrintAndLog("Transaction approved OFFLINE.");
988 PrintAndLog("Transaction approved ONLINE.");
991 PrintAndLog("ERROR: CID transaction code error %2x", CID
->value
[0] & EMVAC_AC_MASK
);
995 PrintAndLog("ERROR: Wrong CID length %d", CID
->len
);
998 PrintAndLog("ERROR: CID(9F27) not found.");
1005 if (AIP
& 0x8000 && TrType
== TT_MSD
) {
1006 PrintAndLog("\n--> MSD transaction.");
1008 PrintAndLog("* MSD dCVV path. Check dCVV");
1010 const struct tlv
*track2
= tlvdb_get(tlvRoot
, 0x57, NULL
);
1012 PrintAndLog("Track2: %s", sprint_hex(track2
->value
, track2
->len
));
1014 struct tlvdb
*dCVV
= GetdCVVRawFromTrack2(track2
);
1015 PrintAndLog("dCVV raw data:");
1016 TLVPrintFromTLV(dCVV
);
1018 if (GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
) {
1019 PrintAndLog("\n* Mastercard calculate UDOL");
1022 const struct tlv
*UDOL
= tlvdb_get(tlvRoot
, 0x9F69, NULL
);
1023 // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
1024 const struct tlv defUDOL
= {
1027 .value
= (uint8_t *)"\x9f\x6a\x04",
1030 PrintAndLog("Use default UDOL.");
1032 struct tlv
*udol_data_tlv
= dol_process(UDOL
? UDOL
: &defUDOL
, tlvRoot
, 0x01); // 0x01 - dummy tag
1033 if (!udol_data_tlv
){
1034 PrintAndLog("ERROR: can't create UDOL TLV.");
1038 PrintAndLog("UDOL data[%d]: %s", udol_data_tlv
->len
, sprint_hex(udol_data_tlv
->value
, udol_data_tlv
->len
));
1040 PrintAndLog("\n* Mastercard compute cryptographic checksum(UDOL)");
1042 res
= MSCComputeCryptoChecksum(true, (uint8_t *)udol_data_tlv
->value
, udol_data_tlv
->len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1044 PrintAndLog("ERROR Compute Crypto Checksum. APDU error %4x", sw
);
1045 free(udol_data_tlv
);
1050 TLVPrintFromBuffer(buf
, len
);
1053 free(udol_data_tlv
);
1057 PrintAndLog("ERROR MSD: Track2 data not found.");
1065 free(pdol_data_tlv
);
1066 tlvdb_free(tlvSelect
);
1067 tlvdb_free(tlvRoot
);
1069 PrintAndLog("\n* Transaction completed.");
1074 int CmdHFEMVScan(const char *cmd
) {
1075 uint8_t AID
[APDU_AID_LEN
] = {0};
1077 uint8_t buf
[APDU_RES_LEN
] = {0};
1084 CLIParserInit("hf emv scan",
1085 "Scan EMV card and save it contents to a file.",
1086 "It executes EMV contactless transaction and saves result to a file which can be used for emulation\n"
1087 "Usage:\n\thf emv scan -at -> scan MSD transaction mode and show APDU and TLV\n"
1088 "\thf emv scan -c -> scan CDA transaction mode\n");
1090 void* argtable
[] = {
1092 arg_lit0("aA", "apdu", "show APDU reqests and responses."),
1093 arg_lit0("tT", "tlv", "TLV decode results."),
1094 arg_lit0("eE", "extract", "Extract TLV elements and fill Application Data"),
1095 arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."),
1096 arg_rem("By default:", "Transaction type - MSD"),
1097 arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."),
1098 arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."),
1099 arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."),
1100 arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
1101 arg_lit0("mM", "merge", "Merge output file with card's data. (warning: the file may be corrupted!)"),
1102 arg_str1(NULL
, NULL
, "output.json", "JSON output file name"),
1105 CLIExecWithReturn(cmd
, argtable
, true);
1107 bool showAPDU
= arg_get_lit(1);
1108 bool decodeTLV
= arg_get_lit(2);
1109 bool extractTLVElements
= arg_get_lit(3);
1110 bool paramLoadJSON
= arg_get_lit(4);
1112 enum TransactionType TrType
= TT_MSD
;
1114 TrType
= TT_QVSDCMCHIP
;
1120 bool GenACGPO
= arg_get_lit(9);
1121 bool MergeJSON
= arg_get_lit(10);
1122 uint8_t relfname
[250] ={0};
1123 char *crelfname
= (char *)relfname
;
1124 int relfnamelen
= 0;
1125 CLIGetStrWithReturn(11, relfname
, &relfnamelen
);
1128 SetAPDULogging(showAPDU
);
1130 // current path + file name
1131 if (!strstr(crelfname
, ".json"))
1132 strcat(crelfname
, ".json");
1133 char fname
[strlen(get_my_executable_directory()) + strlen(crelfname
) + 1];
1134 strcpy(fname
, get_my_executable_directory());
1135 strcat(fname
, crelfname
);
1138 root
= json_load_file(fname
, 0, &error
);
1140 PrintAndLog("ERROR: json error on line %d: %s", error
.line
, error
.text
);
1144 if (!json_is_object(root
)) {
1145 PrintAndLog("ERROR: Invalid json format. root must be an object.");
1149 root
= json_object();
1152 // drop field at start
1156 PrintAndLog("--> GET UID, ATS.");
1158 iso14a_card_select_t card
;
1159 if (Hf14443_4aGetCardData(&card
)) {
1163 JsonSaveStr(root
, "$.File.Created", "proxmark3 `hf emv scan`");
1165 JsonSaveStr(root
, "$.Card.Communication", "iso14443-4a");
1166 JsonSaveBufAsHex(root
, "$.Card.UID", (uint8_t *)&card
.uid
, card
.uidlen
);
1167 JsonSaveHex(root
, "$.Card.ATQA", card
.atqa
[0] + (card
.atqa
[1] << 2), 2);
1168 JsonSaveHex(root
, "$.Card.SAK", card
.sak
, 0);
1169 JsonSaveBufAsHex(root
, "$.Card.ATS", (uint8_t *)card
.ats
, card
.ats_len
);
1171 // init applets list tree
1172 const char *al
= "Applets list";
1173 struct tlvdb
*tlvSelect
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
1176 PrintAndLog("--> PPSE.");
1177 res
= EMVSelectPSE(true, true, 2, buf
, sizeof(buf
), &len
, &sw
);
1179 if (!res
&& sw
== 0x9000){
1181 TLVPrintFromBuffer(buf
, len
);
1183 JsonSaveBufAsHex(root
, "$.PPSE.AID", (uint8_t *)"2PAY.SYS.DDF01", 14);
1185 struct tlvdb
*fci
= tlvdb_parse_multi(buf
, len
);
1186 if (extractTLVElements
)
1187 JsonSaveTLVTree(root
, root
, "$.PPSE.FCITemplate", fci
);
1189 JsonSaveTLVTreeElm(root
, "$.PPSE.FCITemplate", fci
, true, true, false);
1190 JsonSaveTLVValue(root
, "$.Application.KernelID", tlvdb_find_full(fci
, 0x9f2a));
1194 res
= EMVSearchPSE(false, true, decodeTLV
, tlvSelect
);
1196 // check PPSE and select application id
1198 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
1200 // EMV SEARCH with AID list
1201 SetAPDULogging(false);
1202 PrintAndLog("--> AID search.");
1203 if (EMVSearch(false, true, decodeTLV
, tlvSelect
)) {
1204 PrintAndLog("E->Can't found any of EMV AID. Exit...");
1205 tlvdb_free(tlvSelect
);
1210 // check search and select application id
1211 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
1214 // EMV SELECT application
1215 SetAPDULogging(showAPDU
);
1216 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
1218 tlvdb_free(tlvSelect
);
1221 PrintAndLog("Can't select AID. EMV AID not found. Exit...");
1226 JsonSaveBufAsHex(root
, "$.Application.AID", AID
, AIDlen
);
1229 const char *alr
= "Root terminal TLV tree";
1230 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
1232 // EMV SELECT applet
1234 PrintAndLog("\n-->Selecting AID:%s.", sprint_hex_inrow(AID
, AIDlen
));
1235 SetAPDULogging(showAPDU
);
1236 res
= EMVSelect(false, true, AID
, AIDlen
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1239 PrintAndLog("E->Can't select AID (%d). Exit...", res
);
1240 tlvdb_free(tlvRoot
);
1246 TLVPrintFromBuffer(buf
, len
);
1249 if (tlvdb_get(tlvRoot
, 0x9f38, NULL
)) {
1250 JsonSaveStr(root
, "$.Application.Mode", TransactionTypeStr
[TrType
]);
1253 struct tlvdb
*fci
= tlvdb_parse_multi(buf
, len
);
1254 if (extractTLVElements
)
1255 JsonSaveTLVTree(root
, root
, "$.Application.FCITemplate", fci
);
1257 JsonSaveTLVTreeElm(root
, "$.Application.FCITemplate", fci
, true, true, false);
1260 // create transaction parameters
1261 PrintAndLog("-->Init transaction parameters.");
1262 InitTransactionParameters(tlvRoot
, paramLoadJSON
, TrType
, GenACGPO
);
1264 PrintAndLog("-->Calc PDOL.");
1265 struct tlv
*pdol_data_tlv
= dol_process(tlvdb_get(tlvRoot
, 0x9f38, NULL
), tlvRoot
, 0x83);
1266 if (!pdol_data_tlv
){
1267 PrintAndLog("E->Can't create PDOL TLV.");
1268 tlvdb_free(tlvRoot
);
1273 size_t pdol_data_tlv_data_len
;
1274 unsigned char *pdol_data_tlv_data
= tlv_encode(pdol_data_tlv
, &pdol_data_tlv_data_len
);
1275 if (!pdol_data_tlv_data
) {
1276 PrintAndLog("E->Can't create PDOL data.");
1277 tlvdb_free(tlvRoot
);
1281 PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
1283 PrintAndLog("-->GPO.");
1284 res
= EMVGPO(true, pdol_data_tlv_data
, pdol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1286 free(pdol_data_tlv_data
);
1287 free(pdol_data_tlv
);
1290 PrintAndLog("GPO error(%d): %4x. Exit...", res
, sw
);
1291 tlvdb_free(tlvRoot
);
1295 ProcessGPOResponseFormat1(tlvRoot
, buf
, len
, decodeTLV
);
1297 struct tlvdb
*gpofci
= tlvdb_parse_multi(buf
, len
);
1298 if (extractTLVElements
)
1299 JsonSaveTLVTree(root
, root
, "$.Application.GPO", gpofci
);
1301 JsonSaveTLVTreeElm(root
, "$.Application.GPO", gpofci
, true, true, false);
1303 JsonSaveTLVValue(root
, "$.ApplicationData.AIP", tlvdb_find_full(gpofci
, 0x82));
1304 JsonSaveTLVValue(root
, "$.ApplicationData.AFL", tlvdb_find_full(gpofci
, 0x94));
1308 PrintAndLog("-->Read records from AFL.");
1309 const struct tlv
*AFL
= tlvdb_get(tlvRoot
, 0x94, NULL
);
1311 while(AFL
&& AFL
->len
) {
1313 PrintAndLog("E->Wrong AFL length: %d", AFL
->len
);
1317 json_t
*sfijson
= json_path_get(root
, "$.Application.Records");
1319 json_t
*app
= json_path_get(root
, "$.Application");
1320 json_object_set_new(app
, "Records", json_array());
1322 sfijson
= json_path_get(root
, "$.Application.Records");
1324 if (!json_is_array(sfijson
)) {
1325 PrintAndLog("E->Internal logic error. `$.Application.Records` is not an array.");
1328 for (int i
= 0; i
< AFL
->len
/ 4; i
++) {
1329 uint8_t SFI
= AFL
->value
[i
* 4 + 0] >> 3;
1330 uint8_t SFIstart
= AFL
->value
[i
* 4 + 1];
1331 uint8_t SFIend
= AFL
->value
[i
* 4 + 2];
1332 uint8_t SFIoffline
= AFL
->value
[i
* 4 + 3];
1334 PrintAndLog("--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI
, SFIstart
, SFIend
, SFIoffline
);
1335 if (SFI
== 0 || SFI
== 31 || SFIstart
== 0 || SFIstart
> SFIend
) {
1336 PrintAndLog("SFI ERROR! Skipped...");
1340 for(int n
= SFIstart
; n
<= SFIend
; n
++) {
1341 PrintAndLog("---->SFI[%02x] %d", SFI
, n
);
1343 res
= EMVReadRecord(true, SFI
, n
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1345 PrintAndLog("E->SFI[%02x]. APDU error %4x", SFI
, sw
);
1350 TLVPrintFromBuffer(buf
, len
);
1354 json_t
*jsonelm
= json_object();
1355 json_array_append_new(sfijson
, jsonelm
);
1357 JsonSaveHex(jsonelm
, "SFI", SFI
, 1);
1358 JsonSaveHex(jsonelm
, "RecordNum", n
, 1);
1359 JsonSaveHex(jsonelm
, "Offline", SFIoffline
, 1);
1361 struct tlvdb
*rsfi
= tlvdb_parse_multi(buf
, len
);
1362 if (extractTLVElements
)
1363 JsonSaveTLVTree(root
, jsonelm
, "$.Data", rsfi
);
1365 JsonSaveTLVTreeElm(jsonelm
, "$.Data", rsfi
, true, true, false);
1373 // getting certificates
1374 if (tlvdb_get(tlvRoot
, 0x90, NULL
)) {
1375 PrintAndLog("-->Recovering certificates.");
1376 PKISetStrictExecution(false);
1377 RecoveryCertificates(tlvRoot
, root
);
1378 PKISetStrictExecution(true);
1382 tlvdb_free(tlvRoot
);
1387 res
= json_dump_file(root
, fname
, JSON_INDENT(2));
1389 PrintAndLog("ERROR: can't save the file: %s", fname
);
1392 PrintAndLog("File `%s` saved.", fname
);
1400 int CmdHFEMVTest(const char *cmd
) {
1401 return ExecuteCryptoTests(true);
1404 int CmdHelp(const char *Cmd
);
1405 static command_t CommandTable
[] = {
1406 {"help", CmdHelp
, 1, "This help"},
1407 {"exec", CmdHFEMVExec
, 0, "Executes EMV contactless transaction."},
1408 {"pse", CmdHFEMVPPSE
, 0, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."},
1409 {"search", CmdHFEMVSearch
, 0, "Try to select all applets from applets list and print installed applets."},
1410 {"select", CmdHFEMVSelect
, 0, "Select applet."},
1411 {"gpo", CmdHFEMVGPO
, 0, "Execute GetProcessingOptions."},
1412 {"readrec", CmdHFEMVReadRecord
, 0, "Read files from card."},
1413 {"genac", CmdHFEMVAC
, 0, "Generate ApplicationCryptogram."},
1414 {"challenge", CmdHFEMVGenerateChallenge
, 0, "Generate challenge."},
1415 {"intauth", CmdHFEMVInternalAuthenticate
, 0, "Internal authentication."},
1416 {"scan", CmdHFEMVScan
, 0, "Scan EMV card and save it contents to json file for emulator."},
1417 {"test", CmdHFEMVTest
, 0, "Crypto logic test."},
1418 {NULL
, NULL
, 0, NULL
}
1421 int CmdHFEMV(const char *Cmd
) {
1422 CmdsParse(CommandTable
, Cmd
);
1426 int CmdHelp(const char *Cmd
) {
1427 CmdsHelp(CommandTable
);