]>
git.zerfleddert.de Git - proxmark3-svn/blob - client/emv/cmdemv.c
c40a9a69b3544d1861001bdaedea09c0664213cb
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2017 Merlok
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
7 //-----------------------------------------------------------------------------
9 //-----------------------------------------------------------------------------
13 #include "test/cryptotest.h"
14 #include "cliparser/cliparser.h"
16 int UsageCmdHFEMVSelect(void) {
17 PrintAndLog("HELP : Executes select applet command:\n");
18 PrintAndLog("Usage: hf emv select [-s][-k][-a][-t] <HEX applet AID>\n");
19 PrintAndLog(" Options:");
20 PrintAndLog(" -s : select card");
21 PrintAndLog(" -k : keep field for next command");
22 PrintAndLog(" -a : show APDU reqests and responses\n");
23 PrintAndLog(" -t : TLV decode results\n");
24 PrintAndLog("Samples:");
25 PrintAndLog(" hf emv select -s a00000000101 -> select card, select applet");
26 PrintAndLog(" hf emv select -s -t a00000000101 -> select card, select applet, show result in TLV");
30 int CmdHFEMVSelect(const char *cmd
) {
31 uint8_t data
[APDU_AID_LEN
] = {0};
35 CLIParserInit("hf 14a select",
36 "Executes select applet command",
37 "Usage:\n\thf emv select -s a00000000101 -> select card, select applet\n\thf emv select -s -t a00000000101 -> select card, select applet, show result in TLV\n");
41 arg_lit0("sS", "select", "activate field and select card"),
42 arg_lit0("kK", "keep", "keep field for next command"),
43 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
44 arg_lit0("tT", "tlv", "TLV decode results"),
45 arg_str0(NULL
, NULL
, "<HEX applet AID>", NULL
),
48 CLIExecWithReturn(cmd
, argtable
, true);
50 bool activateField
= arg_get_lit(1);
51 bool leaveSignalON
= arg_get_lit(2);
52 bool APDULogging
= arg_get_lit(3);
53 bool decodeTLV
= arg_get_lit(4);
54 if (arg_get_str_len(5))
55 CLIGetStrBLessWithReturn(5, data
, &datalen
, 0);
58 SetAPDULogging(APDULogging
);
61 uint8_t buf
[APDU_RES_LEN
] = {0};
64 int res
= EMVSelect(activateField
, leaveSignalON
, data
, datalen
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
67 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
73 TLVPrintFromBuffer(buf
, len
);
78 int CmdHFEMVSearch(const char *cmd
) {
80 CLIParserInit("hf 14a select",
81 "Tries to select all applets from applet list:\n",
82 "Usage:\n\thf emv search -s -> select card and search\n\thf emv search -s -t -> select card, search and show result in TLV\n");
86 arg_lit0("sS", "select", "activate field and select card"),
87 arg_lit0("kK", "keep", "keep field ON for next command"),
88 arg_lit0("aA", "apdu", "show APDU reqests and responses"),
89 arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
92 CLIExecWithReturn(cmd
, argtable
, true);
94 bool activateField
= arg_get_lit(1);
95 bool leaveSignalON
= arg_get_lit(2);
96 bool APDULogging
= arg_get_lit(3);
97 bool decodeTLV
= arg_get_lit(4);
100 SetAPDULogging(APDULogging
);
102 struct tlvdb
*t
= NULL
;
103 const char *al
= "Applets list";
104 t
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
106 if (EMVSearch(activateField
, leaveSignalON
, decodeTLV
, t
)) {
111 PrintAndLog("Search completed.");
115 TLVPrintAIDlistFromSelectTLV(t
);
123 int UsageCmdHFEMVPPSE(void) {
124 PrintAndLog("HELP : Executes PSE/PPSE select command. It returns list of applet on the card:\n");
125 PrintAndLog("Usage: hf emv pse [-s][-k][-1][-2][-a][-t]\n");
126 PrintAndLog(" Options:");
127 PrintAndLog(" -s : select card");
128 PrintAndLog(" -k : keep field for next command");
129 PrintAndLog(" -1 : ppse (1PAY.SYS.DDF01)");
130 PrintAndLog(" -2 : pse (2PAY.SYS.DDF01)");
131 PrintAndLog(" -a : show APDU reqests and responses\n");
132 PrintAndLog(" -t : TLV decode results\n");
133 PrintAndLog("Samples:");
134 PrintAndLog(" hf emv pse -s -1 -> select, get pse");
135 PrintAndLog(" hf emv pse -s -k -2 -> select, get ppse, keep field");
136 PrintAndLog(" hf emv pse -s -t -2 -> select, get ppse, show result in TLV");
140 int CmdHFEMVPPSE(const char *cmd
) {
143 bool activateField
= false;
144 bool leaveSignalON
= false;
145 bool decodeTLV
= false;
147 if (strlen(cmd
) < 1) {
152 SetAPDULogging(false);
155 while(param_getchar(cmd
, cmdp
) != 0x00) {
156 char c
= param_getchar(cmd
, cmdp
);
157 if ((c
== '-') && (param_getlength(cmd
, cmdp
) == 2))
158 switch (param_getchar_indx(cmd
, 1, cmdp
)) {
165 activateField
= true;
169 leaveSignalON
= true;
173 SetAPDULogging(true);
186 PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd
, 1, cmdp
));
193 uint8_t buf
[APDU_RES_LEN
] = {0};
196 int res
= EMVSelectPSE(activateField
, leaveSignalON
, PSENum
, buf
, sizeof(buf
), &len
, &sw
);
199 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
206 TLVPrintFromBuffer(buf
, len
);
211 int UsageCmdHFEMVExec(void) {
212 PrintAndLog("HELP : Executes EMV contactless transaction:\n");
213 PrintAndLog("Usage: hf emv exec [-s][-a][-t][-f][-v][-c][-x][-g]\n");
214 PrintAndLog(" Options:");
215 PrintAndLog(" -s : select card");
216 PrintAndLog(" -a : show APDU reqests and responses\n");
217 PrintAndLog(" -t : TLV decode results\n");
218 PrintAndLog(" -f : force search AID. Search AID instead of execute PPSE.\n");
219 PrintAndLog(" -v : transaction type - qVSDC or M/Chip.\n");
220 PrintAndLog(" -c : transaction type - qVSDC or M/Chip plus CDA (SDAD generation).\n");
221 PrintAndLog(" -x : transaction type - VSDC. For test only. Not a standart behavior.\n");
222 PrintAndLog(" -g : VISA. generate AC from GPO\n");
223 PrintAndLog("By default : transaction type - MSD.\n");
224 PrintAndLog("Samples:");
225 PrintAndLog(" hf emv exec -s -a -t -> execute MSD transaction");
226 PrintAndLog(" hf emv exec -s -a -t -c -> execute CDA transaction");
230 #define TLV_ADD(tag, value)( tlvdb_add(tlvRoot, tlvdb_fixed(tag, sizeof(value) - 1, (const unsigned char *)value)) )
231 #define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;}
233 int CmdHFEMVExec(const char *cmd
) {
234 bool activateField
= false;
235 bool showAPDU
= false;
236 bool decodeTLV
= false;
237 bool forceSearch
= false;
238 enum TransactionType TrType
= TT_MSD
;
239 bool GenACGPO
= false;
241 uint8_t buf
[APDU_RES_LEN
] = {0};
244 uint8_t AID
[APDU_AID_LEN
] = {0};
246 uint8_t ODAiList
[4096];
247 size_t ODAiListLen
= 0;
251 struct tlvdb
*tlvSelect
= NULL
;
252 struct tlvdb
*tlvRoot
= NULL
;
253 struct tlv
*pdol_data_tlv
= NULL
;
255 if (strlen(cmd
) < 1) {
261 while(param_getchar(cmd
, cmdp
) != 0x00) {
262 char c
= param_getchar(cmd
, cmdp
);
263 if ((c
== '-') && (param_getlength(cmd
, cmdp
) == 2))
264 switch (param_getchar_indx(cmd
, 1, cmdp
)) {
271 activateField
= true;
291 TrType
= TT_QVSDCMCHIP
;
302 PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd
, 1, cmdp
));
309 // init applets list tree
310 const char *al
= "Applets list";
311 tlvSelect
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
313 // Application Selection
314 // https://www.openscdp.org/scripts/tutorial/emv/applicationselection.html
317 PrintAndLog("\n* PPSE.");
318 SetAPDULogging(showAPDU
);
319 res
= EMVSearchPSE(activateField
, true, decodeTLV
, tlvSelect
);
321 // check PPSE and select application id
323 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
324 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
330 PrintAndLog("\n* Search AID in list.");
331 SetAPDULogging(false);
332 if (EMVSearch(activateField
, true, decodeTLV
, tlvSelect
)) {
336 // check search and select application id
337 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
338 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
342 const char *alr
= "Root terminal TLV tree";
343 tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
345 // check if we found EMV application on card
347 PrintAndLog("Can't select AID. EMV AID not found");
352 PrintAndLog("\n* Selecting AID:%s", sprint_hex_inrow(AID
, AIDlen
));
353 SetAPDULogging(showAPDU
);
354 res
= EMVSelect(false, true, AID
, AIDlen
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
357 PrintAndLog("Can't select AID (%d). Exit...", res
);
362 TLVPrintFromBuffer(buf
, len
);
363 PrintAndLog("* Selected.");
365 PrintAndLog("\n* Init transaction parameters.");
367 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
368 char *qVSDC
= "\x26\x00\x00\x00";
370 qVSDC
= "\x26\x80\x00\x00";
374 TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD
376 // not standard for contactless. just for test.
378 TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC
381 TLV_ADD(0x9F66, qVSDC
); // qVSDC
384 TLV_ADD(0x9F66, qVSDC
); // qVSDC (VISA CDA not enabled)
387 TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC
391 //9F02:(Amount, authorized (Numeric)) len:6
392 TLV_ADD(0x9F02, "\x00\x00\x00\x00\x01\x00");
393 //9F1A:(Terminal Country Code) len:2
394 TLV_ADD(0x9F1A, "ru");
395 //5F2A:(Transaction Currency Code) len:2
396 // USD 840, EUR 978, RUR 810, RUB 643, RUR 810(old), UAH 980, AZN 031, n/a 999
397 TLV_ADD(0x5F2A, "\x09\x80");
398 //9A:(Transaction Date) len:3
399 TLV_ADD(0x9A, "\x00\x00\x00");
400 //9C:(Transaction Type) len:1 | 00 => Goods and service #01 => Cash
401 TLV_ADD(0x9C, "\x00");
402 // 9F37 Unpredictable Number len:4
403 TLV_ADD(0x9F37, "\x01\x02\x03\x04");
404 // 9F6A Unpredictable Number (MSD for UDOL) len:4
405 TLV_ADD(0x9F6A, "\x01\x02\x03\x04");
407 TLVPrintFromTLV(tlvRoot
); // TODO delete!!!
409 PrintAndLog("\n* Calc PDOL.");
410 pdol_data_tlv
= dol_process(tlvdb_get(tlvRoot
, 0x9f38, NULL
), tlvRoot
, 0x83);
412 PrintAndLog("ERROR: can't create PDOL TLV.");
416 size_t pdol_data_tlv_data_len
;
417 unsigned char *pdol_data_tlv_data
= tlv_encode(pdol_data_tlv
, &pdol_data_tlv_data_len
);
418 if (!pdol_data_tlv_data
) {
419 PrintAndLog("ERROR: can't create PDOL data.");
422 PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
424 PrintAndLog("\n* GPO.");
425 res
= EMVGPO(true, pdol_data_tlv_data
, pdol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
427 free(pdol_data_tlv_data
);
428 //free(pdol_data_tlv); --- free on exit.
431 PrintAndLog("GPO error(%d): %4x. Exit...", res
, sw
);
435 // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
436 if (buf
[0] == 0x80) {
438 PrintAndLog("GPO response format1:");
439 TLVPrintFromBuffer(buf
, len
);
442 if (len
< 4 || (len
- 4) % 4) {
443 PrintAndLog("ERROR: GPO response format1 parsing error. length=%d", len
);
446 struct tlvdb
* f1AIP
= tlvdb_fixed(0x82, 2, buf
+ 2);
447 tlvdb_add(tlvRoot
, f1AIP
);
449 PrintAndLog("\n* * Decode response format 1 (0x80) AIP and AFL:");
450 TLVPrintFromTLV(f1AIP
);
454 struct tlvdb
* f1AFL
= tlvdb_fixed(0x94, len
- 4, buf
+ 2 + 2);
455 tlvdb_add(tlvRoot
, f1AFL
);
457 TLVPrintFromTLV(f1AFL
);
461 TLVPrintFromBuffer(buf
, len
);
464 // extract PAN from track2
466 const struct tlv
*track2
= tlvdb_get(tlvRoot
, 0x57, NULL
);
467 if (!tlvdb_get(tlvRoot
, 0x5a, NULL
) && track2
&& track2
->len
>= 8) {
468 struct tlvdb
*pan
= GetPANFromTrack2(track2
);
470 tlvdb_add(tlvRoot
, pan
);
472 const struct tlv
*pantlv
= tlvdb_get(tlvRoot
, 0x5a, NULL
);
473 PrintAndLog("\n* * Extracted PAN from track2: %s", sprint_hex(pantlv
->value
, pantlv
->len
));
475 PrintAndLog("\n* * WARNING: Can't extract PAN from track2.");
480 PrintAndLog("\n* Read records from AFL.");
481 const struct tlv
*AFL
= tlvdb_get(tlvRoot
, 0x94, NULL
);
482 if (!AFL
|| !AFL
->len
) {
483 PrintAndLog("WARNING: AFL not found.");
486 while(AFL
&& AFL
->len
) {
488 PrintAndLog("ERROR: Wrong AFL length: %d", AFL
->len
);
492 for (int i
= 0; i
< AFL
->len
/ 4; i
++) {
493 uint8_t SFI
= AFL
->value
[i
* 4 + 0] >> 3;
494 uint8_t SFIstart
= AFL
->value
[i
* 4 + 1];
495 uint8_t SFIend
= AFL
->value
[i
* 4 + 2];
496 uint8_t SFIoffline
= AFL
->value
[i
* 4 + 3];
498 PrintAndLog("* * SFI[%02x] start:%02x end:%02x offline:%02x", SFI
, SFIstart
, SFIend
, SFIoffline
);
499 if (SFI
== 0 || SFI
== 31 || SFIstart
== 0 || SFIstart
> SFIend
) {
500 PrintAndLog("SFI ERROR! Skipped...");
504 for(int n
= SFIstart
; n
<= SFIend
; n
++) {
505 PrintAndLog("* * * SFI[%02x] %d", SFI
, n
);
507 res
= EMVReadRecord(true, SFI
, n
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
509 PrintAndLog("ERROR SFI[%02x]. APDU error %4x", SFI
, sw
);
514 TLVPrintFromBuffer(buf
, len
);
518 // Build Input list for Offline Data Authentication
519 // EMV 4.3 book3 10.3, page 96
522 const unsigned char *abuf
= buf
;
525 if (tlv_parse_tl(&abuf
, &elmlen
, &e
)) {
526 memcpy(&ODAiList
[ODAiListLen
], &buf
[len
- elmlen
], elmlen
);
527 ODAiListLen
+= elmlen
;
529 PrintAndLog("ERROR SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI
);
532 memcpy(&ODAiList
[ODAiListLen
], buf
, len
);
542 // copy Input list for Offline Data Authentication
544 struct tlvdb
*oda
= tlvdb_fixed(0x21, ODAiListLen
, ODAiList
); // not a standard tag
545 tlvdb_add(tlvRoot
, oda
);
546 PrintAndLog("* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen
);
550 const struct tlv
*AIPtlv
= tlvdb_get(tlvRoot
, 0x82, NULL
);
551 uint16_t AIP
= AIPtlv
->value
[0] + AIPtlv
->value
[1] * 0x100;
552 PrintAndLog("* * AIP=%04x", AIP
);
556 PrintAndLog("\n* SDA");
562 PrintAndLog("\n* DDA");
563 trDDA(decodeTLV
, tlvRoot
);
569 if (TrType
== TT_QVSDCMCHIP
|| TrType
== TT_CDA
){
570 // 9F26: Application Cryptogram
571 const struct tlv
*AC
= tlvdb_get(tlvRoot
, 0x9F26, NULL
);
573 PrintAndLog("\n--> qVSDC transaction.");
574 PrintAndLog("* AC path");
576 // 9F36: Application Transaction Counter (ATC)
577 const struct tlv
*ATC
= tlvdb_get(tlvRoot
, 0x9F36, NULL
);
580 // 9F10: Issuer Application Data - optional
581 const struct tlv
*IAD
= tlvdb_get(tlvRoot
, 0x9F10, NULL
);
584 PrintAndLog("ATC: %s", sprint_hex(ATC
->value
, ATC
->len
));
585 PrintAndLog("AC: %s", sprint_hex(AC
->value
, AC
->len
));
587 PrintAndLog("IAD: %s", sprint_hex(IAD
->value
, IAD
->len
));
589 if (IAD
->len
>= IAD
->value
[0] + 1) {
590 PrintAndLog("\tKey index: 0x%02x", IAD
->value
[1]);
591 PrintAndLog("\tCrypto ver: 0x%02x(%03d)", IAD
->value
[2], IAD
->value
[2]);
592 PrintAndLog("\tCVR:", sprint_hex(&IAD
->value
[3], IAD
->value
[0] - 2));
593 struct tlvdb
* cvr
= tlvdb_fixed(0x20, IAD
->value
[0] - 2, &IAD
->value
[3]);
594 TLVPrintFromTLVLev(cvr
, 1);
597 PrintAndLog("WARNING: IAD not found.");
601 PrintAndLog("ERROR AC: Application Transaction Counter (ATC) not found.");
607 if (GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
&& (TrType
== TT_QVSDCMCHIP
|| TrType
== TT_CDA
)){
608 const struct tlv
*CDOL1
= tlvdb_get(tlvRoot
, 0x8c, NULL
);
609 if (CDOL1
&& GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
) { // and m/chip transaction flag
610 PrintAndLog("\n--> Mastercard M/Chip transaction.");
612 PrintAndLog("* * Generate challenge");
613 res
= EMVGenerateChallenge(true, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
615 PrintAndLog("ERROR GetChallenge. APDU error %4x", sw
);
619 PrintAndLog("ERROR GetChallenge. Wrong challenge length %d", len
);
623 // ICC Dynamic Number
624 struct tlvdb
* ICCDynN
= tlvdb_fixed(0x9f4c, len
, buf
);
625 tlvdb_add(tlvRoot
, ICCDynN
);
627 PrintAndLog("\n* * ICC Dynamic Number:");
628 TLVPrintFromTLV(ICCDynN
);
631 PrintAndLog("* * Calc CDOL1");
632 struct tlv
*cdol_data_tlv
= dol_process(tlvdb_get(tlvRoot
, 0x8c, NULL
), tlvRoot
, 0x01); // 0x01 - dummy tag
634 PrintAndLog("ERROR: can't create CDOL1 TLV.");
637 PrintAndLog("CDOL1 data[%d]: %s", cdol_data_tlv
->len
, sprint_hex(cdol_data_tlv
->value
, cdol_data_tlv
->len
));
639 PrintAndLog("* * AC1");
640 // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
641 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
);
644 PrintAndLog("AC1 error(%d): %4x. Exit...", res
, sw
);
649 TLVPrintFromBuffer(buf
, len
);
652 PrintAndLog("\n* CDA:");
653 struct tlvdb
*ac_tlv
= tlvdb_parse_multi(buf
, len
);
654 res
= trCDA(tlvRoot
, ac_tlv
, pdol_data_tlv
, cdol_data_tlv
);
656 PrintAndLog("CDA error (%d)", res
);
661 PrintAndLog("\n* M/Chip transaction result:");
662 // 9F27: Cryptogram Information Data (CID)
663 const struct tlv
*CID
= tlvdb_get(tlvRoot
, 0x9F27, NULL
);
665 emv_tag_dump(CID
, stdout
, 0);
666 PrintAndLog("------------------------------");
668 switch(CID
->value
[0] & EMVAC_AC_MASK
){
670 PrintAndLog("Transaction DECLINED.");
673 PrintAndLog("Transaction approved OFFLINE.");
676 PrintAndLog("Transaction approved ONLINE.");
679 PrintAndLog("ERROR: CID transaction code error %2x", CID
->value
[0] & EMVAC_AC_MASK
);
683 PrintAndLog("ERROR: Wrong CID length %d", CID
->len
);
686 PrintAndLog("ERROR: CID(9F27) not found.");
693 if (AIP
& 0x8000 && TrType
== TT_MSD
) {
694 PrintAndLog("\n--> MSD transaction.");
696 PrintAndLog("* MSD dCVV path. Check dCVV");
698 const struct tlv
*track2
= tlvdb_get(tlvRoot
, 0x57, NULL
);
700 PrintAndLog("Track2: %s", sprint_hex(track2
->value
, track2
->len
));
702 struct tlvdb
*dCVV
= GetdCVVRawFromTrack2(track2
);
703 PrintAndLog("dCVV raw data:");
704 TLVPrintFromTLV(dCVV
);
706 if (GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
) {
707 PrintAndLog("\n* Mastercard calculate UDOL");
710 const struct tlv
*UDOL
= tlvdb_get(tlvRoot
, 0x9F69, NULL
);
711 // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
712 const struct tlv defUDOL
= {
715 .value
= (uint8_t *)"\x9f\x6a\x04",
718 PrintAndLog("Use default UDOL.");
720 struct tlv
*udol_data_tlv
= dol_process(UDOL
? UDOL
: &defUDOL
, tlvRoot
, 0x01); // 0x01 - dummy tag
722 PrintAndLog("ERROR: can't create UDOL TLV.");
726 PrintAndLog("UDOL data[%d]: %s", udol_data_tlv
->len
, sprint_hex(udol_data_tlv
->value
, udol_data_tlv
->len
));
728 PrintAndLog("\n* Mastercard compute cryptographic checksum(UDOL)");
730 res
= MSCComputeCryptoChecksum(true, (uint8_t *)udol_data_tlv
->value
, udol_data_tlv
->len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
732 PrintAndLog("ERROR Compute Crypto Checksum. APDU error %4x", sw
);
738 TLVPrintFromBuffer(buf
, len
);
745 PrintAndLog("ERROR MSD: Track2 data not found.");
754 tlvdb_free(tlvSelect
);
757 PrintAndLog("\n* Transaction completed.");
762 int CmdHFEMVTest(const char *cmd
) {
763 return ExecuteCryptoTests(true);
766 int CmdHelp(const char *Cmd
);
767 static command_t CommandTable
[] = {
768 {"help", CmdHelp
, 1, "This help"},
769 {"exec", CmdHFEMVExec
, 0, "Executes EMV contactless transaction."},
770 {"pse", CmdHFEMVPPSE
, 0, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."},
771 {"search", CmdHFEMVSearch
, 0, "Try to select all applets from applets list and print installed applets."},
772 {"select", CmdHFEMVSelect
, 0, "Select applet."},
773 {"test", CmdHFEMVTest
, 0, "Crypto logic test."},
774 {NULL
, NULL
, 0, NULL
}
777 int CmdHFEMV(const char *Cmd
) {
778 CmdsParse(CommandTable
, Cmd
);
782 int CmdHelp(const char *Cmd
) {
783 CmdsHelp(CommandTable
);