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