diff --git a/armsrc/appmain.c b/armsrc/appmain.c index e673c078a..cb5dbe8a2 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1229,22 +1229,36 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_ICLASS_WRITEBL: { - iClass_WriteBlock(packet->oldarg[0], packet->data.asBytes); + struct p { + uint8_t blockno; + uint8_t data[12]; + } PACKED; + struct p *payload = (struct p *)packet->data.asBytes; + iClass_WriteBlock(payload->blockno, payload->data); break; } + // iceman2019, unused? case CMD_HF_ICLASS_READCHECK: { // auth step 1 iClass_ReadCheck(packet->oldarg[0], packet->oldarg[1]); break; } case CMD_HF_ICLASS_READBL: { +/* struct p { uint8_t blockno; } PACKED; struct p *payload = (struct p *)packet->data.asBytes; - iClass_ReadBlk( payload->blockno ); + */ + iClass_ReadBlk( packet->data.asBytes[0] ); break; } case CMD_HF_ICLASS_AUTH: { //check +/* + struct p { + uint8_t mac[4]; + } PACKED; + struct p *payload = (struct p *)packet->data.asBytes; +*/ iClass_Authentication(packet->data.asBytes); break; } diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 940d0157a..fa90f0881 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -56,10 +56,8 @@ #include "ticks.h" static int g_wait = 300; -static int timeout = 2900; +static int timeout = 5000; static uint32_t time_rdr = 0; -static uint32_t time_delta = 0; -static uint32_t time_delta_wait = 0; static uint32_t time_response = 0; static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay); @@ -1854,12 +1852,9 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, // only, since we are receiving, not transmitting). FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); - time_delta = GetCountSspClk() - time_rdr; - SpinDelayUs(g_wait); //310 Tout= 330us (iso15603-2) (330/21.3) take consideration for clock increments. - time_delta_wait = GetCountSspClk() - time_rdr - time_delta; - uint32_t foo = GetCountSspClk(); + // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; (void)b; @@ -1877,21 +1872,15 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, } // keep tx buffer in a defined state anyway. - /* - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; - } - */ + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; + } + // Wait for byte be become available in rx holding register if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - if (GetCountSspClk() - foo > timeout) return false; -// if (c >= timeout) return false; - c++; - b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - skip = !skip; if (skip) continue; @@ -1902,6 +1891,8 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, time_response = GetCountSspClk() - foo; return true; } + + if (GetCountSspClk() - foo > timeout) return false; } } @@ -1959,12 +1950,15 @@ bool sendCmdGetResponseWithRetries(uint8_t *command, size_t cmdsize, uint8_t *re //iceman - if received size is bigger than expected, we smash the stack here // since its called with fixed sized arrays - // update/write commadn takes 4ms to 15ms before responding + // update/write command takes 4ms to 15ms before responding + int old_wait = g_wait; if (command[0] == ICLASS_CMD_UPDATE) - g_wait = 15000; + g_wait = 3900; uint8_t got_n = ReaderReceiveIClass(resp); + g_wait = old_wait; + // 0xBB is the internal debug separator byte.. if (expected_size != got_n || (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) { //try again @@ -2337,8 +2331,8 @@ void iClass_Authentication(uint8_t *mac) { //memcpy(check+5, mac, 4); // 6 retries - bool isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6); - reply_mix(CMD_ACK, isOK, 0, 0, 0, 0); + uint8_t isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6); + reply_ng(CMD_HF_ICLASS_AUTH, PM3_SUCCESS, (uint8_t*)&isOK ,sizeof(uint8_t)); } typedef struct iclass_premac { @@ -2397,6 +2391,8 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) { }; // since handshakeIclassTag_ext call sends s readcheck, we start with sending first response. + checked = 0; + // Keychunk loop for (i = 0; i < keyCount; i++) { @@ -2496,39 +2492,26 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks) { } memcpy(dataout + (blkCnt * 8), blockdata, 8); } + + switch_off(); //return pointer to dump memory in arg3 reply_mix(CMD_ACK, isOK, blkCnt, BigBuf_max_traceLen(), 0, 0); - switch_off(); BigBuf_free(); } bool iClass_WriteBlock_ext(uint8_t blockno, uint8_t *data) { - uint8_t resp[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t write[] = { ICLASS_CMD_UPDATE, blockno, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; memcpy(write + 2, data, 12); // data + mac AddCrc(write + 1, 13); - - bool isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); - if (isOK) { //if reader responded correctly - - //if response is not equal to write values - if (memcmp(write + 2, resp, 8)) { - - //if not programming key areas (note key blocks don't get programmed with actual key data it is xor data) - if (blockno != 3 && blockno != 4) { - isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); - } - } - } - return isOK; + return sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); } // turn off afterwards void iClass_WriteBlock(uint8_t blockno, uint8_t *data) { - bool isOK = iClass_WriteBlock_ext(blockno, data); - reply_mix(CMD_ACK, isOK, 0, 0, 0, 0); + uint8_t isOK = iClass_WriteBlock_ext(blockno, data); switch_off(); + reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t*)&isOK, sizeof(uint8_t)); } // turn off afterwards diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 2f8d3b56d..5ac3a8925 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -1000,7 +1000,7 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool v clearCommandBuffer(); SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "command execute timeout"); return false; } @@ -1019,7 +1019,9 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool v } if (isOK <= 1) { - PrintAndLogEx(FAILED, "failed to obtain CC! Tag-select is aborting... (%d)", isOK); + if ( verbose ) + PrintAndLogEx(FAILED, "failed to obtain CC! Tag-select is aborting... (%d)", isOK); + return false; } return true; @@ -1042,18 +1044,27 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u if (verbose) PrintAndLogEx(SUCCESS, "authing with %s: %s", rawkey ? "raw key" : "diversified key", sprint_hex(div_key, 8)); doMAC(CCNR, div_key, MAC); + PacketResponseNG resp; clearCommandBuffer(); - SendCommandOLD(CMD_HF_ICLASS_AUTH, 0, 0, 0, MAC, 4); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { - if (verbose) PrintAndLogEx(FAILED, "auth command execute timeout"); + + SendCommandNG(CMD_HF_ICLASS_AUTH, MAC, 4); + if (WaitForResponseTimeout(CMD_HF_ICLASS_AUTH, &resp, 2000) == 0) { + if (verbose) PrintAndLogEx(WARNING, "Command execute timeout"); return false; } - uint8_t isOK = resp.oldarg[0] & 0xFF; - if (!isOK) { + + if ( resp.status != PM3_SUCCESS ) { + if (verbose) PrintAndLogEx(ERR, "failed to communicate with card"); + return false; + } + + uint8_t isOK = resp.data.asBytes[0]; + if (isOK == 0) { if (verbose) PrintAndLogEx(FAILED, "authentication error"); return false; } + return true; } @@ -1311,30 +1322,60 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { } static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool verbose) { - uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; - uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) - return 0; - PacketResponseNG resp; + int numberAuthRetries = ICLASS_AUTH_RETRY; + do { + + uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; + uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) { + numberAuthRetries--; + DropField(); + continue; + } - Calc_wb_mac(blockno, bldata, div_key, MAC); - uint8_t data[12]; - memcpy(data, bldata, 8); - memcpy(data + 8, MAC, 4); + Calc_wb_mac(blockno, bldata, div_key, MAC); - clearCommandBuffer(); - SendCommandOLD(CMD_HF_ICLASS_WRITEBL, blockno, 0, 0, data, sizeof(data)); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { - if (verbose) PrintAndLogEx(WARNING, "Write Command execute timeout"); - return 0; + struct p { + uint8_t blockno; + uint8_t data[12]; + } PACKED payload; + payload.blockno = blockno; + + memcpy(payload.data, bldata, 8); + memcpy(payload.data + 8, MAC, 4); + + clearCommandBuffer(); + SendCommandNG(CMD_HF_ICLASS_WRITEBL, (uint8_t*)&payload, sizeof(payload)); + PacketResponseNG resp; + + if (WaitForResponseTimeout(CMD_HF_ICLASS_WRITEBL, &resp, 4000) == 0) { + if (verbose) PrintAndLogEx(WARNING, "Command execute timeout"); + DropField(); + return PM3_ETIMEOUT; + } + + if ( resp.status != PM3_SUCCESS ) { + if (verbose) PrintAndLogEx(ERR, "failed to communicate with card"); + DropField(); + return PM3_EWRONGANSVER; + } + + if (resp.data.asBytes[0] == 1) + break; + + } while (numberAuthRetries); + + DropField(); + + if ( numberAuthRetries > 0 ) { + PrintAndLogEx(SUCCESS, "Write block %02X successful\n", blockno); + } else { + PrintAndLogEx(ERR,"failed to authenticate and write block"); + return PM3_ESOFT; } - uint8_t isOK = resp.oldarg[0] & 0xff; - if (isOK) - PrintAndLogEx(SUCCESS, "Write block successful"); - else - PrintAndLogEx(WARNING, "Write block failed"); - return isOK; + + return PM3_SUCCESS; } static int CmdHFiClass_WriteBlock(const char *Cmd) { @@ -1344,6 +1385,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { uint8_t keyNbr = 0; uint8_t dataLen = 0; char tempStr[50] = {0}; + bool got_blockno = false; bool use_credit_key = false; bool elite = false; bool rawkey = false; @@ -1355,10 +1397,12 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { case 'h': return usage_hf_iclass_writeblock(); case 'b': - blockno = param_get8ex(Cmd, cmdp + 1, 06, 16); + blockno = param_get8ex(Cmd, cmdp + 1, 07, 16); + got_blockno = true; cmdp += 2; break; case 'c': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("CREDIT")); use_credit_key = true; cmdp++; break; @@ -1370,6 +1414,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { cmdp += 2; break; case 'e': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); elite = true; cmdp++; break; @@ -1380,6 +1425,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { } else if (dataLen == 1) { keyNbr = param_get8(Cmd, cmdp + 1); if (keyNbr < ICLASS_KEYS_MAX) { + PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8 )); memcpy(KEY, iClass_Key_Table[keyNbr], 8); } else { PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n"); @@ -1392,6 +1438,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { cmdp += 2; break; case 'r': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode")); rawkey = true; cmdp++; break; @@ -1405,11 +1452,12 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { break; } } + if ( got_blockno == false) + errors = true; + if (errors || cmdp < 6) return usage_hf_iclass_writeblock(); - int ans = WriteBlock(blockno, bldata, KEY, use_credit_key, elite, rawkey, verbose); - DropField(); - return ans; + return WriteBlock(blockno, bldata, KEY, use_credit_key, elite, rawkey, verbose); } static int CmdHFiClassCloneTag(const char *Cmd) { @@ -1585,6 +1633,7 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; if (!select_and_auth(KEY, MAC, div_key, (keyType == 0x18), elite, rawkey, verbose)) { numberAuthRetries--; + DropField(); continue; } } else { @@ -1592,22 +1641,24 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; if (!select_only(CSN, CCNR, (keyType == 0x18), verbose)) { numberAuthRetries--; + DropField(); continue; } } PacketResponseNG resp; - clearCommandBuffer(); - uint8_t payload[] = { blockno }; - SendCommandNG(CMD_HF_ICLASS_READBL, payload, sizeof(payload)); + clearCommandBuffer(); + SendCommandNG(CMD_HF_ICLASS_READBL, (uint8_t*)&blockno, sizeof(uint8_t)); if (WaitForResponseTimeout(CMD_HF_ICLASS_READBL, &resp, 2000) == 0) { - PrintAndLogEx(WARNING, "Command execute timeout"); + if (verbose) PrintAndLogEx(WARNING, "Command execute timeout"); + DropField(); return PM3_ETIMEOUT; } if ( resp.status != PM3_SUCCESS ) { - PrintAndLogEx(ERR, "failed to communicate with card"); + if (verbose) PrintAndLogEx(ERR, "failed to communicate with card"); + DropField(); return PM3_EWRONGANSVER; } @@ -1617,10 +1668,13 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, } while (numberAuthRetries); + DropField(); + if ( numberAuthRetries > 0 ) { PrintAndLogEx(SUCCESS, "block %02X: %s\n", blockno, sprint_hex(result->blockdata, sizeof(result->blockdata))); } else { PrintAndLogEx(ERR,"failed to authenticate and read block"); + return PM3_ESOFT; } return PM3_SUCCESS; @@ -1633,6 +1687,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { uint8_t keyNbr = 0; uint8_t dataLen = 0; char tempStr[50] = {0}; + bool got_blockno = false; bool elite = false; bool rawkey = false; bool errors = false; @@ -1645,6 +1700,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { return usage_hf_iclass_readblock(); case 'b': blockno = param_get8ex(Cmd, cmdp + 1, 7, 16); + got_blockno = true; cmdp += 2; break; case 'c': @@ -1692,6 +1748,9 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { break; } } + if ( got_blockno == false) + errors = true; + if (errors || cmdp < 4) return usage_hf_iclass_readblock(); if (!auth)