X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/d3c606574f90881daab8585659c18223a7a3c2c3..d00a30d56fc4200a9a921d37ab7dc9e18e092bc0:/client/cmdsmartcard.c diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index edd51b72..b0d96f13 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -18,14 +18,18 @@ #include "smartcard.h" #include "comms.h" #include "protocols.h" +#include "cmdhw.h" #include "cmdhflist.h" #include "emv/apduinfo.h" // APDUcode description #include "emv/emvcore.h" // decodeTVL #include "crypto/libpcrypto.h" // sha512hash #include "emv/dump.h" // dump_buffer +#include "pcsc.h" #define SC_UPGRADE_FILES_DIRECTORY "sc_upgrade_firmware/" +static bool UseAlternativeSmartcardReader = false; // default: use PM3 RDV40 Smartcard Slot (if available) + static int CmdHelp(const char *Cmd); static int usage_sm_raw(void) { @@ -39,8 +43,18 @@ static int usage_sm_raw(void) { PrintAndLogEx(NORMAL, " d : bytes to send"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " sc raw s 0 d 00a404000e315041592e5359532e4444463031 - `1PAY.SYS.DDF01` PPSE directory with get ATR"); - PrintAndLogEx(NORMAL, " sc raw 0 d 00a404000e325041592e5359532e4444463031 - `2PAY.SYS.DDF01` PPSE directory"); + PrintAndLogEx(NORMAL, " sc raw s 0 d 00a404000e315041592e5359532e4444463031 - `1PAY.SYS.DDF01` PSE directory with get ATR"); + return 0; +} + +static int usage_sm_select(void) { + PrintAndLogEx(NORMAL, "Usage: sc select [h|] "); + PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, " : a card reader's name, wildcards allowed, leave empty to pick from available readers"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " sc select : list available card readers and pick"); + PrintAndLogEx(NORMAL, " sc select Gemalto* : select a connected Gemalto card reader" ); return 0; } @@ -162,19 +176,19 @@ float FArray[] = { 0 // b1111 RFU }; -int GetATRDi(uint8_t *atr, size_t atrlen) { +static int GetATRDi(uint8_t *atr, size_t atrlen) { uint8_t TA1 = GetATRTA1(atr, atrlen); return DiArray[TA1 & 0x0f]; // The 4 low-order bits of TA1 (4th MSbit to 1st LSbit) encode Di } -int GetATRFi(uint8_t *atr, size_t atrlen) { +static int GetATRFi(uint8_t *atr, size_t atrlen) { uint8_t TA1 = GetATRTA1(atr, atrlen); return FiArray[TA1 >> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi } -float GetATRF(uint8_t *atr, size_t atrlen) { +static float GetATRF(uint8_t *atr, size_t atrlen) { uint8_t TA1 = GetATRTA1(atr, atrlen); return FArray[TA1 >> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi @@ -185,6 +199,8 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { uint8_t T0 = atr[1]; uint8_t K = T0 & 0x0F; uint8_t TD1 = 0, T1len = 0, TD1len = 0, TDilen = 0; + bool protocol_T0_present = true; + bool protocol_T15_present = false; if (T0 & 0x10) { PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]); @@ -204,6 +220,14 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { if (T0 & 0x80) { TD1 = atr[2 + T1len]; PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f); + protocol_T0_present = false; + if ((TD1 & 0x0f) == 0) { + protocol_T0_present = true; + } + if ((TD1 & 0x0f) == 15) { + protocol_T15_present = true; + } + T1len++; if (TD1 & 0x10) { @@ -221,6 +245,12 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { if (TD1 & 0x80) { uint8_t TDi = atr[2 + T1len + TD1len]; PrintAndLog("\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f); + if ((TDi & 0x0f) == 0) { + protocol_T0_present = true; + } + if ((TDi & 0x0f) == 15) { + protocol_T15_present = true; + } TD1len++; bool nextCycle = true; @@ -251,26 +281,27 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { } } - uint8_t vxor = 0; - for (int i = 1; i < atrlen; i++) - vxor ^= atr[i]; + if (!protocol_T0_present || protocol_T15_present) { // there is CRC Check Byte TCK + uint8_t vxor = 0; + for (int i = 1; i < atrlen; i++) + vxor ^= atr[i]; + + if (vxor) + PrintAndLogEx(WARNING, "Check sum error. Must be 0 got 0x%02X", vxor); + else + PrintAndLogEx(INFO, "Check sum OK."); + } - if (vxor) - PrintAndLogEx(WARNING, "Check summ error. Must be 0 got 0x%02X", vxor); - else - PrintAndLogEx(INFO, "Check summ OK."); - if (atr[0] != 0x3b) PrintAndLogEx(WARNING, "Not a direct convention [ 0x%02x ]", atr[0]); - uint8_t calen = 2 + T1len + TD1len + TDilen + K; if (atrlen != calen && atrlen != calen + 1) // may be CRC PrintAndLogEx(ERR, "ATR length error. len: %d, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen, T1len, TD1len, TDilen, K); if (K > 0) - PrintAndLogEx(INFO, "\nHistorical bytes | len 0x%02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]); + PrintAndLogEx(INFO, "\nHistorical bytes | len %02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]); if (K > 1) { PrintAndLogEx(INFO, "\tHistorical bytes"); @@ -280,106 +311,111 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { return 0; } -static bool smart_select(bool silent) { - UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) { - if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); - return false; +bool smart_getATR(smart_card_atr_t *card) +{ + if (UseAlternativeSmartcardReader) { + return pcscGetATR(card); + } else { + UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}}; + SendCommand(&c); + + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) { + return false; + } + + if (resp.arg[0] & 0xff) { + return resp.arg[0] & 0xFF; + } + + memcpy(card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t)); + + return true; } +} - uint8_t isok = resp.arg[0] & 0xFF; - if (!isok) { +static bool smart_select(bool silent) { + + smart_card_atr_t card; + if (!smart_getATR(&card)) { if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); return false; } if (!silent) { - smart_card_atr_t card; - memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t)); - PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); } return true; } -static int smart_wait(uint8_t *data) { - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - PrintAndLogEx(WARNING, "smart card response timeout"); - return -1; - } - uint32_t len = resp.arg[0]; - if ( !len ) { - PrintAndLogEx(WARNING, "smart card response failed"); - return -2; - } - memcpy(data, resp.d.asBytes, len); - if (len >= 2) { - PrintAndLogEx(SUCCESS, "%02X%02X | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); +static void smart_transmit(uint8_t *data, uint32_t data_len, uint32_t flags, uint8_t *response, int *response_len, uint32_t max_response_len) +{ + // PrintAndLogEx(SUCCESS, "C-TPDU>>>> %s", sprint_hex(data, data_len)); + if (UseAlternativeSmartcardReader) { + *response_len = max_response_len; + pcscTransmit(data, data_len, flags, response, response_len); } else { - PrintAndLogEx(SUCCESS, " %d | %s", len, sprint_hex_inrow_ex(data, len, 8)); - } - - return len; -} + UsbCommand c = {CMD_SMART_RAW, {flags, data_len, 0}}; + memcpy(c.d.asBytes, data, data_len); + SendCommand(&c); -static int smart_response(uint8_t *data) { - - int datalen = smart_wait(data); - bool needGetData = false; + if (!WaitForResponseTimeout(CMD_ACK, &c, 2500)) { + PrintAndLogEx(WARNING, "smart card response timeout"); + *response_len = -1; + return; + } - if (datalen < 2 ) { - goto out; + *response_len = c.arg[0]; + if (*response_len > 0) { + memcpy(response, c.d.asBytes, *response_len); + } } - if ( data[datalen - 2] == 0x61 || data[datalen - 2] == 0x9F ) { - needGetData = true; + if (*response_len <= 0) { + PrintAndLogEx(WARNING, "smart card response failed"); + *response_len = -2; + return; } - if (needGetData) { - int len = data[datalen - 1]; - PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); - uint8_t getstatus[] = {0x00, ISO7816_GETSTATUS, 0x00, 0x00, len}; - UsbCommand cStatus = {CMD_SMART_RAW, {SC_RAW, sizeof(getstatus), 0}}; - memcpy(cStatus.d.asBytes, getstatus, sizeof(getstatus) ); - clearCommandBuffer(); - SendCommand(&cStatus); - - datalen = smart_wait(data); + if (*response_len < 2) { + // PrintAndLogEx(SUCCESS, "R-TPDU %02X | ", response[0]); + return; + } - if (datalen < 2 ) { - goto out; - } + // PrintAndLogEx(SUCCESS, "R-TPDU<<<< %s", sprint_hex(response, *response_len)); + // PrintAndLogEx(SUCCESS, "R-TPDU SW %02X%02X | %s", response[*response_len-2], response[*response_len-1], GetAPDUCodeDescription(response[*response_len-2], response[*response_len-1])); +} - // data wo ACK - if (datalen != len + 2) { - // data with ACK - if (datalen == len + 2 + 1) { // 2 - response, 1 - ACK - if (data[0] != ISO7816_GETSTATUS) { - PrintAndLogEx(ERR, "GetResponse ACK error. len 0x%x | data[0] %02X", len, data[0]); - datalen = 0; - goto out; - } - datalen--; - memmove(data, &data[1], datalen); - } else { - // wrong length - PrintAndLogEx(WARNING, "GetResponse wrong length. Must be 0x%02X got 0x%02X", len, datalen - 3); - } - } +static int CmdSmartSelect(const char *Cmd) +{ + const char *readername; + + if (tolower(param_getchar(Cmd, 0)) == 'h') { + return usage_sm_select(); + } + + if (!PM3hasSmartcardSlot() && !pcscCheckForCardReaders()) { + PrintAndLogEx(WARNING, "No Smartcard Readers available"); + UseAlternativeSmartcardReader = false; + return 1; + } + + int bg, en; + if (param_getptr(Cmd, &bg, &en, 0)) { + UseAlternativeSmartcardReader = pcscSelectAlternativeCardReader(NULL); + } else { + readername = Cmd + bg; + UseAlternativeSmartcardReader = pcscSelectAlternativeCardReader(readername); } - out: - return datalen; + return 0; } -int CmdSmartRaw(const char *Cmd) { + +static int CmdSmartRaw(const char *Cmd) { int hexlen = 0; bool active = false; @@ -387,7 +423,7 @@ int CmdSmartRaw(const char *Cmd) { bool useT0 = false; uint8_t cmdp = 0; bool errors = false, reply = true, decodeTLV = false, breakloop = false; - uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; + uint8_t data[ISO7816_MAX_FRAME_SIZE] = {0x00}; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { @@ -441,101 +477,107 @@ int CmdSmartRaw(const char *Cmd) { //Validations if (errors || cmdp == 0 ) return usage_sm_raw(); - // arg0 = RFU flags - // arg1 = length - UsbCommand c = {CMD_SMART_RAW, {0, hexlen, 0}}; - + uint32_t flags = 0; + uint32_t protocol = 0; if (active || active_select) { - c.arg[0] |= SC_CONNECT; + flags |= SC_CONNECT; if (active_select) - c.arg[0] |= SC_SELECT; + flags |= SC_SELECT; } - if (hexlen > 0) { if (useT0) - c.arg[0] |= SC_RAW_T0; + protocol = SC_RAW_T0; else - c.arg[0] |= SC_RAW; + protocol = SC_RAW; } - - memcpy(c.d.asBytes, data, hexlen ); - clearCommandBuffer(); - SendCommand(&c); + + int response_len = 0; + uint8_t *response = NULL; + if (reply) { + response = calloc(ISO7816_MAX_FRAME_SIZE, sizeof(uint8_t)); + if ( !response ) + return 1; + } + + smart_transmit(data, hexlen, flags|protocol, response, &response_len, ISO7816_MAX_FRAME_SIZE); // reading response from smart card if ( reply ) { - - uint8_t* buf = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); - if ( !buf ) - return 1; - - int len = smart_response(buf); - if ( len < 0 ) { - free(buf); + if ( response_len < 0 ) { + free(response); return 2; } - if ( buf[0] == 0x6C ) { - data[4] = buf[1]; - - memcpy(c.d.asBytes, data, sizeof(data) ); - clearCommandBuffer(); - SendCommand(&c); - len = smart_response(buf); - + if ( response[0] == 0x6C ) { + data[4] = response[1]; + smart_transmit(data, hexlen, protocol, response, &response_len, ISO7816_MAX_FRAME_SIZE); data[4] = 0; } - if (decodeTLV && len > 4) - TLVPrintFromBuffer(buf, len-2); + if (decodeTLV && response_len > 4) + TLVPrintFromBuffer(response, response_len-2); - free(buf); + free(response); } return 0; } -int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { - *dataoutlen = 0; + +int ExchangeAPDUSC(uint8_t *APDU, int APDUlen, bool activateCard, bool leaveSignalON, uint8_t *response, int maxresponselen, int *responselen) +{ + uint8_t TPDU[ISO7816_MAX_FRAME_SIZE]; + + *responselen = 0; if (activateCard) smart_select(false); - PrintAndLogEx(DEBUG, "APDU SC"); - - UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, datainlen, 0}}; + uint32_t flags = SC_RAW_T0; if (activateCard) { - c.arg[0] |= SC_SELECT | SC_CONNECT; + flags |= SC_SELECT | SC_CONNECT; } - memcpy(c.d.asBytes, datain, datainlen); - clearCommandBuffer(); - SendCommand(&c); - - int len = smart_response(dataout); - - if ( len < 0 ) { - return 2; + + if (APDUlen == 4) { // Case 1 + memcpy(TPDU, APDU, 4); + TPDU[4] = 0x00; + smart_transmit(TPDU, 5, flags, response, responselen, maxresponselen); + } else if (APDUlen == 5) { // Case 2 Short + smart_transmit(APDU, 5, flags, response, responselen, maxresponselen); + if (response[0] == 0x6C) { // wrong Le + uint16_t Le = APDU[4] ? APDU[4] : 256; + uint8_t La = response[1]; + memcpy(TPDU, APDU, 5); + TPDU[4] = La; + smart_transmit(TPDU, 5, SC_RAW_T0, response, responselen, maxresponselen); + if (Le < La && *responselen >= 0) { + response[Le] = response[*responselen-2]; + response[Le+1] = response[*responselen-1]; + *responselen = Le + 2; + } + } + } else if (APDU[4] != 0 && APDUlen == 5 + APDU[4]) { // Case 3 Short + smart_transmit(APDU, APDUlen, flags, response, responselen, maxresponselen); + } else if (APDU[4] != 0 && APDUlen == 5 + APDU[4] + 1) { // Case 4 Short + smart_transmit(APDU, APDUlen-1, flags, response, responselen, maxresponselen); + if (response[0] == 0x90 && response[1] == 0x00) { + uint8_t Le = APDU[APDUlen-1]; + uint8_t get_response[5] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, Le}; + return ExchangeAPDUSC(get_response, 5, false, leaveSignalON, response, maxresponselen, responselen); + } + } else { // Long Cases not yet implemented + PrintAndLogEx(ERR, "Long APDUs not yet implemented"); + *responselen = -3; } - // retry - if (len > 1 && dataout[len - 2] == 0x6c && datainlen > 4) { - UsbCommand c2 = {CMD_SMART_RAW, {SC_RAW_T0, datainlen, 0}}; - memcpy(c2.d.asBytes, datain, 5); - - // transfer length via T=0 - c2.d.asBytes[4] = dataout[len - 1]; - - clearCommandBuffer(); - SendCommand(&c2); - - len = smart_response(dataout); + if (*responselen < 0 ) { + return 1; + } else { + return 0; } - *dataoutlen = len; - - return 0; } -int CmdSmartUpgrade(const char *Cmd) { +static int CmdSmartUpgrade(const char *Cmd) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(WARNING, "WARNING - RDV4.0 Smartcard Socket Firmware upgrade."); @@ -735,7 +777,8 @@ int CmdSmartUpgrade(const char *Cmd) { return 0; } -int CmdSmartInfo(const char *Cmd){ + +static int CmdSmartInfo(const char *Cmd){ uint8_t cmdp = 0; bool errors = false, silent = false; @@ -756,24 +799,17 @@ int CmdSmartInfo(const char *Cmd){ //Validations if (errors ) return usage_sm_info(); - UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) { + smart_card_atr_t card; + if (!smart_getATR(&card)) { if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); return 1; } - - uint8_t isok = resp.arg[0] & 0xFF; - if (!isok) { - if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); + + if (!card.atr_len) { + if (!silent) PrintAndLogEx(ERR, "can't get ATR from a smart card"); return 1; } - smart_card_atr_t card; - memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t)); - // print header PrintAndLogEx(INFO, "--- Smartcard Information ---------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); @@ -830,28 +866,18 @@ int CmdSmartReader(const char *Cmd){ //Validations if (errors ) return usage_sm_reader(); - UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) { - if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); - return 1; - } - - uint8_t isok = resp.arg[0] & 0xFF; - if (!isok) { + smart_card_atr_t card; + if (!smart_getATR(&card)) { if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); return 1; } - smart_card_atr_t card; - memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t)); PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); return 0; } -int CmdSmartSetClock(const char *Cmd){ + +static int CmdSmartSetClock(const char *Cmd){ uint8_t cmdp = 0; bool errors = false; uint8_t clock = 0; @@ -906,12 +932,18 @@ int CmdSmartSetClock(const char *Cmd){ return 0; } -int CmdSmartList(const char *Cmd) { - CmdHFList("7816"); + +static int CmdSmartList(const char *Cmd) { + if (UseAlternativeSmartcardReader) { + CmdHFList("7816 p"); + } else { + CmdHFList("7816"); + } return 0; } -int CmdSmartBruteforceSFI(const char *Cmd) { + +static int CmdSmartBruteforceSFI(const char *Cmd) { char ctmp = tolower(param_getchar(Cmd, 0)); if (ctmp == 'h') return usage_sm_brute(); @@ -923,16 +955,16 @@ int CmdSmartBruteforceSFI(const char *Cmd) { return 1; } - PrintAndLogEx(INFO, "Selecting PPSE aid"); + PrintAndLogEx(INFO, "Selecting PSE aid"); CmdSmartRaw("s 0 t d 00a404000e325041592e5359532e4444463031"); CmdSmartRaw("0 t d 00a4040007a000000004101000"); // mastercard // CmdSmartRaw("0 t d 00a4040007a0000000031010"); // visa PrintAndLogEx(INFO, "starting"); - UsbCommand c = {CMD_SMART_RAW, {SC_RAW, sizeof(data), 0}}; - uint8_t* buf = malloc(USB_CMD_DATA_SIZE); - if ( !buf ) + int response_len = 0; + uint8_t* response = malloc(ISO7816_MAX_FRAME_SIZE); + if (!response) return 1; for (uint8_t i=1; i < 4; i++) { @@ -941,52 +973,47 @@ int CmdSmartBruteforceSFI(const char *Cmd) { data[2] = p1; data[3] = (i << 3) + 4; - memcpy(c.d.asBytes, data, sizeof(data) ); - clearCommandBuffer(); - SendCommand(&c); + smart_transmit(data, sizeof(data), SC_RAW_T0, response, &response_len, ISO7816_MAX_FRAME_SIZE); - smart_response(buf); - - if ( buf[0] == 0x6C ) { - data[4] = buf[1]; - - memcpy(c.d.asBytes, data, sizeof(data) ); - clearCommandBuffer(); - SendCommand(&c); - uint8_t len = smart_response(buf); + if ( response[0] == 0x6C ) { + data[4] = response[1]; + smart_transmit(data, sizeof(data), SC_RAW_T0, response, &response_len, ISO7816_MAX_FRAME_SIZE); // TLV decoder - if (len > 4) - TLVPrintFromBuffer(buf+1, len-3); + if (response_len > 4) + TLVPrintFromBuffer(response+1, response_len-3); data[4] = 0; } - memset(buf, 0x00, USB_CMD_DATA_SIZE); + memset(response, 0x00, ISO7816_MAX_FRAME_SIZE); } } - free(buf); + free(response); return 0; } static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"list", CmdSmartList, 0, "List ISO 7816 history"}, - {"info", CmdSmartInfo, 0, "Tag information"}, - {"reader", CmdSmartReader, 0, "Act like an IS07816 reader"}, - {"raw", CmdSmartRaw, 0, "Send raw hex data to tag"}, + {"select", CmdSmartSelect, 1, "Select the Smartcard Reader to use"}, + {"list", CmdSmartList, 1, "List ISO 7816 history"}, + {"info", CmdSmartInfo, 1, "Tag information"}, + {"reader", CmdSmartReader, 1, "Act like an IS07816 reader"}, + {"raw", CmdSmartRaw, 1, "Send raw hex data to tag"}, {"upgrade", CmdSmartUpgrade, 0, "Upgrade firmware"}, - {"setclock", CmdSmartSetClock, 0, "Set clock speed"}, - {"brute", CmdSmartBruteforceSFI, 0, "Bruteforce SFI"}, + {"setclock", CmdSmartSetClock, 1, "Set clock speed"}, + {"brute", CmdSmartBruteforceSFI, 1, "Bruteforce SFI"}, {NULL, NULL, 0, NULL} }; + int CmdSmartcard(const char *Cmd) { clearCommandBuffer(); CmdsParse(CommandTable, Cmd); return 0; } -int CmdHelp(const char *Cmd) { + +static int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); return 0; }