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