]> git.zerfleddert.de Git - proxmark3-svn/blame - client/emv/cmdemv.c
move `hf emv search` to argtable
[proxmark3-svn] / client / emv / cmdemv.c
CommitLineData
3c5fce2b
OM
1//-----------------------------------------------------------------------------
2// Copyright (C) 2017 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
3ded0f97 11#include <ctype.h>
3c5fce2b 12#include "cmdemv.h"
d03fb293 13#include "test/cryptotest.h"
6d31653c 14#include "cliparser/cliparser.h"
3c5fce2b
OM
15
16int UsageCmdHFEMVSelect(void) {
17 PrintAndLog("HELP : Executes select applet command:\n");
18 PrintAndLog("Usage: hf emv select [-s][-k][-a][-t] <HEX applet AID>\n");
19 PrintAndLog(" Options:");
20 PrintAndLog(" -s : select card");
21 PrintAndLog(" -k : keep field for next command");
22 PrintAndLog(" -a : show APDU reqests and responses\n");
23 PrintAndLog(" -t : TLV decode results\n");
24 PrintAndLog("Samples:");
25 PrintAndLog(" hf emv select -s a00000000101 -> select card, select applet");
26 PrintAndLog(" hf emv select -s -t a00000000101 -> select card, select applet, show result in TLV");
27 return 0;
28}
29
30int CmdHFEMVSelect(const char *cmd) {
31 uint8_t data[APDU_AID_LEN] = {0};
32 int datalen = 0;
33 bool activateField = false;
34 bool leaveSignalON = false;
35 bool decodeTLV = false;
36
37 if (strlen(cmd) < 1) {
38 UsageCmdHFEMVSelect();
39 return 0;
40 }
41
42 SetAPDULogging(false);
43
44 int cmdp = 0;
45 while(param_getchar(cmd, cmdp) != 0x00) {
46 char c = param_getchar(cmd, cmdp);
47 if ((c == '-') && (param_getlength(cmd, cmdp) == 2))
48 switch (param_getchar_indx(cmd, 1, cmdp)) {
49 case 'h':
50 case 'H':
51 UsageCmdHFEMVSelect();
52 return 0;
53 case 's':
54 case 'S':
55 activateField = true;
56 break;
57 case 'k':
58 case 'K':
59 leaveSignalON = true;
60 break;
61 case 'a':
62 case 'A':
63 SetAPDULogging(true);
64 break;
65 case 't':
66 case 'T':
67 decodeTLV = true;
68 break;
69 default:
70 PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd, 1, cmdp));
71 return 1;
72 }
73
3ded0f97 74 if (isxdigit((unsigned char)c)) {
3c5fce2b
OM
75 switch(param_gethex_to_eol(cmd, cmdp, data, sizeof(data), &datalen)) {
76 case 1:
77 PrintAndLog("Invalid HEX value.");
78 return 1;
79 case 2:
80 PrintAndLog("AID too large.");
81 return 1;
82 case 3:
83 PrintAndLog("Hex must have even number of digits.");
84 return 1;
85 }
86
87 // we get all the hex to end of line with spaces
88 break;
89 }
90
91
92 cmdp++;
93 }
94
95 // exec
96 uint8_t buf[APDU_RES_LEN] = {0};
97 size_t len = 0;
98 uint16_t sw = 0;
99 int res = EMVSelect(activateField, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL);
100
101 if (sw)
102 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
103
104 if (res)
105 return res;
106
107 if (decodeTLV)
108 TLVPrintFromBuffer(buf, len);
109
110 return 0;
111}
112
113int UsageCmdHFEMVSearch(void) {
114 PrintAndLog("HELP : Tries to select all applets from applet list:\n");
115 PrintAndLog("Usage: hf emv search [-s][-k][-a][-t]\n");
116 PrintAndLog(" Options:");
117 PrintAndLog(" -s : select card");
118 PrintAndLog(" -k : keep field for next command");
119 PrintAndLog(" -a : show APDU reqests and responses\n");
120 PrintAndLog(" -t : TLV decode results of selected applets\n");
121 PrintAndLog("Samples:");
122 PrintAndLog(" hf emv search -s -> select card and search");
123 PrintAndLog(" hf emv search -s -t -> select card, search and show result in TLV");
124 return 0;
125}
126
127int CmdHFEMVSearch(const char *cmd) {
128
6d31653c 129 CLIParserInit("hf 14a select",
130 "Tries to select all applets from applet list:\n",
131 "Usage:\n\thf emv search -s -> select card and search\n\thf emv search -s -t -> select card, search and show result in TLV\n");
132
133 void* argtable[] = {
134 arg_param_begin,
135 arg_lit0("sS", "select", "activate field and select card"),
136 arg_lit0("kK", "keep", "keep field ON for next command"),
137 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
138 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
139 arg_param_end
140 };
141 CLIExecWithReturn(cmd, argtable, true);
3c5fce2b 142
6d31653c 143 bool activateField = arg_get_lit(1);
144 bool leaveSignalON = arg_get_lit(2);
145 bool APDULogging = arg_get_lit(3);
146 bool decodeTLV = arg_get_lit(4);
147
148 SetAPDULogging(APDULogging);
3c5fce2b 149
3c5fce2b
OM
150 struct tlvdb *t = NULL;
151 const char *al = "Applets list";
152 t = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
153
154 if (EMVSearch(activateField, leaveSignalON, decodeTLV, t)) {
155 tlvdb_free(t);
156 return 2;
157 }
158
159 PrintAndLog("Search completed.");
160
161 // print list here
162 if (!decodeTLV) {
163 TLVPrintAIDlistFromSelectTLV(t);
164 }
165
166 tlvdb_free(t);
167
168 return 0;
169}
170
171int UsageCmdHFEMVPPSE(void) {
172 PrintAndLog("HELP : Executes PSE/PPSE select command. It returns list of applet on the card:\n");
173 PrintAndLog("Usage: hf emv pse [-s][-k][-1][-2][-a][-t]\n");
174 PrintAndLog(" Options:");
175 PrintAndLog(" -s : select card");
176 PrintAndLog(" -k : keep field for next command");
177 PrintAndLog(" -1 : ppse (1PAY.SYS.DDF01)");
178 PrintAndLog(" -2 : pse (2PAY.SYS.DDF01)");
179 PrintAndLog(" -a : show APDU reqests and responses\n");
180 PrintAndLog(" -t : TLV decode results\n");
181 PrintAndLog("Samples:");
182 PrintAndLog(" hf emv pse -s -1 -> select, get pse");
183 PrintAndLog(" hf emv pse -s -k -2 -> select, get ppse, keep field");
184 PrintAndLog(" hf emv pse -s -t -2 -> select, get ppse, show result in TLV");
185 return 0;
186}
187
188int CmdHFEMVPPSE(const char *cmd) {
189
190 uint8_t PSENum = 2;
191 bool activateField = false;
192 bool leaveSignalON = false;
193 bool decodeTLV = false;
194
195 if (strlen(cmd) < 1) {
196 UsageCmdHFEMVPPSE();
197 return 0;
198 }
199
200 SetAPDULogging(false);
201
202 int cmdp = 0;
203 while(param_getchar(cmd, cmdp) != 0x00) {
204 char c = param_getchar(cmd, cmdp);
205 if ((c == '-') && (param_getlength(cmd, cmdp) == 2))
206 switch (param_getchar_indx(cmd, 1, cmdp)) {
207 case 'h':
208 case 'H':
209 UsageCmdHFEMVPPSE();
210 return 0;
211 case 's':
212 case 'S':
213 activateField = true;
214 break;
215 case 'k':
216 case 'K':
217 leaveSignalON = true;
218 break;
219 case 'a':
220 case 'A':
221 SetAPDULogging(true);
222 break;
223 case 't':
224 case 'T':
225 decodeTLV = true;
226 break;
227 case '1':
228 PSENum = 1;
229 break;
230 case '2':
231 PSENum = 2;
232 break;
233 default:
234 PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd, 1, cmdp));
235 return 1;
236 }
237 cmdp++;
238 }
239
240 // exec
241 uint8_t buf[APDU_RES_LEN] = {0};
242 size_t len = 0;
243 uint16_t sw = 0;
244 int res = EMVSelectPSE(activateField, leaveSignalON, PSENum, buf, sizeof(buf), &len, &sw);
245
246 if (sw)
247 PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
248
249 if (res)
250 return res;
251
252
253 if (decodeTLV)
254 TLVPrintFromBuffer(buf, len);
255
256 return 0;
257}
258
259int UsageCmdHFEMVExec(void) {
260 PrintAndLog("HELP : Executes EMV contactless transaction:\n");
d03fb293 261 PrintAndLog("Usage: hf emv exec [-s][-a][-t][-f][-v][-c][-x][-g]\n");
3c5fce2b
OM
262 PrintAndLog(" Options:");
263 PrintAndLog(" -s : select card");
264 PrintAndLog(" -a : show APDU reqests and responses\n");
265 PrintAndLog(" -t : TLV decode results\n");
266 PrintAndLog(" -f : force search AID. Search AID instead of execute PPSE.\n");
10d4f823 267 PrintAndLog(" -v : transaction type - qVSDC or M/Chip.\n");
268 PrintAndLog(" -c : transaction type - qVSDC or M/Chip plus CDA (SDAD generation).\n");
269 PrintAndLog(" -x : transaction type - VSDC. For test only. Not a standart behavior.\n");
d03fb293 270 PrintAndLog(" -g : VISA. generate AC from GPO\n");
10d4f823 271 PrintAndLog("By default : transaction type - MSD.\n");
3c5fce2b 272 PrintAndLog("Samples:");
d03fb293
OM
273 PrintAndLog(" hf emv exec -s -a -t -> execute MSD transaction");
274 PrintAndLog(" hf emv exec -s -a -t -c -> execute CDA transaction");
3c5fce2b
OM
275 return 0;
276}
277
278#define TLV_ADD(tag, value)( tlvdb_add(tlvRoot, tlvdb_fixed(tag, sizeof(value) - 1, (const unsigned char *)value)) )
d03fb293 279#define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;}
3c5fce2b
OM
280
281int CmdHFEMVExec(const char *cmd) {
282 bool activateField = false;
283 bool showAPDU = false;
284 bool decodeTLV = false;
285 bool forceSearch = false;
10d4f823 286 enum TransactionType TrType = TT_MSD;
d03fb293 287 bool GenACGPO = false;
3c5fce2b
OM
288
289 uint8_t buf[APDU_RES_LEN] = {0};
290 size_t len = 0;
291 uint16_t sw = 0;
292 uint8_t AID[APDU_AID_LEN] = {0};
293 size_t AIDlen = 0;
d03fb293
OM
294 uint8_t ODAiList[4096];
295 size_t ODAiListLen = 0;
3c5fce2b
OM
296
297 int res;
298
d03fb293
OM
299 struct tlvdb *tlvSelect = NULL;
300 struct tlvdb *tlvRoot = NULL;
301 struct tlv *pdol_data_tlv = NULL;
302
3c5fce2b
OM
303 if (strlen(cmd) < 1) {
304 UsageCmdHFEMVExec();
305 return 0;
306 }
307
308 int cmdp = 0;
309 while(param_getchar(cmd, cmdp) != 0x00) {
310 char c = param_getchar(cmd, cmdp);
311 if ((c == '-') && (param_getlength(cmd, cmdp) == 2))
312 switch (param_getchar_indx(cmd, 1, cmdp)) {
313 case 'h':
314 case 'H':
7a7afeba 315 UsageCmdHFEMVExec();
3c5fce2b
OM
316 return 0;
317 case 's':
318 case 'S':
319 activateField = true;
320 break;
321 case 'a':
322 case 'A':
323 showAPDU = true;
324 break;
325 case 't':
326 case 'T':
327 decodeTLV = true;
328 break;
329 case 'f':
330 case 'F':
331 forceSearch = true;
332 break;
10d4f823 333 case 'x':
334 case 'X':
335 TrType = TT_VSDC;
336 break;
337 case 'v':
338 case 'V':
339 TrType = TT_QVSDCMCHIP;
340 break;
341 case 'c':
342 case 'C':
343 TrType = TT_CDA;
344 break;
d03fb293
OM
345 case 'g':
346 case 'G':
347 GenACGPO = true;
348 break;
3c5fce2b
OM
349 default:
350 PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd, 1, cmdp));
351 return 1;
352 }
353 cmdp++;
354 }
355
356
357 // init applets list tree
3c5fce2b
OM
358 const char *al = "Applets list";
359 tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
360
361 // Application Selection
362 // https://www.openscdp.org/scripts/tutorial/emv/applicationselection.html
363 if (!forceSearch) {
364 // PPSE
365 PrintAndLog("\n* PPSE.");
366 SetAPDULogging(showAPDU);
367 res = EMVSearchPSE(activateField, true, decodeTLV, tlvSelect);
368
369 // check PPSE and select application id
370 if (!res) {
371 TLVPrintAIDlistFromSelectTLV(tlvSelect);
372 EMVSelectApplication(tlvSelect, AID, &AIDlen);
373 }
374 }
375
376 // Search
377 if (!AIDlen) {
378 PrintAndLog("\n* Search AID in list.");
379 SetAPDULogging(false);
380 if (EMVSearch(activateField, true, decodeTLV, tlvSelect)) {
d03fb293 381 dreturn(2);
3c5fce2b
OM
382 }
383
384 // check search and select application id
385 TLVPrintAIDlistFromSelectTLV(tlvSelect);
386 EMVSelectApplication(tlvSelect, AID, &AIDlen);
387 }
388
389 // Init TLV tree
3c5fce2b
OM
390 const char *alr = "Root terminal TLV tree";
391 tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
392
393 // check if we found EMV application on card
394 if (!AIDlen) {
395 PrintAndLog("Can't select AID. EMV AID not found");
d03fb293 396 dreturn(2);
3c5fce2b
OM
397 }
398
399 // Select
400 PrintAndLog("\n* Selecting AID:%s", sprint_hex_inrow(AID, AIDlen));
401 SetAPDULogging(showAPDU);
402 res = EMVSelect(false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
403
404 if (res) {
405 PrintAndLog("Can't select AID (%d). Exit...", res);
d03fb293 406 dreturn(3);
3c5fce2b
OM
407 }
408
409 if (decodeTLV)
410 TLVPrintFromBuffer(buf, len);
411 PrintAndLog("* Selected.");
412
3c5fce2b
OM
413 PrintAndLog("\n* Init transaction parameters.");
414
415 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
d03fb293
OM
416 char *qVSDC = "\x26\x00\x00\x00";
417 if (GenACGPO) {
418 qVSDC = "\x26\x80\x00\x00";
419 }
10d4f823 420 switch(TrType) {
421 case TT_MSD:
422 TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD
423 break;
d03fb293 424 // not standard for contactless. just for test.
10d4f823 425 case TT_VSDC:
426 TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC
427 break;
428 case TT_QVSDCMCHIP:
d03fb293 429 TLV_ADD(0x9F66, qVSDC); // qVSDC
10d4f823 430 break;
431 case TT_CDA:
d03fb293 432 TLV_ADD(0x9F66, qVSDC); // qVSDC (VISA CDA not enabled)
10d4f823 433 break;
434 default:
435 TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC
436 break;
437 }
d03fb293
OM
438
439 //9F02:(Amount, authorized (Numeric)) len:6
3c5fce2b
OM
440 TLV_ADD(0x9F02, "\x00\x00\x00\x00\x01\x00");
441 //9F1A:(Terminal Country Code) len:2
442 TLV_ADD(0x9F1A, "ru");
443 //5F2A:(Transaction Currency Code) len:2
444 // USD 840, EUR 978, RUR 810, RUB 643, RUR 810(old), UAH 980, AZN 031, n/a 999
445 TLV_ADD(0x5F2A, "\x09\x80");
446 //9A:(Transaction Date) len:3
447 TLV_ADD(0x9A, "\x00\x00\x00");
448 //9C:(Transaction Type) len:1 | 00 => Goods and service #01 => Cash
449 TLV_ADD(0x9C, "\x00");
450 // 9F37 Unpredictable Number len:4
451 TLV_ADD(0x9F37, "\x01\x02\x03\x04");
66efdc1f 452 // 9F6A Unpredictable Number (MSD for UDOL) len:4
453 TLV_ADD(0x9F6A, "\x01\x02\x03\x04");
3c5fce2b 454
66efdc1f 455 TLVPrintFromTLV(tlvRoot); // TODO delete!!!
3c5fce2b
OM
456
457 PrintAndLog("\n* Calc PDOL.");
d03fb293 458 pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
3c5fce2b
OM
459 if (!pdol_data_tlv){
460 PrintAndLog("ERROR: can't create PDOL TLV.");
d03fb293 461 dreturn(4);
3c5fce2b
OM
462 }
463
464 size_t pdol_data_tlv_data_len;
465 unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
466 if (!pdol_data_tlv_data) {
467 PrintAndLog("ERROR: can't create PDOL data.");
d03fb293 468 dreturn(4);
3c5fce2b
OM
469 }
470 PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
471
3c5fce2b
OM
472 PrintAndLog("\n* GPO.");
473 res = EMVGPO(true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
474
10d4f823 475 free(pdol_data_tlv_data);
d03fb293 476 //free(pdol_data_tlv); --- free on exit.
3c5fce2b
OM
477
478 if (res) {
479 PrintAndLog("GPO error(%d): %4x. Exit...", res, sw);
d03fb293 480 dreturn(5);
3c5fce2b
OM
481 }
482
483 // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
484 if (buf[0] == 0x80) {
3c5fce2b
OM
485 if (decodeTLV){
486 PrintAndLog("GPO response format1:");
487 TLVPrintFromBuffer(buf, len);
488 }
3c5fce2b 489
66efdc1f 490 if (len < 4 || (len - 4) % 4) {
491 PrintAndLog("ERROR: GPO response format1 parsing error. length=%d", len);
492 } else {
493 // AIP
494 struct tlvdb * f1AIP = tlvdb_fixed(0x82, 2, buf + 2);
495 tlvdb_add(tlvRoot, f1AIP);
496 if (decodeTLV){
497 PrintAndLog("\n* * Decode response format 1 (0x80) AIP and AFL:");
498 TLVPrintFromTLV(f1AIP);
499 }
500
501 // AFL
502 struct tlvdb * f1AFL = tlvdb_fixed(0x94, len - 4, buf + 2 + 2);
503 tlvdb_add(tlvRoot, f1AFL);
504 if (decodeTLV)
505 TLVPrintFromTLV(f1AFL);
506 }
507 } else {
3c5fce2b
OM
508 if (decodeTLV)
509 TLVPrintFromBuffer(buf, len);
510 }
511
66efdc1f 512 // extract PAN from track2
513 {
514 const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
515 if (!tlvdb_get(tlvRoot, 0x5a, NULL) && track2 && track2->len >= 8) {
516 struct tlvdb *pan = GetPANFromTrack2(track2);
517 if (pan) {
518 tlvdb_add(tlvRoot, pan);
519
520 const struct tlv *pantlv = tlvdb_get(tlvRoot, 0x5a, NULL);
521 PrintAndLog("\n* * Extracted PAN from track2: %s", sprint_hex(pantlv->value, pantlv->len));
522 } else {
523 PrintAndLog("\n* * WARNING: Can't extract PAN from track2.");
524 }
525 }
526 }
527
3c5fce2b
OM
528 PrintAndLog("\n* Read records from AFL.");
529 const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
530 if (!AFL || !AFL->len) {
531 PrintAndLog("WARNING: AFL not found.");
532 }
533
534 while(AFL && AFL->len) {
535 if (AFL->len % 4) {
536 PrintAndLog("ERROR: Wrong AFL length: %d", AFL->len);
537 break;
538 }
539
540 for (int i = 0; i < AFL->len / 4; i++) {
541 uint8_t SFI = AFL->value[i * 4 + 0] >> 3;
542 uint8_t SFIstart = AFL->value[i * 4 + 1];
543 uint8_t SFIend = AFL->value[i * 4 + 2];
544 uint8_t SFIoffline = AFL->value[i * 4 + 3];
545
546 PrintAndLog("* * SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
547 if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
548 PrintAndLog("SFI ERROR! Skipped...");
549 continue;
550 }
551
552 for(int n = SFIstart; n <= SFIend; n++) {
553 PrintAndLog("* * * SFI[%02x] %d", SFI, n);
554
555 res = EMVReadRecord(true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
556 if (res) {
557 PrintAndLog("ERROR SFI[%02x]. APDU error %4x", SFI, sw);
558 continue;
559 }
560
561 if (decodeTLV) {
562 TLVPrintFromBuffer(buf, len);
563 PrintAndLog("");
564 }
565
d03fb293
OM
566 // Build Input list for Offline Data Authentication
567 // EMV 4.3 book3 10.3, page 96
3c5fce2b 568 if (SFIoffline) {
d03fb293
OM
569 if (SFI < 11) {
570 const unsigned char *abuf = buf;
571 size_t elmlen = len;
572 struct tlv e;
573 if (tlv_parse_tl(&abuf, &elmlen, &e)) {
574 memcpy(&ODAiList[ODAiListLen], &buf[len - elmlen], elmlen);
575 ODAiListLen += elmlen;
576 } else {
577 PrintAndLog("ERROR SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI);
578 }
579 } else {
580 memcpy(&ODAiList[ODAiListLen], buf, len);
581 ODAiListLen += len;
582 }
3c5fce2b
OM
583 }
584 }
585 }
586
587 break;
588 }
589
d03fb293
OM
590 // copy Input list for Offline Data Authentication
591 if (ODAiListLen) {
592 struct tlvdb *oda = tlvdb_fixed(0x21, ODAiListLen, ODAiList); // not a standard tag
593 tlvdb_add(tlvRoot, oda);
594 PrintAndLog("* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen);
595 }
596
10d4f823 597 // get AIP
66efdc1f 598 const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL);
599 uint16_t AIP = AIPtlv->value[0] + AIPtlv->value[1] * 0x100;
10d4f823 600 PrintAndLog("* * AIP=%04x", AIP);
66efdc1f 601
10d4f823 602 // SDA
603 if (AIP & 0x0040) {
604 PrintAndLog("\n* SDA");
d03fb293 605 trSDA(tlvRoot);
10d4f823 606 }
607
608 // DDA
609 if (AIP & 0x0020) {
610 PrintAndLog("\n* DDA");
d03fb293 611 trDDA(decodeTLV, tlvRoot);
10d4f823 612 }
613
614 // transaction check
615
66efdc1f 616 // qVSDC
10d4f823 617 if (TrType == TT_QVSDCMCHIP|| TrType == TT_CDA){
66efdc1f 618 // 9F26: Application Cryptogram
619 const struct tlv *AC = tlvdb_get(tlvRoot, 0x9F26, NULL);
620 if (AC) {
621 PrintAndLog("\n--> qVSDC transaction.");
622 PrintAndLog("* AC path");
623
624 // 9F36: Application Transaction Counter (ATC)
625 const struct tlv *ATC = tlvdb_get(tlvRoot, 0x9F36, NULL);
626 if (ATC) {
627
628 // 9F10: Issuer Application Data - optional
629 const struct tlv *IAD = tlvdb_get(tlvRoot, 0x9F10, NULL);
630
631 // print AC data
632 PrintAndLog("ATC: %s", sprint_hex(ATC->value, ATC->len));
633 PrintAndLog("AC: %s", sprint_hex(AC->value, AC->len));
634 if (IAD){
635 PrintAndLog("IAD: %s", sprint_hex(IAD->value, IAD->len));
636
637 if (IAD->len >= IAD->value[0] + 1) {
638 PrintAndLog("\tKey index: 0x%02x", IAD->value[1]);
639 PrintAndLog("\tCrypto ver: 0x%02x(%03d)", IAD->value[2], IAD->value[2]);
640 PrintAndLog("\tCVR:", sprint_hex(&IAD->value[3], IAD->value[0] - 2));
641 struct tlvdb * cvr = tlvdb_fixed(0x20, IAD->value[0] - 2, &IAD->value[3]);
642 TLVPrintFromTLVLev(cvr, 1);
643 }
644 } else {
645 PrintAndLog("WARNING: IAD not found.");
646 }
647
648 } else {
649 PrintAndLog("ERROR AC: Application Transaction Counter (ATC) not found.");
650 }
651 }
652 }
653
10d4f823 654 // Mastercard M/CHIP
655 if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD && (TrType == TT_QVSDCMCHIP || TrType == TT_CDA)){
66efdc1f 656 const struct tlv *CDOL1 = tlvdb_get(tlvRoot, 0x8c, NULL);
657 if (CDOL1 && GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) { // and m/chip transaction flag
10d4f823 658 PrintAndLog("\n--> Mastercard M/Chip transaction.");
659
660 PrintAndLog("* * Generate challenge");
661 res = EMVGenerateChallenge(true, buf, sizeof(buf), &len, &sw, tlvRoot);
662 if (res) {
663 PrintAndLog("ERROR GetChallenge. APDU error %4x", sw);
d03fb293 664 dreturn(6);
10d4f823 665 }
666 if (len < 4) {
667 PrintAndLog("ERROR GetChallenge. Wrong challenge length %d", len);
d03fb293 668 dreturn(6);
10d4f823 669 }
670
671 // ICC Dynamic Number
672 struct tlvdb * ICCDynN = tlvdb_fixed(0x9f4c, len, buf);
673 tlvdb_add(tlvRoot, ICCDynN);
674 if (decodeTLV){
675 PrintAndLog("\n* * ICC Dynamic Number:");
676 TLVPrintFromTLV(ICCDynN);
677 }
678
679 PrintAndLog("* * Calc CDOL1");
680 struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
681 if (!cdol_data_tlv){
682 PrintAndLog("ERROR: can't create CDOL1 TLV.");
d03fb293 683 dreturn(6);
10d4f823 684 }
685 PrintAndLog("CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len));
686
687 PrintAndLog("* * AC1");
688 // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
689 res = EMVAC(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);
690
10d4f823 691 if (res) {
692 PrintAndLog("AC1 error(%d): %4x. Exit...", res, sw);
d03fb293 693 dreturn(7);
10d4f823 694 }
695
696 if (decodeTLV)
697 TLVPrintFromBuffer(buf, len);
698
d03fb293
OM
699 // CDA
700 PrintAndLog("\n* CDA:");
701 struct tlvdb *ac_tlv = tlvdb_parse_multi(buf, len);
702 res = trCDA(tlvRoot, ac_tlv, pdol_data_tlv, cdol_data_tlv);
703 if (res) {
704 PrintAndLog("CDA error (%d)", res);
705 }
706 free(ac_tlv);
707 free(cdol_data_tlv);
708
709 PrintAndLog("\n* M/Chip transaction result:");
10d4f823 710 // 9F27: Cryptogram Information Data (CID)
711 const struct tlv *CID = tlvdb_get(tlvRoot, 0x9F27, NULL);
712 if (CID) {
713 emv_tag_dump(CID, stdout, 0);
714 PrintAndLog("------------------------------");
715 if (CID->len > 0) {
716 switch(CID->value[0] & EMVAC_AC_MASK){
717 case EMVAC_AAC:
718 PrintAndLog("Transaction DECLINED.");
719 break;
720 case EMVAC_TC:
721 PrintAndLog("Transaction approved OFFLINE.");
722 break;
723 case EMVAC_ARQC:
724 PrintAndLog("Transaction approved ONLINE.");
725 break;
726 default:
727 PrintAndLog("ERROR: CID transaction code error %2x", CID->value[0] & EMVAC_AC_MASK);
728 break;
729 }
730 } else {
731 PrintAndLog("ERROR: Wrong CID length %d", CID->len);
732 }
733 } else {
734 PrintAndLog("ERROR: CID(9F27) not found.");
735 }
66efdc1f 736
737 }
738 }
739
740 // MSD
10d4f823 741 if (AIP & 0x8000 && TrType == TT_MSD) {
66efdc1f 742 PrintAndLog("\n--> MSD transaction.");
743
66efdc1f 744 PrintAndLog("* MSD dCVV path. Check dCVV");
745
746 const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
747 if (track2) {
748 PrintAndLog("Track2: %s", sprint_hex(track2->value, track2->len));
749
750 struct tlvdb *dCVV = GetdCVVRawFromTrack2(track2);
751 PrintAndLog("dCVV raw data:");
752 TLVPrintFromTLV(dCVV);
753
754 if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) {
755 PrintAndLog("\n* Mastercard calculate UDOL");
756
757 // UDOL (9F69)
758 const struct tlv *UDOL = tlvdb_get(tlvRoot, 0x9F69, NULL);
759 // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
760 const struct tlv defUDOL = {
761 .tag = 0x01,
762 .len = 3,
763 .value = (uint8_t *)"\x9f\x6a\x04",
764 };
765 if (!UDOL)
766 PrintAndLog("Use default UDOL.");
767
10d4f823 768 struct tlv *udol_data_tlv = dol_process(UDOL ? UDOL : &defUDOL, tlvRoot, 0x01); // 0x01 - dummy tag
66efdc1f 769 if (!udol_data_tlv){
770 PrintAndLog("ERROR: can't create UDOL TLV.");
d03fb293 771 dreturn(8);
66efdc1f 772 }
66efdc1f 773
78528074 774 PrintAndLog("UDOL data[%d]: %s", udol_data_tlv->len, sprint_hex(udol_data_tlv->value, udol_data_tlv->len));
66efdc1f 775
776 PrintAndLog("\n* Mastercard compute cryptographic checksum(UDOL)");
777
78528074 778 res = MSCComputeCryptoChecksum(true, (uint8_t *)udol_data_tlv->value, udol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
66efdc1f 779 if (res) {
780 PrintAndLog("ERROR Compute Crypto Checksum. APDU error %4x", sw);
d03fb293
OM
781 free(udol_data_tlv);
782 dreturn(9);
66efdc1f 783 }
784
785 if (decodeTLV) {
786 TLVPrintFromBuffer(buf, len);
787 PrintAndLog("");
788 }
d03fb293 789 free(udol_data_tlv);
66efdc1f 790
791 }
792 } else {
793 PrintAndLog("ERROR MSD: Track2 data not found.");
794 }
795 }
d03fb293 796
3c5fce2b
OM
797 // DropField
798 DropField();
799
800 // Destroy TLV's
d03fb293 801 free(pdol_data_tlv);
3c5fce2b
OM
802 tlvdb_free(tlvSelect);
803 tlvdb_free(tlvRoot);
804
805 PrintAndLog("\n* Transaction completed.");
806
807 return 0;
808}
809
d03fb293
OM
810int CmdHFEMVTest(const char *cmd) {
811 return ExecuteCryptoTests(true);
812}
813
3c5fce2b
OM
814int CmdHelp(const char *Cmd);
815static command_t CommandTable[] = {
816 {"help", CmdHelp, 1, "This help"},
817 {"exec", CmdHFEMVExec, 0, "Executes EMV contactless transaction."},
818 {"pse", CmdHFEMVPPSE, 0, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."},
819 {"search", CmdHFEMVSearch, 0, "Try to select all applets from applets list and print installed applets."},
820 {"select", CmdHFEMVSelect, 0, "Select applet."},
d03fb293 821 {"test", CmdHFEMVTest, 0, "Crypto logic test."},
3c5fce2b
OM
822 {NULL, NULL, 0, NULL}
823};
824
825int CmdHFEMV(const char *Cmd) {
826 CmdsParse(CommandTable, Cmd);
827 return 0;
828}
829
830int CmdHelp(const char *Cmd) {
831 CmdsHelp(CommandTable);
832 return 0;
833}
Impressum, Datenschutz