From 7d1a27819720df273f59b03b6a8b98cbf7eba96b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jul 2020 21:33:17 +0200 Subject: [PATCH] merge hell p.x --- armsrc/fpgaloader.h | 8 +- armsrc/iclass.c | 2077 ++++++++------------------------------ armsrc/iclass.h | 3 +- armsrc/iso14443b.c | 841 ++++++++------- armsrc/iso14443b.h | 2 +- armsrc/iso15693.c | 30 +- armsrc/iso15693.h | 9 + client/src/cmdhf14b.c | 24 +- client/src/cmdhficlass.c | 31 +- include/pm3_cmd.h | 12 + 10 files changed, 919 insertions(+), 2118 deletions(-) diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 474c08e1a..17bd8bbc2 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -65,7 +65,7 @@ thres| x x x x x x x x #define FPGA_MAJOR_MODE_HF_READER (0<<6) // D #define FPGA_MAJOR_MODE_HF_SIMULATOR (1<<6) // D #define FPGA_MAJOR_MODE_HF_ISO14443A (2<<6) // D -#define FPGA_MAJOR_MODE_HF_SNOOP (3<<6) // D +#define FPGA_MAJOR_MODE_HF_SNIFF (3<<6) // D #define FPGA_MAJOR_MODE_HF_ISO18092 (4<<6) // D #define FPGA_MAJOR_MODE_HF_GET_TRACE (5<<6) // D @@ -87,9 +87,9 @@ thres| x x x x x x x x #define FPGA_HF_READER_MODE_RECEIVE_PHASE (2<<0) #define FPGA_HF_READER_MODE_SEND_FULL_MOD (3<<0) #define FPGA_HF_READER_MODE_SEND_SHALLOW_MOD (4<<0) -#define FPGA_HF_READER_MODE_SNOOP_IQ (5<<0) -#define FPGA_HF_READER_MODE_SNOOP_AMPLITUDE (6<<0) -#define FPGA_HF_READER_MODE_SNOOP_PHASE (7<<0) +#define FPGA_HF_READER_MODE_SNIFF_IQ (5<<0) +#define FPGA_HF_READER_MODE_SNIFF_AMPLITUDE (6<<0) +#define FPGA_HF_READER_MODE_SNIFF_PHASE (7<<0) #define FPGA_HF_READER_MODE_SEND_JAM (8<<0) #define FPGA_HF_READER_SUBCARRIER_848_KHZ (0<<4) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 1e9bb671f..dbf759adf 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -54,6 +54,7 @@ #include "dbprint.h" #include "protocols.h" #include "ticks.h" +#include "iso15693.h" static int g_wait = 290; static int timeout = 5000; @@ -63,523 +64,33 @@ static uint32_t time_response = 0; static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay); int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf); -#define MODE_SIM_CSN 0 -#define MODE_EXIT_AFTER_MAC 1 -#define MODE_FULLSIM 2 - -#ifndef ICLASS_DMA_BUFFER_SIZE -# define ICLASS_DMA_BUFFER_SIZE 256 -#endif - // The length of a received command will in most cases be no more than 18 bytes. -// 32 should be enough! +// we expect max 34 bytes as tag answer (response to READ4) #ifndef ICLASS_BUFFER_SIZE -#define ICLASS_BUFFER_SIZE 32 +#define ICLASS_BUFFER_SIZE 34 #endif +// iCLASS has a slightly different timing compared to ISO15693. According to the picopass data sheet the tag response is expected 330us after +// the reader command. This is measured from end of reader EOF to first modulation of the tag's SOF which starts with a 56,64us unmodulated period. +// 330us = 140 ssp_clk cycles @ 423,75kHz when simulating. +// 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 + +// times in samples @ 212kHz when acting as reader +#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 + #define AddCrc(data, len) compute_crc(CRC_ICLASS, (data), (len), (data)+(len), (data)+(len)+1) -//----------------------------------------------------------------------------- -// The software UART that receives commands from the reader, and its state -// variables. -//----------------------------------------------------------------------------- -/* -typedef struct { - enum { - STATE_UNSYNCD, - STATE_START_OF_COMMUNICATION, - STATE_RECEIVING - } state; - uint16_t shiftReg; - int bitCnt; - int byteCnt; -// int byteCntMax; - int posCnt; - int nOutOfCnt; - int OutOfCnt; - int syncBit; - int samples; - int highCnt; - int swapper; - int counter; - int bitBuffer; - int dropPosition; - uint8_t *output; -} tUartIc; -*/ -typedef struct { - enum { - DEMOD_IC_UNSYNCD, - DEMOD_IC_START_OF_COMMUNICATION, - DEMOD_IC_START_OF_COMMUNICATION2, - DEMOD_IC_START_OF_COMMUNICATION3, - DEMOD_IC_SOF_COMPLETE, - DEMOD_IC_MANCHESTER_D, - DEMOD_IC_MANCHESTER_E, - DEMOD_IC_END_OF_COMMUNICATION, - DEMOD_IC_END_OF_COMMUNICATION2, - DEMOD_IC_MANCHESTER_F, - DEMOD_IC_ERROR_WAIT - } state; - int bitCount; - int posCount; - int syncBit; - uint16_t shiftReg; - uint32_t buffer; - uint32_t buffer2; - uint32_t buffer3; - int buff; - int samples; - int len; - enum { - SUB_NONE, - SUB_FIRST_HALF, - SUB_SECOND_HALF, - SUB_BOTH - } sub; - uint8_t *output; -} tDemodIc; - -/* -* Abrasive's uart implementation -* https://github.com/abrasive/proxmark3/commit/2b8bff7daea8ae1193bf7ee29b1fa46e95218902 -*/ -// Static vars for UART -typedef struct { - bool synced; - bool frame; - bool frame_done; - uint8_t *buf; - int len; -} tUartIc; -static tUartIc Uart; - static void OnError(uint8_t reason) { reply_mix(CMD_ACK, 0, reason, 0, 0, 0); switch_off(); } -static void uart_reset(void) { - Uart.frame_done = false; - Uart.synced = false; - Uart.frame = false; -} - -static void uart_init(uint8_t *data) { - Uart.buf = data; - uart_reset(); -} - -static void uart_bit(uint8_t bit) { - static uint8_t buf = 0xff; - static uint8_t n_buf; - static int nmsg_byte; - buf <<= 1; - buf |= bit ? 1 : 0; - - if (!Uart.frame) { - if (buf == 0x7b) { // 0b0111 1011 - Uart.frame = true; - n_buf = 0; - Uart.len = 0; - nmsg_byte = 0; - } - } else { - static uint8_t msg_byte; - n_buf++; - if (n_buf == 8) { - msg_byte >>= 2; - switch (buf) { - case 0xbf: // 0 - 1011 1111 - break; - case 0xef: // 1 - 1110 1111 - msg_byte |= (1 << 6); - break; - case 0xfb: // 2 - 1111 1011 - msg_byte |= (2 << 6); - break; - case 0xfe: // 3 - 1111 1110 - msg_byte |= (3 << 6); - break; - case 0xdf: // eof - 1101 1111 - Uart.frame = false; - Uart.synced = false; - Uart.frame_done = true; - break; - default: - Uart.frame = false; - Uart.synced = false; - Dbprintf("[-] bad %02X at %d:%d", buf, Uart.len, nmsg_byte); - } - - if (Uart.frame) { // data bits - nmsg_byte += 2; - if (nmsg_byte >= 8) { - Uart.buf[Uart.len++] = msg_byte; - nmsg_byte = 0; - } - } - n_buf = 0; - buf = 0xff; - } - } -} - -static void uart_samples(uint8_t byte) { - static uint32_t buf; - static int window; - static int drop_next = 0; - - uint32_t falling; - int lz; - - if (!Uart.synced) { - if (byte == 0xFF) - return; - buf = 0xFFFFFFFF; - window = 0; - drop_next = 0; - Uart.synced = true; - } - - buf <<= 8; - buf |= byte; - - if (drop_next) { - drop_next = 0; - return; - } - -again: - falling = ~buf & ((buf >> 1) ^ buf) & (0xFF << window); - - uart_bit(!falling); - - if (!falling) - return; - - lz = __builtin_clz(falling) - 24 + window; - - // aim to get falling edge on fourth-leftmost bit of window - window += 3 - lz; - - if (window < 0) { - window += 8; - drop_next = 1; - } else if (window >= 8) { - window -= 8; - goto again; - } -} - - -/* -static void UartReset(){ - Uart.state = STATE_UNSYNCD; - Uart.shiftReg = 0; - Uart.bitCnt = 0; - Uart.byteCnt = 0; - Uart.posCnt = 0; - Uart.nOutOfCnt = 0; - Uart.OutOfCnt = 0; - Uart.syncBit = 0; - Uart.samples = 0; - Uart.highCnt = 0; - Uart.swapper = 0; - Uart.counter = 0; - Uart.bitBuffer = 0; - Uart.dropPosition = 0; -} -*/ - -/* -* READER TO CARD -* 1 out of 4 Decoding -* 1 out of 256 Decoding -*/ -/* -static RAMFUNC int OutOfNDecoding(int bit) { - //int error = 0; - int bitright; - - if (!Uart.bitBuffer) { - Uart.bitBuffer = bit ^ 0xFF0; - return false; - } else { - Uart.bitBuffer <<= 4; - Uart.bitBuffer ^= bit; - } - - // if (Uart.swapper) { - // Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF; - // Uart.byteCnt++; - // Uart.swapper = 0; - // if (Uart.byteCnt > 15) return true; - // } - // else { - // Uart.swapper = 1; - // } - - if (Uart.state != STATE_UNSYNCD) { - Uart.posCnt++; - - if ((Uart.bitBuffer & Uart.syncBit) ^ Uart.syncBit) - bit = 0; - else - bit = 1; - - if (((Uart.bitBuffer << 1) & Uart.syncBit) ^ Uart.syncBit) - bitright = 0; - else - bitright = 1; - - if(bit != bitright) - bit = bitright; - - - // So, now we only have to deal with *bit*, lets see... - if (Uart.posCnt == 1) { - // measurement first half bitperiod - if (!bit) { - // Drop in first half means that we are either seeing - // an SOF or an EOF. - - if (Uart.nOutOfCnt == 1) { - // End of Communication - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - if (Uart.byteCnt == 0) { - // Its not straightforward to show single EOFs - // So just leave it and do not return TRUE - Uart.output[0] = 0xf0; - Uart.byteCnt++; - } else { - return true; - } - } else if (Uart.state != STATE_START_OF_COMMUNICATION) { - // When not part of SOF or EOF, it is an error - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - //error = 4; - } - } - } else { - // measurement second half bitperiod - // Count the bitslot we are in... (ISO 15693) - Uart.nOutOfCnt++; - - if (!bit) { - if (Uart.dropPosition) { - if (Uart.state == STATE_START_OF_COMMUNICATION) { - //error = 1; - } else { - //error = 7; - } - // It is an error if we already have seen a drop in current frame - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - } else { - Uart.dropPosition = Uart.nOutOfCnt; - } - } - Uart.posCnt = 0; - - if (Uart.nOutOfCnt == Uart.OutOfCnt && Uart.OutOfCnt == 4) { - Uart.nOutOfCnt = 0; - - if (Uart.state == STATE_START_OF_COMMUNICATION) { - if (Uart.dropPosition == 4) { - Uart.state = STATE_RECEIVING; - Uart.OutOfCnt = 256; - } else if (Uart.dropPosition == 3) { - Uart.state = STATE_RECEIVING; - Uart.OutOfCnt = 4; - //Uart.output[Uart.byteCnt] = 0xdd; - //Uart.byteCnt++; - } else { - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - } - Uart.dropPosition = 0; - } else { - // RECEIVING DATA - // 1 out of 4 - if (!Uart.dropPosition) { - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - //error = 9; - } else { - Uart.shiftReg >>= 2; - - // Swap bit order - Uart.dropPosition--; - //if(Uart.dropPosition == 1) { Uart.dropPosition = 2; } - //else if(Uart.dropPosition == 2) { Uart.dropPosition = 1; } - - Uart.shiftReg ^= ((Uart.dropPosition & 0x03) << 6); - Uart.bitCnt += 2; - Uart.dropPosition = 0; - - if (Uart.bitCnt == 8) { - Uart.output[Uart.byteCnt] = (Uart.shiftReg & 0xff); - Uart.byteCnt++; - Uart.bitCnt = 0; - Uart.shiftReg = 0; - } - } - } - } else if (Uart.nOutOfCnt == Uart.OutOfCnt) { - // RECEIVING DATA - // 1 out of 256 - if (!Uart.dropPosition) { - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - //error = 3; - } else { - Uart.dropPosition--; - Uart.output[Uart.byteCnt] = (Uart.dropPosition & 0xff); - Uart.byteCnt++; - Uart.bitCnt = 0; - Uart.shiftReg = 0; - Uart.nOutOfCnt = 0; - Uart.dropPosition = 0; - } - } -*/ -/*if (error) { - Uart.output[Uart.byteCnt] = 0xAA; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = error & 0xFF; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = 0xAA; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = (Uart.bitBuffer >> 8) & 0xFF; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = (Uart.syncBit >> 3) & 0xFF; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = 0xAA; - Uart.byteCnt++; - return true; -}*/ -/* - } - } else { - bit = Uart.bitBuffer & 0xf0; - bit >>= 4; - bit ^= 0x0F; // drops become 1s ;-) - if (bit) { - // should have been high or at least (4 * 128) / fc - // according to ISO this should be at least (9 * 128 + 20) / fc - if (Uart.highCnt == 8) { - // we went low, so this could be start of communication - // it turns out to be safer to choose a less significant - // syncbit... so we check whether the neighbour also represents the drop - Uart.posCnt = 1; // apparently we are busy with our first half bit period - Uart.syncBit = bit & 8; - Uart.samples = 3; - - if (!Uart.syncBit) { Uart.syncBit = bit & 4; Uart.samples = 2; } - else if (bit & 4) { Uart.syncBit = bit & 4; Uart.samples = 2; bit <<= 2; } - - if (!Uart.syncBit) { Uart.syncBit = bit & 2; Uart.samples = 1; } - else if (bit & 2) { Uart.syncBit = bit & 2; Uart.samples = 1; bit <<= 1; } - - if (!Uart.syncBit) { Uart.syncBit = bit & 1; Uart.samples = 0; - if (Uart.syncBit && (Uart.bitBuffer & 8)) { - Uart.syncBit = 8; - - // the first half bit period is expected in next sample - Uart.posCnt = 0; - Uart.samples = 3; - } - } else if (bit & 1) { Uart.syncBit = bit & 1; Uart.samples = 0; } - - Uart.syncBit <<= 4; - Uart.state = STATE_START_OF_COMMUNICATION; - Uart.bitCnt = 0; - Uart.byteCnt = 0; - Uart.nOutOfCnt = 0; - Uart.OutOfCnt = 4; // Start at 1/4, could switch to 1/256 - Uart.dropPosition = 0; - Uart.shiftReg = 0; - //error = 0; - } else { - Uart.highCnt = 0; - } - } else { - if (Uart.highCnt < 8) - Uart.highCnt++; - } - } - return false; -} -*/ -//============================================================================= -// Manchester -//============================================================================= -static tDemodIc Demod; -static void DemodIcReset(void) { - Demod.bitCount = 0; - Demod.posCount = 0; - Demod.syncBit = 0; - Demod.shiftReg = 0; - Demod.buffer = 0; - Demod.buffer2 = 0; - Demod.buffer3 = 0; - Demod.buff = 0; - Demod.samples = 0; - Demod.len = 0; - Demod.sub = SUB_NONE; - Demod.state = DEMOD_IC_UNSYNCD; -} -static void DemodIcInit(uint8_t *data) { - Demod.output = data; - DemodIcReset(); -} - -// UART debug -// it adds the debug values which will be put in the tracelog, -// visible on client when running 'hf list iclass' -/* -pm3 --> hf li iclass -Recorded Activity (TraceLen = 162 bytes) - Start | End | Src | Data (! denotes parity error) | CRC | Annotation | -------------|------------|-----|-----------------------------------------------------------------|-----|--------------------| - 0 | 0 | Rdr |0a | | ACTALL - 1280 | 1280 | Tag |bb! 33! bb! 01 02 04 08 bb! | ok | - 1280 | 1280 | Rdr |0c | | IDENTIFY - 1616 | 1616 | Tag |bb! 33! bb! 00! 02 00! 02 bb! | ok | - 1616 | 1616 | Rdr |0a | | ACTALL - 2336 | 2336 | Tag |bb! d4! bb! 02 08 00! 08 bb! | ok | - 2336 | 2336 | Rdr |0c | | IDENTIFY - 2448 | 2448 | Tag |bb! 33! bb! 00! 00! 00! 02 bb! | ok | - 2448 | 2448 | Rdr |0a | | ACTALL - 2720 | 2720 | Tag |bb! d4! bb! 08 0b 01 04 bb! | ok | - 2720 | 2720 | Rdr |0c | | IDENTIFY - 3232 | 3232 | Tag |bb! d4! bb! 02 02 08 04 bb! | ok | -*/ -static void uart_debug(int error, int bit) { - Demod.output[Demod.len] = 0xBB; - Demod.len++; - Demod.output[Demod.len] = error & 0xFF; - Demod.len++; - Demod.output[Demod.len] = 0xBB; - Demod.len++; - Demod.output[Demod.len] = bit & 0xFF; - Demod.len++; - Demod.output[Demod.len] = Demod.buffer & 0xFF; - Demod.len++; - // Look harder ;-) - Demod.output[Demod.len] = Demod.buffer2 & 0xFF; - Demod.len++; - Demod.output[Demod.len] = Demod.syncBit & 0xFF; - Demod.len++; - Demod.output[Demod.len] = 0xBB; - Demod.len++; -} - /* * CARD TO READER * in ISO15693-2 mode - Manchester @@ -596,568 +107,63 @@ static void uart_debug(int error, int bit) { * * So for current implementation in ISO15693, its 330 µs from end of reader, to start of card. */ -static RAMFUNC int ManchesterDecoding_iclass(uint32_t v) { - int bit; - int modulation; - int error = 0; - - bit = Demod.buffer; - Demod.buffer = Demod.buffer2; - Demod.buffer2 = Demod.buffer3; - Demod.buffer3 = v; - - // too few bits? - if (Demod.buff < 3) { - Demod.buff++; - return false; - } - - if (Demod.state == DEMOD_IC_UNSYNCD) { - Demod.output[Demod.len] = 0xfa; - Demod.syncBit = 0; - //Demod.samples = 0; - Demod.posCount = 1; // This is the first half bit period, so after syncing handle the second part - - if (bit & 0x08) - Demod.syncBit = 0x08; - - if (bit & 0x04) { - if (Demod.syncBit) - bit <<= 4; - - Demod.syncBit = 0x04; - } - - if (bit & 0x02) { - if (Demod.syncBit) - bit <<= 2; - - Demod.syncBit = 0x02; - } - - if (bit & 0x01 && Demod.syncBit) - Demod.syncBit = 0x01; - - if (Demod.syncBit) { - Demod.len = 0; - Demod.state = DEMOD_IC_START_OF_COMMUNICATION; - Demod.sub = SUB_FIRST_HALF; - Demod.bitCount = 0; - Demod.shiftReg = 0; - Demod.samples = 0; - - if (Demod.posCount) { - - switch (Demod.syncBit) { - case 0x08: - Demod.samples = 3; - break; - case 0x04: - Demod.samples = 2; - break; - case 0x02: - Demod.samples = 1; - break; - case 0x01: - Demod.samples = 0; - break; - } - // SOF must be long burst... otherwise stay unsynced!!! - if (!(Demod.buffer & Demod.syncBit) || !(Demod.buffer2 & Demod.syncBit)) - Demod.state = DEMOD_IC_UNSYNCD; - - } else { - // SOF must be long burst... otherwise stay unsynced!!! - if (!(Demod.buffer2 & Demod.syncBit) || !(Demod.buffer3 & Demod.syncBit)) { - Demod.state = DEMOD_IC_UNSYNCD; - error = 0x88; - uart_debug(error, bit); - return false; - } - } - } - return false; - } - - // state is DEMOD is in SYNC from here on. - - modulation = bit & Demod.syncBit; - modulation |= ((bit << 1) ^ ((Demod.buffer & 0x08) >> 3)) & Demod.syncBit; - Demod.samples += 4; - - if (Demod.posCount == 0) { - Demod.posCount = 1; - Demod.sub = (modulation) ? SUB_FIRST_HALF : SUB_NONE; - return false; - } - - Demod.posCount = 0; - - if (modulation) { - - if (Demod.sub == SUB_FIRST_HALF) - Demod.sub = SUB_BOTH; - else - Demod.sub = SUB_SECOND_HALF; - } - - if (Demod.sub == SUB_NONE) { - if (Demod.state == DEMOD_IC_SOF_COMPLETE) { - Demod.output[Demod.len] = 0x0f; - Demod.len++; - Demod.state = DEMOD_IC_UNSYNCD; - return true; - } else { - Demod.state = DEMOD_IC_ERROR_WAIT; - error = 0x33; - } - } - - switch (Demod.state) { - - case DEMOD_IC_START_OF_COMMUNICATION: - if (Demod.sub == SUB_BOTH) { - - Demod.state = DEMOD_IC_START_OF_COMMUNICATION2; - Demod.posCount = 1; - Demod.sub = SUB_NONE; - } else { - Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_IC_ERROR_WAIT; - error = 0xd2; - } - break; - - case DEMOD_IC_START_OF_COMMUNICATION2: - if (Demod.sub == SUB_SECOND_HALF) { - Demod.state = DEMOD_IC_START_OF_COMMUNICATION3; - } else { - Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_IC_ERROR_WAIT; - error = 0xd3; - } - break; - - case DEMOD_IC_START_OF_COMMUNICATION3: - if (Demod.sub == SUB_SECOND_HALF) { - Demod.state = DEMOD_IC_SOF_COMPLETE; - } else { - Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_IC_ERROR_WAIT; - error = 0xd4; - } - break; - - case DEMOD_IC_SOF_COMPLETE: - case DEMOD_IC_MANCHESTER_D: - case DEMOD_IC_MANCHESTER_E: - // OPPOSITE FROM ISO14443 - 11110000 = 0 (1 in 14443) - // 00001111 = 1 (0 in 14443) - if (Demod.sub == SUB_SECOND_HALF) { // SUB_FIRST_HALF - Demod.bitCount++; - Demod.shiftReg = (Demod.shiftReg >> 1) ^ 0x100; - Demod.state = DEMOD_IC_MANCHESTER_D; - } else if (Demod.sub == SUB_FIRST_HALF) { // SUB_SECOND_HALF - Demod.bitCount++; - Demod.shiftReg >>= 1; - Demod.state = DEMOD_IC_MANCHESTER_E; - } else if (Demod.sub == SUB_BOTH) { - Demod.state = DEMOD_IC_MANCHESTER_F; - } else { - Demod.state = DEMOD_IC_ERROR_WAIT; - error = 0x55; - } - break; - - case DEMOD_IC_MANCHESTER_F: - // Tag response does not need to be a complete byte! - if (Demod.len > 0 || Demod.bitCount > 0) { - if (Demod.bitCount > 1) { // was > 0, do not interpret last closing bit, is part of EOF - Demod.shiftReg >>= (9 - Demod.bitCount); // right align data - Demod.output[Demod.len] = Demod.shiftReg & 0xff; - Demod.len++; - } - - Demod.state = DEMOD_IC_UNSYNCD; - return true; - } else { - Demod.output[Demod.len] = 0xad; - Demod.state = DEMOD_IC_ERROR_WAIT; - error = 0x03; - } - break; - - case DEMOD_IC_ERROR_WAIT: - Demod.state = DEMOD_IC_UNSYNCD; - break; - - default: - Demod.output[Demod.len] = 0xdd; - Demod.state = DEMOD_IC_UNSYNCD; - break; - } - - if (Demod.bitCount >= 8) { - Demod.shiftReg >>= 1; - Demod.output[Demod.len] = (Demod.shiftReg & 0xff); - Demod.len++; - Demod.bitCount = 0; - Demod.shiftReg = 0; - } - - if (error) { - uart_debug(error, bit); - return true; - } - - return false; -} //============================================================================= -// Finally, a `sniffer' for iClass communication +// a `sniffer' for iClass communication // Both sides of communication! //============================================================================= -static void iclass_setup_sniff(void) { - if (DBGLEVEL > 3) Dbprintf("iclass_setup_sniff Enter"); - - LEDsoff(); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - - // connect Demodulated Signal to ADC: - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - - // Set up the synchronous serial port - FpgaSetupSsc(); - - BigBuf_free(); - BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(true); - - // Initialize Demod and Uart structs - DemodIcInit(BigBuf_malloc(ICLASS_BUFFER_SIZE)); - - uart_init(BigBuf_malloc(ICLASS_BUFFER_SIZE)); - //UartIcInit(BigBuf_malloc(ICLASS_BUFFER_SIZE)); - - if (DBGLEVEL > 1) { - // Print debug information about the buffer sizes - Dbprintf("[+] Sniffing buffers initialized:"); - Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen()); - Dbprintf(" Reader -> tag: %i bytes", ICLASS_BUFFER_SIZE); - Dbprintf(" tag -> Reader: %i bytes", ICLASS_BUFFER_SIZE); - Dbprintf(" DMA: %i bytes", ICLASS_DMA_BUFFER_SIZE); - } - - // Set FPGA in the appropriate mode - // put the FPGA in the appropriate mode - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER); - SpinDelay(200); - - // Start the SSP timer - StartCountSspClk(); - - LED_A_ON(); - if (DBGLEVEL > 3) Dbprintf("[+] iclass_setup_sniff Exit"); +void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string) { + SniffIso15693(jam_search_len, jam_search_string); } -//----------------------------------------------------------------------------- -// Record the sequence of commands sent by the reader to the tag, with -// triggering so that we start recording at the point that the tag is moved -// near the reader. -//----------------------------------------------------------------------------- -// turn off afterwards -void RAMFUNC SniffIClass(void) { - - //int datalen = 0; - uint32_t previous_data = 0; - uint32_t time_0 = 0, time_start = 0, time_stop; - uint32_t sniffCounter = 0; - bool TagIsActive = false; - bool ReaderIsActive = false; - - iclass_setup_sniff(); - - // The DMA buffer, used to stream samples from the FPGA - // *dmaBuf is the start reference. - uint8_t *dmaBuf = BigBuf_malloc(ICLASS_DMA_BUFFER_SIZE); - // pointer to samples from fpga - uint8_t *data = dmaBuf; - - // Setup and start DMA. - if (!FpgaSetupSscDma(dmaBuf, ICLASS_DMA_BUFFER_SIZE)) { - if (DBGLEVEL > 1) DbpString("[-] FpgaSetupSscDma failed. Exiting"); - return; - } - - // time ZERO, the point from which it all is calculated. - time_0 = GetCountSspClk(); - - // loop and listen - // every sample (1byte in data), - // contains HIGH nibble = reader data - // contains LOW nibble = tag data - // so two bytes are needed in order to get 1byte of either reader or tag data. (ie 2 sample bytes) - // since reader data is manchester encoded, we need 2bytes of data in order to get one demoded byte. (ie: 4 sample bytes) - uint16_t checked = 0; - for (;;) { - WDT_HIT(); - - if (checked == 1000) { - if (BUTTON_PRESS() || data_available()) break; - checked = 0; - } - ++checked; - - previous_data <<= 8; - previous_data |= *data; - - sniffCounter++; - data++; - - if (data == dmaBuf + ICLASS_DMA_BUFFER_SIZE) { - data = dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNCR = ICLASS_DMA_BUFFER_SIZE; - } - - // every odd sample - if (sniffCounter & 0x01) { - // no need to try decoding reader data if the tag is sending - // READER TO CARD - if (!TagIsActive) { - LED_C_INV(); - // HIGH nibble is always reader data. - uint8_t reader_byte = (previous_data & 0xF0) | (*data >> 4); - uart_samples(reader_byte); - if (Uart.frame_done) { - time_stop = GetCountSspClk() - time_0; - LogTrace(Uart.buf, Uart.len, time_start, time_stop, NULL, true); - DemodIcReset(); - uart_reset(); - } else { - time_start = GetCountSspClk() - time_0; - } - ReaderIsActive = Uart.frame_done; - } - } - // every four sample - if ((sniffCounter % 4) == 0) { - // need two samples to feed Manchester - // no need to try decoding tag data if the reader is sending - and we cannot afford the time - // CARD TO READER - if (!ReaderIsActive) { - LED_C_INV(); - // LOW nibble is always tag data. - /* - uint32_t tag_byte = - ((previous_data & 0x0F000000) >> 8 ) | - ((previous_data & 0x000F0000) >> 4 ) | - ((previous_data & 0x00000F00) ) | - ((previous_data & 0x0000000F) << 4 ) | - (*data & 0xF); - */ - - - uint8_t tag_byte = ((previous_data & 0xF) << 4) | (*data & 0xF); - if (ManchesterDecoding_iclass(tag_byte)) { - time_stop = GetCountSspClk() - time_0; - LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false); - DemodIcReset(); - uart_reset(); - } else { - time_start = GetCountSspClk() - time_0; - } - TagIsActive = (Demod.state != DEMOD_IC_UNSYNCD); - } - } - } // end main loop - - /* - if (DBGLEVEL >= 1) { - DbpString("[+] Sniff statistics:"); - Dbhexdump(ICLASS_DMA_BUFFER_SIZE, data, false); - } - */ - switch_off(); +static void rotateCSN(uint8_t *original_csn, uint8_t *rotated_csn) { + for (uint8_t i = 0; i < 8; i++) + rotated_csn[i] = (original_csn[i] >> 3) | (original_csn[(i + 1) % 8] << 5); } -static void rotateCSN(uint8_t *originalCSN, uint8_t *rotatedCSN) { - int i; - for (i = 0; i < 8; i++) - rotatedCSN[i] = (originalCSN[i] >> 3) | (originalCSN[(i + 1) % 8] << 5); +// Encode SOF only +static void CodeIClassTagSOF(void) { + ToSendReset(); + ToSend[++ToSendMax] = 0x1D; + ToSendMax++; } -//----------------------------------------------------------------------------- -// SIMULATION -// Wait for commands from reader -// Stop when button is pressed -// Or return TRUE when command is captured -//----------------------------------------------------------------------------- -static bool GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) { - // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen - // only, since we are receiving, not transmitting). - // Signal field is off with the appropriate LED - LED_D_OFF(); - uart_init(received); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); - // clear RXRDY: - uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - (void)b; - - uint16_t checked = 0; - for (;;) { - - WDT_HIT(); - - if (checked == 1000) { - if (BUTTON_PRESS() || data_available()) return false; - checked = 0; - } - ++checked; - - // keep tx buffer in a defined state anyway. - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) - AT91C_BASE_SSC->SSC_THR = 0x00; - - // wait for byte to become available in rx holding register - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - - uart_samples(b); - if (Uart.frame_done) { - *len = Uart.len; - return true; - } - } - } - return false; -} /* -static uint8_t encode4Bits(const uint8_t b) { - // OTA, the least significant bits first - // Manchester encoding added - // The columns are - // 1 - Bit value to send - // 2 - Reversed (big-endian) - // 3 - Machester Encoded - // 4 - Hex values + * SOF comprises 3 parts; + * * An unmodulated time of 56.64 us + * * 24 pulses of 423.75 kHz (fc/32) + * * A logic 1, which starts with an unmodulated time of 18.88us + * followed by 8 pulses of 423.75kHz (fc/32) + * + * + * EOF comprises 3 parts: + * - A logic 0 (which starts with 8 pulses of fc/32 followed by an unmodulated + * time of 18.88us. + * - 24 pulses of fc/32 + * - An unmodulated time of 56.64 us + * + * + * A logic 0 starts with 8 pulses of fc/32 + * followed by an unmodulated time of 256/fc (~18,88us). + * + * A logic 0 starts with unmodulated time of 256/fc (~18,88us) followed by + * 8 pulses of fc/32 (also 18.88us) + * + * The mode FPGA_HF_SIMULATOR_MODULATE_424K_8BIT which we use to simulate tag, + * works like this. + * - A 1-bit input to the FPGA becomes 8 pulses on 423.5kHz (fc/32) (18.88us). + * - A 0-bit input to the FPGA becomes an unmodulated time of 18.88us + * + * In this mode + * SOF can be written as 00011101 = 0x1D + * EOF can be written as 10111000 = 0xb8 + * logic 1 be written as 01 = 0x1 + * logic 0 be written as 10 = 0x2 + * + * + */ - uint8_t c = b & 0xF; - switch (c) { - // 1 2 3 4 - case 15: - return 0x55; // 1111 -> 1111 -> 01010101 -> 0x55 - case 14: - return 0x95; // 1110 -> 0111 -> 10010101 -> 0x95 - case 13: - return 0x65; // 1101 -> 1011 -> 01100101 -> 0x65 - case 12: - return 0xa5; // 1100 -> 0011 -> 10100101 -> 0xa5 - case 11: - return 0x59; // 1011 -> 1101 -> 01011001 -> 0x59 - case 10: - return 0x99; // 1010 -> 0101 -> 10011001 -> 0x99 - case 9: - return 0x69; // 1001 -> 1001 -> 01101001 -> 0x69 - case 8: - return 0xa9; // 1000 -> 0001 -> 10101001 -> 0xa9 - case 7: - return 0x56; // 0111 -> 1110 -> 01010110 -> 0x56 - case 6: - return 0x96; // 0110 -> 0110 -> 10010110 -> 0x96 - case 5: - return 0x66; // 0101 -> 1010 -> 01100110 -> 0x66 - case 4: - return 0xa6; // 0100 -> 0010 -> 10100110 -> 0xa6 - case 3: - return 0x5a; // 0011 -> 1100 -> 01011010 -> 0x5a - case 2: - return 0x9a; // 0010 -> 0100 -> 10011010 -> 0x9a - case 1: - return 0x6a; // 0001 -> 1000 -> 01101010 -> 0x6a - default: - return 0xaa; // 0000 -> 0000 -> 10101010 -> 0xaa - } -} -*/ - -static uint8_t lut_enc[] = { 0xAA, 0x6A, 0x9A, 0x5A, 0xA6, 0x66, 0x96, 0x56, 0xA9, 0x69, 0x99, 0x59, 0xA5, 0x65, 0x95, 0x55 }; - -//----------------------------------------------------------------------------- -// Prepare tag messages -//----------------------------------------------------------------------------- -static void CodeIClassTagAnswer(const uint8_t *cmd, int len) { - /* - * SOF comprises 3 parts; - * * An unmodulated time of 56.64 us - * * 24 pulses of 423.75 kHz (fc/32) - * * A logic 1, which starts with an unmodulated time of 18.88us - * followed by 8 pulses of 423.75kHz (fc/32) - * - * - * EOF comprises 3 parts: - * - A logic 0 (which starts with 8 pulses of fc/32 followed by an unmodulated - * time of 18.88us. - * - 24 pulses of fc/32 - * - An unmodulated time of 56.64 us - * - * - * A logic 0 starts with 8 pulses of fc/32 - * followed by an unmodulated time of 256/fc (~18,88us). - * - * A logic 0 starts with unmodulated time of 256/fc (~18,88us) followed by - * 8 pulses of fc/32 (also 18.88us) - * - * The mode FPGA_HF_SIMULATOR_MODULATE_424K_8BIT which we use to simulate tag, - * works like this. - * - A 1-bit input to the FPGA becomes 8 pulses on 423.5kHz (fc/32) (18.88us). - * - A 0-bit input to the FPGA becomes an unmodulated time of 18.88us - * - * In this mode - * SOF can be written as 00011101 = 0x1D - * EOF can be written as 10111000 = 0xb8 - * logic 1 be written as 01 = 0x1 - * logic 0 be written as 10 = 0x2 - * - * */ - ToSendReset(); - - // Send SOF - ToSend[++ToSendMax] = 0x1D; - - int i; - for (i = 0; i < len; i++) { - uint8_t b = cmd[i]; - ToSend[++ToSendMax] = lut_enc[b & 0xF]; // least significant half - ToSend[++ToSendMax] = lut_enc[(b >> 4) & 0xF]; // most significant half - } - - // Send EOF - ToSend[++ToSendMax] = 0xB8; - //lastProxToAirDuration = 8*ToSendMax - 3*8 - 3*8;//Not counting zeroes in the beginning or end - // Convert from last byte pos to length - ToSendMax++; -} - -// Only SOF -static void CodeIClassTagSOF(void) { - //So far a dummy implementation, not used - //int lastProxToAirDuration =0; - - ToSendReset(); - // Send SOF - ToSend[++ToSendMax] = 0x1D; - // lastProxToAirDuration = 8*ToSendMax - 3*8;//Not counting zeroes in the beginning - - // Convert from last byte pos to length - ToSendMax++; -} /** * @brief SimulateIClass simulates an iClass card. @@ -1178,13 +184,8 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - // this will clear out bigbuf memory, the eload command must select this before! - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - FpgaSetupSsc(); - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - - // Enable and clear the trace + Iso15693InitTag(); + clear_trace(); set_tracing(true); @@ -1195,30 +196,29 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain uint8_t *emulator = BigBuf_get_EM_addr(); uint8_t mac_responses[PM3_CMD_DATA_SIZE] = { 0 }; - if (simType == 0) { + if (simType == ICLASS_SIM_MODE_CSN) { // Use the CSN from commandline memcpy(emulator, datain, 8); - doIClassSimulation(MODE_SIM_CSN, NULL); - } else if (simType == 1) { + doIClassSimulation(ICLASS_SIM_MODE_CSN, NULL); + } else if (simType == ICLASS_SIM_MODE_CSN_DEFAULT) { //Default CSN - uint8_t csn_crc[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0, 0x00, 0x00 }; + uint8_t csn[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0 }; // Use the CSN from commandline - memcpy(emulator, csn_crc, 8); - doIClassSimulation(MODE_SIM_CSN, NULL); - } else if (simType == 2) { + memcpy(emulator, csn, 8); + doIClassSimulation(ICLASS_SIM_MODE_CSN, NULL); + } else if (simType == ICLASS_SIM_MODE_READER_ATTACK) { Dbprintf("[+] going into attack mode, %d CSNS sent", numberOfCSNS); // In this mode, a number of csns are within datain. We'll simulate each one, one at a time // in order to collect MAC's from the reader. This can later be used in an offlne-attack // in order to obtain the keys, as in the "dismantling iclass"-paper. -#define EPURSE_MAC_SIZE 16 + #define EPURSE_MAC_SIZE 16 int i = 0; for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < PM3_CMD_DATA_SIZE; i++) { - // The usb data is 512 bytes, fitting 65 8-byte CSNs in there. memcpy(emulator, datain + (i * 8), 8); - if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) { + if (doIClassSimulation(ICLASS_SIM_MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) { // Button pressed reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE); goto out; @@ -1226,11 +226,11 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain } reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE); - } else if (simType == 3) { + } else if (simType == ICLASS_SIM_MODE_FULL) { //This is 'full sim' mode, where we use the emulator storage for data. //ie: BigBuf_get_EM_addr should be previously filled with data from the "eload" command - doIClassSimulation(MODE_FULLSIM, NULL); - } else if (simType == 4) { + doIClassSimulation(ICLASS_SIM_MODE_FULL, NULL); + } else if (simType == ICLASS_SIM_MODE_READER_ATTACK_KEYROLL) { // This is the KEYROLL version of sim 2. // the collected data (mac_response) is doubled out since we are trying to collect both keys in the keyroll process. @@ -1287,11 +287,16 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { // free eventually allocated BigBuf memory BigBuf_free_keep_EM(); - State cipher_state; + uint16_t page_size = 32 * 8; + uint8_t current_page = 0; - uint8_t *csn = BigBuf_get_EM_addr(); - uint8_t *emulator = csn; - uint8_t sof_data[] = { 0x0F} ; + // maintain cipher states for both credit and debit key for each page + State cipher_state_KD[8]; + State cipher_state_KC[8]; + State *cipher_state = &cipher_state_KD[0]; + + uint8_t *emulator = BigBuf_get_EM_addr(); + uint8_t *csn = emulator; // CSN followed by two CRC bytes uint8_t anticoll_data[10] = { 0 }; @@ -1305,28 +310,75 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { AddCrc(anticoll_data, 8); AddCrc(csn_data, 8); - uint8_t diversified_key[8] = { 0 }; + uint8_t diversified_kd[8] = { 0 }; + uint8_t diversified_kc[8] = { 0 }; + uint8_t *diversified_key = diversified_kd; + + // configuration block + uint8_t conf_block[10] = {0x12, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0xFF, 0x3C, 0x00, 0x00}; // e-Purse uint8_t card_challenge_data[8] = { 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - //uint8_t card_challenge_data[8] = { 0 }; - if (simulationMode == MODE_FULLSIM) { - //The diversified key should be stored on block 3 - //Get the diversified key from emulator memory - memcpy(diversified_key, emulator + (8 * 3), 8); - //Card challenge, a.k.a e-purse is on block 2 - memcpy(card_challenge_data, emulator + (8 * 2), 8); + // AIA + uint8_t aia_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00}; + + if (simulationMode == ICLASS_SIM_MODE_FULL) { - //Precalculate the cipher state, feeding it the CC - cipher_state = opt_doTagMAC_1(card_challenge_data, diversified_key); + memcpy(conf_block, emulator + (8 * 1), 8); // blk 1 + memcpy(card_challenge_data, emulator + (8 * 2), 8); // e-purse, blk 2 + memcpy(diversified_kd, emulator + (8 * 3), 8); // Kd, blk 3 + memcpy(diversified_kc, emulator + (8 * 4), 8); // Kc, blk 4 + + + // (iceman) this only works for 2KS / 16KS tags. + // Use application data from block 5 + memcpy(aia_data, emulator + (8 * 5), 8); + // older 2K / 16K tags has its application issuer data on block 2 } + + AddCrc(conf_block, 8); + AddCrc(aia_data, 8); + // set epurse of sim2,4 attack if (reader_mac_buf != NULL) { memcpy(reader_mac_buf, card_challenge_data, 8); } + if ((conf_block[5] & 0x80) == 0x80) { + page_size = 256 * 8; + } + + // From PicoPass DS: + // When the page is in personalization mode this bit is equal to 1. + // Once the application issuer has personalized and coded its dedicated areas, this bit must be set to 0: + // the page is then "in application mode". + bool personalization_mode = conf_block[7] & 0x80; + + // chip memory may be divided in 8 pages + uint8_t max_page = ((conf_block[4] & 0x10) == 0x10) ? 0 : 7; + + // Precalculate the cipher states, feeding it the CC + cipher_state_KD[0] = opt_doTagMAC_1(card_challenge_data, diversified_kd); + cipher_state_KC[0] = opt_doTagMAC_1(card_challenge_data, diversified_kc); + + if (simulationMode == ICLASS_SIM_MODE_FULL) { + + for (int i = 1; i < max_page; i++) { + + // does all pages has their own epurse??) + uint8_t *epurse = emulator + (i * page_size) + (8 * 2); + uint8_t *kd = emulator + (i * page_size) + (8 * 3); + uint8_t *kc = emulator + (i * page_size) + (8 * 4); + + cipher_state_KD[i] = opt_doTagMAC_1(epurse, kd); + cipher_state_KC[i] = opt_doTagMAC_1(epurse, kc); + } + } + int exitLoop = 0; + + // Anti-collision process: // Reader 0a // Tag 0f // Reader 0c @@ -1340,8 +392,8 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { int trace_data_size = 0; // Respond SOF -- takes 1 bytes - uint8_t *resp_sof = BigBuf_malloc(2); - int resp_sof_Len; + uint8_t *resp_sof = BigBuf_malloc(1); + int resp_sof_len; // Anticollision CSN (rotated CSN) // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte) @@ -1353,34 +405,27 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { uint8_t *resp_csn = BigBuf_malloc(28); int resp_csn_len; - // configuration Picopass 2ks + // configuration (blk 1) PICOPASS 2ks uint8_t *resp_conf = BigBuf_malloc(28); int resp_conf_len; - uint8_t conf_data[10] = {0x12, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0xFF, 0x3C, 0x00, 0x00}; - AddCrc(conf_data, 8); // e-Purse // 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit) uint8_t *resp_cc = BigBuf_malloc(28); int resp_cc_len; + // Kd, Kc (blocks 3 and 4). Cannot be read. Always respond with 0xff bytes only + uint8_t *resp_ff = BigBuf_malloc(22); + int resp_ff_len; + uint8_t ff_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00}; + AddCrc(ff_data, 8); + // Application Issuer Area uint8_t *resp_aia = BigBuf_malloc(28); int resp_aia_len; - uint8_t aia_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00}; - if (simulationMode == MODE_FULLSIM) { - - // (iceman) this only works for 2KS / 16KS tags. - // Use application data from block 5 - memcpy(aia_data, emulator + (8 * 5), 8); - - // older 2K / 16K tags has its application issuer data on block 2 - } - AddCrc(aia_data, 8); // receive command uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); - int len = 0; // Prepare card messages ToSendMax = 0; @@ -1388,142 +433,153 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { // First card answer: SOF CodeIClassTagSOF(); memcpy(resp_sof, ToSend, ToSendMax); - resp_sof_Len = ToSendMax; + resp_sof_len = ToSendMax; // Anticollision CSN - CodeIClassTagAnswer(anticoll_data, sizeof(anticoll_data)); + CodeIso15693AsTag(anticoll_data, sizeof(anticoll_data)); memcpy(resp_anticoll, ToSend, ToSendMax); resp_anticoll_len = ToSendMax; - // CSN - CodeIClassTagAnswer(csn_data, sizeof(csn_data)); + // CSN (block 0) + CodeIso15693AsTag(csn_data, sizeof(csn_data)); memcpy(resp_csn, ToSend, ToSendMax); resp_csn_len = ToSendMax; - // Configuration - CodeIClassTagAnswer(conf_data, sizeof(conf_data)); + // Configuration (block 1) + CodeIso15693AsTag(conf_block, sizeof(conf_block)); memcpy(resp_conf, ToSend, ToSendMax); resp_conf_len = ToSendMax; - // e-Purse - CodeIClassTagAnswer(card_challenge_data, sizeof(card_challenge_data)); + // e-Purse (block 2) + CodeIso15693AsTag(card_challenge_data, sizeof(card_challenge_data)); memcpy(resp_cc, ToSend, ToSendMax); resp_cc_len = ToSendMax; - // Application Issuer Area - CodeIClassTagAnswer(aia_data, sizeof(aia_data)); + // Kd, Kc (blocks 3 and 4) + CodeIso15693AsTag(ff_data, sizeof(ff_data)); + memcpy(resp_ff, ToSend, ToSendMax); + resp_ff_len = ToSendMax; + + // Application Issuer Area (block 5) + CodeIso15693AsTag(aia_data, sizeof(aia_data)); memcpy(resp_aia, ToSend, ToSendMax); resp_aia_len = ToSendMax; //This is used for responding to READ-block commands or other data which is dynamically generated //First the 'trace'-data, not encoded for FPGA - uint8_t *data_generic_trace = BigBuf_malloc((8 * 4) + 2);//8 bytes data + 2byte CRC is max tag answer + uint8_t *data_generic_trace = BigBuf_malloc(32 + 2);//8 bytes data + 2byte CRC is max tag answer //Then storage for the modulated data //Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes) - uint8_t *data_response = BigBuf_malloc(((8 * 4) + 2) * 2 + 2); + uint8_t *data_response = BigBuf_malloc((32 + 2) * 2 + 2); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); - SpinDelay(100); - StartCountSspClk(); + enum { IDLE, ACTIVATED, SELECTED, HALTED } chip_state = IDLE; - // To control where we are in the protocol - uint32_t time_0 = GetCountSspClk(); - uint32_t t2r_stime = 0, t2r_etime = 0; - uint32_t r2t_stime, r2t_etime = 0; - LED_A_ON(); - bool buttonPressed = false; + bool button_pressed = false; uint8_t cmd, options, block; + int len = 0; - while (!exitLoop) { + while (exitLoop == false) { WDT_HIT(); - - //Signal tracer, can be used to get a trigger for an oscilloscope.. - LED_B_OFF(); - LED_C_OFF(); - - r2t_stime = (GetCountSspClk() - time_0) << 4; - if (!GetIClassCommandFromReader(receivedCmd, &len, 0)) { - buttonPressed = true; + + uint32_t reader_eof_time = 0; + len = GetIso15693CommandFromReader(receivedCmd, MAX_FRAME_SIZE, &reader_eof_time); + if (len < 0) { + button_pressed = true; exitLoop = true; continue; } - r2t_etime = ((GetCountSspClk() - time_0) << 4) - r2t_stime; - // 330us normal wait, adjusted for our execution - - LED_C_ON(); //Signal tracer + // Now look at the reader command and provide appropriate responses + // default is no response: + modulated_response = NULL; + modulated_response_size = 0; + trace_data = NULL; + trace_data_size = 0; + // extra response data cmd = receivedCmd[0] & 0xF; options = (receivedCmd[0] >> 4) & 0xFF; block = receivedCmd[1]; - if (cmd == ICLASS_CMD_ACTALL) { // 0x0A + if (cmd == ICLASS_CMD_ACTALL && len == 1) { // 0x0A // Reader in anticollission phase - modulated_response = resp_sof; - modulated_response_size = resp_sof_Len; //order = 1; - trace_data = sof_data; - trace_data_size = sizeof(sof_data); - // adjusted for 330 + (160*num of slot) - goto send; - } else if (cmd == ICLASS_CMD_READ_OR_IDENTIFY) { // 0x0C - if (len == 1) { - // Reader asks for anticollission CSN - modulated_response = resp_anticoll; - modulated_response_size = resp_anticoll_len; //order = 2; - trace_data = anticoll_data; - trace_data_size = sizeof(anticoll_data); + if (chip_state != HALTED) { + modulated_response = resp_sof; + modulated_response_size = resp_sof_len; //order = 1; + chip_state = ACTIVATED; goto send; } + } else if (cmd == ICLASS_CMD_READ_OR_IDENTIFY) { // 0x0C + if (len == 1) { + // Reader asks for anticollission CSN + if (chip_state == SELECTED || chip_state == ACTIVATED) { + modulated_response = resp_anticoll; + modulated_response_size = resp_anticoll_len; //order = 2; + trace_data = anticoll_data; + trace_data_size = sizeof(anticoll_data); + goto send; + } + } + if (len == 4) { - // block0,1,2,5 is always readable. - switch (block) { - case 0: // csn (0c 00) - modulated_response = resp_csn; - modulated_response_size = resp_csn_len; - trace_data = csn_data; - trace_data_size = sizeof(csn_data); - goto send; - case 1: // configuration (0c 01) - modulated_response = resp_conf; - modulated_response_size = resp_conf_len; - trace_data = conf_data; - trace_data_size = sizeof(conf_data); - goto send; - case 2: // e-purse (0c 02) - modulated_response = resp_cc; - modulated_response_size = resp_cc_len; - trace_data = card_challenge_data; - trace_data_size = sizeof(card_challenge_data); - // set epurse of sim2,4 attack - if (reader_mac_buf != NULL) { - memcpy(reader_mac_buf, card_challenge_data, 8); - } - goto send; - case 5:// Application Issuer Area (0c 05) - modulated_response = resp_aia; - modulated_response_size = resp_aia_len; - trace_data = aia_data; - trace_data_size = sizeof(aia_data); - goto send; - default : { - if (simulationMode == MODE_FULLSIM) { // 0x0C - //Read block - //Take the data... - memcpy(data_generic_trace, emulator + (block << 3), 8); - AddCrc(data_generic_trace, 8); - trace_data = data_generic_trace; - trace_data_size = 10; - CodeIClassTagAnswer(trace_data, trace_data_size); - memcpy(modulated_response, ToSend, ToSendMax); - modulated_response_size = ToSendMax; + if (chip_state == SELECTED) { + // block0,1,2,5 is always readable. + switch (block) { + case 0: // csn (0c 00) + modulated_response = resp_csn; + modulated_response_size = resp_csn_len; + trace_data = csn_data; + trace_data_size = sizeof(csn_data); goto send; + case 1: // configuration (0c 01) + modulated_response = resp_conf; + modulated_response_size = resp_conf_len; + trace_data = conf_data; + trace_data_size = sizeof(conf_data); + goto send; + case 2: // e-purse (0c 02) + modulated_response = resp_cc; + modulated_response_size = resp_cc_len; + trace_data = card_challenge_data; + trace_data_size = sizeof(card_challenge_data); + // set epurse of sim2,4 attack + if (reader_mac_buf != NULL) { + memcpy(reader_mac_buf, card_challenge_data, 8); + } + goto send; + case 3: + case 4: // Kd, Kc, always respond with 0xff bytes + modulated_response = resp_ff; + modulated_response_size = resp_ff_len; + trace_data = ff_data; + trace_data_size = sizeof(ff_data); + goto send; + case 5:// Application Issuer Area (0c 05) + modulated_response = resp_aia; + modulated_response_size = resp_aia_len; + trace_data = aia_data; + trace_data_size = sizeof(aia_data); + goto send; + default : { + if (simulationMode == ICLASS_SIM_MODE_FULL) { // 0x0C + //Read block + //Take the data... + memcpy(data_generic_trace, emulator + (block << 3), 8); + AddCrc(data_generic_trace, 8); + trace_data = data_generic_trace; + trace_data_size = 10; + CodeIClassTagAnswer(trace_data, trace_data_size); + memcpy(modulated_response, ToSend, ToSendMax); + modulated_response_size = ToSendMax; + goto send; + } + break; } - break; - } - }//swith - }// if 4 + } // swith + } // selected + } // if 4 } else if (cmd == ICLASS_CMD_SELECT) { // 0x81 // Reader selects anticollission CSN. // Tag sends the corresponding real CSN @@ -1542,7 +598,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { goto send; } else if (cmd == ICLASS_CMD_CHECK) { // 0x05 // Reader random and reader MAC!!! - if (simulationMode == MODE_FULLSIM) { + if (simulationMode == ICLASS_SIM_MODE_FULL) { // NR, from reader, is in receivedCmd +1 opt_doTagMAC_2(cipher_state, receivedCmd + 1, data_generic_trace, diversified_key); @@ -1579,24 +635,28 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { } goto send; } else if (cmd == ICLASS_CMD_HALT && options == 0 && len == 1) { - // Reader ends the session - modulated_response = resp_sof; - modulated_response_size = 0; //order = 0; - trace_data = NULL; - trace_data_size = 0; - goto send; - } else if (simulationMode == MODE_FULLSIM && cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06 - //Read block - //Take the data... - memcpy(data_generic_trace, emulator + (block << 3), 8 * 4); - AddCrc(data_generic_trace, 8 * 4); - trace_data = data_generic_trace; - trace_data_size = 34; - CodeIClassTagAnswer(trace_data, trace_data_size); - memcpy(modulated_response, ToSend, ToSendMax); - modulated_response_size = ToSendMax; - goto send; - } else if (simulationMode == MODE_FULLSIM && cmd == ICLASS_CMD_UPDATE) { + + if (chip_state == SELECTED) { + // Reader ends the session + modulated_response = resp_sof; + modulated_response_size = resp_sof_Len; + chip_state = HALTED; + goto send; + } + } else if (simulationMode == ICLASS_SIM_MODE_FULL && cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06 + + if (chip_state == SELECTED) { + //Read block + memcpy(data_generic_trace, emulator + (current_page * page_size) + (block * 8), 8 * 4); + AddCrc(data_generic_trace, 8 * 4); + trace_data = data_generic_trace; + trace_data_size = 34; + CodeIso15693AsTag(trace_data, trace_data_size); + memcpy(modulated_response, ToSend, ToSendMax); + modulated_response_size = ToSendMax; + goto send; + } + } else if (simulationMode == ICLASS_SIM_MODE_FULL && cmd == ICLASS_CMD_UPDATE) { //Probably the reader wants to update the nonce. Let's just ignore that for now. // OBS! If this is implemented, don't forget to regenerate the cipher_state @@ -1622,17 +682,12 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { // It appears we're fine ignoring this. //Otherwise, we should answer 8bytes (block) + 2bytes CRC // } else if(receivedCmd[0] == ICLASS_CMD_DETECT) { // 0x0F + } else if (receivedCmd[0] == 0x26 && len == 5) { + // standard ISO15693 INVENTORY command. Ignore. } else { - //#db# Unknown command received from reader (len=5): 26 1 0 f6 a 44 44 44 44 // Never seen this command before - if (DBGLEVEL == DBG_EXTENDED) + if (DBGLEVEL >= DBG_EXTENDED) print_result("[-] Unhandled command received ", receivedCmd, len); - - // Do not respond - modulated_response = resp_sof; - modulated_response_size = 0; //order = 0; - trace_data = NULL; - trace_data_size = 0; } send: @@ -1640,70 +695,20 @@ send: A legit tag has about 330us delay between reader EOT and tag SOF. **/ if (modulated_response_size > 0) { - t2r_stime = GetCountSspClkDelta(time_0) << 4; - SendIClassAnswer(modulated_response, modulated_response_size, 0); - t2r_etime = ((GetCountSspClk() - time_0) << 4) - t2r_stime; + uint32_t response_time = reader_eof_time + DELAY_ICLASS_VCD_TO_VICC_SIM; + TransmitTo15693Reader(modulated_response, modulated_response_size, &response_time, 0, false); + LogTrace(trace_data, trace_data_size, response_time*32, response_time*32 + modulated_response_size*32*64, NULL, false); } - - LogTrace(receivedCmd, len, r2t_stime, r2t_etime, NULL, true); - - if (trace_data != NULL) - LogTrace(trace_data, trace_data_size, t2r_stime, t2r_etime, NULL, false); } LEDsoff(); - if (buttonPressed) + if (button_pressed) DbpString("[+] button pressed"); - return buttonPressed; + return button_pressed; } -/** - * @brief sends our simulated tag answer - * @param resp - * @param respLen - * @param delay - */ -static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) { - int i = 0; - volatile uint8_t b; - - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K_8BIT); - - AT91C_BASE_SSC->SSC_THR = 0x00; - - uint16_t checked = 0; - for (;;) { - - if (checked == 1000) { - if (BUTTON_PRESS() || data_available()) return 0; - checked = 0; - } - ++checked; - - // Prevent rx holding register from overflowing - if ((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) { - b = AT91C_BASE_SSC->SSC_RHR; - (void) b; - } - - // Put byte into tx holding register as soon as it is ready - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - b = 0x00; - if (i < respLen) { - b = resp[i]; - //Hack - //b = 0xAC; - } - i++; - AT91C_BASE_SSC->SSC_THR = b; - } -// if (i > respLen + 4) break; - if (i > respLen + 1) break; - } - return 0; -} /// THE READER CODE @@ -1754,194 +759,42 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *wait) { time_rdr = GetCountSspClk(); } -//----------------------------------------------------------------------------- -// Prepare iClass reader command to send to FPGA -//----------------------------------------------------------------------------- -static void CodeIClassCommand(const uint8_t *cmd, int len) { - int i, j, k; +static void ReaderTransmitIClass(uint8_t *frame, int len, uint32_t *start_time) { - ToSendReset(); + CodeIso15693AsReader(frame, len); + TransmitTo15693Tag(ToSend, ToSendMax, start_time); + uint32_t end_time = *start_time + 32 * (8 * ToSendMax - 4); // substract the 4 padding bits after EOF - // (SOC) Start of Communication: 1 out of 4 - ToSend[++ToSendMax] = 0xf0; - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0x0f; - ToSend[++ToSendMax] = 0x00; - - // Modulate the bytes - for (i = 0; i < len; i++) { - uint8_t b = cmd[i]; - for (j = 0; j < 4; j++) { - for (k = 0; k < 4; k++) { - - if (k == (b & 3)) - ToSend[++ToSendMax] = 0x0f; - else - ToSend[++ToSendMax] = 0x00; - } - b >>= 2; - } - } - - // (EOC) End of Communication - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0xf0; - ToSend[++ToSendMax] = 0x00; - - // Convert from last character reference to length - ToSendMax++; + LogTrace(frame, len, *start_time * 4, end_time * 4, NULL, true); } -static void ReaderTransmitIClass_ext(uint8_t *frame, int len, int wait) { +static bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, size_t max_resp_size, + uint8_t expected_size, uint8_t tries, uint32_t start_time, + uint32_t timeout, uint32_t *eof_time) { + while (tries-- > 0) { - // This is tied to other size changes - CodeIClassCommand(frame, len); - - // Select the card - TransmitIClassCommand(ToSend, ToSendMax, &wait); - LED_A_ON(); - - LogTrace(frame, len, g_rsamples, g_rsamples, NULL, true); -} -static void ReaderTransmitIClass(uint8_t *frame, int len) { - ReaderTransmitIClass_ext(frame, len, 330); -} - -//----------------------------------------------------------------------------- -// Wait a certain time for tag response -// If a response is captured return TRUE -// If it takes too long return FALSE -//----------------------------------------------------------------------------- -static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *wait) { - // buffer needs to be 512 bytes - // maxLen is not used... - bool skip = false; - - LED_D_ON(); - // Set FPGA mode to "reader listen mode", no modulation (listen - // only, since we are receiving, not transmitting). - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); - - // Setup UART/DEMOD to receive - DemodIcInit(receivedResponse); - - SpinDelayUs(g_wait); //310 Tout= 330us (iso15603-2) (330/21.3) take consideration for clock increments. - - // clear RXRDY: - uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - (void)b; - - uint16_t checked = 0; - - uint32_t card_start = GetCountSspClk(); - for (;;) { - WDT_HIT(); - - if (checked == 1000) { - if (BUTTON_PRESS() || data_available()) return false; - checked = 0; - } - ++checked; - - // Wait for byte be become available in rx holding register - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - - b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - skip = !skip; - if (skip) continue; - - if (ManchesterDecoding_iclass(b & 0x0f)) { - time_response = GetCountSspClk() - card_start; - return true; - } else if (GetCountSspClkDelta(card_start) > timeout && Demod.state == DEMOD_IC_UNSYNCD) { - return false; - } - } - } - return false; -} - -static int ReaderReceiveIClass(uint8_t *receivedAnswer) { - - if (GetIClassAnswer(receivedAnswer, 0, NULL) == false) - return 0; - - LogTrace(receivedAnswer, Demod.len, g_rsamples, g_rsamples, NULL, false); - return Demod.len; -} - -static void setupIclassReader(void) { - - LEDsoff(); - - // Start from off (no field generated) - // Signal field is off with the appropriate LED - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - - FpgaSetupSsc(); - - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - - clear_trace(); - set_tracing(true); - - // Now give it time to spin up. - // Signal field is on with the appropriate LED - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); - SpinDelay(500); - - StartCountSspClk(); - - LED_A_ON(); -} - -static bool sendCmdGetResponseWithRetries(uint8_t *command, size_t cmdsize, uint8_t *resp, uint8_t expected_size, int8_t retries) { - while (retries-- > 0) { - - ReaderTransmitIClass(command, cmdsize); - - //iceman - if received size is bigger than expected, we smash the stack here - // since its called with fixed sized arrays - - // update/write command takes 4ms to 15ms before responding - int old_wait = g_wait; - if ((command[0] & 0xF) == ICLASS_CMD_UPDATE) - 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 -// SpinDelayUs(360); - continue; - } - - if (got_n == expected_size) + ReaderTransmitIClass(command, cmdsize, &start_time); + if (expected_size == GetIso15693AnswerFromTag(resp, max_resp_size, timeout, eof_time)) { return true; + } } return false; } /** * @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 + * @param card_data where the CSN, CONFIG, CC are stored for return + * 8 bytes csn + 8 bytes config + 8 bytes CC + * @return false = fail + * true = Got all. */ -static uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) { +static bool selectIclassTag(uint8_t *card_data, bool use_credit_key, uint32_t *eof_time) { - // act_all... - static uint8_t act_all[] = { ICLASS_CMD_ACTALL }; - static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 }; - static uint8_t select[] = { 0x80 | ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t readcheck_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 }; + static uint8_t act_all[] = { ICLASS_CMD_ACTALL }; + static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 }; + static uint8_t select[] = { 0x80 | ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static uint8_t read_conf[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22 }; + static uint8_t read_check_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 }; // Bit 4: K.If this bit equals to one, the READCHECK will use the Credit Key (Kc); if equals to zero, Debit Key (Kd) willbe used // bit 7: parity. @@ -1950,58 +803,63 @@ static uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) { readcheck_cc[0] = 0x10 | ICLASS_CMD_READCHECK; uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; + + uint32_t start_time = GetCountSspClk(); - // Send act_all ( 330 timeout + 160 timeslot); - ReaderTransmitIClass_ext(act_all, 1, 330 + 180); + ReaderTransmitIClass(act_all, 1, &start_time); - // Card present? - if (ReaderReceiveIClass(resp) == 0) - return 0; + // card present? + if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_ACTALL, eof_time) < 0) + return false; - //Send Identify - ReaderTransmitIClass(identify, 1); + // send Identify + start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + ReaderTransmitIClass(identify, 1, &start_time); - //We expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC - if (ReaderReceiveIClass(resp) != 10) - return 0; + // 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 false; - //Copy the Anti-collision CSN to our select-packet + // copy the Anti-collision CSN to our select-packet memcpy(&select[1], resp, 8); - //Select the card - ReaderTransmitIClass(select, sizeof(select)); + // select the card + start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + ReaderTransmitIClass(select, sizeof(select), &start_time); - //We expect a 10-byte response here, 8 byte CSN and 2 byte CRC - if (ReaderReceiveIClass(resp) != 10) - return 0; + // 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 false; - // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) - // ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); - // if (ReaderReceiveIClass(resp) == 8) { - // //Save CC (e-purse) in response data - // memcpy(card_data+8, resp, 8); - // read_status++; - // } - - //Success - level 1, we got CSN //Save CSN in response data memcpy(card_data, resp, 8); - bool isBlk_2 = sendCmdGetResponseWithRetries(readcheck_cc, sizeof(readcheck_cc), resp, 8, 3); - - //Flag that we got to at least stage 1, read CSN - if (isBlk_2 == false) { - return 1; - } + // card selected, now read config (block1) (only 8 bytes no CRC) + start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + ReaderTransmitIClass(read_conf, sizeof(read_conf), &start_time); + + // expect a 8-byte response here + len = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time); + if (len != 8) + return false; //Save CC (e-purse) in response data memcpy(card_data + 8, resp, 8); - // we got all data; - return 2; -} -static uint8_t handshakeIclassTag(uint8_t *card_data) { - return handshakeIclassTag_ext(card_data, false); + // card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) + start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc), &start_time); + + // expect a 8-byte response here + len = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time); + if (len != 8) + return false; + + //Save CC (e-purse) in response data + memcpy(card_data + 16, resp, 8); + return true; } // Reader iClass Anticollission @@ -2015,129 +873,70 @@ void ReaderIClass(uint8_t arg0) { memset(card_data, 0xFF, sizeof(card_data)); memset(resp, 0xFF, sizeof(resp)); - //Read conf block CRC(0x01) => 0xfa 0x22 - uint8_t readConf[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22}; - - //Read App Issuer Area block CRC(0x05) => 0xde 0x64 - uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64}; - - uint16_t tryCnt = 0; - bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; // flag to read until one tag is found successfully bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY; // flag to not to loop continuously, looking for tag bool use_credit_key = arg0 & FLAG_ICLASS_READER_CEDITKEY; // flag to use credit key - bool flagReadConfig = arg0 & FLAG_ICLASS_READER_CONF; // flag to read block1, configuration - bool flagReadCC = arg0 & FLAG_ICLASS_READER_CC; // flag to read block2, e-purse bool flagReadAIA = arg0 & FLAG_ICLASS_READER_AIA; // flag to read block5, application issuer area - setupIclassReader(); + if (flags & FLAG_ICLASS_READER_INIT) { + Iso15693InitReader(); + } - uint16_t checked = 0; - bool userCancelled = BUTTON_PRESS() || data_available(); - while (!userCancelled) { + if (flags & FLAG_ICLASS_READER_CLEARTRACE) { + set_tracing(true); + clear_trace(); + StartCountSspClk(); + } - WDT_HIT(); + uint32_t start_time = 0; + uint32_t eof_time = 0; - // if only looking for one card try 2 times if we missed it the first time - if (try_once && tryCnt > 10) { - if (DBGLEVEL > 1) DbpString("Failed to find a tag"); - break; + int read_status = selectIclassTag(card_data, use_credit_key, &eof_time); + if (read_status == 0) { + reply_mix(CMD_ACK, 0xFF, 0, 0, card_data, 0); + switch_off(); + return; + } + + uint8_t result_status = FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_CC; + + //Read block 5, AIA + if (flagReadAIA) { + //Read App Issuer Area block CRC(0x05) => 0xde 0x64 + uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64}; + + if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, sizeof(resp), 10, 10, start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time)) { + result_status |= FLAG_ICLASS_READER_AIA; + memcpy(card_data + (8 * 5), resp, 8); + } else { + if (DBGLEVEL >= DBG_EXTENDED) DbpString("Failed to dump AA block"); } + } - tryCnt++; - uint8_t result_status = 0; + // 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. - int read_status = handshakeIclassTag_ext(card_data, use_credit_key); + LED_B_ON(); - 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; - - // 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, 10, 5)) { - result_status |= FLAG_ICLASS_READER_CONF; - memcpy(card_data + 8, resp, 8); - } else { - if (DBGLEVEL > 1) DbpString("Failed to dump config block"); - } - } - - //Read block 5, AIA - if (flagReadAIA) { - if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, 10, 5)) { - result_status |= FLAG_ICLASS_READER_AIA; - memcpy(card_data + (8 * 5), resp, 8); - } else { - if (DBGLEVEL > 1) DbpString("Failed to dump AA block"); - } - } - - // 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 (DBGLEVEL >= DBG_EXTENDED) { - Dbprintf("STATUS %02X | CSN %c | CONF %c | CC %c | AIA %c | ONCE %c | 1TRY %c", - result_status, - (result_status & FLAG_ICLASS_READER_CSN) ? 'Y' : 'N', - (result_status & FLAG_ICLASS_READER_CONF) ? 'Y' : 'N', - (result_status & FLAG_ICLASS_READER_CC) ? 'Y' : 'N', - (result_status & FLAG_ICLASS_READER_AIA) ? 'Y' : 'N' - ); - Dbprintf(" aar %c | to %c, | uc %c | frc %c | fra %c | cc %c", - abort_after_read ? 'Y' : 'N', - try_once ? 'Y' : 'N', - use_credit_key ? 'Y' : 'N', - flagReadConfig ? 'Y' : 'N', - flagReadAIA ? 'Y' : 'N', - flagReadCC ? 'Y' : 'N' - ); - } - - bool send = (result_status & FLAG_ICLASS_READER_CSN); - if (flagReadCC) - send |= (result_status & FLAG_ICLASS_READER_CC); - if (flagReadAIA) - send |= (result_status & FLAG_ICLASS_READER_AIA); - if (flagReadConfig) - send |= (result_status & FLAG_ICLASS_READER_CONF); - - if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("SEND %c", send ? 'y' : 'n'); - - if (send) { - reply_mix(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data)); - if (abort_after_read) { - LED_B_OFF(); - return; - } - //Save that we already sent this.... - memcpy(last_csn, card_data, 8); + //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 (send) { + reply_mix(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data)); + if (abort_after_read) { + LED_B_OFF(); + return; } } LED_B_OFF(); - - if (checked == 1000) { - userCancelled = BUTTON_PRESS() || data_available(); - checked = 0; - } - ++checked; } if (userCancelled) { @@ -2272,8 +1071,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac) { void iClass_ReadCheck(uint8_t blockno, uint8_t keytype) { uint8_t readcheck[] = { keytype, blockno }; uint8_t resp[] = {0, 0, 0, 0, 0, 0, 0, 0}; - size_t isOK = 0; - isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 6); + bool isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 8, 3, 0, ICLASS_READER_TIMEOUT_OTHERS, &eof_time); reply_mix(CMD_ACK, isOK, 0, 0, 0, 0); switch_off(); } @@ -2399,13 +1197,13 @@ out: // Tries to read block. // retries 10times. -bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len) { +static bool iClass_ReadBlock(uint8_t blockno, uint8_t *data) { uint8_t resp[10]; uint8_t cmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockno, 0x00, 0x00}; AddCrc(cmd + 1, 1); - // expect size 10, retry 5times - bool isOK = sendCmdGetResponseWithRetries(cmd, sizeof(cmd), resp, 10, 5); - memcpy(data, resp, len); + uint32_t eof_time; + bool isOK = sendCmdGetResponseWithRetries(readcmd, sizeof(readcmd), resp, sizeof(resp), 10, 10, 0, ICLASS_READER_TIMEOUT_OTHERS, &eof_time); + memcpy(data, resp, 8); return isOK; } @@ -2417,33 +1215,32 @@ void iClass_ReadBlk(uint8_t blockno) { uint8_t blockdata[8]; } PACKED result; - result.isOK = iClass_ReadBlock(blockno, result.blockdata, sizeof(result.blockdata)); + LED_A_ON(); + result.isOK = iClass_ReadBlock(blockno, result.blockdata); switch_off(); reply_ng(CMD_HF_ICLASS_READBL, PM3_SUCCESS, (uint8_t *)&result, sizeof(result)); } // turn off afterwards void iClass_Dump(uint8_t blockno, uint8_t numblks) { - uint8_t blockdata[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - bool isOK = false; - uint8_t blkCnt = 0; - BigBuf_free(); - uint8_t *dataout = BigBuf_malloc(255 * 8); + uint8_t *dataout = BigBuf_malloc(0xFF * 8); if (dataout == NULL) { DbpString("[!] fail to allocate memory"); OnError(1); return; } - // fill mem with 0xFF - memset(dataout, 0xFF, 255 * 8); + memset(dataout, 0xFF, 0xFF * 8); + uint8_t blockdata[8] = {0}; + uint8_t blkCnt = 0; + bool isOK; for (; blkCnt < numblks; blkCnt++) { - isOK = iClass_ReadBlock(blockno + blkCnt, blockdata, sizeof(blockdata)); + isOK = iClass_ReadBlock(blockno + blkCnt, blockdata); // 0xBB is the internal debug separator byte.. if (!isOK || (blockdata[0] == 0xBB || blockdata[7] == 0xBB || blockdata[2] == 0xBB)) { //try again - isOK = iClass_ReadBlock(blockno + blkCnt, blockdata, sizeof(blockdata)); + isOK = iClass_ReadBlock(blockno + blkCnt, blockdata); if (!isOK) { Dbprintf("[!] block %02X failed to read", blkCnt + blockno); break; @@ -2459,15 +1256,42 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks) { } static 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[] = { 0x80 | 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); - return sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); + + uint8_t resp[10] = {0}; + uint32_t eof_time = 0; + bool isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 10, 3, 0, ICLASS_READER_TIMEOUT_UPDATE, &eof_time); + if (isOK == false) { + return false; + } + + uint8_t all_ff[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + if (blockNo == 2) { + // check response. e-purse update swaps first and second half + if (memcmp(data+4, resp, 4) || memcmp(data, resp+4, 4)) { + return false; + } + } else if (blockNo == 3 || blockNo == 4) { + // check response. Key updates always return 0xffffffffffffffff + if (memcmp(all_ff, resp, 8)) { + return false; + } + } else { + // check response. All other updates return unchanged data + if (memcmp(data, resp, 8)) { + return false; + } + } + + return true; } // turn off afterwards void iClass_WriteBlock(uint8_t blockno, uint8_t *data) { + LED_A_ON(); uint8_t isOK = iClass_WriteBlock_ext(blockno, data); switch_off(); reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t *)&isOK, sizeof(uint8_t)); @@ -2475,23 +1299,20 @@ void iClass_WriteBlock(uint8_t blockno, uint8_t *data) { // turn off afterwards void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) { - int i, written = 0; - int total_block = (endblock - startblock) + 1; - for (i = 0; i < total_block; i++) { - // block number - if (iClass_WriteBlock_ext(startblock + i, data + (i * 12))) { - Dbprintf("Write block [%02x] successful", startblock + i); + LED_A_ON(); + uint16_t written = 0; + uint16_t total_blocks = (endblock - startblock) + 1; + for (uint8_t b = startblock; b < total_blocks; b++) { + + if (iClass_WriteBlock_ext(b, data + ((b - startblock) * 12))) { + Dbprintf("Write block [%02x] successful", b); written++; } else { - Dbprintf("Write block [%02x] failed", startblock + i); + Dbprintf("Write block [%02x] failed", b); } } switch_off(); - - uint8_t isOK = 0; - if (written == total_block) - isOK = 1; - + uint8_t isOK = (written == total_blocks) ? 1 : 0; reply_ng(CMD_HF_ICLASS_CLONE, PM3_SUCCESS, (uint8_t *)&isOK, sizeof(uint8_t)); } diff --git a/armsrc/iclass.h b/armsrc/iclass.h index a9edbdfed..6ce23ceb7 100644 --- a/armsrc/iclass.h +++ b/armsrc/iclass.h @@ -13,7 +13,7 @@ #include "common.h" -void RAMFUNC SniffIClass(void); +void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string); void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void ReaderIClass(uint8_t arg0); void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac); @@ -21,7 +21,6 @@ void iClass_Authentication(uint8_t *mac); void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain); void iClass_WriteBlock(uint8_t blockno, uint8_t *data); void iClass_ReadBlk(uint8_t blockno); -bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len); void iClass_Dump(uint8_t blockno, uint8_t numblks); void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data); void iClass_ReadCheck(uint8_t blockno, uint8_t keytype); diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 4999c4d85..4448d3570 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -1,5 +1,6 @@ //----------------------------------------------------------------------------- // Jonathan Westhues, split Nov 2006 +// piwi 2018 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -24,20 +25,19 @@ #include "dbprint.h" #include "ticks.h" -#ifndef FWT_TIMEOUT_14B -// defaults to 2000ms -# define FWT_TIMEOUT_14B 35312 -#endif + #ifndef ISO14443B_DMA_BUFFER_SIZE -# define ISO14443B_DMA_BUFFER_SIZE 512 //changed this from 256 +# define ISO14443B_DMA_BUFFER_SIZE 128 #endif #ifndef RECEIVE_MASK # define RECEIVE_MASK (ISO14443B_DMA_BUFFER_SIZE-1) #endif +#define RECEIVE_SAMPLES_TIMEOUT 64 + // Guard Time (per 14443-2) #ifndef TR0 -# define TR0 32 //this value equals 8 ETU = 32 ssp clk (w/ 424 khz) +# define TR0 64 // TR0 max is 256/fs = 256/(848kHz) = 302us or 64 samples from FPGA #endif // Synchronization time (per 14443-2) @@ -51,30 +51,161 @@ // 4sample #define SEND4STUFFBIT(x) ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x); -//#define SEND4STUFFBIT(x) ToSendStuffBit(x); -// iceman, this threshold value, what makes 8 a good amplitude for this IQ values? -#ifndef SUBCARRIER_DETECT_THRESHOLD -# define SUBCARRIER_DETECT_THRESHOLD 8 -#endif static void iso14b_set_timeout(uint32_t timeout); static void iso14b_set_maxframesize(uint16_t size); // the block number for the ISO14443-4 PCB (used with APDUs) static uint8_t pcb_blocknum = 0; -static uint32_t iso14b_timeout = FWT_TIMEOUT_14B; +static uint32_t iso14b_timeout = TR0; + + +/* ISO 14443 B +* +* Reader to card | ASK - Amplitude Shift Keying Modulation (PCD to PICC for Type B) (NRZ-L encodig) +* Card to reader | BPSK - Binary Phase Shift Keying Modulation, (PICC to PCD for Type B) +* +* fc - carrier frequency 13.56 MHz +* TR0 - Guard Time per 14443-2 +* TR1 - Synchronization Time per 14443-2 +* TR2 - PICC to PCD Frame Delay Time (per 14443-3 Amendment 1) +* +* Elementary Time Unit (ETU) is +* - 128 Carrier Cycles (9.4395 µS) = 8 Subcarrier Units +* - 1 ETU = 1 bit +* - 10 ETU = 1 startbit, 8 databits, 1 stopbit (10bits length) +* - startbit is a 0 +* - stopbit is a 1 +* +* Start of frame (SOF) is +* - [10-11] ETU of ZEROS, unmodulated time +* - [2-3] ETU of ONES, +* +* End of frame (EOF) is +* - [10-11] ETU of ZEROS, unmodulated time +* +* -TO VERIFY THIS BELOW- +* The mode FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK which we use to simulate tag +* works like this: +* - A 1-bit input to the FPGA becomes 8 pulses at 847.5kHz (1.18µS / pulse) == 9.44us +* - A 0-bit input to the FPGA becomes an unmodulated time of 1.18µS or does it become 8 nonpulses for 9.44us +* +* FPGA doesn't seem to work with ETU. It seems to work with pulse / duration instead. +* +* Card sends data ub 847.e kHz subcarrier +* subcar |duration| FC division +* -------+--------+------------ +* 106kHz | 9.44µS | FC/128 +* 212kHz | 4.72µS | FC/64 +* 424kHz | 2.36µS | FC/32 +* 848kHz | 1.18µS | FC/16 +* -------+--------+------------ +* +* Reader data transmission: +* - no modulation ONES +* - SOF +* - Command, data and CRC_B +* - EOF +* - no modulation ONES +* +* Card data transmission +* - TR1 +* - SOF +* - data (each bytes is: 1startbit, 8bits, 1stopbit) +* - CRC_B +* - EOF +* +* FPGA implementation : +* At this point only Type A is implemented. This means that we are using a +* bit rate of 106 kbit/s, or fc/128. Oversample by 4, which ought to make +* things practical for the ARM (fc/32, 423.8 kbits/s, ~50 kbytes/s) +* +*/ + + //============================================================================= // An ISO 14443 Type B tag. We listen for commands from the reader, using -// a kind of thing that's implemented in software. When we get a +// a UART kind of thing that's implemented in software. When we get a // frame (i.e., a group of bytes between SOF and EOF), we check the CRC. // If it's good, then we can do something appropriate with it, and send // a response. //============================================================================= +//----------------------------------------------------------------------------- +// Code up a string of octets at layer 2 (including CRC, we don't generate +// that here) so that they can be transmitted to the reader. Doesn't transmit +// them yet, just leaves them ready to send in ToSend[]. +//----------------------------------------------------------------------------- +static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { + int i; + + ToSendReset(); + + // Transmit a burst of ones, as the initial thing that lets the + // reader get phase sync. + // This loop is TR1, per specification + // TR1 minimum must be > 80/fs + // TR1 maximum 200/fs + // 80/fs < TR1 < 200/fs + // 10 ETU < TR1 < 24 ETU + + // Send TR1. + // 10-11 ETU * 4times samples ONES + for (i = 0; i < 20; i++) { + SEND4STUFFBIT(1); + } + + // Send SOF. + // 10-11 ETU * 4times samples ZEROS + for (i = 0; i < 10; i++) { + SEND4STUFFBIT(0); + } + + // 2-3 ETU * 4times samples ONES + for (i = 0; i < 2; i++) { + SEND4STUFFBIT(1); + } + + // data + for (i = 0; i < len; i++) { + + // Start bit + SEND4STUFFBIT(0); + + // Data bits + uint8_t b = cmd[i]; + for (int j = 0; j < 8; j++) { + SEND4STUFFBIT(b & 1); + b >>= 1; + } + + // Stop bit + SEND4STUFFBIT(1); + + // Extra Guard bit + // For PICC it ranges 0-18us (1etu = 9us) + //SEND4STUFFBIT(1); + } + + // Send EOF. + // 10-11 ETU * 4 sample rate = ZEROS + for(i = 0; i < 10; i++) { + SEND4STUFFBIT(0); + } + + // why this? + for(i = 0; i < 2; i++) { + SEND4STUFFBIT(1); + } + + // Convert from last byte pos to length + ToSendMax++; +} //----------------------------------------------------------------------------- -// The software that receives commands from the reader, and its state variables. +// The software UART that receives commands from the reader, and its state +// variables. //----------------------------------------------------------------------------- static struct { enum { @@ -103,7 +234,6 @@ static void Uart14bReset(void) { static void Uart14bInit(uint8_t *data) { Uart.output = data; Uart14bReset(); -// memset(Uart.output, 0x00, MAX_FRAME_SIZE); } //----------------------------------------------------------------------------- @@ -121,10 +251,6 @@ static struct { uint16_t bitCount; int posCount; int thisBit; - /* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented. - int metric; - int metricN; - */ uint16_t shiftReg; uint8_t *output; uint16_t len; @@ -150,7 +276,6 @@ static void Demod14bReset(void) { static void Demod14bInit(uint8_t *data) { Demod.output = data; Demod14bReset(); - // memset(Demod.output, 0x00, MAX_FRAME_SIZE); } @@ -175,6 +300,7 @@ static void iso14b_set_timeout(uint32_t timeout) { iso14b_timeout = timeout; if (DBGLEVEL >= 3) Dbprintf("ISO14443B Timeout set to %ld fwt", iso14b_timeout); } + static void iso14b_set_maxframesize(uint16_t size) { if (size > 256) size = MAX_FRAME_SIZE; @@ -183,142 +309,6 @@ static void iso14b_set_maxframesize(uint16_t size) { if (DBGLEVEL >= 3) Dbprintf("ISO14443B Max frame size set to %d bytes", Uart.byteCntMax); } -//----------------------------------------------------------------------------- -// Code up a string of octets at layer 2 (including CRC, we don't generate -// that here) so that they can be transmitted to the reader. Doesn't transmit -// them yet, just leaves them ready to send in ToSend[]. -//----------------------------------------------------------------------------- -static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { - /* ISO 14443 B - * - * Reader to card | ASK - Amplitude Shift Keying Modulation (PCD to PICC for Type B) (NRZ-L encodig) - * Card to reader | BPSK - Binary Phase Shift Keying Modulation, (PICC to PCD for Type B) - * - * fc - carrier frequency 13.56 MHz - * TR0 - Guard Time per 14443-2 - * TR1 - Synchronization Time per 14443-2 - * TR2 - PICC to PCD Frame Delay Time (per 14443-3 Amendment 1) - * - * Elementary Time Unit (ETU) is - * - 128 Carrier Cycles (9.4395 µS) = 8 Subcarrier Units - * - 1 ETU = 1 bit - * - 10 ETU = 1 startbit, 8 databits, 1 stopbit (10bits length) - * - startbit is a 0 - * - stopbit is a 1 - * - * Start of frame (SOF) is - * - [10-11] ETU of ZEROS, unmodulated time - * - [2-3] ETU of ONES, - * - * End of frame (EOF) is - * - [10-11] ETU of ZEROS, unmodulated time - * - * -TO VERIFY THIS BELOW- - * The mode FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK which we use to simulate tag - * works like this: - * - A 1-bit input to the FPGA becomes 8 pulses at 847.5kHz (1.18µS / pulse) == 9.44us - * - A 0-bit input to the FPGA becomes an unmodulated time of 1.18µS or does it become 8 nonpulses for 9.44us - * - * FPGA doesn't seem to work with ETU. It seems to work with pulse / duration instead. - * - * Card sends data ub 847.e kHz subcarrier - * subcar |duration| FC division - * -------+--------+------------ - * 106kHz | 9.44µS | FC/128 - * 212kHz | 4.72µS | FC/64 - * 424kHz | 2.36µS | FC/32 - * 848kHz | 1.18µS | FC/16 - * -------+--------+------------ - * - * Reader data transmission: - * - no modulation ONES - * - SOF - * - Command, data and CRC_B - * - EOF - * - no modulation ONES - * - * Card data transmission - * - TR1 - * - SOF - * - data (each bytes is: 1startbit, 8bits, 1stopbit) - * - CRC_B - * - EOF - * - * FPGA implementation : - * At this point only Type A is implemented. This means that we are using a - * bit rate of 106 kbit/s, or fc/128. Oversample by 4, which ought to make - * things practical for the ARM (fc/32, 423.8 kbits/s, ~50 kbytes/s) - * - */ - - ToSendReset(); - - // Transmit a burst of ones, as the initial thing that lets the - // reader get phase sync. - // This loop is TR1, per specification - // TR1 minimum must be > 80/fs - // TR1 maximum 200/fs - // 80/fs < TR1 < 200/fs - // 10 ETU < TR1 < 24 ETU - - // Send TR1. - // 10-11 ETU * 4times samples ONES - for (int i = 0; i < 10; i++) { SEND4STUFFBIT(1); } - - // Send SOF. - // 10-11 ETU * 4times samples ZEROS - for (int i = 0; i < 10; i++) { SEND4STUFFBIT(0); } - //for(i = 0; i < 10; i++) { ToSendStuffBit(0); } - - // 2-3 ETU * 4times samples ONES - for (int i = 0; i < 3; i++) { SEND4STUFFBIT(1); } - //for(i = 0; i < 3; i++) { ToSendStuffBit(1); } - - // data - for (int i = 0; i < len; ++i) { - - // Start bit - SEND4STUFFBIT(0); - //ToSendStuffBit(0); - - // Data bits - uint8_t b = cmd[i]; - for (int j = 0; j < 8; ++j) { - // if(b & 1) { - // SEND4STUFFBIT(1); - // //ToSendStuffBit(1); - // } else { - // SEND4STUFFBIT(0); - // //ToSendStuffBit(0); - // } - SEND4STUFFBIT(b & 1); - b >>= 1; - } - - // Stop bit - SEND4STUFFBIT(1); - //ToSendStuffBit(1); - - // Extra Guard bit - // For PICC it ranges 0-18us (1etu = 9us) - SEND4STUFFBIT(1); - //ToSendStuffBit(1); - } - - // Send EOF. - // 10-11 ETU * 4 sample rate = ZEROS - for (int i = 0; i < 10; i++) { SEND4STUFFBIT(0); } - //for(i = 0; i < 10; i++) { ToSendStuffBit(0); } - - // why this? - for (int i = 0; i < 2; i++) { SEND4STUFFBIT(1); } - //for(i = 0; i < 40; i++) { ToSendStuffBit(1); } - - // Convert from last byte pos to length - ++ToSendMax; -} - - /* Receive & handle a bit coming from the reader. * * This function is called 4 times per bit (every 2 subcarrier cycles). @@ -454,42 +444,16 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) { LED_D_OFF(); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION); - StartCountSspClk(); - - volatile uint8_t b; - - // clear receiving shift register and holding register - // What does this loop do? Is it TR1? - // loop is a wait/delay ? - /* - for(uint8_t c = 0; c < 10;) { - - // keep tx buffer in a defined state anyway. - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0xFF; - ++c; - } - } - */ // Now run a `software UART' on the stream of incoming samples. Uart14bInit(received); - uint8_t mask; - while (!BUTTON_PRESS()) { + while (BUTTON_PRESS() == false) { WDT_HIT(); - // keep tx buffer in a defined state anyway. - 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) { - - b = (uint8_t) AT91C_BASE_SSC->SSC_RHR; - - for (mask = 0x80; mask != 0; mask >>= 1) { - if (Handle14443bReaderUartBit(b & mask)) { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + for (uint8_t mask = 0x80; mask != 0x00; mask >>= 1) { + if (Handle14443bReaderUartBit(b & mask)) { *len = Uart.byteCnt; return true; } @@ -499,57 +463,16 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) { return false; } -void ClearFpgaShiftingRegisters(void) { - - volatile uint8_t b; - - // clear receiving shift register and holding register - while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {}; - - b = AT91C_BASE_SSC->SSC_RHR; - (void) b; - - while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {}; - - b = AT91C_BASE_SSC->SSC_RHR; - (void) b; - - // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line) - for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never - while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {}; - if (AT91C_BASE_SSC->SSC_RHR) break; - } - - // Clear TXRDY: - //AT91C_BASE_SSC->SSC_THR = 0xFF; -} - -void WaitForFpgaDelayQueueIsEmpty(uint16_t delay) { - // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again: - uint8_t fpga_queued_bits = delay >> 3; // twich /8 ?? >>3, - for (uint8_t i = 0; i <= fpga_queued_bits / 8 + 1;) { - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0xFF; - i++; - } - } -} static void TransmitFor14443b_AsTag(uint8_t *response, uint16_t len) { - volatile uint32_t b; - // Signal field is off with the appropriate LED LED_D_OFF(); - //uint16_t fpgasendQueueDelay = 0; // Modulate BPSK FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK); - SpinDelay(40); - - ClearFpgaShiftingRegisters(); - - FpgaSetupSsc(); + AT91C_BASE_SSC->SSC_THR = 0xFF; + FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR); // Transmit the response. for (uint16_t i = 0; i < len;) { @@ -561,13 +484,10 @@ static void TransmitFor14443b_AsTag(uint8_t *response, uint16_t len) { // Prevent rx holding register from overflowing if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - b = AT91C_BASE_SSC->SSC_RHR; + volatile uint32_t b = AT91C_BASE_SSC->SSC_RHR; (void)b; } } - - //WaitForFpgaDelayQueueIsEmpty(fpgasendQueueDelay); - AT91C_BASE_SSC->SSC_THR = 0xFF; } //----------------------------------------------------------------------------- // Main loop of simulated tag: receive commands from reader, decide what @@ -575,41 +495,26 @@ static void TransmitFor14443b_AsTag(uint8_t *response, uint16_t len) { //----------------------------------------------------------------------------- void SimulateIso14443bTag(uint32_t pupi) { - // setup device. - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - // connect Demodulated Signal to ADC: - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - // Set up the synchronous serial port - FpgaSetupSsc(); - - // allocate command receive buffer - BigBuf_free(); - BigBuf_Clear_ext(false); - - clear_trace(); //sim - set_tracing(true); - - uint16_t len, cmdsReceived = 0; - int cardSTATE = SIM_NOFIELD; - int vHf = 0; // in mV - // uint32_t time_0 = 0; - // uint32_t t2r_time = 0; - // uint32_t r2t_time = 0; - uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); - - // the only commands we understand is WUPB, AFI=0, Select All, N=1: -// static const uint8_t cmdWUPB[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 }; // WUPB - // ... and REQB, AFI=0, Normal Request, N=1: -// static const uint8_t cmdREQB[] = { ISO14443B_REQB, 0x00, 0x00, 0x71, 0xFF }; // REQB - // ... and ATTRIB -// static const uint8_t cmdATTRIB[] = { ISO14443B_ATTRIB, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // ATTRIB + LED_A_ON(); + // the only commands we understand is WUPB, AFI=0, Select All, N=1: +// static const uint8_t cmdWUPB[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 }; // WUPB + // ... and REQB, AFI=0, Normal Request, N=1: +// static const uint8_t cmdREQB[] = { ISO14443B_REQB, 0x00, 0x00, 0x71, 0xFF }; // REQB + // ... and HLTB +// static const uint8_t cmdHLTB[] = { 0x50, 0xff, 0xff, 0xff, 0xff }; // HLTB + // ... and ATTRIB +// static const uint8_t cmdATTRIB[] = { ISO14443B_ATTRIB, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // ATTRIB // ... if not PUPI/UID is supplied we always respond with ATQB, PUPI = 820de174, Application Data = 0x20381922, // supports only 106kBit/s in both directions, max frame size = 32Bytes, // supports ISO14443-4, FWI=8 (77ms), NAD supported, CID not supported: - uint8_t respATQB[] = { 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, - 0x22, 0x00, 0x21, 0x85, 0x5e, 0xd7 - }; + uint8_t respATQB[] = { + 0x50, + 0x82, 0x0d, 0xe1, 0x74, + 0x20, 0x38, 0x19, + 0x22, 0x00, 0x21, 0x85, + 0x5e, 0xd7 + }; // response to HLTB and ATTRIB static const uint8_t respOK[] = {0x00, 0x78, 0xF0}; @@ -619,6 +524,26 @@ void SimulateIso14443bTag(uint32_t pupi) { num_to_bytes(pupi, 4, respATQB + 1); AddCrc14B(respATQB, 12); } + + // setup device. + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + + // Set up the synchronous serial port + FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR); + + // allocate command receive buffer + BigBuf_free(); + BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); + + uint16_t len, cmdsReceived = 0; + int cardSTATE = SIM_NOFIELD; + int vHf = 0; // in mV + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); // prepare "ATQB" tag answer (encoded): CodeIso14443bAsTag(respATQB, sizeof(respATQB)); @@ -663,7 +588,7 @@ void SimulateIso14443bTag(uint32_t pupi) { // WUP in HALTED state if (len == 5) { if ((receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8) == 0x8 && cardSTATE == SIM_HALTED) || - receivedCmd[0] == ISO14443B_REQB) { + receivedCmd[0] == ISO14443B_REQB) { LogTrace(receivedCmd, len, 0, 0, NULL, true); cardSTATE = SIM_SELECTING; } @@ -714,15 +639,21 @@ void SimulateIso14443bTag(uint32_t pupi) { // - SLOT MARKER // - ISO7816 // - emulate with a memory dump - Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsReceived); + if (DBGLEVEL >= DBG_DEBUG) + Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsReceived); // CRC Check if (len >= 3) { // if crc exists - if (!check_crc(CRC_14443_B, receivedCmd, len)) - DbpString("+++CRC fail"); - else - DbpString("CRC passes"); + if (!check_crc(CRC_14443_B, receivedCmd, len)) { + if (DBGLEVEL >= DBG_DEBUG) { + DbpString("CRC fail"); + } + } + } else { + if (DBGLEVEL >= DBG_DEBUG) { + DbpString("CRC passed"); + } } cardSTATE = SIM_IDLE; } @@ -734,9 +665,11 @@ void SimulateIso14443bTag(uint32_t pupi) { ++cmdsReceived; } - if (DBGLEVEL >= 2) + + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); - switch_off(); //simulate + + switch_off(); //simulate } //============================================================================= @@ -780,37 +713,8 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { // Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by abs(ci) + abs(cq) // Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq))) -#define CHECK_FOR_SUBCARRIER_old(void) { \ - if (ci < 0) { \ - if (cq < 0) { /* ci < 0, cq < 0 */ \ - if (cq < ci) { \ - v = -cq - (ci >> 1); \ - } else { \ - v = -ci - (cq >> 1); \ - } \ - } else { /* ci < 0, cq >= 0 */ \ - if (cq < -ci) { \ - v = -ci + (cq >> 1); \ - } else { \ - v = cq - (ci >> 1); \ - } \ - } \ - } else { \ - if (cq < 0) { /* ci >= 0, cq < 0 */ \ - if (-cq < ci) { \ - v = ci - (cq >> 1); \ - } else { \ - v = -cq + (ci >> 1); \ - } \ - } else { /* ci >= 0, cq >= 0 */ \ - if (cq < ci) { \ - v = ci + (cq >> 1); \ - } else { \ - v = cq + (ci >> 1); \ - } \ - } \ - } \ - } + +#define SUBCARRIER_DETECT_THRESHOLD 8 //note: couldn't we just use MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2) from common.h - marshmellow #define CHECK_FOR_SUBCARRIER(void) { v = MAX(myI, myQ) + (MIN(myI, myQ) >> 1); } @@ -859,7 +763,9 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { Demod.posCount = 0; // start of SOF sequence } else { // maximum length of TR1 = 200 1/fs - if (Demod.posCount > 200 / 4) Demod.state = DEMOD_UNSYNCD; + if (Demod.posCount > 200 / 4){ + Demod.state = DEMOD_UNSYNCD; + } } Demod.posCount++; break; @@ -877,6 +783,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { LED_C_ON(); // Got SOF Demod.state = DEMOD_AWAITING_START_BIT; Demod.posCount = 0; + Demod.bitCount = 0; Demod.len = 0; } } else { @@ -895,8 +802,12 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { if (v > 0) { if (Demod.posCount > 6 * 2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs - Demod.state = DEMOD_UNSYNCD; - LED_C_OFF(); + LED_C_OFF(); + if (Demod.bitCount == 0 && Demod.len == 0) { // received SOF only, this is valid for iClass/Picopass + return true; + } else { + Demod.state = DEMOD_UNSYNCD; + } } } else { // start bit detected Demod.bitCount = 0; @@ -932,11 +843,12 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { uint16_t s = Demod.shiftReg; // stop bit == '1', start bit == '0' - if ((s & 0x200) && (s & 0x001) == 0) { + if ((s & 0x200) && ((s & 0x001) == 0)) { // left shift to drop the startbit uint8_t b = (s >> 1); Demod.output[Demod.len] = b; - ++Demod.len; + Demod.len++; + Demod.bitCount = 0; Demod.state = DEMOD_AWAITING_START_BIT; } else { // this one is a bit hard, either its a correc byte or its unsynced. @@ -964,99 +876,114 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { * Demodulate the samples we received from the tag, also log to tracebuffer * quiet: set to 'TRUE' to disable debug output */ -static void GetTagSamplesFor14443bDemod(void) { - bool finished = false; -// int lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; +static int GetTagSamplesFor14443bDemod(int timeout) { + int ret = 0; + int maxBehindBy = 0; + int lastRxCounter, samples = 0; + int8_t ci, cq; uint32_t time_0 = 0, time_stop = 0; BigBuf_free(); + // The response (tag -> reader) that we're receiving. + uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE); + + // The DMA buffer, used to stream samples from the FPGA + uint16_t *dmaBuf = (uint16_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE * sizeof(uint16_t)); // Set up the demodulator for tag -> reader responses. - Demod14bInit(BigBuf_malloc(MAX_FRAME_SIZE)); + Demod14bInit(receivedResponse); - // The DMA buffer, used to stream samples from the FPGA - int8_t *dmaBuf = (int8_t *) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); - int8_t *upTo = dmaBuf; + // wait for last transfer to complete + while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY)) // Setup and start DMA. - if (!FpgaSetupSscDma((uint8_t *) dmaBuf, ISO14443B_DMA_BUFFER_SIZE)) { + FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER); + if (FpgaSetupSscDma((uint8_t *) dmaBuf, ISO14443B_DMA_BUFFER_SIZE) == false) { if (DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); - return; + return -1; } + uint16_t *upTo = dmaBuf; + lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; + + // Signal field is ON with the appropriate LED: + LED_D_ON(); // And put the FPGA in the appropriate mode - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_848_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ); - // get current clock - time_0 = GetCountSspClk(); + for(;;) { + int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & (ISO14443B_DMA_BUFFER_SIZE-1); + if (behindBy > maxBehindBy) { + maxBehindBy = behindBy; + } - // rx counter - dma counter? (how much?) & (mod) mask > 2. (since 2bytes at the time is read) - while (!finished) { + if (behindBy < 1) continue; - LED_A_INV(); - WDT_HIT(); + ci = *upTo >> 8; + cq = *upTo; + upTo++; + lastRxCounter--; + if (upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { // we have read all of the DMA buffer content. + upTo = dmaBuf; // start reading the circular buffer from the beginning + lastRxCounter += ISO14443B_DMA_BUFFER_SIZE; + } - // LSB is a fpga signal bit. - int ci = upTo[0]; - int cq = upTo[1]; - upTo += 2; -// lastRxCounter -= 2; + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX)) { // DMA Counter Register had reached 0, already rotated. + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; // refresh the DMA Next Buffer and + AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; // DMA Next Counter registers + } + samples++; - // restart DMA buffer to receive again. - if (upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { - upTo = dmaBuf; -// lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; - AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo; - AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; - } + if (Handle14443bTagSamplesDemod(ci, cq)) { + ret = Demod.len; + break; + } - // https://github.com/Proxmark/proxmark3/issues/103 - bool gotFrame = Handle14443bTagSamplesDemod(ci, cq); - time_stop = GetCountSspClk() - time_0; - - finished = (time_stop > iso14b_timeout || gotFrame); + if(samples > timeout && Demod.state < DEMOD_PHASE_REF_TRAINING) { + ret = -1; + LED_C_OFF(); + break; + } } FpgaDisableSscDma(); - if (upTo) - upTo = NULL; + if (ret < 0) { + return ret; + } - if (Demod.len > 0) - LogTrace(Demod.output, Demod.len, time_0, time_stop, NULL, false); + if (Demod.len > 0) { + LogTrace(Demod.output, Demod.len, time_0, time_stop, NULL, false); + } + + return ret; } //----------------------------------------------------------------------------- // Transmit the command (to the tag) that was placed in ToSend[]. //----------------------------------------------------------------------------- static void TransmitFor14443b_AsReader(void) { - int c; - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); - SpinDelay(60); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD); - // What does this loop do? Is it TR1? - // 0xFF = 8 bits of 1. 1 bit == 1Etu,.. - // loop 10 * 8 = 80 ETU of delay, with a non modulated signal. why? - // 80*9 = 720us. + LED_B_ON(); - for (c = 0; c < 50;) { + for (int c = 0; c < ToSendMax; c++) { + uint8_t data = ToSend[c]; + for (int i = 0; i < 8; i++) { + uint16_t send_word = (data & 0x80) ? 0x0000 : 0xffff; + + while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) ; + + AT91C_BASE_SSC->SSC_THR = send_word; + while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) ; + AT91C_BASE_SSC->SSC_THR = send_word; - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0xFF; - c++; - } + data <<= 1; + } + WDT_HIT(); } - - // Send frame loop - for (c = 0; c < ToSendMax;) { - - // Put byte into tx holding register as soon as it is ready - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = ToSend[c++]; - } - } - WDT_HIT(); + LED_B_OFF(); } //----------------------------------------------------------------------------- @@ -1083,28 +1010,21 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) { // Send SOF // 10-11 ETUs of ZERO - for (int i = 0; i < 10; ++i) ToSendStuffBit(0); + for (int i = 0; i < 10; i++) + ToSendStuffBit(0); + // 2-3 ETUs of ONE ToSendStuffBit(1); ToSendStuffBit(1); -// ToSendStuffBit(1); // Sending cmd, LSB // from here we add BITS - for (int i = 0; i < len; ++i) { + for (int i = 0; i < len; i++) { // Start bit ToSendStuffBit(0); // Data bits uint8_t b = cmd[i]; - // if ( b & 1 ) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>1) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>2) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>3) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>4) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>5) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>6) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>7) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); ToSendStuffBit(b & 1); ToSendStuffBit((b >> 1) & 1); @@ -1119,20 +1039,24 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) { ToSendStuffBit(1); // EGT extra guard time // For PCD it ranges 0-57us (1etu = 9us) - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); +// ToSendStuffBit(1); +// ToSendStuffBit(1); +// ToSendStuffBit(1); } // Send EOF // 10-11 ETUs of ZERO - for (int i = 0; i < 10; ++i) ToSendStuffBit(0); + for (int i = 0; i < 10; i++) + ToSendStuffBit(0); // Transition time. TR0 - guard time // 8ETUS minum? // Per specification, Subcarrier must be stopped no later than 2 ETUs after EOF. // I'm guessing this is for the FPGA to be able to send all bits before we switch to listening mode - for (int i = 0; i < 24 ; ++i) ToSendStuffBit(1); + + // ensure that last byte is filled up + for (int i = 0; i < 8 ; ++i) + ToSendStuffBit(1); // TR1 - Synchronization time // Convert from last character reference to length @@ -1147,11 +1071,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) { uint32_t time_start = GetCountSspClk(); CodeIso14443bAsReader(cmd, len); - TransmitFor14443b_AsReader(); - - if (g_trigger) LED_A_ON(); - LogTrace(cmd, len, time_start, GetCountSspClk(), NULL, true); } @@ -1159,7 +1079,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) { * TODO: check CRC and preamble */ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response) { - + LED_A_ON(); uint8_t message_frame[message_length + 4]; // PCB message_frame[0] = 0x0A | pcb_blocknum; @@ -1171,18 +1091,20 @@ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *r // EDC (CRC) AddCrc14B(message_frame, message_length + 2); // send - CodeAndTransmit14443bAsReader(message_frame, message_length + 4); //no + CodeAndTransmit14443bAsReader(message_frame, message_length + 4); // get response - GetTagSamplesFor14443bDemod(); //no + int ret = GetTagSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT); FpgaDisableTracing(); - if (Demod.len < 3) - return 0; + if (ret < 3) { + LED_A_OFF(); + return 0; + } // VALIDATE CRC if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) { - if (DBGLEVEL > 3) Dbprintf("crc fail ICE"); + if (DBGLEVEL > 3) DbpString("CRC fail"); return 0; } // copy response contents @@ -1190,6 +1112,7 @@ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *r memcpy(response, Demod.output, Demod.len); return Demod.len; + LED_A_OFF(); } /** @@ -1202,12 +1125,14 @@ static uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) { uint8_t select_srx[] = { ISO14443B_SELECT, 0x00, 0x00, 0x00}; CodeAndTransmit14443bAsReader(init_srx, sizeof(init_srx)); - GetTagSamplesFor14443bDemod(); //no + int ret = GetTagSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT); FpgaDisableTracing(); - if (Demod.len == 0) + if (Demod.len == 0 || ret < 0) return 2; + Dbprintf("Randomly generated Chip ID (+ 2 byte CRC): %02x [%02x %02x]", Demod.output[0], Demod.output[1], Demod.output[2]); + // Randomly generated Chip ID if (card) card->chipid = Demod.output[0]; @@ -1216,10 +1141,10 @@ static uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) { AddCrc14B(select_srx, 2); CodeAndTransmit14443bAsReader(select_srx, sizeof(select_srx)); - GetTagSamplesFor14443bDemod(); //no + ret = GetTagSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT); FpgaDisableTracing(); - if (Demod.len != 3) + if (Demod.len != 3 || ret < 0) return 2; // Check the CRC of the answer: @@ -1235,10 +1160,10 @@ static uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) { AddCrc14B(select_srx, 1); CodeAndTransmit14443bAsReader(select_srx, 3); // Only first three bytes for this one - GetTagSamplesFor14443bDemod(); //no + ret = GetTagSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT); FpgaDisableTracing(); - if (Demod.len != 10) + if (Demod.len != 10 || ret < 0) return 2; // The check the CRC of the answer @@ -1258,7 +1183,7 @@ static uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) { * TODO: Support multiple cards (perform anticollision) * TODO: Verify CRC checksums */ -uint8_t iso14443b_select_card(iso14b_card_select_t *card) { +int iso14443b_select_card(iso14b_card_select_t *card) { // WUPB command (including CRC) // Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 }; @@ -1267,16 +1192,16 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card) { // first, wake up the tag CodeAndTransmit14443bAsReader(wupb, sizeof(wupb)); - GetTagSamplesFor14443bDemod(); //select_card + int ret = GetTagSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT); FpgaDisableTracing(); // ATQB too short? - if (Demod.len < 14) - return 2; + if (ret < 14) + return -1; // VALIDATE CRC if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) - return 3; + return -2; if (card) { card->uidlen = 4; @@ -1292,16 +1217,16 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card) { AddCrc14B(attrib, 9); CodeAndTransmit14443bAsReader(attrib, sizeof(attrib)); - GetTagSamplesFor14443bDemod();//select_card + ret = GetTagSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT); FpgaDisableTracing(); // Answer to ATTRIB too short? - if (Demod.len < 3) - return 2; + if (ret < 3) + return -1; // VALIDATE CRC if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) - return 3; + return -2; if (card) { @@ -1344,10 +1269,10 @@ void iso14443b_setup(void) { SetAdcMuxFor(GPIO_MUXSEL_HIPKD); // Set up the synchronous serial port - FpgaSetupSsc(); + FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER); // Signal field is on with the appropriate LED - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD); SpinDelay(100); // Start the timer @@ -1369,21 +1294,22 @@ static bool ReadSTBlock(uint8_t block) { uint8_t cmd[] = {ISO14443B_READ_BLK, block, 0x00, 0x00}; AddCrc14B(cmd, 2); CodeAndTransmit14443bAsReader(cmd, sizeof(cmd)); - GetTagSamplesFor14443bDemod(); + int res = GetTagSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT); FpgaDisableTracing(); // Check if we got an answer from the tag - if (Demod.len != 6) { + if (Demod.len != 6 || res < 0) { DbpString("[!] expected 6 bytes from tag, got less..."); return false; } // The check the CRC of the answer if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) { - DbpString("[!] CRC Error block!"); + DbpString("CRC fail"); return false; } return true; } + void ReadSTMemoryIso14443b(uint8_t numofblocks) { // Make sure that we start from off, since the tags are stateful; // confusing things will happen if we don't reset them between reads. @@ -1427,6 +1353,9 @@ void ReadSTMemoryIso14443b(uint8_t numofblocks) { if (i == 0xff) break; ++i; } + + // Todo: iceman: send back read data to client. + // reply_ng(..., ); out: switch_off(); // disconnect raw @@ -1459,10 +1388,10 @@ static void iso1444b_setup_sniff(void) { SetAdcMuxFor(GPIO_MUXSEL_HIPKD); // Setup for the DMA. - FpgaSetupSsc(); + FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER); // Set FPGA in the appropriate mode - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_848_KHZ | FPGA_HF_READER_MODE_SNIFF_IQ); SpinDelay(20); // Start the SSP timer @@ -1497,10 +1426,17 @@ void RAMFUNC SniffIso14443b(void) { bool ReaderIsActive = false; iso1444b_setup_sniff(); - + // The DMA buffer, used to stream samples from the FPGA - int8_t *dmaBuf = (int8_t *) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); - int8_t *data = dmaBuf; + uint16_t *dmaBuf = (uint16_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE * sizeof(uint16_t)); + uint16_t *upTo = dmaBuf; + int lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; + int8_t ci, cq; + int maxBehindBy = 0; + + // Count of samples received so far, so that we can include timing + // information in the trace buffer. + int samples = 0; // Setup and start DMA. if (!FpgaSetupSscDma((uint8_t *) dmaBuf, ISO14443B_DMA_BUFFER_SIZE)) { @@ -1513,25 +1449,48 @@ void RAMFUNC SniffIso14443b(void) { time_0 = GetCountSspClk(); // loop and listen - while (!BUTTON_PRESS()) { - WDT_HIT(); + for(;;) { - int ci = data[0]; - int cq = data[1]; - data += 2; + int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & (ISO14443B_DMA_BUFFER_SIZE - 1); + if (behindBy > maxBehindBy) { + maxBehindBy = behindBy; + } - if (data >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { - data = dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; - } + if (behindBy < 1) continue; + + ci = *upTo >> 8; + cq = *upTo; + upTo++; + lastRxCounter--; + if (upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { // we have read all of the DMA buffer content. + upTo = dmaBuf; // start reading the circular buffer from the beginning again + lastRxCounter += ISO14443B_DMA_BUFFER_SIZE; + if (behindBy > (9 * ISO14443B_DMA_BUFFER_SIZE / 10)) { + Dbprintf("About to blow circular buffer - aborted! behindBy=%d", behindBy); + break; + } + } + + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX)) { // DMA Counter Register had reached 0, already rotated. + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; // refresh the DMA Next Buffer and + AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; // DMA Next Counter registers + + WDT_HIT(); + if (BUTTON_PRESS()) { + DbpString("Button pressed, cancelled"); + break; + } + } + + samples++; // no need to try decoding reader data if the tag is sending - if (!TagIsActive) { + if (TagIsActive == false) { LED_A_INV(); if (Handle14443bReaderUartBit(ci & 0x01)) { + time_stop = GetCountSspClk() - time_0; LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true); Uart14bReset(); @@ -1556,7 +1515,7 @@ void RAMFUNC SniffIso14443b(void) { // is this | 0x01 the error? & 0xfe in https://github.com/Proxmark/proxmark3/issues/103 // LSB is a fpga signal bit. - if (Handle14443bTagSamplesDemod(ci, cq)) { + if (Handle14443bTagSamplesDemod(ci/2, cq/2) >= 0) { time_stop = GetCountSspClk() - time_0; LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false); Uart14bReset(); @@ -1568,6 +1527,7 @@ void RAMFUNC SniffIso14443b(void) { } } + FpgaDisableSscDma(); if (DBGLEVEL >= 2) { DbpString("[+] Sniff statistics:"); Dbprintf("[+] uart State: %x ByteCount: %i ByteCountMax: %i", Uart.state, Uart.byteCnt, Uart.byteCntMax); @@ -1593,12 +1553,14 @@ static void iso14b_set_trigger(bool enable) { * */ void SendRawCommand14443B_Ex(PacketCommandNG *c) { + iso14b_command_t param = c->oldarg[0]; size_t len = c->oldarg[1] & 0xffff; uint32_t timeout = c->oldarg[2]; uint8_t *cmd = c->data.asBytes; - uint8_t status; + int status; uint32_t sendlen = sizeof(iso14b_card_select_t); + uint8_t buf[PM3_CMD_DATA_SIZE] = {0x00}; if (DBGLEVEL > 3) Dbprintf("14b raw: param, %04x", param); @@ -1620,22 +1582,22 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) { if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) { iso14b_card_select_t *card = (iso14b_card_select_t *)buf; status = iso14443b_select_card(card); - reply_mix(CMD_ACK, status, sendlen, 0, buf, sendlen); - // 0: OK 2: attrib fail, 3:crc fail, - if (status > 0) goto out; + reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, buf, sendlen); + // 0: OK -1: attrib fail, -2:crc fail, + if (status != 0) goto out; } if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) { iso14b_card_select_t *card = (iso14b_card_select_t *)buf; status = iso14443b_select_srx_card(card); - reply_mix(CMD_ACK, status, sendlen, 0, buf, sendlen); + reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, buf, sendlen); // 0: OK 2: demod fail, 3:crc fail, if (status > 0) goto out; } if ((param & ISO14B_APDU) == ISO14B_APDU) { status = iso14443b_apdu(cmd, len, buf); - reply_mix(CMD_ACK, status, status, 0, buf, status); + reply_mix(CMD_HF_ISO14443B_COMMAND, status, status, 0, buf, status); } if ((param & ISO14B_RAW) == ISO14B_RAW) { @@ -1645,12 +1607,11 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) { } CodeAndTransmit14443bAsReader(cmd, len); // raw - GetTagSamplesFor14443bDemod(); // raw + status = GetTagSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT); // raw FpgaDisableTracing(); sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE); - status = (Demod.len > 0) ? 0 : 1; - reply_old(CMD_ACK, status, sendlen, 0, Demod.output, sendlen); + reply_old(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, Demod.output, sendlen); } out: diff --git a/armsrc/iso14443b.h b/armsrc/iso14443b.h index 62dbd6590..0013ad313 100644 --- a/armsrc/iso14443b.h +++ b/armsrc/iso14443b.h @@ -28,7 +28,7 @@ void iso14443b_setup(void); uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response); -uint8_t iso14443b_select_card(iso14b_card_select_t *card); +int iso14443b_select_card(iso14b_card_select_t *card); uint8_t iso14443b_select_card_srx(iso14b_card_select_t *card); void SimulateIso14443bTag(uint32_t pupi); diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index a82bb9a07..51dc7fac8 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -76,7 +76,7 @@ #define DELAY_ARM_TO_TAG 16 #define DELAY_TAG_TO_ARM 32 -//SSP_CLK runs at 13.56MHz / 4 = 3,39MHz when snooping. All values should be multiples of 16 +//SSP_CLK runs at 13.56MHz / 4 = 3,39MHz when sniffing. All values should be multiples of 16 #define DELAY_TAG_TO_ARM_SNIFF 32 #define DELAY_READER_TO_ARM_SNIFF 32 @@ -122,7 +122,7 @@ static void BuildInventoryResponse(uint8_t *uid); // resulting data rate is 26.48 kbit/s (fc/512) // cmd ... data // n ... length of data -static void CodeIso15693AsReader(uint8_t *cmd, int n) { +void CodeIso15693AsReader(uint8_t *cmd, int n) { ToSendReset(); @@ -195,7 +195,7 @@ static void CodeIso15693AsReader256(uint8_t *cmd, int n) { static const uint8_t encode_4bits[16] = { 0xaa, 0x6a, 0x9a, 0x5a, 0xa6, 0x66, 0x96, 0x56, 0xa9, 0x69, 0x99, 0x59, 0xa5, 0x65, 0x95, 0x55 }; -static void CodeIso15693AsTag(uint8_t *cmd, size_t len) { +void CodeIso15693AsTag(uint8_t *cmd, size_t len) { /* * SOF comprises 3 parts; * * An unmodulated time of 56.64 us @@ -241,7 +241,7 @@ static void CodeIso15693AsTag(uint8_t *cmd, size_t len) { } // Transmit the command (to the tag) that was placed in cmd[]. -static void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time) { +void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time) { FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_FULL_MOD); @@ -279,7 +279,7 @@ static void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time //----------------------------------------------------------------------------- // Transmit the command (to the reader) that was placed in cmd[]. //----------------------------------------------------------------------------- -static void TransmitTo15693Reader(const uint8_t *cmd, size_t len, uint32_t *start_time, uint32_t slot_time, bool slow) { +void TransmitTo15693Reader(const uint8_t *cmd, size_t len, uint32_t *start_time, uint32_t slot_time, bool slow) { // don't use the FPGA_HF_SIMULATOR_MODULATE_424K_8BIT minor mode. It would spoil GetCountSspClk() FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K); @@ -617,7 +617,7 @@ static void DecodeTagReset(DecodeTag_t *DecodeTag) { /* * Receive and decode the tag response, also log to tracebuffer */ -static int GetIso15693AnswerFromTag(uint8_t* response, uint16_t max_len, uint16_t timeout, uint32_t *eof_time) { +int GetIso15693AnswerFromTag(uint8_t* response, uint16_t max_len, uint16_t timeout, uint32_t *eof_time) { int samples = 0; int ret = 0; @@ -966,7 +966,7 @@ static RAMFUNC int Handle15693SampleFromReader(bool bit, DecodeReader_t *DecodeR DecodeReader->posCount++; if (DecodeReader->Coding == CODING_1_OUT_OF_4) { if (DecodeReader->posCount == 7*16) { // 7 bits jammed - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNOOP_AMPLITUDE); // stop jamming + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNIFF_AMPLITUDE); // stop jamming // FpgaDisableTracing(); LED_D_OFF(); } else if (DecodeReader->posCount == 8*16) { @@ -976,7 +976,7 @@ static RAMFUNC int Handle15693SampleFromReader(bool bit, DecodeReader_t *DecodeR } } else { if (DecodeReader->posCount == 7*256) { // 7 bits jammend - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNOOP_AMPLITUDE); // stop jamming + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNIFF_AMPLITUDE); // stop jamming LED_D_OFF(); } else if (DecodeReader->posCount == 8*256) { DecodeReader->posCount = 0; @@ -1005,7 +1005,7 @@ static RAMFUNC int Handle15693SampleFromReader(bool bit, DecodeReader_t *DecodeR // correctly. //----------------------------------------------------------------------------- -static int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eof_time) { +int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eof_time) { int samples = 0; bool gotFrame = false; uint8_t b; @@ -1167,7 +1167,7 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) { Dbprintf("Sniff started. Press PM3 Button to stop."); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNOOP_AMPLITUDE); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNIFF_AMPLITUDE); LED_D_OFF(); SetAdcMuxFor(GPIO_MUXSEL_HIPKD); FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER); @@ -1197,7 +1197,7 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) { dma_start_time = GetCountSspClk() & 0xfffffff0; } - uint16_t snoopdata = *upTo++; + uint16_t sniffdata = *upTo++; if (upTo >= dmaBuf + ISO15693_DMA_BUFFER_SIZE) { // we have read all of the DMA buffer content. upTo = dmaBuf; // start reading the circular buffer from the beginning @@ -1218,7 +1218,7 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) { } if (!TagIsActive) { // no need to try decoding reader data if the tag is sending - if (Handle15693SampleFromReader(snoopdata & 0x02, &DecodeReader)) { + if (Handle15693SampleFromReader(sniffdata & 0x02, &DecodeReader)) { uint32_t eof_time = dma_start_time + samples*16 + 8 - DELAY_READER_TO_ARM_SNIFF; // end of EOF if (DecodeReader.byteCount > 0) { @@ -1236,7 +1236,7 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) { ReaderIsActive = false; ExpectTagAnswer = true; - } else if (Handle15693SampleFromReader(snoopdata & 0x01, &DecodeReader)) { + } else if (Handle15693SampleFromReader(sniffdata & 0x01, &DecodeReader)) { uint32_t eof_time = dma_start_time + samples*16 + 16 - DELAY_READER_TO_ARM_SNIFF; // end of EOF if (DecodeReader.byteCount > 0) { @@ -1261,7 +1261,7 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) { } if (!ReaderIsActive && ExpectTagAnswer) { // no need to try decoding tag data if the reader is currently sending or no answer expected yet - if (Handle15693SamplesFromTag(snoopdata >> 2, &DecodeTag)) { + if (Handle15693SamplesFromTag(sniffdata >> 2, &DecodeTag)) { uint32_t eof_time = dma_start_time + samples*16 - DELAY_TAG_TO_ARM_SNIFF; // end of EOF if (DecodeTag.lastBit == SOF_PART2) { @@ -1550,7 +1550,7 @@ void ReaderIso15693(uint32_t parameter) { } // When SIM: initialize the Proxmark3 as ISO15693 tag -static void Iso15693InitTag(void) { +void Iso15693InitTag(void) { FpgaDownloadAndGo(FPGA_BITSTREAM_HF); SetAdcMuxFor(GPIO_MUXSEL_HIPKD); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION); diff --git a/armsrc/iso15693.h b/armsrc/iso15693.h index bc9b89eee..1b5405b13 100644 --- a/armsrc/iso15693.h +++ b/armsrc/iso15693.h @@ -23,6 +23,15 @@ #define DELAY_ISO15693_VCD_TO_VICC_READER 1056 // 1056/3,39MHz = 311.5us from end of command EOF to start of tag response #define DELAY_ISO15693_VICC_TO_VCD_READER 1024 // 1024/3.39MHz = 302.1us between end of tag response and next reader command +void Iso15693InitReader(void); +void Iso15693InitTag(void); +void CodeIso15693AsReader(uint8_t *cmd, int n); +void CodeIso15693AsTag(uint8_t *cmd, size_t len); + +void TransmitTo15693Reader(const uint8_t *cmd, size_t len, uint32_t *start_time, uint32_t slot_time, bool slow); +int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eof_time); +void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time); +int GetIso15693AnswerFromTag(uint8_t* response, uint16_t max_len, uint16_t timeout, uint32_t *eof_time); void RecordRawAdcSamplesIso15693(void); void AcquireRawAdcSamplesIso15693(void); diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index bfb19323b..141fefda5 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -134,7 +134,7 @@ static bool waitCmd14b(bool verbose) { PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { if ((resp.oldarg[0] & 0xFF) > 0) return false; @@ -314,7 +314,7 @@ static bool get_14b_UID(iso14b_card_select_t *card) { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0); - if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { uint8_t status = resp.oldarg[0]; if (status == 0) { @@ -330,7 +330,7 @@ static bool get_14b_UID(iso14b_card_select_t *card) { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); - if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { uint8_t status = resp.oldarg[0]; if (status == 0) { @@ -515,7 +515,7 @@ static bool HF14B_Std_Info(bool verbose) { SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); switch_off_field_14b(); return false; @@ -556,7 +556,7 @@ static bool HF14B_ST_Info(bool verbose) { SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); return false; } @@ -611,7 +611,7 @@ static bool HF14B_ST_Reader(bool verbose) { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); return false; } @@ -651,7 +651,7 @@ static bool HF14B_Std_Reader(bool verbose) { SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); return false; } @@ -695,7 +695,7 @@ static bool HF14B_Other_Reader(void) { // clearCommandBuffer(); // SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, datalen, 0, data, datalen); // PacketResponseNG resp; - // WaitForResponse(CMD_ACK,&resp); + // WaitForResponse(CMD_HF_ISO14443B_COMMAND,&resp); // if (datalen > 2 ) { // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); @@ -709,7 +709,7 @@ static bool HF14B_Other_Reader(void) { // clearCommandBuffer(); // SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, 1, 0, data, 1); // PacketResponseNG resp; - // WaitForResponse(CMD_ACK, &resp); + // WaitForResponse(CMD_HF_ISO14443B_COMMAND, &resp); // if (datalen > 0) { // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); @@ -723,7 +723,7 @@ static bool HF14B_Other_Reader(void) { // clearCommandBuffer(); // SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, 1, 0, data, 1); // PacketResponseNG resp; - // WaitForResponse(CMD_ACK, &resp); + // WaitForResponse(CMD_HF_ISO14443B_COMMAND, &resp); // if (datalen > 0) { // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); @@ -899,7 +899,7 @@ static int CmdHF14BDump(const char *Cmd) { SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0); //select - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) { if (resp.oldarg[0]) { PrintAndLogEx(INFO, "failed to select %" PRId64 " | %" PRId64, resp.oldarg[0], resp.oldarg[1]); goto out; @@ -915,7 +915,7 @@ static int CmdHF14BDump(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_APPEND_CRC | ISO14B_RAW, 2, 0, req, sizeof(req)); - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) { uint8_t status = resp.oldarg[0] & 0xFF; if (status > 0) { diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 501190170..639519c30 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -529,21 +529,19 @@ static int CmdHFiClassSim(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_iclass_sim(); - uint8_t simType = 0; uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint8_t sim_type = param_get8ex(Cmd, 0, 0, 10); - simType = param_get8ex(Cmd, 0, 0, 10); - - if (simType == 0) { + if (sim_type == 0) { if (param_gethex(Cmd, 1, CSN, 16)) { PrintAndLogEx(ERR, "A CSN should consist of 16 HEX symbols"); return usage_hf_iclass_sim(); } - PrintAndLogEx(INFO, " simtype: %02x CSN: %s", simType, sprint_hex(CSN, 8)); + PrintAndLogEx(INFO, " simtype: %02x CSN: %s", sim_type, sprint_hex(CSN, 8)); } - if (simType > 4) { - PrintAndLogEx(ERR, "Undefined simptype %d", simType); + if (sim_type > 4) { + PrintAndLogEx(ERR, "Undefined simtype %d", sim_type); return usage_hf_iclass_sim(); } @@ -575,14 +573,14 @@ static int CmdHFiClassSim(const char *Cmd) { **/ uint8_t tries = 0; - switch (simType) { + switch (sim_type) { - case 2: { + case ICLASS_SIM_MODE_READER_ATTACK: { PrintAndLogEx(INFO, "Starting iCLASS sim 2 attack (elite mode)"); - PrintAndLogEx(INFO, "press Enter to cancel"); + PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel"); PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ICLASS_SIMULATE, simType, NUM_CSNS, 0, csns, 8 * NUM_CSNS); + SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, NUM_CSNS, 0, csns, 8 * NUM_CSNS); while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { tries++; @@ -625,13 +623,13 @@ static int CmdHFiClassSim(const char *Cmd) { free(dump); break; } - case 4: { + case ICLASS_SIM_MODE_READER_ATTACK_KEYROLL: { // reader in key roll mode, when it has two keys it alternates when trying to verify. PrintAndLogEx(INFO, "Starting iCLASS sim 4 attack (elite mode, reader in key roll mode)"); PrintAndLogEx(INFO, "press Enter to cancel"); PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ICLASS_SIMULATE, simType, NUM_CSNS, 0, csns, 8 * NUM_CSNS); + SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, NUM_CSNS, 0, csns, 8 * NUM_CSNS); while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { tries++; @@ -689,12 +687,13 @@ static int CmdHFiClassSim(const char *Cmd) { free(dump); break; } - case 1: - case 3: + case ICLASS_SIM_MODE_CSN: + case ICLASS_SIM_MODE_CSN_DEFAULT: + case ICLASS_SIM_MODE_FULL: default: { uint8_t numberOfCSNs = 0; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ICLASS_SIMULATE, simType, numberOfCSNs, 0, CSN, 8); + SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, numberOfCSNs, 0, CSN, 8); break; } } diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 117eea672..0d24d5bae 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -588,6 +588,18 @@ typedef struct { #define FLAG_ICLASS_READER_ONE_TRY 0x20 #define FLAG_ICLASS_READER_CEDITKEY 0x40 +// iCLASS simulation modes +#define ICLASS_SIM_MODE_CSN 0 +#define ICLASS_SIM_MODE_CSN_DEFAULT 1 +#define ICLASS_SIM_MODE_READER_ATTACK 2 +#define ICLASS_SIM_MODE_FULL 3 +#define ICLASS_SIM_MODE_READER_ATTACK_KEYROLL 4 +#define ICLASS_SIM_MODE_EXIT_AFTER_MAC 5 // note: device internal only + +#define MODE_SIM_CSN 0 +#define MODE_EXIT_AFTER_MAC 1 +#define MODE_FULLSIM 2 + // Dbprintf flags #define FLAG_RAWPRINT 0x00 #define FLAG_LOG 0x01