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 "cmdhflist.h"
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 (reset sc module)");
36 PrintAndLogEx(NORMAL
, " s : active smartcard with select (get ATR)");
37 PrintAndLogEx(NORMAL
, " t : executes TLV decoder if it possible");
38 PrintAndLogEx(NORMAL
, " 0 : use protocol T=0");
39 PrintAndLogEx(NORMAL
, " d <bytes> : bytes to send");
40 PrintAndLogEx(NORMAL
, "");
41 PrintAndLogEx(NORMAL
, "Examples:");
42 PrintAndLogEx(NORMAL
, " sc raw s 0 d 00a404000e315041592e5359532e4444463031 - `1PAY.SYS.DDF01` PPSE directory with get ATR");
43 PrintAndLogEx(NORMAL
, " sc raw 0 d 00a404000e325041592e5359532e4444463031 - `2PAY.SYS.DDF01` PPSE directory");
47 static int usage_sm_reader(void) {
48 PrintAndLogEx(NORMAL
, "Usage: sc reader [h|s]");
49 PrintAndLogEx(NORMAL
, " h : this help");
50 PrintAndLogEx(NORMAL
, " s : silent (no messages)");
51 PrintAndLogEx(NORMAL
, "");
52 PrintAndLogEx(NORMAL
, "Examples:");
53 PrintAndLogEx(NORMAL
, " sc reader");
57 static int usage_sm_info(void) {
58 PrintAndLogEx(NORMAL
, "Usage: s info [h|s]");
59 PrintAndLogEx(NORMAL
, " h : this help");
60 PrintAndLogEx(NORMAL
, " s : silent (no messages)");
61 PrintAndLogEx(NORMAL
, "");
62 PrintAndLogEx(NORMAL
, "Examples:");
63 PrintAndLogEx(NORMAL
, " sc info");
67 static int usage_sm_upgrade(void) {
68 PrintAndLogEx(NORMAL
, "Upgrade RDV4.0 Smartcard Socket Firmware");
69 PrintAndLogEx(NORMAL
, "Usage: sc upgrade f <file name>");
70 PrintAndLogEx(NORMAL
, " h : this help");
71 PrintAndLogEx(NORMAL
, " f <filename> : firmware file name");
72 PrintAndLogEx(NORMAL
, "");
73 PrintAndLogEx(NORMAL
, "Examples:");
74 PrintAndLogEx(NORMAL
, " sc upgrade f SIM010.BIN");
78 static int usage_sm_setclock(void) {
79 PrintAndLogEx(NORMAL
, "Usage: sc setclock [h] c <clockspeed>");
80 PrintAndLogEx(NORMAL
, " h : this help");
81 PrintAndLogEx(NORMAL
, " c <> : clockspeed (0 = 16mhz, 1=8mhz, 2=4mhz) ");
82 PrintAndLogEx(NORMAL
, "");
83 PrintAndLogEx(NORMAL
, "Examples:");
84 PrintAndLogEx(NORMAL
, " sc setclock c 2");
88 static int usage_sm_brute(void) {
89 PrintAndLogEx(NORMAL
, "Tries to bruteforce SFI, ");
90 PrintAndLogEx(NORMAL
, "Usage: sc brute [h]");
91 PrintAndLogEx(NORMAL
, " h : this help");
92 PrintAndLogEx(NORMAL
, "");
93 PrintAndLogEx(NORMAL
, "Examples:");
94 PrintAndLogEx(NORMAL
, " sc brute");
98 uint8_t GetATRTA1(uint8_t *atr
, size_t atrlen
) {
105 return 0x11; // default value is 0x11, corresponding to fmax=5 MHz, Fi=372, Di=1.
116 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
128 372, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock
147 4, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock
165 int GetATRDi(uint8_t *atr
, size_t atrlen
) {
166 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
168 return DiArray
[TA1
& 0x0f]; // The 4 low-order bits of TA1 (4th MSbit to 1st LSbit) encode Di
171 int GetATRFi(uint8_t *atr
, size_t atrlen
) {
172 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
174 return FiArray
[TA1
>> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi
177 float GetATRF(uint8_t *atr
, size_t atrlen
) {
178 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
180 return FArray
[TA1
>> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi
183 static int PrintATR(uint8_t *atr
, size_t atrlen
) {
186 uint8_t K
= T0
& 0x0F;
187 uint8_t TD1
= 0, T1len
= 0, TD1len
= 0, TDilen
= 0;
190 PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr
[2 + T1len
]);
195 PrintAndLog("\t- TB1 (Deprecated: VPP requirements) [ 0x%02x ]", atr
[2 + T1len
]);
200 PrintAndLog("\t- TC1 (Extra delay between bytes required by card) [ 0x%02x ]", atr
[2 + T1len
]);
205 TD1
= atr
[2 + T1len
];
206 PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1
, TD1
& 0x0f);
210 PrintAndLog("\t- TA2 (Specific protocol and parameters to be used after the ATR) [ 0x%02x ]", atr
[2 + T1len
+ TD1len
]);
214 PrintAndLog("\t- TB2 (Deprecated: VPP precise voltage requirement) [ 0x%02x ]", atr
[2 + T1len
+ TD1len
]);
218 PrintAndLog("\t- TC2 (Maximum waiting time for protocol T=0) [ 0x%02x ]", atr
[2 + T1len
+ TD1len
]);
222 uint8_t TDi
= atr
[2 + T1len
+ TD1len
];
223 PrintAndLog("\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi
, TDi
& 0x0f);
226 bool nextCycle
= true;
231 PrintAndLog("\t- TA%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
235 PrintAndLog("\t- TB%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
239 PrintAndLog("\t- TC%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
243 TDi
= atr
[2 + T1len
+ TD1len
+ TDilen
];
244 PrintAndLog("\t- TD%d [ 0x%02x ] Protocol T%d", vi
, TDi
, TDi
& 0x0f);
255 for (int i
= 1; i
< atrlen
; i
++)
259 PrintAndLogEx(WARNING
, "Check summ error. Must be 0 got 0x%02X", vxor
);
261 PrintAndLogEx(INFO
, "Check summ OK.");
264 PrintAndLogEx(WARNING
, "Not a direct convention [ 0x%02x ]", atr
[0]);
267 uint8_t calen
= 2 + T1len
+ TD1len
+ TDilen
+ K
;
269 if (atrlen
!= calen
&& atrlen
!= calen
+ 1) // may be CRC
270 PrintAndLogEx(ERR
, "ATR length error. len: %d, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen
, T1len
, TD1len
, TDilen
, K
);
273 PrintAndLogEx(INFO
, "\nHistorical bytes | len 0x%02d | format %02x", K
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
276 PrintAndLogEx(INFO
, "\tHistorical bytes");
277 dump_buffer(&atr
[2 + T1len
+ TD1len
+ TDilen
], K
, NULL
, 1);
283 static bool smart_select(bool silent
) {
284 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
285 clearCommandBuffer();
288 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
289 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
293 uint8_t isok
= resp
.arg
[0] & 0xFF;
295 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
300 smart_card_atr_t card
;
301 memcpy(&card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
303 PrintAndLogEx(INFO
, "ISO7816-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
309 static int smart_wait(uint8_t *data
) {
311 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2500)) {
312 PrintAndLogEx(WARNING
, "smart card response timeout");
316 uint32_t len
= resp
.arg
[0];
318 PrintAndLogEx(WARNING
, "smart card response failed");
321 memcpy(data
, resp
.d
.asBytes
, len
);
323 PrintAndLogEx(SUCCESS
, "%02X%02X | %s", data
[len
- 2], data
[len
- 1], GetAPDUCodeDescription(data
[len
- 2], data
[len
- 1]));
325 PrintAndLogEx(SUCCESS
, " %d | %s", len
, sprint_hex_inrow_ex(data
, len
, 8));
331 static int smart_response(uint8_t *data
) {
333 int datalen
= smart_wait(data
);
334 bool needGetData
= false;
340 if ( data
[datalen
- 2] == 0x61 || data
[datalen
- 2] == 0x9F ) {
345 int len
= data
[datalen
- 1];
346 PrintAndLogEx(INFO
, "Requesting 0x%02X bytes response", len
);
347 uint8_t getstatus
[] = {0x00, ISO7816_GETSTATUS
, 0x00, 0x00, len
};
348 UsbCommand cStatus
= {CMD_SMART_RAW
, {SC_RAW
, sizeof(getstatus
), 0}};
349 memcpy(cStatus
.d
.asBytes
, getstatus
, sizeof(getstatus
) );
350 clearCommandBuffer();
351 SendCommand(&cStatus
);
353 datalen
= smart_wait(data
);
360 if (datalen
!= len
+ 2) {
362 if (datalen
== len
+ 2 + 1) { // 2 - response, 1 - ACK
363 if (data
[0] != ISO7816_GETSTATUS
) {
364 PrintAndLogEx(ERR
, "GetResponse ACK error. len 0x%x | data[0] %02X", len
, data
[0]);
370 memmove(data
, &data
[1], datalen
);
373 PrintAndLogEx(WARNING
, "GetResponse wrong length. Must be 0x%02X got 0x%02X", len
, datalen
- 3);
382 int CmdSmartRaw(const char *Cmd
) {
386 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;
416 switch (param_gethex_to_eol(Cmd
, cmdp
+1, data
, sizeof(data
), &hexlen
)) {
418 PrintAndLogEx(WARNING
, "Invalid HEX value.");
421 PrintAndLogEx(WARNING
, "Too many bytes. Max %d bytes", sizeof(data
));
424 PrintAndLogEx(WARNING
, "Hex must have even number of digits.");
432 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
442 if (errors
|| cmdp
== 0 ) return usage_sm_raw();
446 UsbCommand c
= {CMD_SMART_RAW
, {0, hexlen
, 0}};
448 if (active
|| active_select
) {
449 c
.arg
[0] |= SC_CONNECT
;
451 c
.arg
[0] |= SC_SELECT
;
456 c
.arg
[0] |= SC_RAW_T0
;
461 memcpy(c
.d
.asBytes
, data
, hexlen
);
462 clearCommandBuffer();
465 // reading response from smart card
468 uint8_t* buf
= calloc(USB_CMD_DATA_SIZE
, sizeof(uint8_t));
472 int len
= smart_response(buf
);
478 if ( buf
[0] == 0x6C ) {
481 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
482 clearCommandBuffer();
484 len
= smart_response(buf
);
489 if (decodeTLV
&& len
> 4)
490 TLVPrintFromBuffer(buf
, len
-2);
497 int ExchangeAPDUSC(uint8_t *datain
, int datainlen
, bool activateCard
, bool leaveSignalON
, uint8_t *dataout
, int maxdataoutlen
, int *dataoutlen
) {
503 PrintAndLogEx(DEBUG
, "APDU SC");
505 UsbCommand c
= {CMD_SMART_RAW
, {SC_RAW_T0
, datainlen
, 0}};
507 c
.arg
[0] |= SC_SELECT
| SC_CONNECT
;
509 memcpy(c
.d
.asBytes
, datain
, datainlen
);
510 clearCommandBuffer();
513 int len
= smart_response(dataout
);
520 if (len
> 1 && dataout
[len
- 2] == 0x6c && datainlen
> 4) {
521 UsbCommand c2
= {CMD_SMART_RAW
, {SC_RAW_T0
, datainlen
, 0}};
522 memcpy(c2
.d
.asBytes
, datain
, 5);
524 // transfer length via T=0
525 c2
.d
.asBytes
[4] = dataout
[len
- 1];
527 clearCommandBuffer();
530 len
= smart_response(dataout
);
538 int CmdSmartUpgrade(const char *Cmd
) {
540 PrintAndLogEx(NORMAL
, "");
541 PrintAndLogEx(WARNING
, "WARNING - RDV4.0 Smartcard Socket Firmware upgrade.");
542 PrintAndLogEx(WARNING
, "A dangerous command, do wrong and you will brick the smart card socket");
543 PrintAndLogEx(NORMAL
, "");
546 char filename
[FILE_PATH_SIZE
] = {0};
550 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
551 switch (tolower(param_getchar(Cmd
, cmdp
))) {
553 //File handling and reading
554 if ( param_getstr(Cmd
, cmdp
+1, filename
, FILE_PATH_SIZE
) >= FILE_PATH_SIZE
) {
555 PrintAndLogEx(FAILED
, "Filename too long");
562 return usage_sm_upgrade();
564 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
571 if (errors
|| cmdp
== 0 ) return usage_sm_upgrade();
573 if (strchr(filename
, '\\') || strchr(filename
, '/')) {
574 PrintAndLogEx(FAILED
, "Filename must not contain \\ or /. Firmware file will be found in client/sc_upgrade_firmware directory.");
578 char sc_upgrade_file_path
[strlen(get_my_executable_directory()) + strlen(SC_UPGRADE_FILES_DIRECTORY
) + strlen(filename
) + 1];
579 strcpy(sc_upgrade_file_path
, get_my_executable_directory());
580 strcat(sc_upgrade_file_path
, SC_UPGRADE_FILES_DIRECTORY
);
581 strcat(sc_upgrade_file_path
, filename
);
582 if (strlen(sc_upgrade_file_path
) >= FILE_PATH_SIZE
) {
583 PrintAndLogEx(FAILED
, "Filename too long");
587 char sha512filename
[FILE_PATH_SIZE
];
588 char *bin_extension
= filename
;
589 char *dot_position
= NULL
;
590 while ((dot_position
= strchr(bin_extension
, '.')) != NULL
) {
591 bin_extension
= dot_position
+ 1;
593 if (!strcmp(bin_extension
, "BIN")
595 || !strcmp(bin_extension
, "bin")
598 strncpy(sha512filename
, filename
, strlen(filename
) - strlen("bin"));
599 strcat(sha512filename
, "sha512.txt");
601 PrintAndLogEx(FAILED
, "Filename extension of Firmware Upgrade File must be .BIN");
605 PrintAndLogEx(INFO
, "Checking integrity using SHA512 File %s ...", sha512filename
);
606 char sc_upgrade_sha512file_path
[strlen(get_my_executable_directory()) + strlen(SC_UPGRADE_FILES_DIRECTORY
) + strlen(sha512filename
) + 1];
607 strcpy(sc_upgrade_sha512file_path
, get_my_executable_directory());
608 strcat(sc_upgrade_sha512file_path
, SC_UPGRADE_FILES_DIRECTORY
);
609 strcat(sc_upgrade_sha512file_path
, sha512filename
);
610 if (strlen(sc_upgrade_sha512file_path
) >= FILE_PATH_SIZE
) {
611 PrintAndLogEx(FAILED
, "Filename too long");
615 // load firmware file
616 f
= fopen(sc_upgrade_file_path
, "rb");
618 PrintAndLogEx(FAILED
, "Firmware file not found or locked.");
622 // get filesize in order to malloc memory
623 fseek(f
, 0, SEEK_END
);
624 size_t fsize
= ftell(f
);
625 fseek(f
, 0, SEEK_SET
);
628 PrintAndLogEx(FAILED
, "Could not determine size of firmware file");
633 uint8_t *dump
= calloc(fsize
, sizeof(uint8_t));
635 PrintAndLogEx(FAILED
, "Could not allocate memory for firmware");
640 size_t firmware_size
= fread(dump
, 1, fsize
, f
);
645 f
= fopen(sc_upgrade_sha512file_path
, "rb");
647 PrintAndLogEx(FAILED
, "SHA-512 file not found or locked.");
651 // get filesize in order to malloc memory
652 fseek(f
, 0, SEEK_END
);
654 fseek(f
, 0, SEEK_SET
);
657 PrintAndLogEx(FAILED
, "Could not determine size of SHA-512 file");
663 PrintAndLogEx(FAILED
, "SHA-512 file too short");
668 char hashstring
[129];
669 size_t bytes_read
= fread(hashstring
, 1, 128, f
);
670 hashstring
[128] = '\0';
676 if (bytes_read
!= 128 || param_gethex(hashstring
, 0, hash1
, 128)) {
677 PrintAndLogEx(FAILED
, "Couldn't read SHA-512 file");
682 if (sha512hash(dump
, firmware_size
, hash2
)) {
683 PrintAndLogEx(FAILED
, "Couldn't calculate SHA-512 of Firmware");
687 if (memcmp(hash1
, hash2
, 64)) {
688 PrintAndLogEx(FAILED
, "Couldn't verify integrity of Firmware file (wrong SHA-512)");
692 PrintAndLogEx(SUCCESS
, "RDV4.0 Smartcard Socket Firmware uploading to PM3");
696 uint32_t bytes_sent
= 0;
697 uint32_t bytes_remaining
= firmware_size
;
699 while (bytes_remaining
> 0){
700 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
701 UsbCommand c
= {CMD_SMART_UPLOAD
, {index
+ bytes_sent
, bytes_in_packet
, 0}};
703 // Fill usb bytes with 0xFF
704 memset(c
.d
.asBytes
, 0xFF, USB_CMD_DATA_SIZE
);
705 memcpy(c
.d
.asBytes
, dump
+ bytes_sent
, bytes_in_packet
);
706 clearCommandBuffer();
708 if ( !WaitForResponseTimeout(CMD_ACK
, NULL
, 2000) ) {
709 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
714 bytes_remaining
-= bytes_in_packet
;
715 bytes_sent
+= bytes_in_packet
;
716 printf("."); fflush(stdout
);
720 PrintAndLogEx(SUCCESS
, "RDV4.0 Smartcard Socket Firmware updating, don\'t turn off your PM3!");
722 // trigger the firmware upgrade
723 UsbCommand c
= {CMD_SMART_UPGRADE
, {firmware_size
, 0, 0}};
724 clearCommandBuffer();
727 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
728 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
731 if ( (resp
.arg
[0] & 0xFF ) )
732 PrintAndLogEx(SUCCESS
, "RDV4.0 Smartcard Socket Firmware upgraded successful");
734 PrintAndLogEx(FAILED
, "RDV4.0 Smartcard Socket Firmware Upgrade failed");
738 int CmdSmartInfo(const char *Cmd
){
740 bool errors
= false, silent
= false;
742 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
743 switch (tolower(param_getchar(Cmd
, cmdp
))) {
744 case 'h': return usage_sm_info();
749 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
757 if (errors
) return usage_sm_info();
759 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
760 clearCommandBuffer();
763 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
764 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
768 uint8_t isok
= resp
.arg
[0] & 0xFF;
770 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
774 smart_card_atr_t card
;
775 memcpy(&card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
778 PrintAndLogEx(INFO
, "--- Smartcard Information ---------");
779 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
780 PrintAndLogEx(INFO
, "ISO7618-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
781 PrintAndLogEx(INFO
, "\nhttp://smartcard-atr.appspot.com/parse?ATR=%s", sprint_hex_inrow(card
.atr
, card
.atr_len
) );
784 PrintAndLogEx(NORMAL
, "");
785 PrintAndLogEx(INFO
, "ATR");
786 PrintATR(card
.atr
, card
.atr_len
);
788 // print D/F (brom byte TA1 or defaults)
789 PrintAndLogEx(NORMAL
, "");
790 PrintAndLogEx(INFO
, "D/F (TA1)");
791 int Di
= GetATRDi(card
.atr
, card
.atr_len
);
792 int Fi
= GetATRFi(card
.atr
, card
.atr_len
);
793 float F
= GetATRF(card
.atr
, card
.atr_len
);
794 if (GetATRTA1(card
.atr
, card
.atr_len
) == 0x11)
795 PrintAndLogEx(INFO
, "Using default values...");
797 PrintAndLogEx(NORMAL
, "\t- Di=%d", Di
);
798 PrintAndLogEx(NORMAL
, "\t- Fi=%d", Fi
);
799 PrintAndLogEx(NORMAL
, "\t- F=%.1f MHz", F
);
802 PrintAndLogEx(NORMAL
, "\t- Cycles/ETU=%d", Fi
/Di
);
803 PrintAndLogEx(NORMAL
, "\t- %.1f bits/sec at 4MHz", (float)4000000 / (Fi
/Di
));
804 PrintAndLogEx(NORMAL
, "\t- %.1f bits/sec at Fmax=%.1fMHz", (F
* 1000000) / (Fi
/Di
), F
);
806 PrintAndLogEx(WARNING
, "\t- Di or Fi is RFU.");
812 int CmdSmartReader(const char *Cmd
){
814 bool errors
= false, silent
= false;
816 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
817 switch (tolower(param_getchar(Cmd
, cmdp
))) {
818 case 'h': return usage_sm_reader();
823 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
831 if (errors
) return usage_sm_reader();
833 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
834 clearCommandBuffer();
837 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
838 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
842 uint8_t isok
= resp
.arg
[0] & 0xFF;
844 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
847 smart_card_atr_t card
;
848 memcpy(&card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
850 PrintAndLogEx(INFO
, "ISO7816-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
854 int CmdSmartSetClock(const char *Cmd
){
858 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
859 switch (tolower(param_getchar(Cmd
, cmdp
))) {
860 case 'h': return usage_sm_setclock();
862 clock
= param_get8ex(Cmd
, cmdp
+1, 2, 10);
869 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
876 if (errors
|| cmdp
== 0) return usage_sm_setclock();
878 UsbCommand c
= {CMD_SMART_SETCLOCK
, {clock
, 0, 0}};
879 clearCommandBuffer();
882 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
883 PrintAndLogEx(WARNING
, "smart card select failed");
887 uint8_t isok
= resp
.arg
[0] & 0xFF;
889 PrintAndLogEx(WARNING
, "smart card set clock failed");
895 PrintAndLogEx(SUCCESS
, "Clock changed to 16mhz giving 10800 baudrate");
898 PrintAndLogEx(SUCCESS
, "Clock changed to 8mhz giving 21600 baudrate");
901 PrintAndLogEx(SUCCESS
, "Clock changed to 4mhz giving 86400 baudrate");
909 int CmdSmartList(const char *Cmd
) {
914 int CmdSmartBruteforceSFI(const char *Cmd
) {
916 char ctmp
= tolower(param_getchar(Cmd
, 0));
917 if (ctmp
== 'h') return usage_sm_brute();
919 uint8_t data
[5] = {0x00, 0xB2, 0x00, 0x00, 0x00};
921 PrintAndLogEx(INFO
, "Selecting card");
922 if ( !smart_select(false) ) {
926 PrintAndLogEx(INFO
, "Selecting PPSE aid");
927 CmdSmartRaw("s 0 t d 00a404000e325041592e5359532e4444463031");
928 CmdSmartRaw("0 t d 00a4040007a000000004101000"); // mastercard
929 // CmdSmartRaw("0 t d 00a4040007a0000000031010"); // visa
931 PrintAndLogEx(INFO
, "starting");
933 UsbCommand c
= {CMD_SMART_RAW
, {SC_RAW
, sizeof(data
), 0}};
934 uint8_t* buf
= malloc(USB_CMD_DATA_SIZE
);
938 for (uint8_t i
=1; i
< 4; i
++) {
939 for (int p1
=1; p1
< 5; p1
++) {
942 data
[3] = (i
<< 3) + 4;
944 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
945 clearCommandBuffer();
950 if ( buf
[0] == 0x6C ) {
953 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
954 clearCommandBuffer();
956 uint8_t len
= smart_response(buf
);
960 TLVPrintFromBuffer(buf
+1, len
-3);
964 memset(buf
, 0x00, USB_CMD_DATA_SIZE
);
971 static command_t CommandTable
[] = {
972 {"help", CmdHelp
, 1, "This help"},
973 {"list", CmdSmartList
, 0, "List ISO 7816 history"},
974 {"info", CmdSmartInfo
, 0, "Tag information"},
975 {"reader", CmdSmartReader
, 0, "Act like an IS07816 reader"},
976 {"raw", CmdSmartRaw
, 0, "Send raw hex data to tag"},
977 {"upgrade", CmdSmartUpgrade
, 0, "Upgrade firmware"},
978 {"setclock", CmdSmartSetClock
, 0, "Set clock speed"},
979 {"brute", CmdSmartBruteforceSFI
, 0, "Bruteforce SFI"},
980 {NULL
, NULL
, 0, NULL
}
983 int CmdSmartcard(const char *Cmd
) {
984 clearCommandBuffer();
985 CmdsParse(CommandTable
, Cmd
);
989 int CmdHelp(const char *Cmd
) {
990 CmdsHelp(CommandTable
);