]> git.zerfleddert.de Git - proxmark3-svn/blame - client/emv/cmdemv.c
Added loading parameters from json to several emv commands (#686)
[proxmark3-svn] / client / emv / cmdemv.c
CommitLineData
3c5fce2b 1//-----------------------------------------------------------------------------
f23565c3 2// Copyright (C) 2017, 2018 Merlok
3c5fce2b
OM
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
3ded0f97 11#include <ctype.h>
3c5fce2b 12#include "cmdemv.h"
d03fb293 13#include "test/cryptotest.h"
f23565c3 14#include "cliparser/cliparser.h"
556826b5 15#include <jansson.h>
3c5fce2b 16
92479429
OM
17bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t * buffer, size_t maxbufferlen, size_t *bufferlen) {
18 int buflen = 0;
19
20 switch(param_gethex_to_eol(hexvalue, 0, buffer, maxbufferlen, &buflen)) {
21 case 1:
22 PrintAndLog("%s Invalid HEX value.", errormsg);
23 return false;
24 case 2:
25 PrintAndLog("%s Hex value too large.", errormsg);
26 return false;
27 case 3:
28 PrintAndLog("%s Hex value must have even number of digits.", errormsg);
29 return false;
30 }
31
32 if (buflen > maxbufferlen) {
33 PrintAndLog("%s HEX length (%d) more than %d", errormsg, *bufferlen, maxbufferlen);
34 return false;
35 }
36
37 *bufferlen = buflen;
38
39 return true;
40}
41
f23565c3
OM
42#define TLV_ADD(tag, value)( tlvdb_change_or_add_node(tlvRoot, tag, sizeof(value) - 1, (const unsigned char *)value) )
43void ParamLoadDefaults(struct tlvdb *tlvRoot) {
44 //9F02:(Amount, authorized (Numeric)) len:6
45 TLV_ADD(0x9F02, "\x00\x00\x00\x00\x01\x00");
46 //9F1A:(Terminal Country Code) len:2
47 TLV_ADD(0x9F1A, "ru");
48 //5F2A:(Transaction Currency Code) len:2
49 // USD 840, EUR 978, RUR 810, RUB 643, RUR 810(old), UAH 980, AZN 031, n/a 999
50 TLV_ADD(0x5F2A, "\x09\x80");
51 //9A:(Transaction Date) len:3
52 TLV_ADD(0x9A, "\x00\x00\x00");
53 //9C:(Transaction Type) len:1 | 00 => Goods and service #01 => Cash
54 TLV_ADD(0x9C, "\x00");
55 // 9F37 Unpredictable Number len:4
56 TLV_ADD(0x9F37, "\x01\x02\x03\x04");
57 // 9F6A Unpredictable Number (MSD for UDOL) len:4
58 TLV_ADD(0x9F6A, "\x01\x02\x03\x04");
59 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
60 TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC
3c5fce2b
OM
61}
62
92479429
OM
63bool ParamLoadFromJson(struct tlvdb *tlv) {
64 json_t *root;
65 json_error_t error;
66
67 if (!tlv) {
68 PrintAndLog("ERROR load params: tlv tree is NULL.");
69 return false;
70 }
71
72 // current path + file name
73 const char *relfname = "emv/defparams.json";
74 char fname[strlen(get_my_executable_directory()) + strlen(relfname) + 1];
75 strcpy(fname, get_my_executable_directory());
76 strcat(fname, relfname);
77
78 root = json_load_file(fname, 0, &error);
79 if (!root) {
80 PrintAndLog("Load params: json error on line %d: %s", error.line, error.text);
81 return false;
82 }
83
84 if (!json_is_array(root)) {
85 PrintAndLog("Load params: Invalid json format. root must be array.");
86 return false;
87 }
88
89 PrintAndLog("Load params: json OK");
90
91 for(int i = 0; i < json_array_size(root); i++) {
92 json_t *data, *jtype, *jlength, *jvalue;
93
94 data = json_array_get(root, i);
95 if(!json_is_object(data))
96 {
97 PrintAndLog("Load params: data [%d] is not an object", i + 1);
98 json_decref(root);
99 return false;
100 }
101
102 jtype = json_object_get(data, "type");
103 if(!json_is_string(jtype))
104 {
105 PrintAndLog("Load params: data [%d] type is not a string", i + 1);
106 json_decref(root);
107 return false;
108 }
109 const char *tlvType = json_string_value(jtype);
110
111 jvalue = json_object_get(data, "value");
112 if(!json_is_string(jvalue))
113 {
114 PrintAndLog("Load params: data [%d] value is not a string", i + 1);
115 json_decref(root);
116 return false;
117 }
118 const char *tlvValue = json_string_value(jvalue);
119
120 jlength = json_object_get(data, "length");
121 if(!json_is_number(jlength))
122 {
123 PrintAndLog("Load params: data [%d] length is not a number", i + 1);
124 json_decref(root);
125 return false;
126 }
127
128 int tlvLength = json_integer_value(jlength);
129 if (tlvLength > 250) {
130 PrintAndLog("Load params: data [%d] length more than 250", i + 1);
131 json_decref(root);
132 return false;
133 }
134
135 PrintAndLog("TLV param: %s[%d]=%s", tlvType, tlvLength, tlvValue);
136 uint8_t buf[251] = {0};
137 size_t buflen = 0;
138
139 // 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...
140 if (!HexToBuffer("TLV Error type:", tlvType, buf, 2, &buflen)) {
141 json_decref(root);
142 return false;
143 }
144 tlv_tag_t tag = 0;
145 for (int i = 0; i < buflen; i++) {
146 tag = (tag << 8) + buf[i];
147 }
148
149 if (!HexToBuffer("TLV Error value:", tlvValue, buf, sizeof(buf) - 1, &buflen)) {
150 json_decref(root);
151 return false;
152 }
153
154 if (buflen != tlvLength) {
155 PrintAndLog("Load params: data [%d] length of HEX must(%d) be identical to length in TLV param(%d)", i + 1, buflen, tlvLength);
156 json_decref(root);
157 return false;
158 }
159
160 tlvdb_change_or_add_node(tlv, tag, tlvLength, (const unsigned char *)buf);
161 }
162
163 json_decref(root);
164
165 return true;
166}
167
3c5fce2b
OM
168int CmdHFEMVSelect(const char *cmd) {
169 uint8_t data[APDU_AID_LEN] = {0};
170 int datalen = 0;
3c5fce2b 171
f23565c3
OM
172 CLIParserInit("hf emv select",
173 "Executes select applet command",
174 "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");
175
176 void* argtable[] = {
177 arg_param_begin,
178 arg_lit0("sS", "select", "activate field and select card"),
179 arg_lit0("kK", "keep", "keep field for next command"),
180 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
181 arg_lit0("tT", "tlv", "TLV decode results"),
11146fc1 182 arg_strx0(NULL, NULL, "<HEX applet AID>", NULL),
f23565c3
OM
183 arg_param_end
184 };
185 CLIExecWithReturn(cmd, argtable, true);
3c5fce2b 186
f23565c3
OM
187 bool activateField = arg_get_lit(1);
188 bool leaveSignalON = arg_get_lit(2);
189 bool APDULogging = arg_get_lit(3);
190 bool decodeTLV = arg_get_lit(4);
191 CLIGetStrWithReturn(5, data, &datalen);
192 CLIParserFree();
193
194 SetAPDULogging(APDULogging);
3c5fce2b
OM
195
196 // exec
197 uint8_t buf[APDU_RES_LEN] = {0};
198 size_t len = 0;
199 uint16_t sw = 0;
200 int res = EMVSelect(activateField, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL);
201
202 if (sw)
203 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
204
205 if (res)
206 return res;
207
208 if (decodeTLV)
209 TLVPrintFromBuffer(buf, len);
210
211 return 0;
212}
213
3c5fce2b
OM
214int CmdHFEMVSearch(const char *cmd) {
215
f23565c3
OM
216 CLIParserInit("hf emv search",
217 "Tries to select all applets from applet list:\n",
218 "Usage:\n\thf emv search -s -> select card and search\n\thf emv search -st -> select card, search and show result in TLV\n");
219
220 void* argtable[] = {
221 arg_param_begin,
222 arg_lit0("sS", "select", "activate field and select card"),
223 arg_lit0("kK", "keep", "keep field ON for next command"),
224 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
225 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
226 arg_param_end
227 };
228 CLIExecWithReturn(cmd, argtable, true);
229
230 bool activateField = arg_get_lit(1);
231 bool leaveSignalON = arg_get_lit(2);
232 bool APDULogging = arg_get_lit(3);
233 bool decodeTLV = arg_get_lit(4);
234 CLIParserFree();
235
236 SetAPDULogging(APDULogging);
3c5fce2b 237
3c5fce2b
OM
238 struct tlvdb *t = NULL;
239 const char *al = "Applets list";
240 t = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
241
242 if (EMVSearch(activateField, leaveSignalON, decodeTLV, t)) {
243 tlvdb_free(t);
244 return 2;
245 }
246
247 PrintAndLog("Search completed.");
248
249 // print list here
250 if (!decodeTLV) {
251 TLVPrintAIDlistFromSelectTLV(t);
252 }
253
254 tlvdb_free(t);
255
256 return 0;
257}
258
3c5fce2b
OM
259int CmdHFEMVPPSE(const char *cmd) {
260
f23565c3
OM
261 CLIParserInit("hf emv pse",
262 "Executes PSE/PPSE select command. It returns list of applet on the card:\n",
263 "Usage:\n\thf emv pse -s1 -> select, get pse\n\thf emv pse -st2 -> select, get ppse, show result in TLV\n");
264
265 void* argtable[] = {
266 arg_param_begin,
267 arg_lit0("sS", "select", "activate field and select card"),
268 arg_lit0("kK", "keep", "keep field ON for next command"),
269 arg_lit0("1", "pse", "pse (1PAY.SYS.DDF01) mode"),
270 arg_lit0("2", "ppse", "ppse (2PAY.SYS.DDF01) mode (default mode)"),
271 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
272 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
273 arg_param_end
274 };
275 CLIExecWithReturn(cmd, argtable, true);
276
277 bool activateField = arg_get_lit(1);
278 bool leaveSignalON = arg_get_lit(2);
3c5fce2b 279 uint8_t PSENum = 2;
f23565c3
OM
280 if (arg_get_lit(3))
281 PSENum = 1;
282 if (arg_get_lit(4))
283 PSENum = 2;
284 bool APDULogging = arg_get_lit(5);
285 bool decodeTLV = arg_get_lit(6);
286 CLIParserFree();
287
288 SetAPDULogging(APDULogging);
289
290 // exec
291 uint8_t buf[APDU_RES_LEN] = {0};
292 size_t len = 0;
293 uint16_t sw = 0;
294 int res = EMVSelectPSE(activateField, leaveSignalON, PSENum, buf, sizeof(buf), &len, &sw);
295
296 if (sw)
297 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
3c5fce2b 298
f23565c3
OM
299 if (res)
300 return res;
301
302
303 if (decodeTLV)
304 TLVPrintFromBuffer(buf, len);
305
306 return 0;
307}
308
309int CmdHFEMVGPO(const char *cmd) {
310 uint8_t data[APDU_RES_LEN] = {0};
311 int datalen = 0;
312
313 CLIParserInit("hf emv gpo",
314 "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.",
315 "Usage:\n\thf emv gpo -k -> execute GPO\n"
92479429
OM
316 "\thf emv gpo -t 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n"
317 "\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");
f23565c3
OM
318
319 void* argtable[] = {
320 arg_param_begin,
321 arg_lit0("kK", "keep", "keep field ON for next command"),
92479429
OM
322 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for PDOLdata making from PDOL and parameters"),
323 arg_lit0("mM", "make", "make PDOLdata from PDOL (tag 9F38) and parameters (by default uses default parameters)"),
f23565c3
OM
324 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
325 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
11146fc1 326 arg_strx0(NULL, NULL, "<HEX PDOLdata/PDOL>", NULL),
f23565c3
OM
327 arg_param_end
328 };
329 CLIExecWithReturn(cmd, argtable, true);
330
331 bool leaveSignalON = arg_get_lit(1);
332 bool paramsLoadFromFile = arg_get_lit(2);
333 bool dataMakeFromPDOL = arg_get_lit(3);
334 bool APDULogging = arg_get_lit(4);
335 bool decodeTLV = arg_get_lit(5);
336 CLIGetStrWithReturn(6, data, &datalen);
337 CLIParserFree();
338
339 SetAPDULogging(APDULogging);
340
341 // Init TLV tree
342 const char *alr = "Root terminal TLV tree";
343 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
344
345 // calc PDOL
346 struct tlv *pdol_data_tlv = NULL;
347 struct tlv data_tlv = {
11146fc1 348 .tag = 0x83,
f23565c3
OM
349 .len = datalen,
350 .value = (uint8_t *)data,
351 };
352 if (dataMakeFromPDOL) {
f23565c3
OM
353 ParamLoadDefaults(tlvRoot);
354
355 if (paramsLoadFromFile) {
92479429
OM
356 PrintAndLog("Params loading from file...");
357 ParamLoadFromJson(tlvRoot);
f23565c3 358 };
92479429
OM
359
360 pdol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x9f38, datalen, data), tlvRoot, 0x83);
f23565c3
OM
361 if (!pdol_data_tlv){
362 PrintAndLog("ERROR: can't create PDOL TLV.");
363 tlvdb_free(tlvRoot);
364 return 4;
92479429 365 }
f23565c3 366 } else {
92479429
OM
367 if (paramsLoadFromFile) {
368 PrintAndLog("WARNING: don't need to load parameters. Sending plain PDOL data...");
369 }
f23565c3 370 pdol_data_tlv = &data_tlv;
3c5fce2b
OM
371 }
372
f23565c3
OM
373 size_t pdol_data_tlv_data_len = 0;
374 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
375 if (!pdol_data_tlv_data) {
376 PrintAndLog("ERROR: can't create PDOL data.");
377 tlvdb_free(tlvRoot);
378 return 4;
3c5fce2b 379 }
f23565c3 380 PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
3c5fce2b
OM
381
382 // exec
383 uint8_t buf[APDU_RES_LEN] = {0};
384 size_t len = 0;
385 uint16_t sw = 0;
f23565c3
OM
386 int res = EMVGPO(leaveSignalON, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
387
92479429
OM
388 if (pdol_data_tlv != &data_tlv)
389 free(pdol_data_tlv);
f23565c3
OM
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
404int CmdHFEMVReadRecord(const char *cmd) {
405 uint8_t data[APDU_RES_LEN] = {0};
406 int datalen = 0;
407
408 CLIParserInit("hf emv readrec",
409 "Executes Read Record command. It returns data in TLV format.\nNeeds a bank applet to be selected and sometimes needs GPO to be executed.",
410 "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");
411
412 void* argtable[] = {
413 arg_param_begin,
414 arg_lit0("kK", "keep", "keep field ON for next command"),
415 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
416 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
11146fc1 417 arg_strx1(NULL, NULL, "<SFI 1byte HEX><SFIrec 1byte HEX>", NULL),
f23565c3
OM
418 arg_param_end
419 };
420 CLIExecWithReturn(cmd, argtable, true);
421
422 bool leaveSignalON = arg_get_lit(1);
423 bool APDULogging = arg_get_lit(2);
424 bool decodeTLV = arg_get_lit(3);
425 CLIGetStrWithReturn(4, data, &datalen);
426 CLIParserFree();
427
428 if (datalen != 2) {
429 PrintAndLog("ERROR: Command needs to have 2 bytes of data");
430 return 1;
431 }
432
433 SetAPDULogging(APDULogging);
434
435 // exec
436 uint8_t buf[APDU_RES_LEN] = {0};
437 size_t len = 0;
438 uint16_t sw = 0;
439 int res = EMVReadRecord(leaveSignalON, data[0], data[1], buf, sizeof(buf), &len, &sw, NULL);
3c5fce2b
OM
440
441 if (sw)
442 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
443
444 if (res)
445 return res;
446
447
448 if (decodeTLV)
449 TLVPrintFromBuffer(buf, len);
450
451 return 0;
452}
453
f23565c3
OM
454int CmdHFEMVAC(const char *cmd) {
455 uint8_t data[APDU_RES_LEN] = {0};
456 int datalen = 0;
457
458 CLIParserInit("hf emv genac",
459 "Generate Application Cryptogram command. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.",
460 "Usage:\n\thf emv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n"
461 "\thf emv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n"
92479429
OM
462 "\thf emv genac -Daac 01020304 -> generate AC with 4-byte CDOL data and terminal decision 'declined'\n"
463 "\thf emv genac -pmt 9F 37 04 -> load params from file, make CDOL data from CDOL, generate AC with CDOL, show result in TLV");
f23565c3
OM
464
465 void* argtable[] = {
466 arg_param_begin,
467 arg_lit0("kK", "keep", "keep field ON for next command"),
468 arg_lit0("cC", "cda", "executes CDA transaction. Needs to get SDAD in results."),
469 arg_str0("dD", "decision", "<aac|tc|arqc>", "Terminal decision. aac - declined, tc - approved, arqc - online authorisation requested"),
92479429
OM
470 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for CDOLdata making from CDOL and parameters"),
471 arg_lit0("mM", "make", "make CDOLdata from CDOL (tag 8C and 8D) and parameters (by default uses default parameters)"),
f23565c3
OM
472 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
473 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
92479429 474 arg_strx1(NULL, NULL, "<HEX CDOLdata/CDOL>", NULL),
f23565c3
OM
475 arg_param_end
476 };
477 CLIExecWithReturn(cmd, argtable, false);
478
479 bool leaveSignalON = arg_get_lit(1);
480 bool trTypeCDA = arg_get_lit(2);
481 uint8_t termDecision = 0xff;
482 if (arg_get_str_len(3)) {
483 if (!strncmp(arg_get_str(3)->sval[0], "aac", 4))
484 termDecision = EMVAC_AAC;
485 if (!strncmp(arg_get_str(3)->sval[0], "tc", 4))
486 termDecision = EMVAC_TC;
487 if (!strncmp(arg_get_str(3)->sval[0], "arqc", 4))
488 termDecision = EMVAC_ARQC;
489
490 if (termDecision == 0xff) {
491 PrintAndLog("ERROR: can't find terminal decision '%s'", arg_get_str(3)->sval[0]);
492 return 1;
493 }
494 } else {
495 termDecision = EMVAC_TC;
496 }
497 if (trTypeCDA)
498 termDecision = termDecision | EMVAC_CDAREQ;
92479429
OM
499 bool paramsLoadFromFile = arg_get_lit(4);
500 bool dataMakeFromCDOL = arg_get_lit(5);
501 bool APDULogging = arg_get_lit(6);
502 bool decodeTLV = arg_get_lit(7);
503 CLIGetStrWithReturn(8, data, &datalen);
f23565c3
OM
504 CLIParserFree();
505
506 SetAPDULogging(APDULogging);
507
508 // Init TLV tree
509 const char *alr = "Root terminal TLV tree";
510 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
511
512 // calc CDOL
513 struct tlv *cdol_data_tlv = NULL;
f23565c3
OM
514 struct tlv data_tlv = {
515 .tag = 0x01,
516 .len = datalen,
517 .value = (uint8_t *)data,
92479429 518 };
f23565c3 519
92479429
OM
520 if (dataMakeFromCDOL) {
521 ParamLoadDefaults(tlvRoot);
522
523 if (paramsLoadFromFile) {
524 PrintAndLog("Params loading from file...");
525 ParamLoadFromJson(tlvRoot);
526 };
527
528 cdol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x8c, datalen, data), tlvRoot, 0x01); // 0x01 - dummy tag
529 if (!cdol_data_tlv){
530 PrintAndLog("ERROR: can't create CDOL TLV.");
531 tlvdb_free(tlvRoot);
532 return 4;
533 }
534 } else {
535 if (paramsLoadFromFile) {
536 PrintAndLog("WARNING: don't need to load parameters. Sending plain CDOL data...");
537 }
538 cdol_data_tlv = &data_tlv;
539 }
540
541 PrintAndLog("CDOL data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len));
542
f23565c3
OM
543 // exec
544 uint8_t buf[APDU_RES_LEN] = {0};
545 size_t len = 0;
546 uint16_t sw = 0;
547 int res = EMVAC(leaveSignalON, termDecision, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
548
92479429
OM
549 if (cdol_data_tlv != &data_tlv)
550 free(cdol_data_tlv);
f23565c3
OM
551 tlvdb_free(tlvRoot);
552
553 if (sw)
554 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
555
556 if (res)
557 return res;
558
559 if (decodeTLV)
560 TLVPrintFromBuffer(buf, len);
561
562 return 0;
563}
564
565int CmdHFEMVGenerateChallenge(const char *cmd) {
566
567 CLIParserInit("hf emv challenge",
568 "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.",
569 "Usage:\n\thf emv challenge -> get challenge\n\thf emv challenge -k -> get challenge, keep fileld ON\n");
570
571 void* argtable[] = {
572 arg_param_begin,
573 arg_lit0("kK", "keep", "keep field ON for next command"),
574 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
575 arg_param_end
576 };
577 CLIExecWithReturn(cmd, argtable, true);
578
579 bool leaveSignalON = arg_get_lit(1);
580 bool APDULogging = arg_get_lit(2);
581 CLIParserFree();
582
583 SetAPDULogging(APDULogging);
584
585 // exec
586 uint8_t buf[APDU_RES_LEN] = {0};
587 size_t len = 0;
588 uint16_t sw = 0;
589 int res = EMVGenerateChallenge(leaveSignalON, buf, sizeof(buf), &len, &sw, NULL);
590
591 if (sw)
592 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
593
594 if (res)
595 return res;
596
597 PrintAndLog("Challenge: %s", sprint_hex(buf, len));
598
599 if (len != 4 && len != 8)
600 PrintAndLog("WARNING: length of challenge must be 4 or 8, but it %d", len);
601
3c5fce2b
OM
602 return 0;
603}
604
f23565c3
OM
605int CmdHFEMVInternalAuthenticate(const char *cmd) {
606 uint8_t data[APDU_RES_LEN] = {0};
607 int datalen = 0;
608
609 CLIParserInit("hf emv intauth",
610 "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.",
611 "Usage:\n\thf emv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n"
92479429
OM
612 "\thf emv intauth -t 01020304 -> execute Internal Authenticate with 4-byte DDOL data, show result in TLV\n"
613 "\thf emv intauth -pmt 9F 37 04 -> load params from file, make DDOL data from DDOL, Internal Authenticate with DDOL, show result in TLV");
f23565c3
OM
614
615 void* argtable[] = {
616 arg_param_begin,
617 arg_lit0("kK", "keep", "keep field ON for next command"),
92479429
OM
618 arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for DDOLdata making from DDOL and parameters"),
619 arg_lit0("mM", "make", "make DDOLdata from DDOL (tag 9F49) and parameters (by default uses default parameters)"),
f23565c3
OM
620 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
621 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
92479429 622 arg_strx1(NULL, NULL, "<HEX DDOLdata/DDOL>", NULL),
f23565c3
OM
623 arg_param_end
624 };
625 CLIExecWithReturn(cmd, argtable, false);
626
627 bool leaveSignalON = arg_get_lit(1);
92479429
OM
628 bool paramsLoadFromFile = arg_get_lit(2);
629 bool dataMakeFromDDOL = arg_get_lit(3);
630 bool APDULogging = arg_get_lit(4);
631 bool decodeTLV = arg_get_lit(5);
632 CLIGetStrWithReturn(6, data, &datalen);
f23565c3
OM
633 CLIParserFree();
634
635 SetAPDULogging(APDULogging);
92479429
OM
636
637 // Init TLV tree
638 const char *alr = "Root terminal TLV tree";
639 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
640
641 // calc DDOL
642 struct tlv *ddol_data_tlv = NULL;
643 struct tlv data_tlv = {
644 .tag = 0x01,
645 .len = datalen,
646 .value = (uint8_t *)data,
647 };
648
649 if (dataMakeFromDDOL) {
650 ParamLoadDefaults(tlvRoot);
651
652 if (paramsLoadFromFile) {
653 PrintAndLog("Params loading from file...");
654 ParamLoadFromJson(tlvRoot);
655 };
656
657 ddol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x9f49, datalen, data), tlvRoot, 0x01); // 0x01 - dummy tag
658 if (!ddol_data_tlv){
659 PrintAndLog("ERROR: can't create DDOL TLV.");
660 tlvdb_free(tlvRoot);
661 return 4;
662 }
663 } else {
664 if (paramsLoadFromFile) {
665 PrintAndLog("WARNING: don't need to load parameters. Sending plain DDOL data...");
666 }
667 ddol_data_tlv = &data_tlv;
668 }
f23565c3 669
92479429 670 PrintAndLog("DDOL data[%d]: %s", ddol_data_tlv->len, sprint_hex(ddol_data_tlv->value, ddol_data_tlv->len));
f23565c3
OM
671
672 // exec
673 uint8_t buf[APDU_RES_LEN] = {0};
674 size_t len = 0;
675 uint16_t sw = 0;
676 int res = EMVInternalAuthenticate(leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL);
677
92479429
OM
678 if (ddol_data_tlv != &data_tlv)
679 free(ddol_data_tlv);
680 tlvdb_free(tlvRoot);
681
f23565c3
OM
682 if (sw)
683 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
684
685 if (res)
686 return res;
687
688 if (decodeTLV)
689 TLVPrintFromBuffer(buf, len);
690
691 return 0;
692}
693
d03fb293 694#define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;}
3c5fce2b
OM
695
696int CmdHFEMVExec(const char *cmd) {
3c5fce2b
OM
697 uint8_t buf[APDU_RES_LEN] = {0};
698 size_t len = 0;
699 uint16_t sw = 0;
700 uint8_t AID[APDU_AID_LEN] = {0};
701 size_t AIDlen = 0;
d03fb293
OM
702 uint8_t ODAiList[4096];
703 size_t ODAiListLen = 0;
3c5fce2b
OM
704
705 int res;
706
d03fb293
OM
707 struct tlvdb *tlvSelect = NULL;
708 struct tlvdb *tlvRoot = NULL;
709 struct tlv *pdol_data_tlv = NULL;
710
f23565c3
OM
711 CLIParserInit("hf emv exec",
712 "Executes EMV contactless transaction",
713 "Usage:\n\thf emv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n"
714 "\thf emv exec -satc -> select card, execute CDA transaction, show APDU and TLV\n");
715
716 void* argtable[] = {
717 arg_param_begin,
718 arg_lit0("sS", "select", "activate field and select card."),
719 arg_lit0("aA", "apdu", "show APDU reqests and responses."),
720 arg_lit0("tT", "tlv", "TLV decode results."),
721 arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."),
722 arg_lit0("fF", "forceaid", "Force search AID. Search AID instead of execute PPSE."),
723 arg_rem("By default:", "Transaction type - MSD"),
724 arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."),
725 arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."),
726 arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."),
727 arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
728 arg_param_end
729 };
730 CLIExecWithReturn(cmd, argtable, true);
3c5fce2b 731
f23565c3
OM
732 bool activateField = arg_get_lit(1);
733 bool showAPDU = arg_get_lit(2);
734 bool decodeTLV = arg_get_lit(3);
735 bool paramLoadJSON = arg_get_lit(4);
736 bool forceSearch = arg_get_lit(5);
3c5fce2b 737
f23565c3
OM
738 enum TransactionType TrType = TT_MSD;
739 if (arg_get_lit(6))
740 TrType = TT_QVSDCMCHIP;
741 if (arg_get_lit(7))
742 TrType = TT_CDA;
743 if (arg_get_lit(8))
744 TrType = TT_VSDC;
745
746 bool GenACGPO = arg_get_lit(9);
747 CLIParserFree();
748
749 SetAPDULogging(showAPDU);
3c5fce2b
OM
750
751 // init applets list tree
3c5fce2b
OM
752 const char *al = "Applets list";
753 tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
754
755 // Application Selection
756 // https://www.openscdp.org/scripts/tutorial/emv/applicationselection.html
757 if (!forceSearch) {
758 // PPSE
759 PrintAndLog("\n* PPSE.");
760 SetAPDULogging(showAPDU);
761 res = EMVSearchPSE(activateField, true, decodeTLV, tlvSelect);
762
763 // check PPSE and select application id
764 if (!res) {
765 TLVPrintAIDlistFromSelectTLV(tlvSelect);
766 EMVSelectApplication(tlvSelect, AID, &AIDlen);
767 }
768 }
769
770 // Search
771 if (!AIDlen) {
772 PrintAndLog("\n* Search AID in list.");
773 SetAPDULogging(false);
774 if (EMVSearch(activateField, true, decodeTLV, tlvSelect)) {
d03fb293 775 dreturn(2);
3c5fce2b
OM
776 }
777
778 // check search and select application id
779 TLVPrintAIDlistFromSelectTLV(tlvSelect);
780 EMVSelectApplication(tlvSelect, AID, &AIDlen);
781 }
782
783 // Init TLV tree
3c5fce2b
OM
784 const char *alr = "Root terminal TLV tree";
785 tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
786
787 // check if we found EMV application on card
788 if (!AIDlen) {
789 PrintAndLog("Can't select AID. EMV AID not found");
d03fb293 790 dreturn(2);
3c5fce2b
OM
791 }
792
793 // Select
794 PrintAndLog("\n* Selecting AID:%s", sprint_hex_inrow(AID, AIDlen));
795 SetAPDULogging(showAPDU);
796 res = EMVSelect(false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
797
798 if (res) {
799 PrintAndLog("Can't select AID (%d). Exit...", res);
d03fb293 800 dreturn(3);
3c5fce2b
OM
801 }
802
803 if (decodeTLV)
804 TLVPrintFromBuffer(buf, len);
805 PrintAndLog("* Selected.");
806
3c5fce2b
OM
807 PrintAndLog("\n* Init transaction parameters.");
808
556826b5
OM
809 ParamLoadDefaults(tlvRoot);
810
811 if (paramLoadJSON) {
812 PrintAndLog("* * Transaction parameters loading from JSON...");
813 ParamLoadFromJson(tlvRoot);
814 }
815
816 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
d03fb293
OM
817 char *qVSDC = "\x26\x00\x00\x00";
818 if (GenACGPO) {
819 qVSDC = "\x26\x80\x00\x00";
820 }
10d4f823 821 switch(TrType) {
822 case TT_MSD:
823 TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD
824 break;
d03fb293 825 // not standard for contactless. just for test.
10d4f823 826 case TT_VSDC:
827 TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC
828 break;
829 case TT_QVSDCMCHIP:
d03fb293 830 TLV_ADD(0x9F66, qVSDC); // qVSDC
10d4f823 831 break;
832 case TT_CDA:
d03fb293 833 TLV_ADD(0x9F66, qVSDC); // qVSDC (VISA CDA not enabled)
10d4f823 834 break;
835 default:
10d4f823 836 break;
837 }
d03fb293 838
66efdc1f 839 TLVPrintFromTLV(tlvRoot); // TODO delete!!!
3c5fce2b
OM
840
841 PrintAndLog("\n* Calc PDOL.");
d03fb293 842 pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
3c5fce2b
OM
843 if (!pdol_data_tlv){
844 PrintAndLog("ERROR: can't create PDOL TLV.");
d03fb293 845 dreturn(4);
3c5fce2b
OM
846 }
847
848 size_t pdol_data_tlv_data_len;
849 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
850 if (!pdol_data_tlv_data) {
851 PrintAndLog("ERROR: can't create PDOL data.");
d03fb293 852 dreturn(4);
3c5fce2b
OM
853 }
854 PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
855
3c5fce2b
OM
856 PrintAndLog("\n* GPO.");
857 res = EMVGPO(true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
858
10d4f823 859 free(pdol_data_tlv_data);
d03fb293 860 //free(pdol_data_tlv); --- free on exit.
3c5fce2b
OM
861
862 if (res) {
863 PrintAndLog("GPO error(%d): %4x. Exit...", res, sw);
d03fb293 864 dreturn(5);
3c5fce2b
OM
865 }
866
867 // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
868 if (buf[0] == 0x80) {
3c5fce2b
OM
869 if (decodeTLV){
870 PrintAndLog("GPO response format1:");
871 TLVPrintFromBuffer(buf, len);
872 }
3c5fce2b 873
66efdc1f 874 if (len < 4 || (len - 4) % 4) {
875 PrintAndLog("ERROR: GPO response format1 parsing error. length=%d", len);
876 } else {
877 // AIP
878 struct tlvdb * f1AIP = tlvdb_fixed(0x82, 2, buf + 2);
879 tlvdb_add(tlvRoot, f1AIP);
880 if (decodeTLV){
881 PrintAndLog("\n* * Decode response format 1 (0x80) AIP and AFL:");
882 TLVPrintFromTLV(f1AIP);
883 }
884
885 // AFL
886 struct tlvdb * f1AFL = tlvdb_fixed(0x94, len - 4, buf + 2 + 2);
887 tlvdb_add(tlvRoot, f1AFL);
888 if (decodeTLV)
889 TLVPrintFromTLV(f1AFL);
890 }
891 } else {
3c5fce2b
OM
892 if (decodeTLV)
893 TLVPrintFromBuffer(buf, len);
894 }
895
66efdc1f 896 // extract PAN from track2
897 {
898 const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
899 if (!tlvdb_get(tlvRoot, 0x5a, NULL) && track2 && track2->len >= 8) {
900 struct tlvdb *pan = GetPANFromTrack2(track2);
901 if (pan) {
902 tlvdb_add(tlvRoot, pan);
903
904 const struct tlv *pantlv = tlvdb_get(tlvRoot, 0x5a, NULL);
905 PrintAndLog("\n* * Extracted PAN from track2: %s", sprint_hex(pantlv->value, pantlv->len));
906 } else {
907 PrintAndLog("\n* * WARNING: Can't extract PAN from track2.");
908 }
909 }
910 }
911
3c5fce2b
OM
912 PrintAndLog("\n* Read records from AFL.");
913 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
914 if (!AFL || !AFL->len) {
915 PrintAndLog("WARNING: AFL not found.");
916 }
917
918 while(AFL && AFL->len) {
919 if (AFL->len % 4) {
920 PrintAndLog("ERROR: Wrong AFL length: %d", AFL->len);
921 break;
922 }
923
924 for (int i = 0; i < AFL->len / 4; i++) {
925 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
926 uint8_t SFIstart = AFL->value[i * 4 + 1];
927 uint8_t SFIend = AFL->value[i * 4 + 2];
928 uint8_t SFIoffline = AFL->value[i * 4 + 3];
929
930 PrintAndLog("* * SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
931 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
932 PrintAndLog("SFI ERROR! Skipped...");
933 continue;
934 }
935
936 for(int n = SFIstart; n <= SFIend; n++) {
937 PrintAndLog("* * * SFI[%02x] %d", SFI, n);
938
939 res = EMVReadRecord(true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
940 if (res) {
941 PrintAndLog("ERROR SFI[%02x]. APDU error %4x", SFI, sw);
942 continue;
943 }
944
945 if (decodeTLV) {
946 TLVPrintFromBuffer(buf, len);
947 PrintAndLog("");
948 }
949
d03fb293
OM
950 // Build Input list for Offline Data Authentication
951 // EMV 4.3 book3 10.3, page 96
3c5fce2b 952 if (SFIoffline) {
d03fb293
OM
953 if (SFI < 11) {
954 const unsigned char *abuf = buf;
955 size_t elmlen = len;
956 struct tlv e;
957 if (tlv_parse_tl(&abuf, &elmlen, &e)) {
958 memcpy(&ODAiList[ODAiListLen], &buf[len - elmlen], elmlen);
959 ODAiListLen += elmlen;
960 } else {
961 PrintAndLog("ERROR SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI);
962 }
963 } else {
964 memcpy(&ODAiList[ODAiListLen], buf, len);
965 ODAiListLen += len;
966 }
3c5fce2b
OM
967 }
968 }
969 }
970
971 break;
972 }
973
d03fb293
OM
974 // copy Input list for Offline Data Authentication
975 if (ODAiListLen) {
976 struct tlvdb *oda = tlvdb_fixed(0x21, ODAiListLen, ODAiList); // not a standard tag
977 tlvdb_add(tlvRoot, oda);
978 PrintAndLog("* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen);
979 }
980
10d4f823 981 // get AIP
66efdc1f 982 const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL);
983 uint16_t AIP = AIPtlv->value[0] + AIPtlv->value[1] * 0x100;
10d4f823 984 PrintAndLog("* * AIP=%04x", AIP);
66efdc1f 985
10d4f823 986 // SDA
987 if (AIP & 0x0040) {
988 PrintAndLog("\n* SDA");
d03fb293 989 trSDA(tlvRoot);
10d4f823 990 }
991
992 // DDA
993 if (AIP & 0x0020) {
994 PrintAndLog("\n* DDA");
d03fb293 995 trDDA(decodeTLV, tlvRoot);
10d4f823 996 }
997
998 // transaction check
999
66efdc1f 1000 // qVSDC
10d4f823 1001 if (TrType == TT_QVSDCMCHIP|| TrType == TT_CDA){
66efdc1f 1002 // 9F26: Application Cryptogram
1003 const struct tlv *AC = tlvdb_get(tlvRoot, 0x9F26, NULL);
1004 if (AC) {
1005 PrintAndLog("\n--> qVSDC transaction.");
1006 PrintAndLog("* AC path");
1007
1008 // 9F36: Application Transaction Counter (ATC)
1009 const struct tlv *ATC = tlvdb_get(tlvRoot, 0x9F36, NULL);
1010 if (ATC) {
1011
1012 // 9F10: Issuer Application Data - optional
1013 const struct tlv *IAD = tlvdb_get(tlvRoot, 0x9F10, NULL);
1014
1015 // print AC data
1016 PrintAndLog("ATC: %s", sprint_hex(ATC->value, ATC->len));
1017 PrintAndLog("AC: %s", sprint_hex(AC->value, AC->len));
1018 if (IAD){
1019 PrintAndLog("IAD: %s", sprint_hex(IAD->value, IAD->len));
1020
1021 if (IAD->len >= IAD->value[0] + 1) {
1022 PrintAndLog("\tKey index: 0x%02x", IAD->value[1]);
1023 PrintAndLog("\tCrypto ver: 0x%02x(%03d)", IAD->value[2], IAD->value[2]);
1024 PrintAndLog("\tCVR:", sprint_hex(&IAD->value[3], IAD->value[0] - 2));
1025 struct tlvdb * cvr = tlvdb_fixed(0x20, IAD->value[0] - 2, &IAD->value[3]);
1026 TLVPrintFromTLVLev(cvr, 1);
1027 }
1028 } else {
1029 PrintAndLog("WARNING: IAD not found.");
1030 }
1031
1032 } else {
1033 PrintAndLog("ERROR AC: Application Transaction Counter (ATC) not found.");
1034 }
1035 }
1036 }
1037
10d4f823 1038 // Mastercard M/CHIP
1039 if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD && (TrType == TT_QVSDCMCHIP || TrType == TT_CDA)){
66efdc1f 1040 const struct tlv *CDOL1 = tlvdb_get(tlvRoot, 0x8c, NULL);
1041 if (CDOL1 && GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) { // and m/chip transaction flag
10d4f823 1042 PrintAndLog("\n--> Mastercard M/Chip transaction.");
1043
1044 PrintAndLog("* * Generate challenge");
1045 res = EMVGenerateChallenge(true, buf, sizeof(buf), &len, &sw, tlvRoot);
1046 if (res) {
1047 PrintAndLog("ERROR GetChallenge. APDU error %4x", sw);
d03fb293 1048 dreturn(6);
10d4f823 1049 }
1050 if (len < 4) {
1051 PrintAndLog("ERROR GetChallenge. Wrong challenge length %d", len);
d03fb293 1052 dreturn(6);
10d4f823 1053 }
1054
1055 // ICC Dynamic Number
1056 struct tlvdb * ICCDynN = tlvdb_fixed(0x9f4c, len, buf);
1057 tlvdb_add(tlvRoot, ICCDynN);
1058 if (decodeTLV){
1059 PrintAndLog("\n* * ICC Dynamic Number:");
1060 TLVPrintFromTLV(ICCDynN);
1061 }
1062
1063 PrintAndLog("* * Calc CDOL1");
1064 struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
1065 if (!cdol_data_tlv){
1066 PrintAndLog("ERROR: can't create CDOL1 TLV.");
d03fb293 1067 dreturn(6);
10d4f823 1068 }
1069 PrintAndLog("CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len));
1070
1071 PrintAndLog("* * AC1");
1072 // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
1073 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);
1074
10d4f823 1075 if (res) {
1076 PrintAndLog("AC1 error(%d): %4x. Exit...", res, sw);
d03fb293 1077 dreturn(7);
10d4f823 1078 }
1079
1080 if (decodeTLV)
1081 TLVPrintFromBuffer(buf, len);
1082
d03fb293
OM
1083 // CDA
1084 PrintAndLog("\n* CDA:");
1085 struct tlvdb *ac_tlv = tlvdb_parse_multi(buf, len);
1086 res = trCDA(tlvRoot, ac_tlv, pdol_data_tlv, cdol_data_tlv);
1087 if (res) {
1088 PrintAndLog("CDA error (%d)", res);
1089 }
1090 free(ac_tlv);
1091 free(cdol_data_tlv);
1092
1093 PrintAndLog("\n* M/Chip transaction result:");
10d4f823 1094 // 9F27: Cryptogram Information Data (CID)
1095 const struct tlv *CID = tlvdb_get(tlvRoot, 0x9F27, NULL);
1096 if (CID) {
1097 emv_tag_dump(CID, stdout, 0);
1098 PrintAndLog("------------------------------");
1099 if (CID->len > 0) {
1100 switch(CID->value[0] & EMVAC_AC_MASK){
1101 case EMVAC_AAC:
1102 PrintAndLog("Transaction DECLINED.");
1103 break;
1104 case EMVAC_TC:
1105 PrintAndLog("Transaction approved OFFLINE.");
1106 break;
1107 case EMVAC_ARQC:
1108 PrintAndLog("Transaction approved ONLINE.");
1109 break;
1110 default:
1111 PrintAndLog("ERROR: CID transaction code error %2x", CID->value[0] & EMVAC_AC_MASK);
1112 break;
1113 }
1114 } else {
1115 PrintAndLog("ERROR: Wrong CID length %d", CID->len);
1116 }
1117 } else {
1118 PrintAndLog("ERROR: CID(9F27) not found.");
1119 }
66efdc1f 1120
1121 }
1122 }
1123
1124 // MSD
10d4f823 1125 if (AIP & 0x8000 && TrType == TT_MSD) {
66efdc1f 1126 PrintAndLog("\n--> MSD transaction.");
1127
66efdc1f 1128 PrintAndLog("* MSD dCVV path. Check dCVV");
1129
1130 const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
1131 if (track2) {
1132 PrintAndLog("Track2: %s", sprint_hex(track2->value, track2->len));
1133
1134 struct tlvdb *dCVV = GetdCVVRawFromTrack2(track2);
1135 PrintAndLog("dCVV raw data:");
1136 TLVPrintFromTLV(dCVV);
1137
1138 if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) {
1139 PrintAndLog("\n* Mastercard calculate UDOL");
1140
1141 // UDOL (9F69)
1142 const struct tlv *UDOL = tlvdb_get(tlvRoot, 0x9F69, NULL);
1143 // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
1144 const struct tlv defUDOL = {
1145 .tag = 0x01,
1146 .len = 3,
1147 .value = (uint8_t *)"\x9f\x6a\x04",
1148 };
1149 if (!UDOL)
1150 PrintAndLog("Use default UDOL.");
1151
10d4f823 1152 struct tlv *udol_data_tlv = dol_process(UDOL ? UDOL : &defUDOL, tlvRoot, 0x01); // 0x01 - dummy tag
66efdc1f 1153 if (!udol_data_tlv){
1154 PrintAndLog("ERROR: can't create UDOL TLV.");
d03fb293 1155 dreturn(8);
66efdc1f 1156 }
66efdc1f 1157
78528074 1158 PrintAndLog("UDOL data[%d]: %s", udol_data_tlv->len, sprint_hex(udol_data_tlv->value, udol_data_tlv->len));
66efdc1f 1159
1160 PrintAndLog("\n* Mastercard compute cryptographic checksum(UDOL)");
1161
78528074 1162 res = MSCComputeCryptoChecksum(true, (uint8_t *)udol_data_tlv->value, udol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
66efdc1f 1163 if (res) {
1164 PrintAndLog("ERROR Compute Crypto Checksum. APDU error %4x", sw);
d03fb293
OM
1165 free(udol_data_tlv);
1166 dreturn(9);
66efdc1f 1167 }
1168
1169 if (decodeTLV) {
1170 TLVPrintFromBuffer(buf, len);
1171 PrintAndLog("");
1172 }
d03fb293 1173 free(udol_data_tlv);
66efdc1f 1174
1175 }
1176 } else {
1177 PrintAndLog("ERROR MSD: Track2 data not found.");
1178 }
1179 }
d03fb293 1180
3c5fce2b
OM
1181 // DropField
1182 DropField();
1183
1184 // Destroy TLV's
d03fb293 1185 free(pdol_data_tlv);
3c5fce2b
OM
1186 tlvdb_free(tlvSelect);
1187 tlvdb_free(tlvRoot);
1188
1189 PrintAndLog("\n* Transaction completed.");
1190
1191 return 0;
1192}
1193
556826b5
OM
1194int UsageCmdHFEMVScan(void) {
1195 PrintAndLog("HELP : Scan EMV card and save it contents to a file. \n");
1196 PrintAndLog(" It executes EMV contactless transaction and saves result to a file which can be used for emulation.\n");
1197 PrintAndLog("Usage: hf emv scan [-a][-t][-v][-c][-x][-g] <file_name>\n");
1198 PrintAndLog(" Options:");
1199 PrintAndLog(" -a : show APDU reqests and responses\n");
1200 PrintAndLog(" -t : TLV decode results\n");
1201 PrintAndLog(" -v : transaction type - qVSDC or M/Chip.\n");
1202 PrintAndLog(" -c : transaction type - qVSDC or M/Chip plus CDA (SDAD generation).\n");
1203 PrintAndLog(" -x : transaction type - VSDC. For test only. Not a standart behavior.\n");
1204 PrintAndLog(" -g : VISA. generate AC from GPO\n");
1205 PrintAndLog("By default : transaction type - MSD.\n");
1206 PrintAndLog("Samples:");
1207 PrintAndLog(" hf emv scan -a -t -> scan MSD transaction mode");
1208 PrintAndLog(" hf emv scan -a -t -c -> scan CDA transaction mode");
1209 return 0;
1210}
1211
1212int CmdHFEMVScan(const char *cmd) {
1213 UsageCmdHFEMVScan();
1214
1215 return 0;
1216}
1217
d03fb293
OM
1218int CmdHFEMVTest(const char *cmd) {
1219 return ExecuteCryptoTests(true);
1220}
1221
3c5fce2b
OM
1222int CmdHelp(const char *Cmd);
1223static command_t CommandTable[] = {
f23565c3
OM
1224 {"help", CmdHelp, 1, "This help"},
1225 {"exec", CmdHFEMVExec, 0, "Executes EMV contactless transaction."},
1226 {"pse", CmdHFEMVPPSE, 0, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."},
1227 {"search", CmdHFEMVSearch, 0, "Try to select all applets from applets list and print installed applets."},
1228 {"select", CmdHFEMVSelect, 0, "Select applet."},
1229 {"gpo", CmdHFEMVGPO, 0, "Execute GetProcessingOptions."},
1230 {"readrec", CmdHFEMVReadRecord, 0, "Read files from card."},
1231 {"genac", CmdHFEMVAC, 0, "Generate ApplicationCryptogram."},
1232 {"challenge", CmdHFEMVGenerateChallenge, 0, "Generate challenge."},
1233 {"intauth", CmdHFEMVInternalAuthenticate, 0, "Internal authentication."},
556826b5 1234// {"scan", CmdHFEMVScan, 0, "Scan EMV card and save it contents to json file for emulator."},
f23565c3 1235 {"test", CmdHFEMVTest, 0, "Crypto logic test."},
3c5fce2b
OM
1236 {NULL, NULL, 0, NULL}
1237};
1238
1239int CmdHFEMV(const char *Cmd) {
1240 CmdsParse(CommandTable, Cmd);
1241 return 0;
1242}
1243
1244int CmdHelp(const char *Cmd) {
1245 CmdsHelp(CommandTable);
1246 return 0;
1247}
Impressum, Datenschutz