X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/0923c43cc675b08a295dd531ae0f7c4ed87a1d1d..65cdf0e3f9598e17c7cd0570ca616f51eec11725:/armsrc/iso14443b.c diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index b7016725..cccf0dd6 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -19,6 +19,11 @@ #define TR1 0 // Frame Delay Time PICC to PCD (per 14443-3 Amendment 1) #define TR2 0 + +// 4sample +#define SEND4STUFFBIT(x) ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x); +//#define SEND4STUFFBIT(x) ToSendStuffBit(x); + static void switch_off(void); // the block number for the ISO14443-4 PCB (used with APDUs) @@ -200,9 +205,6 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { * */ - // ToSendStuffBit, 40 calls - // 1 ETU = 1startbit, 1stopbit, 8databits == 10bits. - // 1 ETU = 10 * 4 == 40 stuffbits ( ETU_TAG_BIT ) int i,j; uint8_t b; @@ -218,77 +220,51 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { // Send SOF. // 10-11 ETU * 4times samples ZEROS - for(i = 0; i < 10; i++) { - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - } + for(i = 0; i < 10; i++) { SEND4STUFFBIT(0); } + //for(i = 0; i < 10; i++) { ToSendStuffBit(0); } // 2-3 ETU * 4times samples ONES - for(i = 0; i < 3; i++) { - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - } + for(i = 0; i < 3; i++) { SEND4STUFFBIT(1); } + //for(i = 0; i < 3; i++) { ToSendStuffBit(1); } // data for(i = 0; i < len; ++i) { // Start bit - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); + SEND4STUFFBIT(0); + //ToSendStuffBit(0); // Data bits b = cmd[i]; for(j = 0; j < 8; ++j) { - if(b & 1) { - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); + if(b & 1) { + SEND4STUFFBIT(1); + //ToSendStuffBit(1); } else { - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); + SEND4STUFFBIT(0); + //ToSendStuffBit(0); } b >>= 1; } // Stop bit - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); + SEND4STUFFBIT(1); + //ToSendStuffBit(1); // Extra Guard bit // For PICC it ranges 0-18us (1etu = 9us) - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); + SEND4STUFFBIT(1); + //ToSendStuffBit(1); } // Send EOF. // 10-11 ETU * 4 sample rate = ZEROS - for(i = 0; i < 10; i++) { - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - } + for(i = 0; i < 10; i++) { SEND4STUFFBIT(0); } + //for(i = 0; i < 10; i++) { ToSendStuffBit(0); } // why this? - for(i = 0; i < 40; i++) { - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - } + for(i = 0; i < 40; i++) { SEND4STUFFBIT(1); } + //for(i = 0; i < 40; i++) { ToSendStuffBit(1); } // Convert from last byte pos to length ++ToSendMax; @@ -434,13 +410,25 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) { // Signal field is off with the appropriate LED 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? + for(uint8_t c = 0; c < 10;) { + 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. UartInit(received); - - uint8_t mask, b = 0; + + b = 0; + uint8_t mask; while( !BUTTON_PRESS() ) { WDT_HIT(); @@ -457,27 +445,68 @@ 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) { // 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); - // 8 ETU / 8bits. 8/4= 2 etus. - AT91C_BASE_SSC->SSC_THR = 0XFF; - + ClearFpgaShiftingRegisters(); + FpgaSetupSsc(); + volatile uint32_t b; // Transmit the response. for(uint16_t i = 0; i < len;) { if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { - AT91C_BASE_SSC->SSC_THR = response[i]; - ++i; + AT91C_BASE_SSC->SSC_THR = response[++i]; } + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + 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 @@ -527,8 +556,9 @@ void SimulateIso14443bTag(uint32_t pupi) { // ...PUPI/UID supplied from user. Adjust ATQB response accordingly if ( pupi > 0 ) { + uint8_t len = size(respATQB); num_to_bytes(pupi, 4, respATQB+1); - ComputeCrc14443(CRC_14443_B, respATQB, 12, respATQB+13, respATQB+14); + ComputeCrc14443(CRC_14443_B, respATQB, 12, &respATQB[len-2], &respATQB[len-1]); } // prepare "ATQB" tag answer (encoded): @@ -568,13 +598,10 @@ void SimulateIso14443bTag(uint32_t pupi) { // REQ or WUP request in ANY state // WUP in HALTED state if (len == 5 ) { - if ( (receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8)== 0x8 && cardSTATE != SIM_HALTED) || - (receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8)== 0) ){ - - TransmitFor14443b_AsTag( encodedATQB, encodedATQBLen ); - LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, FALSE); + if ( (receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8)== 0x8 && cardSTATE == SIM_HALTED) || + receivedCmd[0] == ISO14443B_REQB ){ + LogTrace(receivedCmd, len, 0, 0, NULL, TRUE); cardSTATE = SIM_SELECTING; - continue; } } @@ -587,30 +614,7 @@ void SimulateIso14443bTag(uint32_t pupi) { * HALT send halt response ( waiting for wupb ) */ - - if ( len == 7 && receivedCmd[0] == ISO14443B_HALT ) { - cardSTATE = SIM_HALTED; - } else if ( len == 11 && receivedCmd[0] == ISO14443B_ATTRIB ) { - cardSTATE = SIM_ACKNOWLEDGE; - } else { - // Todo: - // - SLOT MARKER - // - ISO7816 - // - emulate with a memory dump - Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsReceived); - - // CRC Check - 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]) - DbpString("+++CRC fail"); - else - DbpString("CRC passes"); - } - cardSTATE = SIM_IDLE; - } - + switch(cardSTATE){ case SIM_NOFIELD: case SIM_HALTED: @@ -621,7 +625,7 @@ void SimulateIso14443bTag(uint32_t pupi) { case SIM_SELECTING: { TransmitFor14443b_AsTag( encodedATQB, encodedATQBLen ); LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, FALSE); - cardSTATE = SIM_IDLE; + cardSTATE = SIM_WORK; break; } case SIM_HALTING: { @@ -636,8 +640,32 @@ void SimulateIso14443bTag(uint32_t pupi) { cardSTATE = SIM_IDLE; break; } - default: + case SIM_WORK:{ + if ( len == 7 && receivedCmd[0] == ISO14443B_HALT ) { + cardSTATE = SIM_HALTED; + } else if ( len == 11 && receivedCmd[0] == ISO14443B_ATTRIB ) { + cardSTATE = SIM_ACKNOWLEDGE; + } else { + // Todo: + // - SLOT MARKER + // - ISO7816 + // - emulate with a memory dump + Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsReceived); + + // CRC Check + 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]) + DbpString("+++CRC fail"); + else + DbpString("CRC passes"); + } + cardSTATE = SIM_IDLE; + } break; + } + default: break; } ++cmdsReceived; @@ -776,7 +804,7 @@ 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 > 25*2) Demod.state = DEMOD_UNSYNCD; + if(Demod.posCount > 26*2) Demod.state = DEMOD_UNSYNCD; } ++Demod.posCount; break; @@ -788,7 +816,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { if(v > 0) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges - if(Demod.posCount < 9*2) { + if(Demod.posCount < 8*2) { Demod.state = DEMOD_UNSYNCD; } else { LED_C_ON(); // Got SOF @@ -799,7 +827,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { } } else { // low phase of SOF too long (> 12 etu) - if (Demod.posCount > 12*2) { + if (Demod.posCount > 14*2) { Demod.state = DEMOD_UNSYNCD; LED_C_OFF(); } @@ -812,7 +840,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { MAKE_SOFT_DECISION(); if (v > 0) { - if(Demod.posCount > 3*2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs + if(Demod.posCount > 2*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(); } @@ -904,7 +932,7 @@ static void GetTagSamplesFor14443bDemod() { // And put the FPGA in the appropriate mode FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ); - + while( !BUTTON_PRESS() ) { WDT_HIT(); @@ -963,29 +991,47 @@ static void GetTagSamplesFor14443bDemod() { //----------------------------------------------------------------------------- static void TransmitFor14443b_AsReader(void) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); - SpinDelay(20); - - int c; // we could been in following mode: // FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ // if its second call or more + + // while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + // AT91C_BASE_SSC->SSC_THR = 0XFF; + // } + + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); + SpinDelay(40); + int c; + volatile uint32_t b; + // What does this loop do? Is it TR1? - for(c = 0; c < 10;) { + // 0xFF = 8 bits of 1. 1 bit == 1Etu,.. + // loop 10 * 8 = 80 ETU of delay, with a non modulated signal. why? + // 80*9 = 720us. + for(c = 0; c < 50;) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0xFF; ++c; } + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + b = AT91C_BASE_SSC->SSC_RHR; + (void)b; + } } - + // Send frame loop for(c = 0; c < ToSendMax;) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = ToSend[c]; - ++c; + AT91C_BASE_SSC->SSC_THR = ToSend[c++]; } + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + b = AT91C_BASE_SSC->SSC_RHR; + (void)b; + } } + //WaitForFpgaDelayQueueIsEmpty(delay); + // We should wait here for the FPGA to send all bits. WDT_HIT(); } @@ -1005,6 +1051,9 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) * * 1 ETU == 1 BIT! * TR0 - 8 ETUS minimum. + * + * QUESTION: how long is a 1 or 0 in pulses in the xcorr_848 mode? + * 1 "stuffbit" = 1ETU (9us) */ int i; uint8_t b; @@ -1051,7 +1100,8 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) // Transition time. TR0 - guard time // 8ETUS minum? // Per specification, Subcarrier must be stopped no later than 2 ETUs after EOF. - for(i = 0; i < 40 ; ++i) ToSendStuffBit(1); + // I'm guessing this is for the FPGA to be able to send all bits before we switch to listening mode + for(i = 0; i < 32 ; ++i) ToSendStuffBit(1); // TR1 - Synchronization time // Convert from last character reference to length @@ -1219,12 +1269,13 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) return 3; // CID - if (card) card->cid = Demod.output[0]; - - uint8_t fwt = card->atqb[6]>>4; - if ( fwt < 16 ){ - uint32_t fwt_time = (302 << fwt); - iso14b_set_timeout( fwt_time); + if (card) { + card->cid = Demod.output[0]; + uint8_t fwt = card->atqb[6] >> 4; + if ( fwt < 16 ){ + uint32_t fwt_time = (302 << fwt); + iso14b_set_timeout( fwt_time); + } } // reset PCB block number pcb_blocknum = 0; @@ -1588,8 +1639,8 @@ void RAMFUNC SnoopIso14443b(void) { Dbprintf(" Trace length: %i", BigBuf_get_traceLen()); // free mem refs. - if ( dmaBuf ) dmaBuf = NULL; if ( upTo ) upTo = NULL; + // Uart.byteCntMax should be set with ATQB value.. }