X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/05ddb52c43f932db852e18fe6836bee71e91f74e..d9cc4e1ae29f3fdad933e631076efe9ac0ac4e70:/armsrc/iso14443a.c diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 0bd681d9..27574dad 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -213,6 +213,12 @@ void AppendCrc14443a(uint8_t* data, int len) ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1); } +void AppendCrc14443b(uint8_t* data, int len) +{ + ComputeCrc14443(CRC_14443_B,data,len,data+len,data+len+1); +} + + //============================================================================= // ISO 14443 Type A - Miller decoder //============================================================================= @@ -238,8 +244,6 @@ static tUart Uart; // 0111 - a 2 tick wide pause shifted left // 1001 - a 2 tick wide pause shifted right const bool Mod_Miller_LUT[] = { -// TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, -// TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }; @@ -279,8 +283,8 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111) // we therefore look for a ...xx11111111111100x11111xxxxxx... pattern // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's) -#define ISO14443A_STARTBIT_MASK 0x07FFEF80 // mask is 00000111 11111111 11101111 10000000 -#define ISO14443A_STARTBIT_PATTERN 0x07FF8F80 // pattern is 00000111 11111111 10001111 10000000 + #define ISO14443A_STARTBIT_MASK 0x07FFEF80 // mask is 00000111 11111111 11101111 10000000 + #define ISO14443A_STARTBIT_PATTERN 0x07FF8F80 // pattern is 00000111 11111111 10001111 10000000 if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 0)) == ISO14443A_STARTBIT_PATTERN >> 0) Uart.syncBit = 7; else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 1)) == ISO14443A_STARTBIT_PATTERN >> 1) Uart.syncBit = 6; else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 2)) == ISO14443A_STARTBIT_PATTERN >> 2) Uart.syncBit = 5; @@ -551,12 +555,8 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { LEDsoff(); - // We won't start recording the frames that we acquire until we trigger; - // a good trigger condition to get started is probably when we see a - // response from the tag. - // triggered == FALSE -- to wait first for card - bool triggered = !(param & 0x03); - + iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); + // Allocate memory from BigBuf for some buffers // free all previous allocations first BigBuf_free(); @@ -583,8 +583,6 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { bool TagIsActive = FALSE; bool ReaderIsActive = FALSE; - iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); - // Set up the demodulator for tag -> reader responses. DemodInit(receivedResponse, receivedResponsePar); @@ -594,6 +592,12 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { // Setup and start DMA. FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); + // We won't start recording the frames that we acquire until we trigger; + // a good trigger condition to get started is probably when we see a + // response from the tag. + // triggered == FALSE -- to wait first for card + bool triggered = !(param & 0x03); + // And now we loop, receiving samples. for(uint32_t rsamples = 0; TRUE; ) { @@ -655,7 +659,7 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { TRUE)) break; } /* And ready to receive another command. */ - UartInit(receivedCmd, receivedCmdPar); + UartReset(); /* And also reset the demod code, which might have been */ /* false-triggered by the commands from the reader. */ DemodReset(); @@ -680,6 +684,9 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { // And ready to receive another response. DemodReset(); + // And reset the Miller decoder including itS (now outdated) input buffer + UartInit(receivedCmd, receivedCmdPar); + LED_C_OFF(); } TagIsActive = (Demod.state != DEMOD_UNSYNCD); @@ -1026,6 +1033,9 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) .modulation_n = 0 }; + // We need to listen to the high-frequency, peak-detected path. + iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); + BigBuf_free_keep_EM(); // allocate buffers: @@ -1054,16 +1064,12 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) int happened2 = 0; int cmdsRecvd = 0; - // We need to listen to the high-frequency, peak-detected path. - iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); - cmdsRecvd = 0; tag_response_info_t* p_response; LED_A_ON(); for(;;) { // Clean receive command buffer - if(!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { DbpString("Button press"); break; @@ -1337,7 +1343,7 @@ void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8 } // Only transmit parity bit if we transmitted a complete byte - if (j == 8) { + if (j == 8 && parity != NULL) { // Get the parity bit if (parity[i>>3] & (0x80 >> (i&0x0007))) { // Sequence X @@ -1631,6 +1637,7 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive } } + void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t *timing) { CodeIso14443aBitsAsReaderPar(frame, bits, par); @@ -1646,11 +1653,13 @@ void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t } } + void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *timing) { ReaderTransmitBitsPar(frame, len*8, par, timing); } + void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing) { // Generate parity and redirect @@ -1659,6 +1668,7 @@ void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing) ReaderTransmitBitsPar(frame, len, par, timing); } + void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing) { // Generate parity and redirect @@ -1932,15 +1942,38 @@ void ReaderIso14443a(UsbCommand *c) if(param & ISO14A_RAW) { if(param & ISO14A_APPEND_CRC) { - AppendCrc14443a(cmd,len); + if(param & ISO14A_TOPAZMODE) { + AppendCrc14443b(cmd,len); + } else { + AppendCrc14443a(cmd,len); + } len += 2; if (lenbits) lenbits += 16; } - if(lenbits>0) { - GetParity(cmd, lenbits/8, par); - ReaderTransmitBitsPar(cmd, lenbits, par, NULL); - } else { - ReaderTransmit(cmd,len, NULL); + if(lenbits>0) { // want to send a specific number of bits (e.g. short commands) + if(param & ISO14A_TOPAZMODE) { + int bits_to_send = lenbits; + uint16_t i = 0; + ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 7), NULL, NULL); // first byte is always short (7bits) and no parity + bits_to_send -= 7; + while (bits_to_send > 0) { + ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 8), NULL, NULL); // following bytes are 8 bit and no parity + bits_to_send -= 8; + } + } else { + GetParity(cmd, lenbits/8, par); + ReaderTransmitBitsPar(cmd, lenbits, par, NULL); // bytes are 8 bit with odd parity + } + } else { // want to send complete bytes only + if(param & ISO14A_TOPAZMODE) { + uint16_t i = 0; + ReaderTransmitBitsPar(&cmd[i++], 7, NULL, NULL); // first byte: 7 bits, no paritiy + while (i < len) { + ReaderTransmitBitsPar(&cmd[i++], 8, NULL, NULL); // following bytes: 8 bits, no paritiy + } + } else { + ReaderTransmit(cmd,len, NULL); // 8 bits, odd parity + } } arg0 = ReaderReceive(buf, par); cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf)); @@ -1976,7 +2009,7 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) { nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i; nttmp2 = prng_successor(nttmp2, 1); - if (nttmp2 == nt1) return -i; + if (nttmp2 == nt1) return -i; } return(-99999); // either nt1 or nt2 are invalid nonces @@ -1999,6 +2032,10 @@ void ReaderMifare(bool first_try) uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; + if (first_try) { + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); + } + // free eventually allocated BigBuf memory. We want all for tracing. BigBuf_free(); @@ -2018,20 +2055,20 @@ void ReaderMifare(bool first_try) byte_t par_list[8] = {0x00}; byte_t ks_list[8] = {0x00}; + #define PRNG_SEQUENCE_LENGTH (1 << 16); static uint32_t sync_time; - static uint32_t sync_cycles; + static int32_t sync_cycles; int catch_up_cycles = 0; int last_catch_up = 0; + uint16_t elapsed_prng_sequences; uint16_t consecutive_resyncs = 0; int isOK = 0; if (first_try) { mf_nr_ar3 = 0; - iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); sync_time = GetCountSspClk() & 0xfffffff8; - sync_cycles = 65536; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). + sync_cycles = PRNG_SEQUENCE_LENGTH; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the tag nonces). nt_attacked = 0; - nt = 0; par[0] = 0; } else { @@ -2045,33 +2082,84 @@ void ReaderMifare(bool first_try) LED_B_OFF(); LED_C_OFF(); - + + #define MAX_UNEXPECTED_RANDOM 4 // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up. + #define MAX_SYNC_TRIES 32 + #define NUM_DEBUG_INFOS 8 // per strategy + #define MAX_STRATEGY 3 + uint16_t unexpected_random = 0; + uint16_t sync_tries = 0; + int16_t debug_info_nr = -1; + uint16_t strategy = 0; + int32_t debug_info[MAX_STRATEGY][NUM_DEBUG_INFOS]; + uint32_t select_time; + uint32_t halt_time; + for(uint16_t i = 0; TRUE; i++) { + LED_C_ON(); WDT_HIT(); // Test if the action was cancelled if(BUTTON_PRESS()) { + isOK = -1; break; } - LED_C_ON(); + if (strategy == 2) { + // test with additional hlt command + halt_time = 0; + int len = mifare_sendcmd_short(NULL, false, 0x50, 0x00, receivedAnswer, receivedAnswerPar, &halt_time); + if (len && MF_DBGLEVEL >= 3) { + Dbprintf("Unexpected response of %d bytes to hlt command (additional debugging).", len); + } + } + if (strategy == 3) { + // test with FPGA power off/on + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(200); + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); + SpinDelay(100); + } + if(!iso14443a_select_card(uid, NULL, &cuid)) { if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card"); continue; } + select_time = GetCountSspClk(); - sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles; - catch_up_cycles = 0; + elapsed_prng_sequences = 1; + if (debug_info_nr == -1) { + sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles; + catch_up_cycles = 0; - // if we missed the sync time already, advance to the next nonce repeat - while(GetCountSspClk() > sync_time) { - sync_time = (sync_time & 0xfffffff8) + sync_cycles; - } + // if we missed the sync time already, advance to the next nonce repeat + while(GetCountSspClk() > sync_time) { + elapsed_prng_sequences++; + sync_time = (sync_time & 0xfffffff8) + sync_cycles; + } - // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked) - ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time); + // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked) + ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time); + } else { + // collect some information on tag nonces for debugging: + #define DEBUG_FIXED_SYNC_CYCLES PRNG_SEQUENCE_LENGTH + if (strategy == 0) { + // nonce distances at fixed time after card select: + sync_time = select_time + DEBUG_FIXED_SYNC_CYCLES; + } else if (strategy == 1) { + // nonce distances at fixed time between authentications: + sync_time = sync_time + DEBUG_FIXED_SYNC_CYCLES; + } else if (strategy == 2) { + // nonce distances at fixed time after halt: + sync_time = halt_time + DEBUG_FIXED_SYNC_CYCLES; + } else { + // nonce_distances at fixed time after power on + sync_time = DEBUG_FIXED_SYNC_CYCLES; + } + ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time); + } // Receive the (4 Byte) "random" nonce if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) { @@ -2089,13 +2177,37 @@ void ReaderMifare(bool first_try) int nt_distance = dist_nt(previous_nt, nt); if (nt_distance == 0) { nt_attacked = nt; - } - else { - if (nt_distance == -99999) { // invalid nonce received, try again - continue; + } else { + if (nt_distance == -99999) { // invalid nonce received + unexpected_random++; + if (unexpected_random > MAX_UNEXPECTED_RANDOM) { + isOK = -3; // Card has an unpredictable PRNG. Give up + break; + } else { + continue; // continue trying... + } + } + if (++sync_tries > MAX_SYNC_TRIES) { + if (strategy > MAX_STRATEGY || MF_DBGLEVEL < 3) { + isOK = -4; // Card's PRNG runs at an unexpected frequency or resets unexpectedly + break; + } else { // continue for a while, just to collect some debug info + debug_info[strategy][debug_info_nr] = nt_distance; + debug_info_nr++; + if (debug_info_nr == NUM_DEBUG_INFOS) { + strategy++; + debug_info_nr = 0; + } + continue; + } + } + sync_cycles = (sync_cycles - nt_distance/elapsed_prng_sequences); + if (sync_cycles <= 0) { + sync_cycles += PRNG_SEQUENCE_LENGTH; + } + if (MF_DBGLEVEL >= 3) { + Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n", i, nt_distance, elapsed_prng_sequences, sync_cycles); } - sync_cycles = (sync_cycles - nt_distance); - if (MF_DBGLEVEL >= 3) Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles); continue; } } @@ -2106,6 +2218,7 @@ void ReaderMifare(bool first_try) catch_up_cycles = 0; continue; } + catch_up_cycles /= elapsed_prng_sequences; if (catch_up_cycles == last_catch_up) { consecutive_resyncs++; } @@ -2119,6 +2232,9 @@ void ReaderMifare(bool first_try) else { sync_cycles = sync_cycles + catch_up_cycles; if (MF_DBGLEVEL >= 3) Dbprintf("Lost sync in cycle %d for the fourth time consecutively (nt_distance = %d). Adjusting sync_cycles to %d.\n", i, -catch_up_cycles, sync_cycles); + last_catch_up = 0; + catch_up_cycles = 0; + consecutive_resyncs = 0; } continue; } @@ -2126,12 +2242,10 @@ void ReaderMifare(bool first_try) consecutive_resyncs = 0; // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding - if (ReaderReceive(receivedAnswer, receivedAnswerPar)) - { + if (ReaderReceive(receivedAnswer, receivedAnswerPar)) { catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer - if (nt_diff == 0) - { + if (nt_diff == 0) { par_low = par[0] & 0xE0; // there is no need to check all parities for other nt_diff. Parity Bits for mf_nr_ar[0..2] won't change } @@ -2154,6 +2268,10 @@ void ReaderMifare(bool first_try) if (nt_diff == 0 && first_try) { par[0]++; + if (par[0] == 0x00) { // tried all 256 possible parities without success. Card doesn't send NACK. + isOK = -2; + break; + } } else { par[0] = ((par[0] & 0x1F) + 1) | par_low; } @@ -2162,6 +2280,16 @@ void ReaderMifare(bool first_try) mf_nr_ar[3] &= 0x1F; + + if (isOK == -4) { + if (MF_DBGLEVEL >= 3) { + for (uint16_t i = 0; i <= MAX_STRATEGY; i++) { + for(uint16_t j = 0; j < NUM_DEBUG_INFOS; j++) { + Dbprintf("collected debug info[%d][%d] = %d", i, j, debug_info[i][j]); + } + } + } + } byte_t buf[28]; memcpy(buf + 0, uid, 4); @@ -2170,7 +2298,7 @@ void ReaderMifare(bool first_try) memcpy(buf + 16, ks_list, 8); memcpy(buf + 24, mf_nr_ar, 4); - cmd_send(CMD_ACK,isOK,0,0,buf,28); + cmd_send(CMD_ACK, isOK, 0, 0, buf, 28); // Thats it... FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -2231,13 +2359,6 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0}; uint8_t ar_nr_collected = 0; - // free eventually allocated BigBuf memory but keep Emulator Memory - BigBuf_free_keep_EM(); - - // clear trace - clear_trace(); - set_tracing(TRUE); - // Authenticate response - nonce uint32_t nonce = bytes_to_num(rAUTH_NT, 4); @@ -2275,13 +2396,10 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * if (_7BUID) { rATQA[0] = 0x44; rUIDBCC1[0] = 0x88; + rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; } - // We need to listen to the high-frequency, peak-detected path. - iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); - - if (MF_DBGLEVEL >= 1) { if (!_7BUID) { Dbprintf("4B UID: %02x%02x%02x%02x", @@ -2293,6 +2411,17 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } } + // We need to listen to the high-frequency, peak-detected path. + iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); + + // free eventually allocated BigBuf memory but keep Emulator Memory + BigBuf_free_keep_EM(); + + // clear trace + clear_trace(); + set_tracing(TRUE); + + bool finished = FALSE; while (!BUTTON_PRESS() && !finished) { WDT_HIT(); @@ -2514,13 +2643,13 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * || receivedCmd[0] == 0xB0) { // transfer if (receivedCmd[1] >= 16 * 4) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]); + if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]); break; } if (receivedCmd[1] / 4 != cardAUTHSC) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd[0],receivedCmd[1],cardAUTHSC); + if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd[0],receivedCmd[1],cardAUTHSC); break; } } @@ -2711,10 +2840,8 @@ void RAMFUNC SniffMifare(uint8_t param) { uint8_t receivedResponse[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedResponsePar[MAX_MIFARE_PARITY_SIZE]; - // As we receive stuff, we copy it from receivedCmd or receivedResponse - // into trace, along with its length and other annotations. - //uint8_t *trace = (uint8_t *)BigBuf; - + iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); + // free eventually allocated BigBuf memory BigBuf_free(); // allocate the DMA buffer, used to stream samples from the FPGA @@ -2726,8 +2853,6 @@ void RAMFUNC SniffMifare(uint8_t param) { bool ReaderIsActive = FALSE; bool TagIsActive = FALSE; - iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); - // Set up the demodulator for tag -> reader responses. DemodInit(receivedResponse, receivedResponsePar); @@ -2824,6 +2949,8 @@ void RAMFUNC SniffMifare(uint8_t param) { // And ready to receive another response. DemodReset(); + // And reset the Miller decoder including its (now outdated) input buffer + UartInit(receivedCmd, receivedCmdPar); } TagIsActive = (Demod.state != DEMOD_UNSYNCD); }