diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index d97451e47..24803035c 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -306,7 +306,7 @@ static int smart_wait(uint8_t *data) { return len; } -static int smart_response(uint8_t apduINS, uint8_t *data) { +static int smart_response(uint8_t *data) { int datalen = smart_wait(data); bool needGetData = false; @@ -315,12 +315,6 @@ static int smart_response(uint8_t apduINS, uint8_t *data) { goto out; } - if (datalen > 2 && data[0] != apduINS) { - PrintAndLogEx(ERR, "Card ACK error. len=0x%x data[0]=%02x", datalen, data[0]); - datalen = 0; - goto out; - } - if ( data[datalen - 2] == 0x61 || data[datalen - 2] == 0x9F ) { needGetData = true; } @@ -339,22 +333,26 @@ static int smart_response(uint8_t apduINS, uint8_t *data) { if (datalen < 2 ) { goto out; } - - if (datalen > 2 && data[0] != ISO7816_GETSTATUS) { - PrintAndLogEx(ERR, "GetResponse ACK error. len=0x%x data[0]=%02x", len, data[0]); - datalen = 0; - goto out; - } - if (datalen != len + 2 + 1) { // 2 - response, 1 - ACK - PrintAndLogEx(WARNING, "GetResponse wrong length. Must be: 0x%02x but: 0x%02x", len, datalen - 3); + // 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 but: 0x%02x", len, datalen - 3); + } } } - if (datalen > 2) { - datalen--; - memmove(data, &data[1], datalen); - } out: return datalen; } @@ -441,7 +439,7 @@ int CmdSmartRaw(const char *Cmd) { if ( !buf ) return 1; - int len = smart_response(data[1], buf); + int len = smart_response(buf); if ( len < 0 ) { free(buf); return 2; @@ -453,7 +451,7 @@ int CmdSmartRaw(const char *Cmd) { memcpy(c.d.asBytes, data, sizeof(data) ); clearCommandBuffer(); SendCommand(&c); - len = smart_response(data[1], buf); + len = smart_response(buf); data[4] = 0; } @@ -473,15 +471,15 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave smart_select(false); printf("* APDU SC\n"); - UsbCommand c = {CMD_SMART_RAW, {SC_RAW | SC_CONNECT, datainlen, 0}}; + UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, datainlen, 0}}; if (activateCard) { - c.arg[0] |= SC_SELECT; + c.arg[0] |= SC_SELECT | SC_CONNECT; } memcpy(c.d.asBytes, datain, datainlen); clearCommandBuffer(); SendCommand(&c); - int len = smart_response(datain[1], dataout); + int len = smart_response(dataout); if ( len < 0 ) { return 2; @@ -489,19 +487,16 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave // retry if (len > 1 && dataout[len - 2] == 0x6c && datainlen > 4) { - UsbCommand c2 = {CMD_SMART_RAW, {SC_RAW, datainlen, 0}}; - memcpy(c2.d.asBytes, datain, datainlen); + UsbCommand c2 = {CMD_SMART_RAW, {SC_RAW_T0, datainlen, 0}}; + memcpy(c2.d.asBytes, datain, 5); - int vlen = 5 + datain[4]; - if (datainlen == vlen) - datainlen++; - - c2.d.asBytes[vlen] = dataout[len - 1]; + // transfer length via T=0 + c2.d.asBytes[4] = dataout[len - 1]; clearCommandBuffer(); SendCommand(&c2); - len = smart_response(datain[1], dataout); + len = smart_response(dataout); } *dataoutlen = len; @@ -822,7 +817,7 @@ int CmdSmartBruteforceSFI(const char *Cmd) { clearCommandBuffer(); SendCommand(&c); - smart_response(data[1], buf); + smart_response(buf); // if 0x6C if ( buf[0] == 0x6C ) { @@ -831,7 +826,7 @@ int CmdSmartBruteforceSFI(const char *Cmd) { memcpy(c.d.asBytes, data, sizeof(data) ); clearCommandBuffer(); SendCommand(&c); - uint8_t len = smart_response(data[1], buf); + uint8_t len = smart_response(buf); // TLV decoder if (len > 4) diff --git a/common/i2c.c b/common/i2c.c index ecf5a5bd9..ea830a1bd 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -698,14 +698,14 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) { } } - if ((flags & SC_RAW)) { + if ((flags & SC_RAW) || (flags & SC_RAW_T0)) { LogTrace(data, arg1, 0, 0, NULL, true); // Send raw bytes // asBytes = A0 A4 00 00 02 // arg1 = len 5 - bool res = I2C_BufferWrite(data, arg1, I2C_DEVICE_CMD_SEND, I2C_DEVICE_ADDRESS_MAIN); + bool res = I2C_BufferWrite(data, arg1, ((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND), I2C_DEVICE_ADDRESS_MAIN); if ( !res && MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); // read bytes from module diff --git a/common/i2c.h b/common/i2c.h index 8350029bd..e5ff26e4d 100644 --- a/common/i2c.h +++ b/common/i2c.h @@ -17,6 +17,7 @@ #define I2C_DEVICE_CMD_SETBAUD 0x04 #define I2C_DEVICE_CMD_SIM_CLC 0x05 #define I2C_DEVICE_CMD_GETVERSION 0x06 +#define I2C_DEVICE_CMD_SEND_T0 0x07 void I2C_recovery(void); diff --git a/include/mifare.h b/include/mifare.h index 63cdf0fb6..cda7cfe9d 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -109,7 +109,8 @@ typedef enum SMARTCARD_COMMAND { SC_CONNECT = (1 << 0), SC_NO_DISCONNECT = (1 << 1), SC_RAW = (1 << 2), - SC_SELECT = (1 << 3) + SC_SELECT = (1 << 3), + SC_RAW_T0 = (1 << 4), } smartcard_command_t; //-----------------------------------------------------------------------------