]>
git.zerfleddert.de Git - proxmark3-svn/blob - client/emv/cmdemv.c
da444a26659c8bca6bbe4e5b3e34841478705b9b
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 int 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");
27 int CmdHFEMVSelect(const char *cmd
) {
28 uint8_t data
[APDU_AID_LEN
] = {0};
30 bool activateField
= false;
31 bool leaveSignalON
= false;
32 bool decodeTLV
= false;
34 if (strlen(cmd
) < 1) {
35 UsageCmdHFEMVSelect();
39 SetAPDULogging(false);
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
)) {
48 UsageCmdHFEMVSelect();
67 PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd
, 1, cmdp
));
72 switch(param_gethex_to_eol(cmd
, cmdp
, data
, sizeof(data
), &datalen
)) {
74 PrintAndLog("Invalid HEX value.");
77 PrintAndLog("AID too large.");
80 PrintAndLog("Hex must have even number of digits.");
84 // we get all the hex to end of line with spaces
93 uint8_t buf
[APDU_RES_LEN
] = {0};
96 int res
= EMVSelect(activateField
, leaveSignalON
, data
, datalen
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
99 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
105 TLVPrintFromBuffer(buf
, len
);
110 int 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");
124 int CmdHFEMVSearch(const char *cmd
) {
126 bool activateField
= false;
127 bool leaveSignalON
= false;
128 bool decodeTLV
= false;
130 if (strlen(cmd
) < 1) {
131 UsageCmdHFEMVSearch();
135 SetAPDULogging(false);
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
)) {
144 UsageCmdHFEMVSearch();
148 activateField
= true;
152 leaveSignalON
= true;
156 SetAPDULogging(true);
163 PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd
, 1, cmdp
));
169 struct tlvdb
*t
= NULL
;
170 const char *al
= "Applets list";
171 t
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
173 if (EMVSearch(activateField
, leaveSignalON
, decodeTLV
, t
)) {
178 PrintAndLog("Search completed.");
182 TLVPrintAIDlistFromSelectTLV(t
);
190 int 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");
207 int CmdHFEMVPPSE(const char *cmd
) {
210 bool activateField
= false;
211 bool leaveSignalON
= false;
212 bool decodeTLV
= false;
214 if (strlen(cmd
) < 1) {
219 SetAPDULogging(false);
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
)) {
232 activateField
= true;
236 leaveSignalON
= true;
240 SetAPDULogging(true);
253 PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd
, 1, cmdp
));
260 uint8_t buf
[APDU_RES_LEN
] = {0};
263 int res
= EMVSelectPSE(activateField
, leaveSignalON
, PSENum
, buf
, sizeof(buf
), &len
, &sw
);
266 PrintAndLog("APDU response status: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
273 TLVPrintFromBuffer(buf
, len
);
278 int 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("Samples:");
287 PrintAndLog(" hf emv pse -s -> select card");
288 PrintAndLog(" hf emv pse -s -t -a -> select card, show responses in TLV, show APDU");
292 #define TLV_ADD(tag, value)( tlvdb_add(tlvRoot, tlvdb_fixed(tag, sizeof(value) - 1, (const unsigned char *)value)) )
294 int CmdHFEMVExec(const char *cmd
) {
295 bool activateField
= false;
296 bool showAPDU
= false;
297 bool decodeTLV
= false;
298 bool forceSearch
= false;
300 uint8_t buf
[APDU_RES_LEN
] = {0};
303 uint8_t AID
[APDU_AID_LEN
] = {0};
308 if (strlen(cmd
) < 1) {
314 while(param_getchar(cmd
, cmdp
) != 0x00) {
315 char c
= param_getchar(cmd
, cmdp
);
316 if ((c
== '-') && (param_getlength(cmd
, cmdp
) == 2))
317 switch (param_getchar_indx(cmd
, 1, cmdp
)) {
324 activateField
= true;
339 PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd
, 1, cmdp
));
346 // init applets list tree
347 struct tlvdb
*tlvSelect
= NULL
;
348 const char *al
= "Applets list";
349 tlvSelect
= tlvdb_fixed(1, strlen(al
), (const unsigned char *)al
);
351 // Application Selection
352 // https://www.openscdp.org/scripts/tutorial/emv/applicationselection.html
355 PrintAndLog("\n* PPSE.");
356 SetAPDULogging(showAPDU
);
357 res
= EMVSearchPSE(activateField
, true, decodeTLV
, tlvSelect
);
359 // check PPSE and select application id
361 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
362 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
368 PrintAndLog("\n* Search AID in list.");
369 SetAPDULogging(false);
370 if (EMVSearch(activateField
, true, decodeTLV
, tlvSelect
)) {
371 tlvdb_free(tlvSelect
);
375 // check search and select application id
376 TLVPrintAIDlistFromSelectTLV(tlvSelect
);
377 EMVSelectApplication(tlvSelect
, AID
, &AIDlen
);
381 struct tlvdb
*tlvRoot
= NULL
;
382 const char *alr
= "Root terminal TLV tree";
383 tlvRoot
= tlvdb_fixed(1, strlen(alr
), (const unsigned char *)alr
);
385 // check if we found EMV application on card
387 PrintAndLog("Can't select AID. EMV AID not found");
392 PrintAndLog("\n* Selecting AID:%s", sprint_hex_inrow(AID
, AIDlen
));
393 SetAPDULogging(showAPDU
);
394 res
= EMVSelect(false, true, AID
, AIDlen
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
397 PrintAndLog("Can't select AID (%d). Exit...", res
);
402 TLVPrintFromBuffer(buf
, len
);
403 PrintAndLog("* Selected.");
405 PrintAndLog("\n* Init transaction parameters.");
407 //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
408 TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD
409 // TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC
410 // TLV_ADD(0x9F66, "\x8e\x00\x00\x00"); // CDA
411 //9F02:(Amount, Authorised (Numeric)) len:6
412 TLV_ADD(0x9F02, "\x00\x00\x00\x00\x01\x00");
413 //9F1A:(Terminal Country Code) len:2
414 TLV_ADD(0x9F1A, "ru");
415 //5F2A:(Transaction Currency Code) len:2
416 // USD 840, EUR 978, RUR 810, RUB 643, RUR 810(old), UAH 980, AZN 031, n/a 999
417 TLV_ADD(0x5F2A, "\x09\x80");
418 //9A:(Transaction Date) len:3
419 TLV_ADD(0x9A, "\x00\x00\x00");
420 //9C:(Transaction Type) len:1 | 00 => Goods and service #01 => Cash
421 TLV_ADD(0x9C, "\x00");
422 // 9F37 Unpredictable Number len:4
423 TLV_ADD(0x9F37, "\x01\x02\x03\x04");
424 // 9F6A Unpredictable Number (MSD for UDOL) len:4
425 TLV_ADD(0x9F6A, "\x01\x02\x03\x04");
427 TLVPrintFromTLV(tlvRoot
); // TODO delete!!!
429 PrintAndLog("\n* Calc PDOL.");
430 struct tlv
*pdol_data_tlv
= dol_process(tlvdb_get(tlvRoot
, 0x9f38, NULL
), tlvRoot
, 0x83);
432 PrintAndLog("ERROR: can't create PDOL TLV.");
436 size_t pdol_data_tlv_data_len
;
437 unsigned char *pdol_data_tlv_data
= tlv_encode(pdol_data_tlv
, &pdol_data_tlv_data_len
);
438 if (!pdol_data_tlv_data
) {
439 PrintAndLog("ERROR: can't create PDOL data.");
442 PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len
, sprint_hex(pdol_data_tlv_data
, pdol_data_tlv_data_len
));
444 PrintAndLog("\n* GPO.");
445 res
= EMVGPO(true, pdol_data_tlv_data
, pdol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
450 PrintAndLog("GPO error(%d): %4x. Exit...", res
, sw
);
454 // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
455 if (buf
[0] == 0x80) {
457 PrintAndLog("GPO response format1:");
458 TLVPrintFromBuffer(buf
, len
);
461 if (len
< 4 || (len
- 4) % 4) {
462 PrintAndLog("ERROR: GPO response format1 parsing error. length=%d", len
);
465 struct tlvdb
* f1AIP
= tlvdb_fixed(0x82, 2, buf
+ 2);
466 tlvdb_add(tlvRoot
, f1AIP
);
468 PrintAndLog("\n* * Decode response format 1 (0x80) AIP and AFL:");
469 TLVPrintFromTLV(f1AIP
);
473 struct tlvdb
* f1AFL
= tlvdb_fixed(0x94, len
- 4, buf
+ 2 + 2);
474 tlvdb_add(tlvRoot
, f1AFL
);
476 TLVPrintFromTLV(f1AFL
);
480 TLVPrintFromBuffer(buf
, len
);
483 // extract PAN from track2
485 const struct tlv
*track2
= tlvdb_get(tlvRoot
, 0x57, NULL
);
486 if (!tlvdb_get(tlvRoot
, 0x5a, NULL
) && track2
&& track2
->len
>= 8) {
487 struct tlvdb
*pan
= GetPANFromTrack2(track2
);
489 tlvdb_add(tlvRoot
, pan
);
491 const struct tlv
*pantlv
= tlvdb_get(tlvRoot
, 0x5a, NULL
);
492 PrintAndLog("\n* * Extracted PAN from track2: %s", sprint_hex(pantlv
->value
, pantlv
->len
));
494 PrintAndLog("\n* * WARNING: Can't extract PAN from track2.");
499 PrintAndLog("\n* Read records from AFL.");
500 const struct tlv
*AFL
= tlvdb_get(tlvRoot
, 0x94, NULL
);
501 if (!AFL
|| !AFL
->len
) {
502 PrintAndLog("WARNING: AFL not found.");
505 while(AFL
&& AFL
->len
) {
507 PrintAndLog("ERROR: Wrong AFL length: %d", AFL
->len
);
511 for (int i
= 0; i
< AFL
->len
/ 4; i
++) {
512 uint8_t SFI
= AFL
->value
[i
* 4 + 0] >> 3;
513 uint8_t SFIstart
= AFL
->value
[i
* 4 + 1];
514 uint8_t SFIend
= AFL
->value
[i
* 4 + 2];
515 uint8_t SFIoffline
= AFL
->value
[i
* 4 + 3];
517 PrintAndLog("* * SFI[%02x] start:%02x end:%02x offline:%02x", SFI
, SFIstart
, SFIend
, SFIoffline
);
518 if (SFI
== 0 || SFI
== 31 || SFIstart
== 0 || SFIstart
> SFIend
) {
519 PrintAndLog("SFI ERROR! Skipped...");
523 for(int n
= SFIstart
; n
<= SFIend
; n
++) {
524 PrintAndLog("* * * SFI[%02x] %d", SFI
, n
);
526 res
= EMVReadRecord(true, SFI
, n
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
528 PrintAndLog("ERROR SFI[%02x]. APDU error %4x", SFI
, sw
);
533 TLVPrintFromBuffer(buf
, len
);
538 // here will be offline records storing...
539 // dont foget: if (sfi < 11)
548 const struct tlv
*AIPtlv
= tlvdb_get(tlvRoot
, 0x82, NULL
);
549 uint16_t AIP
= AIPtlv
->value
[0] + AIPtlv
->value
[1] * 0x100;
550 PrintAndLog("* * AIP=%x", AIP
);
554 // 9F26: Application Cryptogram
555 const struct tlv
*AC
= tlvdb_get(tlvRoot
, 0x9F26, NULL
);
557 PrintAndLog("\n--> qVSDC transaction.");
558 PrintAndLog("* AC path");
560 // 9F36: Application Transaction Counter (ATC)
561 const struct tlv
*ATC
= tlvdb_get(tlvRoot
, 0x9F36, NULL
);
564 // 9F10: Issuer Application Data - optional
565 const struct tlv
*IAD
= tlvdb_get(tlvRoot
, 0x9F10, NULL
);
568 PrintAndLog("ATC: %s", sprint_hex(ATC
->value
, ATC
->len
));
569 PrintAndLog("AC: %s", sprint_hex(AC
->value
, AC
->len
));
571 PrintAndLog("IAD: %s", sprint_hex(IAD
->value
, IAD
->len
));
573 if (IAD
->len
>= IAD
->value
[0] + 1) {
574 PrintAndLog("\tKey index: 0x%02x", IAD
->value
[1]);
575 PrintAndLog("\tCrypto ver: 0x%02x(%03d)", IAD
->value
[2], IAD
->value
[2]);
576 PrintAndLog("\tCVR:", sprint_hex(&IAD
->value
[3], IAD
->value
[0] - 2));
577 struct tlvdb
* cvr
= tlvdb_fixed(0x20, IAD
->value
[0] - 2, &IAD
->value
[3]);
578 TLVPrintFromTLVLev(cvr
, 1);
581 PrintAndLog("WARNING: IAD not found.");
585 PrintAndLog("ERROR AC: Application Transaction Counter (ATC) not found.");
590 // TODO: Mastercard M/CHIP
592 const struct tlv
*CDOL1
= tlvdb_get(tlvRoot
, 0x8c, NULL
);
593 if (CDOL1
&& GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
) { // and m/chip transaction flag
600 PrintAndLog("\n--> MSD transaction.");
603 PrintAndLog("* MSD dCVV path. Check dCVV");
605 const struct tlv
*track2
= tlvdb_get(tlvRoot
, 0x57, NULL
);
607 PrintAndLog("Track2: %s", sprint_hex(track2
->value
, track2
->len
));
609 struct tlvdb
*dCVV
= GetdCVVRawFromTrack2(track2
);
610 PrintAndLog("dCVV raw data:");
611 TLVPrintFromTLV(dCVV
);
613 if (GetCardPSVendor(AID
, AIDlen
) == CV_MASTERCARD
) {
614 PrintAndLog("\n* Mastercard calculate UDOL");
617 const struct tlv
*UDOL
= tlvdb_get(tlvRoot
, 0x9F69, NULL
);
618 // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
619 const struct tlv defUDOL
= {
622 .value
= (uint8_t *)"\x9f\x6a\x04",
625 PrintAndLog("Use default UDOL.");
627 struct tlv
*udol_data_tlv
= dol_process(UDOL
? UDOL
: &defUDOL
, tlvRoot
, 0x01); // 0x01 - fake tag!
629 PrintAndLog("ERROR: can't create UDOL TLV.");
633 size_t udol_data_tlv_data_len
;
634 unsigned char *udol_data_tlv_data
= tlv_encode(udol_data_tlv
, &udol_data_tlv_data_len
);
635 if (!udol_data_tlv_data
) {
636 PrintAndLog("ERROR: can't create UDOL data.");
640 // eliminate fake tag
641 udol_data_tlv_data_len
-= 2;
642 udol_data_tlv_data
+= 2;
644 PrintAndLog("UDOL data[%d]: %s", udol_data_tlv_data_len
, sprint_hex(udol_data_tlv_data
, udol_data_tlv_data_len
));
646 PrintAndLog("\n* Mastercard compute cryptographic checksum(UDOL)");
648 res
= MSCComputeCryptoChecksum(true, udol_data_tlv_data
, udol_data_tlv_data_len
, buf
, sizeof(buf
), &len
, &sw
, tlvRoot
);
650 PrintAndLog("ERROR Compute Crypto Checksum. APDU error %4x", sw
);
655 TLVPrintFromBuffer(buf
, len
);
661 PrintAndLog("ERROR MSD: Track2 data not found.");
665 // additional contacless EMV commands (fDDA, external authenticate)
672 tlvdb_free(tlvSelect
);
675 PrintAndLog("\n* Transaction completed.");
680 int CmdHelp(const char *Cmd
);
681 static command_t CommandTable
[] = {
682 {"help", CmdHelp
, 1, "This help"},
683 {"exec", CmdHFEMVExec
, 0, "Executes EMV contactless transaction."},
684 {"pse", CmdHFEMVPPSE
, 0, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."},
685 {"search", CmdHFEMVSearch
, 0, "Try to select all applets from applets list and print installed applets."},
686 {"select", CmdHFEMVSelect
, 0, "Select applet."},
687 {NULL
, NULL
, 0, NULL
}
690 int CmdHFEMV(const char *Cmd
) {
691 CmdsParse(CommandTable
, Cmd
);
695 int CmdHelp(const char *Cmd
) {
696 CmdsHelp(CommandTable
);