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