1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2018 iceman
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 //-----------------------------------------------------------------------------
8 // Proxmark3 RDV40 Smartcard module commands
9 //-----------------------------------------------------------------------------
10 #include "cmdsmartcard.h"
15 #include "cmdparser.h"
16 #include "proxmark3.h"
18 #include "smartcard.h"
20 #include "protocols.h"
22 #include "cmdhflist.h"
23 #include "emv/apduinfo.h" // APDUcode description
24 #include "emv/emvcore.h" // decodeTVL
25 #include "crypto/libpcrypto.h" // sha512hash
26 #include "emv/dump.h" // dump_buffer
29 #define SC_UPGRADE_FILES_DIRECTORY "sc_upgrade_firmware/"
31 static bool UseAlternativeSmartcardReader
= false; // default: use PM3 RDV40 Smartcard Slot (if available)
33 static int CmdHelp(const char *Cmd
);
35 static int usage_sm_raw(void) {
36 PrintAndLogEx(NORMAL
, "Usage: sc raw [h|r|c] d <0A 0B 0C ... hex>");
37 PrintAndLogEx(NORMAL
, " h : this help");
38 PrintAndLogEx(NORMAL
, " r : do not read response");
39 PrintAndLogEx(NORMAL
, " a : active smartcard without select (reset sc module)");
40 PrintAndLogEx(NORMAL
, " s : active smartcard with select (get ATR)");
41 PrintAndLogEx(NORMAL
, " t : executes TLV decoder if it possible");
42 PrintAndLogEx(NORMAL
, " 0 : use protocol T=0");
43 PrintAndLogEx(NORMAL
, " d <bytes> : bytes to send");
44 PrintAndLogEx(NORMAL
, "");
45 PrintAndLogEx(NORMAL
, "Examples:");
46 PrintAndLogEx(NORMAL
, " sc raw s 0 d 00a404000e315041592e5359532e4444463031 - `1PAY.SYS.DDF01` PSE directory with get ATR");
50 static int usage_sm_select(void) {
51 PrintAndLogEx(NORMAL
, "Usage: sc select [h|<reader name>] ");
52 PrintAndLogEx(NORMAL
, " h : this help");
53 PrintAndLogEx(NORMAL
, " <reader name> : a card reader's name, wildcards allowed, leave empty to pick from available readers");
54 PrintAndLogEx(NORMAL
, "");
55 PrintAndLogEx(NORMAL
, "Examples:");
56 PrintAndLogEx(NORMAL
, " sc select : list available card readers and pick");
57 PrintAndLogEx(NORMAL
, " sc select Gemalto* : select a connected Gemalto card reader" );
61 static int usage_sm_reader(void) {
62 PrintAndLogEx(NORMAL
, "Usage: sc reader [h|s]");
63 PrintAndLogEx(NORMAL
, " h : this help");
64 PrintAndLogEx(NORMAL
, " s : silent (no messages)");
65 PrintAndLogEx(NORMAL
, "");
66 PrintAndLogEx(NORMAL
, "Examples:");
67 PrintAndLogEx(NORMAL
, " sc reader");
71 static int usage_sm_info(void) {
72 PrintAndLogEx(NORMAL
, "Usage: s info [h|s]");
73 PrintAndLogEx(NORMAL
, " h : this help");
74 PrintAndLogEx(NORMAL
, " s : silent (no messages)");
75 PrintAndLogEx(NORMAL
, "");
76 PrintAndLogEx(NORMAL
, "Examples:");
77 PrintAndLogEx(NORMAL
, " sc info");
81 static int usage_sm_upgrade(void) {
82 PrintAndLogEx(NORMAL
, "Upgrade RDV4.0 Smartcard Socket Firmware");
83 PrintAndLogEx(NORMAL
, "Usage: sc upgrade f <file name>");
84 PrintAndLogEx(NORMAL
, " h : this help");
85 PrintAndLogEx(NORMAL
, " f <filename> : firmware file name");
86 PrintAndLogEx(NORMAL
, "");
87 PrintAndLogEx(NORMAL
, "Examples:");
88 PrintAndLogEx(NORMAL
, " sc upgrade f SIM010.BIN");
92 static int usage_sm_setclock(void) {
93 PrintAndLogEx(NORMAL
, "Usage: sc setclock [h] c <clockspeed>");
94 PrintAndLogEx(NORMAL
, " h : this help");
95 PrintAndLogEx(NORMAL
, " c <> : clockspeed (0 = 16mhz, 1=8mhz, 2=4mhz) ");
96 PrintAndLogEx(NORMAL
, "");
97 PrintAndLogEx(NORMAL
, "Examples:");
98 PrintAndLogEx(NORMAL
, " sc setclock c 2");
102 static int usage_sm_brute(void) {
103 PrintAndLogEx(NORMAL
, "Tries to bruteforce SFI, ");
104 PrintAndLogEx(NORMAL
, "Usage: sc brute [h]");
105 PrintAndLogEx(NORMAL
, " h : this help");
106 PrintAndLogEx(NORMAL
, "");
107 PrintAndLogEx(NORMAL
, "Examples:");
108 PrintAndLogEx(NORMAL
, " sc brute");
112 uint8_t GetATRTA1(uint8_t *atr
, size_t atrlen
) {
119 return 0x11; // default value is 0x11, corresponding to fmax=5 MHz, Fi=372, Di=1.
130 64, // b0111. This was RFU in ISO/IEC 7816-3:1997 and former. Some card readers or drivers may erroneously reject cards using this value
142 372, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock
161 4, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock
179 static int GetATRDi(uint8_t *atr
, size_t atrlen
) {
180 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
182 return DiArray
[TA1
& 0x0f]; // The 4 low-order bits of TA1 (4th MSbit to 1st LSbit) encode Di
185 static int GetATRFi(uint8_t *atr
, size_t atrlen
) {
186 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
188 return FiArray
[TA1
>> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi
191 static float GetATRF(uint8_t *atr
, size_t atrlen
) {
192 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
194 return FArray
[TA1
>> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi
197 static int PrintATR(uint8_t *atr
, size_t atrlen
) {
200 uint8_t K
= T0
& 0x0F;
201 uint8_t TD1
= 0, T1len
= 0, TD1len
= 0, TDilen
= 0;
202 bool protocol_T0_present
= true;
203 bool protocol_T15_present
= false;
206 PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr
[2 + T1len
]);
211 PrintAndLog("\t- TB1 (Deprecated: VPP requirements) [ 0x%02x ]", atr
[2 + T1len
]);
216 PrintAndLog("\t- TC1 (Extra delay between bytes required by card) [ 0x%02x ]", atr
[2 + T1len
]);
221 TD1
= atr
[2 + T1len
];
222 PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1
, TD1
& 0x0f);
223 protocol_T0_present
= false;
224 if ((TD1
& 0x0f) == 0) {
225 protocol_T0_present
= true;
227 if ((TD1
& 0x0f) == 15) {
228 protocol_T15_present
= true;
234 PrintAndLog("\t- TA2 (Specific protocol and parameters to be used after the ATR) [ 0x%02x ]", atr
[2 + T1len
+ TD1len
]);
238 PrintAndLog("\t- TB2 (Deprecated: VPP precise voltage requirement) [ 0x%02x ]", atr
[2 + T1len
+ TD1len
]);
242 PrintAndLog("\t- TC2 (Maximum waiting time for protocol T=0) [ 0x%02x ]", atr
[2 + T1len
+ TD1len
]);
246 uint8_t TDi
= atr
[2 + T1len
+ TD1len
];
247 PrintAndLog("\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi
, TDi
& 0x0f);
248 if ((TDi
& 0x0f) == 0) {
249 protocol_T0_present
= true;
251 if ((TDi
& 0x0f) == 15) {
252 protocol_T15_present
= true;
256 bool nextCycle
= true;
261 PrintAndLog("\t- TA%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
265 PrintAndLog("\t- TB%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
269 PrintAndLog("\t- TC%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
273 TDi
= atr
[2 + T1len
+ TD1len
+ TDilen
];
274 PrintAndLog("\t- TD%d [ 0x%02x ] Protocol T%d", vi
, TDi
, TDi
& 0x0f);
284 if (!protocol_T0_present
|| protocol_T15_present
) { // there is CRC Check Byte TCK
286 for (int i
= 1; i
< atrlen
; i
++)
290 PrintAndLogEx(WARNING
, "Check sum error. Must be 0 got 0x%02X", vxor
);
292 PrintAndLogEx(INFO
, "Check sum OK.");
296 PrintAndLogEx(WARNING
, "Not a direct convention [ 0x%02x ]", atr
[0]);
298 uint8_t calen
= 2 + T1len
+ TD1len
+ TDilen
+ K
;
300 if (atrlen
!= calen
&& atrlen
!= calen
+ 1) // may be CRC
301 PrintAndLogEx(ERR
, "ATR length error. len: %d, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen
, T1len
, TD1len
, TDilen
, K
);
304 PrintAndLogEx(INFO
, "\nHistorical bytes | len %02d | format %02x", K
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
307 PrintAndLogEx(INFO
, "\tHistorical bytes");
308 dump_buffer(&atr
[2 + T1len
+ TD1len
+ TDilen
], K
, NULL
, 1);
314 static bool smart_getATR(smart_card_atr_t
*card
)
316 if (UseAlternativeSmartcardReader
) {
317 return pcscGetATR(card
);
319 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
323 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
327 if (resp
.arg
[0] & 0xff) {
328 return resp
.arg
[0] & 0xFF;
331 memcpy(card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
337 static bool smart_select(bool silent
) {
339 smart_card_atr_t card
;
340 if (!smart_getATR(&card
)) {
341 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
346 PrintAndLogEx(INFO
, "ISO7816-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
353 static void smart_transmit(uint8_t *data
, uint32_t data_len
, uint32_t flags
, uint8_t *response
, int *response_len
, uint32_t max_response_len
)
355 // PrintAndLogEx(SUCCESS, "C-TPDU>>>> %s", sprint_hex(data, data_len));
356 if (UseAlternativeSmartcardReader
) {
357 *response_len
= max_response_len
;
358 pcscTransmit(data
, data_len
, flags
, response
, response_len
);
360 UsbCommand c
= {CMD_SMART_RAW
, {flags
, data_len
, 0}};
361 memcpy(c
.d
.asBytes
, data
, data_len
);
364 if (!WaitForResponseTimeout(CMD_ACK
, &c
, 2500)) {
365 PrintAndLogEx(WARNING
, "smart card response timeout");
370 *response_len
= c
.arg
[0];
371 if (*response_len
> 0) {
372 memcpy(response
, c
.d
.asBytes
, *response_len
);
376 if (*response_len
<= 0) {
377 PrintAndLogEx(WARNING
, "smart card response failed");
382 if (*response_len
< 2) {
383 // PrintAndLogEx(SUCCESS, "R-TPDU %02X | ", response[0]);
387 // PrintAndLogEx(SUCCESS, "R-TPDU<<<< %s", sprint_hex(response, *response_len));
388 // PrintAndLogEx(SUCCESS, "R-TPDU SW %02X%02X | %s", response[*response_len-2], response[*response_len-1], GetAPDUCodeDescription(response[*response_len-2], response[*response_len-1]));
392 static int CmdSmartSelect(const char *Cmd
)
394 const char *readername
;
396 if (tolower(param_getchar(Cmd
, 0)) == 'h') {
397 return usage_sm_select();
400 if (!PM3hasSmartcardSlot() && !pcscCheckForCardReaders()) {
401 PrintAndLogEx(WARNING
, "No Smartcard Readers available");
402 UseAlternativeSmartcardReader
= false;
407 if (param_getptr(Cmd
, &bg
, &en
, 0)) {
408 UseAlternativeSmartcardReader
= pcscSelectAlternativeCardReader(NULL
);
410 readername
= Cmd
+ bg
;
411 UseAlternativeSmartcardReader
= pcscSelectAlternativeCardReader(readername
);
418 static int CmdSmartRaw(const char *Cmd
) {
422 bool active_select
= false;
425 bool errors
= false, reply
= true, decodeTLV
= false, breakloop
= false;
426 uint8_t data
[ISO7816_MAX_FRAME_SIZE
] = {0x00};
428 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
429 switch (tolower(param_getchar(Cmd
, cmdp
))) {
430 case 'h': return usage_sm_raw();
440 active_select
= true;
452 switch (param_gethex_to_eol(Cmd
, cmdp
+1, data
, sizeof(data
), &hexlen
)) {
454 PrintAndLogEx(WARNING
, "Invalid HEX value.");
457 PrintAndLogEx(WARNING
, "Too many bytes. Max %d bytes", sizeof(data
));
460 PrintAndLogEx(WARNING
, "Hex must have even number of digits.");
468 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
478 if (errors
|| cmdp
== 0 ) return usage_sm_raw();
481 uint32_t protocol
= 0;
482 if (active
|| active_select
) {
489 protocol
= SC_RAW_T0
;
494 int response_len
= 0;
495 uint8_t *response
= NULL
;
497 response
= calloc(ISO7816_MAX_FRAME_SIZE
, sizeof(uint8_t));
502 smart_transmit(data
, hexlen
, flags
|protocol
, response
, &response_len
, ISO7816_MAX_FRAME_SIZE
);
504 // reading response from smart card
506 if ( response_len
< 0 ) {
511 if ( response
[0] == 0x6C ) {
512 data
[4] = response
[1];
513 smart_transmit(data
, hexlen
, protocol
, response
, &response_len
, ISO7816_MAX_FRAME_SIZE
);
517 if (decodeTLV
&& response_len
> 4)
518 TLVPrintFromBuffer(response
, response_len
-2);
526 int ExchangeAPDUSC(uint8_t *APDU
, int APDUlen
, bool activateCard
, bool leaveSignalON
, uint8_t *response
, int maxresponselen
, int *responselen
)
528 uint8_t TPDU
[ISO7816_MAX_FRAME_SIZE
];
535 uint32_t flags
= SC_RAW_T0
;
537 flags
|= SC_SELECT
| SC_CONNECT
;
540 if (APDUlen
== 4) { // Case 1
541 memcpy(TPDU
, APDU
, 4);
543 smart_transmit(TPDU
, 5, flags
, response
, responselen
, maxresponselen
);
544 } else if (APDUlen
== 5) { // Case 2 Short
545 smart_transmit(APDU
, 5, flags
, response
, responselen
, maxresponselen
);
546 if (response
[0] == 0x6C) { // wrong Le
547 uint16_t Le
= APDU
[4] ? APDU
[4] : 256;
548 uint8_t La
= response
[1];
549 memcpy(TPDU
, APDU
, 5);
551 smart_transmit(TPDU
, 5, SC_RAW_T0
, response
, responselen
, maxresponselen
);
552 if (Le
< La
&& *responselen
>= 0) {
553 response
[Le
] = response
[*responselen
-2];
554 response
[Le
+1] = response
[*responselen
-1];
555 *responselen
= Le
+ 2;
558 } else if (APDU
[4] != 0 && APDUlen
== 5 + APDU
[4]) { // Case 3 Short
559 smart_transmit(APDU
, APDUlen
, flags
, response
, responselen
, maxresponselen
);
560 } else if (APDU
[4] != 0 && APDUlen
== 5 + APDU
[4] + 1) { // Case 4 Short
561 smart_transmit(APDU
, APDUlen
-1, flags
, response
, responselen
, maxresponselen
);
562 if (response
[0] == 0x90 && response
[1] == 0x00) {
563 uint8_t Le
= APDU
[APDUlen
-1];
564 uint8_t get_response
[5] = {0x00, ISO7816_GET_RESPONSE
, 0x00, 0x00, Le
};
565 return ExchangeAPDUSC(get_response
, 5, false, leaveSignalON
, response
, maxresponselen
, responselen
);
567 } else { // Long Cases not yet implemented
568 PrintAndLogEx(ERR
, "Long APDUs not yet implemented");
572 if (*responselen
< 0 ) {
580 static int CmdSmartUpgrade(const char *Cmd
) {
582 PrintAndLogEx(NORMAL
, "");
583 PrintAndLogEx(WARNING
, "WARNING - RDV4.0 Smartcard Socket Firmware upgrade.");
584 PrintAndLogEx(WARNING
, "A dangerous command, do wrong and you will brick the smart card socket");
585 PrintAndLogEx(NORMAL
, "");
588 char filename
[FILE_PATH_SIZE
] = {0};
592 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
593 switch (tolower(param_getchar(Cmd
, cmdp
))) {
595 //File handling and reading
596 if ( param_getstr(Cmd
, cmdp
+1, filename
, FILE_PATH_SIZE
) >= FILE_PATH_SIZE
) {
597 PrintAndLogEx(FAILED
, "Filename too long");
604 return usage_sm_upgrade();
606 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
613 if (errors
|| cmdp
== 0 ) return usage_sm_upgrade();
615 if (strchr(filename
, '\\') || strchr(filename
, '/')) {
616 PrintAndLogEx(FAILED
, "Filename must not contain \\ or /. Firmware file will be found in client/sc_upgrade_firmware directory.");
620 char sc_upgrade_file_path
[strlen(get_my_executable_directory()) + strlen(SC_UPGRADE_FILES_DIRECTORY
) + strlen(filename
) + 1];
621 strcpy(sc_upgrade_file_path
, get_my_executable_directory());
622 strcat(sc_upgrade_file_path
, SC_UPGRADE_FILES_DIRECTORY
);
623 strcat(sc_upgrade_file_path
, filename
);
624 if (strlen(sc_upgrade_file_path
) >= FILE_PATH_SIZE
) {
625 PrintAndLogEx(FAILED
, "Filename too long");
629 char sha512filename
[FILE_PATH_SIZE
] = {'\0'};
630 char *bin_extension
= filename
;
631 char *dot_position
= NULL
;
632 while ((dot_position
= strchr(bin_extension
, '.')) != NULL
) {
633 bin_extension
= dot_position
+ 1;
635 if (!strcmp(bin_extension
, "BIN")
637 || !strcmp(bin_extension
, "bin")
640 memcpy(sha512filename
, filename
, strlen(filename
) - strlen("bin"));
641 strcat(sha512filename
, "sha512.txt");
643 PrintAndLogEx(FAILED
, "Filename extension of Firmware Upgrade File must be .BIN");
647 PrintAndLogEx(INFO
, "Checking integrity using SHA512 File %s ...", sha512filename
);
648 char sc_upgrade_sha512file_path
[strlen(get_my_executable_directory()) + strlen(SC_UPGRADE_FILES_DIRECTORY
) + strlen(sha512filename
) + 1];
649 strcpy(sc_upgrade_sha512file_path
, get_my_executable_directory());
650 strcat(sc_upgrade_sha512file_path
, SC_UPGRADE_FILES_DIRECTORY
);
651 strcat(sc_upgrade_sha512file_path
, sha512filename
);
652 if (strlen(sc_upgrade_sha512file_path
) >= FILE_PATH_SIZE
) {
653 PrintAndLogEx(FAILED
, "Filename too long");
657 // load firmware file
658 f
= fopen(sc_upgrade_file_path
, "rb");
660 PrintAndLogEx(FAILED
, "Firmware file not found or locked.");
664 // get filesize in order to malloc memory
665 fseek(f
, 0, SEEK_END
);
666 size_t fsize
= ftell(f
);
667 fseek(f
, 0, SEEK_SET
);
670 PrintAndLogEx(FAILED
, "Could not determine size of firmware file");
675 uint8_t *dump
= calloc(fsize
, sizeof(uint8_t));
677 PrintAndLogEx(FAILED
, "Could not allocate memory for firmware");
682 size_t firmware_size
= fread(dump
, 1, fsize
, f
);
687 f
= fopen(sc_upgrade_sha512file_path
, "rb");
689 PrintAndLogEx(FAILED
, "SHA-512 file not found or locked.");
693 // get filesize in order to malloc memory
694 fseek(f
, 0, SEEK_END
);
696 fseek(f
, 0, SEEK_SET
);
699 PrintAndLogEx(FAILED
, "Could not determine size of SHA-512 file");
705 PrintAndLogEx(FAILED
, "SHA-512 file too short");
710 char hashstring
[129];
711 size_t bytes_read
= fread(hashstring
, 1, 128, f
);
712 hashstring
[128] = '\0';
718 if (bytes_read
!= 128 || param_gethex(hashstring
, 0, hash1
, 128)) {
719 PrintAndLogEx(FAILED
, "Couldn't read SHA-512 file");
724 if (sha512hash(dump
, firmware_size
, hash2
)) {
725 PrintAndLogEx(FAILED
, "Couldn't calculate SHA-512 of Firmware");
729 if (memcmp(hash1
, hash2
, 64)) {
730 PrintAndLogEx(FAILED
, "Couldn't verify integrity of Firmware file (wrong SHA-512)");
734 PrintAndLogEx(SUCCESS
, "RDV4.0 Smartcard Socket Firmware uploading to PM3");
738 uint32_t bytes_sent
= 0;
739 uint32_t bytes_remaining
= firmware_size
;
741 while (bytes_remaining
> 0){
742 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
743 UsbCommand c
= {CMD_SMART_UPLOAD
, {index
+ bytes_sent
, bytes_in_packet
, 0}};
745 // Fill usb bytes with 0xFF
746 memset(c
.d
.asBytes
, 0xFF, USB_CMD_DATA_SIZE
);
747 memcpy(c
.d
.asBytes
, dump
+ bytes_sent
, bytes_in_packet
);
748 clearCommandBuffer();
750 if ( !WaitForResponseTimeout(CMD_ACK
, NULL
, 2000) ) {
751 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
756 bytes_remaining
-= bytes_in_packet
;
757 bytes_sent
+= bytes_in_packet
;
758 printf("."); fflush(stdout
);
762 PrintAndLogEx(SUCCESS
, "RDV4.0 Smartcard Socket Firmware updating, don\'t turn off your PM3!");
764 // trigger the firmware upgrade
765 UsbCommand c
= {CMD_SMART_UPGRADE
, {firmware_size
, 0, 0}};
766 clearCommandBuffer();
769 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
770 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
773 if ( (resp
.arg
[0] & 0xFF ) )
774 PrintAndLogEx(SUCCESS
, "RDV4.0 Smartcard Socket Firmware upgraded successful");
776 PrintAndLogEx(FAILED
, "RDV4.0 Smartcard Socket Firmware Upgrade failed");
781 static int CmdSmartInfo(const char *Cmd
){
783 bool errors
= false, silent
= false;
785 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
786 switch (tolower(param_getchar(Cmd
, cmdp
))) {
787 case 'h': return usage_sm_info();
792 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
800 if (errors
) return usage_sm_info();
802 smart_card_atr_t card
;
803 if (!smart_getATR(&card
)) {
804 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
809 PrintAndLogEx(INFO
, "--- Smartcard Information ---------");
810 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
811 PrintAndLogEx(INFO
, "ISO7618-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
812 PrintAndLogEx(INFO
, "\nhttp://smartcard-atr.appspot.com/parse?ATR=%s", sprint_hex_inrow(card
.atr
, card
.atr_len
) );
815 PrintAndLogEx(NORMAL
, "");
816 PrintAndLogEx(INFO
, "ATR");
817 PrintATR(card
.atr
, card
.atr_len
);
819 // print D/F (brom byte TA1 or defaults)
820 PrintAndLogEx(NORMAL
, "");
821 PrintAndLogEx(INFO
, "D/F (TA1)");
822 int Di
= GetATRDi(card
.atr
, card
.atr_len
);
823 int Fi
= GetATRFi(card
.atr
, card
.atr_len
);
824 float F
= GetATRF(card
.atr
, card
.atr_len
);
825 if (GetATRTA1(card
.atr
, card
.atr_len
) == 0x11)
826 PrintAndLogEx(INFO
, "Using default values...");
828 PrintAndLogEx(NORMAL
, "\t- Di=%d", Di
);
829 PrintAndLogEx(NORMAL
, "\t- Fi=%d", Fi
);
830 PrintAndLogEx(NORMAL
, "\t- F=%.1f MHz", F
);
833 PrintAndLogEx(NORMAL
, "\t- Cycles/ETU=%d", Fi
/Di
);
834 PrintAndLogEx(NORMAL
, "\t- %.1f bits/sec at 4MHz", (float)4000000 / (Fi
/Di
));
835 PrintAndLogEx(NORMAL
, "\t- %.1f bits/sec at Fmax=%.1fMHz", (F
* 1000000) / (Fi
/Di
), F
);
837 PrintAndLogEx(WARNING
, "\t- Di or Fi is RFU.");
843 int CmdSmartReader(const char *Cmd
){
845 bool errors
= false, silent
= false;
847 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
848 switch (tolower(param_getchar(Cmd
, cmdp
))) {
849 case 'h': return usage_sm_reader();
854 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
862 if (errors
) return usage_sm_reader();
864 smart_card_atr_t card
;
865 if (!smart_getATR(&card
)) {
866 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
870 PrintAndLogEx(INFO
, "ISO7816-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
875 static int CmdSmartSetClock(const char *Cmd
){
879 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
880 switch (tolower(param_getchar(Cmd
, cmdp
))) {
881 case 'h': return usage_sm_setclock();
883 clock
= param_get8ex(Cmd
, cmdp
+1, 2, 10);
890 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
897 if (errors
|| cmdp
== 0) return usage_sm_setclock();
899 UsbCommand c
= {CMD_SMART_SETCLOCK
, {clock
, 0, 0}};
900 clearCommandBuffer();
903 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
904 PrintAndLogEx(WARNING
, "smart card select failed");
908 uint8_t isok
= resp
.arg
[0] & 0xFF;
910 PrintAndLogEx(WARNING
, "smart card set clock failed");
916 PrintAndLogEx(SUCCESS
, "Clock changed to 16mhz giving 10800 baudrate");
919 PrintAndLogEx(SUCCESS
, "Clock changed to 8mhz giving 21600 baudrate");
922 PrintAndLogEx(SUCCESS
, "Clock changed to 4mhz giving 86400 baudrate");
931 static int CmdSmartList(const char *Cmd
) {
937 static int CmdSmartBruteforceSFI(const char *Cmd
) {
939 char ctmp
= tolower(param_getchar(Cmd
, 0));
940 if (ctmp
== 'h') return usage_sm_brute();
942 uint8_t data
[5] = {0x00, 0xB2, 0x00, 0x00, 0x00};
944 PrintAndLogEx(INFO
, "Selecting card");
945 if ( !smart_select(false) ) {
949 PrintAndLogEx(INFO
, "Selecting PSE aid");
950 CmdSmartRaw("s 0 t d 00a404000e325041592e5359532e4444463031");
951 CmdSmartRaw("0 t d 00a4040007a000000004101000"); // mastercard
952 // CmdSmartRaw("0 t d 00a4040007a0000000031010"); // visa
954 PrintAndLogEx(INFO
, "starting");
956 int response_len
= 0;
957 uint8_t* response
= malloc(ISO7816_MAX_FRAME_SIZE
);
961 for (uint8_t i
=1; i
< 4; i
++) {
962 for (int p1
=1; p1
< 5; p1
++) {
965 data
[3] = (i
<< 3) + 4;
967 smart_transmit(data
, sizeof(data
), SC_RAW_T0
, response
, &response_len
, ISO7816_MAX_FRAME_SIZE
);
969 if ( response
[0] == 0x6C ) {
970 data
[4] = response
[1];
971 smart_transmit(data
, sizeof(data
), SC_RAW_T0
, response
, &response_len
, ISO7816_MAX_FRAME_SIZE
);
974 if (response_len
> 4)
975 TLVPrintFromBuffer(response
+1, response_len
-3);
979 memset(response
, 0x00, ISO7816_MAX_FRAME_SIZE
);
986 static command_t CommandTable
[] = {
987 {"help", CmdHelp
, 1, "This help"},
988 {"select", CmdSmartSelect
, 1, "Select the Smartcard Reader to use"},
989 {"list", CmdSmartList
, 1, "List ISO 7816 history"},
990 {"info", CmdSmartInfo
, 1, "Tag information"},
991 {"reader", CmdSmartReader
, 1, "Act like an IS07816 reader"},
992 {"raw", CmdSmartRaw
, 1, "Send raw hex data to tag"},
993 {"upgrade", CmdSmartUpgrade
, 0, "Upgrade firmware"},
994 {"setclock", CmdSmartSetClock
, 1, "Set clock speed"},
995 {"brute", CmdSmartBruteforceSFI
, 1, "Bruteforce SFI"},
996 {NULL
, NULL
, 0, NULL
}
1000 int CmdSmartcard(const char *Cmd
) {
1001 clearCommandBuffer();
1002 CmdsParse(CommandTable
, Cmd
);
1007 static int CmdHelp(const char *Cmd
) {
1008 CmdsHelp(CommandTable
);