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