]> git.zerfleddert.de Git - proxmark3-svn/blob - client/emv/cmdemv.c
delete unused procedure after merge
[proxmark3-svn] / client / emv / cmdemv.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2017, 2018 Merlok
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // EMV commands
9 //-----------------------------------------------------------------------------
10
11 #include <ctype.h>
12 #include "cmdemv.h"
13 #include "test/cryptotest.h"
14 #include "cliparser/cliparser.h"
15 #include <jansson.h>
16
17 int CmdHFEMVSelect(const char *cmd) {
18 uint8_t data[APDU_AID_LEN] = {0};
19 int datalen = 0;
20
21
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");
25
26 void* argtable[] = {
27 arg_param_begin,
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),
33 arg_param_end
34 };
35 CLIExecWithReturn(cmd, argtable, true);
36
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);
42 CLIParserFree();
43
44 SetAPDULogging(APDULogging);
45
46 // exec
47 uint8_t buf[APDU_RES_LEN] = {0};
48 size_t len = 0;
49 uint16_t sw = 0;
50 int res = EMVSelect(activateField, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL);
51
52 if (sw)
53 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
54
55 if (res)
56 return res;
57
58 if (decodeTLV)
59 TLVPrintFromBuffer(buf, len);
60
61 return 0;
62 }
63
64 int CmdHFEMVSearch(const char *cmd) {
65
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");
69
70 void* argtable[] = {
71 arg_param_begin,
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"),
76 arg_param_end
77 };
78 CLIExecWithReturn(cmd, argtable, true);
79
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);
84 CLIParserFree();
85
86 SetAPDULogging(APDULogging);
87
88 struct tlvdb *t = NULL;
89 const char *al = "Applets list";
90 t = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
91
92 if (EMVSearch(activateField, leaveSignalON, decodeTLV, t)) {
93 tlvdb_free(t);
94 return 2;
95 }
96
97 PrintAndLog("Search completed.");
98
99 // print list here
100 if (!decodeTLV) {
101 TLVPrintAIDlistFromSelectTLV(t);
102 }
103
104 tlvdb_free(t);
105
106 return 0;
107 }
108
109 int CmdHFEMVPPSE(const char *cmd) {
110
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");
114
115 void* argtable[] = {
116 arg_param_begin,
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"),
123 arg_param_end
124 };
125 CLIExecWithReturn(cmd, argtable, true);
126
127 bool activateField = arg_get_lit(1);
128 bool leaveSignalON = arg_get_lit(2);
129 uint8_t PSENum = 2;
130 if (arg_get_lit(3))
131 PSENum = 1;
132 if (arg_get_lit(4))
133 PSENum = 2;
134 bool APDULogging = arg_get_lit(5);
135 bool decodeTLV = arg_get_lit(6);
136 CLIParserFree();
137
138 SetAPDULogging(APDULogging);
139
140 // exec
141 uint8_t buf[APDU_RES_LEN] = {0};
142 size_t len = 0;
143 uint16_t sw = 0;
144 int res = EMVSelectPSE(activateField, leaveSignalON, PSENum, buf, sizeof(buf), &len, &sw);
145
146 if (sw)
147 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
148
149 if (res)
150 return res;
151
152
153 if (decodeTLV)
154 TLVPrintFromBuffer(buf, len);
155
156 return 0;
157 }
158
159 #define TLV_ADD(tag, value)( tlvdb_change_or_add_node(tlvRoot, tag, sizeof(value) - 1, (const unsigned char *)value) )
160
161 int CmdHFEMVGPO(const char *cmd) {
162 uint8_t data[APDU_RES_LEN] = {0};
163 int datalen = 0;
164
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
170
171 void* argtable[] = {
172 arg_param_begin,
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),
179 arg_param_end
180 };
181 CLIExecWithReturn(cmd, argtable, true);
182
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);
189 CLIParserFree();
190
191 SetAPDULogging(APDULogging);
192
193 // Init TLV tree
194 const char *alr = "Root terminal TLV tree";
195 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
196
197 // calc PDOL
198 struct tlv *pdol_data_tlv = NULL;
199 struct tlv data_tlv = {
200 .tag = 0x01,
201 .len = datalen,
202 .value = (uint8_t *)data,
203 };
204 if (dataMakeFromPDOL) {
205 // TODO
206 PrintAndLog("Make PDOL data not implemented!");
207
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
225
226 if (paramsLoadFromFile) {
227 };
228 /* pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
229 if (!pdol_data_tlv){
230 PrintAndLog("ERROR: can't create PDOL TLV.");
231 tlvdb_free(tlvRoot);
232 return 4;
233 }*/
234 return 0;
235 } else {
236 pdol_data_tlv = &data_tlv;
237 }
238
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.");
243 tlvdb_free(tlvRoot);
244 return 4;
245 }
246 PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
247
248 // exec
249 uint8_t buf[APDU_RES_LEN] = {0};
250 size_t len = 0;
251 uint16_t sw = 0;
252 int res = EMVGPO(leaveSignalON, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
253
254 free(pdol_data_tlv_data);
255 tlvdb_free(tlvRoot);
256
257 if (sw)
258 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
259
260 if (res)
261 return res;
262
263 if (decodeTLV)
264 TLVPrintFromBuffer(buf, len);
265
266 return 0;
267 }
268
269 int CmdHFEMVReadRecord(const char *cmd) {
270 uint8_t data[APDU_RES_LEN] = {0};
271 int datalen = 0;
272
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");
276
277 void* argtable[] = {
278 arg_param_begin,
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),
283 arg_param_end
284 };
285 CLIExecWithReturn(cmd, argtable, true);
286
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);
291 CLIParserFree();
292
293 if (datalen != 2) {
294 PrintAndLog("ERROR: Command needs to have 2 bytes of data");
295 return 1;
296 }
297
298 SetAPDULogging(APDULogging);
299
300 // exec
301 uint8_t buf[APDU_RES_LEN] = {0};
302 size_t len = 0;
303 uint16_t sw = 0;
304 int res = EMVReadRecord(leaveSignalON, data[0], data[1], buf, sizeof(buf), &len, &sw, NULL);
305
306 if (sw)
307 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
308
309 if (res)
310 return res;
311
312
313 if (decodeTLV)
314 TLVPrintFromBuffer(buf, len);
315
316 return 0;
317 }
318
319 int CmdHFEMVAC(const char *cmd) {
320 uint8_t data[APDU_RES_LEN] = {0};
321 int datalen = 0;
322
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");
328
329 void* argtable[] = {
330 arg_param_begin,
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),
337 arg_param_end
338 };
339 CLIExecWithReturn(cmd, argtable, false);
340
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;
351
352 if (termDecision == 0xff) {
353 PrintAndLog("ERROR: can't find terminal decision '%s'", arg_get_str(3)->sval[0]);
354 return 1;
355 }
356 } else {
357 termDecision = EMVAC_TC;
358 }
359 if (trTypeCDA)
360 termDecision = termDecision | EMVAC_CDAREQ;
361 bool APDULogging = arg_get_lit(4);
362 bool decodeTLV = arg_get_lit(5);
363 CLIGetStrWithReturn(6, data, &datalen);
364 CLIParserFree();
365
366 SetAPDULogging(APDULogging);
367
368 // Init TLV tree
369 const char *alr = "Root terminal TLV tree";
370 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
371
372 // calc CDOL
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 = {
376 .tag = 0x01,
377 .len = datalen,
378 .value = (uint8_t *)data,
379 };
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));
382
383 // exec
384 uint8_t buf[APDU_RES_LEN] = {0};
385 size_t len = 0;
386 uint16_t sw = 0;
387 int res = EMVAC(leaveSignalON, termDecision, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
388
389 // free(cdol_data_tlv);
390 tlvdb_free(tlvRoot);
391
392 if (sw)
393 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
394
395 if (res)
396 return res;
397
398 if (decodeTLV)
399 TLVPrintFromBuffer(buf, len);
400
401 return 0;
402 }
403
404 int CmdHFEMVGenerateChallenge(const char *cmd) {
405
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");
409
410 void* argtable[] = {
411 arg_param_begin,
412 arg_lit0("kK", "keep", "keep field ON for next command"),
413 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
414 arg_param_end
415 };
416 CLIExecWithReturn(cmd, argtable, true);
417
418 bool leaveSignalON = arg_get_lit(1);
419 bool APDULogging = arg_get_lit(2);
420 CLIParserFree();
421
422 SetAPDULogging(APDULogging);
423
424 // exec
425 uint8_t buf[APDU_RES_LEN] = {0};
426 size_t len = 0;
427 uint16_t sw = 0;
428 int res = EMVGenerateChallenge(leaveSignalON, buf, sizeof(buf), &len, &sw, NULL);
429
430 if (sw)
431 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
432
433 if (res)
434 return res;
435
436 PrintAndLog("Challenge: %s", sprint_hex(buf, len));
437
438 if (len != 4 && len != 8)
439 PrintAndLog("WARNING: length of challenge must be 4 or 8, but it %d", len);
440
441 return 0;
442 }
443
444 int CmdHFEMVInternalAuthenticate(const char *cmd) {
445 uint8_t data[APDU_RES_LEN] = {0};
446 int datalen = 0;
447
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");
452
453 void* argtable[] = {
454 arg_param_begin,
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),
459 arg_param_end
460 };
461 CLIExecWithReturn(cmd, argtable, false);
462
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);
467 CLIParserFree();
468
469 SetAPDULogging(APDULogging);
470
471 // DDOL
472 PrintAndLog("DDOL data[%d]: %s", datalen, sprint_hex(data, datalen));
473
474 // exec
475 uint8_t buf[APDU_RES_LEN] = {0};
476 size_t len = 0;
477 uint16_t sw = 0;
478 int res = EMVInternalAuthenticate(leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL);
479
480 if (sw)
481 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
482
483 if (res)
484 return res;
485
486 if (decodeTLV)
487 TLVPrintFromBuffer(buf, len);
488
489 return 0;
490 }
491
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");
509 return 0;
510 }
511
512 #define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;}
513
514 bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t * buffer, size_t maxbufferlen, size_t *bufferlen) {
515 int buflen = 0;
516
517 switch(param_gethex_to_eol(hexvalue, 0, buffer, maxbufferlen, &buflen)) {
518 case 1:
519 PrintAndLog("%s Invalid HEX value.", errormsg);
520 return false;
521 case 2:
522 PrintAndLog("%s Hex value too large.", errormsg);
523 return false;
524 case 3:
525 PrintAndLog("%s Hex value must have even number of digits.", errormsg);
526 return false;
527 }
528
529 if (buflen > maxbufferlen) {
530 PrintAndLog("%s HEX length (%d) more than %d", errormsg, *bufferlen, maxbufferlen);
531 return false;
532 }
533
534 *bufferlen = buflen;
535
536 return true;
537 }
538
539 bool ParamLoadFromJson(struct tlvdb *tlv) {
540 json_t *root;
541 json_error_t error;
542
543 if (!tlv) {
544 PrintAndLog("ERROR load params: tlv tree is NULL.");
545 return false;
546 }
547
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);
553
554 root = json_load_file(fname, 0, &error);
555 if (!root) {
556 PrintAndLog("Load params: json error on line %d: %s", error.line, error.text);
557 return false;
558 }
559
560 if (!json_is_array(root)) {
561 PrintAndLog("Load params: Invalid json format. root must be array.");
562 return false;
563 }
564
565 PrintAndLog("Load params: json OK");
566
567 for(int i = 0; i < json_array_size(root); i++) {
568 json_t *data, *jtype, *jlength, *jvalue;
569
570 data = json_array_get(root, i);
571 if(!json_is_object(data))
572 {
573 PrintAndLog("Load params: data [%d] is not an object", i + 1);
574 json_decref(root);
575 return false;
576 }
577
578 jtype = json_object_get(data, "type");
579 if(!json_is_string(jtype))
580 {
581 PrintAndLog("Load params: data [%d] type is not a string", i + 1);
582 json_decref(root);
583 return false;
584 }
585 const char *tlvType = json_string_value(jtype);
586
587 jvalue = json_object_get(data, "value");
588 if(!json_is_string(jvalue))
589 {
590 PrintAndLog("Load params: data [%d] value is not a string", i + 1);
591 json_decref(root);
592 return false;
593 }
594 const char *tlvValue = json_string_value(jvalue);
595
596 jlength = json_object_get(data, "length");
597 if(!json_is_number(jlength))
598 {
599 PrintAndLog("Load params: data [%d] length is not a number", i + 1);
600 json_decref(root);
601 return false;
602 }
603
604 int tlvLength = json_integer_value(jlength);
605 if (tlvLength > 250) {
606 PrintAndLog("Load params: data [%d] length more than 250", i + 1);
607 json_decref(root);
608 return false;
609 }
610
611 PrintAndLog("TLV param: %s[%d]=%s", tlvType, tlvLength, tlvValue);
612 uint8_t buf[251] = {0};
613 size_t buflen = 0;
614
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)) {
617 json_decref(root);
618 return false;
619 }
620 tlv_tag_t tag = 0;
621 for (int i = 0; i < buflen; i++) {
622 tag = (tag << 8) + buf[i];
623 }
624
625 if (!HexToBuffer("TLV Error value:", tlvValue, buf, sizeof(buf) - 1, &buflen)) {
626 json_decref(root);
627 return false;
628 }
629
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);
632 json_decref(root);
633 return false;
634 }
635
636 tlvdb_change_or_add_node(tlv, tag, tlvLength, (const unsigned char *)buf);
637 }
638
639 json_decref(root);
640
641 return true;
642 }
643
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
662 }
663
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;
672
673 uint8_t buf[APDU_RES_LEN] = {0};
674 size_t len = 0;
675 uint16_t sw = 0;
676 uint8_t AID[APDU_AID_LEN] = {0};
677 size_t AIDlen = 0;
678 uint8_t ODAiList[4096];
679 size_t ODAiListLen = 0;
680
681 int res;
682
683 struct tlvdb *tlvSelect = NULL;
684 struct tlvdb *tlvRoot = NULL;
685 struct tlv *pdol_data_tlv = NULL;
686
687 if (strlen(cmd) < 1) {
688 UsageCmdHFEMVExec();
689 return 0;
690 }
691
692 int cmdp = 0;
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)) {
697 case 'h':
698 case 'H':
699 UsageCmdHFEMVExec();
700 return 0;
701 case 's':
702 case 'S':
703 activateField = true;
704 break;
705 case 'a':
706 case 'A':
707 showAPDU = true;
708 break;
709 case 't':
710 case 'T':
711 decodeTLV = true;
712 break;
713 case 'f':
714 case 'F':
715 forceSearch = true;
716 break;
717 case 'x':
718 case 'X':
719 TrType = TT_VSDC;
720 break;
721 case 'v':
722 case 'V':
723 TrType = TT_QVSDCMCHIP;
724 break;
725 case 'c':
726 case 'C':
727 TrType = TT_CDA;
728 break;
729 case 'g':
730 case 'G':
731 GenACGPO = true;
732 break;
733 case 'j':
734 case 'J':
735 paramLoadJSON = true;
736 break;
737 default:
738 PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd, 1, cmdp));
739 return 1;
740 }
741 cmdp++;
742 }
743
744
745 // init applets list tree
746 const char *al = "Applets list";
747 tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
748
749 // Application Selection
750 // https://www.openscdp.org/scripts/tutorial/emv/applicationselection.html
751 if (!forceSearch) {
752 // PPSE
753 PrintAndLog("\n* PPSE.");
754 SetAPDULogging(showAPDU);
755 res = EMVSearchPSE(activateField, true, decodeTLV, tlvSelect);
756
757 // check PPSE and select application id
758 if (!res) {
759 TLVPrintAIDlistFromSelectTLV(tlvSelect);
760 EMVSelectApplication(tlvSelect, AID, &AIDlen);
761 }
762 }
763
764 // Search
765 if (!AIDlen) {
766 PrintAndLog("\n* Search AID in list.");
767 SetAPDULogging(false);
768 if (EMVSearch(activateField, true, decodeTLV, tlvSelect)) {
769 dreturn(2);
770 }
771
772 // check search and select application id
773 TLVPrintAIDlistFromSelectTLV(tlvSelect);
774 EMVSelectApplication(tlvSelect, AID, &AIDlen);
775 }
776
777 // Init TLV tree
778 const char *alr = "Root terminal TLV tree";
779 tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
780
781 // check if we found EMV application on card
782 if (!AIDlen) {
783 PrintAndLog("Can't select AID. EMV AID not found");
784 dreturn(2);
785 }
786
787 // Select
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);
791
792 if (res) {
793 PrintAndLog("Can't select AID (%d). Exit...", res);
794 dreturn(3);
795 }
796
797 if (decodeTLV)
798 TLVPrintFromBuffer(buf, len);
799 PrintAndLog("* Selected.");
800
801 PrintAndLog("\n* Init transaction parameters.");
802
803 ParamLoadDefaults(tlvRoot);
804
805 if (paramLoadJSON) {
806 PrintAndLog("* * Transaction parameters loading from JSON...");
807 ParamLoadFromJson(tlvRoot);
808 }
809
810 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
811 char *qVSDC = "\x26\x00\x00\x00";
812 if (GenACGPO) {
813 qVSDC = "\x26\x80\x00\x00";
814 }
815 switch(TrType) {
816 case TT_MSD:
817 TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD
818 break;
819 // not standard for contactless. just for test.
820 case TT_VSDC:
821 TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC
822 break;
823 case TT_QVSDCMCHIP:
824 TLV_ADD(0x9F66, qVSDC); // qVSDC
825 break;
826 case TT_CDA:
827 TLV_ADD(0x9F66, qVSDC); // qVSDC (VISA CDA not enabled)
828 break;
829 default:
830 break;
831 }
832
833 TLVPrintFromTLV(tlvRoot); // TODO delete!!!
834
835 PrintAndLog("\n* Calc PDOL.");
836 pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
837 if (!pdol_data_tlv){
838 PrintAndLog("ERROR: can't create PDOL TLV.");
839 dreturn(4);
840 }
841
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.");
846 dreturn(4);
847 }
848 PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
849
850 PrintAndLog("\n* GPO.");
851 res = EMVGPO(true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
852
853 free(pdol_data_tlv_data);
854 //free(pdol_data_tlv); --- free on exit.
855
856 if (res) {
857 PrintAndLog("GPO error(%d): %4x. Exit...", res, sw);
858 dreturn(5);
859 }
860
861 // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
862 if (buf[0] == 0x80) {
863 if (decodeTLV){
864 PrintAndLog("GPO response format1:");
865 TLVPrintFromBuffer(buf, len);
866 }
867
868 if (len < 4 || (len - 4) % 4) {
869 PrintAndLog("ERROR: GPO response format1 parsing error. length=%d", len);
870 } else {
871 // AIP
872 struct tlvdb * f1AIP = tlvdb_fixed(0x82, 2, buf + 2);
873 tlvdb_add(tlvRoot, f1AIP);
874 if (decodeTLV){
875 PrintAndLog("\n* * Decode response format 1 (0x80) AIP and AFL:");
876 TLVPrintFromTLV(f1AIP);
877 }
878
879 // AFL
880 struct tlvdb * f1AFL = tlvdb_fixed(0x94, len - 4, buf + 2 + 2);
881 tlvdb_add(tlvRoot, f1AFL);
882 if (decodeTLV)
883 TLVPrintFromTLV(f1AFL);
884 }
885 } else {
886 if (decodeTLV)
887 TLVPrintFromBuffer(buf, len);
888 }
889
890 // extract PAN from track2
891 {
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);
895 if (pan) {
896 tlvdb_add(tlvRoot, pan);
897
898 const struct tlv *pantlv = tlvdb_get(tlvRoot, 0x5a, NULL);
899 PrintAndLog("\n* * Extracted PAN from track2: %s", sprint_hex(pantlv->value, pantlv->len));
900 } else {
901 PrintAndLog("\n* * WARNING: Can't extract PAN from track2.");
902 }
903 }
904 }
905
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.");
910 }
911
912 while(AFL && AFL->len) {
913 if (AFL->len % 4) {
914 PrintAndLog("ERROR: Wrong AFL length: %d", AFL->len);
915 break;
916 }
917
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];
923
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...");
927 continue;
928 }
929
930 for(int n = SFIstart; n <= SFIend; n++) {
931 PrintAndLog("* * * SFI[%02x] %d", SFI, n);
932
933 res = EMVReadRecord(true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
934 if (res) {
935 PrintAndLog("ERROR SFI[%02x]. APDU error %4x", SFI, sw);
936 continue;
937 }
938
939 if (decodeTLV) {
940 TLVPrintFromBuffer(buf, len);
941 PrintAndLog("");
942 }
943
944 // Build Input list for Offline Data Authentication
945 // EMV 4.3 book3 10.3, page 96
946 if (SFIoffline) {
947 if (SFI < 11) {
948 const unsigned char *abuf = buf;
949 size_t elmlen = len;
950 struct tlv e;
951 if (tlv_parse_tl(&abuf, &elmlen, &e)) {
952 memcpy(&ODAiList[ODAiListLen], &buf[len - elmlen], elmlen);
953 ODAiListLen += elmlen;
954 } else {
955 PrintAndLog("ERROR SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI);
956 }
957 } else {
958 memcpy(&ODAiList[ODAiListLen], buf, len);
959 ODAiListLen += len;
960 }
961 }
962 }
963 }
964
965 break;
966 }
967
968 // copy Input list for Offline Data Authentication
969 if (ODAiListLen) {
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);
973 }
974
975 // get AIP
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);
979
980 // SDA
981 if (AIP & 0x0040) {
982 PrintAndLog("\n* SDA");
983 trSDA(tlvRoot);
984 }
985
986 // DDA
987 if (AIP & 0x0020) {
988 PrintAndLog("\n* DDA");
989 trDDA(decodeTLV, tlvRoot);
990 }
991
992 // transaction check
993
994 // qVSDC
995 if (TrType == TT_QVSDCMCHIP|| TrType == TT_CDA){
996 // 9F26: Application Cryptogram
997 const struct tlv *AC = tlvdb_get(tlvRoot, 0x9F26, NULL);
998 if (AC) {
999 PrintAndLog("\n--> qVSDC transaction.");
1000 PrintAndLog("* AC path");
1001
1002 // 9F36: Application Transaction Counter (ATC)
1003 const struct tlv *ATC = tlvdb_get(tlvRoot, 0x9F36, NULL);
1004 if (ATC) {
1005
1006 // 9F10: Issuer Application Data - optional
1007 const struct tlv *IAD = tlvdb_get(tlvRoot, 0x9F10, NULL);
1008
1009 // print AC data
1010 PrintAndLog("ATC: %s", sprint_hex(ATC->value, ATC->len));
1011 PrintAndLog("AC: %s", sprint_hex(AC->value, AC->len));
1012 if (IAD){
1013 PrintAndLog("IAD: %s", sprint_hex(IAD->value, IAD->len));
1014
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);
1021 }
1022 } else {
1023 PrintAndLog("WARNING: IAD not found.");
1024 }
1025
1026 } else {
1027 PrintAndLog("ERROR AC: Application Transaction Counter (ATC) not found.");
1028 }
1029 }
1030 }
1031
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.");
1037
1038 PrintAndLog("* * Generate challenge");
1039 res = EMVGenerateChallenge(true, buf, sizeof(buf), &len, &sw, tlvRoot);
1040 if (res) {
1041 PrintAndLog("ERROR GetChallenge. APDU error %4x", sw);
1042 dreturn(6);
1043 }
1044 if (len < 4) {
1045 PrintAndLog("ERROR GetChallenge. Wrong challenge length %d", len);
1046 dreturn(6);
1047 }
1048
1049 // ICC Dynamic Number
1050 struct tlvdb * ICCDynN = tlvdb_fixed(0x9f4c, len, buf);
1051 tlvdb_add(tlvRoot, ICCDynN);
1052 if (decodeTLV){
1053 PrintAndLog("\n* * ICC Dynamic Number:");
1054 TLVPrintFromTLV(ICCDynN);
1055 }
1056
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.");
1061 dreturn(6);
1062 }
1063 PrintAndLog("CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len));
1064
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);
1068
1069 if (res) {
1070 PrintAndLog("AC1 error(%d): %4x. Exit...", res, sw);
1071 dreturn(7);
1072 }
1073
1074 if (decodeTLV)
1075 TLVPrintFromBuffer(buf, len);
1076
1077 // CDA
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);
1081 if (res) {
1082 PrintAndLog("CDA error (%d)", res);
1083 }
1084 free(ac_tlv);
1085 free(cdol_data_tlv);
1086
1087 PrintAndLog("\n* M/Chip transaction result:");
1088 // 9F27: Cryptogram Information Data (CID)
1089 const struct tlv *CID = tlvdb_get(tlvRoot, 0x9F27, NULL);
1090 if (CID) {
1091 emv_tag_dump(CID, stdout, 0);
1092 PrintAndLog("------------------------------");
1093 if (CID->len > 0) {
1094 switch(CID->value[0] & EMVAC_AC_MASK){
1095 case EMVAC_AAC:
1096 PrintAndLog("Transaction DECLINED.");
1097 break;
1098 case EMVAC_TC:
1099 PrintAndLog("Transaction approved OFFLINE.");
1100 break;
1101 case EMVAC_ARQC:
1102 PrintAndLog("Transaction approved ONLINE.");
1103 break;
1104 default:
1105 PrintAndLog("ERROR: CID transaction code error %2x", CID->value[0] & EMVAC_AC_MASK);
1106 break;
1107 }
1108 } else {
1109 PrintAndLog("ERROR: Wrong CID length %d", CID->len);
1110 }
1111 } else {
1112 PrintAndLog("ERROR: CID(9F27) not found.");
1113 }
1114
1115 }
1116 }
1117
1118 // MSD
1119 if (AIP & 0x8000 && TrType == TT_MSD) {
1120 PrintAndLog("\n--> MSD transaction.");
1121
1122 PrintAndLog("* MSD dCVV path. Check dCVV");
1123
1124 const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
1125 if (track2) {
1126 PrintAndLog("Track2: %s", sprint_hex(track2->value, track2->len));
1127
1128 struct tlvdb *dCVV = GetdCVVRawFromTrack2(track2);
1129 PrintAndLog("dCVV raw data:");
1130 TLVPrintFromTLV(dCVV);
1131
1132 if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) {
1133 PrintAndLog("\n* Mastercard calculate UDOL");
1134
1135 // UDOL (9F69)
1136 const struct tlv *UDOL = tlvdb_get(tlvRoot, 0x9F69, NULL);
1137 // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
1138 const struct tlv defUDOL = {
1139 .tag = 0x01,
1140 .len = 3,
1141 .value = (uint8_t *)"\x9f\x6a\x04",
1142 };
1143 if (!UDOL)
1144 PrintAndLog("Use default UDOL.");
1145
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.");
1149 dreturn(8);
1150 }
1151
1152 PrintAndLog("UDOL data[%d]: %s", udol_data_tlv->len, sprint_hex(udol_data_tlv->value, udol_data_tlv->len));
1153
1154 PrintAndLog("\n* Mastercard compute cryptographic checksum(UDOL)");
1155
1156 res = MSCComputeCryptoChecksum(true, (uint8_t *)udol_data_tlv->value, udol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
1157 if (res) {
1158 PrintAndLog("ERROR Compute Crypto Checksum. APDU error %4x", sw);
1159 free(udol_data_tlv);
1160 dreturn(9);
1161 }
1162
1163 if (decodeTLV) {
1164 TLVPrintFromBuffer(buf, len);
1165 PrintAndLog("");
1166 }
1167 free(udol_data_tlv);
1168
1169 }
1170 } else {
1171 PrintAndLog("ERROR MSD: Track2 data not found.");
1172 }
1173 }
1174
1175 // DropField
1176 DropField();
1177
1178 // Destroy TLV's
1179 free(pdol_data_tlv);
1180 tlvdb_free(tlvSelect);
1181 tlvdb_free(tlvRoot);
1182
1183 PrintAndLog("\n* Transaction completed.");
1184
1185 return 0;
1186 }
1187
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");
1203 return 0;
1204 }
1205
1206 int CmdHFEMVScan(const char *cmd) {
1207 UsageCmdHFEMVScan();
1208
1209 return 0;
1210 }
1211
1212 int CmdHFEMVTest(const char *cmd) {
1213 return ExecuteCryptoTests(true);
1214 }
1215
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}
1231 };
1232
1233 int CmdHFEMV(const char *Cmd) {
1234 CmdsParse(CommandTable, Cmd);
1235 return 0;
1236 }
1237
1238 int CmdHelp(const char *Cmd) {
1239 CmdsHelp(CommandTable);
1240 return 0;
1241 }
Impressum, Datenschutz