X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/d8af608f8e4e6dc520045bac69e8e9dac6de7d42..95215e873f969f76a3e028c975342c8d3be48bff:/armsrc/iso14443b.c diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 2bdce7cb..9d033f61 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -13,13 +13,12 @@ #include "apps.h" #include "util.h" #include "string.h" - #include "iso14443crc.h" - -#define RECEIVE_SAMPLES_TIMEOUT 0x0004FFFF +#include "common.h" +#define RECEIVE_SAMPLES_TIMEOUT 600000 #define ISO14443B_DMA_BUFFER_SIZE 256 -uint8_t PowerOn = TRUE; + // PCB Block number for APDUs static uint8_t pcb_blocknum = 0; @@ -270,6 +269,7 @@ static void UartReset() Uart.state = STATE_UNSYNCD; Uart.byteCnt = 0; Uart.bitCnt = 0; + Uart.posCnt = 0; memset(Uart.output, 0x00, MAX_FRAME_SIZE); } @@ -345,7 +345,7 @@ void SimulateIso14443bTag(void) // response to HLTB and ATTRIB static const uint8_t response2[] = {0x00, 0x78, 0xF0}; - uint8_t parity[MAX_PARITY_SIZE]; + uint8_t parity[MAX_PARITY_SIZE] = {0x00}; FpgaDownloadAndGo(FPGA_BITSTREAM_HF); @@ -383,14 +383,12 @@ void SimulateIso14443bTag(void) for(;;) { - if(!GetIso14443bCommandFromReader(receivedCmd, &len)) { - Dbprintf("button pressed, received %d commands", cmdsRecvd); - break; + if (!GetIso14443bCommandFromReader(receivedCmd, &len)) { + Dbprintf("button pressed, received %d commands", cmdsRecvd); + break; } - if (tracing) { - LogTrace(receivedCmd, len, 0, 0, parity, TRUE); - } + LogTrace(receivedCmd, len, 0, 0, parity, TRUE); // Good, look at the command now. if ( (len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len) == 0) @@ -410,14 +408,14 @@ void SimulateIso14443bTag(void) // And print whether the CRC fails, just for good measure uint8_t b1, b2; if (len >= 3){ // if crc exists - ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2); - if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) { - // Not so good, try again. - DbpString("+++CRC fail"); - - } else { - DbpString("CRC passes"); - } + ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2); + if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) { + // Not so good, try again. + DbpString("+++CRC fail"); + + } else { + DbpString("CRC passes"); + } } //get rid of compiler warning respCodeLen = 0; @@ -462,7 +460,7 @@ void SimulateIso14443bTag(void) AT91C_BASE_SSC->SSC_THR = respCode[i++]; FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR; } - if(BUTTON_PRESS()) break; + if(BUTTON_PRESS()) break; } // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again: @@ -475,10 +473,10 @@ void SimulateIso14443bTag(void) } } - // trace the response: - if (tracing) LogTrace(resp, respLen, 0, 0, parity, FALSE); + LogTrace(resp, respLen, 0, 0, parity, FALSE); } FpgaDisableSscDma(); + set_tracing(FALSE); } //============================================================================= @@ -525,9 +523,14 @@ static struct { * false if we are still waiting for some more * */ + #define abs(x) ( ((x)<0) ? -(x) : (x) ) static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq) { - int v; + int v = 0; + int ai = abs(ci); + int aq = abs(cq); + int halfci = (ai >> 1); + int halfcq = (aq >> 1); // The soft decision on the bit uses an estimate of just the // quadrant of the reference angle, not the exact angle. @@ -546,50 +549,12 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq) #define SUBCARRIER_DETECT_THRESHOLD 8 -// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by abs(ci) + abs(cq) -/* #define CHECK_FOR_SUBCARRIER() { \ - v = ci; \ - if(v < 0) v = -v; \ - if(cq > 0) { \ - v += cq; \ - } else { \ - v -= 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() { \ - 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); \ - } \ - } \ - } \ - } - + v = MAX(ai, aq) + MIN(halfci, halfcq); \ +} + + switch(Demod.state) { case DEMOD_UNSYNCD: CHECK_FOR_SUBCARRIER(); @@ -602,7 +567,8 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq) break; case DEMOD_PHASE_REF_TRAINING: - if(Demod.posCount < 10*2) { + if(Demod.posCount < 8) { + //if(Demod.posCount < 10*2) { CHECK_FOR_SUBCARRIER(); if (v > SUBCARRIER_DETECT_THRESHOLD) { // set the reference phase (will code a logic '1') by averaging over 32 1/fs. @@ -620,11 +586,11 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq) case DEMOD_AWAITING_FALLING_EDGE_OF_SOF: MAKE_SOFT_DECISION(); - if(v < 0) { // logic '0' detected + //Dbprintf("ICE: %d %d %d %d %d", v, Demod.sumI, Demod.sumQ, ci, cq ); + if(v <= 0) { // logic '0' detected Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF; Demod.posCount = 0; // start of SOF sequence } else { - //if(Demod.posCount > 200/4) { // maximum length of TR1 = 200 1/fs if(Demod.posCount > 25*2) { // maximum length of TR1 = 200 1/fs Demod.state = DEMOD_UNSYNCD; } @@ -731,6 +697,11 @@ static void DemodReset() Demod.len = 0; Demod.state = DEMOD_UNSYNCD; Demod.posCount = 0; + Demod.sumI = 0; + Demod.sumQ = 0; + Demod.bitCount = 0; + Demod.thisBit = 0; + Demod.shiftReg = 0; memset(Demod.output, 0x00, MAX_FRAME_SIZE); } @@ -760,25 +731,20 @@ static void GetSamplesFor14443bDemod(int n, bool quiet) FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ); // The response (tag -> reader) that we're receiving. - uint8_t *resp = BigBuf_malloc(MAX_FRAME_SIZE); - // Set up the demodulator for tag -> reader responses. - DemodInit(resp); + DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); // The DMA buffer, used to stream samples from the FPGA int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); - + // Setup and start DMA. + FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE); + int8_t *upTo = dmaBuf; lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; // Signal field is ON with the appropriate LED: LED_D_ON(); - - // Setup and start DMA. - FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE); - - for(;;) { int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR; if(behindBy > max) max = behindBy; @@ -794,16 +760,16 @@ static void GetSamplesFor14443bDemod(int n, bool quiet) } lastRxCounter -= 2; if(lastRxCounter <= 0) { - lastRxCounter += ISO14443B_DMA_BUFFER_SIZE; + lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; } samples += 2; - if(Handle14443bSamplesDemod(ci | 0x01 , cq | 0x01)) { - gotFrame = TRUE; + // + gotFrame = Handle14443bSamplesDemod(ci , cq ); + if ( gotFrame ) break; } - } if(samples > n || gotFrame) { break; @@ -824,8 +790,8 @@ static void GetSamplesFor14443bDemod(int n, bool quiet) } //Tracing - if (tracing && Demod.len > 0) { - uint8_t parity[MAX_PARITY_SIZE]; + if (Demod.len > 0) { + uint8_t parity[MAX_PARITY_SIZE] = {0x00}; LogTrace(Demod.output, Demod.len, 0, 0, parity, FALSE); } } @@ -839,9 +805,6 @@ static void TransmitFor14443b(void) int c; FpgaSetupSsc(); - - // Start the timer - StartCountSspClk(); while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0xff; @@ -852,8 +815,6 @@ static void TransmitFor14443b(void) // Signal we are transmitting with the Green LED LED_B_ON(); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); - if ( !PowerOn ) - SpinDelay(200); for(c = 0; c < 10;) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { @@ -898,7 +859,7 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) ToSendReset(); // Establish initial reference level - for(i = 0; i < 80; i++) { + for(i = 0; i < 40; i++) { ToSendStuffBit(1); } // Send SOF @@ -1032,7 +993,9 @@ int iso14443b_select_card() // Set up ISO 14443 Type B communication (similar to iso14443a_setup) void iso14443b_setup() { + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + BigBuf_free(); // Set up the synchronous serial port FpgaSetupSsc(); @@ -1042,9 +1005,11 @@ void iso14443b_setup() { // Signal field is on with the appropriate LED LED_D_ON(); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); + + //SpinDelay(100); // Start the timer - StartCountSspClk(); + //StartCountSspClk(); DemodReset(); UartReset(); @@ -1091,6 +1056,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast) if (Demod.len == 0) { DbpString("No response from tag"); + set_tracing(FALSE); return; } else { Dbprintf("Randomly generated Chip ID (+ 2 byte CRC): %02x %02x %02x", @@ -1106,17 +1072,20 @@ void ReadSTMemoryIso14443b(uint32_t dwLast) GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); if (Demod.len != 3) { Dbprintf("Expected 3 bytes from tag, got %d", Demod.len); + set_tracing(FALSE); return; } // Check the CRC of the answer: ComputeCrc14443(CRC_14443_B, Demod.output, 1 , &cmd1[2], &cmd1[3]); if(cmd1[2] != Demod.output[1] || cmd1[3] != Demod.output[2]) { DbpString("CRC Error reading select response."); + set_tracing(FALSE); return; } // Check response from the tag: should be the same UID as the command we just sent: if (cmd1[1] != Demod.output[0]) { Dbprintf("Bad response to SELECT from Tag, aborting: %02x %02x", cmd1[1], Demod.output[0]); + set_tracing(FALSE); return; } @@ -1128,6 +1097,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast) GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); if (Demod.len != 10) { Dbprintf("Expected 10 bytes from tag, got %d", Demod.len); + set_tracing(FALSE); return; } // The check the CRC of the answer (use cmd1 as temporary variable): @@ -1175,6 +1145,8 @@ void ReadSTMemoryIso14443b(uint32_t dwLast) } i++; } + + set_tracing(FALSE); } @@ -1241,7 +1213,7 @@ void RAMFUNC SnoopIso14443b(void) upTo = dmaBuf; lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE); - uint8_t parity[MAX_PARITY_SIZE]; + uint8_t parity[MAX_PARITY_SIZE] = {0x00}; bool TagIsActive = FALSE; bool ReaderIsActive = FALSE; @@ -1270,10 +1242,12 @@ void RAMFUNC SnoopIso14443b(void) Dbprintf("blew circular buffer! behindBy=%d", behindBy); break; } + if(!tracing) { - DbpString("Reached trace limit"); + DbpString("Trace full"); break; } + if(BUTTON_PRESS()) { DbpString("cancelled"); break; @@ -1283,51 +1257,48 @@ void RAMFUNC SnoopIso14443b(void) samples += 2; if (!TagIsActive) { // no need to try decoding reader data if the tag is sending - if(Handle14443bUartBit(ci & 0x01)) { - if(triggered && tracing) { + if (Handle14443bUartBit(ci & 0x01)) { + if ( triggered) LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE); + + /* And ready to receive another command. */ + UartReset(); + /* And also reset the demod code, which might have been */ + /* false-triggered by the commands from the reader. */ + DemodReset(); } - /* And ready to receive another command. */ - UartReset(); - /* And also reset the demod code, which might have been */ - /* false-triggered by the commands from the reader. */ - DemodReset(); - } - if(Handle14443bUartBit(cq & 0x01)) { - if(triggered && tracing) { + if (Handle14443bUartBit(cq & 0x01)) { + if (triggered) LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE); - } - /* And ready to receive another command. */ - UartReset(); - /* And also reset the demod code, which might have been */ - /* false-triggered by the commands from the reader. */ - DemodReset(); - } + + /* And ready to receive another command. */ + UartReset(); + /* And also reset the demod code, which might have been */ + /* false-triggered by the commands from the reader. */ + DemodReset(); + } ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF); } if(!ReaderIsActive) { // no need to try decoding tag data if the reader is sending - and we cannot afford the time // is this | 0x01 the error? & 0xfe in https://github.com/Proxmark/proxmark3/issues/103 - if(Handle14443bSamplesDemod(ci | 0x01, cq | 0x01)) { + if(Handle14443bSamplesDemod(ci & 0xfe, cq & 0xfe)) { - //Use samples as a time measurement - if(tracing) - { - //uint8_t parity[MAX_PARITY_SIZE]; + //Use samples as a time measurement LogTrace(Demod.output, Demod.len, samples, samples, parity, FALSE); - } - triggered = TRUE; - // And ready to receive another response. - DemodReset(); - } + triggered = TRUE; + + // And ready to receive another response. + DemodReset(); + } TagIsActive = (Demod.state > DEMOD_GOT_FALLING_EDGE_OF_SOF); } - } FpgaDisableSscDma(); LEDsoff(); + AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; DbpString("Snoop statistics:"); Dbprintf(" Max behind by: %i", maxBehindBy); @@ -1335,6 +1306,7 @@ void RAMFUNC SnoopIso14443b(void) Dbprintf(" Uart ByteCnt: %i", Uart.byteCnt); Dbprintf(" Uart ByteCntMax: %i", Uart.byteCntMax); Dbprintf(" Trace length: %i", BigBuf_get_traceLen()); + set_tracing(FALSE); } @@ -1353,37 +1325,25 @@ void RAMFUNC SnoopIso14443b(void) void SendRawCommand14443B(uint32_t datalen, uint32_t recv, uint8_t powerfield, uint8_t data[]) { iso14443b_setup(); - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - BigBuf_free(); - if ( !PowerOn ){ - FpgaSetupSsc(); - } - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - - // Start the timer - StartCountSspClk(); - - DemodReset(); - UartReset(); if ( datalen == 0 && recv == 0 && powerfield == 0){ - clear_trace(); - } else { + + } else { set_tracing(TRUE); CodeAndTransmit14443bAsReader(data, datalen); } - if(recv) { + if (recv) { GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, FALSE); uint16_t iLen = MIN(Demod.len, USB_CMD_DATA_SIZE); cmd_send(CMD_ACK, iLen, 0, 0, Demod.output, iLen); } - if(!powerfield) { + if (!powerfield) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaDisableSscDma(); + set_tracing(FALSE); LED_D_OFF(); - PowerOn = 0; } }