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