From: pwpiwi Date: Fri, 20 Oct 2017 15:55:13 +0000 (+0200) Subject: fix hf mf sim (issue #412) (#419) X-Git-Tag: v3.1.0~153 X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/6e49717b5e025b6ac7139b00f2f39d3b22b424a1 fix hf mf sim (issue #412) (#419) * move to separate files mifaresim.[ch] * check CRC of commands * don't execute commands without successfull authentication * ensure correct timing of REQA, WUPA, ANTICOL and SELECT responses * trace reader commands immediately, only fix start time after tag response. Decreases time to be ready for next reader command. * remove iso14443-4 remnants * trace raw reader commands instead of decrypted ones * some refactoring * fix hf mf sim * timing: decrease time to get ready for new reader commands --- diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index 8870f426..4fe97b46 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -136,6 +136,10 @@ void set_tracing(bool enable) { tracing = enable; } +bool get_tracing(void) { + return tracing; +} + /** * Get the number of bytes traced * @return diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index 6a052dca..05538044 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -37,6 +37,7 @@ extern void BigBuf_print_status(void); extern uint16_t BigBuf_get_traceLen(void); extern void clear_trace(void); extern void set_tracing(bool enable); +extern bool get_tracing(void); extern bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); extern int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader); extern uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length); diff --git a/armsrc/Makefile b/armsrc/Makefile index 861d98c6..dea5d06c 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -17,7 +17,7 @@ APP_CFLAGS = -DWITH_ISO14443a_StandAlone -DWITH_LF -DWITH_ISO15693 -DWITH_ISO144 #SRC_LCD = fonts.c LCD.c SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c protocols.c SRC_ISO15693 = iso15693.c iso15693tools.c -SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c +SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c mifaresim.c SRC_ISO14443b = iso14443b.c SRC_CRAPTO1 = crypto1.c des.c SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c parity.c diff --git a/armsrc/apps.h b/armsrc/apps.h index b0070148..542e6b90 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -99,14 +99,9 @@ void ReadSTMemoryIso14443b(uint32_t); void RAMFUNC SnoopIso14443b(void); void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]); -/// iso14443a.h -void RAMFUNC SnoopIso14443a(uint8_t param); -void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data); -void ReaderIso14443a(UsbCommand * c); // Also used in iclass.c bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *parity); -void iso14a_set_trigger(bool enable); void RAMFUNC SniffMifare(uint8_t param); @@ -115,8 +110,6 @@ void EPA_PACE_Collect_Nonce(UsbCommand * c); void EPA_PACE_Replay(UsbCommand *c); // mifarecmd.h -void ReaderMifare(bool first_try); -int32_t dist_nt(uint32_t nt1, uint32_t nt2); void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data); void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareUC_Auth(uint8_t arg0, uint8_t *datain); diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 32f9594b..f9aedc95 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -42,6 +42,7 @@ #include "string.h" #include "common.h" #include "cmd.h" +#include "iso14443a.h" // Needed for CRC in emulation mode; // same construction as in ISO 14443; // different initial value (CRC_ICLASS) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index e9ad2535..a3367036 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -132,13 +132,13 @@ uint16_t FpgaSendQueueDelay; #define DELAY_FPGA_QUEUE (FpgaSendQueueDelay<<1) // When the PM acts as tag and is sending, it takes -// 4*16 ticks until we can write data to the sending hold register +// 4*16 + 8 ticks until we can write data to the sending hold register // 8*16 ticks until the SHR is transferred to the Sending Shift Register -// 8 ticks until the first transfer starts -// 8 ticks later the FPGA samples the data -// + a varying number of ticks in the FPGA Delay Queue (mod_sig_buf) +// 8 ticks later the FPGA samples the first data +// + 16 ticks until assigned to mod_sig // + 1 tick to assign mod_sig_coil -#define DELAY_ARM2AIR_AS_TAG (4*16 + 8*16 + 8 + 8 + DELAY_FPGA_QUEUE + 1) +// + a varying number of ticks in the FPGA Delay Queue (mod_sig_buf) +#define DELAY_ARM2AIR_AS_TAG (4*16 + 8 + 8*16 + 8 + 16 + 1 + DELAY_FPGA_QUEUE) // When the PM acts as sniffer and is receiving tag data, it takes // 3 ticks A/D conversion @@ -185,13 +185,13 @@ void iso14a_set_trigger(bool enable) { } -void iso14a_set_timeout(uint32_t timeout) { +static void iso14a_set_timeout(uint32_t timeout) { iso14a_timeout = timeout; if(MF_DBGLEVEL >= 3) Dbprintf("ISO14443A Timeout set to %ld (%dms)", iso14a_timeout, iso14a_timeout / 106); } -void iso14a_set_ATS_timeout(uint8_t *ats) { +static void iso14a_set_ATS_timeout(uint8_t *ats) { uint8_t tb1; uint8_t fwi; @@ -246,7 +246,7 @@ 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) +static void AppendCrc14443b(uint8_t* data, int len) { ComputeCrc14443(CRC_14443_B,data,len,data+len,data+len+1); } @@ -283,7 +283,7 @@ const bool Mod_Miller_LUT[] = { #define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4]) #define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)]) -void UartReset() +static void UartReset() { Uart.state = STATE_UNSYNCD; Uart.bitCount = 0; @@ -295,7 +295,7 @@ void UartReset() Uart.endTime = 0; } -void UartInit(uint8_t *data, uint8_t *parity) +static void UartInit(uint8_t *data, uint8_t *parity) { Uart.output = data; Uart.parity = parity; @@ -455,7 +455,7 @@ const bool Mod_Manchester_LUT[] = { #define IsManchesterModulationNibble2(b) (Mod_Manchester_LUT[(b & 0x000F)]) -void DemodReset() +static void DemodReset() { Demod.state = DEMOD_UNSYNCD; Demod.len = 0; // number of decoded data bytes @@ -469,7 +469,7 @@ void DemodReset() Demod.endTime = 0; } -void DemodInit(uint8_t *data, uint8_t *parity) +static void DemodInit(uint8_t *data, uint8_t *parity) { Demod.output = data; Demod.parity = parity; @@ -793,14 +793,6 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par ToSendMax++; } -static void CodeIso14443aAsTag(const uint8_t *cmd, uint16_t len) -{ - uint8_t par[MAX_PARITY_SIZE]; - - GetParity(cmd, len, par); - CodeIso14443aAsTagPar(cmd, len, par); -} - static void Code4bitAnswerAsTag(uint8_t cmd) { @@ -840,6 +832,38 @@ static void Code4bitAnswerAsTag(uint8_t cmd) ToSendMax++; } + +static uint8_t *LastReaderTraceTime = NULL; + +static void EmLogTraceReader(void) { + // remember last reader trace start to fix timing info later + LastReaderTraceTime = BigBuf_get_addr() + BigBuf_get_traceLen(); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); +} + + +static void FixLastReaderTraceTime(uint32_t tag_StartTime) { + uint32_t reader_EndTime = Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG; + uint32_t reader_StartTime = Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG; + uint16_t reader_modlen = reader_EndTime - reader_StartTime; + uint16_t approx_fdt = tag_StartTime - reader_EndTime; + uint16_t exact_fdt = (approx_fdt - 20 + 32)/64 * 64 + 20; + reader_StartTime = tag_StartTime - exact_fdt - reader_modlen; + LastReaderTraceTime[0] = (reader_StartTime >> 0) & 0xff; + LastReaderTraceTime[1] = (reader_StartTime >> 8) & 0xff; + LastReaderTraceTime[2] = (reader_StartTime >> 16) & 0xff; + LastReaderTraceTime[3] = (reader_StartTime >> 24) & 0xff; +} + + +static void EmLogTraceTag(uint8_t *tag_data, uint16_t tag_len, uint8_t *tag_Parity, uint32_t ProxToAirDuration) { + uint32_t tag_StartTime = LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG; + uint32_t tag_EndTime = (LastTimeProxToAirStart + ProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG; + LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, false); + FixLastReaderTraceTime(tag_StartTime); +} + + //----------------------------------------------------------------------------- // Wait for commands from reader // Stop when button is pressed @@ -868,33 +892,22 @@ static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; if(MillerDecoding(b, 0)) { *len = Uart.len; + EmLogTraceReader(); return true; } } } } -static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNeeded); -int EmSend4bitEx(uint8_t resp, bool correctionNeeded); + +static int EmSend4bitEx(uint8_t resp, bool correctionNeeded); int EmSend4bit(uint8_t resp); -int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, bool correctionNeeded, uint8_t *par); +static int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, bool correctionNeeded, uint8_t *par); int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool correctionNeeded); -int EmSendCmd(uint8_t *resp, uint16_t respLen); -int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par); -bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, - uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity); +int EmSendPrecompiledCmd(tag_response_info_t *response_info, bool correctionNeeded); -static uint8_t* free_buffer_pointer; -typedef struct { - uint8_t* response; - size_t response_n; - uint8_t* modulation; - size_t modulation_n; - uint32_t ProxToAirDuration; -} tag_response_info_t; - -bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffer_size) { +static bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffer_size) { // Example response, answer to MIFARE Classic read block will be 16 bytes + 2 CRC = 18 bytes // This will need the following byte array for a modulation sequence // 144 data bits (18 * 8) @@ -908,17 +921,18 @@ bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffe // Prepare the tag modulation bits from the message - CodeIso14443aAsTag(response_info->response,response_info->response_n); + GetParity(response_info->response, response_info->response_n, &(response_info->par)); + CodeIso14443aAsTagPar(response_info->response,response_info->response_n, &(response_info->par)); // Make sure we do not exceed the free buffer space if (ToSendMax > max_buffer_size) { Dbprintf("Out of memory, when modulating bits for tag answer:"); - Dbhexdump(response_info->response_n,response_info->response,false); + Dbhexdump(response_info->response_n, response_info->response, false); return false; } // Copy the byte array, used for this modulation to the buffer position - memcpy(response_info->modulation,ToSend,ToSendMax); + memcpy(response_info->modulation, ToSend, ToSendMax); // Store the number of bytes that were used for encoding/modulation and the time needed to transfer them response_info->modulation_n = ToSendMax; @@ -930,21 +944,20 @@ bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffe // "precompile" responses. There are 7 predefined responses with a total of 28 bytes data to transmit. // Coded responses need one byte per bit to transfer (data, parity, start, stop, correction) -// 28 * 8 data bits, 28 * 1 parity bits, 7 start bits, 7 stop bits, 7 correction bits +// 28 * 8 data bits, 28 * 1 parity bits, 7 start bits, 7 stop bits, 7 correction bits for the modulation // -> need 273 bytes buffer #define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 273 -bool prepare_allocated_tag_modulation(tag_response_info_t* response_info) { +bool prepare_allocated_tag_modulation(tag_response_info_t* response_info, uint8_t **buffer, size_t *max_buffer_size) { + // Retrieve and store the current buffer index - response_info->modulation = free_buffer_pointer; - - // Determine the maximum size we can use from our buffer - size_t max_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE; + response_info->modulation = *buffer; // Forward the prepare tag modulation function to the inner function - if (prepare_tag_modulation(response_info, max_buffer_size)) { - // Update the free buffer offset - free_buffer_pointer += ToSendMax; + if (prepare_tag_modulation(response_info, *max_buffer_size)) { + // Update the free buffer offset and the remaining buffer size + *buffer += ToSendMax; + *max_buffer_size -= ToSendMax; return true; } else { return false; @@ -1074,8 +1087,8 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) // allocate buffers: uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE); - free_buffer_pointer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE); - + uint8_t *free_buffer_pointer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE); + size_t free_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE; // clear trace clear_trace(); set_tracing(true); @@ -1083,7 +1096,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) // Prepare the responses of the anticollision phase // there will be not enough time to do this at the moment the reader sends it REQA for (size_t i=0; imodulation, p_response->modulation_n, receivedCmd[0] == 0x52); - // do the tracing for the previous reader request and this tag answer: - uint8_t par[MAX_PARITY_SIZE]; - GetParity(p_response->response, p_response->response_n, par); - - EmLogTrace(Uart.output, - Uart.len, - Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.parity, - p_response->response, - p_response->response_n, - LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, - (LastTimeProxToAirStart + p_response->ProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, - par); + EmSendPrecompiledCmd(p_response, receivedCmd[0] == 0x52); } if (!tracing) { @@ -1262,7 +1248,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) // prepare a delayed transfer. This simply shifts ToSend[] by a number // of bits specified in the delay parameter. -void PrepareDelayedTransfer(uint16_t delay) +static void PrepareDelayedTransfer(uint16_t delay) { uint8_t bitmask = 0; uint8_t bits_to_shift = 0; @@ -1335,7 +1321,7 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing //----------------------------------------------------------------------------- // Prepare reader command (in bits, support short frames) to send to FPGA //----------------------------------------------------------------------------- -void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *parity) +static void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *parity) { int i, j; int last; @@ -1413,21 +1399,13 @@ void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8 ToSendMax++; } -//----------------------------------------------------------------------------- -// Prepare reader command to send to FPGA -//----------------------------------------------------------------------------- -void CodeIso14443aAsReaderPar(const uint8_t *cmd, uint16_t len, const uint8_t *parity) -{ - CodeIso14443aBitsAsReaderPar(cmd, len*8, parity); -} - //----------------------------------------------------------------------------- // Wait for commands from reader // Stop when button is pressed (return 1) or field was gone (return 2) // Or return 0 when command is captured //----------------------------------------------------------------------------- -static int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) +int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) { *len = 0; @@ -1485,6 +1463,7 @@ static int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; if(MillerDecoding(b, 0)) { *len = Uart.len; + EmLogTraceReader(); return 0; } } @@ -1497,7 +1476,6 @@ static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNe { uint8_t b; uint16_t i = 0; - uint32_t ThisTransferTime; // Modulate Manchester FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD); @@ -1525,10 +1503,7 @@ static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNe if (AT91C_BASE_SSC->SSC_RHR) break; } - while ((ThisTransferTime = GetCountSspClk()) & 0x00000007); - - // Clear TXRDY: - AT91C_BASE_SSC->SSC_THR = SEC_F; + LastTimeProxToAirStart = (GetCountSspClk() & 0xfffffff8) + (correctionNeeded?8:0); // send cycle for(; i < respLen; ) { @@ -1544,7 +1519,7 @@ static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNe // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again: uint8_t fpga_queued_bits = FpgaSendQueueDelay >> 3; - for (i = 0; i <= fpga_queued_bits/8 + 1; ) { + for (i = 0; i < fpga_queued_bits/8; ) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = SEC_F; FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR; @@ -1552,87 +1527,60 @@ static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNe } } - LastTimeProxToAirStart = ThisTransferTime + (correctionNeeded?8:0); - return 0; } -int EmSend4bitEx(uint8_t resp, bool correctionNeeded){ + +static int EmSend4bitEx(uint8_t resp, bool correctionNeeded){ Code4bitAnswerAsTag(resp); int res = EmSendCmd14443aRaw(ToSend, ToSendMax, correctionNeeded); // do the tracing for the previous reader request and this tag answer: - uint8_t par[1]; - GetParity(&resp, 1, par); - EmLogTrace(Uart.output, - Uart.len, - Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.parity, - &resp, - 1, - LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, - (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, - par); + EmLogTraceTag(&resp, 1, NULL, LastProxToAirDuration); return res; } + int EmSend4bit(uint8_t resp){ return EmSend4bitEx(resp, false); } -int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, bool correctionNeeded, uint8_t *par){ + +static int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, bool correctionNeeded, uint8_t *par){ CodeIso14443aAsTagPar(resp, respLen, par); int res = EmSendCmd14443aRaw(ToSend, ToSendMax, correctionNeeded); // do the tracing for the previous reader request and this tag answer: - EmLogTrace(Uart.output, - Uart.len, - Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.parity, - resp, - respLen, - LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, - (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, - par); + EmLogTraceTag(resp, respLen, par, LastProxToAirDuration); return res; } + int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool correctionNeeded){ uint8_t par[MAX_PARITY_SIZE]; GetParity(resp, respLen, par); return EmSendCmdExPar(resp, respLen, correctionNeeded, par); } + int EmSendCmd(uint8_t *resp, uint16_t respLen){ uint8_t par[MAX_PARITY_SIZE]; GetParity(resp, respLen, par); return EmSendCmdExPar(resp, respLen, false, par); } + int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par){ return EmSendCmdExPar(resp, respLen, false, par); } -bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, - uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity) -{ - if (tracing) { - // we cannot exactly measure the end and start of a received command from reader. However we know that the delay from - // end of the received command to start of the tag's (simulated by us) answer is n*128+20 or n*128+84 resp. - // with n >= 9. The start of the tags answer can be measured and therefore the end of the received command be calculated: - uint16_t reader_modlen = reader_EndTime - reader_StartTime; - uint16_t approx_fdt = tag_StartTime - reader_EndTime; - uint16_t exact_fdt = (approx_fdt - 20 + 32)/64 * 64 + 20; - reader_EndTime = tag_StartTime - exact_fdt; - reader_StartTime = reader_EndTime - reader_modlen; - if (!LogTrace(reader_data, reader_len, reader_StartTime, reader_EndTime, reader_Parity, true)) { - return false; - } else return(!LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, false)); - } else { - return true; - } + +int EmSendPrecompiledCmd(tag_response_info_t *response_info, bool correctionNeeded) { + int ret = EmSendCmd14443aRaw(response_info->modulation, response_info->modulation_n, correctionNeeded); + // do the tracing for the previous reader request and this tag answer: + EmLogTraceTag(response_info->response, response_info->response_n, &(response_info->par), response_info->ProxToAirDuration); + return ret; } + //----------------------------------------------------------------------------- // Wait a certain time for tag response // If a response is captured return true @@ -1693,7 +1641,7 @@ void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *tim } -void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing) +static void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing) { // Generate parity and redirect uint8_t par[MAX_PARITY_SIZE]; @@ -1710,7 +1658,8 @@ void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing) ReaderTransmitBitsPar(frame, len*8, par, timing); } -int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t *parity) + +static int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t *parity) { if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, offset)) return false; if (tracing) { @@ -1719,6 +1668,7 @@ int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t *parit return Demod.len; } + int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity) { if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, 0)) return false; @@ -1890,6 +1840,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u return 1; } + void iso14443a_setup(uint8_t fpga_minor_mode) { FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // Set up the synchronous serial port @@ -1912,9 +1863,10 @@ void iso14443a_setup(uint8_t fpga_minor_mode) { DemodReset(); UartReset(); NextTransferTime = 2*DELAY_ARM2AIR_AS_READER; - iso14a_set_timeout(1050); // 10ms default + iso14a_set_timeout(1060); // 10ms default } + int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) { uint8_t parity[MAX_PARITY_SIZE]; uint8_t real_cmd[cmd_len+4]; @@ -1943,6 +1895,7 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) { return len; } + //----------------------------------------------------------------------------- // Read an ISO 14443a tag. Send out commands and store answers. // @@ -2041,7 +1994,7 @@ void ReaderIso14443a(UsbCommand *c) // Determine the distance between two nonces. // Assume that the difference is small, but we don't know which is first. // Therefore try in alternating directions. -int32_t dist_nt(uint32_t nt1, uint32_t nt2) { +static int32_t dist_nt(uint32_t nt1, uint32_t nt2) { uint16_t i; uint32_t nttmp1, nttmp2; @@ -2353,696 +2306,6 @@ void ReaderMifare(bool first_try) set_tracing(false); } -/** - *MIFARE 1K simulate. - * - *@param flags : - * FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK - * FLAG_4B_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that - * FLAG_7B_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that - * FLAG_10B_UID_IN_DATA - use 10-byte UID in the data-section not finished - * FLAG_NR_AR_ATTACK - means we should collect NR_AR responses for bruteforcing later - * FLAG_RANDOM_NONCE - means we should generate some pseudo-random nonce data (only allows moebius attack) - *@param exitAfterNReads, exit simulation after n blocks have been read, 0 is infinite ... - * (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted) - */ -void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain) -{ - int cardSTATE = MFEMUL_NOFIELD; - int _UID_LEN = 0; // 4, 7, 10 - int vHf = 0; // in mV - int res; - uint32_t selTimer = 0; - uint32_t authTimer = 0; - uint16_t len = 0; - uint8_t cardWRBL = 0; - uint8_t cardAUTHSC = 0; - uint8_t cardAUTHKEY = 0xff; // no authentication - uint32_t cardRr = 0; - uint32_t cuid = 0; - //uint32_t rn_enc = 0; - uint32_t ans = 0; - uint32_t cardINTREG = 0; - uint8_t cardINTBLOCK = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - uint32_t numReads = 0;//Counts numer of times reader read a block - uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE]; - uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE]; - uint8_t response[MAX_MIFARE_FRAME_SIZE]; - uint8_t response_par[MAX_MIFARE_PARITY_SIZE]; - - uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID - uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; - uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!! - uint8_t rUIDBCC3[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; - - uint8_t rSAKfinal[]= {0x08, 0xb6, 0xdd}; // mifare 1k indicated - uint8_t rSAK1[] = {0x04, 0xda, 0x17}; // indicate UID not finished - - uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04}; - uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00}; - - //Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2 - // This will be used in the reader-only attack. - - //allow collecting up to 7 sets of nonces to allow recovery of up to 7 keys - #define ATTACK_KEY_COUNT 7 // keep same as define in cmdhfmf.c -> readerAttack() (Cannot be more than 7) - nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; //*2 for 2 separate attack types (nml, moebius) - memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp)); - - uint8_t ar_nr_collected[ATTACK_KEY_COUNT*2]; //*2 for 2nd attack type (moebius) - memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected)); - uint8_t nonce1_count = 0; - uint8_t nonce2_count = 0; - uint8_t moebius_n_count = 0; - bool gettingMoebius = false; - uint8_t mM = 0; //moebius_modifier for collection storage - - // Authenticate response - nonce - uint32_t nonce; - if (flags & FLAG_RANDOM_NONCE) { - nonce = prand(); - } else { - nonce = bytes_to_num(rAUTH_NT, 4); - } - - //-- Determine the UID - // Can be set from emulator memory, incoming data - // and can be 7 or 4 bytes long - if (flags & FLAG_4B_UID_IN_DATA) - { - // 4B uid comes from data-portion of packet - memcpy(rUIDBCC1,datain,4); - rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - _UID_LEN = 4; - } else if (flags & FLAG_7B_UID_IN_DATA) { - // 7B uid comes from data-portion of packet - memcpy(&rUIDBCC1[1],datain,3); - memcpy(rUIDBCC2, datain+3, 4); - _UID_LEN = 7; - } else if (flags & FLAG_10B_UID_IN_DATA) { - memcpy(&rUIDBCC1[1], datain, 3); - memcpy(&rUIDBCC2[1], datain+3, 3); - memcpy( rUIDBCC3, datain+6, 4); - _UID_LEN = 10; - } else { - // get UID from emul memory - guess at length - emlGetMemBt(receivedCmd, 7, 1); - if (receivedCmd[0] == 0x00) { // ---------- 4BUID - emlGetMemBt(rUIDBCC1, 0, 4); - _UID_LEN = 4; - } else { // ---------- 7BUID - emlGetMemBt(&rUIDBCC1[1], 0, 3); - emlGetMemBt(rUIDBCC2, 3, 4); - _UID_LEN = 7; - } - } - - switch (_UID_LEN) { - case 4: - // save CUID - cuid = bytes_to_num(rUIDBCC1, 4); - // BCC - rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - if (MF_DBGLEVEL >= 2) { - Dbprintf("4B UID: %02x%02x%02x%02x", - rUIDBCC1[0], - rUIDBCC1[1], - rUIDBCC1[2], - rUIDBCC1[3] - ); - } - break; - case 7: - rATQA[0] |= 0x40; - // save CUID - cuid = bytes_to_num(rUIDBCC2, 4); - // CascadeTag, CT - rUIDBCC1[0] = 0x88; - // BCC - rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; - if (MF_DBGLEVEL >= 2) { - Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x", - rUIDBCC1[1], - rUIDBCC1[2], - rUIDBCC1[3], - rUIDBCC2[0], - rUIDBCC2[1], - rUIDBCC2[2], - rUIDBCC2[3] - ); - } - break; - case 10: - rATQA[0] |= 0x80; - //sak_10[0] &= 0xFB; - // save CUID - cuid = bytes_to_num(rUIDBCC3, 4); - // CascadeTag, CT - rUIDBCC1[0] = 0x88; - rUIDBCC2[0] = 0x88; - // BCC - rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; - rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3]; - - if (MF_DBGLEVEL >= 2) { - Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", - rUIDBCC1[1], - rUIDBCC1[2], - rUIDBCC1[3], - rUIDBCC2[1], - rUIDBCC2[2], - rUIDBCC2[3], - rUIDBCC3[0], - rUIDBCC3[1], - rUIDBCC3[2], - rUIDBCC3[3] - ); - } - break; - default: - break; - } - - // 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; - bool button_pushed = BUTTON_PRESS(); - while (!button_pushed && !finished && !usb_poll_validate_length()) { - WDT_HIT(); - - // find reader field - if (cardSTATE == MFEMUL_NOFIELD) { - vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; - if (vHf > MF_MINFIELDV) { - cardSTATE_TO_IDLE(); - LED_A_ON(); - } - } - if (cardSTATE == MFEMUL_NOFIELD) { - button_pushed = BUTTON_PRESS(); - continue; - } - - //Now, get data - res = EmGetCmd(receivedCmd, &len, receivedCmd_par); - if (res == 2) { //Field is off! - cardSTATE = MFEMUL_NOFIELD; - LEDsoff(); - continue; - } else if (res == 1) { - break; //return value 1 means button press - } - - // REQ or WUP request in ANY state and WUP in HALTED state - if (len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) { - selTimer = GetTickCount(); - EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == ISO14443A_CMD_WUPA)); - cardSTATE = MFEMUL_SELECT1; - - // init crypto block - LED_B_OFF(); - LED_C_OFF(); - crypto1_destroy(pcs); - cardAUTHKEY = 0xff; - if (flags & FLAG_RANDOM_NONCE) { - nonce = prand(); - } - continue; - } - - switch (cardSTATE) { - case MFEMUL_NOFIELD: - case MFEMUL_HALTED: - case MFEMUL_IDLE:{ - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - case MFEMUL_SELECT1:{ - // select all - 0x93 0x20 - if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) { - if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL received"); - EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1)); - break; - } - - // select card - 0x93 0x70 ... - if (len == 9 && - (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) { - if (MF_DBGLEVEL >= 4) - Dbprintf("SELECT %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]); - - switch(_UID_LEN) { - case 4: - cardSTATE = MFEMUL_WORK; - LED_B_ON(); - if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer); - EmSendCmd(rSAKfinal, sizeof(rSAKfinal)); - break; - case 7: - cardSTATE = MFEMUL_SELECT2; - EmSendCmd(rSAK1, sizeof(rSAK1)); - break; - case 10: - cardSTATE = MFEMUL_SELECT2; - EmSendCmd(rSAK1, sizeof(rSAK1)); - break; - default:break; - } - } else { - cardSTATE_TO_IDLE(); - } - break; - } - case MFEMUL_SELECT3:{ - if (!len) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - // select all cl3 - 0x97 0x20 - if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && receivedCmd[1] == 0x20)) { - EmSendCmd(rUIDBCC3, sizeof(rUIDBCC3)); - break; - } - // select card cl3 - 0x97 0x70 - if (len == 9 && - (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && - receivedCmd[1] == 0x70 && - memcmp(&receivedCmd[2], rUIDBCC3, 4) == 0) ) { - - EmSendCmd(rSAKfinal, sizeof(rSAKfinal)); - cardSTATE = MFEMUL_WORK; - LED_B_ON(); - if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer); - break; - } - cardSTATE_TO_IDLE(); - break; - } - case MFEMUL_AUTH1:{ - if( len != 8) { - cardSTATE_TO_IDLE(); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - - uint32_t nr = bytes_to_num(receivedCmd, 4); - uint32_t ar = bytes_to_num(&receivedCmd[4], 4); - - // Collect AR/NR per keytype & sector - if(flags & FLAG_NR_AR_ATTACK) { - for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { - if ( ar_nr_collected[i+mM]==0 || ((cardAUTHSC == ar_nr_resp[i+mM].sector) && (cardAUTHKEY == ar_nr_resp[i+mM].keytype) && (ar_nr_collected[i+mM] > 0)) ) { - // if first auth for sector, or matches sector and keytype of previous auth - if (ar_nr_collected[i+mM] < 2) { - // if we haven't already collected 2 nonces for this sector - if (ar_nr_resp[ar_nr_collected[i+mM]].ar != ar) { - // Avoid duplicates... probably not necessary, ar should vary. - if (ar_nr_collected[i+mM]==0) { - // first nonce collect - ar_nr_resp[i+mM].cuid = cuid; - ar_nr_resp[i+mM].sector = cardAUTHSC; - ar_nr_resp[i+mM].keytype = cardAUTHKEY; - ar_nr_resp[i+mM].nonce = nonce; - ar_nr_resp[i+mM].nr = nr; - ar_nr_resp[i+mM].ar = ar; - nonce1_count++; - // add this nonce to first moebius nonce - ar_nr_resp[i+ATTACK_KEY_COUNT].cuid = cuid; - ar_nr_resp[i+ATTACK_KEY_COUNT].sector = cardAUTHSC; - ar_nr_resp[i+ATTACK_KEY_COUNT].keytype = cardAUTHKEY; - ar_nr_resp[i+ATTACK_KEY_COUNT].nonce = nonce; - ar_nr_resp[i+ATTACK_KEY_COUNT].nr = nr; - ar_nr_resp[i+ATTACK_KEY_COUNT].ar = ar; - ar_nr_collected[i+ATTACK_KEY_COUNT]++; - } else { // second nonce collect (std and moebius) - ar_nr_resp[i+mM].nonce2 = nonce; - ar_nr_resp[i+mM].nr2 = nr; - ar_nr_resp[i+mM].ar2 = ar; - if (!gettingMoebius) { - nonce2_count++; - // check if this was the last second nonce we need for std attack - if ( nonce2_count == nonce1_count ) { - // done collecting std test switch to moebius - // first finish incrementing last sample - ar_nr_collected[i+mM]++; - // switch to moebius collection - gettingMoebius = true; - mM = ATTACK_KEY_COUNT; - if (flags & FLAG_RANDOM_NONCE) { - nonce = prand(); - } else { - nonce = nonce*7; - } - break; - } - } else { - moebius_n_count++; - // if we've collected all the nonces we need - finish. - if (nonce1_count == moebius_n_count) finished = true; - } - } - ar_nr_collected[i+mM]++; - } - } - // we found right spot for this nonce stop looking - break; - } - } - } - - // --- crypto - crypto1_word(pcs, nr , 1); - cardRr = ar ^ crypto1_word(pcs, 0, 0); - - // test if auth OK - if (cardRr != prng_successor(nonce, 64)){ - if (MF_DBGLEVEL >= 2) Dbprintf("AUTH FAILED for sector %d with key %c. cardRr=%08x, succ=%08x", - cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B', - cardRr, prng_successor(nonce, 64)); - // Shouldn't we respond anything here? - // Right now, we don't nack or anything, which causes the - // reader to do a WUPA after a while. /Martin - // -- which is the correct response. /piwi - cardSTATE_TO_IDLE(); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - - //auth successful - ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0); - - num_to_bytes(ans, 4, rAUTH_AT); - // --- crypto - EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); - LED_C_ON(); - cardSTATE = MFEMUL_WORK; - if (MF_DBGLEVEL >= 4) Dbprintf("AUTH COMPLETED for sector %d with key %c. time=%d", - cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B', - GetTickCount() - authTimer); - break; - } - case MFEMUL_SELECT2:{ - if (!len) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - // select all cl2 - 0x95 0x20 - if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) { - EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2)); - break; - } - - // select cl2 card - 0x95 0x70 xxxxxxxxxxxx - if (len == 9 && - (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0)) { - switch(_UID_LEN) { - case 7: - EmSendCmd(rSAKfinal, sizeof(rSAKfinal)); - cardSTATE = MFEMUL_WORK; - LED_B_ON(); - if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer); - break; - case 10: - EmSendCmd(rSAK1, sizeof(rSAK1)); - cardSTATE = MFEMUL_SELECT3; - break; - default:break; - } - break; - } - - // i guess there is a command). go into the work state. - if (len != 4) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - cardSTATE = MFEMUL_WORK; - //goto lbWORK; - //intentional fall-through to the next case-stmt - } - - case MFEMUL_WORK:{ - if (len == 0) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - - bool encrypted_data = (cardAUTHKEY != 0xFF) ; - - if(encrypted_data) { - // decrypt seqence - mf_crypto1_decrypt(pcs, receivedCmd, len); - } - - if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) { - - // if authenticating to a block that shouldn't exist - as long as we are not doing the reader attack - if (receivedCmd[1] >= 16 * 4 && !(flags & FLAG_NR_AR_ATTACK)) { - //is this the correct response to an auth on a out of range block? marshmellow - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - 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; - } - - authTimer = GetTickCount(); - cardAUTHSC = receivedCmd[1] / 4; // received block num - cardAUTHKEY = receivedCmd[0] - 0x60; - crypto1_destroy(pcs);//Added by martin - crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY)); - //uint64_t key=emlGetKey(cardAUTHSC, cardAUTHKEY); - //Dbprintf("key: %04x%08x",(uint32_t)(key>>32)&0xFFFF,(uint32_t)(key&0xFFFFFFFF)); - - if (!encrypted_data) { // first authentication - if (MF_DBGLEVEL >= 4) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY ); - - crypto1_word(pcs, cuid ^ nonce, 0);//Update crypto state - num_to_bytes(nonce, 4, rAUTH_AT); // Send nonce - } else { // nested authentication - if (MF_DBGLEVEL >= 4) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY ); - ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); - num_to_bytes(ans, 4, rAUTH_AT); - } - - EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); - //Dbprintf("Sending rAUTH %02x%02x%02x%02x", rAUTH_AT[0],rAUTH_AT[1],rAUTH_AT[2],rAUTH_AT[3]); - cardSTATE = MFEMUL_AUTH1; - break; - } - - // rule 13 of 7.5.3. in ISO 14443-4. chaining shall be continued - // BUT... ACK --> NACK - if (len == 1 && receivedCmd[0] == CARD_ACK) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - break; - } - - // rule 12 of 7.5.3. in ISO 14443-4. R(NAK) --> R(ACK) - if (len == 1 && receivedCmd[0] == CARD_NACK_NA) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); - break; - } - - if(len != 4) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - - if(receivedCmd[0] == 0x30 // read block - || receivedCmd[0] == 0xA0 // write block - || receivedCmd[0] == 0xC0 // inc - || receivedCmd[0] == 0xC1 // dec - || receivedCmd[0] == 0xC2 // restore - || 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%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%02x) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd[0],receivedCmd[1],cardAUTHSC); - break; - } - } - // read block - if (receivedCmd[0] == 0x30) { - if (MF_DBGLEVEL >= 4) { - Dbprintf("Reader reading block %d (0x%02x)",receivedCmd[1],receivedCmd[1]); - } - emlGetMem(response, receivedCmd[1], 1); - AppendCrc14443a(response, 16); - mf_crypto1_encrypt(pcs, response, 18, response_par); - EmSendCmdPar(response, 18, response_par); - numReads++; - if(exitAfterNReads > 0 && numReads == exitAfterNReads) { - Dbprintf("%d reads done, exiting", numReads); - finished = true; - } - break; - } - // write block - if (receivedCmd[0] == 0xA0) { - if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0xA0 write block %d (%02x)",receivedCmd[1],receivedCmd[1]); - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); - cardSTATE = MFEMUL_WRITEBL2; - cardWRBL = receivedCmd[1]; - break; - } - // increment, decrement, restore - if (receivedCmd[0] == 0xC0 || receivedCmd[0] == 0xC1 || receivedCmd[0] == 0xC2) { - if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd[0],receivedCmd[1],receivedCmd[1]); - if (emlCheckValBl(receivedCmd[1])) { - if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking"); - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - break; - } - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); - if (receivedCmd[0] == 0xC1) - cardSTATE = MFEMUL_INTREG_INC; - if (receivedCmd[0] == 0xC0) - cardSTATE = MFEMUL_INTREG_DEC; - if (receivedCmd[0] == 0xC2) - cardSTATE = MFEMUL_INTREG_REST; - cardWRBL = receivedCmd[1]; - break; - } - // transfer - if (receivedCmd[0] == 0xB0) { - if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x transfer block %d (%02x)",receivedCmd[0],receivedCmd[1],receivedCmd[1]); - if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd[1])) - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - else - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); - break; - } - // halt - if (receivedCmd[0] == 0x50 && receivedCmd[1] == 0x00) { - LED_B_OFF(); - LED_C_OFF(); - cardSTATE = MFEMUL_HALTED; - if (MF_DBGLEVEL >= 4) Dbprintf("--> HALTED. Selected time: %d ms", GetTickCount() - selTimer); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - // RATS - if (receivedCmd[0] == 0xe0) {//RATS - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - break; - } - // command not allowed - if (MF_DBGLEVEL >= 4) Dbprintf("Received command not allowed, nacking"); - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - break; - } - case MFEMUL_WRITEBL2:{ - if (len == 18){ - mf_crypto1_decrypt(pcs, receivedCmd, len); - emlSetMem(receivedCmd, cardWRBL, 1); - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); - cardSTATE = MFEMUL_WORK; - } else { - cardSTATE_TO_IDLE(); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - } - break; - } - - case MFEMUL_INTREG_INC:{ - mf_crypto1_decrypt(pcs, receivedCmd, len); - memcpy(&ans, receivedCmd, 4); - if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - cardSTATE_TO_IDLE(); - break; - } - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - cardINTREG = cardINTREG + ans; - cardSTATE = MFEMUL_WORK; - break; - } - case MFEMUL_INTREG_DEC:{ - mf_crypto1_decrypt(pcs, receivedCmd, len); - memcpy(&ans, receivedCmd, 4); - if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - cardSTATE_TO_IDLE(); - break; - } - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - cardINTREG = cardINTREG - ans; - cardSTATE = MFEMUL_WORK; - break; - } - case MFEMUL_INTREG_REST:{ - mf_crypto1_decrypt(pcs, receivedCmd, len); - memcpy(&ans, receivedCmd, 4); - if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - cardSTATE_TO_IDLE(); - break; - } - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - cardSTATE = MFEMUL_WORK; - break; - } - } - button_pushed = BUTTON_PRESS(); - } - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - - if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) { - for ( uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { - if (ar_nr_collected[i] == 2) { - Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); - - if(flags & FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK - //Send the collected ar_nr in the response - cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,button_pushed,0,&ar_nr_resp,sizeof(ar_nr_resp)); - } -} - //----------------------------------------------------------------------------- // MIFARE sniffer. diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 9977a658..8bd80510 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -15,15 +15,38 @@ #include #include +#include "usb_cmd.h" #include "mifare.h" +typedef struct { + uint8_t* response; + uint8_t* modulation; + uint16_t response_n; + uint16_t modulation_n; + uint32_t ProxToAirDuration; + uint8_t par; // enough for precalculated parity of 8 Byte responses +} tag_response_info_t; + extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); extern void AppendCrc14443a(uint8_t *data, int len); +extern void RAMFUNC SnoopIso14443a(uint8_t param); +extern void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t *data); +extern void ReaderIso14443a(UsbCommand *c); extern void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing); extern void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing); extern void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing); extern int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par); +extern void ReaderMifare(bool first_try); + +extern int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity); +extern int EmSendCmd(uint8_t *resp, uint16_t respLen); +extern int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool correctionNeeded); +extern int EmSend4bit(uint8_t resp); +extern int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par); +extern int EmSendPrecompiledCmd(tag_response_info_t *response_info, bool correctionNeeded); + +extern bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *buffer_size); extern void iso14443a_setup(uint8_t fpga_minor_mode); extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data); diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c new file mode 100644 index 00000000..91f45efd --- /dev/null +++ b/armsrc/mifaresim.c @@ -0,0 +1,620 @@ +//----------------------------------------------------------------------------- +// Merlok - June 2011, 2012 +// Gerhard de Koning Gans - May 2008 +// Hagen Fritsch - June 2010 +// +// 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 +// the license. +//----------------------------------------------------------------------------- +// Mifare Classic Card Simulation +//----------------------------------------------------------------------------- + +#include "mifaresim.h" +#include "iso14443a.h" +#include "iso14443crc.h" +#include "crapto1/crapto1.h" +#include "BigBuf.h" +#include "string.h" +#include "mifareutil.h" +#include "fpgaloader.h" +#include "proxmark3.h" +#include "usb_cdc.h" +#include "cmd.h" +#include "protocols.h" +#include "apps.h" + +//mifare emulator states +#define MFEMUL_NOFIELD 0 +#define MFEMUL_IDLE 1 +#define MFEMUL_SELECT1 2 +#define MFEMUL_SELECT2 3 +#define MFEMUL_SELECT3 4 +#define MFEMUL_AUTH1 5 +#define MFEMUL_AUTH2 6 +#define MFEMUL_WORK 7 +#define MFEMUL_WRITEBL2 8 +#define MFEMUL_INTREG_INC 9 +#define MFEMUL_INTREG_DEC 10 +#define MFEMUL_INTREG_REST 11 +#define MFEMUL_HALTED 12 + +#define cardSTATE_TO_IDLE() { cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF(); } + + + +static void MifareSimInit(uint8_t flags, uint8_t *datain, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len) { + + #define TAG_RESPONSE_COUNT 5 // number of precompiled responses + static uint8_t rATQA[] = {0x04, 0x00}; // indicate Mifare classic 1k 4Byte UID + static uint8_t rUIDBCC1[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 1st cascade level + static uint8_t rUIDBCC2[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 2nd cascade level + static uint8_t rSAKfinal[]= {0x08, 0xb6, 0xdd}; // mifare 1k indicated + static uint8_t rSAK1[] = {0x04, 0xda, 0x17}; // indicate UID not finished + + *uid_len = 4; + // UID can be set from emulator memory or incoming data and can be 4 or 7 bytes long + if (flags & FLAG_4B_UID_IN_DATA) { // get UID from datain + memcpy(rUIDBCC1, datain, 4); + } else if (flags & FLAG_7B_UID_IN_DATA) { + rUIDBCC1[0] = 0x88; + memcpy(rUIDBCC1+1, datain, 3); + memcpy(rUIDBCC2, datain+3, 4); + *uid_len = 7; + } else { + uint8_t probable_atqa; + emlGetMemBt(&probable_atqa, 7, 1); // get UID from emul memory - weak guess at length + if (probable_atqa == 0x00) { // ---------- 4BUID + emlGetMemBt(rUIDBCC1, 0, 4); + } else { // ---------- 7BUID + rUIDBCC1[0] = 0x88; + emlGetMemBt(rUIDBCC1+1, 0, 3); + emlGetMemBt(rUIDBCC2, 3, 4); + *uid_len = 7; + } + } + + switch (*uid_len) { + case 4: + *cuid = bytes_to_num(rUIDBCC1, 4); + rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; + if (MF_DBGLEVEL >= 2) { + Dbprintf("4B UID: %02x%02x%02x%02x", + rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3] ); + } + break; + case 7: + rATQA[0] |= 0x40; + *cuid = bytes_to_num(rUIDBCC2, 4); + rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; + rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; + if (MF_DBGLEVEL >= 2) { + Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x", + rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3] ); + } + break; + default: + break; + } + + static tag_response_info_t responses_init[TAG_RESPONSE_COUNT] = { + { .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type + { .response = rUIDBCC1, .response_n = sizeof(rUIDBCC1) }, // Anticollision cascade1 - respond with first part of uid + { .response = rUIDBCC2, .response_n = sizeof(rUIDBCC2) }, // Anticollision cascade2 - respond with 2nd part of uid + { .response = rSAKfinal, .response_n = sizeof(rSAKfinal) }, // Acknowledge select - last cascade + { .response = rSAK1, .response_n = sizeof(rSAK1) } // Acknowledge select - previous cascades + }; + + // Prepare ("precompile") the responses of the anticollision phase. There will be not enough time to do this at the moment the reader sends its REQA or SELECT + // There are 7 predefined responses with a total of 18 bytes data to transmit. Coded responses need one byte per bit to transfer (data, parity, start, stop, correction) + // 18 * 8 data bits, 18 * 1 parity bits, 5 start bits, 5 stop bits, 5 correction bits -> need 177 bytes buffer + #define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 177 // number of bytes required for precompiled responses + + uint8_t *free_buffer_pointer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE); + size_t free_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE; + for (size_t i = 0; i < TAG_RESPONSE_COUNT; i++) { + prepare_allocated_tag_modulation(&responses_init[i], &free_buffer_pointer, &free_buffer_size); + } + + *responses = responses_init; + + // indices into responses array: + #define ATQA 0 + #define UIDBCC1 1 + #define UIDBCC2 2 + #define SAKfinal 3 + #define SAK1 4 + +} + + +static bool HasValidCRC(uint8_t *receivedCmd, uint16_t receivedCmd_len) { + uint8_t CRC_byte_1, CRC_byte_2; + ComputeCrc14443(CRC_14443_A, receivedCmd, receivedCmd_len-2, &CRC_byte_1, &CRC_byte_2); + return (receivedCmd[receivedCmd_len-2] == CRC_byte_1 && receivedCmd[receivedCmd_len-1] == CRC_byte_2); +} + + +/** + *MIFARE 1K simulate. + * + *@param flags : + * FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK + * FLAG_4B_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that + * FLAG_7B_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that + * FLAG_10B_UID_IN_DATA - use 10-byte UID in the data-section not finished + * FLAG_NR_AR_ATTACK - means we should collect NR_AR responses for bruteforcing later + * FLAG_RANDOM_NONCE - means we should generate some pseudo-random nonce data (only allows moebius attack) + *@param exitAfterNReads, exit simulation after n blocks have been read, 0 is infinite ... + * (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted) + */ +void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain) +{ + tag_response_info_t *responses; + uint8_t uid_len = 4; + uint32_t cuid = 0; + uint8_t cardWRBL = 0; + uint8_t cardAUTHSC = 0; + uint8_t cardAUTHKEY = 0xff; // no authentication + uint32_t cardRr = 0; + //uint32_t rn_enc = 0; + uint32_t ans = 0; + uint32_t cardINTREG = 0; + uint8_t cardINTBLOCK = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + uint32_t numReads = 0;//Counts numer of times reader reads a block + uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE]; + uint8_t receivedCmd_dec[MAX_MIFARE_FRAME_SIZE]; + uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE]; + uint16_t receivedCmd_len; + uint8_t response[MAX_MIFARE_FRAME_SIZE]; + uint8_t response_par[MAX_MIFARE_PARITY_SIZE]; + + uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00}; + + //Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2 + // This will be used in the reader-only attack. + + //allow collecting up to 7 sets of nonces to allow recovery of up to 7 keys + #define ATTACK_KEY_COUNT 7 // keep same as define in cmdhfmf.c -> readerAttack() (Cannot be more than 7) + nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; //*2 for 2 separate attack types (nml, moebius) 36 * 7 * 2 bytes = 504 bytes + memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp)); + + uint8_t ar_nr_collected[ATTACK_KEY_COUNT*2]; //*2 for 2nd attack type (moebius) + memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected)); + uint8_t nonce1_count = 0; + uint8_t nonce2_count = 0; + uint8_t moebius_n_count = 0; + bool gettingMoebius = false; + uint8_t mM = 0; //moebius_modifier for collection storage + + // Authenticate response - nonce + uint32_t nonce; + if (flags & FLAG_RANDOM_NONCE) { + nonce = prand(); + } else { + nonce = bytes_to_num(rAUTH_NT, 4); + } + + // free eventually allocated BigBuf memory but keep Emulator Memory + BigBuf_free_keep_EM(); + + MifareSimInit(flags, datain, &responses, &cuid, &uid_len); + + // We need to listen to the high-frequency, peak-detected path. + iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); + + // clear trace + clear_trace(); + set_tracing(true); + ResetSspClk(); + + bool finished = false; + bool button_pushed = BUTTON_PRESS(); + int cardSTATE = MFEMUL_NOFIELD; + + while (!button_pushed && !finished && !usb_poll_validate_length()) { + WDT_HIT(); + + // find reader field + if (cardSTATE == MFEMUL_NOFIELD) { + int vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; + if (vHf > MF_MINFIELDV) { + LED_A_ON(); + cardSTATE_TO_IDLE(); + } + button_pushed = BUTTON_PRESS(); + continue; + } + + //Now, get data + int res = EmGetCmd(receivedCmd, &receivedCmd_len, receivedCmd_par); + + if (res == 2) { //Field is off! + LEDsoff(); + cardSTATE = MFEMUL_NOFIELD; + continue; + } else if (res == 1) { // button pressed + button_pushed = true; + break; + } + + // WUPA in HALTED state or REQA or WUPA in any other state + if (receivedCmd_len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) { + EmSendPrecompiledCmd(&responses[ATQA], (receivedCmd[0] == ISO14443A_CMD_WUPA)); + + // init crypto block + crypto1_destroy(pcs); + cardAUTHKEY = 0xff; + if (flags & FLAG_RANDOM_NONCE) { + nonce = prand(); + } + LED_B_OFF(); + LED_C_OFF(); + cardSTATE = MFEMUL_SELECT1; + continue; + } + + switch (cardSTATE) { + case MFEMUL_NOFIELD: + case MFEMUL_HALTED: + case MFEMUL_IDLE:{ + break; + } + case MFEMUL_SELECT1:{ + // select all - 0x93 0x20 + if (receivedCmd_len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) { + if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL CL1 received"); + EmSendPrecompiledCmd(&responses[UIDBCC1], false); + break; + } + // select card - 0x93 0x70 ... + if (receivedCmd_len == 9 && + (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], responses[UIDBCC1].response, 4) == 0)) { + if (MF_DBGLEVEL >= 4) Dbprintf("SELECT CL1 %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]); + if (uid_len == 4) { + EmSendPrecompiledCmd(&responses[SAKfinal], false); + LED_B_ON(); + cardSTATE = MFEMUL_WORK; + break; + } else if (uid_len == 7) { + EmSendPrecompiledCmd(&responses[SAK1], false); + cardSTATE = MFEMUL_SELECT2; + break; + } + } + cardSTATE_TO_IDLE(); + break; + } + case MFEMUL_SELECT2:{ + // select all cl2 - 0x95 0x20 + if (receivedCmd_len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) { + if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL CL2 received"); + EmSendPrecompiledCmd(&responses[UIDBCC2], false); + break; + } + // select cl2 card - 0x95 0x70 xxxxxxxxxxxx + if (receivedCmd_len == 9 && + (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], responses[UIDBCC2].response, 4) == 0)) { + if (uid_len == 7) { + if (MF_DBGLEVEL >= 4) Dbprintf("SELECT CL2 %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]); + EmSendPrecompiledCmd(&responses[SAKfinal], false); + LED_B_ON(); + cardSTATE = MFEMUL_WORK; + break; + } + } + cardSTATE_TO_IDLE(); + break; + } + case MFEMUL_WORK:{ + if (receivedCmd_len != 4) { // all commands must have exactly 4 bytes + break; + } + bool encrypted_data = (cardAUTHKEY != 0xFF) ; + if (encrypted_data) { + // decrypt seqence + mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec); + } else { + memcpy(receivedCmd_dec, receivedCmd, receivedCmd_len); + } + if (!HasValidCRC(receivedCmd_dec, receivedCmd_len)) { // all commands must have a valid CRC + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + break; + } + if (receivedCmd_dec[0] == MIFARE_AUTH_KEYA || receivedCmd_dec[0] == MIFARE_AUTH_KEYB) { + // if authenticating to a block that shouldn't exist - as long as we are not doing the reader attack + if (receivedCmd_dec[1] >= 16 * 4 && !(flags & FLAG_NR_AR_ATTACK)) { + //is this the correct response to an auth on a out of range block? marshmellow + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking",receivedCmd_dec[0],receivedCmd_dec[1],receivedCmd_dec[1]); + break; + } + cardAUTHSC = receivedCmd_dec[1] / 4; // received block num + cardAUTHKEY = receivedCmd_dec[0] & 0x01; + crypto1_destroy(pcs);//Added by martin + crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY)); + if (!encrypted_data) { // first authentication + if (MF_DBGLEVEL >= 4) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d",receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY); + crypto1_word(pcs, cuid ^ nonce, 0);//Update crypto state + num_to_bytes(nonce, 4, rAUTH_AT); // Send nonce + } else { // nested authentication + if (MF_DBGLEVEL >= 4) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY); + ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); + num_to_bytes(ans, 4, rAUTH_AT); + } + EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); + cardSTATE = MFEMUL_AUTH1; + break; + } + if (!encrypted_data) { // all other commands must be encrypted (authenticated) + break; + } + if(receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK + || receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK + || receivedCmd_dec[0] == MIFARE_CMD_INC + || receivedCmd_dec[0] == MIFARE_CMD_DEC + || receivedCmd_dec[0] == MIFARE_CMD_RESTORE + || receivedCmd_dec[0] == MIFARE_CMD_TRANSFER) { + if (receivedCmd_dec[1] >= 16 * 4) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking",receivedCmd_dec[0],receivedCmd_dec[1],receivedCmd_dec[1]); + break; + } + if (receivedCmd_dec[1] / 4 != cardAUTHSC) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd_dec[0],receivedCmd_dec[1],cardAUTHSC); + break; + } + } + if (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK) { + if (MF_DBGLEVEL >= 4) { + Dbprintf("Reader reading block %d (0x%02x)",receivedCmd_dec[1],receivedCmd_dec[1]); + } + emlGetMem(response, receivedCmd_dec[1], 1); + AppendCrc14443a(response, 16); + mf_crypto1_encrypt(pcs, response, 18, response_par); + EmSendCmdPar(response, 18, response_par); + numReads++; + if(exitAfterNReads > 0 && numReads == exitAfterNReads) { + Dbprintf("%d reads done, exiting", numReads); + finished = true; + } + break; + } + if (receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK) { + if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0xA0 write block %d (%02x)",receivedCmd_dec[1],receivedCmd_dec[1]); + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + cardWRBL = receivedCmd_dec[1]; + cardSTATE = MFEMUL_WRITEBL2; + break; + } + if (receivedCmd_dec[0] == MIFARE_CMD_INC || receivedCmd_dec[0] == MIFARE_CMD_DEC || receivedCmd_dec[0] == MIFARE_CMD_RESTORE) { + if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd_dec[0],receivedCmd_dec[1],receivedCmd_dec[1]); + if (emlCheckValBl(receivedCmd_dec[1])) { + if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking"); + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + break; + } + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + cardWRBL = receivedCmd_dec[1]; + if (receivedCmd_dec[0] == MIFARE_CMD_INC) + cardSTATE = MFEMUL_INTREG_INC; + if (receivedCmd_dec[0] == MIFARE_CMD_DEC) + cardSTATE = MFEMUL_INTREG_DEC; + if (receivedCmd_dec[0] == MIFARE_CMD_RESTORE) + cardSTATE = MFEMUL_INTREG_REST; + break; + } + if (receivedCmd_dec[0] == MIFARE_CMD_TRANSFER) { + if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x transfer block %d (%02x)",receivedCmd_dec[0],receivedCmd_dec[1],receivedCmd_dec[1]); + if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd_dec[1])) + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + else + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + break; + } + // halt + if (receivedCmd_dec[0] == ISO14443A_CMD_HALT && receivedCmd_dec[1] == 0x00) { + if (MF_DBGLEVEL >= 4) Dbprintf("--> HALTED."); + LED_B_OFF(); + LED_C_OFF(); + cardSTATE = MFEMUL_HALTED; + break; + } + // command not allowed + if (MF_DBGLEVEL >= 4) Dbprintf("Received command not allowed, nacking"); + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + break; + } + case MFEMUL_AUTH1:{ + if (receivedCmd_len != 8) { + cardSTATE_TO_IDLE(); + break; + } + + uint32_t nr = bytes_to_num(receivedCmd, 4); + uint32_t ar = bytes_to_num(&receivedCmd[4], 4); + + // Collect AR/NR per keytype & sector + if(flags & FLAG_NR_AR_ATTACK) { + for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { + if ( ar_nr_collected[i+mM]==0 || ((cardAUTHSC == ar_nr_resp[i+mM].sector) && (cardAUTHKEY == ar_nr_resp[i+mM].keytype) && (ar_nr_collected[i+mM] > 0)) ) { + // if first auth for sector, or matches sector and keytype of previous auth + if (ar_nr_collected[i+mM] < 2) { + // if we haven't already collected 2 nonces for this sector + if (ar_nr_resp[ar_nr_collected[i+mM]].ar != ar) { + // Avoid duplicates... probably not necessary, ar should vary. + if (ar_nr_collected[i+mM]==0) { + // first nonce collect + ar_nr_resp[i+mM].cuid = cuid; + ar_nr_resp[i+mM].sector = cardAUTHSC; + ar_nr_resp[i+mM].keytype = cardAUTHKEY; + ar_nr_resp[i+mM].nonce = nonce; + ar_nr_resp[i+mM].nr = nr; + ar_nr_resp[i+mM].ar = ar; + nonce1_count++; + // add this nonce to first moebius nonce + ar_nr_resp[i+ATTACK_KEY_COUNT].cuid = cuid; + ar_nr_resp[i+ATTACK_KEY_COUNT].sector = cardAUTHSC; + ar_nr_resp[i+ATTACK_KEY_COUNT].keytype = cardAUTHKEY; + ar_nr_resp[i+ATTACK_KEY_COUNT].nonce = nonce; + ar_nr_resp[i+ATTACK_KEY_COUNT].nr = nr; + ar_nr_resp[i+ATTACK_KEY_COUNT].ar = ar; + ar_nr_collected[i+ATTACK_KEY_COUNT]++; + } else { // second nonce collect (std and moebius) + ar_nr_resp[i+mM].nonce2 = nonce; + ar_nr_resp[i+mM].nr2 = nr; + ar_nr_resp[i+mM].ar2 = ar; + if (!gettingMoebius) { + nonce2_count++; + // check if this was the last second nonce we need for std attack + if ( nonce2_count == nonce1_count ) { + // done collecting std test switch to moebius + // first finish incrementing last sample + ar_nr_collected[i+mM]++; + // switch to moebius collection + gettingMoebius = true; + mM = ATTACK_KEY_COUNT; + if (flags & FLAG_RANDOM_NONCE) { + nonce = prand(); + } else { + nonce = nonce*7; + } + break; + } + } else { + moebius_n_count++; + // if we've collected all the nonces we need - finish. + if (nonce1_count == moebius_n_count) finished = true; + } + } + ar_nr_collected[i+mM]++; + } + } + // we found right spot for this nonce stop looking + break; + } + } + } + + // --- crypto + crypto1_word(pcs, nr , 1); + cardRr = ar ^ crypto1_word(pcs, 0, 0); + + // test if auth OK + if (cardRr != prng_successor(nonce, 64)){ + if (MF_DBGLEVEL >= 2) Dbprintf("AUTH FAILED for sector %d with key %c. cardRr=%08x, succ=%08x", + cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B', + cardRr, prng_successor(nonce, 64)); + // Shouldn't we respond anything here? + // Right now, we don't nack or anything, which causes the + // reader to do a WUPA after a while. /Martin + // -- which is the correct response. /piwi + cardAUTHKEY = 0xff; // not authenticated + cardSTATE_TO_IDLE(); + break; + } + ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0); + num_to_bytes(ans, 4, rAUTH_AT); + EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); + if (MF_DBGLEVEL >= 4) Dbprintf("AUTH COMPLETED for sector %d with key %c.", cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B'); + LED_C_ON(); + cardSTATE = MFEMUL_WORK; + break; + } + case MFEMUL_WRITEBL2:{ + if (receivedCmd_len == 18) { + mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec); + if (HasValidCRC(receivedCmd_dec, receivedCmd_len)) { + emlSetMem(receivedCmd_dec, cardWRBL, 1); + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + cardSTATE = MFEMUL_WORK; + break; + } + } + cardSTATE_TO_IDLE(); + break; + } + case MFEMUL_INTREG_INC:{ + if (receivedCmd_len == 6) { + mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t*)&ans); + if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + cardSTATE_TO_IDLE(); + break; + } + cardINTREG = cardINTREG + ans; + } + cardSTATE = MFEMUL_WORK; + break; + } + case MFEMUL_INTREG_DEC:{ + if (receivedCmd_len == 6) { + mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t*)&ans); + if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + cardSTATE_TO_IDLE(); + break; + } + } + cardINTREG = cardINTREG - ans; + cardSTATE = MFEMUL_WORK; + break; + } + case MFEMUL_INTREG_REST:{ + mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t*)&ans); + if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + cardSTATE_TO_IDLE(); + break; + } + cardSTATE = MFEMUL_WORK; + break; + } + } + button_pushed = BUTTON_PRESS(); + } + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + + if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) { + for ( uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { + if (ar_nr_collected[i] == 2) { + Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen()); + + if(flags & FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK + //Send the collected ar_nr in the response + cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,button_pushed,0,&ar_nr_resp,sizeof(ar_nr_resp)); + } +} diff --git a/armsrc/mifaresim.h b/armsrc/mifaresim.h new file mode 100644 index 00000000..1e17a882 --- /dev/null +++ b/armsrc/mifaresim.h @@ -0,0 +1,20 @@ +//----------------------------------------------------------------------------- +// Merlok - June 2011, 2012 +// Gerhard de Koning Gans - May 2008 +// Hagen Fritsch - June 2010 +// +// 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 +// the license. +//----------------------------------------------------------------------------- +// Mifare Classic Card Simulation +//----------------------------------------------------------------------------- + +#ifndef __MIFARESIM_H +#define __MIFARESIM_H + +#include + +extern void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain); + +#endif diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 97f7b3d1..e5ef6c19 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -24,23 +24,27 @@ int MF_DBGLEVEL = MF_DBG_ALL; // crypto1 helpers -void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){ +void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out){ uint8_t bt = 0; int i; if (len != 1) { for (i = 0; i < len; i++) - data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i]; + data_out[i] = crypto1_byte(pcs, 0x00, 0) ^ data_in[i]; } else { bt = 0; for (i = 0; i < 4; i++) - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data[0], i)) << i; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], i)) << i; - data[0] = bt; + data_out[0] = bt; } return; } +void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){ + mf_crypto1_decryptEx(pcs, data, len, data); +} + void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par) { uint8_t bt = 0; int i; diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 8ffd5e89..645d0e7d 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -41,23 +41,6 @@ extern int MF_DBGLEVEL; -//mifare emulator states -#define MFEMUL_NOFIELD 0 -#define MFEMUL_IDLE 1 -#define MFEMUL_SELECT1 2 -#define MFEMUL_SELECT2 3 -#define MFEMUL_SELECT3 4 -#define MFEMUL_AUTH1 5 -#define MFEMUL_AUTH2 6 -#define MFEMUL_WORK 7 -#define MFEMUL_WRITEBL2 8 -#define MFEMUL_INTREG_INC 9 -#define MFEMUL_INTREG_DEC 10 -#define MFEMUL_INTREG_REST 11 -#define MFEMUL_HALTED 12 - -#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF(); - //functions int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); @@ -85,6 +68,7 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData); // crypto functions void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len); +void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out); void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par); uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data);