]>
git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdsmartcard.c
c6f08aa4f9f1c816f7b16c67844d1873d09cbe8f
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"
17 #include "smartcard.h"
19 #include "protocols.h"
20 #include "cmdhf.h" // CmdHFlist
21 #include "emv/apduinfo.h" // APDUcode description
22 #include "emv/emvcore.h" // decodeTVL
23 #include "emv/dump.h" // dump_buffer
26 static int CmdHelp(const char *Cmd
);
28 static int usage_sm_raw(void) {
29 PrintAndLogEx(NORMAL
, "Usage: sc raw [h|r|c] d <0A 0B 0C ... hex>");
30 PrintAndLogEx(NORMAL
, " h : this help");
31 PrintAndLogEx(NORMAL
, " r : do not read response");
32 PrintAndLogEx(NORMAL
, " a : active smartcard without select");
33 PrintAndLogEx(NORMAL
, " s : active smartcard with select");
34 PrintAndLogEx(NORMAL
, " t : executes TLV decoder if it possible");
35 PrintAndLogEx(NORMAL
, " d <bytes> : bytes to send");
36 PrintAndLogEx(NORMAL
, "");
37 PrintAndLogEx(NORMAL
, "Examples:");
38 PrintAndLogEx(NORMAL
, " sc raw d 00a404000e315041592e5359532e444446303100 - `1PAY.SYS.DDF01` PPSE directory");
39 PrintAndLogEx(NORMAL
, " sc raw d 00a404000e325041592e5359532e444446303100 - `2PAY.SYS.DDF01` PPSE directory");
43 static int usage_sm_reader(void) {
44 PrintAndLogEx(NORMAL
, "Usage: sc reader [h|s]");
45 PrintAndLogEx(NORMAL
, " h : this help");
46 PrintAndLogEx(NORMAL
, " s : silent (no messages)");
47 PrintAndLogEx(NORMAL
, "");
48 PrintAndLogEx(NORMAL
, "Examples:");
49 PrintAndLogEx(NORMAL
, " sc reader");
53 static int usage_sm_info(void) {
54 PrintAndLogEx(NORMAL
, "Usage: s info [h|s]");
55 PrintAndLogEx(NORMAL
, " h : this help");
56 PrintAndLogEx(NORMAL
, " s : silent (no messages)");
57 PrintAndLogEx(NORMAL
, "");
58 PrintAndLogEx(NORMAL
, "Examples:");
59 PrintAndLogEx(NORMAL
, " sc info");
63 static int usage_sm_upgrade(void) {
64 PrintAndLogEx(NORMAL
, "Upgrade firmware");
65 PrintAndLogEx(NORMAL
, "Usage: sc upgrade f <file name>");
66 PrintAndLogEx(NORMAL
, " h : this help");
67 PrintAndLogEx(NORMAL
, " f <filename> : firmware file name");
68 PrintAndLogEx(NORMAL
, "");
69 PrintAndLogEx(NORMAL
, "Examples:");
70 PrintAndLogEx(NORMAL
, " sc upgrade f myfile");
74 static int usage_sm_setclock(void) {
75 PrintAndLogEx(NORMAL
, "Usage: sc setclock [h] c <clockspeed>");
76 PrintAndLogEx(NORMAL
, " h : this help");
77 PrintAndLogEx(NORMAL
, " c <> : clockspeed (0 = 16mhz, 1=8mhz, 2=4mhz) ");
78 PrintAndLogEx(NORMAL
, "");
79 PrintAndLogEx(NORMAL
, "Examples:");
80 PrintAndLogEx(NORMAL
, " sc setclock c 2");
84 static int usage_sm_brute(void) {
85 PrintAndLogEx(NORMAL
, "Tries to bruteforce SFI, ");
86 PrintAndLogEx(NORMAL
, "Usage: sc brute [h]");
87 PrintAndLogEx(NORMAL
, " h : this help");
88 PrintAndLogEx(NORMAL
, "");
89 PrintAndLogEx(NORMAL
, "Examples:");
90 PrintAndLogEx(NORMAL
, " sc brute");
94 uint8_t GetATRTA1(uint8_t *atr
, size_t atrlen
) {
101 return 0x11; // default value is 0x11, corresponding to fmax=5 MHz, Fi=372, Di=1.
112 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
124 372, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock
143 4, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock
161 int GetATRDi(uint8_t *atr
, size_t atrlen
) {
162 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
164 return DiArray
[TA1
& 0x0f]; // The 4 low-order bits of TA1 (4th MSbit to 1st LSbit) encode Di
167 int GetATRFi(uint8_t *atr
, size_t atrlen
) {
168 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
170 return FiArray
[TA1
>> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi
173 float GetATRF(uint8_t *atr
, size_t atrlen
) {
174 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
176 return FArray
[TA1
>> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi
179 static int PrintATR(uint8_t *atr
, size_t atrlen
) {
181 for (int i
= 1; i
< atrlen
; i
++)
185 PrintAndLogEx(WARNING
, "Check summ error. Must be 0 but: 0x%02x", vxor
);
187 PrintAndLogEx(INFO
, "Check summ OK.");
190 PrintAndLogEx(WARNING
, "Not a direct convention: 0x%02x", atr
[0]);
193 uint8_t K
= T0
& 0x0F;
201 PrintAndLog("TA1 (Maximum clock frequency, proposed bit duration): 0x%02x", atr
[2 + T1len
]);
205 PrintAndLog("TB1 (Deprecated: VPP requirements): 0x%02x", atr
[2 + T1len
]);
209 PrintAndLog("TC1 (Extra delay between bytes required by card): 0x%02x", atr
[2 + T1len
]);
213 TD1
= atr
[2 + T1len
];
214 PrintAndLog("TD1 (First offered transmission protocol, presence of TA2..TD2): 0x%02x. Protocol T=%d", TD1
, TD1
& 0x0f);
218 PrintAndLog("TA2 (Specific protocol and parameters to be used after the ATR): 0x%02x", atr
[2 + T1len
+ TD1len
]);
222 PrintAndLog("TB2 (Deprecated: VPP precise voltage requirement): 0x%02x", atr
[2 + T1len
+ TD1len
]);
226 PrintAndLog("TC2 (Maximum waiting time for protocol T=0): 0x%02x", atr
[2 + T1len
+ TD1len
]);
230 uint8_t TDi
= atr
[2 + T1len
+ TD1len
];
231 PrintAndLog("TD2 (A supported protocol or more global parameters, presence of TA3..TD3): 0x%02x. Protocol T=%d", TDi
, TDi
& 0x0f);
234 bool nextCycle
= true;
239 PrintAndLog("TA%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
243 PrintAndLog("TB%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
247 PrintAndLog("TC%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
251 TDi
= atr
[2 + T1len
+ TD1len
+ TDilen
];
252 PrintAndLog("TD%d: 0x%02x. Protocol T=%d", vi
, TDi
, TDi
& 0x0f);
262 uint8_t calen
= 2 + T1len
+ TD1len
+ TDilen
+ K
;
264 if (atrlen
!= calen
&& atrlen
!= calen
+ 1) // may be CRC
265 PrintAndLogEx(ERR
, "ATR length error. len: %d, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen
, T1len
, TD1len
, TDilen
, K
);
267 PrintAndLogEx(INFO
, "ATR length OK.");
269 PrintAndLog("Historical bytes len: 0x%02x", K
);
271 PrintAndLog("The format of historical bytes: %02x", atr
[2 + T1len
+ TD1len
+ TDilen
]);
273 PrintAndLog("Historical bytes:");
274 dump_buffer(&atr
[2 + T1len
+ TD1len
+ TDilen
], K
, NULL
, 1);
281 static bool smart_select(bool silent
) {
282 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
283 clearCommandBuffer();
286 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
287 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
291 uint8_t isok
= resp
.arg
[0] & 0xFF;
293 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
298 smart_card_atr_t card
;
299 memcpy(&card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
301 PrintAndLogEx(INFO
, "ISO7816-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
307 static int smart_wait(uint8_t *data
) {
309 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2500)) {
310 PrintAndLogEx(WARNING
, "smart card response failed");
314 uint32_t len
= resp
.arg
[0];
316 PrintAndLogEx(WARNING
, "smart card response failed");
319 memcpy(data
, resp
.d
.asBytes
, len
);
320 PrintAndLogEx(SUCCESS
, " %d | %s", len
, sprint_hex_inrow_ex(data
, len
, 32));
323 PrintAndLogEx(SUCCESS
, "%02X%02X | %s", data
[len
- 2], data
[len
- 1], GetAPDUCodeDescription(data
[len
- 2], data
[len
- 1]));
328 static int smart_response(uint8_t apduINS
, uint8_t *data
) {
330 int datalen
= smart_wait(data
);
331 bool needGetData
= false;
337 if (datalen
> 2 && data
[0] != apduINS
) {
338 PrintAndLogEx(ERR
, "Card ACK error. len=0x%x data[0]=%02x", datalen
, data
[0]);
343 if ( data
[datalen
- 2] == 0x61 || data
[datalen
- 2] == 0x9F ) {
348 int len
= data
[datalen
- 1];
349 PrintAndLogEx(INFO
, "Requesting response. len=0x%x", len
);
350 uint8_t getstatus
[] = {ISO7816_GETSTATUS
, 0x00, 0x00, len
};
351 UsbCommand cStatus
= {CMD_SMART_RAW
, {SC_RAW
, sizeof(getstatus
), 0}};
352 memcpy(cStatus
.d
.asBytes
, getstatus
, sizeof(getstatus
) );
353 clearCommandBuffer();
354 SendCommand(&cStatus
);
356 datalen
= smart_wait(data
);
361 if (datalen
> 2 && data
[0] != ISO7816_GETSTATUS
) {
362 PrintAndLogEx(ERR
, "GetResponse ACK error. len=0x%x data[0]=%02x", len
, data
[0]);
367 if (datalen
!= len
+ 2 + 1) { // 2 - response, 1 - ACK
368 PrintAndLogEx(WARNING
, "GetResponse wrong length. Must be: 0x%02x but: 0x%02x", len
, datalen
- 3);
374 memmove(data
, &data
[1], datalen
);
380 int CmdSmartRaw(const char *Cmd
) {
384 bool active_select
= false;
386 bool errors
= false, reply
= true, decodeTLV
= false, breakloop
= false;
387 uint8_t data
[USB_CMD_DATA_SIZE
] = {0x00};
389 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
390 switch (tolower(param_getchar(Cmd
, cmdp
))) {
391 case 'h': return usage_sm_raw();
401 active_select
= true;
409 switch (param_gethex_to_eol(Cmd
, cmdp
+1, data
, sizeof(data
), &hexlen
)) {
411 PrintAndLogEx(WARNING
, "Invalid HEX value.");
414 PrintAndLogEx(WARNING
, "Too many bytes. Max %d bytes", sizeof(data
));
417 PrintAndLogEx(WARNING
, "Hex must have even number of digits.");
425 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
435 if (errors
|| cmdp
== 0 ) return usage_sm_raw();
439 UsbCommand c
= {CMD_SMART_RAW
, {0, hexlen
, 0}};
441 if (active
|| active_select
) {
442 c
.arg
[0] |= SC_CONNECT
;
444 c
.arg
[0] |= SC_SELECT
;
451 memcpy(c
.d
.asBytes
, data
, hexlen
);
452 clearCommandBuffer();
455 // reading response from smart card
458 uint8_t* buf
= calloc(USB_CMD_DATA_SIZE
, sizeof(uint8_t));
462 int len
= smart_response(data
[1], buf
);
468 if ( buf
[0] == 0x6C ) {
471 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
472 clearCommandBuffer();
474 len
= smart_response(data
[1], buf
);
479 if (decodeTLV
&& len
> 4)
480 TLVPrintFromBuffer(buf
+1, len
-3);
487 int ExchangeAPDUSC(uint8_t *datain
, int datainlen
, bool activateCard
, bool leaveSignalON
, uint8_t *dataout
, int maxdataoutlen
, int *dataoutlen
) {
492 printf("* APDU SC\n");
494 UsbCommand c
= {CMD_SMART_RAW
, {SC_RAW
| SC_CONNECT
, datainlen
, 0}};
496 c
.arg
[0] |= SC_SELECT
;
498 memcpy(c
.d
.asBytes
, datain
, datainlen
);
499 clearCommandBuffer();
502 int len
= smart_response(datain
[1], dataout
);
510 if (len
> 1 && dataout
[len
- 2] == 0x6c && datainlen
> 4) {
511 UsbCommand c2
= {CMD_SMART_RAW
, {SC_RAW
, datainlen
, 0}};
512 memcpy(c2
.d
.asBytes
, datain
, datainlen
);
514 int vlen
= 5 + datain
[4];
515 if (datainlen
== vlen
)
518 c2
.d
.asBytes
[vlen
] = dataout
[len
- 1];
520 clearCommandBuffer();
523 len
= smart_response(datain
[1], dataout
);
531 int CmdSmartUpgrade(const char *Cmd
) {
533 PrintAndLogEx(WARNING
, "WARNING - Smartcard socket firmware upgrade.");
534 PrintAndLogEx(WARNING
, "A dangerous command, do wrong and you will brick the smart card socket");
537 char filename
[FILE_PATH_SIZE
] = {0};
541 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
542 switch (tolower(param_getchar(Cmd
, cmdp
))) {
544 //File handling and reading
545 if ( param_getstr(Cmd
, cmdp
+1, filename
, FILE_PATH_SIZE
) >= FILE_PATH_SIZE
) {
546 PrintAndLogEx(FAILED
, "Filename too long");
553 return usage_sm_upgrade();
555 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
562 if (errors
|| cmdp
== 0 ) return usage_sm_upgrade();
565 f
= fopen(filename
, "rb");
567 PrintAndLogEx(FAILED
, "File: %s: not found or locked.", filename
);
571 // get filesize in order to malloc memory
572 fseek(f
, 0, SEEK_END
);
573 long fsize
= ftell(f
);
574 fseek(f
, 0, SEEK_SET
);
577 PrintAndLogEx(WARNING
, "error, when getting filesize");
582 uint8_t *dump
= calloc(fsize
, sizeof(uint8_t));
584 PrintAndLogEx(WARNING
, "error, cannot allocate memory ");
589 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
593 PrintAndLogEx(SUCCESS
, "Smartcard socket firmware uploading to PM3");
596 uint32_t bytes_sent
= 0;
597 uint32_t bytes_remaining
= bytes_read
;
599 while (bytes_remaining
> 0){
600 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
601 UsbCommand c
= {CMD_SMART_UPLOAD
, {index
+ bytes_sent
, bytes_in_packet
, 0}};
603 // Fill usb bytes with 0xFF
604 memset(c
.d
.asBytes
, 0xFF, USB_CMD_DATA_SIZE
);
605 memcpy(c
.d
.asBytes
, dump
+ bytes_sent
, bytes_in_packet
);
606 clearCommandBuffer();
608 if ( !WaitForResponseTimeout(CMD_ACK
, NULL
, 2000) ) {
609 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
614 bytes_remaining
-= bytes_in_packet
;
615 bytes_sent
+= bytes_in_packet
;
616 printf("."); fflush(stdout
);
620 PrintAndLogEx(SUCCESS
, "Smartcard socket firmware updating, don\'t turn off your PM3!");
622 // trigger the firmware upgrade
623 UsbCommand c
= {CMD_SMART_UPGRADE
, {bytes_read
, 0, 0}};
624 clearCommandBuffer();
627 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
628 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
631 if ( (resp
.arg
[0] & 0xFF ) )
632 PrintAndLogEx(SUCCESS
, "Smartcard socket firmware upgraded successful");
634 PrintAndLogEx(FAILED
, "Smartcard socket firmware updating failed");
638 int CmdSmartInfo(const char *Cmd
){
640 bool errors
= false, silent
= false;
642 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
643 switch (tolower(param_getchar(Cmd
, cmdp
))) {
644 case 'h': return usage_sm_info();
649 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
657 if (errors
) return usage_sm_info();
659 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
660 clearCommandBuffer();
663 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
664 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
668 uint8_t isok
= resp
.arg
[0] & 0xFF;
670 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
674 smart_card_atr_t card
;
675 memcpy(&card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
678 PrintAndLogEx(INFO
, "\n--- Smartcard Information ---------");
679 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
680 PrintAndLogEx(INFO
, "ISO76183 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
681 PrintAndLogEx(INFO
, "look up ATR");
682 PrintAndLogEx(INFO
, "http://smartcard-atr.appspot.com/parse?ATR=%s", sprint_hex_inrow(card
.atr
, card
.atr_len
) );
685 PrintAndLogEx(NORMAL
, "");
686 PrintAndLogEx(NORMAL
, "* ATR:");
687 PrintATR(card
.atr
, card
.atr_len
);
689 // print D/F (brom byte TA1 or defaults)
690 PrintAndLogEx(NORMAL
, "");
691 PrintAndLogEx(NORMAL
, "* D/F (TA1):");
692 int Di
= GetATRDi(card
.atr
, card
.atr_len
);
693 int Fi
= GetATRFi(card
.atr
, card
.atr_len
);
694 float F
= GetATRF(card
.atr
, card
.atr_len
);
695 if (GetATRTA1(card
.atr
, card
.atr_len
) == 0x11)
696 PrintAndLogEx(INFO
, "Using default values...");
698 PrintAndLogEx(NORMAL
, "Di=%d", Di
);
699 PrintAndLogEx(NORMAL
, "Fi=%d", Fi
);
700 PrintAndLogEx(NORMAL
, "F=%.1f MHz", F
);
701 PrintAndLogEx(NORMAL
, "Cycles/ETU=%d", Fi
/Di
);
702 PrintAndLogEx(NORMAL
, "%.1f bits/sec at 4MHz", (float)4000000 / (Fi
/Di
));
703 PrintAndLogEx(NORMAL
, "%.1f bits/sec at Fmax=%.1fMHz", (F
* 1000000) / (Fi
/Di
), F
);
708 int CmdSmartReader(const char *Cmd
){
710 bool errors
= false, silent
= false;
712 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
713 switch (tolower(param_getchar(Cmd
, cmdp
))) {
714 case 'h': return usage_sm_reader();
719 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
727 if (errors
) return usage_sm_reader();
729 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
730 clearCommandBuffer();
733 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
734 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
738 uint8_t isok
= resp
.arg
[0] & 0xFF;
740 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
743 smart_card_atr_t card
;
744 memcpy(&card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
746 PrintAndLogEx(INFO
, "ISO7816-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
750 int CmdSmartSetClock(const char *Cmd
){
754 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
755 switch (tolower(param_getchar(Cmd
, cmdp
))) {
756 case 'h': return usage_sm_setclock();
758 clock
= param_get8ex(Cmd
, cmdp
+1, 2, 10);
765 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
772 if (errors
|| cmdp
== 0) return usage_sm_setclock();
774 UsbCommand c
= {CMD_SMART_SETCLOCK
, {clock
, 0, 0}};
775 clearCommandBuffer();
778 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
779 PrintAndLogEx(WARNING
, "smart card select failed");
783 uint8_t isok
= resp
.arg
[0] & 0xFF;
785 PrintAndLogEx(WARNING
, "smart card set clock failed");
791 PrintAndLogEx(SUCCESS
, "Clock changed to 16mhz giving 10800 baudrate");
794 PrintAndLogEx(SUCCESS
, "Clock changed to 8mhz giving 21600 baudrate");
797 PrintAndLogEx(SUCCESS
, "Clock changed to 4mhz giving 86400 baudrate");
805 int CmdSmartList(const char *Cmd
) {
810 int CmdSmartBruteforceSFI(const char *Cmd
) {
812 char ctmp
= tolower(param_getchar(Cmd
, 0));
813 if (ctmp
== 'h') return usage_sm_brute();
815 uint8_t data
[5] = {0x00, 0xB2, 0x00, 0x00, 0x00};
817 PrintAndLogEx(INFO
, "Selecting card");
818 if ( !smart_select(false) ) {
822 PrintAndLogEx(INFO
, "Selecting PPSE aid");
823 CmdSmartRaw("d 00a404000e325041592e5359532e444446303100");
824 CmdSmartRaw("d 00a4040007a000000004101000");
826 PrintAndLogEx(INFO
, "starting");
828 UsbCommand c
= {CMD_SMART_RAW
, {SC_RAW
, sizeof(data
), 0}};
829 uint8_t* buf
= malloc(USB_CMD_DATA_SIZE
);
833 for (uint8_t i
=1; i
< 4; i
++) {
834 for (int p1
=1; p1
< 5; p1
++) {
837 data
[3] = (i
<< 3) + 4;
839 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
840 clearCommandBuffer();
843 smart_response(data
[1], buf
);
846 if ( buf
[0] == 0x6C ) {
849 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
850 clearCommandBuffer();
852 uint8_t len
= smart_response(data
[1], buf
);
856 TLVPrintFromBuffer(buf
+1, len
-3);
860 memset(buf
, 0x00, USB_CMD_DATA_SIZE
);
867 static command_t CommandTable
[] = {
868 {"help", CmdHelp
, 1, "This help"},
869 {"list", CmdSmartList
, 0, "List ISO 7816 history"},
870 {"info", CmdSmartInfo
, 1, "Tag information"},
871 {"reader", CmdSmartReader
, 1, "Act like an IS07816 reader"},
872 {"raw", CmdSmartRaw
, 1, "Send raw hex data to tag"},
873 {"upgrade", CmdSmartUpgrade
, 1, "Upgrade firmware"},
874 {"setclock", CmdSmartSetClock
, 1, "Set clock speed"},
875 {"brute", CmdSmartBruteforceSFI
, 1, "Bruteforce SFI"},
876 {NULL
, NULL
, 0, NULL
}
879 int CmdSmartcard(const char *Cmd
) {
880 clearCommandBuffer();
881 CmdsParse(CommandTable
, Cmd
);
885 int CmdHelp(const char *Cmd
) {
886 CmdsHelp(CommandTable
);