From: marshmellow42 Date: Mon, 29 Dec 2014 21:14:23 +0000 (-0500) Subject: Merge pull request #1 from Proxmark/master X-Git-Tag: v2.0.0-rc1~75^2~6 X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/6bfa18eab4750123d0e24090597b0d4c7bd58daf?hp=2df8c07907a07068d717d9b4ddcc2848f4efd608 Merge pull request #1 from Proxmark/master Test --- diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 8347bed9..57c485e8 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -36,7 +36,8 @@ // is the order in which they go out on the wire. //============================================================================= -uint8_t ToSend[512]; +#define TOSEND_BUFFER_SIZE (9*MAX_FRAME_SIZE + 1 + 1 + 2) // 8 data bits and 1 parity bit per payload byte, 1 correction bit, 1 SOC bit, 2 EOC bits +uint8_t ToSend[TOSEND_BUFFER_SIZE]; int ToSendMax; static int ToSendBit; struct common_area common_area __attribute__((section(".commonarea"))); @@ -67,7 +68,7 @@ void ToSendStuffBit(int b) ToSendBit++; - if(ToSendBit >= sizeof(ToSend)) { + if(ToSendMax >= sizeof(ToSend)) { ToSendBit = 0; DbpString("ToSendStuffBit overflowed!"); } @@ -195,15 +196,11 @@ int AvgAdc(int ch) // was static - merlok void MeasureAntennaTuning(void) { - uint8_t *dest = (uint8_t *)BigBuf+FREE_BUFFER_OFFSET; + uint8_t LF_Results[256]; int i, adcval = 0, peak = 0, peakv = 0, peakf = 0; //ptr = 0 int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV -// UsbCommand c; - - LED_B_ON(); - DbpString("Measuring antenna characteristics, please wait..."); - memset(dest,0,FREE_BUFFER_SIZE); + LED_B_ON(); /* * Sweeps the useful LF range of the proxmark from @@ -216,7 +213,7 @@ void MeasureAntennaTuning(void) FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - for (i=255; i>19; i--) { + for (i=255; i>=19; i--) { WDT_HIT(); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i); SpinDelay(20); @@ -226,16 +223,18 @@ void MeasureAntennaTuning(void) if (i==95) vLf125 = adcval; // voltage at 125Khz if (i==89) vLf134 = adcval; // voltage at 134Khz - dest[i] = adcval>>8; // scale int to fit in byte for graphing purposes - if(dest[i] > peak) { + LF_Results[i] = adcval>>8; // scale int to fit in byte for graphing purposes + if(LF_Results[i] > peak) { peakv = adcval; - peak = dest[i]; + peak = LF_Results[i]; peakf = i; //ptr = i; } } - LED_A_ON(); + for (i=18; i >= 0; i--) LF_Results[i] = 0; + + LED_A_ON(); // Let the FPGA drive the high-frequency antenna around 13.56 MHz. FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); @@ -244,18 +243,11 @@ void MeasureAntennaTuning(void) // can measure voltages up to 33000 mV vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10; -// c.cmd = CMD_MEASURED_ANTENNA_TUNING; -// c.arg[0] = (vLf125 << 0) | (vLf134 << 16); -// c.arg[1] = vHf; -// c.arg[2] = peakf | (peakv << 16); - - DbpString("Measuring complete, sending report back to host"); - cmd_send(CMD_MEASURED_ANTENNA_TUNING,vLf125|(vLf134<<16),vHf,peakf|(peakv<<16),0,0); -// UsbSendPacket((uint8_t *)&c, sizeof(c)); + cmd_send(CMD_MEASURED_ANTENNA_TUNING,vLf125|(vLf134<<16),vHf,peakf|(peakv<<16),LF_Results,256); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_A_OFF(); - LED_B_OFF(); - return; + LED_A_OFF(); + LED_B_OFF(); + return; } void MeasureAntennaTuningHf(void) diff --git a/armsrc/apps.h b/armsrc/apps.h index ee9fea74..ed51c7b9 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -20,18 +20,22 @@ // The large multi-purpose buffer, typically used to hold A/D samples, // maybe processed in some way. -uint32_t BigBuf[10000]; -// BIG CHANGE - UNDERSTAND THIS BEFORE WE COMMIT -#define TRACE_OFFSET 0 -#define TRACE_SIZE 3000 -#define RECV_CMD_OFFSET 3032 -#define RECV_CMD_SIZE 64 -#define RECV_RES_OFFSET 3096 -#define RECV_RES_SIZE 64 -#define DMA_BUFFER_OFFSET 3160 -#define DMA_BUFFER_SIZE 4096 -#define FREE_BUFFER_OFFSET 7256 -#define FREE_BUFFER_SIZE 2744 +#define BIGBUF_SIZE 40000 +uint32_t BigBuf[BIGBUF_SIZE / sizeof(uint32_t)]; +#define TRACE_OFFSET 0 +#define TRACE_SIZE 3000 +#define RECV_CMD_OFFSET (TRACE_OFFSET + TRACE_SIZE) +#define MAX_FRAME_SIZE 256 +#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 1)/ 8) +#define RECV_CMD_PAR_OFFSET (RECV_CMD_OFFSET + MAX_FRAME_SIZE) +#define RECV_RESP_OFFSET (RECV_CMD_PAR_OFFSET + MAX_PARITY_SIZE) +#define RECV_RESP_PAR_OFFSET (RECV_RESP_OFFSET + MAX_FRAME_SIZE) +#define CARD_MEMORY_OFFSET (RECV_RESP_PAR_OFFSET + MAX_PARITY_SIZE) +#define CARD_MEMORY_SIZE 4096 +#define DMA_BUFFER_OFFSET CARD_MEMORY_OFFSET +#define DMA_BUFFER_SIZE CARD_MEMORY_SIZE +#define FREE_BUFFER_OFFSET (CARD_MEMORY_OFFSET + CARD_MEMORY_SIZE) +#define FREE_BUFFER_SIZE (BIGBUF_SIZE - FREE_BUFFER_OFFSET - 1) extern const uint8_t OddByteParity[256]; extern uint8_t *trace; // = (uint8_t *) BigBuf; @@ -158,8 +162,8 @@ 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, uint8_t iLen, uint32_t iSamples, uint32_t dwParity, bool readerToTag); -uint32_t GetParity(const uint8_t * pbtCmd, int iLen); +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 iso14a_clear_trace(); void iso14a_set_tracing(bool enable); diff --git a/armsrc/epa.c b/armsrc/epa.c index b1f0a187..fb19656d 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -108,9 +108,9 @@ size_t EPA_Parse_CardAccess(uint8_t *data, if (data[index] == 0x31 || data[index] == 0x30) { // enter the set (skip tag + length) index += 2; - // extended length + // check for extended length if ((data[index - 1] & 0x80) != 0) { - index += (data[index] & 0x7F); + index += (data[index-1] & 0x7F); } } // OID @@ -434,7 +434,8 @@ int EPA_Setup() // send the PPS request ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL); uint8_t pps_response[3]; - return_code = ReaderReceive(pps_response); + uint8_t pps_response_par[1]; + return_code = ReaderReceive(pps_response, pps_response_par); if (return_code != 3 || pps_response[0] != 0xD0) { return return_code == 0 ? 2 : return_code; } diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 0ee1b355..28bdb3bc 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -71,14 +71,13 @@ static struct { int nOutOfCnt; int OutOfCnt; int syncBit; - int parityBits; int samples; int highCnt; int swapper; int counter; int bitBuffer; int dropPosition; - uint8_t *output; + uint8_t *output; } Uart; static RAMFUNC int OutOfNDecoding(int bit) @@ -137,11 +136,8 @@ static RAMFUNC int OutOfNDecoding(int bit) if(Uart.byteCnt == 0) { // Its not straightforward to show single EOFs // So just leave it and do not return TRUE - Uart.output[Uart.byteCnt] = 0xf0; + Uart.output[0] = 0xf0; Uart.byteCnt++; - - // Calculate the parity bit for the client... - Uart.parityBits = 1; } else { return TRUE; @@ -223,11 +219,6 @@ static RAMFUNC int OutOfNDecoding(int bit) if(Uart.bitCnt == 8) { Uart.output[Uart.byteCnt] = (Uart.shiftReg & 0xff); Uart.byteCnt++; - - // Calculate the parity bit for the client... - Uart.parityBits <<= 1; - Uart.parityBits ^= OddByteParity[(Uart.shiftReg & 0xff)]; - Uart.bitCnt = 0; Uart.shiftReg = 0; } @@ -246,11 +237,6 @@ static RAMFUNC int OutOfNDecoding(int bit) Uart.dropPosition--; Uart.output[Uart.byteCnt] = (Uart.dropPosition & 0xff); Uart.byteCnt++; - - // Calculate the parity bit for the client... - Uart.parityBits <<= 1; - Uart.parityBits ^= OddByteParity[(Uart.dropPosition & 0xff)]; - Uart.bitCnt = 0; Uart.shiftReg = 0; Uart.nOutOfCnt = 0; @@ -311,7 +297,6 @@ static RAMFUNC int OutOfNDecoding(int bit) Uart.state = STATE_START_OF_COMMUNICATION; Uart.bitCnt = 0; Uart.byteCnt = 0; - Uart.parityBits = 0; Uart.nOutOfCnt = 0; Uart.OutOfCnt = 4; // Start at 1/4, could switch to 1/256 Uart.dropPosition = 0; @@ -353,7 +338,6 @@ static struct { int bitCount; int posCount; int syncBit; - int parityBits; uint16_t shiftReg; int buffer; int buffer2; @@ -367,7 +351,7 @@ static struct { SUB_SECOND_HALF, SUB_BOTH } sub; - uint8_t *output; + uint8_t *output; } Demod; static RAMFUNC int ManchesterDecoding(int v) @@ -420,7 +404,6 @@ static RAMFUNC int ManchesterDecoding(int v) Demod.sub = SUB_FIRST_HALF; Demod.bitCount = 0; Demod.shiftReg = 0; - Demod.parityBits = 0; Demod.samples = 0; if(Demod.posCount) { //if(trigger) LED_A_OFF(); // Not useful in this case... @@ -485,8 +468,6 @@ static RAMFUNC int ManchesterDecoding(int v) if(Demod.state == DEMOD_SOF_COMPLETE) { Demod.output[Demod.len] = 0x0f; Demod.len++; - Demod.parityBits <<= 1; - Demod.parityBits ^= OddByteParity[0x0f]; Demod.state = DEMOD_UNSYNCD; // error = 0x0f; return TRUE; @@ -567,11 +548,9 @@ static RAMFUNC int ManchesterDecoding(int v) // Tag response does not need to be a complete byte! if(Demod.len > 0 || Demod.bitCount > 0) { if(Demod.bitCount > 1) { // was > 0, do not interpret last closing bit, is part of EOF - Demod.shiftReg >>= (9 - Demod.bitCount); + Demod.shiftReg >>= (9 - Demod.bitCount); // right align data Demod.output[Demod.len] = Demod.shiftReg & 0xff; Demod.len++; - // No parity bit, so just shift a 0 - Demod.parityBits <<= 1; } Demod.state = DEMOD_UNSYNCD; @@ -608,11 +587,6 @@ static RAMFUNC int ManchesterDecoding(int v) Demod.shiftReg >>= 1; Demod.output[Demod.len] = (Demod.shiftReg & 0xff); Demod.len++; - - // FOR ISO15639 PARITY NOT SEND OTA, JUST CALCULATE IT FOR THE CLIENT - Demod.parityBits <<= 1; - Demod.parityBits ^= OddByteParity[(Demod.shiftReg & 0xff)]; - Demod.bitCount = 0; Demod.shiftReg = 0; } @@ -669,8 +643,8 @@ void RAMFUNC SnoopIClass(void) // So 32 should be enough! uint8_t *readerToTagCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET); // The response (tag -> reader) that we're receiving. - uint8_t *tagToReaderResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET); - + uint8_t *tagToReaderResponse = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // reset traceLen to 0 @@ -769,10 +743,10 @@ void RAMFUNC SnoopIClass(void) //if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,TRUE)) break; //if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, TRUE)) break; - if(tracing) - { - LogTrace(Uart.output,Uart.byteCnt, (GetCountSspClk()-time_0) << 4, Uart.parityBits,TRUE); - LogTrace(NULL, 0, (GetCountSspClk()-time_0) << 4, 0, TRUE); + if(tracing) { + uint8_t parity[MAX_PARITY_SIZE]; + GetParity(Uart.output, Uart.byteCnt, parity); + LogTrace(Uart.output,Uart.byteCnt, (GetCountSspClk()-time_0) << 4, (GetCountSspClk()-time_0) << 4, parity, TRUE); } @@ -793,10 +767,10 @@ void RAMFUNC SnoopIClass(void) rsamples = samples - Demod.samples; LED_B_ON(); - if(tracing) - { - LogTrace(Demod.output,Demod.len, (GetCountSspClk()-time_0) << 4 , Demod.parityBits,FALSE); - LogTrace(NULL, 0, (GetCountSspClk()-time_0) << 4, 0, FALSE); + if(tracing) { + uint8_t parity[MAX_PARITY_SIZE]; + GetParity(Demod.output, Demod.len, parity); + LogTrace(Demod.output, Demod.len, (GetCountSspClk()-time_0) << 4, (GetCountSspClk()-time_0) << 4, parity, FALSE); } @@ -994,7 +968,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain { uint8_t mac_responses[64] = { 0 }; - Dbprintf("Going into attack mode"); + Dbprintf("Going into attack mode, %d CSNS sent", numberOfCSNS); // In this mode, a number of csns are within datain. We'll simulate each one, one at a time // in order to collect MAC's from the reader. This can later be used in an offlne-attack // in order to obtain the keys, as in the "dismantling iclass"-paper. @@ -1004,7 +978,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain // The usb data is 512 bytes, fitting 65 8-byte CSNs in there. memcpy(csn_crc, datain+(i*8), 8); - if(doIClassSimulation(csn_crc,1,mac_responses)) + if(doIClassSimulation(csn_crc,1,mac_responses+i*8)) { return; // Button pressed } @@ -1079,7 +1053,7 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader // + 1720.. uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET); - memset(receivedCmd, 0x44, RECV_CMD_SIZE); + memset(receivedCmd, 0x44, MAX_FRAME_SIZE); int len; // Prepare card messages @@ -1132,7 +1106,6 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader //Signal tracer // Can be used to get a trigger for an oscilloscope.. LED_C_OFF(); - if(!GetIClassCommandFromReader(receivedCmd, &len, 100)) { buttonPressed = true; break; @@ -1175,9 +1148,10 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader respsize = 0; if (breakAfterMacReceived){ // dbprintf:ing ... - Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x",csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]); + Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x" + ,csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]); Dbprintf("RDR: (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x",len, - receivedCmd[0], receivedCmd[1], receivedCmd[2], + receivedCmd[0], receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5], receivedCmd[6], receivedCmd[7], receivedCmd[8]); if (reader_mac_buf != NULL) @@ -1219,14 +1193,13 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader } if (tracing) { - LogTrace(receivedCmd,len, (r2t_time-time_0)<< 4, Uart.parityBits,TRUE); - LogTrace(NULL,0, (r2t_time-time_0) << 4, 0,TRUE); + uint8_t parity[MAX_PARITY_SIZE]; + GetParity(receivedCmd, len, parity); + LogTrace(receivedCmd,len, (r2t_time-time_0)<< 4, (r2t_time-time_0) << 4, parity, TRUE); if (respdata != NULL) { - LogTrace(respdata,respsize, (t2r_time-time_0) << 4,SwapBits(GetParity(respdata,respsize),respsize),FALSE); - LogTrace(NULL,0, (t2r_time-time_0) << 4,0,FALSE); - - + GetParity(respdata, respsize, parity); + LogTrace(respdata, respsize, (t2r_time-time_0) << 4, (t2r_time-time_0) << 4, parity, FALSE); } if(!tracing) { DbpString("Trace full"); @@ -1234,7 +1207,7 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader } } - memset(receivedCmd, 0x44, RECV_CMD_SIZE); + memset(receivedCmd, 0x44, MAX_FRAME_SIZE); } //Dbprintf("%x", cmdsRecvd); @@ -1391,21 +1364,24 @@ void CodeIClassCommand(const uint8_t * cmd, int len) void ReaderTransmitIClass(uint8_t* frame, int len) { - int wait = 0; - int samples = 0; - int par = 0; - - // This is tied to other size changes - // uint8_t* frame_addr = ((uint8_t*)BigBuf) + 2024; - CodeIClassCommand(frame,len); - - // Select the card - TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait); - if(trigger) - LED_A_ON(); - - // Store reader command in buffer - if (tracing) LogTrace(frame,len,rsamples,par,TRUE); + int wait = 0; + int samples = 0; + + // This is tied to other size changes + // uint8_t* frame_addr = ((uint8_t*)BigBuf) + 2024; + CodeIClassCommand(frame,len); + + // Select the card + TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait); + if(trigger) + LED_A_ON(); + + // Store reader command in buffer + if (tracing) { + uint8_t par[MAX_PARITY_SIZE]; + GetParity(frame, len, par); + LogTrace(frame, len, rsamples, rsamples, par, TRUE); + } } //----------------------------------------------------------------------------- @@ -1464,7 +1440,11 @@ int ReaderReceiveIClass(uint8_t* receivedAnswer) int samples = 0; if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return FALSE; rsamples += samples; - if (tracing) LogTrace(receivedAnswer,Demod.len,rsamples,Demod.parityBits,FALSE); + if (tracing) { + uint8_t parity[MAX_PARITY_SIZE]; + GetParity(receivedAnswer, Demod.len, parity); + LogTrace(receivedAnswer,Demod.len,rsamples,rsamples,parity,FALSE); + } if(samples == 0) return FALSE; return Demod.len; } @@ -1504,8 +1484,8 @@ void ReaderIClass(uint8_t arg0) { uint8_t card_data[24]={0}; uint8_t last_csn[8]={0}; - uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes - + uint8_t *resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET); + int read_status= 0; bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; @@ -1595,8 +1575,8 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { int keyaccess; } memory; - uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes - + uint8_t* resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET); + setupIclassReader(); @@ -1714,7 +1694,7 @@ void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_ uint16_t crc = 0; - uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes + uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // Reset trace buffer memset(trace, 0x44, RECV_CMD_OFFSET); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 01cf2486..a4632aa5 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -104,9 +104,9 @@ uint16_t FpgaSendQueueDelay; //variables used for timing purposes: //these are in ssp_clk cycles: -uint32_t NextTransferTime; -uint32_t LastTimeProxToAirStart; -uint32_t LastProxToAirDuration; +static uint32_t NextTransferTime; +static uint32_t LastTimeProxToAirStart; +static uint32_t LastProxToAirDuration; @@ -171,17 +171,28 @@ byte_t oddparity (const byte_t bt) return OddByteParity[bt]; } -uint32_t GetParity(const uint8_t * pbtCmd, int iLen) +void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par) { - int i; - uint32_t dwPar = 0; - - // Generate the parity bits - for (i = 0; i < iLen; i++) { - // and save them to a 32Bit word - dwPar |= ((OddByteParity[pbtCmd[i]]) << i); + uint16_t paritybit_cnt = 0; + uint16_t paritybyte_cnt = 0; + uint8_t parityBits = 0; + + for (uint16_t i = 0; i < iLen; i++) { + // Generate the parity bits + parityBits |= ((OddByteParity[pbtCmd[i]]) << (7-paritybit_cnt)); + if (paritybit_cnt == 7) { + par[paritybyte_cnt] = parityBits; // save 8 Bits parity + parityBits = 0; // and advance to next Parity Byte + paritybyte_cnt++; + paritybit_cnt = 0; + } else { + paritybit_cnt++; + } } - return dwPar; + + // save remaining parity bits + par[paritybyte_cnt] = parityBits; + } void AppendCrc14443a(uint8_t* data, int len) @@ -190,33 +201,57 @@ void AppendCrc14443a(uint8_t* data, int len) } // The function LogTrace() is also used by the iClass implementation in iClass.c -bool RAMFUNC LogTrace(const uint8_t * btBytes, uint8_t iLen, uint32_t timestamp, uint32_t dwParity, bool readerToTag) +bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag) { if (!tracing) return FALSE; + + uint16_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity + uint16_t duration = timestamp_end - timestamp_start; + // Return when trace is full - if (traceLen + sizeof(timestamp) + sizeof(dwParity) + iLen >= TRACE_SIZE) { + if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= TRACE_SIZE) { tracing = FALSE; // don't trace any more return FALSE; } - // Trace the random, i'm curious - trace[traceLen++] = ((timestamp >> 0) & 0xff); - trace[traceLen++] = ((timestamp >> 8) & 0xff); - trace[traceLen++] = ((timestamp >> 16) & 0xff); - trace[traceLen++] = ((timestamp >> 24) & 0xff); + // Traceformat: + // 32 bits timestamp (little endian) + // 16 bits duration (little endian) + // 16 bits data length (little endian, Highest Bit used as readerToTag flag) + // y Bytes data + // x Bytes parity (one byte per 8 bytes data) + + // timestamp (start) + trace[traceLen++] = ((timestamp_start >> 0) & 0xff); + trace[traceLen++] = ((timestamp_start >> 8) & 0xff); + trace[traceLen++] = ((timestamp_start >> 16) & 0xff); + trace[traceLen++] = ((timestamp_start >> 24) & 0xff); + + // duration + trace[traceLen++] = ((duration >> 0) & 0xff); + trace[traceLen++] = ((duration >> 8) & 0xff); + + // data length + trace[traceLen++] = ((iLen >> 0) & 0xff); + trace[traceLen++] = ((iLen >> 8) & 0xff); + // readerToTag flag if (!readerToTag) { trace[traceLen - 1] |= 0x80; } - trace[traceLen++] = ((dwParity >> 0) & 0xff); - trace[traceLen++] = ((dwParity >> 8) & 0xff); - trace[traceLen++] = ((dwParity >> 16) & 0xff); - trace[traceLen++] = ((dwParity >> 24) & 0xff); - trace[traceLen++] = iLen; + + // data bytes if (btBytes != NULL && iLen != 0) { memcpy(trace + traceLen, btBytes, iLen); } traceLen += iLen; + + // parity bytes + if (parity != NULL && iLen != 0) { + memcpy(trace + traceLen, parity, num_paritybytes); + } + traceLen += num_paritybytes; + return TRUE; } @@ -252,14 +287,21 @@ void UartReset() Uart.state = STATE_UNSYNCD; Uart.bitCount = 0; Uart.len = 0; // number of decoded data bytes + Uart.parityLen = 0; // number of decoded parity bytes Uart.shiftReg = 0; // shiftreg to hold decoded data bits - Uart.parityBits = 0; // + Uart.parityBits = 0; // holds 8 parity bits Uart.twoBits = 0x0000; // buffer for 2 Bits Uart.highCnt = 0; Uart.startTime = 0; Uart.endTime = 0; } +void UartInit(uint8_t *data, uint8_t *parity) +{ + Uart.output = data; + Uart.parity = parity; + UartReset(); +} // use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) @@ -314,6 +356,10 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit Uart.bitCount = 0; Uart.shiftReg = 0; + if((Uart.len&0x0007) == 0) { // every 8 data bytes + Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits + Uart.parityBits = 0; + } } } } @@ -329,17 +375,32 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit Uart.bitCount = 0; Uart.shiftReg = 0; + if ((Uart.len&0x0007) == 0) { // every 8 data bytes + Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits + Uart.parityBits = 0; + } } } else { // no modulation in both halves - Sequence Y if (Uart.state == STATE_MILLER_Z || Uart.state == STATE_MILLER_Y) { // Y after logic "0" - End of Communication Uart.state = STATE_UNSYNCD; - if(Uart.len == 0 && Uart.bitCount > 0) { // if we decoded some bits - Uart.shiftReg >>= (9 - Uart.bitCount); // add them to the output - Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); - Uart.parityBits <<= 1; // no parity bit - add "0" - Uart.bitCount--; // last "0" was part of the EOC sequence + Uart.bitCount--; // last "0" was part of EOC sequence + Uart.shiftReg <<= 1; // drop it + if(Uart.bitCount > 0) { // if we decoded some bits + Uart.shiftReg >>= (9 - Uart.bitCount); // right align them + Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); // add last byte to the output + Uart.parityBits <<= 1; // add a (void) parity bit + Uart.parityBits <<= (8 - (Uart.len&0x0007)); // left align parity bits + Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store it + return TRUE; + } else if (Uart.len & 0x0007) { // there are some parity bits to store + Uart.parityBits <<= (8 - (Uart.len&0x0007)); // left align remaining parity bits + Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store them + } + if (Uart.len) { + return TRUE; // we are finished with decoding the raw data sequence + } else { + UartReset(); // Nothing received - try again } - return TRUE; } if (Uart.state == STATE_START_OF_COMMUNICATION) { // error - must not follow directly after SOC UartReset(); @@ -354,6 +415,10 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit Uart.bitCount = 0; Uart.shiftReg = 0; + if ((Uart.len&0x0007) == 0) { // every 8 data bytes + Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits + Uart.parityBits = 0; + } } } } @@ -398,6 +463,7 @@ void DemodReset() { Demod.state = DEMOD_UNSYNCD; Demod.len = 0; // number of decoded data bytes + Demod.parityLen = 0; Demod.shiftReg = 0; // shiftreg to hold decoded data bits Demod.parityBits = 0; // Demod.collisionPos = 0; // Position of collision bit @@ -407,6 +473,14 @@ void DemodReset() Demod.endTime = 0; } + +void DemodInit(uint8_t *data, uint8_t *parity) +{ + Demod.output = data; + Demod.parity = parity; + DemodReset(); +} + // use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time) { @@ -455,6 +529,10 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit Demod.bitCount = 0; Demod.shiftReg = 0; + if((Demod.len&0x0007) == 0) { // every 8 data bytes + Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits + Demod.parityBits = 0; + } } Demod.endTime = Demod.startTime + 8*(9*Demod.len + Demod.bitCount + 1) - 4; } else { // no modulation in first half @@ -467,16 +545,25 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit Demod.bitCount = 0; Demod.shiftReg = 0; + if ((Demod.len&0x0007) == 0) { // every 8 data bytes + Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits1 + Demod.parityBits = 0; + } } Demod.endTime = Demod.startTime + 8*(9*Demod.len + Demod.bitCount + 1); } else { // no modulation in both halves - End of communication - if (Demod.len > 0 || Demod.bitCount > 0) { // received something - if(Demod.bitCount > 0) { // if we decoded bits - Demod.shiftReg >>= (9 - Demod.bitCount); // add the remaining decoded bits to the output - Demod.output[Demod.len++] = Demod.shiftReg & 0xff; - // No parity bit, so just shift a 0 - Demod.parityBits <<= 1; - } + if(Demod.bitCount > 0) { // there are some remaining data bits + Demod.shiftReg >>= (9 - Demod.bitCount); // right align the decoded bits + Demod.output[Demod.len++] = Demod.shiftReg & 0xff; // and add them to the output + Demod.parityBits <<= 1; // add a (void) parity bit + Demod.parityBits <<= (8 - (Demod.len&0x0007)); // left align remaining parity bits + Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them + return TRUE; + } else if (Demod.len & 0x0007) { // there are some parity bits to store + Demod.parityBits <<= (8 - (Demod.len&0x0007)); // left align remaining parity bits + Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them + } + if (Demod.len) { return TRUE; // we are finished with decoding the raw data sequence } else { // nothing received. Start over DemodReset(); @@ -518,10 +605,13 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { // The command (reader -> tag) that we're receiving. // The length of a received command will in most cases be no more than 18 bytes. // So 32 should be enough! - uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET); + uint8_t *receivedCmd = ((uint8_t *)BigBuf) + RECV_CMD_OFFSET; + uint8_t *receivedCmdPar = ((uint8_t *)BigBuf) + RECV_CMD_PAR_OFFSET; + // The response (tag -> reader) that we're receiving. - uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET); - + uint8_t *receivedResponse = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET; + uint8_t *receivedResponsePar = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET; + // 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; @@ -538,11 +628,11 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); // Set up the demodulator for tag -> reader responses. - Demod.output = receivedResponse; - + DemodInit(receivedResponse, receivedResponsePar); + // Set up the demodulator for the reader -> tag commands - Uart.output = receivedCmd; - + UartInit(receivedCmd, receivedCmdPar); + // Setup and start DMA. FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); @@ -599,8 +689,12 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { if ((!triggered) && (param & 0x02) && (Uart.len == 1) && (Uart.bitCount == 7)) triggered = TRUE; if(triggered) { - if (!LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, Uart.parityBits, TRUE)) break; - if (!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, TRUE)) break; + if (!LogTrace(receivedCmd, + Uart.len, + Uart.startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, + Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, + Uart.parity, + TRUE)) break; } /* And ready to receive another command. */ UartReset(); @@ -617,8 +711,12 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { if(ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) { LED_B_ON(); - if (!LogTrace(receivedResponse, Demod.len, Demod.startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, Demod.parityBits, FALSE)) break; - if (!LogTrace(NULL, 0, Demod.endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, 0, FALSE)) break; + if (!LogTrace(receivedResponse, + Demod.len, + Demod.startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, + Demod.endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, + Demod.parity, + FALSE)) break; if ((!triggered) && (param & 0x01)) triggered = TRUE; @@ -649,10 +747,8 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { //----------------------------------------------------------------------------- // Prepare tag messages //----------------------------------------------------------------------------- -static void CodeIso14443aAsTagPar(const uint8_t *cmd, int len, uint32_t dwParity) +static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity) { - int i; - ToSendReset(); // Correction bit, might be removed when not needed @@ -667,14 +763,14 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, int len, uint32_t dwParity // Send startbit ToSend[++ToSendMax] = SEC_D; + LastProxToAirDuration = 8 * ToSendMax - 4; - for(i = 0; i < len; i++) { - int j; + for(uint16_t i = 0; i < len; i++) { uint8_t b = cmd[i]; // Data bits - for(j = 0; j < 8; j++) { + for(uint16_t j = 0; j < 8; j++) { if(b & 1) { ToSend[++ToSendMax] = SEC_D; } else { @@ -684,7 +780,7 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, int len, uint32_t dwParity } // Get the parity bit - if ((dwParity >> i) & 0x01) { + if (parity[i>>3] & (0x80>>(i&0x0007))) { ToSend[++ToSendMax] = SEC_D; LastProxToAirDuration = 8 * ToSendMax - 4; } else { @@ -700,8 +796,12 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, int len, uint32_t dwParity ToSendMax++; } -static void CodeIso14443aAsTag(const uint8_t *cmd, int len){ - CodeIso14443aAsTagPar(cmd, len, GetParity(cmd, len)); +static void CodeIso14443aAsTag(const uint8_t *cmd, uint16_t len) +{ + uint8_t par[MAX_PARITY_SIZE]; + + GetParity(cmd, len, par); + CodeIso14443aAsTagPar(cmd, len, par); } @@ -748,7 +848,7 @@ static void Code4bitAnswerAsTag(uint8_t cmd) // Stop when button is pressed // Or return TRUE when command is captured //----------------------------------------------------------------------------- -static int GetIso14443aCommandFromReader(uint8_t *received, int *len, int maxLen) +static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len) { // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen // only, since we are receiving, not transmitting). @@ -757,8 +857,7 @@ static int GetIso14443aCommandFromReader(uint8_t *received, int *len, int maxLen FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); // Now run a `software UART' on the stream of incoming samples. - UartReset(); - Uart.output = received; + UartInit(received, parity); // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; @@ -778,16 +877,15 @@ static int GetIso14443aCommandFromReader(uint8_t *received, int *len, int maxLen } } -static int EmSendCmd14443aRaw(uint8_t *resp, int respLen, bool correctionNeeded); +static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNeeded); int EmSend4bitEx(uint8_t resp, bool correctionNeeded); int EmSend4bit(uint8_t resp); -int EmSendCmdExPar(uint8_t *resp, int respLen, bool correctionNeeded, uint32_t par); -int EmSendCmdExPar(uint8_t *resp, int respLen, bool correctionNeeded, uint32_t par); -int EmSendCmdEx(uint8_t *resp, int respLen, bool correctionNeeded); -int EmSendCmd(uint8_t *resp, int respLen); -int EmSendCmdPar(uint8_t *resp, int respLen, uint32_t par); -bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint32_t reader_Parity, - uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint32_t tag_Parity); +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); static uint8_t* free_buffer_pointer = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET); @@ -840,7 +938,7 @@ bool prepare_allocated_tag_modulation(tag_response_info_t* response_info) { response_info->modulation = free_buffer_pointer; // Determine the maximum size we can use from our buffer - size_t max_buffer_size = (((uint8_t *)BigBuf)+FREE_BUFFER_OFFSET+FREE_BUFFER_SIZE)-free_buffer_pointer; + size_t max_buffer_size = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + FREE_BUFFER_SIZE) - free_buffer_pointer; // Forward the prepare tag modulation function to the inner function if (prepare_tag_modulation(response_info,max_buffer_size)) { @@ -933,7 +1031,11 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); uint8_t response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce - uint8_t response6[] = { 0x04, 0x58, 0x00, 0x02, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS + uint8_t response6[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS: + // Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present, + // TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1 + // TB(1) = not present. Defaults: FWI = 4 (FWT = 256 * 16 * 2^4 * 1/fc = 4833us), SFGI = 0 (SFG = 256 * 16 * 2^0 * 1/fc = 302us) + // TC(1) = 0x02: CID supported, NAD not supported ComputeCrc14443(CRC_14443_A, response6, 4, &response6[4], &response6[5]); #define TAG_RESPONSE_COUNT 7 @@ -969,7 +1071,6 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) prepare_allocated_tag_modulation(&responses[i]); } - uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET); int len = 0; // To control where we are in the protocol @@ -984,6 +1085,10 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) // We need to listen to the high-frequency, peak-detected path. iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); + // buffers used on software Uart: + uint8_t *receivedCmd = ((uint8_t *)BigBuf) + RECV_CMD_OFFSET; + uint8_t *receivedCmdPar = ((uint8_t *)BigBuf) + RECV_CMD_PAR_OFFSET; + cmdsRecvd = 0; tag_response_info_t* p_response; @@ -991,14 +1096,13 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) for(;;) { // Clean receive command buffer - if(!GetIso14443aCommandFromReader(receivedCmd, &len, RECV_CMD_SIZE)) { + if(!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { DbpString("Button press"); break; } p_response = NULL; - // doob - added loads of debug strings so we can see what the reader is saying to us during the sim as hi14alist is not populated // Okay, look at the command now. lastorder = order; if(receivedCmd[0] == 0x26) { // Received a REQUEST @@ -1007,22 +1111,21 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) p_response = &responses[0]; order = 6; } else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x93) { // Received request for UID (cascade 1) p_response = &responses[1]; order = 2; - } else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x95) { // Received request for UID (cascade 2) + } else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x95) { // Received request for UID (cascade 2) p_response = &responses[2]; order = 20; } else if(receivedCmd[1] == 0x70 && receivedCmd[0] == 0x93) { // Received a SELECT (cascade 1) p_response = &responses[3]; order = 3; } else if(receivedCmd[1] == 0x70 && receivedCmd[0] == 0x95) { // Received a SELECT (cascade 2) p_response = &responses[4]; order = 30; } else if(receivedCmd[0] == 0x30) { // Received a (plain) READ - EmSendCmdEx(data+(4*receivedCmd[0]),16,false); + EmSendCmdEx(data+(4*receivedCmd[1]),16,false); // Dbprintf("Read request from reader: %x %x",receivedCmd[0],receivedCmd[1]); // We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below p_response = NULL; } else if(receivedCmd[0] == 0x50) { // Received a HALT // DbpString("Reader requested we HALT!:"); if (tracing) { - LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); } p_response = NULL; } else if(receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61) { // Received an authentication request @@ -1034,10 +1137,9 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) } else { p_response = &responses[6]; order = 70; } - } else if (order == 7 && len == 8) { // Received authentication request + } else if (order == 7 && len == 8) { // Received {nr] and {ar} (part of authentication) if (tracing) { - LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); } uint32_t nr = bytes_to_num(receivedCmd,4); uint32_t ar = bytes_to_num(receivedCmd+4,4); @@ -1081,8 +1183,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) default: { // Never seen this command before if (tracing) { - LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); } Dbprintf("Received unknown command (len=%d):",len); Dbhexdump(len,receivedCmd,false); @@ -1102,8 +1203,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) if (prepare_tag_modulation(&dynamic_response_info,DYNAMIC_MODULATION_BUFFER_SIZE) == false) { Dbprintf("Error preparing tag response"); if (tracing) { - LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); } break; } @@ -1126,16 +1226,18 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) if (p_response != NULL) { EmSendCmd14443aRaw(p_response->modulation, 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.parityBits, + Uart.parity, p_response->response, p_response->response_n, LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, (LastTimeProxToAirStart + p_response->ProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, - SwapBits(GetParity(p_response->response, p_response->response_n), p_response->response_n)); + par); } if (!tracing) { @@ -1181,7 +1283,7 @@ void PrepareDelayedTransfer(uint16_t delay) // if == 0: transfer immediately and return time of transfer // if != 0: delay transfer until time specified //------------------------------------------------------------------------------------- -static void TransmitFor14443a(const uint8_t *cmd, int len, uint32_t *timing) +static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing) { FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); @@ -1232,7 +1334,7 @@ static void TransmitFor14443a(const uint8_t *cmd, int len, uint32_t *timing) //----------------------------------------------------------------------------- // Prepare reader command (in bits, support short frames) to send to FPGA //----------------------------------------------------------------------------- -void CodeIso14443aBitsAsReaderPar(const uint8_t * cmd, int bits, uint32_t dwParity) +void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *parity) { int i, j; int last; @@ -1272,10 +1374,10 @@ void CodeIso14443aBitsAsReaderPar(const uint8_t * cmd, int bits, uint32_t dwPari b >>= 1; } - // Only transmit (last) parity bit if we transmitted a complete byte + // Only transmit parity bit if we transmitted a complete byte if (j == 8) { // Get the parity bit - if ((dwParity >> i) & 0x01) { + if (parity[i>>3] & (0x80 >> (i&0x0007))) { // Sequence X ToSend[++ToSendMax] = SEC_X; LastProxToAirDuration = 8 * (ToSendMax+1) - 2; @@ -1313,9 +1415,9 @@ void CodeIso14443aBitsAsReaderPar(const uint8_t * cmd, int bits, uint32_t dwPari //----------------------------------------------------------------------------- // Prepare reader command to send to FPGA //----------------------------------------------------------------------------- -void CodeIso14443aAsReaderPar(const uint8_t * cmd, int len, uint32_t dwParity) +void CodeIso14443aAsReaderPar(const uint8_t *cmd, uint16_t len, const uint8_t *parity) { - CodeIso14443aBitsAsReaderPar(cmd,len*8,dwParity); + CodeIso14443aBitsAsReaderPar(cmd, len*8, parity); } //----------------------------------------------------------------------------- @@ -1323,7 +1425,7 @@ void CodeIso14443aAsReaderPar(const uint8_t * cmd, int len, uint32_t dwParity) // 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, int *len) +static int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) { *len = 0; @@ -1348,8 +1450,7 @@ static int EmGetCmd(uint8_t *received, int *len) AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; // Now run a 'software UART' on the stream of incoming samples. - UartReset(); - Uart.output = received; + UartInit(received, parity); // Clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; @@ -1390,7 +1491,7 @@ static int EmGetCmd(uint8_t *received, int *len) } -static int EmSendCmd14443aRaw(uint8_t *resp, int respLen, bool correctionNeeded) +static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNeeded) { uint8_t b; uint16_t i = 0; @@ -1457,16 +1558,18 @@ 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.parityBits, + Uart.parity, &resp, 1, LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, - SwapBits(GetParity(&resp, 1), 1)); + par); return res; } @@ -1474,7 +1577,7 @@ int EmSend4bit(uint8_t resp){ return EmSend4bitEx(resp, false); } -int EmSendCmdExPar(uint8_t *resp, int respLen, bool correctionNeeded, uint32_t par){ +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: @@ -1482,29 +1585,33 @@ int EmSendCmdExPar(uint8_t *resp, int respLen, bool correctionNeeded, uint32_t p Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.parityBits, + Uart.parity, resp, respLen, LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, - SwapBits(GetParity(resp, respLen), respLen)); + par); return res; } -int EmSendCmdEx(uint8_t *resp, int respLen, bool correctionNeeded){ - return EmSendCmdExPar(resp, respLen, correctionNeeded, GetParity(resp, respLen)); +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, int respLen){ - return EmSendCmdExPar(resp, respLen, false, GetParity(resp, respLen)); +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, int respLen, uint32_t 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, uint32_t reader_Parity, - uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint32_t tag_Parity) +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 @@ -1515,15 +1622,9 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start 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_Parity, TRUE)) { - return FALSE; - } else if (!LogTrace(NULL, 0, reader_EndTime, 0, TRUE)) { - return FALSE; - } else if (!LogTrace(tag_data, tag_len, tag_StartTime, tag_Parity, FALSE)) { + if (!LogTrace(reader_data, reader_len, reader_StartTime, reader_EndTime, reader_Parity, TRUE)) { return FALSE; - } else { - return (!LogTrace(NULL, 0, tag_EndTime, 0, FALSE)); - } + } else return(!LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, FALSE)); } else { return TRUE; } @@ -1534,9 +1635,9 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start // If a response is captured return TRUE // If it takes too long return FALSE //----------------------------------------------------------------------------- -static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint16_t offset, int maxLen) +static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) { - uint16_t c; + uint32_t c; // Set FPGA mode to "reader listen mode", no modulation (listen // only, since we are receiving, not transmitting). @@ -1545,8 +1646,7 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint16_t offset, FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); // Now get the answer from the card - DemodReset(); - Demod.output = receivedResponse; + DemodInit(receivedResponse, receivedResponsePar); // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; @@ -1560,17 +1660,17 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint16_t offset, if(ManchesterDecoding(b, offset, 0)) { NextTransferTime = MAX(NextTransferTime, Demod.endTime - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/16 + FRAME_DELAY_TIME_PICC_TO_PCD); return TRUE; - } else if(c++ > iso14a_timeout) { + } else if (c++ > iso14a_timeout) { return FALSE; } } } } -void ReaderTransmitBitsPar(uint8_t* frame, int bits, uint32_t par, uint32_t *timing) +void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t *timing) { - CodeIso14443aBitsAsReaderPar(frame,bits,par); + CodeIso14443aBitsAsReaderPar(frame, bits, par); // Send command to tag TransmitFor14443a(ToSend, ToSendMax, timing); @@ -1579,198 +1679,195 @@ void ReaderTransmitBitsPar(uint8_t* frame, int bits, uint32_t par, uint32_t *tim // Log reader command in trace buffer if (tracing) { - LogTrace(frame, nbytes(bits), LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_READER, par, TRUE); - LogTrace(NULL, 0, (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_READER, 0, TRUE); + LogTrace(frame, nbytes(bits), LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_READER, (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_READER, par, TRUE); } } -void ReaderTransmitPar(uint8_t* frame, int len, uint32_t par, uint32_t *timing) +void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *timing) { - ReaderTransmitBitsPar(frame,len*8,par, timing); + ReaderTransmitBitsPar(frame, len*8, par, timing); } -void ReaderTransmitBits(uint8_t* frame, int len, uint32_t *timing) +void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing) { // Generate parity and redirect - ReaderTransmitBitsPar(frame,len,GetParity(frame,len/8), timing); + uint8_t par[MAX_PARITY_SIZE]; + GetParity(frame, len/8, par); + ReaderTransmitBitsPar(frame, len, par, timing); } -void ReaderTransmit(uint8_t* frame, int len, uint32_t *timing) +void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing) { // Generate parity and redirect - ReaderTransmitBitsPar(frame,len*8,GetParity(frame,len), timing); + uint8_t par[MAX_PARITY_SIZE]; + GetParity(frame, len, par); + ReaderTransmitBitsPar(frame, len*8, par, timing); } -int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset) +int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t *parity) { - if (!GetIso14443aAnswerFromTag(receivedAnswer,offset,160)) return FALSE; + if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, offset)) return FALSE; if (tracing) { - LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.parityBits, FALSE); - LogTrace(NULL, 0, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, 0, FALSE); + LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, FALSE); } return Demod.len; } -int ReaderReceive(uint8_t* receivedAnswer) -{ - return ReaderReceiveOffset(receivedAnswer, 0); -} - -int ReaderReceivePar(uint8_t *receivedAnswer, uint32_t *parptr) +int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity) { - if (!GetIso14443aAnswerFromTag(receivedAnswer,0,160)) return FALSE; + if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, 0)) return FALSE; if (tracing) { - LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.parityBits, FALSE); - LogTrace(NULL, 0, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, 0, FALSE); + LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, FALSE); } - *parptr = Demod.parityBits; return Demod.len; } /* performs iso14443a anticollision procedure * fills the uid pointer unless NULL * fills resp_data unless NULL */ -int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, uint32_t* cuid_ptr) { - uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP - uint8_t sel_all[] = { 0x93,0x20 }; - uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0 - uint8_t* resp = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET); // was 3560 - tied to other size changes - byte_t uid_resp[4]; - size_t uid_resp_len; - - uint8_t sak = 0x04; // cascade uid - int cascade_level = 0; - int len; - - // Broadcast for a card, WUPA (0x52) will force response from all cards in the field +int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr) { + uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP + uint8_t sel_all[] = { 0x93,0x20 }; + uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0 + uint8_t *resp = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET; + uint8_t *resp_par = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET; + byte_t uid_resp[4]; + size_t uid_resp_len; + + uint8_t sak = 0x04; // cascade uid + int cascade_level = 0; + int len; + + // Broadcast for a card, WUPA (0x52) will force response from all cards in the field ReaderTransmitBitsPar(wupa,7,0, NULL); - // Receive the ATQA - if(!ReaderReceive(resp)) return 0; - // Dbprintf("atqa: %02x %02x",resp[0],resp[1]); - - if(p_hi14a_card) { - memcpy(p_hi14a_card->atqa, resp, 2); - p_hi14a_card->uidlen = 0; - memset(p_hi14a_card->uid,0,10); - } + // Receive the ATQA + if(!ReaderReceive(resp, resp_par)) return 0; + //Dbprintf("atqa: %02x %02x",resp[1],resp[0]); + + if(p_hi14a_card) { + memcpy(p_hi14a_card->atqa, resp, 2); + p_hi14a_card->uidlen = 0; + memset(p_hi14a_card->uid,0,10); + } - // clear uid - if (uid_ptr) { - memset(uid_ptr,0,10); - } + // clear uid + if (uid_ptr) { + memset(uid_ptr,0,10); + } - // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in - // which case we need to make a cascade 2 request and select - this is a long UID - // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. - for(; sak & 0x04; cascade_level++) { - // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97) - sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2; - - // SELECT_ALL - ReaderTransmit(sel_all,sizeof(sel_all), NULL); - if (!ReaderReceive(resp)) return 0; - - if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit - memset(uid_resp, 0, 4); - uint16_t uid_resp_bits = 0; - uint16_t collision_answer_offset = 0; - // anti-collision-loop: - while (Demod.collisionPos) { - Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos); - for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point - uint16_t UIDbit = (resp[i/8] >> (i % 8)) & 0x01; - uid_resp[uid_resp_bits & 0xf8] |= UIDbit << (uid_resp_bits % 8); + // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in + // which case we need to make a cascade 2 request and select - this is a long UID + // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. + for(; sak & 0x04; cascade_level++) { + // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97) + sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2; + + // SELECT_ALL + ReaderTransmit(sel_all, sizeof(sel_all), NULL); + if (!ReaderReceive(resp, resp_par)) return 0; + + if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit + memset(uid_resp, 0, 4); + uint16_t uid_resp_bits = 0; + uint16_t collision_answer_offset = 0; + // anti-collision-loop: + while (Demod.collisionPos) { + Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos); + for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point + uint16_t UIDbit = (resp[i/8] >> (i % 8)) & 0x01; + uid_resp[uid_resp_bits & 0xf8] |= UIDbit << (uid_resp_bits % 8); + } + uid_resp[uid_resp_bits/8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position + uid_resp_bits++; + // construct anticollosion command: + sel_uid[1] = ((2 + uid_resp_bits/8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits + for (uint16_t i = 0; i <= uid_resp_bits/8; i++) { + sel_uid[2+i] = uid_resp[i]; + } + collision_answer_offset = uid_resp_bits%8; + ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL); + if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) return 0; } - uid_resp[uid_resp_bits/8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position - uid_resp_bits++; - // construct anticollosion command: - sel_uid[1] = ((2 + uid_resp_bits/8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits - for (uint16_t i = 0; i <= uid_resp_bits/8; i++) { - sel_uid[2+i] = uid_resp[i]; + // finally, add the last bits and BCC of the UID + for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) { + uint16_t UIDbit = (resp[i/8] >> (i%8)) & 0x01; + uid_resp[uid_resp_bits/8] |= UIDbit << (uid_resp_bits % 8); } - collision_answer_offset = uid_resp_bits%8; - ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL); - if (!ReaderReceiveOffset(resp, collision_answer_offset)) return 0; - } - // finally, add the last bits and BCC of the UID - for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) { - uint16_t UIDbit = (resp[i/8] >> (i%8)) & 0x01; - uid_resp[uid_resp_bits/8] |= UIDbit << (uid_resp_bits % 8); - } - } else { // no collision, use the response to SELECT_ALL as current uid - memcpy(uid_resp,resp,4); - } - uid_resp_len = 4; - // Dbprintf("uid: %02x %02x %02x %02x",uid_resp[0],uid_resp[1],uid_resp[2],uid_resp[3]); + } else { // no collision, use the response to SELECT_ALL as current uid + memcpy(uid_resp, resp, 4); + } + uid_resp_len = 4; + //Dbprintf("uid: %02x %02x %02x %02x",uid_resp[0],uid_resp[1],uid_resp[2],uid_resp[3]); - // calculate crypto UID. Always use last 4 Bytes. - if(cuid_ptr) { - *cuid_ptr = bytes_to_num(uid_resp, 4); - } + // calculate crypto UID. Always use last 4 Bytes. + if(cuid_ptr) { + *cuid_ptr = bytes_to_num(uid_resp, 4); + } - // Construct SELECT UID command - sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC) - memcpy(sel_uid+2,uid_resp,4); // the UID - sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC - AppendCrc14443a(sel_uid,7); // calculate and add CRC - ReaderTransmit(sel_uid,sizeof(sel_uid), NULL); - - // Receive the SAK - if (!ReaderReceive(resp)) return 0; - sak = resp[0]; - - // Test if more parts of the uid are comming - if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) { - // Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of: - // http://www.nxp.com/documents/application_note/AN10927.pdf - // This was earlier: - //memcpy(uid_resp, uid_resp + 1, 3); - // But memcpy should not be used for overlapping arrays, - // and memmove appears to not be available in the arm build. - // Therefore: - uid_resp[0] = uid_resp[1]; - uid_resp[1] = uid_resp[2]; - uid_resp[2] = uid_resp[3]; - - uid_resp_len = 3; - } + // Construct SELECT UID command + sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC) + memcpy(sel_uid+2, uid_resp, 4); // the UID + sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC + AppendCrc14443a(sel_uid, 7); // calculate and add CRC + ReaderTransmit(sel_uid, sizeof(sel_uid), NULL); + + // Receive the SAK + if (!ReaderReceive(resp, resp_par)) return 0; + sak = resp[0]; + + // Test if more parts of the uid are comming + if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) { + // Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of: + // http://www.nxp.com/documents/application_note/AN10927.pdf + // This was earlier: + //memcpy(uid_resp, uid_resp + 1, 3); + // But memcpy should not be used for overlapping arrays, + // and memmove appears to not be available in the arm build. + // Therefore: + uid_resp[0] = uid_resp[1]; + uid_resp[1] = uid_resp[2]; + uid_resp[2] = uid_resp[3]; + + uid_resp_len = 3; + } - if(uid_ptr) { - memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len); - } + if(uid_ptr) { + memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len); + } - if(p_hi14a_card) { - memcpy(p_hi14a_card->uid + (cascade_level*3), uid_resp, uid_resp_len); - p_hi14a_card->uidlen += uid_resp_len; - } - } + if(p_hi14a_card) { + memcpy(p_hi14a_card->uid + (cascade_level*3), uid_resp, uid_resp_len); + p_hi14a_card->uidlen += uid_resp_len; + } + } - if(p_hi14a_card) { - p_hi14a_card->sak = sak; - p_hi14a_card->ats_len = 0; - } + if(p_hi14a_card) { + p_hi14a_card->sak = sak; + p_hi14a_card->ats_len = 0; + } - if( (sak & 0x20) == 0) { - return 2; // non iso14443a compliant tag - } + if( (sak & 0x20) == 0) { + return 2; // non iso14443a compliant tag + } - // Request for answer to select - AppendCrc14443a(rats, 2); - ReaderTransmit(rats, sizeof(rats), NULL); + // Request for answer to select + AppendCrc14443a(rats, 2); + ReaderTransmit(rats, sizeof(rats), NULL); - if (!(len = ReaderReceive(resp))) return 0; + if (!(len = ReaderReceive(resp, resp_par))) return 0; - if(p_hi14a_card) { - memcpy(p_hi14a_card->ats, resp, sizeof(p_hi14a_card->ats)); - p_hi14a_card->ats_len = len; - } + if(p_hi14a_card) { + memcpy(p_hi14a_card->ats, resp, sizeof(p_hi14a_card->ats)); + p_hi14a_card->ats_len = len; + } - // reset the PCB block number - iso14_pcb_blocknum = 0; - return 1; + // reset the PCB block number + iso14_pcb_blocknum = 0; + + return 1; } void iso14443a_setup(uint8_t fpga_minor_mode) { @@ -1798,7 +1895,8 @@ void iso14443a_setup(uint8_t fpga_minor_mode) { iso14a_set_timeout(1050); // 10ms default } -int iso14_apdu(uint8_t * cmd, size_t cmd_len, void * data) { +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]; real_cmd[0] = 0x0a; //I-Block // put block number into the PCB @@ -1808,8 +1906,8 @@ int iso14_apdu(uint8_t * cmd, size_t cmd_len, void * data) { AppendCrc14443a(real_cmd,cmd_len+2); ReaderTransmit(real_cmd, cmd_len+4, NULL); - size_t len = ReaderReceive(data); - uint8_t * data_bytes = (uint8_t *) data; + size_t len = ReaderReceive(data, parity); + uint8_t *data_bytes = (uint8_t *) data; if (!len) return 0; //DATA LINK ERROR // if we received an I- or R(ACK)-Block with a block number equal to the @@ -1837,6 +1935,7 @@ void ReaderIso14443a(UsbCommand *c) size_t lenbits = c->arg[2]; uint32_t arg0 = 0; byte_t buf[USB_CMD_DATA_SIZE]; + uint8_t par[MAX_PARITY_SIZE]; if(param & ISO14A_CONNECT) { iso14a_clear_trace(); @@ -1873,11 +1972,12 @@ void ReaderIso14443a(UsbCommand *c) if (lenbits) lenbits += 16; } if(lenbits>0) { - ReaderTransmitBitsPar(cmd,lenbits,GetParity(cmd,lenbits/8), NULL); + GetParity(cmd, lenbits/8, par); + ReaderTransmitBitsPar(cmd, lenbits, par, NULL); } else { ReaderTransmit(cmd,len, NULL); } - arg0 = ReaderReceive(buf); + arg0 = ReaderReceive(buf, par); cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf)); } @@ -1931,20 +2031,20 @@ void ReaderMifare(bool first_try) uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; static uint8_t mf_nr_ar3; - uint8_t* receivedAnswer = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET); + uint8_t* receivedAnswer = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET); + uint8_t* receivedAnswerPar = (((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET); iso14a_clear_trace(); iso14a_set_tracing(TRUE); byte_t nt_diff = 0; - byte_t par = 0; - //byte_t par_mask = 0xff; + uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough static byte_t par_low = 0; bool led_on = TRUE; uint8_t uid[10] ={0}; uint32_t cuid; - uint32_t nt =0 ; + uint32_t nt = 0; uint32_t previous_nt = 0; static uint32_t nt_attacked = 0; byte_t par_list[8] = {0,0,0,0,0,0,0,0}; @@ -1966,14 +2066,13 @@ void ReaderMifare(bool first_try) sync_cycles = 65536; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). nt_attacked = 0; nt = 0; - par = 0; + par[0] = 0; } else { // we were unsuccessful on a previous call. Try another READER nonce (first 3 parity bits remain the same) - // nt_attacked = prng_successor(nt_attacked, 1); mf_nr_ar3++; mf_nr_ar[3] = mf_nr_ar3; - par = par_low; + par[0] = par_low; } LED_A_ON(); @@ -2009,7 +2108,7 @@ void ReaderMifare(bool first_try) ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time); // Receive the (4 Byte) "random" nonce - if (!ReaderReceive(receivedAnswer)) { + if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) { if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Couldn't receive tag nonce"); continue; } @@ -2061,19 +2160,19 @@ 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)) + 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) { - par_low = par & 0x07; // there is no need to check all parities for other nt_diff. Parity Bits for mf_nr_ar[0..2] won't change + 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 } led_on = !led_on; if(led_on) LED_B_ON(); else LED_B_OFF(); - par_list[nt_diff] = par; + par_list[nt_diff] = SwapBits(par[0], 8); ks_list[nt_diff] = receivedAnswer[0] ^ 0x05; // Test if the information is complete @@ -2084,13 +2183,13 @@ void ReaderMifare(bool first_try) nt_diff = (nt_diff + 1) & 0x07; mf_nr_ar[3] = (mf_nr_ar[3] & 0x1F) | (nt_diff << 5); - par = par_low; + par[0] = par_low; } else { if (nt_diff == 0 && first_try) { - par++; + par[0]++; } else { - par = (((par >> 3) + 1) << 3) | par_low; + par[0] = ((par[0] & 0x1F) + 1) | par_low; } } } @@ -2132,8 +2231,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * int res; uint32_t selTimer = 0; uint32_t authTimer = 0; - uint32_t par = 0; - int len = 0; + uint16_t len = 0; uint8_t cardWRBL = 0; uint8_t cardAUTHSC = 0; uint8_t cardAUTHKEY = 0xff; // no authentication @@ -2147,8 +2245,10 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * struct Crypto1State *pcs; pcs = &mpcs; uint32_t numReads = 0;//Counts numer of times reader read a block - uint8_t* receivedCmd = eml_get_bigbufptr_recbuf(); - uint8_t *response = eml_get_bigbufptr_sendbuf(); + uint8_t* receivedCmd = get_bigbufptr_recvcmdbuf(); + uint8_t* receivedCmd_par = receivedCmd + MAX_FRAME_SIZE; + uint8_t* response = get_bigbufptr_recvrespbuf(); + uint8_t* response_par = response + MAX_FRAME_SIZE; uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; @@ -2242,7 +2342,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * //Now, get data - res = EmGetCmd(receivedCmd, &len); + res = EmGetCmd(receivedCmd, &len, receivedCmd_par); if (res == 2) { //Field is off! cardSTATE = MFEMUL_NOFIELD; LEDsoff(); @@ -2269,8 +2369,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * case MFEMUL_NOFIELD: case MFEMUL_HALTED: case MFEMUL_IDLE:{ - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + 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:{ @@ -2305,12 +2404,11 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * if( len != 8) { cardSTATE_TO_IDLE(); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + 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 ar = bytes_to_num(receivedCmd, 4); - uint32_t nr= bytes_to_num(&receivedCmd[4], 4); + uint32_t nr = bytes_to_num(&receivedCmd[4], 4); //Collect AR/NR if(ar_nr_collected < 2){ @@ -2338,8 +2436,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // 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.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); break; } @@ -2357,8 +2454,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } case MFEMUL_SELECT2:{ if (!len) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); break; } if (len == 2 && (receivedCmd[0] == 0x95 && receivedCmd[1] == 0x20)) { @@ -2379,8 +2475,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // 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.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + 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; @@ -2390,8 +2485,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * case MFEMUL_WORK:{ if (len == 0) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); break; } @@ -2439,8 +2533,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } if(len != 4) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); break; } @@ -2469,8 +2562,8 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } emlGetMem(response, receivedCmd[1], 1); AppendCrc14443a(response, 16); - mf_crypto1_encrypt(pcs, response, 18, &par); - EmSendCmdPar(response, 18, par); + 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); @@ -2519,8 +2612,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * 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.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); break; } // RATS @@ -2541,8 +2633,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * cardSTATE = MFEMUL_WORK; } else { cardSTATE_TO_IDLE(); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); } break; } @@ -2555,8 +2646,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * cardSTATE_TO_IDLE(); break; } - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + 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; @@ -2569,8 +2659,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * cardSTATE_TO_IDLE(); break; } - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + 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; @@ -2583,8 +2672,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * cardSTATE_TO_IDLE(); break; } - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE); - LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE); + 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; } @@ -2648,8 +2736,10 @@ void RAMFUNC SniffMifare(uint8_t param) { // The length of a received command will in most cases be no more than 18 bytes. // So 32 should be enough! uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET); + uint8_t *receivedCmdPar = ((uint8_t *)BigBuf) + RECV_CMD_PAR_OFFSET; // The response (tag -> reader) that we're receiving. - uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET); + uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET); + uint8_t *receivedResponsePar = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET; // As we receive stuff, we copy it from receivedCmd or receivedResponse // into trace, along with its length and other annotations. @@ -2667,10 +2757,10 @@ void RAMFUNC SniffMifare(uint8_t param) { iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); // Set up the demodulator for tag -> reader responses. - Demod.output = receivedResponse; + DemodInit(receivedResponse, receivedResponsePar); // Set up the demodulator for the reader -> tag commands - Uart.output = receivedCmd; + UartInit(receivedCmd, receivedCmdPar); // Setup for the DMA. FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); // set transfer address and number of bytes. Start transfer. @@ -2742,7 +2832,7 @@ void RAMFUNC SniffMifare(uint8_t param) { uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); if(MillerDecoding(readerdata, (sniffCounter-1)*4)) { LED_C_INV(); - if (MfSniffLogic(receivedCmd, Uart.len, Uart.parityBits, Uart.bitCount, TRUE)) break; + if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, TRUE)) break; /* And ready to receive another command. */ UartReset(); @@ -2758,7 +2848,7 @@ void RAMFUNC SniffMifare(uint8_t param) { if(ManchesterDecoding(tagdata, 0, (sniffCounter-1)*4)) { LED_C_INV(); - if (MfSniffLogic(receivedResponse, Demod.len, Demod.parityBits, Demod.bitCount, FALSE)) break; + if (MfSniffLogic(receivedResponse, Demod.len, Demod.parity, Demod.bitCount, FALSE)) break; // And ready to receive another response. DemodReset(); diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 6d18515f..c595d5e1 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -15,13 +15,6 @@ #include "common.h" #include "mifaresniff.h" -// mifare reader over DMA buffer (SnoopIso14443a())!!! -#define MIFARE_BUFF_OFFSET 3560 // \/ \/ \/ -// card emulator memory -#define EML_RESPONSES 4000 -#define CARD_MEMORY 6000 -#define CARD_MEMORY_LEN 4096 - typedef struct { enum { DEMOD_UNSYNCD, @@ -35,12 +28,14 @@ typedef struct { uint16_t bitCount; uint16_t collisionPos; uint16_t syncBit; - uint32_t parityBits; + uint8_t parityBits; + uint8_t parityLen; uint16_t shiftReg; uint16_t samples; uint16_t len; uint32_t startTime, endTime; uint8_t *output; + uint8_t *parity; } tDemod; typedef enum { @@ -66,32 +61,33 @@ typedef struct { uint16_t byteCntMax; uint16_t posCnt; uint16_t syncBit; - uint32_t parityBits; + uint8_t parityBits; + uint8_t parityLen; uint16_t highCnt; uint16_t twoBits; uint32_t startTime, endTime; uint8_t *output; + uint8_t *parity; } tUart; extern byte_t oddparity (const byte_t bt); -extern uint32_t GetParity(const uint8_t *pbtCmd, int iLen); +extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); extern void AppendCrc14443a(uint8_t *data, int len); -extern void ReaderTransmit(uint8_t *frame, int len, uint32_t *timing); -extern void ReaderTransmitBitsPar(uint8_t *frame, int bits, uint32_t par, uint32_t *timing); -extern void ReaderTransmitPar(uint8_t *frame, int len, uint32_t par, uint32_t *timing); -extern int ReaderReceive(uint8_t *receivedAnswer); -extern int ReaderReceivePar(uint8_t *receivedAnswer, uint32_t *parptr); +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 iso14443a_setup(uint8_t fpga_minor_mode); -extern int iso14_apdu(uint8_t *cmd, size_t cmd_len, void *data); +extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data); extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr); extern void iso14a_set_trigger(bool enable); extern void iso14a_set_timeout(uint32_t timeout); -extern void iso14a_clear_tracelen(); +extern void iso14a_clear_trace(); extern void iso14a_set_tracing(bool enable); #endif /* __ISO14443A_H */ diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 42dee56e..344b0f3e 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -126,11 +126,8 @@ void MifareUReadBlock(uint8_t arg0,uint8_t *datain) if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED"); - // add trace trailer - memset(uid, 0x44, 4); - LogTrace(uid, 4, 0, 0, TRUE); LED_B_ON(); - cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16); + cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16); LED_B_OFF(); @@ -459,7 +456,7 @@ void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain) // Return 1 if the nonce is invalid else return 0 -int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, byte_t * parity) { +int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) { return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \ (oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \ (oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0; @@ -486,7 +483,8 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat uint16_t davg; static uint16_t dmin, dmax; uint8_t uid[10]; - uint32_t cuid, nt1, nt2, nttmp, nttest, par, ks1; + uint32_t cuid, nt1, nt2, nttmp, nttest, ks1; + uint8_t par[1]; uint32_t target_nt[2], target_ks[2]; uint8_t par_array[4]; @@ -494,7 +492,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat struct Crypto1State mpcs = {0, 0}; struct Crypto1State *pcs; pcs = &mpcs; - uint8_t* receivedAnswer = mifare_get_bigbufptr(); + uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf(); uint32_t auth1_time, auth2_time; static uint16_t delta_time; @@ -610,19 +608,18 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat // nested authentication auth2_time = auth1_time + delta_time; - len = mifare_sendcmd_shortex(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, &par, &auth2_time); + len = mifare_sendcmd_shortex(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time); if (len != 4) { if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len); continue; }; nt2 = bytes_to_num(receivedAnswer, 4); - if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par); + if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par[0]); // Parity validity check for (j = 0; j < 4; j++) { - par_array[j] = (oddparity(receivedAnswer[j]) != ((par & 0x08) >> 3)); - par = par << 1; + par_array[j] = (oddparity(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01)); } ncount = 0; @@ -657,10 +654,6 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat // ----------------------------- crypto1 destroy crypto1_destroy(pcs); - // add trace trailer - memset(uid, 0x44, 4); - LogTrace(uid, 4, 0, 0, TRUE); - byte_t buf[4 + 4 * 4]; memcpy(buf, &cuid, 4); memcpy(buf+4, &target_nt[0], 4); @@ -896,8 +889,9 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai uint32_t cuid; memset(uid, 0x00, 10); - uint8_t* receivedAnswer = mifare_get_bigbufptr(); - + uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf(); + uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; + if (workFlags & 0x08) { // clear trace iso14a_clear_trace(); @@ -931,14 +925,14 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai // reset chip if (needWipe){ - ReaderTransmitBitsPar(wupC1,7,0, NULL); - if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) { + ReaderTransmitBitsPar(wupC1,7,0, NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); break; }; ReaderTransmit(wipeC, sizeof(wipeC), NULL); - if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) { + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error"); break; }; @@ -951,20 +945,20 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai // write block if (workFlags & 0x02) { - ReaderTransmitBitsPar(wupC1,7,0, NULL); - if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) { + ReaderTransmitBitsPar(wupC1,7,0, NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); break; }; ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) { + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); break; }; } - if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { + if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error"); break; }; @@ -973,7 +967,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai AppendCrc14443a(d_block, 16); ReaderTransmit(d_block, sizeof(d_block), NULL); - if ((ReaderReceive(receivedAnswer) != 1) || (receivedAnswer[0] != 0x0a)) { + if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error"); break; }; @@ -1021,7 +1015,8 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai uint32_t cuid = 0; memset(data, 0x00, 18); - uint8_t* receivedAnswer = mifare_get_bigbufptr(); + uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf(); + uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; if (workFlags & 0x08) { // clear trace @@ -1043,20 +1038,20 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai while (true) { if (workFlags & 0x02) { ReaderTransmitBitsPar(wupC1,7,0, NULL); - if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) { + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); break; }; ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) { + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); break; }; } // read block - if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, NULL) != 18)) { + if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) { if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error"); break; }; diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index 3e5570f9..910ea74d 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -11,6 +11,7 @@ #include "mifaresniff.h" #include "apps.h" + static int sniffState = SNF_INIT; static uint8_t sniffUIDType; static uint8_t sniffUID[8]; @@ -37,7 +38,7 @@ bool MfSniffEnd(void){ return FALSE; } -bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint32_t parity, uint16_t bitCnt, bool reader) { +bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) { if (reader && (len == 1) && (bitCnt == 7)) { // reset on 7-Bit commands from reader sniffState = SNF_INIT; @@ -114,16 +115,16 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint32_t parity, ui sniffBuf[11] = sniffSAK; sniffBuf[12] = 0xFF; sniffBuf[13] = 0xFF; - LogTrace(sniffBuf, 14, 0, parity, true); + LogTrace(sniffBuf, 14, 0, 0, NULL, TRUE); } // intentionally no break; case SNF_CARD_CMD:{ - LogTrace(data, len, 0, parity, true); + LogTrace(data, len, 0, 0, NULL, TRUE); sniffState = SNF_CARD_RESP; timerData = GetTickCount(); break; } case SNF_CARD_RESP:{ - LogTrace(data, len, 0, parity, false); + LogTrace(data, len, 0, 0, NULL, FALSE); sniffState = SNF_CARD_CMD; timerData = GetTickCount(); break; diff --git a/armsrc/mifaresniff.h b/armsrc/mifaresniff.h index 1065fa61..22daffee 100644 --- a/armsrc/mifaresniff.h +++ b/armsrc/mifaresniff.h @@ -39,7 +39,7 @@ #define SNF_UID_7 0 bool MfSniffInit(void); -bool RAMFUNC MfSniffLogic(const uint8_t * data, uint16_t len, uint32_t parity, uint16_t bitCnt, bool reader); +bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader); bool RAMFUNC MfSniffSend(uint16_t maxTimeoutMs); bool intMfSniffSend(); bool MfSniffEnd(void); diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 0b93db8f..5122d0ec 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -22,17 +22,14 @@ int MF_DBGLEVEL = MF_DBG_ALL; // memory management -uint8_t* mifare_get_bigbufptr(void) { - return (((uint8_t *)BigBuf) + MIFARE_BUFF_OFFSET); // was 3560 - tied to other size changes +uint8_t* get_bigbufptr_recvrespbuf(void) { + return (((uint8_t *)BigBuf) + RECV_RESP_OFFSET); } -uint8_t* eml_get_bigbufptr_sendbuf(void) { +uint8_t* get_bigbufptr_recvcmdbuf(void) { return (((uint8_t *)BigBuf) + RECV_CMD_OFFSET); } -uint8_t* eml_get_bigbufptr_recbuf(void) { - return (((uint8_t *)BigBuf) + MIFARE_BUFF_OFFSET); -} -uint8_t* eml_get_bigbufptr_cardmem(void) { - return (((uint8_t *)BigBuf) + CARD_MEMORY); +uint8_t* get_bigbufptr_emlcardmem(void) { + return (((uint8_t *)BigBuf) + CARD_MEMORY_OFFSET); } // crypto1 helpers @@ -53,15 +50,15 @@ void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){ return; } -void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, int len, uint32_t *par) { +void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par) { uint8_t bt = 0; int i; - uint32_t mltpl = 1 << (len - 1); // for len=18 it=0x20000 - *par = 0; + par[0] = 0; for (i = 0; i < len; i++) { bt = data[i]; data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i]; - *par = (*par >> 1) | ( ((filter(pcs->odd) ^ oddparity(bt)) & 0x01) * mltpl ); + if((i&0x0007) == 0) par[i>>3] = 0; + par[i>>3] |= (((filter(pcs->odd) ^ oddparity(bt)) & 0x01)<<(7-(i&0x0007))); } return; } @@ -77,18 +74,18 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) { } // send commands -int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, 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) { - return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, NULL, timing); + return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, timing); } -int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *timing) +int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) { - uint8_t dcmd[8];//, ecmd[4]; - //uint32_t par=0; + uint8_t dcmd[8];//, ecmd[4]; + //uint32_t par=0; - dcmd[0] = cmd; - dcmd[1] = data[0]; + dcmd[0] = cmd; + dcmd[1] = data[0]; dcmd[2] = data[1]; dcmd[3] = data[2]; dcmd[4] = data[3]; @@ -99,7 +96,7 @@ int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint //memcpy(ecmd, dcmd, sizeof(dcmd)); ReaderTransmit(dcmd, sizeof(dcmd), NULL); - int len = ReaderReceive(answer); + int len = ReaderReceive(answer, answer_parity); if(!len) { if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout."); @@ -108,11 +105,11 @@ int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint return len; } -int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t * parptr, uint32_t *timing) +int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) { uint8_t dcmd[4], ecmd[4]; - uint32_t pos, par, res; - + uint16_t pos, res; + uint8_t par[1]; // 1 Byte parity is enough here dcmd[0] = cmd; dcmd[1] = data; AppendCrc14443a(dcmd, 2); @@ -120,11 +117,11 @@ int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cm memcpy(ecmd, dcmd, sizeof(dcmd)); if (crypted) { - par = 0; + par[0] = 0; for (pos = 0; pos < 4; pos++) { ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos]; - par = (par >> 1) | ( ((filter(pcs->odd) ^ oddparity(dcmd[pos])) & 0x01) * 0x08 ); + par[0] |= (((filter(pcs->odd) ^ oddparity(dcmd[pos])) & 0x01) << (7-pos)); } ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing); @@ -133,10 +130,10 @@ int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cm ReaderTransmit(dcmd, sizeof(dcmd), timing); } - int len = ReaderReceivePar(answer, &par); + int len = ReaderReceive(answer, par); + + if (answer_parity) *answer_parity = par[0]; - if (parptr) *parptr = par; - if (crypted == CRYPT_ALL) { if (len == 1) { res = 0; @@ -157,33 +154,35 @@ int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cm } // mifare commands -int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested) +int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested) { return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); } -int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested, uint32_t * ntptr, uint32_t *timing) +int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { // variables int len; uint32_t pos; uint8_t tmp4[4]; - byte_t par = 0; - byte_t ar[4]; + uint8_t par[1] = {0}; + byte_t nr[4]; uint32_t nt, ntpp; // Supplied tag nonce uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t* receivedAnswer = mifare_get_bigbufptr(); - + uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf(); + uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; + // Transmit MIFARE_CLASSIC_AUTH - len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, timing); - if (MF_DBGLEVEL >= 4) Dbprintf("rand nonce len: %x", len); + len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing); + if (MF_DBGLEVEL >= 4) Dbprintf("rand tag nonce len: %x", len); if (len != 4) return 1; - ar[0] = 0x55; - ar[1] = 0x41; - ar[2] = 0x49; - ar[3] = 0x92; + // "random" reader nonce: + nr[0] = 0x55; + nr[1] = 0x41; + nr[2] = 0x49; + nr[3] = 0x92; // Save the tag nonce (nt) nt = bytes_to_num(receivedAnswer, 4); @@ -211,12 +210,13 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN if (ntptr) *ntptr = nt; - par = 0; + // Generate (encrypted) nr+parity by loading it into the cipher (Nr) + par[0] = 0; for (pos = 0; pos < 4; pos++) { - mf_nr_ar[pos] = crypto1_byte(pcs, ar[pos], 0) ^ ar[pos]; - par = (par >> 1) | ( ((filter(pcs->odd) ^ oddparity(ar[pos])) & 0x01) * 0x80 ); + mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos]; + par[0] |= (((filter(pcs->odd) ^ oddparity(nr[pos])) & 0x01) << (7-pos)); } // Skip 32 bits in pseudo random generator @@ -227,14 +227,14 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN { nt = prng_successor(nt,8); mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff); - par = (par >> 1)| ( ((filter(pcs->odd) ^ oddparity(nt & 0xff)) & 0x01) * 0x80 ); + par[0] |= (((filter(pcs->odd) ^ oddparity(nt & 0xff)) & 0x01) << (7-pos)); } // Transmit reader nonce and reader answer ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); - // Receive 4 bit answer - len = ReaderReceive(receivedAnswer); + // Receive 4 byte tag answer + len = ReaderReceive(receivedAnswer, receivedAnswerPar); if (!len) { if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout."); @@ -258,10 +258,11 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo int len; uint8_t bt[2]; - uint8_t* receivedAnswer = mifare_get_bigbufptr(); + uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf(); + uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; // command MIFARE_CLASSIC_READBLOCK - len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer, NULL); + len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL); if (len == 1) { if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); return 1; @@ -285,13 +286,14 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData) { // variables - int len; + uint16_t len; uint8_t bt[2]; - uint8_t* receivedAnswer = mifare_get_bigbufptr(); + uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf(); + uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; // command MIFARE_CLASSIC_READBLOCK - len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer,NULL); + len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL); if (len == 1) { if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); return 1; @@ -318,14 +320,15 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl // variables int len, i; uint32_t pos; - uint32_t par = 0; + uint8_t par[3] = {0}; // enough for 18 Bytes to send byte_t res; uint8_t d_block[18], d_block_enc[18]; - uint8_t* receivedAnswer = mifare_get_bigbufptr(); + uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf(); + uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; // command MIFARE_CLASSIC_WRITEBLOCK - len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer, NULL); + len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL); if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); @@ -336,17 +339,16 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl AppendCrc14443a(d_block, 16); // crypto - par = 0; for (pos = 0; pos < 18; pos++) { d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; - par = (par >> 1) | ( ((filter(pcs->odd) ^ oddparity(d_block[pos])) & 0x01) * 0x20000 ); + par[pos>>3] |= (((filter(pcs->odd) ^ oddparity(d_block[pos])) & 0x01) << (7 - (pos&0x0007))); } ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL); // Receive the response - len = ReaderReceive(receivedAnswer); + len = ReaderReceive(receivedAnswer, receivedAnswerPar); res = 0; for (i = 0; i < 4; i++) @@ -362,72 +364,74 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData) { - // variables - int len; - uint32_t par = 0; + // variables + uint16_t len; + uint8_t par[3] = {0}; // enough for 18 parity bits - uint8_t d_block[18]; - uint8_t* receivedAnswer = mifare_get_bigbufptr(); + uint8_t d_block[18]; + uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf(); + uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; - // command MIFARE_CLASSIC_WRITEBLOCK - len = mifare_sendcmd_short(NULL, 1, 0xA0, blockNo, receivedAnswer,NULL); + // command MIFARE_CLASSIC_WRITEBLOCK + len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL); - if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK - if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); - return 1; - } + if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK + if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); + return 1; + } memset(d_block,'\0',18); memcpy(d_block, blockData, 16); - AppendCrc14443a(d_block, 16); + AppendCrc14443a(d_block, 16); ReaderTransmitPar(d_block, sizeof(d_block), par, NULL); - // Receive the response - len = ReaderReceive(receivedAnswer); + // Receive the response + len = ReaderReceive(receivedAnswer, receivedAnswerPar); if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK - if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len); - return 2; - } + if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len); + return 2; + } - return 0; + return 0; } int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData) { - // variables - int len; - //uint32_t par = 0; + uint16_t len; - uint8_t d_block[8]; - uint8_t* receivedAnswer = mifare_get_bigbufptr(); + uint8_t d_block[8]; + uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf(); + uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; - // command MIFARE_CLASSIC_WRITEBLOCK + // command MIFARE_CLASSIC_WRITEBLOCK memset(d_block,'\0',8); d_block[0]= blockNo; memcpy(d_block+1,blockData,4); AppendCrc14443a(d_block, 6); //i know the data send here is correct - len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer,NULL); + len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL); - if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK - if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len); - return 1; - } - return 0; + if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK + if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len); + return 1; + } + + return 0; } int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) { // variables - int len; + uint16_t len; // Mifare HALT - uint8_t* receivedAnswer = mifare_get_bigbufptr(); + uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf(); + uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; - len = mifare_sendcmd_short(pcs, pcs == NULL ? 0:1, 0x50, 0x00, receivedAnswer, NULL); + len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL); if (len != 0) { if (MF_DBGLEVEL >= 1) Dbprintf("halt error. response len: %x", len); return 1; @@ -438,13 +442,13 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) int mifare_ultra_halt(uint32_t uid) { - // variables - int len; + uint16_t len; // Mifare HALT - uint8_t* receivedAnswer = mifare_get_bigbufptr(); + uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf(); + uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; - len = mifare_sendcmd_short(NULL, 1, 0x50, 0x00, receivedAnswer, NULL); + len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL); if (len != 0) { if (MF_DBGLEVEL >= 1) Dbprintf("halt error. response len: %x", len); return 1; @@ -476,25 +480,25 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo) // work with emulator memory void emlSetMem(uint8_t *data, int blockNum, int blocksCount) { - uint8_t* emCARD = eml_get_bigbufptr_cardmem(); + uint8_t* emCARD = get_bigbufptr_emlcardmem(); memcpy(emCARD + blockNum * 16, data, blocksCount * 16); } void emlGetMem(uint8_t *data, int blockNum, int blocksCount) { - uint8_t* emCARD = eml_get_bigbufptr_cardmem(); + uint8_t* emCARD = get_bigbufptr_emlcardmem(); memcpy(data, emCARD + blockNum * 16, blocksCount * 16); } void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount) { - uint8_t* emCARD = eml_get_bigbufptr_cardmem(); + uint8_t* emCARD = get_bigbufptr_emlcardmem(); memcpy(data, emCARD + bytePtr, byteCount); } int emlCheckValBl(int blockNum) { - uint8_t* emCARD = eml_get_bigbufptr_cardmem(); + uint8_t* emCARD = get_bigbufptr_emlcardmem(); uint8_t* data = emCARD + blockNum * 16; if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) || @@ -509,7 +513,7 @@ int emlCheckValBl(int blockNum) { } int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) { - uint8_t* emCARD = eml_get_bigbufptr_cardmem(); + uint8_t* emCARD = get_bigbufptr_emlcardmem(); uint8_t* data = emCARD + blockNum * 16; if (emlCheckValBl(blockNum)) { @@ -523,7 +527,7 @@ int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) { } int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) { - uint8_t* emCARD = eml_get_bigbufptr_cardmem(); + uint8_t* emCARD = get_bigbufptr_emlcardmem(); uint8_t* data = emCARD + blockNum * 16; memcpy(data + 0, &blReg, 4); @@ -541,7 +545,7 @@ int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) { uint64_t emlGetKey(int sectorNum, int keyType) { uint8_t key[6]; - uint8_t* emCARD = eml_get_bigbufptr_cardmem(); + uint8_t* emCARD = get_bigbufptr_emlcardmem(); memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6); return bytes_to_num(key, 6); @@ -552,9 +556,9 @@ void emlClearMem(void) { const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04}; - uint8_t* emCARD = eml_get_bigbufptr_cardmem(); + uint8_t* emCARD = get_bigbufptr_emlcardmem(); - memset(emCARD, 0, CARD_MEMORY_LEN); + memset(emCARD, 0, CARD_MEMORY_SIZE); // fill sectors trailer data for(b = 3; b < 256; b<127?(b+=4):(b+=16)) { diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 8708d3dd..c8f3dadf 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -16,7 +16,7 @@ #define CRYPT_NONE 0 #define CRYPT_ALL 1 #define CRYPT_REQUEST 2 -#define AUTH_FIRST 0 +#define AUTH_FIRST 0 #define AUTH_NESTED 2 // mifare 4bit card answers @@ -54,14 +54,12 @@ extern int MF_DBGLEVEL; //functions uint8_t* mifare_get_bigbufptr(void); -int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t *timing); -int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* amswer, uint8_t *timing); -int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t * parptr, 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); +int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); +int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); -int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, \ - uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested); -int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, \ - uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested, uint32_t * ntptr, uint32_t *timing); +int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); +int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing); int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); @@ -72,13 +70,13 @@ int mifare_ultra_halt(uint32_t uid); // crypto functions void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len); -void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, int len, uint32_t *par); +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); // memory management -uint8_t* mifare_get_bigbufptr(void); -uint8_t* eml_get_bigbufptr_sendbuf(void); -uint8_t* eml_get_bigbufptr_recbuf(void); +uint8_t* get_bigbufptr_recvrespbuf(void); +uint8_t* get_bigbufptr_recvcmdbuf(void); +uint8_t* get_bigbufptr_emlcardmem(void); // Mifare memory structure uint8_t NumBlocksPerSector(uint8_t sectorNo); diff --git a/client/cmddata.c b/client/cmddata.c index 6416ebbc..9025e8f1 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -860,24 +860,56 @@ int CmdSamples(const char *Cmd) int CmdTuneSamples(const char *Cmd) { - int cnt = 0; - int n = 255; - uint8_t got[255]; - - PrintAndLog("Reading %d samples\n", n); - GetFromBigBuf(got,n,7256); // armsrc/apps.h: #define FREE_BUFFER_OFFSET 7256 - WaitForResponse(CMD_ACK,NULL); - for (int j = 0; j < n; j++) { - GraphBuffer[cnt++] = ((int)got[j]) - 128; - } + int timeout = 0; + printf("\nMeasuring antenna characteristics, please wait..."); + + UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING}; + SendCommand(&c); + + UsbCommand resp; + while(!WaitForResponseTimeout(CMD_MEASURED_ANTENNA_TUNING,&resp,1000)) { + timeout++; + printf("."); + if (timeout > 7) { + PrintAndLog("\nNo response from Proxmark. Aborting..."); + return 1; + } + } + + int peakv, peakf; + int vLf125, vLf134, vHf; + vLf125 = resp.arg[0] & 0xffff; + vLf134 = resp.arg[0] >> 16; + vHf = resp.arg[1] & 0xffff;; + peakf = resp.arg[2] & 0xffff; + peakv = resp.arg[2] >> 16; + PrintAndLog(""); + PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/1000.0); + PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/1000.0); + PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/1000.0, 12000.0/(peakf+1)); + PrintAndLog("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0); + if (peakv<2000) + PrintAndLog("# Your LF antenna is unusable."); + else if (peakv<10000) + PrintAndLog("# Your LF antenna is marginal."); + if (vHf<2000) + PrintAndLog("# Your HF antenna is unusable."); + else if (vHf<5000) + PrintAndLog("# Your HF antenna is marginal."); + + for (int i = 0; i < 256; i++) { + GraphBuffer[i] = resp.d.asBytes[i] - 128; + } - PrintAndLog("Done! Divisor 89 is 134khz, 95 is 125khz.\n"); - PrintAndLog("\n"); - GraphTraceLen = n; - RepaintGraphWindow(); - return 0; + PrintAndLog("Done! Divisor 89 is 134khz, 95 is 125khz.\n"); + PrintAndLog("\n"); + GraphTraceLen = 256; + ShowGraphWindow(); + + return 0; } + int CmdLoad(const char *Cmd) { FILE *f = fopen(Cmd, "r"); diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 39bdcf40..c9976076 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -43,136 +43,131 @@ int CmdHF14AList(const char *Cmd) if (param == 'f') { ShowWaitCycles = true; } - - uint8_t got[1920]; - GetFromBigBuf(got,sizeof(got),0); - WaitForResponse(CMD_ACK,NULL); + +// for the time being. Need better Bigbuf handling. +#define TRACE_SIZE 3000 + + uint8_t trace[TRACE_SIZE]; + GetFromBigBuf(trace, TRACE_SIZE, 0); + WaitForResponse(CMD_ACK, NULL); PrintAndLog("Recorded Activity"); PrintAndLog(""); PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); PrintAndLog("All times are in carrier periods (1/13.56Mhz)"); PrintAndLog(""); - PrintAndLog(" Start | End | Src | Data"); - PrintAndLog("-----------|-----------|-----|--------"); - - int i = 0; - uint32_t first_timestamp = 0; + PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC "); + PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------------"); + + uint16_t tracepos = 0; + uint16_t duration; + uint16_t data_len; + uint16_t parity_len; + bool isResponse; uint32_t timestamp; - uint32_t EndOfTransmissionTimestamp = 0; + uint32_t first_timestamp; + uint32_t EndOfTransmissionTimestamp; for (;;) { - if(i >= 1900) { + + if(tracepos >= TRACE_SIZE) { break; } - bool isResponse; - timestamp = *((uint32_t *)(got+i)); - if (timestamp & 0x80000000) { - timestamp &= 0x7fffffff; + timestamp = *((uint32_t *)(trace + tracepos)); + if(tracepos == 0) { + first_timestamp = timestamp; + } + + // Break and stick with current result if buffer was not completely full + if (timestamp == 0x44444444) break; + + tracepos += 4; + duration = *((uint16_t *)(trace + tracepos)); + tracepos += 2; + data_len = *((uint16_t *)(trace + tracepos)); + tracepos += 2; + + if (data_len & 0x8000) { + data_len &= 0x7fff; isResponse = true; } else { isResponse = false; } - if(i==0) { - first_timestamp = timestamp; - } - - int parityBits = *((uint32_t *)(got+i+4)); - - int len = got[i+8]; + parity_len = (data_len-1)/8 + 1; - if (len > 100) { + if (tracepos + data_len + parity_len >= TRACE_SIZE) { break; } - if (i + len >= 1900) { - break; - } - - uint8_t *frame = (got+i+9); - - // Break and stick with current result if buffer was not completely full - if (frame[0] == 0x44 && frame[1] == 0x44 && frame[2] == 0x44 && frame[3] == 0x44) break; + + uint8_t *frame = trace + tracepos; + tracepos += data_len; + uint8_t *parityBytes = trace + tracepos; + tracepos += parity_len; + + char line[16][110]; + for (int j = 0; j < data_len; j++) { + int oddparity = 0x01; + int k; + + for (k=0;k<8;k++) { + oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); + } - char line[1000] = ""; - int j; - if (len) { - for (j = 0; j < len; j++) { - int oddparity = 0x01; - int k; + uint8_t parityBits = parityBytes[j>>3]; + if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { + sprintf(line[j/16]+((j%16)*4), "%02x! ", frame[j]); + } else { + sprintf(line[j/16]+((j%16)*4), "%02x ", frame[j]); + } - for (k=0;k<8;k++) { - oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); - } + } - //if((parityBits >> (len - j - 1)) & 0x01) { - if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) { - sprintf(line+(j*4), "%02x! ", frame[j]); - } else { - sprintf(line+(j*4), "%02x ", frame[j]); - } - } - } else { - if (ShowWaitCycles) { - uint32_t next_timestamp = (*((uint32_t *)(got+i+9))) & 0x7fffffff; - sprintf(line, "fdt (Frame Delay Time): %d", (next_timestamp - timestamp)); + char crc[5] = ""; + if (data_len > 2) { + uint8_t b1, b2; + ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2); + if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { + sprintf(crc, (isResponse & (data_len < 6)) ? "" : "!crc"); + } else { + sprintf(crc, ""); } } - char *crc; - crc = ""; - if (len > 2) { - uint8_t b1, b2; - for (j = 0; j < (len - 1); j++) { - // gives problems... search for the reason.. - /*if(frame[j] == 0xAA) { - switch(frame[j+1]) { - case 0x01: - crc = "[1] Two drops close after each other"; - break; - case 0x02: - crc = "[2] Potential SOC with a drop in second half of bitperiod"; - break; - case 0x03: - crc = "[3] Segment Z after segment X is not possible"; - break; - case 0x04: - crc = "[4] Parity bit of a fully received byte was wrong"; - break; - default: - crc = "[?] Unknown error"; - break; - } - break; - }*/ + EndOfTransmissionTimestamp = timestamp + duration; + + int num_lines = (data_len - 1)/16 + 1; + for (int j = 0; j < num_lines; j++) { + if (j == 0) { + PrintAndLog(" %9d | %9d | %s | %-64s| %s", + (timestamp - first_timestamp), + (EndOfTransmissionTimestamp - first_timestamp), + (isResponse ? "Tag" : "Rdr"), + line[j], + (j == num_lines-1)?crc:""); + } else { + PrintAndLog(" | | | %-64s| %s", + line[j], + (j == num_lines-1)?crc:""); } + } - if (strlen(crc)==0) { - ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2); - if (b1 != frame[len-2] || b2 != frame[len-1]) { - crc = (isResponse & (len < 6)) ? "" : " !crc"; - } else { - crc = ""; - } + bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000; + + if (ShowWaitCycles && !isResponse && next_isResponse) { + uint32_t next_timestamp = *((uint32_t *)(trace + tracepos)); + if (next_timestamp != 0x44444444) { + PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d", + (EndOfTransmissionTimestamp - first_timestamp), + (next_timestamp - first_timestamp), + " ", + (next_timestamp - EndOfTransmissionTimestamp)); } - } else { - crc = ""; // SHORT } - - i += (len + 9); - - EndOfTransmissionTimestamp = (*((uint32_t *)(got+i))) & 0x7fffffff; - - if (!ShowWaitCycles) i += 9; - - PrintAndLog(" %9d | %9d | %s | %s %s", - (timestamp - first_timestamp), - (EndOfTransmissionTimestamp - first_timestamp), - (len?(isResponse ? "Tag" : "Rdr"):" "), - line, crc); - + } + return 0; } @@ -196,6 +191,11 @@ int CmdHF14AReader(const char *Cmd) if(select_status == 0) { PrintAndLog("iso14443a card select failed"); + // disconnect + c.arg[0] = 0; + c.arg[1] = 0; + c.arg[2] = 0; + SendCommand(&c); return 0; } diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index 8a36d6ae..8f6a6af2 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -54,10 +54,10 @@ int CmdHFEPACollectPACENonces(const char *Cmd) size_t nonce_length = resp.arg[1]; char *nonce = (char *) malloc(2 * nonce_length + 1); for(int j = 0; j < nonce_length; j++) { - snprintf(nonce + (2 * j), 3, "%02X", resp.d.asBytes[j]); + sprintf(nonce + (2 * j), "%02X", resp.d.asBytes[j]); } // print nonce - PrintAndLog("Length: %d, Nonce: %s",resp.arg[1], nonce); + PrintAndLog("Length: %d, Nonce: %s", nonce_length, nonce); } if (i < n - 1) { sleep(d); diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index d9af9044..583d518e 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -44,10 +44,9 @@ int xorbits_8(uint8_t val) int CmdHFiClassList(const char *Cmd) { - bool ShowWaitCycles = false; char param = param_getchar(Cmd, 0); - + if (param != 0) { PrintAndLog("List data in trace buffer."); PrintAndLog("Usage: hf iclass list"); @@ -56,254 +55,149 @@ int CmdHFiClassList(const char *Cmd) return 0; } - uint8_t got[1920]; - GetFromBigBuf(got,sizeof(got),0); - WaitForResponse(CMD_ACK,NULL); +// for the time being. Need better Bigbuf handling. +#define TRACE_SIZE 3000 + + uint8_t trace[TRACE_SIZE]; + GetFromBigBuf(trace, TRACE_SIZE, 0); + WaitForResponse(CMD_ACK, NULL); PrintAndLog("Recorded Activity"); PrintAndLog(""); PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); PrintAndLog("All times are in carrier periods (1/13.56Mhz)"); PrintAndLog(""); - PrintAndLog(" Start | End | Src | Data"); - PrintAndLog("-----------|-----------|-----|--------"); - - int i; - uint32_t first_timestamp = 0; + PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC "); + PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------------"); + + uint16_t tracepos = 0; + uint16_t duration; + uint16_t data_len; + uint16_t parity_len; + bool isResponse; uint32_t timestamp; - bool tagToReader; - uint32_t parityBits; - uint8_t len; - uint8_t *frame; - uint32_t EndOfTransmissionTimestamp = 0; + uint32_t first_timestamp; + uint32_t EndOfTransmissionTimestamp; + + for (;;) { + if(tracepos >= TRACE_SIZE) { + break; + } - for( i=0; i < 1900;) - { - //First 32 bits contain - // isResponse (1 bit) - // timestamp (remaining) - //Then paritybits - //Then length - timestamp = *((uint32_t *)(got+i)); - parityBits = *((uint32_t *)(got+i+4)); - len = got[i+8]; - frame = (got+i+9); - uint32_t next_timestamp = (*((uint32_t *)(got+i+9))) & 0x7fffffff; - - tagToReader = timestamp & 0x80000000; - timestamp &= 0x7fffffff; - - if(i==0) { + timestamp = *((uint32_t *)(trace + tracepos)); + if(tracepos == 0) { first_timestamp = timestamp; } - // Break and stick with current result idf buffer was not completely full - if (frame[0] == 0x44 && frame[1] == 0x44 && frame[2] == 0x44 && frame[3] == 0x44) break; - - char line[1000] = ""; - - if(len)//We have some data to display - { - int j,oddparity; + // Break and stick with current result if buffer was not completely full + if (timestamp == 0x44444444) break; + + tracepos += 4; + duration = *((uint16_t *)(trace + tracepos)); + tracepos += 2; + data_len = *((uint16_t *)(trace + tracepos)); + tracepos += 2; + + if (data_len & 0x8000) { + data_len &= 0x7fff; + isResponse = true; + } else { + isResponse = false; + } - for(j = 0; j < len ; j++) - { - oddparity = 0x01 ^ xorbits_8(frame[j] & 0xFF); + parity_len = (data_len-1)/8 + 1; - if (tagToReader && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) { - sprintf(line+(j*4), "%02x! ", frame[j]); - } else { - sprintf(line+(j*4), "%02x ", frame[j]); - } + if (tracepos + data_len + parity_len >= TRACE_SIZE) { + break; + } + + uint8_t *frame = trace + tracepos; + tracepos += data_len; + uint8_t *parityBytes = trace + tracepos; + tracepos += parity_len; + + char line[16][110]; + for (int j = 0; j < data_len; j++) { + int oddparity = 0x01; + int k; + + for (k=0;k<8;k++) { + oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); } - }else - { - if (ShowWaitCycles) { - sprintf(line, "fdt (Frame Delay Time): %d", (next_timestamp - timestamp)); + + uint8_t parityBits = parityBytes[j>>3]; + if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { + sprintf(line[j/16]+((j%16)*4), "%02x! ", frame[j]); + } else { + sprintf(line[j/16]+((j%16)*4), "%02x ", frame[j]); } - } - char *crc = ""; + } - if(len > 2) - { + char *crc = ""; + if (data_len > 2) { uint8_t b1, b2; - if(!tagToReader && len == 4) { + if(!isResponse && data_len == 4 ) { // Rough guess that this is a command from the reader // For iClass the command byte is not part of the CRC - ComputeCrc14443(CRC_ICLASS, &frame[1], len-3, &b1, &b2); + ComputeCrc14443(CRC_ICLASS, &frame[1], data_len-3, &b1, &b2); + if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { + crc = "!crc"; + } } else { - // For other data.. CRC might not be applicable (UPDATE commands etc.) - ComputeCrc14443(CRC_ICLASS, frame, len-2, &b1, &b2); + // For other data.. CRC might not be applicable (UPDATE commands etc.) + ComputeCrc14443(CRC_ICLASS, frame, data_len-2, &b1, &b2); + if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { + crc = "!crc"; + } } + } - if (b1 != frame[len-2] || b2 != frame[len-1]) { - crc = (tagToReader & (len < 8)) ? "" : " !crc"; + EndOfTransmissionTimestamp = timestamp + duration; + + int num_lines = (data_len - 1)/16 + 1; + for (int j = 0; j < num_lines; j++) { + if (j == 0) { + PrintAndLog(" %9d | %9d | %s | %-64s| %s", + (timestamp - first_timestamp), + (EndOfTransmissionTimestamp - first_timestamp), + (isResponse ? "Tag" : "Rdr"), + line[j], + (j == num_lines-1)?crc:""); + } else { + PrintAndLog(" | | | %-64s| %s", + line[j], + (j == num_lines-1)?crc:""); + } + } + + bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000; + + if (ShowWaitCycles && !isResponse && next_isResponse) { + uint32_t next_timestamp = *((uint32_t *)(trace + tracepos)); + if (next_timestamp != 0x44444444) { + PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d", + (EndOfTransmissionTimestamp - first_timestamp), + (next_timestamp - first_timestamp), + " ", + (next_timestamp - EndOfTransmissionTimestamp)); } } - - i += (len + 9); - EndOfTransmissionTimestamp = (*((uint32_t *)(got+i))) & 0x7fffffff; - - // Not implemented for iclass on the ARM-side - //if (!ShowWaitCycles) i += 9; - - PrintAndLog(" %9d | %9d | %s | %s %s", - (timestamp - first_timestamp), - (EndOfTransmissionTimestamp - first_timestamp), - (len?(tagToReader ? "Tag" : "Rdr"):" "), - line, crc); + } + return 0; } -int CmdHFiClassListOld(const char *Cmd) -{ - uint8_t got[1920]; - GetFromBigBuf(got,sizeof(got),0); - - PrintAndLog("recorded activity:"); - PrintAndLog(" ETU :rssi: who bytes"); - PrintAndLog("---------+----+----+-----------"); - - int i = 0; - int prev = -1; - - for (;;) { - if(i >= 1900) { - break; - } - - bool isResponse; - int timestamp = *((uint32_t *)(got+i)); - if (timestamp & 0x80000000) { - timestamp &= 0x7fffffff; - isResponse = 1; - } else { - isResponse = 0; - } - - - int metric = 0; - - int parityBits = *((uint32_t *)(got+i+4)); - // 4 bytes of additional information... - // maximum of 32 additional parity bit information - // - // TODO: - // at each quarter bit period we can send power level (16 levels) - // or each half bit period in 256 levels. - - - int len = got[i+8]; - - if (len > 100) { - break; - } - if (i + len >= 1900) { - break; - } - - uint8_t *frame = (got+i+9); - - // Break and stick with current result if buffer was not completely full - if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; } - - char line[1000] = ""; - int j; - for (j = 0; j < len; j++) { - int oddparity = 0x01; - int k; - - for (k=0;k<8;k++) { - oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); - } - - //if((parityBits >> (len - j - 1)) & 0x01) { - if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) { - sprintf(line+(j*4), "%02x! ", frame[j]); - } - else { - sprintf(line+(j*4), "%02x ", frame[j]); - } - } - - char *crc; - crc = ""; - if (len > 2) { - uint8_t b1, b2; - for (j = 0; j < (len - 1); j++) { - // gives problems... search for the reason.. - /*if(frame[j] == 0xAA) { - switch(frame[j+1]) { - case 0x01: - crc = "[1] Two drops close after each other"; - break; - case 0x02: - crc = "[2] Potential SOC with a drop in second half of bitperiod"; - break; - case 0x03: - crc = "[3] Segment Z after segment X is not possible"; - break; - case 0x04: - crc = "[4] Parity bit of a fully received byte was wrong"; - break; - default: - crc = "[?] Unknown error"; - break; - } - break; - }*/ - } - - if (strlen(crc)==0) { - if(!isResponse && len == 4) { - // Rough guess that this is a command from the reader - // For iClass the command byte is not part of the CRC - ComputeCrc14443(CRC_ICLASS, &frame[1], len-3, &b1, &b2); - } - else { - // For other data.. CRC might not be applicable (UPDATE commands etc.) - ComputeCrc14443(CRC_ICLASS, frame, len-2, &b1, &b2); - } - //printf("%1x %1x",(unsigned)b1,(unsigned)b2); - if (b1 != frame[len-2] || b2 != frame[len-1]) { - crc = (isResponse & (len < 8)) ? "" : " !crc"; - } else { - crc = ""; - } - } - } else { - crc = ""; // SHORT - } - - char metricString[100]; - if (isResponse) { - sprintf(metricString, "%3d", metric); - } else { - strcpy(metricString, " "); - } - - PrintAndLog(" +%7d: %s: %s %s %s", - (prev < 0 ? 0 : (timestamp - prev)), - metricString, - (isResponse ? "TAG" : " "), line, crc); - - prev = timestamp; - i += (len + 9); - } - return 0; -} - int CmdHFiClassSnoop(const char *Cmd) { UsbCommand c = {CMD_SNOOP_ICLASS}; SendCommand(&c); return 0; } - +#define NUM_CSNS 15 int CmdHFiClassSim(const char *Cmd) { uint8_t simType = 0; @@ -340,10 +234,10 @@ int CmdHFiClassSim(const char *Cmd) if(simType == 2) { - UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,63}}; + UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}}; UsbCommand resp = {0}; - uint8_t csns[64] = { + /*uint8_t csns[8 * NUM_CSNS] = { 0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0 , 0x00,0x13,0x94,0x7e,0x76,0xff,0x12,0xe0 , 0x2a,0x99,0xac,0x79,0xec,0xff,0x12,0xe0 , @@ -352,8 +246,26 @@ int CmdHFiClassSim(const char *Cmd) 0x4b,0x5e,0x0b,0x72,0xef,0xff,0x12,0xe0 , 0x00,0x73,0xd8,0x75,0x58,0xff,0x12,0xe0 , 0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 }; - - memcpy(c.d.asBytes, csns, 64); +*/ + + uint8_t csns[8*NUM_CSNS] = { + 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 }; + + memcpy(c.d.asBytes, csns, 8*NUM_CSNS); SendCommand(&c); if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) { @@ -362,9 +274,9 @@ int CmdHFiClassSim(const char *Cmd) } uint8_t num_mac_responses = resp.arg[1]; - PrintAndLog("Mac responses: %d MACs obtained (should be 8)", num_mac_responses); + PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS); - size_t datalen = 8*24; + size_t datalen = NUM_CSNS*24; /* * Now, time to dump to file. We'll use this format: * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>.... @@ -378,7 +290,7 @@ int CmdHFiClassSim(const char *Cmd) void* dump = malloc(datalen); memset(dump,0,datalen);//<-- Need zeroes for the CC-field uint8_t i = 0; - for(i = 0 ; i < 8 ; i++) + for(i = 0 ; i < NUM_CSNS ; i++) { memcpy(dump+i*24, csns+i*8,8); //CSN //8 zero bytes here... @@ -495,17 +407,31 @@ int CmdHFiClassReader_Dump(const char *Cmd) } + UsbCommand resp; + uint8_t key_sel[8] = {0}; + uint8_t key_sel_p[8] = { 0 }; + + //HACK -- Below is for testing without access to a tag + uint8_t fake_dummy_test = false; + if(fake_dummy_test) + { + uint8_t xdata[16] = {0x01,0x02,0x03,0x04,0xF7,0xFF,0x12,0xE0, //CSN from http://www.proxmark.org/forum/viewtopic.php?pid=11230#p11230 + 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; // Just a random CC. Would be good to add a real testcase here + memcpy(resp.d.asBytes,xdata, 16); + resp.arg[0] = 2; + } + + //End hack + UsbCommand c = {CMD_READER_ICLASS, {0}}; c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE; - - SendCommand(&c); + if(!fake_dummy_test) + SendCommand(&c); - UsbCommand resp; - uint8_t key_sel[8] = {0}; - uint8_t key_sel_p[8] = { 0 }; - if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) { + + if (fake_dummy_test || WaitForResponseTimeout(CMD_ACK,&resp,4500)) { uint8_t isOK = resp.arg[0] & 0xff; uint8_t * data = resp.d.asBytes; @@ -529,6 +455,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) printvar("hash1", key_index,8); for(i = 0; i < 8 ; i++) key_sel[i] = keytable[key_index[i]] & 0xFF; + PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:"); printvar("k_sel", key_sel,8); //Permute from iclass format to standard format permutekey_rev(key_sel,key_sel_p); @@ -545,8 +472,11 @@ int CmdHFiClassReader_Dump(const char *Cmd) used_key = KEY; } + + PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:"); printvar("Used key",used_key,8); diversifyKey(CSN,used_key, div_key); + PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):"); printvar("Div key", div_key, 8); printvar("CC_NR:",CCNR,12); doMAC(CCNR,12,div_key, MAC); @@ -554,7 +484,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}}; memcpy(d.d.asBytes, MAC, 4); - SendCommand(&d); + if(!fake_dummy_test) SendCommand(&d); }else{ PrintAndLog("Failed to obtain CC! Aborting"); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index bdb0e7e7..6d0bebd7 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1894,7 +1894,6 @@ int CmdHF14AMfSniff(const char *Cmd){ uint8_t atqa[2]; uint8_t sak; bool isTag; - uint32_t parity; uint8_t buf[3000]; uint8_t * bufPtr = buf; memset(buf, 0x00, 3000); @@ -1961,14 +1960,17 @@ int CmdHF14AMfSniff(const char *Cmd){ printf(">\n"); PrintAndLog("received trace len: %d packages: %d", blockLen, pckNum); num = 0; - while (bufPtr - buf + 9 < blockLen) { - isTag = bufPtr[3] & 0x80 ? true:false; - bufPtr += 4; - parity = *((uint32_t *)(bufPtr)); - bufPtr += 4; - len = bufPtr[0]; - bufPtr++; - if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff)) { + while (bufPtr - buf < blockLen) { + bufPtr += 6; // ignore void timing information + len = *((uint16_t *)bufPtr); + if(len & 0x8000) { + isTag = true; + len &= 0x7fff; + } else { + isTag = false; + } + bufPtr += 2; + if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[12] == 0xff) && (bufPtr[13] == 0xff)) { memcpy(uid, bufPtr + 2, 7); memcpy(atqa, bufPtr + 2 + 7, 2); uid_len = (atqa[0] & 0xC0) == 0x40 ? 7 : 4; @@ -1987,9 +1989,10 @@ int CmdHF14AMfSniff(const char *Cmd){ } else { PrintAndLog("%s(%d):%s", isTag ? "TAG":"RDR", num, sprint_hex(bufPtr, len)); if (wantLogToFile) AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len); - if (wantDecrypt) mfTraceDecode(bufPtr, len, parity, wantSaveToEmlFile); + if (wantDecrypt) mfTraceDecode(bufPtr, len, wantSaveToEmlFile); } bufPtr += len; + bufPtr += ((len-1)/8+1); // ignore parity num++; } } diff --git a/client/cmdhw.c b/client/cmdhw.c index 4f0f3e38..443973b8 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -18,6 +18,7 @@ #include "cmdparser.h" #include "cmdhw.h" #include "cmdmain.h" +#include "cmddata.h" /* low-level hardware control */ @@ -391,9 +392,7 @@ int CmdSetMux(const char *Cmd) int CmdTune(const char *Cmd) { - UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING}; - SendCommand(&c); - return 0; + return CmdTuneSamples(Cmd); } int CmdVersion(const char *Cmd) diff --git a/client/cmdmain.c b/client/cmdmain.c index 77f1c373..b2723490 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -206,28 +206,28 @@ void UsbCommandReceived(UsbCommand *UC) return; } break; - case CMD_MEASURED_ANTENNA_TUNING: { - int peakv, peakf; - int vLf125, vLf134, vHf; - vLf125 = UC->arg[0] & 0xffff; - vLf134 = UC->arg[0] >> 16; - vHf = UC->arg[1] & 0xffff;; - peakf = UC->arg[2] & 0xffff; - peakv = UC->arg[2] >> 16; - PrintAndLog(""); - PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/1000.0); - PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/1000.0); - PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/1000.0, 12000.0/(peakf+1)); - PrintAndLog("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0); - if (peakv<2000) - PrintAndLog("# Your LF antenna is unusable."); - else if (peakv<10000) - PrintAndLog("# Your LF antenna is marginal."); - if (vHf<2000) - PrintAndLog("# Your HF antenna is unusable."); - else if (vHf<5000) - PrintAndLog("# Your HF antenna is marginal."); - } break; + // case CMD_MEASURED_ANTENNA_TUNING: { + // int peakv, peakf; + // int vLf125, vLf134, vHf; + // vLf125 = UC->arg[0] & 0xffff; + // vLf134 = UC->arg[0] >> 16; + // vHf = UC->arg[1] & 0xffff;; + // peakf = UC->arg[2] & 0xffff; + // peakv = UC->arg[2] >> 16; + // PrintAndLog(""); + // PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/1000.0); + // PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/1000.0); + // PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/1000.0, 12000.0/(peakf+1)); + // PrintAndLog("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0); + // if (peakv<2000) + // PrintAndLog("# Your LF antenna is unusable."); + // else if (peakv<10000) + // PrintAndLog("# Your LF antenna is marginal."); + // if (vHf<2000) + // PrintAndLog("# Your HF antenna is unusable."); + // else if (vHf<5000) + // PrintAndLog("# Your HF antenna is marginal."); + // } break; case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: { // printf("received samples: "); diff --git a/client/loclass/elite_crack.c b/client/loclass/elite_crack.c index 1a464b6c..7dc60396 100644 --- a/client/loclass/elite_crack.c +++ b/client/loclass/elite_crack.c @@ -113,9 +113,9 @@ void hash1(uint8_t csn[] , uint8_t k[]) k[0] = csn[0]^csn[1]^csn[2]^csn[3]^csn[4]^csn[5]^csn[6]^csn[7]; k[1] = csn[0]+csn[1]+csn[2]+csn[3]+csn[4]+csn[5]+csn[6]+csn[7]; k[2] = rr(swap( csn[2]+k[1] )); - k[3] = rr(swap( csn[3]+k[0] )); - k[4] = ~rr(swap( csn[4]+k[2] ))+1; - k[5] = ~rr(swap( csn[5]+k[3] ))+1; + k[3] = rl(swap( csn[3]+k[0] )); + k[4] = ~rr( csn[4]+k[2] )+1; + k[5] = ~rl( csn[5]+k[3] )+1; k[6] = rr( csn[6]+(k[4]^0x3c) ); k[7] = rl( csn[7]+(k[5]^0xc3) ); int i; diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 8c08c9ee..255aa313 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -18,7 +18,7 @@ int fileExists(const char *filename) { int saveFile(const char *preferredName, const char *suffix, const void* data, size_t datalen) { - int size = sizeof(char) * (strlen(preferredName)+strlen(suffix)+5); + int size = sizeof(char) * (strlen(preferredName)+strlen(suffix)+10); char * fileName = malloc(size); memset(fileName,0,size); @@ -34,13 +34,14 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si /*Opening file for writing in binary mode*/ FILE *fileHandle=fopen(fileName,"wb"); if(!fileHandle) { - prnlog("Failed to write to file '%s'", fileName); + PrintAndLog("Failed to write to file '%s'", fileName); free(fileName); return 1; } fwrite(data, 1, datalen, fileHandle); fclose(fileHandle); - prnlog("Saved data to '%s'", fileName); + PrintAndLog(">Saved data to '%s'", fileName); + free(fileName); return 0; diff --git a/client/mifarehost.c b/client/mifarehost.c index 2a1f8a48..378fb2e5 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -238,7 +238,7 @@ int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) { // "MAGIC" CARD -int mfCSetUID(uint8_t *uid, uint8_t *oldUID, int wantWipe) { +int mfCSetUID(uint8_t *uid, uint8_t *oldUID, bool wantWipe) { uint8_t block0[16]; memset(block0, 0, 16); memcpy(block0, uid, 4); @@ -251,7 +251,7 @@ int mfCSetUID(uint8_t *uid, uint8_t *oldUID, int wantWipe) { return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER); } -int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, int wantWipe, uint8_t params) { +int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uint8_t params) { uint8_t isOK = 0; UsbCommand c = {CMD_MIFARE_EML_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}}; @@ -310,12 +310,9 @@ uint32_t ks3; uint32_t uid; // serial number uint32_t nt; // tag challenge -uint32_t nt_par; uint32_t nr_enc; // encrypted reader challenge uint32_t ar_enc; // encrypted reader response -uint32_t nr_ar_par; uint32_t at_enc; // encrypted tag response -uint32_t at_par; int isTraceCardEmpty(void) { return ((traceCard[0] == 0) && (traceCard[1] == 0) && (traceCard[2] == 0) && (traceCard[3] == 0)); @@ -424,7 +421,7 @@ void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool i } -int mfTraceDecode(uint8_t *data_src, int len, uint32_t parity, bool wantSaveToEmlFile) { +int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { uint8_t data[64]; if (traceState == TRACE_ERROR) return 1; @@ -527,7 +524,6 @@ int mfTraceDecode(uint8_t *data_src, int len, uint32_t parity, bool wantSaveToEm traceState = TRACE_AUTH2; nt = bytes_to_num(data, 4); - nt_par = parity; return 0; } else { traceState = TRACE_ERROR; @@ -541,7 +537,6 @@ int mfTraceDecode(uint8_t *data_src, int len, uint32_t parity, bool wantSaveToEm nr_enc = bytes_to_num(data, 4); ar_enc = bytes_to_num(data + 4, 4); - nr_ar_par = parity; return 0; } else { traceState = TRACE_ERROR; @@ -554,7 +549,6 @@ int mfTraceDecode(uint8_t *data_src, int len, uint32_t parity, bool wantSaveToEm traceState = TRACE_IDLE; at_enc = bytes_to_num(data, 4); - at_par = parity; // decode key here) ks2 = ar_enc ^ prng_successor(nt, 64); diff --git a/client/mifarehost.h b/client/mifarehost.h index 5de082ce..cb99a407 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -56,12 +56,12 @@ int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * key int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount); int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); -int mfCSetUID(uint8_t *uid, uint8_t *oldUID, int wantWipe); -int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, int wantWipe, uint8_t params); +int mfCSetUID(uint8_t *uid, uint8_t *oldUID, bool wantWipe); +int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uint8_t params); int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params); int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile); -int mfTraceDecode(uint8_t *data_src, int len, uint32_t parity, bool wantSaveToEmlFile); +int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile); int isTraceCardEmpty(void); int isBlockEmpty(int blockN);