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