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