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` PPSE directory with get ATR");
47 PrintAndLogEx(NORMAL
, " sc raw 0 d 00a404000e325041592e5359532e4444463031 - `2PAY.SYS.DDF01` PPSE directory");
51 static int usage_sm_select(void) {
52 PrintAndLogEx(NORMAL
, "Usage: sc select [h|<reader name>] ");
53 PrintAndLogEx(NORMAL
, " h : this help");
54 PrintAndLogEx(NORMAL
, " <reader name> : a card reader's name, wildcards allowed, leave empty to pick from available readers");
55 PrintAndLogEx(NORMAL
, "");
56 PrintAndLogEx(NORMAL
, "Examples:");
57 PrintAndLogEx(NORMAL
, " sc select : list available card readers and pick");
58 PrintAndLogEx(NORMAL
, " sc select Gemalto* : select a connected Gemalto card reader" );
62 static int usage_sm_reader(void) {
63 PrintAndLogEx(NORMAL
, "Usage: sc reader [h|s]");
64 PrintAndLogEx(NORMAL
, " h : this help");
65 PrintAndLogEx(NORMAL
, " s : silent (no messages)");
66 PrintAndLogEx(NORMAL
, "");
67 PrintAndLogEx(NORMAL
, "Examples:");
68 PrintAndLogEx(NORMAL
, " sc reader");
72 static int usage_sm_info(void) {
73 PrintAndLogEx(NORMAL
, "Usage: s info [h|s]");
74 PrintAndLogEx(NORMAL
, " h : this help");
75 PrintAndLogEx(NORMAL
, " s : silent (no messages)");
76 PrintAndLogEx(NORMAL
, "");
77 PrintAndLogEx(NORMAL
, "Examples:");
78 PrintAndLogEx(NORMAL
, " sc info");
82 static int usage_sm_upgrade(void) {
83 PrintAndLogEx(NORMAL
, "Upgrade RDV4.0 Smartcard Socket Firmware");
84 PrintAndLogEx(NORMAL
, "Usage: sc upgrade f <file name>");
85 PrintAndLogEx(NORMAL
, " h : this help");
86 PrintAndLogEx(NORMAL
, " f <filename> : firmware file name");
87 PrintAndLogEx(NORMAL
, "");
88 PrintAndLogEx(NORMAL
, "Examples:");
89 PrintAndLogEx(NORMAL
, " sc upgrade f SIM010.BIN");
93 static int usage_sm_setclock(void) {
94 PrintAndLogEx(NORMAL
, "Usage: sc setclock [h] c <clockspeed>");
95 PrintAndLogEx(NORMAL
, " h : this help");
96 PrintAndLogEx(NORMAL
, " c <> : clockspeed (0 = 16mhz, 1=8mhz, 2=4mhz) ");
97 PrintAndLogEx(NORMAL
, "");
98 PrintAndLogEx(NORMAL
, "Examples:");
99 PrintAndLogEx(NORMAL
, " sc setclock c 2");
103 static int usage_sm_brute(void) {
104 PrintAndLogEx(NORMAL
, "Tries to bruteforce SFI, ");
105 PrintAndLogEx(NORMAL
, "Usage: sc brute [h]");
106 PrintAndLogEx(NORMAL
, " h : this help");
107 PrintAndLogEx(NORMAL
, "");
108 PrintAndLogEx(NORMAL
, "Examples:");
109 PrintAndLogEx(NORMAL
, " sc brute");
113 uint8_t GetATRTA1(uint8_t *atr
, size_t atrlen
) {
120 return 0x11; // default value is 0x11, corresponding to fmax=5 MHz, Fi=372, Di=1.
131 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
143 372, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock
162 4, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock
180 int GetATRDi(uint8_t *atr
, size_t atrlen
) {
181 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
183 return DiArray
[TA1
& 0x0f]; // The 4 low-order bits of TA1 (4th MSbit to 1st LSbit) encode Di
186 int GetATRFi(uint8_t *atr
, size_t atrlen
) {
187 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
189 return FiArray
[TA1
>> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi
192 float GetATRF(uint8_t *atr
, size_t atrlen
) {
193 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
195 return FArray
[TA1
>> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi
198 static int PrintATR(uint8_t *atr
, size_t atrlen
) {
201 uint8_t K
= T0
& 0x0F;
202 uint8_t TD1
= 0, T1len
= 0, TD1len
= 0, TDilen
= 0;
203 bool protocol_T0_present
= true;
204 bool protocol_T15_present
= false;
207 PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr
[2 + T1len
]);
212 PrintAndLog("\t- TB1 (Deprecated: VPP requirements) [ 0x%02x ]", atr
[2 + T1len
]);
217 PrintAndLog("\t- TC1 (Extra delay between bytes required by card) [ 0x%02x ]", atr
[2 + T1len
]);
222 TD1
= atr
[2 + T1len
];
223 PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1
, TD1
& 0x0f);
224 protocol_T0_present
= false;
225 if ((TD1
& 0x0f) == 0) {
226 protocol_T0_present
= true;
228 if ((TD1
& 0x0f) == 15) {
229 protocol_T15_present
= true;
235 PrintAndLog("\t- TA2 (Specific protocol and parameters to be used after the ATR) [ 0x%02x ]", atr
[2 + T1len
+ TD1len
]);
239 PrintAndLog("\t- TB2 (Deprecated: VPP precise voltage requirement) [ 0x%02x ]", atr
[2 + T1len
+ TD1len
]);
243 PrintAndLog("\t- TC2 (Maximum waiting time for protocol T=0) [ 0x%02x ]", atr
[2 + T1len
+ TD1len
]);
247 uint8_t TDi
= atr
[2 + T1len
+ TD1len
];
248 PrintAndLog("\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi
, TDi
& 0x0f);
249 if ((TDi
& 0x0f) == 0) {
250 protocol_T0_present
= true;
252 if ((TDi
& 0x0f) == 15) {
253 protocol_T15_present
= true;
257 bool nextCycle
= true;
262 PrintAndLog("\t- TA%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
266 PrintAndLog("\t- TB%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
270 PrintAndLog("\t- TC%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
274 TDi
= atr
[2 + T1len
+ TD1len
+ TDilen
];
275 PrintAndLog("\t- TD%d [ 0x%02x ] Protocol T%d", vi
, TDi
, TDi
& 0x0f);
285 if (!protocol_T0_present
|| protocol_T15_present
) { // there is CRC Check Byte TCK
287 for (int i
= 1; i
< atrlen
; i
++)
291 PrintAndLogEx(WARNING
, "Check sum error. Must be 0 got 0x%02X", vxor
);
293 PrintAndLogEx(INFO
, "Check sum OK.");
297 PrintAndLogEx(WARNING
, "Not a direct convention [ 0x%02x ]", atr
[0]);
299 uint8_t calen
= 2 + T1len
+ TD1len
+ TDilen
+ K
;
301 if (atrlen
!= calen
&& atrlen
!= calen
+ 1) // may be CRC
302 PrintAndLogEx(ERR
, "ATR length error. len: %d, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen
, T1len
, TD1len
, TDilen
, K
);
305 PrintAndLogEx(INFO
, "\nHistorical bytes | len %02d | format %02x", K
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
308 PrintAndLogEx(INFO
, "\tHistorical bytes");
309 dump_buffer(&atr
[2 + T1len
+ TD1len
+ TDilen
], K
, NULL
, 1);
315 static bool smart_getATR(smart_card_atr_t
*card
)
317 if (UseAlternativeSmartcardReader
) {
318 return pcscGetATR(card
);
320 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
324 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
328 if (resp
.arg
[0] & 0xff) {
329 return resp
.arg
[0] & 0xFF;
332 memcpy(card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
338 static bool smart_select(bool silent
) {
340 smart_card_atr_t card
;
341 if (!smart_getATR(&card
)) {
342 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
347 PrintAndLogEx(INFO
, "ISO7816-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
353 static int smart_wait(uint8_t *data
) {
355 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2500)) {
356 PrintAndLogEx(WARNING
, "smart card response timeout");
360 uint32_t len
= resp
.arg
[0];
362 PrintAndLogEx(WARNING
, "smart card response failed");
365 memcpy(data
, resp
.d
.asBytes
, len
);
367 PrintAndLogEx(SUCCESS
, "%02X%02X | %s", data
[len
- 2], data
[len
- 1], GetAPDUCodeDescription(data
[len
- 2], data
[len
- 1]));
369 PrintAndLogEx(SUCCESS
, " %d | %s", len
, sprint_hex_inrow_ex(data
, len
, 8));
375 static int smart_response(uint8_t *data
) {
377 int datalen
= smart_wait(data
);
378 bool needGetData
= false;
384 if ( data
[datalen
- 2] == 0x61 || data
[datalen
- 2] == 0x9F ) {
389 int len
= data
[datalen
- 1];
390 PrintAndLogEx(INFO
, "Requesting 0x%02X bytes response", len
);
391 uint8_t getstatus
[] = {0x00, ISO7816_GETSTATUS
, 0x00, 0x00, len
};
392 UsbCommand cStatus
= {CMD_SMART_RAW
, {SC_RAW
, sizeof(getstatus
), 0}};
393 memcpy(cStatus
.d
.asBytes
, getstatus
, sizeof(getstatus
) );
394 clearCommandBuffer();
395 SendCommand(&cStatus
);
397 datalen
= smart_wait(data
);
404 if (datalen
!= len
+ 2) {
406 if (datalen
== len
+ 2 + 1) { // 2 - response, 1 - ACK
407 if (data
[0] != ISO7816_GETSTATUS
) {
408 PrintAndLogEx(ERR
, "GetResponse ACK error. len 0x%x | data[0] %02X", len
, data
[0]);
414 memmove(data
, &data
[1], datalen
);
417 PrintAndLogEx(WARNING
, "GetResponse wrong length. Must be 0x%02X got 0x%02X", len
, datalen
- 3);
427 int CmdSmartSelect(const char *Cmd
) {
429 const char *readername
;
431 if (tolower(param_getchar(Cmd
, 0)) == 'h') {
432 return usage_sm_select();
435 if (!PM3hasSmartcardSlot() && !pcscCheckForCardReaders()) {
436 PrintAndLogEx(WARNING
, "No Smartcard Readers available");
437 UseAlternativeSmartcardReader
= false;
442 if (param_getptr(Cmd
, &bg
, &en
, 0)) {
443 UseAlternativeSmartcardReader
= pcscSelectAlternativeCardReader(NULL
);
445 readername
= Cmd
+ bg
;
446 UseAlternativeSmartcardReader
= pcscSelectAlternativeCardReader(readername
);
452 int CmdSmartRaw(const char *Cmd
) {
456 bool active_select
= false;
459 bool errors
= false, reply
= true, decodeTLV
= false, breakloop
= false;
460 uint8_t data
[USB_CMD_DATA_SIZE
] = {0x00};
462 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
463 switch (tolower(param_getchar(Cmd
, cmdp
))) {
464 case 'h': return usage_sm_raw();
474 active_select
= true;
486 switch (param_gethex_to_eol(Cmd
, cmdp
+1, data
, sizeof(data
), &hexlen
)) {
488 PrintAndLogEx(WARNING
, "Invalid HEX value.");
491 PrintAndLogEx(WARNING
, "Too many bytes. Max %d bytes", sizeof(data
));
494 PrintAndLogEx(WARNING
, "Hex must have even number of digits.");
502 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
512 if (errors
|| cmdp
== 0 ) return usage_sm_raw();
516 UsbCommand c
= {CMD_SMART_RAW
, {0, hexlen
, 0}};
518 if (active
|| active_select
) {
519 c
.arg
[0] |= SC_CONNECT
;
521 c
.arg
[0] |= SC_SELECT
;
526 c
.arg
[0] |= SC_RAW_T0
;
531 memcpy(c
.d
.asBytes
, data
, hexlen
);
532 clearCommandBuffer();
535 // reading response from smart card
538 uint8_t* buf
= calloc(USB_CMD_DATA_SIZE
, sizeof(uint8_t));
542 int len
= smart_response(buf
);
548 if ( buf
[0] == 0x6C ) {
551 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
552 clearCommandBuffer();
554 len
= smart_response(buf
);
559 if (decodeTLV
&& len
> 4)
560 TLVPrintFromBuffer(buf
, len
-2);
567 int ExchangeAPDUSC(uint8_t *datain
, int datainlen
, bool activateCard
, bool leaveSignalON
, uint8_t *dataout
, int maxdataoutlen
, int *dataoutlen
) {
573 PrintAndLogEx(DEBUG
, "APDU SC");
575 UsbCommand c
= {CMD_SMART_RAW
, {SC_RAW_T0
, datainlen
, 0}};
577 c
.arg
[0] |= SC_SELECT
| SC_CONNECT
;
579 memcpy(c
.d
.asBytes
, datain
, datainlen
);
580 clearCommandBuffer();
583 int len
= smart_response(dataout
);
590 if (len
> 1 && dataout
[len
- 2] == 0x6c && datainlen
> 4) {
591 UsbCommand c2
= {CMD_SMART_RAW
, {SC_RAW_T0
, datainlen
, 0}};
592 memcpy(c2
.d
.asBytes
, datain
, 5);
594 // transfer length via T=0
595 c2
.d
.asBytes
[4] = dataout
[len
- 1];
597 clearCommandBuffer();
600 len
= smart_response(dataout
);
608 int CmdSmartUpgrade(const char *Cmd
) {
610 PrintAndLogEx(NORMAL
, "");
611 PrintAndLogEx(WARNING
, "WARNING - RDV4.0 Smartcard Socket Firmware upgrade.");
612 PrintAndLogEx(WARNING
, "A dangerous command, do wrong and you will brick the smart card socket");
613 PrintAndLogEx(NORMAL
, "");
616 char filename
[FILE_PATH_SIZE
] = {0};
620 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
621 switch (tolower(param_getchar(Cmd
, cmdp
))) {
623 //File handling and reading
624 if ( param_getstr(Cmd
, cmdp
+1, filename
, FILE_PATH_SIZE
) >= FILE_PATH_SIZE
) {
625 PrintAndLogEx(FAILED
, "Filename too long");
632 return usage_sm_upgrade();
634 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
641 if (errors
|| cmdp
== 0 ) return usage_sm_upgrade();
643 if (strchr(filename
, '\\') || strchr(filename
, '/')) {
644 PrintAndLogEx(FAILED
, "Filename must not contain \\ or /. Firmware file will be found in client/sc_upgrade_firmware directory.");
648 char sc_upgrade_file_path
[strlen(get_my_executable_directory()) + strlen(SC_UPGRADE_FILES_DIRECTORY
) + strlen(filename
) + 1];
649 strcpy(sc_upgrade_file_path
, get_my_executable_directory());
650 strcat(sc_upgrade_file_path
, SC_UPGRADE_FILES_DIRECTORY
);
651 strcat(sc_upgrade_file_path
, filename
);
652 if (strlen(sc_upgrade_file_path
) >= FILE_PATH_SIZE
) {
653 PrintAndLogEx(FAILED
, "Filename too long");
657 char sha512filename
[FILE_PATH_SIZE
] = {'\0'};
658 char *bin_extension
= filename
;
659 char *dot_position
= NULL
;
660 while ((dot_position
= strchr(bin_extension
, '.')) != NULL
) {
661 bin_extension
= dot_position
+ 1;
663 if (!strcmp(bin_extension
, "BIN")
665 || !strcmp(bin_extension
, "bin")
668 memcpy(sha512filename
, filename
, strlen(filename
) - strlen("bin"));
669 strcat(sha512filename
, "sha512.txt");
671 PrintAndLogEx(FAILED
, "Filename extension of Firmware Upgrade File must be .BIN");
675 PrintAndLogEx(INFO
, "Checking integrity using SHA512 File %s ...", sha512filename
);
676 char sc_upgrade_sha512file_path
[strlen(get_my_executable_directory()) + strlen(SC_UPGRADE_FILES_DIRECTORY
) + strlen(sha512filename
) + 1];
677 strcpy(sc_upgrade_sha512file_path
, get_my_executable_directory());
678 strcat(sc_upgrade_sha512file_path
, SC_UPGRADE_FILES_DIRECTORY
);
679 strcat(sc_upgrade_sha512file_path
, sha512filename
);
680 if (strlen(sc_upgrade_sha512file_path
) >= FILE_PATH_SIZE
) {
681 PrintAndLogEx(FAILED
, "Filename too long");
685 // load firmware file
686 f
= fopen(sc_upgrade_file_path
, "rb");
688 PrintAndLogEx(FAILED
, "Firmware file not found or locked.");
692 // get filesize in order to malloc memory
693 fseek(f
, 0, SEEK_END
);
694 size_t fsize
= ftell(f
);
695 fseek(f
, 0, SEEK_SET
);
698 PrintAndLogEx(FAILED
, "Could not determine size of firmware file");
703 uint8_t *dump
= calloc(fsize
, sizeof(uint8_t));
705 PrintAndLogEx(FAILED
, "Could not allocate memory for firmware");
710 size_t firmware_size
= fread(dump
, 1, fsize
, f
);
715 f
= fopen(sc_upgrade_sha512file_path
, "rb");
717 PrintAndLogEx(FAILED
, "SHA-512 file not found or locked.");
721 // get filesize in order to malloc memory
722 fseek(f
, 0, SEEK_END
);
724 fseek(f
, 0, SEEK_SET
);
727 PrintAndLogEx(FAILED
, "Could not determine size of SHA-512 file");
733 PrintAndLogEx(FAILED
, "SHA-512 file too short");
738 char hashstring
[129];
739 size_t bytes_read
= fread(hashstring
, 1, 128, f
);
740 hashstring
[128] = '\0';
746 if (bytes_read
!= 128 || param_gethex(hashstring
, 0, hash1
, 128)) {
747 PrintAndLogEx(FAILED
, "Couldn't read SHA-512 file");
752 if (sha512hash(dump
, firmware_size
, hash2
)) {
753 PrintAndLogEx(FAILED
, "Couldn't calculate SHA-512 of Firmware");
757 if (memcmp(hash1
, hash2
, 64)) {
758 PrintAndLogEx(FAILED
, "Couldn't verify integrity of Firmware file (wrong SHA-512)");
762 PrintAndLogEx(SUCCESS
, "RDV4.0 Smartcard Socket Firmware uploading to PM3");
766 uint32_t bytes_sent
= 0;
767 uint32_t bytes_remaining
= firmware_size
;
769 while (bytes_remaining
> 0){
770 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
771 UsbCommand c
= {CMD_SMART_UPLOAD
, {index
+ bytes_sent
, bytes_in_packet
, 0}};
773 // Fill usb bytes with 0xFF
774 memset(c
.d
.asBytes
, 0xFF, USB_CMD_DATA_SIZE
);
775 memcpy(c
.d
.asBytes
, dump
+ bytes_sent
, bytes_in_packet
);
776 clearCommandBuffer();
778 if ( !WaitForResponseTimeout(CMD_ACK
, NULL
, 2000) ) {
779 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
784 bytes_remaining
-= bytes_in_packet
;
785 bytes_sent
+= bytes_in_packet
;
786 printf("."); fflush(stdout
);
790 PrintAndLogEx(SUCCESS
, "RDV4.0 Smartcard Socket Firmware updating, don\'t turn off your PM3!");
792 // trigger the firmware upgrade
793 UsbCommand c
= {CMD_SMART_UPGRADE
, {firmware_size
, 0, 0}};
794 clearCommandBuffer();
797 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
798 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
801 if ( (resp
.arg
[0] & 0xFF ) )
802 PrintAndLogEx(SUCCESS
, "RDV4.0 Smartcard Socket Firmware upgraded successful");
804 PrintAndLogEx(FAILED
, "RDV4.0 Smartcard Socket Firmware Upgrade failed");
808 int CmdSmartInfo(const char *Cmd
){
810 bool errors
= false, silent
= false;
812 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
813 switch (tolower(param_getchar(Cmd
, cmdp
))) {
814 case 'h': return usage_sm_info();
819 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
827 if (errors
) return usage_sm_info();
829 smart_card_atr_t card
;
830 if (!smart_getATR(&card
)) {
831 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
836 PrintAndLogEx(INFO
, "--- Smartcard Information ---------");
837 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
838 PrintAndLogEx(INFO
, "ISO7618-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
839 PrintAndLogEx(INFO
, "\nhttp://smartcard-atr.appspot.com/parse?ATR=%s", sprint_hex_inrow(card
.atr
, card
.atr_len
) );
842 PrintAndLogEx(NORMAL
, "");
843 PrintAndLogEx(INFO
, "ATR");
844 PrintATR(card
.atr
, card
.atr_len
);
846 // print D/F (brom byte TA1 or defaults)
847 PrintAndLogEx(NORMAL
, "");
848 PrintAndLogEx(INFO
, "D/F (TA1)");
849 int Di
= GetATRDi(card
.atr
, card
.atr_len
);
850 int Fi
= GetATRFi(card
.atr
, card
.atr_len
);
851 float F
= GetATRF(card
.atr
, card
.atr_len
);
852 if (GetATRTA1(card
.atr
, card
.atr_len
) == 0x11)
853 PrintAndLogEx(INFO
, "Using default values...");
855 PrintAndLogEx(NORMAL
, "\t- Di=%d", Di
);
856 PrintAndLogEx(NORMAL
, "\t- Fi=%d", Fi
);
857 PrintAndLogEx(NORMAL
, "\t- F=%.1f MHz", F
);
860 PrintAndLogEx(NORMAL
, "\t- Cycles/ETU=%d", Fi
/Di
);
861 PrintAndLogEx(NORMAL
, "\t- %.1f bits/sec at 4MHz", (float)4000000 / (Fi
/Di
));
862 PrintAndLogEx(NORMAL
, "\t- %.1f bits/sec at Fmax=%.1fMHz", (F
* 1000000) / (Fi
/Di
), F
);
864 PrintAndLogEx(WARNING
, "\t- Di or Fi is RFU.");
870 int CmdSmartReader(const char *Cmd
){
872 bool errors
= false, silent
= false;
874 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
875 switch (tolower(param_getchar(Cmd
, cmdp
))) {
876 case 'h': return usage_sm_reader();
881 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
889 if (errors
) return usage_sm_reader();
891 smart_card_atr_t card
;
892 if (!smart_getATR(&card
)) {
893 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
897 PrintAndLogEx(INFO
, "ISO7816-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
901 int CmdSmartSetClock(const char *Cmd
){
905 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
906 switch (tolower(param_getchar(Cmd
, cmdp
))) {
907 case 'h': return usage_sm_setclock();
909 clock
= param_get8ex(Cmd
, cmdp
+1, 2, 10);
916 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
923 if (errors
|| cmdp
== 0) return usage_sm_setclock();
925 UsbCommand c
= {CMD_SMART_SETCLOCK
, {clock
, 0, 0}};
926 clearCommandBuffer();
929 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
930 PrintAndLogEx(WARNING
, "smart card select failed");
934 uint8_t isok
= resp
.arg
[0] & 0xFF;
936 PrintAndLogEx(WARNING
, "smart card set clock failed");
942 PrintAndLogEx(SUCCESS
, "Clock changed to 16mhz giving 10800 baudrate");
945 PrintAndLogEx(SUCCESS
, "Clock changed to 8mhz giving 21600 baudrate");
948 PrintAndLogEx(SUCCESS
, "Clock changed to 4mhz giving 86400 baudrate");
956 int CmdSmartList(const char *Cmd
) {
961 int CmdSmartBruteforceSFI(const char *Cmd
) {
963 char ctmp
= tolower(param_getchar(Cmd
, 0));
964 if (ctmp
== 'h') return usage_sm_brute();
966 uint8_t data
[5] = {0x00, 0xB2, 0x00, 0x00, 0x00};
968 PrintAndLogEx(INFO
, "Selecting card");
969 if ( !smart_select(false) ) {
973 PrintAndLogEx(INFO
, "Selecting PPSE aid");
974 CmdSmartRaw("s 0 t d 00a404000e325041592e5359532e4444463031");
975 CmdSmartRaw("0 t d 00a4040007a000000004101000"); // mastercard
976 // CmdSmartRaw("0 t d 00a4040007a0000000031010"); // visa
978 PrintAndLogEx(INFO
, "starting");
980 UsbCommand c
= {CMD_SMART_RAW
, {SC_RAW
, sizeof(data
), 0}};
981 uint8_t* buf
= malloc(USB_CMD_DATA_SIZE
);
985 for (uint8_t i
=1; i
< 4; i
++) {
986 for (int p1
=1; p1
< 5; p1
++) {
989 data
[3] = (i
<< 3) + 4;
991 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
992 clearCommandBuffer();
997 if ( buf
[0] == 0x6C ) {
1000 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
1001 clearCommandBuffer();
1003 uint8_t len
= smart_response(buf
);
1007 TLVPrintFromBuffer(buf
+1, len
-3);
1011 memset(buf
, 0x00, USB_CMD_DATA_SIZE
);
1018 static command_t CommandTable
[] = {
1019 {"help", CmdHelp
, 1, "This help"},
1020 {"select", CmdSmartSelect
, 1, "Select the Smartcard Reader to use"},
1021 {"list", CmdSmartList
, 0, "List ISO 7816 history"},
1022 {"info", CmdSmartInfo
, 0, "Tag information"},
1023 {"reader", CmdSmartReader
, 0, "Act like an IS07816 reader"},
1024 {"raw", CmdSmartRaw
, 0, "Send raw hex data to tag"},
1025 {"upgrade", CmdSmartUpgrade
, 0, "Upgrade firmware"},
1026 {"setclock", CmdSmartSetClock
, 0, "Set clock speed"},
1027 {"brute", CmdSmartBruteforceSFI
, 0, "Bruteforce SFI"},
1028 {NULL
, NULL
, 0, NULL
}
1031 int CmdSmartcard(const char *Cmd
) {
1032 clearCommandBuffer();
1033 CmdsParse(CommandTable
, Cmd
);
1037 int CmdHelp(const char *Cmd
) {
1038 CmdsHelp(CommandTable
);