From c04a4b60cefc545641582da165c42b3023f5f753 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Sun, 1 Oct 2017 17:52:10 +0200 Subject: [PATCH] Don't do iso14443-4 select for mifare emulations on processor cards (IDPrime, SmartMX, ...) --- armsrc/appmain.c | 2 +- armsrc/epa.c | 2 +- armsrc/iso14443a.c | 35 ++++++++++++++++++----------------- armsrc/iso14443a.h | 2 +- armsrc/mifarecmd.c | 34 +++++++++++++++++----------------- client/cmdhf14a.c | 11 ++++++++++- client/cmdhfmfu.c | 2 +- client/mifarehost.c | 28 ++++++++++++++-------------- include/mifare.h | 3 ++- 9 files changed, 65 insertions(+), 54 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index b375c3ce..e292483b 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -450,7 +450,7 @@ void StandAloneMode14a() SpinDelay(300); } } - if (!iso14443a_select_card(uid, &hi14a_card[selected], &cuid, true, 0)) + if (!iso14443a_select_card(uid, &hi14a_card[selected], &cuid, true, 0, true)) continue; else { diff --git a/armsrc/epa.c b/armsrc/epa.c index f434aa34..fd71430b 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -530,7 +530,7 @@ int EPA_Setup() // power up the field iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); // select the card - return_code = iso14443a_select_card(uid, &card_select_info, NULL, true, 0); + return_code = iso14443a_select_card(uid, &card_select_info, NULL, true, 0, false); if (return_code == 1) { // send the PPS request ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 29b23833..e9ad2535 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1733,7 +1733,8 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity) // fills the card info record unless NULL // if anticollision is false, then the UID must be provided in uid_ptr[] // and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID) -int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades) { +// requests ATS unless no_rats is true +int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) { uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP uint8_t sel_all[] = { 0x93,0x20 }; uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; @@ -1868,24 +1869,24 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u // non iso14443a compliant tag if( (sak & 0x20) == 0) return 2; - // Request for answer to select - AppendCrc14443a(rats, 2); - ReaderTransmit(rats, sizeof(rats), NULL); + if (!no_rats) { + // Request for answer to select + AppendCrc14443a(rats, 2); + ReaderTransmit(rats, sizeof(rats), NULL); - if (!(len = ReaderReceive(resp, resp_par))) return 0; + if (!(len = ReaderReceive(resp, resp_par))) return 0; - - if(p_hi14a_card) { - memcpy(p_hi14a_card->ats, resp, sizeof(p_hi14a_card->ats)); - p_hi14a_card->ats_len = len; - } - - // reset the PCB block number - iso14_pcb_blocknum = 0; + if(p_hi14a_card) { + memcpy(p_hi14a_card->ats, resp, len); + p_hi14a_card->ats_len = len; + } - // set default timeout based on ATS - iso14a_set_ATS_timeout(resp); + // reset the PCB block number + iso14_pcb_blocknum = 0; + // set default timeout based on ATS + iso14a_set_ATS_timeout(resp); + } return 1; } @@ -1971,7 +1972,7 @@ void ReaderIso14443a(UsbCommand *c) iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); if(!(param & ISO14A_NO_SELECT)) { iso14a_card_select_t *card = (iso14a_card_select_t*)buf; - arg0 = iso14443a_select_card(NULL, card, NULL, true, 0); + arg0 = iso14443a_select_card(NULL, card, NULL, true, 0, param & ISO14A_NO_RATS); cmd_send(CMD_ACK,arg0,card->uidlen,0,buf,sizeof(iso14a_card_select_t)); } } @@ -2168,7 +2169,7 @@ void ReaderMifare(bool first_try) SpinDelay(100); } - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card"); continue; } diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 658216e7..10e50e0f 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -27,6 +27,6 @@ extern int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par); extern void iso14443a_setup(uint8_t fpga_minor_mode); extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data); -extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades); +extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats); extern void iso14a_set_trigger(bool enable); #endif /* __ISO14443A_H */ diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 60a85c80..a3f0d374 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -59,7 +59,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) LED_C_OFF(); while (true) { - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); break; }; @@ -106,7 +106,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){ clear_trace(); - if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) { + if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); OnError(0); return; @@ -141,7 +141,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) clear_trace(); - int len = iso14443a_select_card(NULL, NULL, NULL, true, 0); + int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true); if(!len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len); OnError(1); @@ -217,7 +217,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) LED_C_OFF(); isOK = 1; - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { isOK = 0; if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); } @@ -281,7 +281,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) return; } - int len = iso14443a_select_card(NULL, NULL, NULL, true, 0); + int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true); if (!len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len); OnError(1); @@ -383,7 +383,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) LED_C_OFF(); while (true) { - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); break; }; @@ -483,7 +483,7 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) clear_trace(); - if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) { + if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); OnError(0); return; @@ -542,7 +542,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){ clear_trace(); - if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) { + if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); OnError(0); return; @@ -662,7 +662,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, if (!have_uid) { // need a full select cycle to get the uid first iso14a_card_select_t card_info; - if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0)) { + if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); continue; } @@ -674,7 +674,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, } have_uid = true; } else { // no need for anticollision. We can directly select the card - if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels)) { + if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); continue; } @@ -807,7 +807,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat continue; } - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card"); rtr--; continue; @@ -881,7 +881,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat continue; } - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card"); continue; }; @@ -1000,7 +1000,7 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // Iceman: use piwi's faster nonce collecting part in hardnested. if (!have_uid) { // need a full select cycle to get the uid first iso14a_card_select_t card_info; - if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0)) { + if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card"); --i; // try same key once again continue; @@ -1013,7 +1013,7 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) } have_uid = true; } else { // no need for anticollision. We can directly select the card - if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels)) { + if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) { if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)"); --i; // try same key once again continue; @@ -1111,7 +1111,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai bool isOK = true; - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { isOK = false; if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); } @@ -1349,7 +1349,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai // get UID from chip if (workFlags & 0x01) { - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); // Continue, if we set wrong UID or wrong UID checksum or some ATQA or SAK we will can't select card. But we need to write block 0 to make card work. //break; @@ -1573,7 +1573,7 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){ iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); - int len = iso14443a_select_card(uid, NULL, &cuid, true, 0); + int len = iso14443a_select_card(uid, NULL, &cuid, true, 0, true); if(!len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); OnError(1); diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index b75215a0..db9ce46e 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -442,7 +442,7 @@ int CmdHF14ACUIDs(const char *Cmd) // repeat n times for (int i = 0; i < n; i++) { // execute anticollision procedure - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0}}; SendCommand(&c); UsbCommand resp; @@ -581,6 +581,7 @@ int CmdHF14ACmdRaw(const char *cmd) { bool power = false; bool active = false; bool active_select = false; + bool no_rats = false; uint16_t numbits = 0; bool bTimeout = false; uint32_t timeout = 0; @@ -601,6 +602,7 @@ int CmdHF14ACmdRaw(const char *cmd) { PrintAndLog(" -b number of bits to send. Useful for send partial byte"); PrintAndLog(" -t timeout in ms"); PrintAndLog(" -T use Topaz protocol to send command"); + PrintAndLog(" -3 ISO14443-3 select only (skip RATS)"); return 0; } @@ -645,6 +647,9 @@ int CmdHF14ACmdRaw(const char *cmd) { case 'T': topazmode = true; break; + case '3': + no_rats = true; + break; default: PrintAndLog("Invalid option"); return 0; @@ -718,6 +723,10 @@ int CmdHF14ACmdRaw(const char *cmd) { c.arg[0] |= ISO14A_TOPAZMODE; } + if(no_rats) { + c.arg[0] |= ISO14A_NO_RATS; + } + // Max buffer is USB_CMD_DATA_SIZE (512) c.arg[1] = (datalen & 0xFFFF) | ((uint32_t)numbits << 16); memcpy(c.d.asBytes,data,datalen); diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index ca4544f3..3021631a 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -108,7 +108,7 @@ char *getUlev1CardSizeStr( uint8_t fsize ){ } static void ul_switch_on_field(void) { - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 0, 0}}; clearCommandBuffer(); SendCommand(&c); } diff --git a/client/mifarehost.c b/client/mifarehost.c index 8a840d47..629c8feb 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -519,20 +519,20 @@ int mfCIdentify() UsbCommand resp; WaitForResponse(CMD_ACK,&resp); - iso14a_card_select_t card; - memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - - uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - - if(select_status != 0) { - uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 - c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; - c.arg[1] = 2; - c.arg[2] = 0; - memcpy(c.d.asBytes, rats, 2); - SendCommand(&c); - WaitForResponse(CMD_ACK,&resp); - } + // iso14a_card_select_t card; + // memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + + // uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + + // if(select_status != 0) { + // uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 + // c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; + // c.arg[1] = 2; + // c.arg[2] = 0; + // memcpy(c.d.asBytes, rats, 2); + // SendCommand(&c); + // WaitForResponse(CMD_ACK,&resp); + // } c.cmd = CMD_MIFARE_CIDENT; c.arg[0] = 0; diff --git a/include/mifare.h b/include/mifare.h index e2386cd5..bede67a9 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -34,7 +34,8 @@ typedef enum ISO14A_COMMAND { ISO14A_APPEND_CRC = (1 << 5), ISO14A_SET_TIMEOUT = (1 << 6), ISO14A_NO_SELECT = (1 << 7), - ISO14A_TOPAZMODE = (1 << 8) + ISO14A_TOPAZMODE = (1 << 8), + ISO14A_NO_RATS = (1 << 9) } iso14a_command_t; typedef struct { -- 2.39.2