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