]>
cvs.zerfleddert.de Git - proxmark3-svn/blob - client/cmdsmartcard.c
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
25 static int CmdHelp(const char *Cmd
);
27 static int usage_sm_raw(void) {
28 PrintAndLogEx(NORMAL
, "Usage: sc raw [h|r|c] d <0A 0B 0C ... hex>");
29 PrintAndLogEx(NORMAL
, " h : this help");
30 PrintAndLogEx(NORMAL
, " r : do not read response");
31 PrintAndLogEx(NORMAL
, " a : active smartcard without select");
32 PrintAndLogEx(NORMAL
, " s : active smartcard with select");
33 PrintAndLogEx(NORMAL
, " t : executes TLV decoder if it possible");
34 PrintAndLogEx(NORMAL
, " d <bytes> : bytes to send");
35 PrintAndLogEx(NORMAL
, "");
36 PrintAndLogEx(NORMAL
, "Examples:");
37 PrintAndLogEx(NORMAL
, " sc raw d 00a404000e315041592e5359532e444446303100 - `1PAY.SYS.DDF01` PPSE directory");
38 PrintAndLogEx(NORMAL
, " sc raw d 00a404000e325041592e5359532e444446303100 - `2PAY.SYS.DDF01` PPSE directory");
42 static int usage_sm_reader(void) {
43 PrintAndLogEx(NORMAL
, "Usage: sc reader [h|s]");
44 PrintAndLogEx(NORMAL
, " h : this help");
45 PrintAndLogEx(NORMAL
, " s : silent (no messages)");
46 PrintAndLogEx(NORMAL
, "");
47 PrintAndLogEx(NORMAL
, "Examples:");
48 PrintAndLogEx(NORMAL
, " sc reader");
52 static int usage_sm_info(void) {
53 PrintAndLogEx(NORMAL
, "Usage: s info [h|s]");
54 PrintAndLogEx(NORMAL
, " h : this help");
55 PrintAndLogEx(NORMAL
, " s : silent (no messages)");
56 PrintAndLogEx(NORMAL
, "");
57 PrintAndLogEx(NORMAL
, "Examples:");
58 PrintAndLogEx(NORMAL
, " sc info");
62 static int usage_sm_upgrade(void) {
63 PrintAndLogEx(NORMAL
, "Upgrade firmware");
64 PrintAndLogEx(NORMAL
, "Usage: sc upgrade f <file name>");
65 PrintAndLogEx(NORMAL
, " h : this help");
66 PrintAndLogEx(NORMAL
, " f <filename> : firmware file name");
67 PrintAndLogEx(NORMAL
, "");
68 PrintAndLogEx(NORMAL
, "Examples:");
69 PrintAndLogEx(NORMAL
, " sc upgrade f myfile");
73 static int usage_sm_setclock(void) {
74 PrintAndLogEx(NORMAL
, "Usage: sc setclock [h] c <clockspeed>");
75 PrintAndLogEx(NORMAL
, " h : this help");
76 PrintAndLogEx(NORMAL
, " c <> : clockspeed (0 = 16mhz, 1=8mhz, 2=4mhz) ");
77 PrintAndLogEx(NORMAL
, "");
78 PrintAndLogEx(NORMAL
, "Examples:");
79 PrintAndLogEx(NORMAL
, " sc setclock c 2");
83 static int usage_sm_brute(void) {
84 PrintAndLogEx(NORMAL
, "Tries to bruteforce SFI, ");
85 PrintAndLogEx(NORMAL
, "Usage: sc brute [h]");
86 PrintAndLogEx(NORMAL
, " h : this help");
87 PrintAndLogEx(NORMAL
, "");
88 PrintAndLogEx(NORMAL
, "Examples:");
89 PrintAndLogEx(NORMAL
, " sc brute");
93 static bool smart_select(bool silent
) {
94 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
98 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
99 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
103 uint8_t isok
= resp
.arg
[0] & 0xFF;
105 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
110 smart_card_atr_t card
;
111 memcpy(&card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
113 PrintAndLogEx(INFO
, "ISO7816-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
119 static int smart_wait(uint8_t *data
) {
121 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2500)) {
122 PrintAndLogEx(WARNING
, "smart card response failed");
126 uint32_t len
= resp
.arg
[0];
128 PrintAndLogEx(WARNING
, "smart card response failed");
131 memcpy(data
, resp
.d
.asBytes
, len
);
132 PrintAndLogEx(SUCCESS
, " %d | %s", len
, sprint_hex_inrow_ex(data
, len
, 32));
135 PrintAndLogEx(SUCCESS
, "%02X%02X | %s", data
[len
- 2], data
[len
- 1], GetAPDUCodeDescription(data
[len
- 2], data
[len
- 1]));
140 static int smart_response(uint8_t *data
) {
143 int datalen
= smart_wait(data
);
145 if ( data
[datalen
- 2] == 0x61 || data
[datalen
- 2] == 0x9F ) {
146 len
= data
[datalen
- 1];
153 PrintAndLogEx(INFO
, "Requesting response. len=0x%x", len
);
154 uint8_t getstatus
[] = {ISO7816_GETSTATUS
, 0x00, 0x00, len
};
155 UsbCommand cStatus
= {CMD_SMART_RAW
, {SC_RAW
, sizeof(getstatus
), 0}};
156 memcpy(cStatus
.d
.asBytes
, getstatus
, sizeof(getstatus
) );
157 clearCommandBuffer();
158 SendCommand(&cStatus
);
160 datalen
= smart_wait(data
);
166 int CmdSmartRaw(const char *Cmd
) {
170 bool active_select
= false;
172 bool errors
= false, reply
= true, decodeTLV
= false, breakloop
= false;
173 uint8_t data
[USB_CMD_DATA_SIZE
] = {0x00};
175 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
176 switch (tolower(param_getchar(Cmd
, cmdp
))) {
177 case 'h': return usage_sm_raw();
187 active_select
= true;
195 switch (param_gethex_to_eol(Cmd
, cmdp
+1, data
, sizeof(data
), &hexlen
)) {
197 PrintAndLogEx(WARNING
, "Invalid HEX value.");
200 PrintAndLogEx(WARNING
, "Too many bytes. Max %d bytes", sizeof(data
));
203 PrintAndLogEx(WARNING
, "Hex must have even number of digits.");
211 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
221 if (errors
|| cmdp
== 0 ) return usage_sm_raw();
225 UsbCommand c
= {CMD_SMART_RAW
, {0, hexlen
, 0}};
227 if (active
|| active_select
) {
228 c
.arg
[0] |= SC_CONNECT
;
230 c
.arg
[0] |= SC_SELECT
;
237 memcpy(c
.d
.asBytes
, data
, hexlen
);
238 clearCommandBuffer();
241 // reading response from smart card
244 uint8_t* buf
= calloc(USB_CMD_DATA_SIZE
, sizeof(uint8_t));
248 int len
= smart_response(buf
);
254 if ( buf
[0] == 0x6C ) {
257 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
258 clearCommandBuffer();
260 len
= smart_response(buf
);
265 if (decodeTLV
&& len
> 4)
266 TLVPrintFromBuffer(buf
+1, len
-3);
273 int ExchangeAPDUSC(uint8_t *datain
, int datainlen
, bool activateCard
, bool leaveSignalON
, uint8_t *dataout
, int maxdataoutlen
, int *dataoutlen
) {
278 printf("* APDU SC\n");
280 UsbCommand c
= {CMD_SMART_RAW
, {SC_RAW
| SC_CONNECT
, datainlen
, 0}};
282 c
.arg
[0] |= SC_SELECT
;
284 memcpy(c
.d
.asBytes
, datain
, datainlen
);
285 clearCommandBuffer();
288 int len
= smart_response(dataout
);
300 int CmdSmartUpgrade(const char *Cmd
) {
302 PrintAndLogEx(WARNING
, "WARNING - Smartcard socket firmware upgrade.");
303 PrintAndLogEx(WARNING
, "A dangerous command, do wrong and you will brick the smart card socket");
306 char filename
[FILE_PATH_SIZE
] = {0};
310 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
311 switch (tolower(param_getchar(Cmd
, cmdp
))) {
313 //File handling and reading
314 if ( param_getstr(Cmd
, cmdp
+1, filename
, FILE_PATH_SIZE
) >= FILE_PATH_SIZE
) {
315 PrintAndLogEx(FAILED
, "Filename too long");
322 return usage_sm_upgrade();
324 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
331 if (errors
|| cmdp
== 0 ) return usage_sm_upgrade();
334 f
= fopen(filename
, "rb");
336 PrintAndLogEx(FAILED
, "File: %s: not found or locked.", filename
);
340 // get filesize in order to malloc memory
341 fseek(f
, 0, SEEK_END
);
342 long fsize
= ftell(f
);
343 fseek(f
, 0, SEEK_SET
);
346 PrintAndLogEx(WARNING
, "error, when getting filesize");
351 uint8_t *dump
= calloc(fsize
, sizeof(uint8_t));
353 PrintAndLogEx(WARNING
, "error, cannot allocate memory ");
358 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
362 PrintAndLogEx(SUCCESS
, "Smartcard socket firmware uploading to PM3");
365 uint32_t bytes_sent
= 0;
366 uint32_t bytes_remaining
= bytes_read
;
368 while (bytes_remaining
> 0){
369 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
370 UsbCommand c
= {CMD_SMART_UPLOAD
, {index
+ bytes_sent
, bytes_in_packet
, 0}};
372 // Fill usb bytes with 0xFF
373 memset(c
.d
.asBytes
, 0xFF, USB_CMD_DATA_SIZE
);
374 memcpy(c
.d
.asBytes
, dump
+ bytes_sent
, bytes_in_packet
);
375 clearCommandBuffer();
377 if ( !WaitForResponseTimeout(CMD_ACK
, NULL
, 2000) ) {
378 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
383 bytes_remaining
-= bytes_in_packet
;
384 bytes_sent
+= bytes_in_packet
;
385 printf("."); fflush(stdout
);
389 PrintAndLogEx(SUCCESS
, "Smartcard socket firmware updating, don\'t turn off your PM3!");
391 // trigger the firmware upgrade
392 UsbCommand c
= {CMD_SMART_UPGRADE
, {bytes_read
, 0, 0}};
393 clearCommandBuffer();
396 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
397 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
400 if ( (resp
.arg
[0] & 0xFF ) )
401 PrintAndLogEx(SUCCESS
, "Smartcard socket firmware upgraded successful");
403 PrintAndLogEx(FAILED
, "Smartcard socket firmware updating failed");
407 int CmdSmartInfo(const char *Cmd
){
409 bool errors
= false, silent
= false;
411 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
412 switch (tolower(param_getchar(Cmd
, cmdp
))) {
413 case 'h': return usage_sm_info();
418 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
426 if (errors
) return usage_sm_info();
428 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
429 clearCommandBuffer();
432 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
433 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
437 uint8_t isok
= resp
.arg
[0] & 0xFF;
439 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
443 smart_card_atr_t card
;
444 memcpy(&card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
447 PrintAndLogEx(INFO
, "\n--- Smartcard Information ---------");
448 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
449 PrintAndLogEx(INFO
, "ISO76183 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
450 PrintAndLogEx(INFO
, "look up ATR");
451 PrintAndLogEx(INFO
, "http://smartcard-atr.appspot.com/parse?ATR=%s", sprint_hex_inrow(card
.atr
, card
.atr_len
) );
455 int CmdSmartReader(const char *Cmd
){
457 bool errors
= false, silent
= false;
459 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
460 switch (tolower(param_getchar(Cmd
, cmdp
))) {
461 case 'h': return usage_sm_reader();
466 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
474 if (errors
) return usage_sm_reader();
476 UsbCommand c
= {CMD_SMART_ATR
, {0, 0, 0}};
477 clearCommandBuffer();
480 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
481 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
485 uint8_t isok
= resp
.arg
[0] & 0xFF;
487 if (!silent
) PrintAndLogEx(WARNING
, "smart card select failed");
490 smart_card_atr_t card
;
491 memcpy(&card
, (smart_card_atr_t
*)resp
.d
.asBytes
, sizeof(smart_card_atr_t
));
493 PrintAndLogEx(INFO
, "ISO7816-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));
497 int CmdSmartSetClock(const char *Cmd
){
501 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
502 switch (tolower(param_getchar(Cmd
, cmdp
))) {
503 case 'h': return usage_sm_setclock();
505 clock
= param_get8ex(Cmd
, cmdp
+1, 2, 10);
512 PrintAndLogEx(WARNING
, "Unknown parameter '%c'", param_getchar(Cmd
, cmdp
));
519 if (errors
|| cmdp
== 0) return usage_sm_setclock();
521 UsbCommand c
= {CMD_SMART_SETCLOCK
, {clock
, 0, 0}};
522 clearCommandBuffer();
525 if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) {
526 PrintAndLogEx(WARNING
, "smart card select failed");
530 uint8_t isok
= resp
.arg
[0] & 0xFF;
532 PrintAndLogEx(WARNING
, "smart card set clock failed");
538 PrintAndLogEx(SUCCESS
, "Clock changed to 16mhz giving 10800 baudrate");
541 PrintAndLogEx(SUCCESS
, "Clock changed to 8mhz giving 21600 baudrate");
544 PrintAndLogEx(SUCCESS
, "Clock changed to 4mhz giving 86400 baudrate");
552 int CmdSmartList(const char *Cmd
) {
557 int CmdSmartBruteforceSFI(const char *Cmd
) {
559 char ctmp
= tolower(param_getchar(Cmd
, 0));
560 if (ctmp
== 'h') return usage_sm_brute();
562 uint8_t data
[5] = {0x00, 0xB2, 0x00, 0x00, 0x00};
564 PrintAndLogEx(INFO
, "Selecting card");
565 if ( !smart_select(false) ) {
569 PrintAndLogEx(INFO
, "Selecting PPSE aid");
570 CmdSmartRaw("d 00a404000e325041592e5359532e444446303100");
571 CmdSmartRaw("d 00a4040007a000000004101000");
573 PrintAndLogEx(INFO
, "starting");
575 UsbCommand c
= {CMD_SMART_RAW
, {SC_RAW
, sizeof(data
), 0}};
576 uint8_t* buf
= malloc(USB_CMD_DATA_SIZE
);
580 for (uint8_t i
=1; i
< 4; i
++) {
581 for (int p1
=1; p1
< 5; p1
++) {
584 data
[3] = (i
<< 3) + 4;
586 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
587 clearCommandBuffer();
593 if ( buf
[0] == 0x6C ) {
596 memcpy(c
.d
.asBytes
, data
, sizeof(data
) );
597 clearCommandBuffer();
599 uint8_t len
= smart_response(buf
);
603 TLVPrintFromBuffer(buf
+1, len
-3);
607 memset(buf
, 0x00, USB_CMD_DATA_SIZE
);
614 static command_t CommandTable
[] = {
615 {"help", CmdHelp
, 1, "This help"},
616 {"list", CmdSmartList
, 0, "List ISO 7816 history"},
617 {"info", CmdSmartInfo
, 1, "Tag information"},
618 {"reader", CmdSmartReader
, 1, "Act like an IS07816 reader"},
619 {"raw", CmdSmartRaw
, 1, "Send raw hex data to tag"},
620 {"upgrade", CmdSmartUpgrade
, 1, "Upgrade firmware"},
621 {"setclock", CmdSmartSetClock
, 1, "Set clock speed"},
622 {"brute", CmdSmartBruteforceSFI
, 1, "Bruteforce SFI"},
623 {NULL
, NULL
, 0, NULL
}
626 int CmdSmartcard(const char *Cmd
) {
627 clearCommandBuffer();
628 CmdsParse(CommandTable
, Cmd
);
632 int CmdHelp(const char *Cmd
) {
633 CmdsHelp(CommandTable
);