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 //-----------------------------------------------------------------------------
13 #include "test/cryptotest.h"
14 #include "cliparser/cliparser.h"
17 int CmdHFEMVSelect(const char *cmd
) {
18 uint8_t data
[APDU_AID_LEN
] = {0};
22 CLIParserInit("hf emv select",
23 "Executes select applet command",
24 "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");
28 arg_lit0("sS", "select", "activate field and select card"),
29 arg_lit0("kK", "keep", "keep field for next command"),
30 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
31 arg_lit0("tT", "tlv", "TLV decode results"),
32 arg_str0(NULL
, NULL
, "<HEX applet AID>", NULL
),
35 CLIExecWithReturn(cmd
, argtable
, true);
37 bool activateField
= arg_get_lit(1);
38 bool leaveSignalON
= arg_get_lit(2);
39 bool APDULogging
= arg_get_lit(3);
40 bool decodeTLV
= arg_get_lit(4);
41 CLIGetStrWithReturn(5, data
, &datalen
);
44 SetAPDULogging(APDULogging
);
47 uint8_t buf
[APDU_RES_LEN
] = {0};
50 int res
= EMVSelect(activateField
, leaveSignalON
, data
, datalen
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
53 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
59 TLVPrintFromBuffer(buf
, len
);
64 int CmdHFEMVSearch(const char *cmd
) {
66 CLIParserInit("hf emv search",
67 "Tries to select all applets from applet list:\n",
68 "Usage:\n\thf emv search -s -> select card and search\n\thf emv search -st -> select card, search and show result in TLV\n");
72 arg_lit0("sS", "select", "activate field and select card"),
73 arg_lit0("kK", "keep", "keep field ON for next command"),
74 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
75 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
78 CLIExecWithReturn(cmd
, argtable
, true);
80 bool activateField
= arg_get_lit(1);
81 bool leaveSignalON
= arg_get_lit(2);
82 bool APDULogging
= arg_get_lit(3);
83 bool decodeTLV
= arg_get_lit(4);
86 SetAPDULogging(APDULogging
);
88 struct tlvdb
*t
= NULL
;
89 const char *al
= "Applets list";
90 t
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
92 if (EMVSearch(activateField
, leaveSignalON
, decodeTLV
, t
)) {
97 PrintAndLog("Search completed.");
101 TLVPrintAIDlistFromSelectTLV(t
);
109 int CmdHFEMVPPSE(const char *cmd
) {
111 CLIParserInit("hf emv pse",
112 "Executes PSE/PPSE select command. It returns list of applet on the card:\n",
113 "Usage:\n\thf emv pse -s1 -> select, get pse\n\thf emv pse -st2 -> select, get ppse, show result in TLV\n");
117 arg_lit0("sS", "select", "activate field and select card"),
118 arg_lit0("kK", "keep", "keep field ON for next command"),
119 arg_lit0("1", "pse", "pse (1PAY.SYS.DDF01) mode"),
120 arg_lit0("2", "ppse", "ppse (2PAY.SYS.DDF01) mode (default mode)"),
121 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
122 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
125 CLIExecWithReturn(cmd
, argtable
, true);
127 bool activateField
= arg_get_lit(1);
128 bool leaveSignalON
= arg_get_lit(2);
134 bool APDULogging
= arg_get_lit(5);
135 bool decodeTLV
= arg_get_lit(6);
138 SetAPDULogging(APDULogging
);
141 uint8_t buf
[APDU_RES_LEN
] = {0};
144 int res
= EMVSelectPSE(activateField
, leaveSignalON
, PSENum
, buf
, sizeof(buf
), &len
, &sw
);
147 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
154 TLVPrintFromBuffer(buf
, len
);
159 #define TLV_ADD(tag, value)( tlvdb_change_or_add_node(tlvRoot, tag, sizeof(value) - 1, (const unsigned char *)value) )
161 int CmdHFEMVGPO(const char *cmd
) {
162 uint8_t data
[APDU_RES_LEN
] = {0};
165 CLIParserInit("hf emv gpo",
166 "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.",
167 "Usage:\n\thf emv gpo -k -> execute GPO\n"
168 "\thf emv gpo -st 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n");
169 // here need to add load params from file and gen pdol
173 arg_lit0("kK", "keep", "keep field ON for next command"),
174 arg_lit0("pP", "params", "load parameters for PDOL making from `emv/defparams.json` file (by default uses default parameters) (NOT WORK!!!)"),
175 arg_lit0("mM", "make", "make PDOLdata from PDOL (tag 9F38) and parameters (NOT WORK!!!)"),
176 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
177 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
178 arg_str0(NULL
, NULL
, "<HEX PDOLdata/PDOL>", NULL
),
181 CLIExecWithReturn(cmd
, argtable
, true);
183 bool leaveSignalON
= arg_get_lit(1);
184 bool paramsLoadFromFile
= arg_get_lit(2);
185 bool dataMakeFromPDOL
= arg_get_lit(3);
186 bool APDULogging
= arg_get_lit(4);
187 bool decodeTLV
= arg_get_lit(5);
188 CLIGetStrWithReturn(6, data
, &datalen
);
191 SetAPDULogging(APDULogging
);
194 const char *alr
= "Root terminal TLV tree";
195 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
198 struct tlv
*pdol_data_tlv
= NULL
;
199 struct tlv data_tlv
= {
202 .value
= (uint8_t *)data
,
204 if (dataMakeFromPDOL
) {
206 PrintAndLog("Make PDOL data not implemented!");
208 //9F02:(Amount, authorized (Numeric)) len:6
209 TLV_ADD(0x9F02, "\x00\x00\x00\x00\x01\x00");
210 //9F1A:(Terminal Country Code) len:2
211 TLV_ADD(0x9F1A, "ru");
212 //5F2A:(Transaction Currency Code) len:2
213 // USD 840, EUR 978, RUR 810, RUB 643, RUR 810(old), UAH 980, AZN 031, n/a 999
214 TLV_ADD(0x5F2A, "\x09\x80");
215 //9A:(Transaction Date) len:3
216 TLV_ADD(0x9A, "\x00\x00\x00");
217 //9C:(Transaction Type) len:1 | 00 => Goods and service #01 => Cash
218 TLV_ADD(0x9C, "\x00");
219 // 9F37 Unpredictable Number len:4
220 TLV_ADD(0x9F37, "\x01\x02\x03\x04");
221 // 9F6A Unpredictable Number (MSD for UDOL) len:4
222 TLV_ADD(0x9F6A, "\x01\x02\x03\x04");
223 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
224 TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC
226 if (paramsLoadFromFile
) {
228 /* pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
230 PrintAndLog("ERROR: can't create PDOL TLV.");
236 pdol_data_tlv
= &data_tlv
;
239 size_t pdol_data_tlv_data_len
= 0;
240 unsigned char *pdol_data_tlv_data
= tlv_encode(pdol_data_tlv
, &pdol_data_tlv_data_len
);
241 if (!pdol_data_tlv_data
) {
242 PrintAndLog("ERROR: can't create PDOL data.");
246 PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
249 uint8_t buf
[APDU_RES_LEN
] = {0};
252 int res
= EMVGPO(leaveSignalON
, pdol_data_tlv_data
, pdol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
254 free(pdol_data_tlv_data
);
258 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
264 TLVPrintFromBuffer(buf
, len
);
269 int CmdHFEMVReadRecord(const char *cmd
) {
270 uint8_t data
[APDU_RES_LEN
] = {0};
273 CLIParserInit("hf emv readrec",
274 "Executes Read Record command. It returns data in TLV format.\nNeeds a bank applet to be selected and sometimes needs GPO to be executed.",
275 "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");
279 arg_lit0("kK", "keep", "keep field ON for next command"),
280 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
281 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
282 arg_str1(NULL
, NULL
, "<SFI 1byte HEX><SFIrec 1byte HEX>", NULL
),
285 CLIExecWithReturn(cmd
, argtable
, true);
287 bool leaveSignalON
= arg_get_lit(1);
288 bool APDULogging
= arg_get_lit(2);
289 bool decodeTLV
= arg_get_lit(3);
290 CLIGetStrWithReturn(4, data
, &datalen
);
294 PrintAndLog("ERROR: Command needs to have 2 bytes of data");
298 SetAPDULogging(APDULogging
);
301 uint8_t buf
[APDU_RES_LEN
] = {0};
304 int res
= EMVReadRecord(leaveSignalON
, data
[0], data
[1], buf
, sizeof(buf
), &len
, &sw
, NULL
);
307 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
314 TLVPrintFromBuffer(buf
, len
);
319 int CmdHFEMVAC(const char *cmd
) {
320 uint8_t data
[APDU_RES_LEN
] = {0};
323 CLIParserInit("hf emv genac",
324 "Generate Application Cryptogram command. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.",
325 "Usage:\n\thf emv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n"
326 "\thf emv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n"
327 "\thf emv genac -Daac 01020304 -> generate AC with 4-byte CDOL data and terminal decision 'declined'\n");
331 arg_lit0("kK", "keep", "keep field ON for next command"),
332 arg_lit0("cC", "cda", "executes CDA transaction. Needs to get SDAD in results."),
333 arg_str0("dD", "decision", "<aac|tc|arqc>", "Terminal decision. aac - declined, tc - approved, arqc - online authorisation requested"),
334 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
335 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
336 arg_str1(NULL
, NULL
, "<HEX CDOLdata>", NULL
),
339 CLIExecWithReturn(cmd
, argtable
, false);
341 bool leaveSignalON
= arg_get_lit(1);
342 bool trTypeCDA
= arg_get_lit(2);
343 uint8_t termDecision
= 0xff;
344 if (arg_get_str_len(3)) {
345 if (!strncmp(arg_get_str(3)->sval
[0], "aac", 4))
346 termDecision
= EMVAC_AAC
;
347 if (!strncmp(arg_get_str(3)->sval
[0], "tc", 4))
348 termDecision
= EMVAC_TC
;
349 if (!strncmp(arg_get_str(3)->sval
[0], "arqc", 4))
350 termDecision
= EMVAC_ARQC
;
352 if (termDecision
== 0xff) {
353 PrintAndLog("ERROR: can't find terminal decision '%s'", arg_get_str(3)->sval
[0]);
357 termDecision
= EMVAC_TC
;
360 termDecision
= termDecision
| EMVAC_CDAREQ
;
361 bool APDULogging
= arg_get_lit(4);
362 bool decodeTLV
= arg_get_lit(5);
363 CLIGetStrWithReturn(6, data
, &datalen
);
366 SetAPDULogging(APDULogging
);
369 const char *alr
= "Root terminal TLV tree";
370 struct tlvdb
*tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
373 struct tlv
*cdol_data_tlv
= NULL
;
374 // struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
375 struct tlv data_tlv
= {
378 .value
= (uint8_t *)data
,
380 cdol_data_tlv
= &data_tlv
;
381 PrintAndLog("CDOL data[%d]: %s", cdol_data_tlv
->len
, sprint_hex(cdol_data_tlv
->value
, cdol_data_tlv
->len
));
384 uint8_t buf
[APDU_RES_LEN
] = {0};
387 int res
= EMVAC(leaveSignalON
, termDecision
, (uint8_t *)cdol_data_tlv
->value
, cdol_data_tlv
->len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
389 // free(cdol_data_tlv);
393 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
399 TLVPrintFromBuffer(buf
, len
);
404 int CmdHFEMVGenerateChallenge(const char *cmd
) {
406 CLIParserInit("hf emv challenge",
407 "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.",
408 "Usage:\n\thf emv challenge -> get challenge\n\thf emv challenge -k -> get challenge, keep fileld ON\n");
412 arg_lit0("kK", "keep", "keep field ON for next command"),
413 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
416 CLIExecWithReturn(cmd
, argtable
, true);
418 bool leaveSignalON
= arg_get_lit(1);
419 bool APDULogging
= arg_get_lit(2);
422 SetAPDULogging(APDULogging
);
425 uint8_t buf
[APDU_RES_LEN
] = {0};
428 int res
= EMVGenerateChallenge(leaveSignalON
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
431 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
436 PrintAndLog("Challenge: %s", sprint_hex(buf
, len
));
438 if (len
!= 4 && len
!= 8)
439 PrintAndLog("WARNING: length of challenge must be 4 or 8, but it %d", len
);
444 int CmdHFEMVInternalAuthenticate(const char *cmd
) {
445 uint8_t data
[APDU_RES_LEN
] = {0};
448 CLIParserInit("hf emv intauth",
449 "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.",
450 "Usage:\n\thf emv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n"
451 "\thf emv intauth -t 01020304 -> execute Internal Authenticate with 4-byte DDOL data, show result in TLV\n");
455 arg_lit0("kK", "keep", "keep field ON for next command"),
456 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
457 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
458 arg_str1(NULL
, NULL
, "<HEX DDOLdata>", NULL
),
461 CLIExecWithReturn(cmd
, argtable
, false);
463 bool leaveSignalON
= arg_get_lit(1);
464 bool APDULogging
= arg_get_lit(2);
465 bool decodeTLV
= arg_get_lit(3);
466 CLIGetStrWithReturn(4, data
, &datalen
);
469 SetAPDULogging(APDULogging
);
472 PrintAndLog("DDOL data[%d]: %s", datalen
, sprint_hex(data
, datalen
));
475 uint8_t buf
[APDU_RES_LEN
] = {0};
478 int res
= EMVInternalAuthenticate(leaveSignalON
, data
, datalen
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
481 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
487 TLVPrintFromBuffer(buf
, len
);
492 int UsageCmdHFEMVExec(void) {
493 PrintAndLog("HELP : Executes EMV contactless transaction:\n");
494 PrintAndLog("Usage: hf emv exec [-s][-a][-t][-j][-f][-v][-c][-x][-g]\n");
495 PrintAndLog(" Options:");
496 PrintAndLog(" -s : select card");
497 PrintAndLog(" -a : show APDU reqests and responses\n");
498 PrintAndLog(" -t : TLV decode results\n");
499 PrintAndLog(" -j : load transaction parameters from `emv/defparams.json` file\n");
500 PrintAndLog(" -f : force search AID. Search AID instead of execute PPSE.\n");
501 PrintAndLog(" -v : transaction type - qVSDC or M/Chip.\n");
502 PrintAndLog(" -c : transaction type - qVSDC or M/Chip plus CDA (SDAD generation).\n");
503 PrintAndLog(" -x : transaction type - VSDC. For test only. Not a standart behavior.\n");
504 PrintAndLog(" -g : VISA. generate AC from GPO\n");
505 PrintAndLog("By default : transaction type - MSD.\n");
506 PrintAndLog("Samples:");
507 PrintAndLog(" hf emv exec -s -a -t -> execute MSD transaction");
508 PrintAndLog(" hf emv exec -s -a -t -c -> execute CDA transaction");
512 #define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;}
514 bool HexToBuffer(const char *errormsg
, const char *hexvalue
, uint8_t * buffer
, size_t maxbufferlen
, size_t *bufferlen
) {
517 switch(param_gethex_to_eol(hexvalue
, 0, buffer
, maxbufferlen
, &buflen
)) {
519 PrintAndLog("%s Invalid HEX value.", errormsg
);
522 PrintAndLog("%s Hex value too large.", errormsg
);
525 PrintAndLog("%s Hex value must have even number of digits.", errormsg
);
529 if (buflen
> maxbufferlen
) {
530 PrintAndLog("%s HEX length (%d) more than %d", errormsg
, *bufferlen
, maxbufferlen
);
539 bool ParamLoadFromJson(struct tlvdb
*tlv
) {
544 PrintAndLog("ERROR load params: tlv tree is NULL.");
548 // current path + file name
549 const char *relfname
= "emv/defparams.json";
550 char fname
[strlen(get_my_executable_directory()) + strlen(relfname
) + 1];
551 strcpy(fname
, get_my_executable_directory());
552 strcat(fname
, relfname
);
554 root
= json_load_file(fname
, 0, &error
);
556 PrintAndLog("Load params: json error on line %d: %s", error
.line
, error
.text
);
560 if (!json_is_array(root
)) {
561 PrintAndLog("Load params: Invalid json format. root must be array.");
565 PrintAndLog("Load params: json OK");
567 for(int i
= 0; i
< json_array_size(root
); i
++) {
568 json_t
*data
, *jtype
, *jlength
, *jvalue
;
570 data
= json_array_get(root
, i
);
571 if(!json_is_object(data
))
573 PrintAndLog("Load params: data [%d] is not an object", i
+ 1);
578 jtype
= json_object_get(data
, "type");
579 if(!json_is_string(jtype
))
581 PrintAndLog("Load params: data [%d] type is not a string", i
+ 1);
585 const char *tlvType
= json_string_value(jtype
);
587 jvalue
= json_object_get(data
, "value");
588 if(!json_is_string(jvalue
))
590 PrintAndLog("Load params: data [%d] value is not a string", i
+ 1);
594 const char *tlvValue
= json_string_value(jvalue
);
596 jlength
= json_object_get(data
, "length");
597 if(!json_is_number(jlength
))
599 PrintAndLog("Load params: data [%d] length is not a number", i
+ 1);
604 int tlvLength
= json_integer_value(jlength
);
605 if (tlvLength
> 250) {
606 PrintAndLog("Load params: data [%d] length more than 250", i
+ 1);
611 PrintAndLog("TLV param: %s[%d]=%s", tlvType
, tlvLength
, tlvValue
);
612 uint8_t buf
[251] = {0};
615 // here max length must be 4, but now tlv_tag_t is 2-byte var. so let it be 2 by now... TODO: needs refactoring tlv_tag_t...
616 if (!HexToBuffer("TLV Error type:", tlvType
, buf
, 2, &buflen
)) {
621 for (int i
= 0; i
< buflen
; i
++) {
622 tag
= (tag
<< 8) + buf
[i
];
625 if (!HexToBuffer("TLV Error value:", tlvValue
, buf
, sizeof(buf
) - 1, &buflen
)) {
630 if (buflen
!= tlvLength
) {
631 PrintAndLog("Load params: data [%d] length of HEX must(%d) be identical to length in TLV param(%d)", i
+ 1, buflen
, tlvLength
);
636 tlvdb_change_or_add_node(tlv
, tag
, tlvLength
, (const unsigned char *)buf
);
644 void ParamLoadDefaults(struct tlvdb
*tlvRoot
) {
645 //9F02:(Amount, authorized (Numeric)) len:6
646 TLV_ADD(0x9F02, "\x00\x00\x00\x00\x01\x00");
647 //9F1A:(Terminal Country Code) len:2
648 TLV_ADD(0x9F1A, "ru");
649 //5F2A:(Transaction Currency Code) len:2
650 // USD 840, EUR 978, RUR 810, RUB 643, RUR 810(old), UAH 980, AZN 031, n/a 999
651 TLV_ADD(0x5F2A, "\x09\x80");
652 //9A:(Transaction Date) len:3
653 TLV_ADD(0x9A, "\x00\x00\x00");
654 //9C:(Transaction Type) len:1 | 00 => Goods and service #01 => Cash
655 TLV_ADD(0x9C, "\x00");
656 // 9F37 Unpredictable Number len:4
657 TLV_ADD(0x9F37, "\x01\x02\x03\x04");
658 // 9F6A Unpredictable Number (MSD for UDOL) len:4
659 TLV_ADD(0x9F6A, "\x01\x02\x03\x04");
660 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
661 TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC
664 int CmdHFEMVExec(const char *cmd
) {
665 bool activateField
= false;
666 bool showAPDU
= false;
667 bool decodeTLV
= false;
668 bool forceSearch
= false;
669 enum TransactionType TrType
= TT_MSD
;
670 bool GenACGPO
= false;
671 bool paramLoadJSON
= false;
673 uint8_t buf
[APDU_RES_LEN
] = {0};
676 uint8_t AID
[APDU_AID_LEN
] = {0};
678 uint8_t ODAiList
[4096];
679 size_t ODAiListLen
= 0;
683 struct tlvdb
*tlvSelect
= NULL
;
684 struct tlvdb
*tlvRoot
= NULL
;
685 struct tlv
*pdol_data_tlv
= NULL
;
687 if (strlen(cmd
) < 1) {
693 while(param_getchar(cmd
, cmdp
) != 0x00) {
694 char c
= param_getchar(cmd
, cmdp
);
695 if ((c
== '-') && (param_getlength(cmd
, cmdp
) == 2))
696 switch (param_getchar_indx(cmd
, 1, cmdp
)) {
703 activateField
= true;
723 TrType
= TT_QVSDCMCHIP
;
735 paramLoadJSON
= true;
738 PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd
, 1, cmdp
));
745 // init applets list tree
746 const char *al
= "Applets list";
747 tlvSelect
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
749 // Application Selection
750 // https://www.openscdp.org/scripts/tutorial/emv/applicationselection.html
753 PrintAndLog("\n* PPSE.");
754 SetAPDULogging(showAPDU
);
755 res
= EMVSearchPSE(activateField
, true, decodeTLV
, tlvSelect
);
757 // check PPSE and select application id
759 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
760 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
766 PrintAndLog("\n* Search AID in list.");
767 SetAPDULogging(false);
768 if (EMVSearch(activateField
, true, decodeTLV
, tlvSelect
)) {
772 // check search and select application id
773 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
774 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
778 const char *alr
= "Root terminal TLV tree";
779 tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
781 // check if we found EMV application on card
783 PrintAndLog("Can't select AID. EMV AID not found");
788 PrintAndLog("\n* Selecting AID:%s", sprint_hex_inrow(AID
, AIDlen
));
789 SetAPDULogging(showAPDU
);
790 res
= EMVSelect(false, true, AID
, AIDlen
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
793 PrintAndLog("Can't select AID (%d). Exit...", res
);
798 TLVPrintFromBuffer(buf
, len
);
799 PrintAndLog("* Selected.");
801 PrintAndLog("\n* Init transaction parameters.");
803 ParamLoadDefaults(tlvRoot
);
806 PrintAndLog("* * Transaction parameters loading from JSON...");
807 ParamLoadFromJson(tlvRoot
);
810 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
811 char *qVSDC
= "\x26\x00\x00\x00";
813 qVSDC
= "\x26\x80\x00\x00";
817 TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD
819 // not standard for contactless. just for test.
821 TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC
824 TLV_ADD(0x9F66, qVSDC
); // qVSDC
827 TLV_ADD(0x9F66, qVSDC
); // qVSDC (VISA CDA not enabled)
833 TLVPrintFromTLV(tlvRoot
); // TODO delete!!!
835 PrintAndLog("\n* Calc PDOL.");
836 pdol_data_tlv
= dol_process(tlvdb_get(tlvRoot
, 0x9f38, NULL
), tlvRoot
, 0x83);
838 PrintAndLog("ERROR: can't create PDOL TLV.");
842 size_t pdol_data_tlv_data_len
;
843 unsigned char *pdol_data_tlv_data
= tlv_encode(pdol_data_tlv
, &pdol_data_tlv_data_len
);
844 if (!pdol_data_tlv_data
) {
845 PrintAndLog("ERROR: can't create PDOL data.");
848 PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
850 PrintAndLog("\n* GPO.");
851 res
= EMVGPO(true, pdol_data_tlv_data
, pdol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
853 free(pdol_data_tlv_data
);
854 //free(pdol_data_tlv); --- free on exit.
857 PrintAndLog("GPO error(%d): %4x. Exit...", res
, sw
);
861 // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
862 if (buf
[0] == 0x80) {
864 PrintAndLog("GPO response format1:");
865 TLVPrintFromBuffer(buf
, len
);
868 if (len
< 4 || (len
- 4) % 4) {
869 PrintAndLog("ERROR: GPO response format1 parsing error. length=%d", len
);
872 struct tlvdb
* f1AIP
= tlvdb_fixed(0x82, 2, buf
+ 2);
873 tlvdb_add(tlvRoot
, f1AIP
);
875 PrintAndLog("\n* * Decode response format 1 (0x80) AIP and AFL:");
876 TLVPrintFromTLV(f1AIP
);
880 struct tlvdb
* f1AFL
= tlvdb_fixed(0x94, len
- 4, buf
+ 2 + 2);
881 tlvdb_add(tlvRoot
, f1AFL
);
883 TLVPrintFromTLV(f1AFL
);
887 TLVPrintFromBuffer(buf
, len
);
890 // extract PAN from track2
892 const struct tlv
*track2
= tlvdb_get(tlvRoot
, 0x57, NULL
);
893 if (!tlvdb_get(tlvRoot
, 0x5a, NULL
) && track2
&& track2
->len
>= 8) {
894 struct tlvdb
*pan
= GetPANFromTrack2(track2
);
896 tlvdb_add(tlvRoot
, pan
);
898 const struct tlv
*pantlv
= tlvdb_get(tlvRoot
, 0x5a, NULL
);
899 PrintAndLog("\n* * Extracted PAN from track2: %s", sprint_hex(pantlv
->value
, pantlv
->len
));
901 PrintAndLog("\n* * WARNING: Can't extract PAN from track2.");
906 PrintAndLog("\n* Read records from AFL.");
907 const struct tlv
*AFL
= tlvdb_get(tlvRoot
, 0x94, NULL
);
908 if (!AFL
|| !AFL
->len
) {
909 PrintAndLog("WARNING: AFL not found.");
912 while(AFL
&& AFL
->len
) {
914 PrintAndLog("ERROR: Wrong AFL length: %d", AFL
->len
);
918 for (int i
= 0; i
< AFL
->len
/ 4; i
++) {
919 uint8_t SFI
= AFL
->value
[i
* 4 + 0] >> 3;
920 uint8_t SFIstart
= AFL
->value
[i
* 4 + 1];
921 uint8_t SFIend
= AFL
->value
[i
* 4 + 2];
922 uint8_t SFIoffline
= AFL
->value
[i
* 4 + 3];
924 PrintAndLog("* * SFI[%02x] start:%02x end:%02x offline:%02x", SFI
, SFIstart
, SFIend
, SFIoffline
);
925 if (SFI
== 0 || SFI
== 31 || SFIstart
== 0 || SFIstart
> SFIend
) {
926 PrintAndLog("SFI ERROR! Skipped...");
930 for(int n
= SFIstart
; n
<= SFIend
; n
++) {
931 PrintAndLog("* * * SFI[%02x] %d", SFI
, n
);
933 res
= EMVReadRecord(true, SFI
, n
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
935 PrintAndLog("ERROR SFI[%02x]. APDU error %4x", SFI
, sw
);
940 TLVPrintFromBuffer(buf
, len
);
944 // Build Input list for Offline Data Authentication
945 // EMV 4.3 book3 10.3, page 96
948 const unsigned char *abuf
= buf
;
951 if (tlv_parse_tl(&abuf
, &elmlen
, &e
)) {
952 memcpy(&ODAiList
[ODAiListLen
], &buf
[len
- elmlen
], elmlen
);
953 ODAiListLen
+= elmlen
;
955 PrintAndLog("ERROR SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI
);
958 memcpy(&ODAiList
[ODAiListLen
], buf
, len
);
968 // copy Input list for Offline Data Authentication
970 struct tlvdb
*oda
= tlvdb_fixed(0x21, ODAiListLen
, ODAiList
); // not a standard tag
971 tlvdb_add(tlvRoot
, oda
);
972 PrintAndLog("* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen
);
976 const struct tlv
*AIPtlv
= tlvdb_get(tlvRoot
, 0x82, NULL
);
977 uint16_t AIP
= AIPtlv
->value
[0] + AIPtlv
->value
[1] * 0x100;
978 PrintAndLog("* * AIP=%04x", AIP
);
982 PrintAndLog("\n* SDA");
988 PrintAndLog("\n* DDA");
989 trDDA(decodeTLV
, tlvRoot
);
995 if (TrType
== TT_QVSDCMCHIP
|| TrType
== TT_CDA
){
996 // 9F26: Application Cryptogram
997 const struct tlv
*AC
= tlvdb_get(tlvRoot
, 0x9F26, NULL
);
999 PrintAndLog("\n--> qVSDC transaction.");
1000 PrintAndLog("* AC path");
1002 // 9F36: Application Transaction Counter (ATC)
1003 const struct tlv
*ATC
= tlvdb_get(tlvRoot
, 0x9F36, NULL
);
1006 // 9F10: Issuer Application Data - optional
1007 const struct tlv
*IAD
= tlvdb_get(tlvRoot
, 0x9F10, NULL
);
1010 PrintAndLog("ATC: %s", sprint_hex(ATC
->value
, ATC
->len
));
1011 PrintAndLog("AC: %s", sprint_hex(AC
->value
, AC
->len
));
1013 PrintAndLog("IAD: %s", sprint_hex(IAD
->value
, IAD
->len
));
1015 if (IAD
->len
>= IAD
->value
[0] + 1) {
1016 PrintAndLog("\tKey index: 0x%02x", IAD
->value
[1]);
1017 PrintAndLog("\tCrypto ver: 0x%02x(%03d)", IAD
->value
[2], IAD
->value
[2]);
1018 PrintAndLog("\tCVR:", sprint_hex(&IAD
->value
[3], IAD
->value
[0] - 2));
1019 struct tlvdb
* cvr
= tlvdb_fixed(0x20, IAD
->value
[0] - 2, &IAD
->value
[3]);
1020 TLVPrintFromTLVLev(cvr
, 1);
1023 PrintAndLog("WARNING: IAD not found.");
1027 PrintAndLog("ERROR AC: Application Transaction Counter (ATC) not found.");
1032 // Mastercard M/CHIP
1033 if (GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
&& (TrType
== TT_QVSDCMCHIP
|| TrType
== TT_CDA
)){
1034 const struct tlv
*CDOL1
= tlvdb_get(tlvRoot
, 0x8c, NULL
);
1035 if (CDOL1
&& GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
) { // and m/chip transaction flag
1036 PrintAndLog("\n--> Mastercard M/Chip transaction.");
1038 PrintAndLog("* * Generate challenge");
1039 res
= EMVGenerateChallenge(true, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1041 PrintAndLog("ERROR GetChallenge. APDU error %4x", sw
);
1045 PrintAndLog("ERROR GetChallenge. Wrong challenge length %d", len
);
1049 // ICC Dynamic Number
1050 struct tlvdb
* ICCDynN
= tlvdb_fixed(0x9f4c, len
, buf
);
1051 tlvdb_add(tlvRoot
, ICCDynN
);
1053 PrintAndLog("\n* * ICC Dynamic Number:");
1054 TLVPrintFromTLV(ICCDynN
);
1057 PrintAndLog("* * Calc CDOL1");
1058 struct tlv
*cdol_data_tlv
= dol_process(tlvdb_get(tlvRoot
, 0x8c, NULL
), tlvRoot
, 0x01); // 0x01 - dummy tag
1059 if (!cdol_data_tlv
){
1060 PrintAndLog("ERROR: can't create CDOL1 TLV.");
1063 PrintAndLog("CDOL1 data[%d]: %s", cdol_data_tlv
->len
, sprint_hex(cdol_data_tlv
->value
, cdol_data_tlv
->len
));
1065 PrintAndLog("* * AC1");
1066 // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
1067 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
);
1070 PrintAndLog("AC1 error(%d): %4x. Exit...", res
, sw
);
1075 TLVPrintFromBuffer(buf
, len
);
1078 PrintAndLog("\n* CDA:");
1079 struct tlvdb
*ac_tlv
= tlvdb_parse_multi(buf
, len
);
1080 res
= trCDA(tlvRoot
, ac_tlv
, pdol_data_tlv
, cdol_data_tlv
);
1082 PrintAndLog("CDA error (%d)", res
);
1085 free(cdol_data_tlv
);
1087 PrintAndLog("\n* M/Chip transaction result:");
1088 // 9F27: Cryptogram Information Data (CID)
1089 const struct tlv
*CID
= tlvdb_get(tlvRoot
, 0x9F27, NULL
);
1091 emv_tag_dump(CID
, stdout
, 0);
1092 PrintAndLog("------------------------------");
1094 switch(CID
->value
[0] & EMVAC_AC_MASK
){
1096 PrintAndLog("Transaction DECLINED.");
1099 PrintAndLog("Transaction approved OFFLINE.");
1102 PrintAndLog("Transaction approved ONLINE.");
1105 PrintAndLog("ERROR: CID transaction code error %2x", CID
->value
[0] & EMVAC_AC_MASK
);
1109 PrintAndLog("ERROR: Wrong CID length %d", CID
->len
);
1112 PrintAndLog("ERROR: CID(9F27) not found.");
1119 if (AIP
& 0x8000 && TrType
== TT_MSD
) {
1120 PrintAndLog("\n--> MSD transaction.");
1122 PrintAndLog("* MSD dCVV path. Check dCVV");
1124 const struct tlv
*track2
= tlvdb_get(tlvRoot
, 0x57, NULL
);
1126 PrintAndLog("Track2: %s", sprint_hex(track2
->value
, track2
->len
));
1128 struct tlvdb
*dCVV
= GetdCVVRawFromTrack2(track2
);
1129 PrintAndLog("dCVV raw data:");
1130 TLVPrintFromTLV(dCVV
);
1132 if (GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
) {
1133 PrintAndLog("\n* Mastercard calculate UDOL");
1136 const struct tlv
*UDOL
= tlvdb_get(tlvRoot
, 0x9F69, NULL
);
1137 // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
1138 const struct tlv defUDOL
= {
1141 .value
= (uint8_t *)"\x9f\x6a\x04",
1144 PrintAndLog("Use default UDOL.");
1146 struct tlv
*udol_data_tlv
= dol_process(UDOL
? UDOL
: &defUDOL
, tlvRoot
, 0x01); // 0x01 - dummy tag
1147 if (!udol_data_tlv
){
1148 PrintAndLog("ERROR: can't create UDOL TLV.");
1152 PrintAndLog("UDOL data[%d]: %s", udol_data_tlv
->len
, sprint_hex(udol_data_tlv
->value
, udol_data_tlv
->len
));
1154 PrintAndLog("\n* Mastercard compute cryptographic checksum(UDOL)");
1156 res
= MSCComputeCryptoChecksum(true, (uint8_t *)udol_data_tlv
->value
, udol_data_tlv
->len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
1158 PrintAndLog("ERROR Compute Crypto Checksum. APDU error %4x", sw
);
1159 free(udol_data_tlv
);
1164 TLVPrintFromBuffer(buf
, len
);
1167 free(udol_data_tlv
);
1171 PrintAndLog("ERROR MSD: Track2 data not found.");
1179 free(pdol_data_tlv
);
1180 tlvdb_free(tlvSelect
);
1181 tlvdb_free(tlvRoot
);
1183 PrintAndLog("\n* Transaction completed.");
1188 int UsageCmdHFEMVScan(void) {
1189 PrintAndLog("HELP : Scan EMV card and save it contents to a file. \n");
1190 PrintAndLog(" It executes EMV contactless transaction and saves result to a file which can be used for emulation.\n");
1191 PrintAndLog("Usage: hf emv scan [-a][-t][-v][-c][-x][-g] <file_name>\n");
1192 PrintAndLog(" Options:");
1193 PrintAndLog(" -a : show APDU reqests and responses\n");
1194 PrintAndLog(" -t : TLV decode results\n");
1195 PrintAndLog(" -v : transaction type - qVSDC or M/Chip.\n");
1196 PrintAndLog(" -c : transaction type - qVSDC or M/Chip plus CDA (SDAD generation).\n");
1197 PrintAndLog(" -x : transaction type - VSDC. For test only. Not a standart behavior.\n");
1198 PrintAndLog(" -g : VISA. generate AC from GPO\n");
1199 PrintAndLog("By default : transaction type - MSD.\n");
1200 PrintAndLog("Samples:");
1201 PrintAndLog(" hf emv scan -a -t -> scan MSD transaction mode");
1202 PrintAndLog(" hf emv scan -a -t -c -> scan CDA transaction mode");
1206 int CmdHFEMVScan(const char *cmd
) {
1207 UsageCmdHFEMVScan();
1212 int CmdHFEMVTest(const char *cmd
) {
1213 return ExecuteCryptoTests(true);
1216 int CmdHelp(const char *Cmd
);
1217 static command_t CommandTable
[] = {
1218 {"help", CmdHelp
, 1, "This help"},
1219 {"exec", CmdHFEMVExec
, 0, "Executes EMV contactless transaction."},
1220 {"pse", CmdHFEMVPPSE
, 0, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."},
1221 {"search", CmdHFEMVSearch
, 0, "Try to select all applets from applets list and print installed applets."},
1222 {"select", CmdHFEMVSelect
, 0, "Select applet."},
1223 {"gpo", CmdHFEMVGPO
, 0, "Execute GetProcessingOptions."},
1224 {"readrec", CmdHFEMVReadRecord
, 0, "Read files from card."},
1225 {"genac", CmdHFEMVAC
, 0, "Generate ApplicationCryptogram."},
1226 {"challenge", CmdHFEMVGenerateChallenge
, 0, "Generate challenge."},
1227 {"intauth", CmdHFEMVInternalAuthenticate
, 0, "Internal authentication."},
1228 // {"scan", CmdHFEMVScan, 0, "Scan EMV card and save it contents to json file for emulator."},
1229 {"test", CmdHFEMVTest
, 0, "Crypto logic test."},
1230 {NULL
, NULL
, 0, NULL
}
1233 int CmdHFEMV(const char *Cmd
) {
1234 CmdsParse(CommandTable
, Cmd
);
1238 int CmdHelp(const char *Cmd
) {
1239 CmdsHelp(CommandTable
);