X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/c41dd5f9f690777eefd08eaeb43db52f599ce38c..d3bcdbdabfccb09e93be14d6478eeccc0b131201:/armsrc/iclass.c diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 392271bd..430597c1 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -63,9 +63,10 @@ // 56,64us = 24 ssp_clk_cycles #define DELAY_ICLASS_VCD_TO_VICC_SIM (140 - 24) // times in ssp_clk_cycles @ 3,3625MHz when acting as reader -#define DELAY_ICLASS_VICC_TO_VCD_READER DELAY_ISO15693_VICC_TO_VCD_READER +#define DELAY_ICLASS_VICC_TO_VCD_READER DELAY_ISO15693_VICC_TO_VCD_READER // times in samples @ 212kHz when acting as reader -#define ICLASS_READER_TIMEOUT_ACTALL 330 // 1558us, nominal 330us + 7slots*160us = 1450us +#define ICLASS_READER_TIMEOUT_ACTALL 330 // 1558us, nominal 330us + 7slots*160us = 1450us +#define ICLASS_READER_TIMEOUT_UPDATE 3390 // 16000us, nominal 4-15ms #define ICLASS_READER_TIMEOUT_OTHERS 80 // 380us, nominal 330us @@ -695,7 +696,6 @@ void RAMFUNC SnoopIClass(void) { if (OutOfNDecoding((smpl & 0xF0) >> 4)) { rsamples = samples - Uart.samples; time_stop = (GetCountSspClk()-time_0) << 4; - LED_C_ON(); //if (!LogTrace(Uart.output, Uart.byteCnt, rsamples, Uart.parityBits,true)) break; //if (!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, true)) break; @@ -708,7 +708,6 @@ void RAMFUNC SnoopIClass(void) { /* And also reset the demod code, which might have been */ /* false-triggered by the commands from the reader. */ Demod.state = DEMOD_UNSYNCD; - LED_B_OFF(); Uart.byteCnt = 0; } else { time_start = (GetCountSspClk()-time_0) << 4; @@ -722,7 +721,6 @@ void RAMFUNC SnoopIClass(void) { time_stop = (GetCountSspClk()-time_0) << 4; rsamples = samples - Demod.samples; - LED_B_ON(); uint8_t parity[MAX_PARITY_SIZE]; GetParity(Demod.output, Demod.len, parity); @@ -732,7 +730,6 @@ void RAMFUNC SnoopIClass(void) { memset(&Demod, 0, sizeof(Demod)); Demod.output = tagToReaderResponse; Demod.state = DEMOD_UNSYNCD; - LED_C_OFF(); } else { time_start = (GetCountSspClk()-time_0) << 4; } @@ -1341,11 +1338,11 @@ static void ReaderTransmitIClass(uint8_t *frame, int len, uint32_t *start_time) } -static bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, size_t max_resp_size, - uint8_t expected_size, uint8_t retries, uint32_t start_time, uint32_t *eof_time) { +static bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, size_t max_resp_size, + uint8_t expected_size, uint8_t retries, uint32_t start_time, uint32_t timeout, uint32_t *eof_time) { while (retries-- > 0) { ReaderTransmitIClass(command, cmdsize, &start_time); - if (expected_size == GetIso15693AnswerFromTag(resp, max_resp_size, ICLASS_READER_TIMEOUT_OTHERS, eof_time)) { + if (expected_size == GetIso15693AnswerFromTag(resp, max_resp_size, timeout, eof_time)) { return true; } } @@ -1353,39 +1350,31 @@ static bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint } /** - * @brief Talks to an iclass tag, sends the commands to get CSN and CC. - * @param card_data where the CSN and CC are stored for return - * @return 0 = fail - * 1 = Got CSN - * 2 = Got CSN and CC + * @brief Selects an iclass tag + * @param card_data where the CSN is stored for return + * @return false = fail + * true = success */ -static uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key, uint32_t *eof_time) { +static bool selectIclassTag(uint8_t *card_data, uint32_t *eof_time) { uint8_t act_all[] = { 0x0a }; uint8_t identify[] = { 0x0c }; uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t readcheck_cc[] = { 0x88, 0x02 }; - if (use_credit_key) - readcheck_cc[0] = 0x18; - else - readcheck_cc[0] = 0x88; uint8_t resp[ICLASS_BUFFER_SIZE]; - uint8_t read_status = 0; uint32_t start_time = GetCountSspClk(); // Send act_all ReaderTransmitIClass(act_all, 1, &start_time); // Card present? - if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_ACTALL, eof_time) < 0) return read_status;//Fail - + if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_ACTALL, eof_time) < 0) return false;//Fail + //Send Identify start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; ReaderTransmitIClass(identify, 1, &start_time); - // FpgaDisableTracing(); // DEBUGGING //We expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC uint8_t len = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time); - if (len != 10) return read_status;//Fail + if (len != 10) return false;//Fail //Copy the Anti-collision CSN to our select-packet memcpy(&select[1], resp, 8); @@ -1394,153 +1383,96 @@ static uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key, u ReaderTransmitIClass(select, sizeof(select), &start_time); //We expect a 10-byte response here, 8 byte CSN and 2 byte CRC len = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time); - if (len != 10) return read_status;//Fail + if (len != 10) return false;//Fail - //Success - level 1, we got CSN + //Success - we got CSN //Save CSN in response data memcpy(card_data, resp, 8); - //Flag that we got to at least stage 1, read CSN - read_status = 1; - - // Card selected, now read e-purse (cc) (only 8 bytes no CRC) - start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; - ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc), &start_time); - if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time) == 8) { - //Save CC (e-purse) in response data - memcpy(card_data+8, resp, 8); - read_status++; - } - - return read_status; + return true; } -static uint8_t handshakeIclassTag(uint8_t *card_data, uint32_t *eof_time) { - return handshakeIclassTag_ext(card_data, false, eof_time); -} +// Select an iClass tag and read all blocks which are always readable without authentication +void ReaderIClass(uint8_t flags) { -// Reader iClass Anticollission -void ReaderIClass(uint8_t arg0) { + LED_A_ON(); uint8_t card_data[6 * 8] = {0}; memset(card_data, 0xFF, sizeof(card_data)); - uint8_t last_csn[8] = {0,0,0,0,0,0,0,0}; uint8_t resp[ICLASS_BUFFER_SIZE]; - memset(resp, 0xFF, sizeof(resp)); //Read conf block CRC(0x01) => 0xfa 0x22 - uint8_t readConf[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22}; + uint8_t readConf[] = {ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22}; + //Read e-purse block CRC(0x02) => 0x61 0x10 + uint8_t readEpurse[] = {ICLASS_CMD_READ_OR_IDENTIFY, 0x02, 0x61, 0x10}; //Read App Issuer Area block CRC(0x05) => 0xde 0x64 - uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64}; + uint8_t readAA[] = {ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64}; - int read_status= 0; uint8_t result_status = 0; - // flag to read until one tag is found successfully - bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; - // flag to only try 5 times to find one tag then return - bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY; - // if neither abort_after_read nor try_once then continue reading until button pressed. - - bool use_credit_key = arg0 & FLAG_ICLASS_READER_CEDITKEY; - // test flags for what blocks to be sure to read - uint8_t flagReadConfig = arg0 & FLAG_ICLASS_READER_CONF; - uint8_t flagReadCC = arg0 & FLAG_ICLASS_READER_CC; - uint8_t flagReadAA = arg0 & FLAG_ICLASS_READER_AA; - set_tracing(true); - clear_trace(); - Iso15693InitReader(); + if (flags & FLAG_ICLASS_READER_INIT) { + Iso15693InitReader(); + } + + if (flags & FLAG_ICLASS_READER_CLEARTRACE) { + set_tracing(true); + clear_trace(); + StartCountSspClk(); + } - StartCountSspClk(); uint32_t start_time = 0; uint32_t eof_time = 0; - - uint16_t tryCnt = 0; - bool userCancelled = BUTTON_PRESS() || usb_poll_validate_length(); - while (!userCancelled) { - // if only looking for one card try 2 times if we missed it the first time - if (try_once && tryCnt > 2) { - break; - } - tryCnt++; - if (!get_tracing()) { - DbpString("Trace full"); - break; - } - WDT_HIT(); - read_status = handshakeIclassTag_ext(card_data, use_credit_key, &eof_time); + if (selectIclassTag(resp, &eof_time)) { + result_status = FLAG_ICLASS_READER_CSN; + memcpy(card_data, resp, 8); + } - if (read_status == 0) continue; - if (read_status == 1) result_status = FLAG_ICLASS_READER_CSN; - if (read_status == 2) result_status = FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CC; + start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; - start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; - // handshakeIclass returns CSN|CC, but the actual block - // layout is CSN|CONFIG|CC, so here we reorder the data, - // moving CC forward 8 bytes - memcpy(card_data+16, card_data+8, 8); - //Read block 1, config - if (flagReadConfig) { - if (sendCmdGetResponseWithRetries(readConf, sizeof(readConf), resp, sizeof(resp), 10, 10, start_time, &eof_time)) { - result_status |= FLAG_ICLASS_READER_CONF; - memcpy(card_data+8, resp, 8); - } else { - Dbprintf("Failed to dump config block"); - } - start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + //Read block 1, config + if (flags & FLAG_ICLASS_READER_CONF) { + if (sendCmdGetResponseWithRetries(readConf, sizeof(readConf), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) { + result_status |= FLAG_ICLASS_READER_CONF; + memcpy(card_data+8, resp, 8); + } else { + Dbprintf("Failed to read config block"); } + start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + } - //Read block 5, AA - if (flagReadAA) { - if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, sizeof(resp), 10, 10, start_time, &eof_time)) { - result_status |= FLAG_ICLASS_READER_AA; - memcpy(card_data + (8*5), resp, 8); - } else { - //Dbprintf("Failed to dump AA block"); - } + //Read block 2, e-purse + if (flags & FLAG_ICLASS_READER_CC) { + if (sendCmdGetResponseWithRetries(readEpurse, sizeof(readEpurse), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) { + result_status |= FLAG_ICLASS_READER_CC; + memcpy(card_data + (8*2), resp, 8); + } else { + Dbprintf("Failed to read e-purse"); } + start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + } - // 0 : CSN - // 1 : Configuration - // 2 : e-purse - // 3 : kd / debit / aa2 (write-only) - // 4 : kc / credit / aa1 (write-only) - // 5 : AIA, Application issuer area - //Then we can 'ship' back the 6 * 8 bytes of data, - // with 0xFF:s in block 3 and 4. - - LED_B_ON(); - //Send back to client, but don't bother if we already sent this - - // only useful if looping in arm (not try_once && not abort_after_read) - if (memcmp(last_csn, card_data, 8) != 0) { - // If caller requires that we get Conf, CC, AA, continue until we got it - if ( (result_status ^ FLAG_ICLASS_READER_CSN ^ flagReadConfig ^ flagReadCC ^ flagReadAA) == 0) { - cmd_send(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data)); - if (abort_after_read) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_A_OFF(); - LED_B_OFF(); - return; - } - //Save that we already sent this.... - memcpy(last_csn, card_data, 8); - } - + //Read block 5, AA + if (flags & FLAG_ICLASS_READER_AA) { + if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) { + result_status |= FLAG_ICLASS_READER_AA; + memcpy(card_data + (8*5), resp, 8); + } else { + Dbprintf("Failed to read AA block"); } - LED_B_OFF(); - userCancelled = BUTTON_PRESS() || usb_poll_validate_length(); - } - if (userCancelled) { - cmd_send(CMD_ACK, 0xFF, 0, 0, card_data, 0); - } else { - cmd_send(CMD_ACK, 0, 0, 0, card_data, 0); } + + cmd_send(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data)); + LED_A_OFF(); } + void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { + LED_A_ON(); + + bool use_credit_key = false; uint8_t card_data[USB_CMD_DATA_SIZE]={0}; uint16_t block_crc_LUT[255] = {0}; @@ -1551,6 +1483,9 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { } //Dbprintf("Lookup table: %02x %02x %02x" ,block_crc_LUT[0],block_crc_LUT[1],block_crc_LUT[2]); + uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 }; + if (use_credit_key) + readcheck_cc[0] = ICLASS_CMD_READCHECK_KC; uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 }; @@ -1575,7 +1510,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { StartCountSspClk(); uint32_t start_time = 0; uint32_t eof_time = 0; - + while (!BUTTON_PRESS()) { WDT_HIT(); @@ -1585,34 +1520,33 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { break; } - uint8_t read_status = handshakeIclassTag(card_data, &eof_time); - start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + if (!selectIclassTag(card_data, &eof_time)) continue; - if (read_status < 2) continue; + start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + if (!sendCmdGetResponseWithRetries(readcheck_cc, sizeof(readcheck_cc), resp, sizeof(resp), 8, 3, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) continue; - //for now replay captured auth (as cc not updated) + // replay captured auth (cc must not have been updated) memcpy(check+5, MAC, 4); - if (!sendCmdGetResponseWithRetries(check, sizeof(check), resp, sizeof(resp), 4, 5, start_time, &eof_time)) { - start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + if (!sendCmdGetResponseWithRetries(check, sizeof(check), resp, sizeof(resp), 4, 5, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) { Dbprintf("Error: Authentication Fail!"); continue; } - start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; //first get configuration block (block 1) crc = block_crc_LUT[1]; read[1] = 1; read[2] = crc >> 8; read[3] = crc & 0xff; - if (!sendCmdGetResponseWithRetries(read, sizeof(read), resp, sizeof(resp), 10, 10, start_time, &eof_time)) { + start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + if (!sendCmdGetResponseWithRetries(read, sizeof(read), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) { start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; Dbprintf("Dump config (block 1) failed"); continue; } - start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; mem = resp[5]; memory.k16 = (mem & 0x80); memory.book = (mem & 0x20); @@ -1633,8 +1567,8 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { read[2] = crc >> 8; read[3] = crc & 0xff; - if (sendCmdGetResponseWithRetries(read, sizeof(read), resp, sizeof(resp), 10, 10, start_time, &eof_time)) { - start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + if (sendCmdGetResponseWithRetries(read, sizeof(read), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) { Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x", block, resp[0], resp[1], resp[2], resp[3], resp[4], resp[5], @@ -1683,19 +1617,33 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { 0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); LED_A_OFF(); } -void iClass_Authentication(uint8_t *MAC) { - uint8_t check[] = { ICLASS_CMD_CHECK_KD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t resp[ICLASS_BUFFER_SIZE]; + +void iClass_Check(uint8_t *MAC) { + uint8_t check[9] = {ICLASS_CMD_CHECK_KD, 0x00}; + uint8_t resp[4]; memcpy(check+5, MAC, 4); - bool isOK; uint32_t eof_time; - isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, sizeof(resp), 4, 6, 0, &eof_time); - cmd_send(CMD_ACK,isOK, 0, 0, 0, 0); + bool isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, sizeof(resp), 4, 6, 0, ICLASS_READER_TIMEOUT_OTHERS, &eof_time); + cmd_send(CMD_ACK, isOK, 0, 0, resp, sizeof(resp)); +} + + +void iClass_Readcheck(uint8_t block, bool use_credit_key) { + uint8_t readcheck[2] = {ICLASS_CMD_READCHECK_KD, block}; + if (use_credit_key) { + readcheck[0] = ICLASS_CMD_READCHECK_KC; + } + uint8_t resp[8]; + uint32_t eof_time; + bool isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 8, 6, 0, ICLASS_READER_TIMEOUT_OTHERS, &eof_time); + cmd_send(CMD_ACK, isOK, 0, 0, resp, sizeof(resp)); } + static bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata) { uint8_t readcmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockNo, 0x00, 0x00}; //0x88, 0x00 // can i use 0C? char bl = blockNo; @@ -1703,97 +1651,92 @@ static bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata) { readcmd[2] = rdCrc >> 8; readcmd[3] = rdCrc & 0xff; uint8_t resp[10]; - bool isOK = false; uint32_t eof_time; - - //readcmd[1] = blockNo; - isOK = sendCmdGetResponseWithRetries(readcmd, sizeof(readcmd), resp, sizeof(resp), 10, 10, 0, &eof_time); + + bool isOK = sendCmdGetResponseWithRetries(readcmd, sizeof(readcmd), resp, sizeof(resp), 10, 10, 0, ICLASS_READER_TIMEOUT_OTHERS, &eof_time); memcpy(readdata, resp, sizeof(resp)); return isOK; } + void iClass_ReadBlk(uint8_t blockno) { + + LED_A_ON(); + uint8_t readblockdata[] = {0,0,0,0,0,0,0,0,0,0}; - bool isOK = false; - isOK = iClass_ReadBlock(blockno, readblockdata); + bool isOK = iClass_ReadBlock(blockno, readblockdata); cmd_send(CMD_ACK, isOK, 0, 0, readblockdata, 8); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + + LED_A_OFF(); } -void iClass_Dump(uint8_t blockno, uint8_t numblks) { - uint8_t readblockdata[] = {0,0,0,0,0,0,0,0,0,0}; + +void iClass_Dump(uint8_t startblock, uint8_t numblks) { + + LED_A_ON(); + + uint8_t readblockdata[USB_CMD_DATA_SIZE+2] = {0}; bool isOK = false; - uint8_t blkCnt = 0; + uint16_t blkCnt = 0; - BigBuf_free(); - uint8_t *dataout = BigBuf_malloc(255*8); - if (dataout == NULL) { - Dbprintf("out of memory"); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_D_OFF(); - cmd_send(CMD_ACK, 0, 1, 0, 0, 0); - LED_A_OFF(); - return; + if (numblks > USB_CMD_DATA_SIZE / 8) { + numblks = USB_CMD_DATA_SIZE / 8; } - memset(dataout, 0xFF, 255*8); - - for ( ; blkCnt < numblks; blkCnt++) { - isOK = iClass_ReadBlock(blockno+blkCnt, readblockdata); - if (!isOK || (readblockdata[0] == 0xBB || readblockdata[7] == 0xBB || readblockdata[2] == 0xBB)) { //try again - isOK = iClass_ReadBlock(blockno+blkCnt, readblockdata); - if (!isOK) { - Dbprintf("Block %02X failed to read", blkCnt+blockno); - break; - } + + for (blkCnt = 0; blkCnt < numblks; blkCnt++) { + isOK = iClass_ReadBlock(startblock+blkCnt, readblockdata+8*blkCnt); + if (!isOK) { + Dbprintf("Block %02X failed to read", startblock+blkCnt); + break; } - memcpy(dataout + (blkCnt*8), readblockdata, 8); } - //return pointer to dump memory in arg3 - cmd_send(CMD_ACK, isOK, blkCnt, BigBuf_max_traceLen(), 0, 0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - BigBuf_free(); + + cmd_send(CMD_ACK, isOK, blkCnt, 0, readblockdata, blkCnt*8); + + LED_A_OFF(); } + static bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) { - uint8_t write[] = { ICLASS_CMD_UPDATE, blockNo, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - //uint8_t readblockdata[10]; - //write[1] = blockNo; + + uint8_t write[16] = {ICLASS_CMD_UPDATE, blockNo}; memcpy(write+2, data, 12); // data + mac - char *wrCmd = (char *)(write+1); - uint16_t wrCrc = iclass_crc16(wrCmd, 13); - write[14] = wrCrc >> 8; - write[15] = wrCrc & 0xff; + AppendCrc(write+1, 13); uint8_t resp[10]; bool isOK = false; uint32_t eof_time = 0; - - isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 10, 10, 0, &eof_time); - uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; - if (isOK) { //if reader responded correctly - //Dbprintf("WriteResp: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",resp[0],resp[1],resp[2],resp[3],resp[4],resp[5],resp[6],resp[7],resp[8],resp[9]); - if (memcmp(write+2, resp, 8)) { //if response is not equal to write values - if (blockNo != 3 && blockNo != 4) { //if not programming key areas (note key blocks don't get programmed with actual key data it is xor data) - //error try again - isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 10, 10, start_time, &eof_time); - } - } + + isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 10, 10, 0, ICLASS_READER_TIMEOUT_UPDATE, &eof_time); + if (isOK && blockNo != 3 && blockNo != 4 && memcmp(write+2, resp, 8)) { // check response + isOK = false; } + return isOK; } + void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) { + + LED_A_ON(); + bool isOK = iClass_WriteBlock_ext(blockNo, data); - if (isOK){ + if (isOK) { Dbprintf("Write block [%02x] successful", blockNo); } else { Dbprintf("Write block [%02x] failed", blockNo); } cmd_send(CMD_ACK, isOK, 0, 0, 0, 0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + + LED_A_OFF(); } + void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) { int i; int written = 0; @@ -1819,5 +1762,6 @@ void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) { cmd_send(CMD_ACK, 1, 0, 0, 0, 0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + LED_D_OFF(); + LED_A_OFF(); }