added SoloKey certificate (#778)
[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) {
6b5105be 48 uint8_t data[APDU_DATA_LEN] = {0};
3c5fce2b 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
6b5105be 86 uint8_t buf[APDU_RESPONSE_LEN] = {0};
3c5fce2b
OM
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
6b5105be 196 uint8_t buf[APDU_RESPONSE_LEN] = {0};
f23565c3
OM
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) {
6b5105be 215 uint8_t data[APDU_RESPONSE_LEN] = {0};
f23565c3
OM
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
6b5105be 298 uint8_t buf[APDU_RESPONSE_LEN] = {0};
3c5fce2b
OM
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) {
6b5105be 320 uint8_t data[APDU_RESPONSE_LEN] = {0};
f23565c3
OM
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
6b5105be 359 uint8_t buf[APDU_RESPONSE_LEN] = {0};
f23565c3
OM
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) {
6b5105be 378 uint8_t data[APDU_RESPONSE_LEN] = {0};
f23565c3
OM
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 476 // exec
6b5105be 477 uint8_t buf[APDU_RESPONSE_LEN] = {0};
f23565c3
OM
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
6b5105be 527 uint8_t buf[APDU_RESPONSE_LEN] = {0};
f23565c3
OM
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) {
6b5105be 547 uint8_t data[APDU_RESPONSE_LEN] = {0};
f23565c3
OM
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
6b5105be 627 uint8_t buf[APDU_RESPONSE_LEN] = {0};
f23565c3
OM
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) {
6b5105be 714 uint8_t buf[APDU_RESPONSE_LEN] = {0};
3c5fce2b
OM
715 size_t len = 0;
716 uint16_t sw = 0;
6b5105be 717 uint8_t AID[APDU_DATA_LEN] = {0};
3c5fce2b 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;
6b5105be 772 char *PSE_or_PPSE = psenum == 1 ? "PSE" : "PPSE";
773
f23565c3
OM
774 CLIParserFree();
775
776 SetAPDULogging(showAPDU);
3c5fce2b
OM
777
778 // init applets list tree
3c5fce2b
OM
779 const char *al = "Applets list";
780 tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
781
782 // Application Selection
783 // https://www.openscdp.org/scripts/tutorial/emv/applicationselection.html
784 if (!forceSearch) {
6b5105be 785 // PPSE / PSE
786 PrintAndLogEx(NORMAL, "\n* %s.", PSE_or_PPSE);
3c5fce2b 787 SetAPDULogging(showAPDU);
1511ea28 788 res = EMVSearchPSE(channel, activateField, true, psenum, decodeTLV, tlvSelect);
3c5fce2b 789
6b5105be 790 // check PPSE / PSE and select application id
8d7d7b61 791 if (!res) {
3c5fce2b
OM
792 TLVPrintAIDlistFromSelectTLV(tlvSelect);
793 EMVSelectApplication(tlvSelect, AID, &AIDlen);
794 }
795 }
796
797 // Search
798 if (!AIDlen) {
8d7d7b61 799 PrintAndLogEx(NORMAL, "\n* Search AID in list.");
3c5fce2b 800 SetAPDULogging(false);
8d7d7b61 801 if (EMVSearch(channel, activateField, true, decodeTLV, tlvSelect)) {
d03fb293 802 dreturn(2);
3c5fce2b
OM
803 }
804
805 // check search and select application id
806 TLVPrintAIDlistFromSelectTLV(tlvSelect);
807 EMVSelectApplication(tlvSelect, AID, &AIDlen);
808 }
809
810 // Init TLV tree
3c5fce2b
OM
811 const char *alr = "Root terminal TLV tree";
812 tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
813
814 // check if we found EMV application on card
815 if (!AIDlen) {
8d7d7b61 816 PrintAndLogEx(WARNING, "Can't select AID. EMV AID not found");
d03fb293 817 dreturn(2);
3c5fce2b
OM
818 }
819
820 // Select
8d7d7b61 821 PrintAndLogEx(NORMAL, "\n* Selecting AID:%s", sprint_hex_inrow(AID, AIDlen));
3c5fce2b 822 SetAPDULogging(showAPDU);
8d7d7b61 823 res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
3c5fce2b 824
8d7d7b61 825 if (res) {
826 PrintAndLogEx(WARNING, "Can't select AID (%d). Exit...", res);
d03fb293 827 dreturn(3);
3c5fce2b
OM
828 }
829
830 if (decodeTLV)
831 TLVPrintFromBuffer(buf, len);
8d7d7b61 832 PrintAndLogEx(INFO, "* Selected.");
3c5fce2b 833
8d7d7b61 834 PrintAndLogEx(INFO, "\n* Init transaction parameters.");
95b697f0 835 InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO);
66efdc1f 836 TLVPrintFromTLV(tlvRoot); // TODO delete!!!
3c5fce2b 837
8d7d7b61 838 PrintAndLogEx(NORMAL, "\n* Calc PDOL.");
d03fb293 839 pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
3c5fce2b 840 if (!pdol_data_tlv){
8d7d7b61 841 PrintAndLogEx(WARNING, "Error: can't create PDOL TLV.");
d03fb293 842 dreturn(4);
3c5fce2b
OM
843 }
844
845 size_t pdol_data_tlv_data_len;
846 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
847 if (!pdol_data_tlv_data) {
8d7d7b61 848 PrintAndLogEx(WARNING, "Error: can't create PDOL data.");
d03fb293 849 dreturn(4);
3c5fce2b 850 }
8d7d7b61 851 PrintAndLogEx(NORMAL, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
3c5fce2b 852
8d7d7b61 853 PrintAndLogEx(NORMAL, "\n* GPO.");
854 res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
3c5fce2b 855
10d4f823 856 free(pdol_data_tlv_data);
d03fb293 857 //free(pdol_data_tlv); --- free on exit.
3c5fce2b 858
8d7d7b61 859 if (res) {
860 PrintAndLogEx(NORMAL, "GPO error(%d): %4x. Exit...", res, sw);
d03fb293 861 dreturn(5);
3c5fce2b
OM
862 }
863
864 // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
95b697f0 865 ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV);
3c5fce2b 866
66efdc1f 867 // extract PAN from track2
868 {
869 const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
870 if (!tlvdb_get(tlvRoot, 0x5a, NULL) && track2 && track2->len >= 8) {
871 struct tlvdb *pan = GetPANFromTrack2(track2);
872 if (pan) {
873 tlvdb_add(tlvRoot, pan);
874
8d7d7b61 875 const struct tlv *pantlv = tlvdb_get(tlvRoot, 0x5a, NULL);
876 PrintAndLogEx(NORMAL, "\n* * Extracted PAN from track2: %s", sprint_hex(pantlv->value, pantlv->len));
66efdc1f 877 } else {
8d7d7b61 878 PrintAndLogEx(NORMAL, "\n* * WARNING: Can't extract PAN from track2.");
66efdc1f 879 }
880 }
881 }
882
8d7d7b61 883 PrintAndLogEx(NORMAL, "\n* Read records from AFL.");
3c5fce2b
OM
884 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
885 if (!AFL || !AFL->len) {
8d7d7b61 886 PrintAndLogEx(WARNING, "AFL not found.");
3c5fce2b
OM
887 }
888
889 while(AFL && AFL->len) {
890 if (AFL->len % 4) {
8d7d7b61 891 PrintAndLogEx(WARNING, "Error: Wrong AFL length: %d", AFL->len);
3c5fce2b
OM
892 break;
893 }
894
895 for (int i = 0; i < AFL->len / 4; i++) {
896 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
897 uint8_t SFIstart = AFL->value[i * 4 + 1];
898 uint8_t SFIend = AFL->value[i * 4 + 2];
899 uint8_t SFIoffline = AFL->value[i * 4 + 3];
900
8d7d7b61 901 PrintAndLogEx(NORMAL, "* * SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
3c5fce2b 902 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
8d7d7b61 903 PrintAndLogEx(NORMAL, "SFI ERROR! Skipped...");
3c5fce2b
OM
904 continue;
905 }
906
907 for(int n = SFIstart; n <= SFIend; n++) {
8d7d7b61 908 PrintAndLogEx(NORMAL, "* * * SFI[%02x] %d", SFI, n);
3c5fce2b 909
8d7d7b61 910 res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
3c5fce2b 911 if (res) {
8d7d7b61 912 PrintAndLogEx(WARNING, "Error SFI[%02x]. APDU error %4x", SFI, sw);
3c5fce2b
OM
913 continue;
914 }
915
916 if (decodeTLV) {
917 TLVPrintFromBuffer(buf, len);
8d7d7b61 918 PrintAndLogEx(NORMAL, "");
3c5fce2b
OM
919 }
920
d03fb293
OM
921 // Build Input list for Offline Data Authentication
922 // EMV 4.3 book3 10.3, page 96
3c5fce2b 923 if (SFIoffline) {
d03fb293
OM
924 if (SFI < 11) {
925 const unsigned char *abuf = buf;
926 size_t elmlen = len;
927 struct tlv e;
928 if (tlv_parse_tl(&abuf, &elmlen, &e)) {
929 memcpy(&ODAiList[ODAiListLen], &buf[len - elmlen], elmlen);
930 ODAiListLen += elmlen;
931 } else {
8d7d7b61 932 PrintAndLogEx(WARNING, "Error SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI);
d03fb293
OM
933 }
934 } else {
935 memcpy(&ODAiList[ODAiListLen], buf, len);
936 ODAiListLen += len;
937 }
3c5fce2b
OM
938 }
939 }
940 }
941
942 break;
8d7d7b61 943 }
3c5fce2b 944
d03fb293
OM
945 // copy Input list for Offline Data Authentication
946 if (ODAiListLen) {
947 struct tlvdb *oda = tlvdb_fixed(0x21, ODAiListLen, ODAiList); // not a standard tag
948 tlvdb_add(tlvRoot, oda);
8d7d7b61 949 PrintAndLogEx(NORMAL, "* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen);
d03fb293
OM
950 }
951
10d4f823 952 // get AIP
8d7d7b61 953 uint16_t AIP = 0;
954 const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL);
955 if (AIPtlv) {
956 AIP = AIPtlv->value[0] + AIPtlv->value[1] * 0x100;
957 PrintAndLogEx(NORMAL, "* * AIP=%04x", AIP);
958 } else {
959 PrintAndLogEx(ERR, "Can't found AIP.");
960 }
66efdc1f 961
10d4f823 962 // SDA
963 if (AIP & 0x0040) {
8d7d7b61 964 PrintAndLogEx(NORMAL, "\n* SDA");
d03fb293 965 trSDA(tlvRoot);
10d4f823 966 }
967
968 // DDA
969 if (AIP & 0x0020) {
8d7d7b61 970 PrintAndLogEx(NORMAL, "\n* DDA");
971 trDDA(channel, decodeTLV, tlvRoot);
972 }
10d4f823 973
974 // transaction check
975
66efdc1f 976 // qVSDC
10d4f823 977 if (TrType == TT_QVSDCMCHIP|| TrType == TT_CDA){
66efdc1f 978 // 9F26: Application Cryptogram
979 const struct tlv *AC = tlvdb_get(tlvRoot, 0x9F26, NULL);
980 if (AC) {
8d7d7b61 981 PrintAndLogEx(NORMAL, "\n--> qVSDC transaction.");
982 PrintAndLogEx(NORMAL, "* AC path");
66efdc1f 983
984 // 9F36: Application Transaction Counter (ATC)
985 const struct tlv *ATC = tlvdb_get(tlvRoot, 0x9F36, NULL);
986 if (ATC) {
987
988 // 9F10: Issuer Application Data - optional
989 const struct tlv *IAD = tlvdb_get(tlvRoot, 0x9F10, NULL);
990
991 // print AC data
8d7d7b61 992 PrintAndLogEx(NORMAL, "ATC: %s", sprint_hex(ATC->value, ATC->len));
993 PrintAndLogEx(NORMAL, "AC: %s", sprint_hex(AC->value, AC->len));
66efdc1f 994 if (IAD){
8d7d7b61 995 PrintAndLogEx(NORMAL, "IAD: %s", sprint_hex(IAD->value, IAD->len));
66efdc1f 996
997 if (IAD->len >= IAD->value[0] + 1) {
8d7d7b61 998 PrintAndLogEx(NORMAL, "\tKey index: 0x%02x", IAD->value[1]);
999 PrintAndLogEx(NORMAL, "\tCrypto ver: 0x%02x(%03d)", IAD->value[2], IAD->value[2]);
1000 PrintAndLogEx(NORMAL, "\tCVR:", sprint_hex(&IAD->value[3], IAD->value[0] - 2));
66efdc1f 1001 struct tlvdb * cvr = tlvdb_fixed(0x20, IAD->value[0] - 2, &IAD->value[3]);
1002 TLVPrintFromTLVLev(cvr, 1);
1003 }
1004 } else {
8d7d7b61 1005 PrintAndLogEx(WARNING, "IAD not found.");
66efdc1f 1006 }
1007
1008 } else {
5a28b510 1009 PrintAndLogEx(ERR, "AC: Application Transaction Counter (ATC) not found.");
66efdc1f 1010 }
1011 }
1012 }
1013
10d4f823 1014 // Mastercard M/CHIP
1015 if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD && (TrType == TT_QVSDCMCHIP || TrType == TT_CDA)){
66efdc1f 1016 const struct tlv *CDOL1 = tlvdb_get(tlvRoot, 0x8c, NULL);
1017 if (CDOL1 && GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) { // and m/chip transaction flag
8d7d7b61 1018 PrintAndLogEx(NORMAL, "\n--> Mastercard M/Chip transaction.");
10d4f823 1019
8d7d7b61 1020 PrintAndLogEx(NORMAL, "* * Generate challenge");
1021 res = EMVGenerateChallenge(channel, true, buf, sizeof(buf), &len, &sw, tlvRoot);
10d4f823 1022 if (res) {
8d7d7b61 1023 PrintAndLogEx(WARNING, "GetChallenge. APDU error %4x", sw);
d03fb293 1024 dreturn(6);
10d4f823 1025 }
1026 if (len < 4) {
8d7d7b61 1027 PrintAndLogEx(WARNING, "GetChallenge. Wrong challenge length %d", len);
d03fb293 1028 dreturn(6);
10d4f823 1029 }
1030
1031 // ICC Dynamic Number
1032 struct tlvdb * ICCDynN = tlvdb_fixed(0x9f4c, len, buf);
1033 tlvdb_add(tlvRoot, ICCDynN);
1034 if (decodeTLV){
8d7d7b61 1035 PrintAndLogEx(NORMAL, "\n* * ICC Dynamic Number:");
10d4f823 1036 TLVPrintFromTLV(ICCDynN);
1037 }
1038
8d7d7b61 1039 PrintAndLogEx(NORMAL, "* * Calc CDOL1");
10d4f823 1040 struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
1041 if (!cdol_data_tlv){
8d7d7b61 1042 PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV.");
d03fb293 1043 dreturn(6);
10d4f823 1044 }
8d7d7b61 1045 PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len));
10d4f823 1046
8d7d7b61 1047 PrintAndLogEx(NORMAL, "* * AC1");
10d4f823 1048 // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
8d7d7b61 1049 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 1050
8d7d7b61 1051 if (res) {
1052 PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw);
d03fb293 1053 dreturn(7);
10d4f823 1054 }
1055
1056 if (decodeTLV)
1057 TLVPrintFromBuffer(buf, len);
1058
d03fb293 1059 // CDA
8d7d7b61 1060 PrintAndLogEx(NORMAL, "\n* CDA:");
d03fb293
OM
1061 struct tlvdb *ac_tlv = tlvdb_parse_multi(buf, len);
1062 res = trCDA(tlvRoot, ac_tlv, pdol_data_tlv, cdol_data_tlv);
8d7d7b61 1063 if (res) {
1064 PrintAndLogEx(NORMAL, "CDA error (%d)", res);
d03fb293
OM
1065 }
1066 free(ac_tlv);
1067 free(cdol_data_tlv);
1068
8d7d7b61 1069 PrintAndLogEx(NORMAL, "\n* M/Chip transaction result:");
10d4f823 1070 // 9F27: Cryptogram Information Data (CID)
1071 const struct tlv *CID = tlvdb_get(tlvRoot, 0x9F27, NULL);
1072 if (CID) {
1073 emv_tag_dump(CID, stdout, 0);
8d7d7b61 1074 PrintAndLogEx(NORMAL, "------------------------------");
10d4f823 1075 if (CID->len > 0) {
1076 switch(CID->value[0] & EMVAC_AC_MASK){
1077 case EMVAC_AAC:
8d7d7b61 1078 PrintAndLogEx(NORMAL, "Transaction DECLINED.");
10d4f823 1079 break;
1080 case EMVAC_TC:
8d7d7b61 1081 PrintAndLogEx(NORMAL, "Transaction approved OFFLINE.");
10d4f823 1082 break;
1083 case EMVAC_ARQC:
8d7d7b61 1084 PrintAndLogEx(NORMAL, "Transaction approved ONLINE.");
10d4f823 1085 break;
1086 default:
8d7d7b61 1087 PrintAndLogEx(WARNING, "Error: CID transaction code error %2x", CID->value[0] & EMVAC_AC_MASK);
10d4f823 1088 break;
1089 }
1090 } else {
8d7d7b61 1091 PrintAndLogEx(WARNING, "Wrong CID length %d", CID->len);
10d4f823 1092 }
1093 } else {
8d7d7b61 1094 PrintAndLogEx(WARNING, "CID(9F27) not found.");
10d4f823 1095 }
66efdc1f 1096
1097 }
1098 }
1099
1100 // MSD
10d4f823 1101 if (AIP & 0x8000 && TrType == TT_MSD) {
8d7d7b61 1102 PrintAndLogEx(NORMAL, "\n--> MSD transaction.");
66efdc1f 1103
8d7d7b61 1104 PrintAndLogEx(NORMAL, "* MSD dCVV path. Check dCVV");
66efdc1f 1105
1106 const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
1107 if (track2) {
8d7d7b61 1108 PrintAndLogEx(NORMAL, "Track2: %s", sprint_hex(track2->value, track2->len));
66efdc1f 1109
1110 struct tlvdb *dCVV = GetdCVVRawFromTrack2(track2);
8d7d7b61 1111 PrintAndLogEx(NORMAL, "dCVV raw data:");
66efdc1f 1112 TLVPrintFromTLV(dCVV);
1113
1114 if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) {
8d7d7b61 1115 PrintAndLogEx(NORMAL, "\n* Mastercard calculate UDOL");
66efdc1f 1116
1117 // UDOL (9F69)
1118 const struct tlv *UDOL = tlvdb_get(tlvRoot, 0x9F69, NULL);
1119 // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
1120 const struct tlv defUDOL = {
1121 .tag = 0x01,
1122 .len = 3,
1123 .value = (uint8_t *)"\x9f\x6a\x04",
1124 };
1125 if (!UDOL)
8d7d7b61 1126 PrintAndLogEx(NORMAL, "Use default UDOL.");
66efdc1f 1127
10d4f823 1128 struct tlv *udol_data_tlv = dol_process(UDOL ? UDOL : &defUDOL, tlvRoot, 0x01); // 0x01 - dummy tag
66efdc1f 1129 if (!udol_data_tlv){
8d7d7b61 1130 PrintAndLogEx(WARNING, "can't create UDOL TLV.");
d03fb293 1131 dreturn(8);
66efdc1f 1132 }
66efdc1f 1133
8d7d7b61 1134 PrintAndLogEx(NORMAL, "UDOL data[%d]: %s", udol_data_tlv->len, sprint_hex(udol_data_tlv->value, udol_data_tlv->len));
66efdc1f 1135
8d7d7b61 1136 PrintAndLogEx(NORMAL, "\n* Mastercard compute cryptographic checksum(UDOL)");
66efdc1f 1137
8d7d7b61 1138 res = MSCComputeCryptoChecksum(channel, true, (uint8_t *)udol_data_tlv->value, udol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
66efdc1f 1139 if (res) {
8d7d7b61 1140 PrintAndLogEx(WARNING, "Compute Crypto Checksum. APDU error %4x", sw);
d03fb293
OM
1141 free(udol_data_tlv);
1142 dreturn(9);
66efdc1f 1143 }
1144
8d7d7b61 1145 // Mastercard compute cryptographic checksum result
1146 TLVPrintFromBuffer(buf, len);
1147 PrintAndLogEx(NORMAL, "");
1148
d03fb293 1149 free(udol_data_tlv);
66efdc1f 1150
1151 }
1152 } else {
8d7d7b61 1153 PrintAndLogEx(WARNING, "MSD: Track2 data not found.");
66efdc1f 1154 }
1155 }
d03fb293 1156
6b5105be 1157 if (channel == ECC_CONTACTLESS) {
1158 DropField();
1159 }
3c5fce2b
OM
1160
1161 // Destroy TLV's
d03fb293 1162 free(pdol_data_tlv);
3c5fce2b
OM
1163 tlvdb_free(tlvSelect);
1164 tlvdb_free(tlvRoot);
1165
8d7d7b61 1166 PrintAndLogEx(NORMAL, "\n* Transaction completed.");
3c5fce2b
OM
1167 return 0;
1168}
1169
8d7d7b61 1170int CmdEMVScan(const char *cmd) {
6b5105be 1171 uint8_t AID[APDU_DATA_LEN] = {0};
95b697f0 1172 size_t AIDlen = 0;
6b5105be 1173 uint8_t buf[APDU_RESPONSE_LEN] = {0};
95b697f0
OM
1174 size_t len = 0;
1175 uint16_t sw = 0;
1176 int res;
1177 json_t *root;
1178 json_error_t error;
1179
8d7d7b61 1180 CLIParserInit("emv scan",
95b697f0
OM
1181 "Scan EMV card and save it contents to a file.",
1182 "It executes EMV contactless transaction and saves result to a file which can be used for emulation\n"
8d7d7b61 1183 "Usage:\n\temv scan -at -> scan MSD transaction mode and show APDU and TLV\n"
1184 "\temv scan -c -> scan CDA transaction mode\n");
95b697f0
OM
1185
1186 void* argtable[] = {
1187 arg_param_begin,
1188 arg_lit0("aA", "apdu", "show APDU reqests and responses."),
1189 arg_lit0("tT", "tlv", "TLV decode results."),
1190 arg_lit0("eE", "extract", "Extract TLV elements and fill Application Data"),
1191 arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."),
1192 arg_rem("By default:", "Transaction type - MSD"),
1193 arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."),
1194 arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."),
1195 arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."),
1196 arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
1197 arg_lit0("mM", "merge", "Merge output file with card's data. (warning: the file may be corrupted!)"),
8d7d7b61 1198#ifdef WITH_SMARTCARD
1199 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
1200#endif
1201 arg_str1(NULL, NULL, "output.json", "JSON output file name"),
95b697f0
OM
1202 arg_param_end
1203 };
1204 CLIExecWithReturn(cmd, argtable, true);
1205
1206 bool showAPDU = arg_get_lit(1);
1207 bool decodeTLV = arg_get_lit(2);
1208 bool extractTLVElements = arg_get_lit(3);
1209 bool paramLoadJSON = arg_get_lit(4);
1210
1211 enum TransactionType TrType = TT_MSD;
1212 if (arg_get_lit(6))
1213 TrType = TT_QVSDCMCHIP;
1214 if (arg_get_lit(7))
1215 TrType = TT_CDA;
1216 if (arg_get_lit(8))
1217 TrType = TT_VSDC;
1218
1219 bool GenACGPO = arg_get_lit(9);
1220 bool MergeJSON = arg_get_lit(10);
8d7d7b61 1221 EMVCommandChannel channel = ECC_CONTACTLESS;
1222 uint8_t relfname[250] = {0};
95b697f0
OM
1223 char *crelfname = (char *)relfname;
1224 int relfnamelen = 0;
8d7d7b61 1225#ifdef WITH_SMARTCARD
1511ea28 1226 if (arg_get_lit(11)) {
8d7d7b61 1227 channel = ECC_CONTACT;
1511ea28 1228 }
8d7d7b61 1229 CLIGetStrWithReturn(12, relfname, &relfnamelen);
1230#else
95b697f0 1231 CLIGetStrWithReturn(11, relfname, &relfnamelen);
8d7d7b61 1232#endif
1511ea28 1233 uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
95b697f0
OM
1234 CLIParserFree();
1235
1236 SetAPDULogging(showAPDU);
1237
8d7d7b61 1238 // TODO
1239 if (channel == ECC_CONTACT) {
1240 PrintAndLogEx(ERR, "Do not use contact interface. Exit.");
1241 return 1;
1242 }
1243
95b697f0
OM
1244 // current path + file name
1245 if (!strstr(crelfname, ".json"))
1246 strcat(crelfname, ".json");
1247 char fname[strlen(get_my_executable_directory()) + strlen(crelfname) + 1];
1248 strcpy(fname, get_my_executable_directory());
1249 strcat(fname, crelfname);
1250
1251 if (MergeJSON) {
1252 root = json_load_file(fname, 0, &error);
1253 if (!root) {
5a28b510 1254 PrintAndLogEx(ERR, "json error on line %d: %s", error.line, error.text);
95b697f0
OM
1255 return 1;
1256 }
1257
1258 if (!json_is_object(root)) {
5a28b510 1259 PrintAndLogEx(ERR, "Invalid json format. root must be an object.");
95b697f0
OM
1260 return 1;
1261 }
1262 } else {
1263 root = json_object();
1264 }
1265
1266 // drop field at start
6b5105be 1267 if (channel == ECC_CONTACTLESS) {
1268 DropField();
1269 }
1270
95b697f0 1271 // iso 14443 select
8d7d7b61 1272 PrintAndLogEx(NORMAL, "--> GET UID, ATS.");
95b697f0
OM
1273
1274 iso14a_card_select_t card;
1275 if (Hf14443_4aGetCardData(&card)) {
1276 return 2;
1277 }
1278
8d7d7b61 1279 JsonSaveStr(root, "$.File.Created", "proxmark3 `emv scan`");
95b697f0
OM
1280
1281 JsonSaveStr(root, "$.Card.Communication", "iso14443-4a");
1282 JsonSaveBufAsHex(root, "$.Card.UID", (uint8_t *)&card.uid, card.uidlen);
1283 JsonSaveHex(root, "$.Card.ATQA", card.atqa[0] + (card.atqa[1] << 2), 2);
1284 JsonSaveHex(root, "$.Card.SAK", card.sak, 0);
1285 JsonSaveBufAsHex(root, "$.Card.ATS", (uint8_t *)card.ats, card.ats_len);
1286
1287 // init applets list tree
1288 const char *al = "Applets list";
1289 struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
1290
1291 // EMV PPSE
8d7d7b61 1292 PrintAndLogEx(NORMAL, "--> PPSE.");
1293 res = EMVSelectPSE(channel, true, true, 2, buf, sizeof(buf), &len, &sw);
95b697f0
OM
1294
1295 if (!res && sw == 0x9000){
1296 if (decodeTLV)
1297 TLVPrintFromBuffer(buf, len);
1298
1299 JsonSaveBufAsHex(root, "$.PPSE.AID", (uint8_t *)"2PAY.SYS.DDF01", 14);
1300
1301 struct tlvdb *fci = tlvdb_parse_multi(buf, len);
1302 if (extractTLVElements)
1303 JsonSaveTLVTree(root, root, "$.PPSE.FCITemplate", fci);
1304 else
1305 JsonSaveTLVTreeElm(root, "$.PPSE.FCITemplate", fci, true, true, false);
1306 JsonSaveTLVValue(root, "$.Application.KernelID", tlvdb_find_full(fci, 0x9f2a));
1307 tlvdb_free(fci);
1308 }
1309
1511ea28 1310 res = EMVSearchPSE(channel, false, true, psenum, decodeTLV, tlvSelect);
95b697f0
OM
1311
1312 // check PPSE and select application id
8d7d7b61 1313 if (!res) {
1314 TLVPrintAIDlistFromSelectTLV(tlvSelect);
95b697f0
OM
1315 } else {
1316 // EMV SEARCH with AID list
1317 SetAPDULogging(false);
8d7d7b61 1318 PrintAndLogEx(NORMAL, "--> AID search.");
1319 if (EMVSearch(channel, false, true, decodeTLV, tlvSelect)) {
5a28b510 1320 PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit...");
95b697f0
OM
1321 tlvdb_free(tlvSelect);
1322 DropField();
1323 return 3;
1324 }
1325
1326 // check search and select application id
1327 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1328 }
1329
1330 // EMV SELECT application
1331 SetAPDULogging(showAPDU);
1332 EMVSelectApplication(tlvSelect, AID, &AIDlen);
1333
1334 tlvdb_free(tlvSelect);
1335
1336 if (!AIDlen) {
8d7d7b61 1337 PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit...");
6b5105be 1338 if (channel == ECC_CONTACTLESS) {
1339 DropField();
1340 }
95b697f0
OM
1341 return 4;
1342 }
1343
1344 JsonSaveBufAsHex(root, "$.Application.AID", AID, AIDlen);
1345
1346 // Init TLV tree
1347 const char *alr = "Root terminal TLV tree";
1348 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
1349
1350 // EMV SELECT applet
1351
8d7d7b61 1352 PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen));
95b697f0 1353 SetAPDULogging(showAPDU);
8d7d7b61 1354 res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
95b697f0 1355
8d7d7b61 1356 if (res) {
5a28b510 1357 PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res);
95b697f0
OM
1358 tlvdb_free(tlvRoot);
1359 DropField();
1360 return 5;
1361 }
1362
1363 if (decodeTLV)
1364 TLVPrintFromBuffer(buf, len);
1365
1366 // save mode
1367 if (tlvdb_get(tlvRoot, 0x9f38, NULL)) {
1368 JsonSaveStr(root, "$.Application.Mode", TransactionTypeStr[TrType]);
1369 }
1370
1371 struct tlvdb *fci = tlvdb_parse_multi(buf, len);
1372 if (extractTLVElements)
1373 JsonSaveTLVTree(root, root, "$.Application.FCITemplate", fci);
1374 else
1375 JsonSaveTLVTreeElm(root, "$.Application.FCITemplate", fci, true, true, false);
1376 tlvdb_free(fci);
1377
1378 // create transaction parameters
8d7d7b61 1379 PrintAndLogEx(NORMAL, "-->Init transaction parameters.");
95b697f0
OM
1380 InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO);
1381
8d7d7b61 1382 PrintAndLogEx(NORMAL, "-->Calc PDOL.");
95b697f0
OM
1383 struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
1384 if (!pdol_data_tlv){
5a28b510 1385 PrintAndLogEx(ERR, "Can't create PDOL TLV.");
95b697f0 1386 tlvdb_free(tlvRoot);
6b5105be 1387 if (channel == ECC_CONTACTLESS) {
1388 DropField();
1389 }
95b697f0
OM
1390 return 6;
1391 }
1392
1393 size_t pdol_data_tlv_data_len;
1394 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
1395 if (!pdol_data_tlv_data) {
5a28b510 1396 PrintAndLogEx(ERR, "Can't create PDOL data.");
95b697f0
OM
1397 tlvdb_free(tlvRoot);
1398 DropField();
1399 return 6;
1400 }
8d7d7b61 1401 PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
95b697f0 1402
8d7d7b61 1403 PrintAndLogEx(INFO, "-->GPO.");
1404 res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
95b697f0
OM
1405
1406 free(pdol_data_tlv_data);
1407 free(pdol_data_tlv);
1408
8d7d7b61 1409 if (res) {
5a28b510 1410 PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw);
95b697f0 1411 tlvdb_free(tlvRoot);
6b5105be 1412 if (channel == ECC_CONTACTLESS) {
1413 DropField();
1414 }
95b697f0
OM
1415 return 7;
1416 }
1417 ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV);
1418
1419 struct tlvdb *gpofci = tlvdb_parse_multi(buf, len);
1420 if (extractTLVElements)
1421 JsonSaveTLVTree(root, root, "$.Application.GPO", gpofci);
1422 else
1423 JsonSaveTLVTreeElm(root, "$.Application.GPO", gpofci, true, true, false);
1424
1425 JsonSaveTLVValue(root, "$.ApplicationData.AIP", tlvdb_find_full(gpofci, 0x82));
1426 JsonSaveTLVValue(root, "$.ApplicationData.AFL", tlvdb_find_full(gpofci, 0x94));
1427
1428 tlvdb_free(gpofci);
1429
8d7d7b61 1430 PrintAndLogEx(INFO, "-->Read records from AFL.");
95b697f0
OM
1431 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
1432
1433 while(AFL && AFL->len) {
1434 if (AFL->len % 4) {
5a28b510 1435 PrintAndLogEx(ERR, "Wrong AFL length: %d", AFL->len);
95b697f0
OM
1436 break;
1437 }
1438
1439 json_t *sfijson = json_path_get(root, "$.Application.Records");
1440 if (!sfijson) {
1441 json_t *app = json_path_get(root, "$.Application");
1442 json_object_set_new(app, "Records", json_array());
1443
1444 sfijson = json_path_get(root, "$.Application.Records");
1445 }
1446 if (!json_is_array(sfijson)) {
5a28b510 1447 PrintAndLogEx(ERR, "Internal logic error. `$.Application.Records` is not an array.");
95b697f0
OM
1448 break;
1449 }
1450 for (int i = 0; i < AFL->len / 4; i++) {
1451 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
1452 uint8_t SFIstart = AFL->value[i * 4 + 1];
1453 uint8_t SFIend = AFL->value[i * 4 + 2];
1454 uint8_t SFIoffline = AFL->value[i * 4 + 3];
1455
8d7d7b61 1456 PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
95b697f0 1457 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
5a28b510 1458 PrintAndLogEx(ERR, "SFI ERROR! Skipped...");
95b697f0
OM
1459 continue;
1460 }
1461
1462 for(int n = SFIstart; n <= SFIend; n++) {
8d7d7b61 1463 PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n);
95b697f0 1464
8d7d7b61 1465 res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
95b697f0 1466 if (res) {
5a28b510 1467 PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw);
95b697f0
OM
1468 continue;
1469 }
1470
1471 if (decodeTLV) {
1472 TLVPrintFromBuffer(buf, len);
8d7d7b61 1473 PrintAndLogEx(NORMAL, "");
95b697f0
OM
1474 }
1475
1476 json_t *jsonelm = json_object();
1477 json_array_append_new(sfijson, jsonelm);
1478
1479 JsonSaveHex(jsonelm, "SFI", SFI, 1);
1480 JsonSaveHex(jsonelm, "RecordNum", n, 1);
1481 JsonSaveHex(jsonelm, "Offline", SFIoffline, 1);
1482
1483 struct tlvdb *rsfi = tlvdb_parse_multi(buf, len);
1484 if (extractTLVElements)
1485 JsonSaveTLVTree(root, jsonelm, "$.Data", rsfi);
1486 else
1487 JsonSaveTLVTreeElm(jsonelm, "$.Data", rsfi, true, true, false);
1488 tlvdb_free(rsfi);
1489 }
1490 }
1491
1492 break;
1493 }
1494
1495 // getting certificates
1496 if (tlvdb_get(tlvRoot, 0x90, NULL)) {
8d7d7b61 1497 PrintAndLogEx(INFO, "-->Recovering certificates.");
95b697f0
OM
1498 PKISetStrictExecution(false);
1499 RecoveryCertificates(tlvRoot, root);
1500 PKISetStrictExecution(true);
1501 }
1502
1503 // free tlv object
1504 tlvdb_free(tlvRoot);
1505
6b5105be 1506 if (channel == ECC_CONTACTLESS) {
1507 DropField();
1508 }
95b697f0
OM
1509
1510 res = json_dump_file(root, fname, JSON_INDENT(2));
1511 if (res) {
5a28b510 1512 PrintAndLogEx(ERR, "Can't save the file: %s", fname);
95b697f0
OM
1513 return 200;
1514 }
8d7d7b61 1515 PrintAndLogEx(SUCCESS, "File `%s` saved.", fname);
95b697f0
OM
1516
1517 // free json object
1518 json_decref(root);
556826b5
OM
1519
1520 return 0;
1521}
1522
8d7d7b61 1523int CmdEMVTest(const char *cmd) {
d03fb293
OM
1524 return ExecuteCryptoTests(true);
1525}
1526
1511ea28 1527int CmdEMVRoca(const char *cmd) {
6b5105be 1528 uint8_t AID[APDU_DATA_LEN] = {0};
1511ea28 1529 size_t AIDlen = 0;
6b5105be 1530 uint8_t buf[APDU_RESPONSE_LEN] = {0};
1511ea28 1531 size_t len = 0;
1532 uint16_t sw = 0;
1533 int res;
1534
1535 CLIParserInit("emv roca",
1536 "Tries to extract public keys and run the ROCA test against them.\n",
1537 "Usage:\n"
1538 "\temv roca -w -> select CONTACT card and run test\n\temv roca -> select CONTACTLESS card and run test\n");
1539
1540 void* argtable[] = {
1541 arg_param_begin,
1542 arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
1543 arg_param_end
1544 };
1545 CLIExecWithReturn(cmd, argtable, true);
1546
1547 EMVCommandChannel channel = ECC_CONTACTLESS;
1548 if (arg_get_lit(1))
1549 channel = ECC_CONTACT;
1550
1551 // select card
1552 uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
1553
1554 SetAPDULogging(false);
1555
1556 // init applets list tree
1557 const char *al = "Applets list";
1558 struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
1559
1560 // EMV PPSE
1561 PrintAndLogEx(NORMAL, "--> PPSE.");
1562 res = EMVSearchPSE(channel, false, true, psenum, false, tlvSelect);
1563
1564 // check PPSE and select application id
1565 if (!res) {
1566 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1567 } else {
1568 // EMV SEARCH with AID list
1569 PrintAndLogEx(NORMAL, "--> AID search.");
1570 if (EMVSearch(channel, false, true, false, tlvSelect)) {
1571 PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit...");
1572 tlvdb_free(tlvSelect);
1573 DropField();
1574 return 3;
1575 }
1576
1577 // check search and select application id
1578 TLVPrintAIDlistFromSelectTLV(tlvSelect);
1579 }
1580
1581 // EMV SELECT application
1582 SetAPDULogging(false);
1583 EMVSelectApplication(tlvSelect, AID, &AIDlen);
1584
1585 tlvdb_free(tlvSelect);
1586
1587 if (!AIDlen) {
1588 PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit...");
6b5105be 1589 if (channel == ECC_CONTACTLESS) {
1590 DropField();
1591 }
1511ea28 1592 return 4;
1593 }
1594
1595 // Init TLV tree
1596 const char *alr = "Root terminal TLV tree";
1597 struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
1598
1599 // EMV SELECT applet
1600 PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen));
1601 res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
1602
1603 if (res) {
1604 PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res);
1605 tlvdb_free(tlvRoot);
6b5105be 1606 if (channel == ECC_CONTACTLESS) {
1607 DropField();
1608 }
1511ea28 1609 return 5;
1610 }
1611
1612 PrintAndLog("\n* Init transaction parameters.");
1613 InitTransactionParameters(tlvRoot, true, TT_QVSDCMCHIP, false);
1614
1615 PrintAndLogEx(NORMAL, "-->Calc PDOL.");
1616 struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
1617 if (!pdol_data_tlv){
1618 PrintAndLogEx(ERR, "Can't create PDOL TLV.");
1619 tlvdb_free(tlvRoot);
6b5105be 1620 if (channel == ECC_CONTACTLESS) {
1621 DropField();
1622 }
1511ea28 1623 return 6;
1624 }
1625
1626 size_t pdol_data_tlv_data_len;
1627 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
1628 if (!pdol_data_tlv_data) {
1629 PrintAndLogEx(ERR, "Can't create PDOL data.");
1630 tlvdb_free(tlvRoot);
1631 DropField();
1632 return 6;
1633 }
1634 PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
1635
1636 PrintAndLogEx(INFO, "-->GPO.");
1637 res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
1638
1639 free(pdol_data_tlv_data);
1640 free(pdol_data_tlv);
1641
1642 if (res) {
1643 PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw);
1644 tlvdb_free(tlvRoot);
6b5105be 1645 if (channel == ECC_CONTACTLESS) {
1646 DropField();
1647 }
1511ea28 1648 return 7;
1649 }
1650 ProcessGPOResponseFormat1(tlvRoot, buf, len, false);
1651
1652 PrintAndLogEx(INFO, "-->Read records from AFL.");
1653 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
1654
1655 while(AFL && AFL->len) {
1656 if (AFL->len % 4) {
1657 PrintAndLogEx(ERR, "Wrong AFL length: %d", AFL->len);
1658 break;
1659 }
1660
1661 for (int i = 0; i < AFL->len / 4; i++) {
1662 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
1663 uint8_t SFIstart = AFL->value[i * 4 + 1];
1664 uint8_t SFIend = AFL->value[i * 4 + 2];
1665 uint8_t SFIoffline = AFL->value[i * 4 + 3];
1666
1667 PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
1668 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
1669 PrintAndLogEx(ERR, "SFI ERROR! Skipped...");
1670 continue;
1671 }
1672
1673 for(int n = SFIstart; n <= SFIend; n++) {
1674 PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n);
1675
1676 res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
1677 if (res) {
1678 PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw);
1679 continue;
1680 }
1681 }
1682 }
1683
1684 break;
1685 }
1686
1687 // getting certificates
1688 if (tlvdb_get(tlvRoot, 0x90, NULL)) {
1689 PrintAndLogEx(INFO, "-->Recovering certificates.");
1690 PKISetStrictExecution(false);
1691
1692 struct emv_pk *pk = get_ca_pk(tlvRoot);
1693 if (!pk) {
1694 PrintAndLogEx(ERR, "ERROR: Key not found. Exit.");
1695 goto out;
1696 }
1697
1698 struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlvRoot);
1699 if (!issuer_pk) {
1700 emv_pk_free(pk);
1701 PrintAndLogEx(WARNING, "WARNING: Issuer certificate not found. Exit.");
1702 goto out;
1703 }
1704
1705 PrintAndLogEx(SUCCESS, "Issuer PK recovered. RID %s IDX %02hhx CSN %s",
1706 sprint_hex(issuer_pk->rid, 5),
1707 issuer_pk->index,
1708 sprint_hex(issuer_pk->serial, 3)
1709 );
1710
1711
1712 struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlvRoot, NULL);
1713 if (!icc_pk) {
1714 emv_pk_free(pk);
1715 emv_pk_free(issuer_pk);
1716 PrintAndLogEx(WARNING, "WARNING: ICC certificate not found. Exit.");
1717 goto out;
1718 }
1719 PrintAndLogEx(SUCCESS, "ICC PK recovered. RID %s IDX %02hhx CSN %s\n",
1720 sprint_hex(icc_pk->rid, 5),
1721 icc_pk->index,
1722 sprint_hex(icc_pk->serial, 3)
1723 );
1724
1725 PrintAndLogEx(INFO, "ICC pk modulus: %s", sprint_hex_inrow(icc_pk->modulus, icc_pk->mlen));
1726
1727 // icc_pk->exp, icc_pk->elen
1728 // icc_pk->modulus, icc_pk->mlen
1729 if (icc_pk->elen > 0 && icc_pk->mlen > 0) {
1730 if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen, true)) {
1731 PrintAndLogEx(INFO, "ICC pk is a subject to ROCA vulnerability, insecure..");
1732 } else {
1733 PrintAndLogEx(INFO, "ICC pk is OK(");
1734 }
1735 }
1736
1737 PKISetStrictExecution(true);
1738 }
1739
1740out:
1741
1742 // free tlv object
1743 tlvdb_free(tlvRoot);
1744
6b5105be 1745 if (channel == ECC_CONTACTLESS) {
1511ea28 1746 DropField();
6b5105be 1747 }
1511ea28 1748
1749 return 0;
1750}
1751
3c5fce2b 1752int CmdHelp(const char *Cmd);
1511ea28 1753
3c5fce2b 1754static command_t CommandTable[] = {
8d7d7b61 1755 {"help", CmdHelp, 1, "This help"},
6b5105be 1756 {"exec", CmdEMVExec, 1, "Executes EMV contactless transaction."},
1757 {"pse", CmdEMVPPSE, 1, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."},
1758 {"search", CmdEMVSearch, 1, "Try to select all applets from applets list and print installed applets."},
1759 {"select", CmdEMVSelect, 1, "Select applet."},
1760 {"gpo", CmdEMVGPO, 1, "Execute GetProcessingOptions."},
1761 {"readrec", CmdEMVReadRecord, 1, "Read files from card."},
1762 {"genac", CmdEMVAC, 1, "Generate ApplicationCryptogram."},
1763 {"challenge", CmdEMVGenerateChallenge, 1, "Generate challenge."},
1764 {"intauth", CmdEMVInternalAuthenticate, 1, "Internal authentication."},
1765 {"scan", CmdEMVScan, 1, "Scan EMV card and save it contents to json file for emulator."},
1766 {"test", CmdEMVTest, 1, "Crypto logic test."},
1767 {"roca", CmdEMVRoca, 1, "Extract public keys and run ROCA test"},
8d7d7b61 1768 {NULL, NULL, 0, NULL}
3c5fce2b
OM
1769};
1770
8d7d7b61 1771int CmdEMV(const char *Cmd) {
3c5fce2b
OM
1772 CmdsParse(CommandTable, Cmd);
1773 return 0;
1774}
1775
1776int CmdHelp(const char *Cmd) {
1777 CmdsHelp(CommandTable);
1778 return 0;
1779}
Impressum, Datenschutz