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