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"
21 #include "cmdhf.h" // CmdHFlist
22 #include "emv/apduinfo.h" // APDUcode description
23 #include "emv/emvcore.h" // decodeTVL
24 #include "crypto/libpcrypto.h" // sha512hash
25 #include "emv/dump.h" // dump_buffer
27 #define SC_UPGRADE_FILES_DIRECTORY "sc_upgrade_firmware/"
29 static int CmdHelp(const char *Cmd
);
31 static int usage_sm_raw(void) {
32 PrintAndLogEx(NORMAL
, "Usage: sc raw [h|r|c] d <0A 0B 0C ... hex>");
33 PrintAndLogEx(NORMAL
, " h : this help");
34 PrintAndLogEx(NORMAL
, " r : do not read response");
35 PrintAndLogEx(NORMAL
, " a : active smartcard without select");
36 PrintAndLogEx(NORMAL
, " s : active smartcard with select");
37 PrintAndLogEx(NORMAL
, " t : executes TLV decoder if it possible");
38 PrintAndLogEx(NORMAL
, " d <bytes> : bytes to send");
39 PrintAndLogEx(NORMAL
, "");
40 PrintAndLogEx(NORMAL
, "Examples:");
41 PrintAndLogEx(NORMAL
, " sc raw d 00a404000e315041592e5359532e444446303100 - `1PAY.SYS.DDF01` PPSE directory");
42 PrintAndLogEx(NORMAL
, " sc raw d 00a404000e325041592e5359532e444446303100 - `2PAY.SYS.DDF01` PPSE directory");
46 static int usage_sm_reader(void) {
47 PrintAndLogEx(NORMAL
, "Usage: sc reader [h|s]");
48 PrintAndLogEx(NORMAL
, " h : this help");
49 PrintAndLogEx(NORMAL
, " s : silent (no messages)");
50 PrintAndLogEx(NORMAL
, "");
51 PrintAndLogEx(NORMAL
, "Examples:");
52 PrintAndLogEx(NORMAL
, " sc reader");
56 static int usage_sm_info(void) {
57 PrintAndLogEx(NORMAL
, "Usage: s info [h|s]");
58 PrintAndLogEx(NORMAL
, " h : this help");
59 PrintAndLogEx(NORMAL
, " s : silent (no messages)");
60 PrintAndLogEx(NORMAL
, "");
61 PrintAndLogEx(NORMAL
, "Examples:");
62 PrintAndLogEx(NORMAL
, " sc info");
66 static int usage_sm_upgrade(void) {
67 PrintAndLogEx(NORMAL
, "Upgrade RDV4.0 Smartcard Socket Firmware");
68 PrintAndLogEx(NORMAL
, "Usage: sc upgrade f <file name>");
69 PrintAndLogEx(NORMAL
, " h : this help");
70 PrintAndLogEx(NORMAL
, " f <filename> : firmware file name");
71 PrintAndLogEx(NORMAL
, "");
72 PrintAndLogEx(NORMAL
, "Examples:");
73 PrintAndLogEx(NORMAL
, " sc upgrade f SIM010.BIN");
77 static int usage_sm_setclock(void) {
78 PrintAndLogEx(NORMAL
, "Usage: sc setclock [h] c <clockspeed>");
79 PrintAndLogEx(NORMAL
, " h : this help");
80 PrintAndLogEx(NORMAL
, " c <> : clockspeed (0 = 16mhz, 1=8mhz, 2=4mhz) ");
81 PrintAndLogEx(NORMAL
, "");
82 PrintAndLogEx(NORMAL
, "Examples:");
83 PrintAndLogEx(NORMAL
, " sc setclock c 2");
87 static int usage_sm_brute(void) {
88 PrintAndLogEx(NORMAL
, "Tries to bruteforce SFI, ");
89 PrintAndLogEx(NORMAL
, "Usage: sc brute [h]");
90 PrintAndLogEx(NORMAL
, " h : this help");
91 PrintAndLogEx(NORMAL
, "");
92 PrintAndLogEx(NORMAL
, "Examples:");
93 PrintAndLogEx(NORMAL
, " sc brute");
97 uint8_t GetATRTA1(uint8_t *atr
, size_t atrlen
) {
104 return 0x11; // default value is 0x11, corresponding to fmax=5 MHz, Fi=372, Di=1.
115 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
127 372, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock
146 4, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock
164 int GetATRDi(uint8_t *atr
, size_t atrlen
) {
165 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
167 return DiArray
[TA1
& 0x0f]; // The 4 low-order bits of TA1 (4th MSbit to 1st LSbit) encode Di
170 int GetATRFi(uint8_t *atr
, size_t atrlen
) {
171 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
173 return FiArray
[TA1
>> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi
176 float GetATRF(uint8_t *atr
, size_t atrlen
) {
177 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
179 return FArray
[TA1
>> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi
182 static int PrintATR(uint8_t *atr
, size_t atrlen
) {
184 for (int i
= 1; i
< atrlen
; i
++)
188 PrintAndLogEx(WARNING
, "Check summ error. Must be 0 but: 0x%02x", vxor
);
190 PrintAndLogEx(INFO
, "Check summ OK.");
193 PrintAndLogEx(WARNING
, "Not a direct convention: 0x%02x", atr
[0]);
196 uint8_t K
= T0
& 0x0F;
204 PrintAndLog("TA1 (Maximum clock frequency, proposed bit duration): 0x%02x", atr
[2 + T1len
]);
208 PrintAndLog("TB1 (Deprecated: VPP requirements): 0x%02x", atr
[2 + T1len
]);
212 PrintAndLog("TC1 (Extra delay between bytes required by card): 0x%02x", atr
[2 + T1len
]);
216 TD1
= atr
[2 + T1len
];
217 PrintAndLog("TD1 (First offered transmission protocol, presence of TA2..TD2): 0x%02x. Protocol T=%d", TD1
, TD1
& 0x0f);
221 PrintAndLog("TA2 (Specific protocol and parameters to be used after the ATR): 0x%02x", atr
[2 + T1len
+ TD1len
]);
225 PrintAndLog("TB2 (Deprecated: VPP precise voltage requirement): 0x%02x", atr
[2 + T1len
+ TD1len
]);
229 PrintAndLog("TC2 (Maximum waiting time for protocol T=0): 0x%02x", atr
[2 + T1len
+ TD1len
]);
233 uint8_t TDi
= atr
[2 + T1len
+ TD1len
];
234 PrintAndLog("TD2 (A supported protocol or more global parameters, presence of TA3..TD3): 0x%02x. Protocol T=%d", TDi
, TDi
& 0x0f);
237 bool nextCycle
= true;
242 PrintAndLog("TA%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
246 PrintAndLog("TB%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
250 PrintAndLog("TC%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
254 TDi
= atr
[2 + T1len
+ TD1len
+ TDilen
];
255 PrintAndLog("TD%d: 0x%02x. Protocol T=%d", vi
, TDi
, TDi
& 0x0f);
265 uint8_t calen
= 2 + T1len
+ TD1len
+ TDilen
+ K
;
267 if (atrlen
!= calen
&& atrlen
!= calen
+ 1) // may be CRC
268 PrintAndLogEx(ERR
, "ATR length error. len: %d, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen
, T1len
, TD1len
, TDilen
, K
);
270 PrintAndLogEx(INFO
, "ATR length OK.");
272 PrintAndLog("Historical bytes len: 0x%02x", K
);
274 PrintAndLog("The format of historical bytes: %02x", atr
[2 + T1len
+ TD1len
+ TDilen
]);
276 PrintAndLog("Historical bytes:");
277 dump_buffer(&atr
[2 + T1len
+ TD1len
+ TDilen
], K
, NULL
, 1);
284 static bool smart_select(bool silent
) {
285 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
286 clearCommandBuffer();
289 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
290 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
294 uint8_t isok
= resp
.arg
[0] & 0xFF;
296 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
301 smart_card_atr_t card
;
302 memcpy(&card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
304 PrintAndLogEx(INFO
, "ISO7816-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
310 static int smart_wait(uint8_t *data
) {
312 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2500)) {
313 PrintAndLogEx(WARNING
, "smart card response failed");
317 uint32_t len
= resp
.arg
[0];
319 PrintAndLogEx(WARNING
, "smart card response failed");
322 memcpy(data
, resp
.d
.asBytes
, len
);
323 PrintAndLogEx(SUCCESS
, " %d | %s", len
, sprint_hex_inrow_ex(data
, len
, 32));
326 PrintAndLogEx(SUCCESS
, "%02X%02X | %s", data
[len
- 2], data
[len
- 1], GetAPDUCodeDescription(data
[len
- 2], data
[len
- 1]));
331 static int smart_response(uint8_t apduINS
, uint8_t *data
) {
333 int datalen
= smart_wait(data
);
334 bool needGetData
= false;
340 if (datalen
> 2 && data
[0] != apduINS
) {
341 PrintAndLogEx(ERR
, "Card ACK error. len=0x%x data[0]=%02x", datalen
, data
[0]);
346 if ( data
[datalen
- 2] == 0x61 || data
[datalen
- 2] == 0x9F ) {
351 int len
= data
[datalen
- 1];
352 PrintAndLogEx(INFO
, "Requesting response. len=0x%x", len
);
353 uint8_t getstatus
[] = {ISO7816_GETSTATUS
, 0x00, 0x00, len
};
354 UsbCommand cStatus
= {CMD_SMART_RAW
, {SC_RAW
, sizeof(getstatus
), 0}};
355 memcpy(cStatus
.d
.asBytes
, getstatus
, sizeof(getstatus
) );
356 clearCommandBuffer();
357 SendCommand(&cStatus
);
359 datalen
= smart_wait(data
);
364 if (datalen
> 2 && data
[0] != ISO7816_GETSTATUS
) {
365 PrintAndLogEx(ERR
, "GetResponse ACK error. len=0x%x data[0]=%02x", len
, data
[0]);
370 if (datalen
!= len
+ 2 + 1) { // 2 - response, 1 - ACK
371 PrintAndLogEx(WARNING
, "GetResponse wrong length. Must be: 0x%02x but: 0x%02x", len
, datalen
- 3);
377 memmove(data
, &data
[1], datalen
);
383 int CmdSmartRaw(const char *Cmd
) {
387 bool active_select
= false;
389 bool errors
= false, reply
= true, decodeTLV
= false, breakloop
= false;
390 uint8_t data
[USB_CMD_DATA_SIZE
] = {0x00};
392 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
393 switch (tolower(param_getchar(Cmd
, cmdp
))) {
394 case 'h': return usage_sm_raw();
404 active_select
= true;
412 switch (param_gethex_to_eol(Cmd
, cmdp
+1, data
, sizeof(data
), &hexlen
)) {
414 PrintAndLogEx(WARNING
, "Invalid HEX value.");
417 PrintAndLogEx(WARNING
, "Too many bytes. Max %d bytes", sizeof(data
));
420 PrintAndLogEx(WARNING
, "Hex must have even number of digits.");
428 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
438 if (errors
|| cmdp
== 0 ) return usage_sm_raw();
442 UsbCommand c
= {CMD_SMART_RAW
, {0, hexlen
, 0}};
444 if (active
|| active_select
) {
445 c
.arg
[0] |= SC_CONNECT
;
447 c
.arg
[0] |= SC_SELECT
;
454 memcpy(c
.d
.asBytes
, data
, hexlen
);
455 clearCommandBuffer();
458 // reading response from smart card
461 uint8_t* buf
= calloc(USB_CMD_DATA_SIZE
, sizeof(uint8_t));
465 int len
= smart_response(data
[1], buf
);
471 if ( buf
[0] == 0x6C ) {
474 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
475 clearCommandBuffer();
477 len
= smart_response(data
[1], buf
);
482 if (decodeTLV
&& len
> 4)
483 TLVPrintFromBuffer(buf
+1, len
-3);
490 int ExchangeAPDUSC(uint8_t *datain
, int datainlen
, bool activateCard
, bool leaveSignalON
, uint8_t *dataout
, int maxdataoutlen
, int *dataoutlen
) {
495 printf("* APDU SC\n");
497 UsbCommand c
= {CMD_SMART_RAW
, {SC_RAW
| SC_CONNECT
, datainlen
, 0}};
499 c
.arg
[0] |= SC_SELECT
;
501 memcpy(c
.d
.asBytes
, datain
, datainlen
);
502 clearCommandBuffer();
505 int len
= smart_response(datain
[1], dataout
);
513 if (len
> 1 && dataout
[len
- 2] == 0x6c && datainlen
> 4) {
514 UsbCommand c2
= {CMD_SMART_RAW
, {SC_RAW
, datainlen
, 0}};
515 memcpy(c2
.d
.asBytes
, datain
, datainlen
);
517 int vlen
= 5 + datain
[4];
518 if (datainlen
== vlen
)
521 c2
.d
.asBytes
[vlen
] = dataout
[len
- 1];
523 clearCommandBuffer();
526 len
= smart_response(datain
[1], dataout
);
534 int CmdSmartUpgrade(const char *Cmd
) {
536 PrintAndLogEx(NORMAL
, "");
537 PrintAndLogEx(WARNING
, "WARNING - RDV4.0 Smartcard Socket Firmware upgrade.");
538 PrintAndLogEx(WARNING
, "A dangerous command, do wrong and you will brick the smart card socket");
539 PrintAndLogEx(NORMAL
, "");
542 char filename
[FILE_PATH_SIZE
] = {0};
546 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
547 switch (tolower(param_getchar(Cmd
, cmdp
))) {
549 //File handling and reading
550 if ( param_getstr(Cmd
, cmdp
+1, filename
, FILE_PATH_SIZE
) >= FILE_PATH_SIZE
) {
551 PrintAndLogEx(FAILED
, "Filename too long");
559 return usage_sm_upgrade();
561 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
568 if (errors
|| cmdp
== 0 ) return usage_sm_upgrade();
570 if (strchr(filename
, '\\') || strchr(filename
, '/')) {
571 PrintAndLogEx(FAILED
, "Filename must not contain \\ or /. Firmware file will be found in client/sc_upgrade_firmware directory.");
575 char sc_upgrade_file_path
[strlen(get_my_executable_directory()) + strlen(SC_UPGRADE_FILES_DIRECTORY
) + strlen(filename
) + 1];
576 strcpy(sc_upgrade_file_path
, get_my_executable_directory());
577 strcat(sc_upgrade_file_path
, SC_UPGRADE_FILES_DIRECTORY
);
578 strcat(sc_upgrade_file_path
, filename
);
579 if (strlen(sc_upgrade_file_path
) >= FILE_PATH_SIZE
) {
580 PrintAndLogEx(FAILED
, "Filename too long");
584 char sha512filename
[FILE_PATH_SIZE
];
585 char *bin_extension
= filename
;
586 char *dot_position
= NULL
;
587 while ((dot_position
= strchr(bin_extension
, '.')) != NULL
) {
588 bin_extension
= dot_position
+ 1;
590 if (!strcmp(bin_extension
, "BIN")
592 || !strcmp(bin_extension
, "bin")
595 strncpy(sha512filename
, filename
, strlen(filename
) - strlen("bin"));
596 strcat(sha512filename
, "sha512.txt");
598 PrintAndLogEx(FAILED
, "Filename extension of Firmware Upgrade File must be .BIN");
602 PrintAndLogEx(INFO
, "Checking integrity using SHA512 File %s ...", sha512filename
);
603 char sc_upgrade_sha512file_path
[strlen(get_my_executable_directory()) + strlen(SC_UPGRADE_FILES_DIRECTORY
) + strlen(sha512filename
) + 1];
604 strcpy(sc_upgrade_sha512file_path
, get_my_executable_directory());
605 strcat(sc_upgrade_sha512file_path
, SC_UPGRADE_FILES_DIRECTORY
);
606 strcat(sc_upgrade_sha512file_path
, sha512filename
);
607 if (strlen(sc_upgrade_sha512file_path
) >= FILE_PATH_SIZE
) {
608 PrintAndLogEx(FAILED
, "Filename too long");
612 // load firmware file
613 f
= fopen(sc_upgrade_file_path
, "rb");
615 PrintAndLogEx(FAILED
, "Firmware file not found or locked.");
619 // get filesize in order to malloc memory
620 fseek(f
, 0, SEEK_END
);
621 size_t fsize
= ftell(f
);
622 fseek(f
, 0, SEEK_SET
);
625 PrintAndLogEx(FAILED
, "Could not determine size of firmware file");
630 uint8_t *dump
= calloc(fsize
, sizeof(uint8_t));
632 PrintAndLogEx(FAILED
, "Could not allocate memory for firmware");
637 size_t firmware_size
= fread(dump
, 1, fsize
, f
);
642 f
= fopen(sc_upgrade_sha512file_path
, "rb");
644 PrintAndLogEx(FAILED
, "SHA-512 file not found or locked.");
648 // get filesize in order to malloc memory
649 fseek(f
, 0, SEEK_END
);
651 fseek(f
, 0, SEEK_SET
);
654 PrintAndLogEx(FAILED
, "Could not determine size of SHA-512 file");
660 PrintAndLogEx(FAILED
, "SHA-512 file too short");
665 char hashstring
[129];
666 size_t bytes_read
= fread(hashstring
, 1, 128, f
);
667 hashstring
[128] = '\0';
673 if (bytes_read
!= 128 || param_gethex(hashstring
, 0, hash1
, 128)) {
674 PrintAndLogEx(FAILED
, "Couldn't read SHA-512 file");
679 if (sha512hash(dump
, firmware_size
, hash2
)) {
680 PrintAndLogEx(FAILED
, "Couldn't calculate SHA-512 of Firmware");
684 if (memcmp(hash1
, hash2
, 64)) {
685 PrintAndLogEx(FAILED
, "Couldn't verify integrity of Firmware file (wrong SHA-512)");
689 PrintAndLogEx(SUCCESS
, "RDV4.0 Smartcard Socket Firmware uploading to PM3");
693 uint32_t bytes_sent
= 0;
694 uint32_t bytes_remaining
= firmware_size
;
696 while (bytes_remaining
> 0){
697 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
698 UsbCommand c
= {CMD_SMART_UPLOAD
, {index
+ bytes_sent
, bytes_in_packet
, 0}};
700 // Fill usb bytes with 0xFF
701 memset(c
.d
.asBytes
, 0xFF, USB_CMD_DATA_SIZE
);
702 memcpy(c
.d
.asBytes
, dump
+ bytes_sent
, bytes_in_packet
);
703 clearCommandBuffer();
705 if ( !WaitForResponseTimeout(CMD_ACK
, NULL
, 2000) ) {
706 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
711 bytes_remaining
-= bytes_in_packet
;
712 bytes_sent
+= bytes_in_packet
;
713 printf("."); fflush(stdout
);
717 PrintAndLogEx(SUCCESS
, "RDV4.0 Smartcard Socket Firmware updating, don\'t turn off your PM3!");
719 // trigger the firmware upgrade
720 UsbCommand c
= {CMD_SMART_UPGRADE
, {firmware_size
, 0, 0}};
721 clearCommandBuffer();
724 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
725 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
728 if ( (resp
.arg
[0] & 0xFF ) )
729 PrintAndLogEx(SUCCESS
, "RDV4.0 Smartcard Socket Firmware upgraded successful");
731 PrintAndLogEx(FAILED
, "RDV4.0 Smartcard Socket Firmware Upgrade failed");
735 int CmdSmartInfo(const char *Cmd
){
737 bool errors
= false, silent
= false;
739 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
740 switch (tolower(param_getchar(Cmd
, cmdp
))) {
741 case 'h': return usage_sm_info();
746 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
754 if (errors
) return usage_sm_info();
756 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
757 clearCommandBuffer();
760 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
761 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
765 uint8_t isok
= resp
.arg
[0] & 0xFF;
767 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
771 smart_card_atr_t card
;
772 memcpy(&card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
775 PrintAndLogEx(INFO
, "\n--- Smartcard Information ---------");
776 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
777 PrintAndLogEx(INFO
, "ISO76183 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
778 PrintAndLogEx(INFO
, "look up ATR");
779 PrintAndLogEx(INFO
, "http://smartcard-atr.appspot.com/parse?ATR=%s", sprint_hex_inrow(card
.atr
, card
.atr_len
) );
782 PrintAndLogEx(NORMAL
, "");
783 PrintAndLogEx(NORMAL
, "* ATR:");
784 PrintATR(card
.atr
, card
.atr_len
);
786 // print D/F (brom byte TA1 or defaults)
787 PrintAndLogEx(NORMAL
, "");
788 PrintAndLogEx(NORMAL
, "* D/F (TA1):");
789 int Di
= GetATRDi(card
.atr
, card
.atr_len
);
790 int Fi
= GetATRFi(card
.atr
, card
.atr_len
);
791 float F
= GetATRF(card
.atr
, card
.atr_len
);
792 if (GetATRTA1(card
.atr
, card
.atr_len
) == 0x11)
793 PrintAndLogEx(INFO
, "Using default values...");
795 PrintAndLogEx(NORMAL
, "Di=%d", Di
);
796 PrintAndLogEx(NORMAL
, "Fi=%d", Fi
);
797 PrintAndLogEx(NORMAL
, "F=%.1f MHz", F
);
798 PrintAndLogEx(NORMAL
, "Cycles/ETU=%d", Fi
/Di
);
799 PrintAndLogEx(NORMAL
, "%.1f bits/sec at 4MHz", (float)4000000 / (Fi
/Di
));
800 PrintAndLogEx(NORMAL
, "%.1f bits/sec at Fmax=%.1fMHz", (F
* 1000000) / (Fi
/Di
), F
);
805 int CmdSmartReader(const char *Cmd
){
807 bool errors
= false, silent
= false;
809 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
810 switch (tolower(param_getchar(Cmd
, cmdp
))) {
811 case 'h': return usage_sm_reader();
816 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
824 if (errors
) return usage_sm_reader();
826 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
827 clearCommandBuffer();
830 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
831 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
835 uint8_t isok
= resp
.arg
[0] & 0xFF;
837 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
840 smart_card_atr_t card
;
841 memcpy(&card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
843 PrintAndLogEx(INFO
, "ISO7816-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
847 int CmdSmartSetClock(const char *Cmd
){
851 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
852 switch (tolower(param_getchar(Cmd
, cmdp
))) {
853 case 'h': return usage_sm_setclock();
855 clock
= param_get8ex(Cmd
, cmdp
+1, 2, 10);
862 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
869 if (errors
|| cmdp
== 0) return usage_sm_setclock();
871 UsbCommand c
= {CMD_SMART_SETCLOCK
, {clock
, 0, 0}};
872 clearCommandBuffer();
875 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
876 PrintAndLogEx(WARNING
, "smart card select failed");
880 uint8_t isok
= resp
.arg
[0] & 0xFF;
882 PrintAndLogEx(WARNING
, "smart card set clock failed");
888 PrintAndLogEx(SUCCESS
, "Clock changed to 16mhz giving 10800 baudrate");
891 PrintAndLogEx(SUCCESS
, "Clock changed to 8mhz giving 21600 baudrate");
894 PrintAndLogEx(SUCCESS
, "Clock changed to 4mhz giving 86400 baudrate");
902 int CmdSmartList(const char *Cmd
) {
907 int CmdSmartBruteforceSFI(const char *Cmd
) {
909 char ctmp
= tolower(param_getchar(Cmd
, 0));
910 if (ctmp
== 'h') return usage_sm_brute();
912 uint8_t data
[5] = {0x00, 0xB2, 0x00, 0x00, 0x00};
914 PrintAndLogEx(INFO
, "Selecting card");
915 if ( !smart_select(false) ) {
919 PrintAndLogEx(INFO
, "Selecting PPSE aid");
920 CmdSmartRaw("d 00a404000e325041592e5359532e444446303100");
921 CmdSmartRaw("d 00a4040007a000000004101000");
923 PrintAndLogEx(INFO
, "starting");
925 UsbCommand c
= {CMD_SMART_RAW
, {SC_RAW
, sizeof(data
), 0}};
926 uint8_t* buf
= malloc(USB_CMD_DATA_SIZE
);
930 for (uint8_t i
=1; i
< 4; i
++) {
931 for (int p1
=1; p1
< 5; p1
++) {
934 data
[3] = (i
<< 3) + 4;
936 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
937 clearCommandBuffer();
940 smart_response(data
[1], buf
);
943 if ( buf
[0] == 0x6C ) {
946 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
947 clearCommandBuffer();
949 uint8_t len
= smart_response(data
[1], buf
);
953 TLVPrintFromBuffer(buf
+1, len
-3);
957 memset(buf
, 0x00, USB_CMD_DATA_SIZE
);
964 static command_t CommandTable
[] = {
965 {"help", CmdHelp
, 1, "This help"},
966 {"list", CmdSmartList
, 0, "List ISO 7816 history"},
967 {"info", CmdSmartInfo
, 0, "Tag information"},
968 {"reader", CmdSmartReader
, 0, "Act like an IS07816 reader"},
969 {"raw", CmdSmartRaw
, 0, "Send raw hex data to tag"},
970 {"upgrade", CmdSmartUpgrade
, 0, "Upgrade firmware"},
971 {"setclock", CmdSmartSetClock
, 0, "Set clock speed"},
972 {"brute", CmdSmartBruteforceSFI
, 0, "Bruteforce SFI"},
973 {NULL
, NULL
, 0, NULL
}
976 int CmdSmartcard(const char *Cmd
) {
977 clearCommandBuffer();
978 CmdsParse(CommandTable
, Cmd
);
982 int CmdHelp(const char *Cmd
) {
983 CmdsHelp(CommandTable
);