X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/ff7bb4ef177ba1c680dd9af5a1e30d4f7f29c65f..6db28145eacac986d481ceadf7ee9fc1061555fd:/armsrc/iclass.c?ds=sidebyside diff --git a/armsrc/iclass.c b/armsrc/iclass.c index bfa4a730..d5cd366d 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -48,17 +48,6 @@ static int timeout = 4096; -// CARD TO READER -// Sequence D: 11110000 modulation with subcarrier during first half -// Sequence E: 00001111 modulation with subcarrier during second half -// Sequence F: 00000000 no modulation with subcarrier -// READER TO CARD -// Sequence X: 00001100 drop after half a period -// Sequence Y: 00000000 no drop -// Sequence Z: 11000000 drop at start -#define SEC_X 0x0c -#define SEC_Y 0x00 -#define SEC_Z 0xc0 static int SendIClassAnswer(uint8_t *resp, int respLen, int delay); @@ -666,12 +655,7 @@ static RAMFUNC int ManchesterDecoding(int v) //----------------------------------------------------------------------------- void RAMFUNC SnoopIClass(void) { -// DEFINED ABOVE -// #define RECV_CMD_OFFSET 3032 -// #define RECV_RES_OFFSET 3096 -// #define DMA_BUFFER_OFFSET 3160 -// #define DMA_BUFFER_SIZE 4096 -// #define TRACE_SIZE 3000 + // We won't start recording the frames that we acquire until we trigger; // a good trigger condition to get started is probably when we see a @@ -681,14 +665,12 @@ void RAMFUNC SnoopIClass(void) // 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 *readerToTagCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET); // The response (tag -> reader) that we're receiving. - uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET); + uint8_t *tagToReaderResponse = (((uint8_t *)BigBuf) + RECV_RES_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; - + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // reset traceLen to 0 iso14a_set_tracing(TRUE); iso14a_clear_trace(); @@ -706,10 +688,8 @@ void RAMFUNC SnoopIClass(void) int samples = 0; rsamples = 0; - memset(trace, 0x44, RECV_CMD_OFFSET); - // Set up the demodulator for tag -> reader responses. - Demod.output = receivedResponse; + Demod.output = tagToReaderResponse; Demod.len = 0; Demod.state = DEMOD_UNSYNCD; @@ -721,7 +701,7 @@ void RAMFUNC SnoopIClass(void) // And the reader -> tag commands memset(&Uart, 0, sizeof(Uart)); - Uart.output = receivedCmd; + Uart.output = readerToTagCmd; Uart.byteCntMax = 32; // was 100 (greg)//////////////////////////////////////////////////////////////////////// Uart.state = STATE_UNSYNCD; @@ -731,6 +711,9 @@ void RAMFUNC SnoopIClass(void) FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER); SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + uint32_t time_0 = GetCountSspClk(); + + int div = 0; //int div2 = 0; int decbyte = 0; @@ -764,20 +747,13 @@ void RAMFUNC SnoopIClass(void) //samples += 4; samples += 1; - //div2++; - //if(div2 > 3) { - //div2 = 0; - //decbyte ^= ((smpl & 0x01) << (3 - div)); - //decbyte ^= (((smpl & 0x01) | ((smpl & 0x02) >> 1)) << (3 - div)); // better already... - //decbyte ^= (((smpl & 0x01) | ((smpl & 0x02) >> 1) | ((smpl & 0x04) >> 2)) << (3 - div)); // even better... if(smpl & 0xF) { decbyte ^= (1 << (3 - div)); } - //decbyte ^= (MajorityNibble[(smpl & 0x0F)] << (3 - div)); // FOR READER SIDE COMMUMICATION... - //decbyte ^= ((smpl & 0x10) << (3 - div)); + decbyter <<= 2; decbyter ^= (smpl & 0x30); @@ -788,21 +764,17 @@ void RAMFUNC SnoopIClass(void) if(OutOfNDecoding((smpl & 0xF0) >> 4)) { rsamples = samples - Uart.samples; LED_C_ON(); - //if(triggered) { - trace[traceLen++] = ((rsamples >> 0) & 0xff); - trace[traceLen++] = ((rsamples >> 8) & 0xff); - trace[traceLen++] = ((rsamples >> 16) & 0xff); - trace[traceLen++] = ((rsamples >> 24) & 0xff); - trace[traceLen++] = ((Uart.parityBits >> 0) & 0xff); - trace[traceLen++] = ((Uart.parityBits >> 8) & 0xff); - trace[traceLen++] = ((Uart.parityBits >> 16) & 0xff); - trace[traceLen++] = ((Uart.parityBits >> 24) & 0xff); - trace[traceLen++] = Uart.byteCnt; - memcpy(trace+traceLen, receivedCmd, Uart.byteCnt); - traceLen += Uart.byteCnt; - if(traceLen > TRACE_SIZE) break; - //} - /* And ready to receive another command. */ + + //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); + } + + + /* And ready to receive another command. */ Uart.state = STATE_UNSYNCD; /* And also reset the demod code, which might have been */ /* false-triggered by the commands from the reader. */ @@ -819,26 +791,16 @@ void RAMFUNC SnoopIClass(void) rsamples = samples - Demod.samples; LED_B_ON(); - // timestamp, as a count of samples - trace[traceLen++] = ((rsamples >> 0) & 0xff); - trace[traceLen++] = ((rsamples >> 8) & 0xff); - trace[traceLen++] = ((rsamples >> 16) & 0xff); - trace[traceLen++] = 0x80 | ((rsamples >> 24) & 0xff); - trace[traceLen++] = ((Demod.parityBits >> 0) & 0xff); - trace[traceLen++] = ((Demod.parityBits >> 8) & 0xff); - trace[traceLen++] = ((Demod.parityBits >> 16) & 0xff); - trace[traceLen++] = ((Demod.parityBits >> 24) & 0xff); - // length - trace[traceLen++] = Demod.len; - memcpy(trace+traceLen, receivedResponse, Demod.len); - traceLen += Demod.len; - if(traceLen > TRACE_SIZE) break; - - //triggered = TRUE; + if(tracing) + { + LogTrace(Demod.output,Demod.len, (GetCountSspClk()-time_0) << 4 , Demod.parityBits,FALSE); + LogTrace(NULL, 0, (GetCountSspClk()-time_0) << 4, 0, FALSE); + } + // And ready to receive another response. memset(&Demod, 0, sizeof(Demod)); - Demod.output = receivedResponse; + Demod.output = tagToReaderResponse; Demod.state = DEMOD_UNSYNCD; LED_C_OFF(); } @@ -922,6 +884,8 @@ static int GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) //----------------------------------------------------------------------------- static void CodeIClassTagAnswer(const uint8_t *cmd, int len) { + //So far a dummy implementation, not used + //int lastProxToAirDuration =0; int i; ToSendReset(); @@ -930,7 +894,7 @@ static void CodeIClassTagAnswer(const uint8_t *cmd, int len) ToSend[++ToSendMax] = 0x00; ToSend[++ToSendMax] = 0x00; ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0xff; + ToSend[++ToSendMax] = 0xff;//Proxtoair duration starts here ToSend[++ToSendMax] = 0xff; ToSend[++ToSendMax] = 0xff; ToSend[++ToSendMax] = 0x00; @@ -958,11 +922,13 @@ static void CodeIClassTagAnswer(const uint8_t *cmd, int len) ToSend[++ToSendMax] = 0x00; ToSend[++ToSendMax] = 0xff; ToSend[++ToSendMax] = 0xff; - ToSend[++ToSendMax] = 0xff; + ToSend[++ToSendMax] = 0xff; ToSend[++ToSendMax] = 0x00; ToSend[++ToSendMax] = 0x00; ToSend[++ToSendMax] = 0x00; + //lastProxToAirDuration = 8*ToSendMax - 3*8 - 3*8;//Not counting zeroes in the beginning or end + // Convert from last byte pos to length ToSendMax++; } @@ -970,8 +936,10 @@ static void CodeIClassTagAnswer(const uint8_t *cmd, int len) // Only SOF static void CodeIClassTagSOF() { - ToSendReset(); + //So far a dummy implementation, not used + //int lastProxToAirDuration =0; + ToSendReset(); // Send SOF ToSend[++ToSendMax] = 0x00; ToSend[++ToSendMax] = 0x00; @@ -981,11 +949,14 @@ static void CodeIClassTagSOF() ToSend[++ToSendMax] = 0xff; ToSend[++ToSendMax] = 0x00; ToSend[++ToSendMax] = 0xff; + +// lastProxToAirDuration = 8*ToSendMax - 3*8;//Not counting zeroes in the beginning + // Convert from last byte pos to length ToSendMax++; } - +int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader_mac_buf); /** * @brief SimulateIClass simulates an iClass card. * @param arg0 type of simulation @@ -1002,38 +973,49 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain { uint32_t simType = arg0; uint32_t numberOfCSNS = arg1; + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // Enable and clear the trace iso14a_set_tracing(TRUE); iso14a_clear_trace(); uint8_t csn_crc[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0, 0x00, 0x00 }; - if(simType == 0) { // Use the CSN from commandline memcpy(csn_crc, datain, 8); - doIClassSimulation(csn_crc,0); + doIClassSimulation(csn_crc,0,NULL); }else if(simType == 1) { - doIClassSimulation(csn_crc,0); + doIClassSimulation(csn_crc,0,NULL); } else if(simType == 2) { + + uint8_t mac_responses[64] = { 0 }; + Dbprintf("Going into attack mode"); // 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. - for(int i = 0 ; i < numberOfCSNS && i*8+8 < USB_CMD_DATA_SIZE; i++) + int i = 0; + for( ; i < numberOfCSNS && i*8+8 < USB_CMD_DATA_SIZE; i++) { // The usb data is 512 bytes, fitting 65 8-byte CSNs in there. memcpy(csn_crc, datain+(i*8), 8); - doIClassSimulation(csn_crc,1); + if(doIClassSimulation(csn_crc,1,mac_responses)) + { + return; // Button pressed + } } - }else{ + cmd_send(CMD_ACK,CMD_SIMULATE_TAG_ICLASS,i,0,mac_responses,i*8); + + } + else{ // We may want a mode here where we hardcode the csns to use (from proxclone). // That will speed things up a little, but not required just yet. Dbprintf("The mode is not implemented, reserved for future use"); } + Dbprintf("Done..."); } /** @@ -1041,13 +1023,15 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain * @param csn - csn to use * @param breakAfterMacReceived if true, returns after reader MAC has been received. */ -void doIClassSimulation(uint8_t csn[], int breakAfterMacReceived) +int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader_mac_buf) { + + // CSN followed by two CRC bytes uint8_t response2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t response3[] = { 0,0,0,0,0,0,0,0,0,0}; memcpy(response3,csn,sizeof(response3)); - + Dbprintf("Simulating 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]); // e-Purse uint8_t response4[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -1115,29 +1099,52 @@ void doIClassSimulation(uint8_t csn[], int breakAfterMacReceived) CodeIClassTagAnswer(response4, sizeof(response4)); memcpy(resp4, ToSend, ToSendMax); resp4Len = ToSendMax; + + // Start from off (no field generated) + //FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + //SpinDelay(200); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); + SpinDelay(100); + StartCountSspClk(); // We need to listen to the high-frequency, peak-detected path. SetAdcMuxFor(GPIO_MUXSEL_HIPKD); FpgaSetupSsc(); // To control where we are in the protocol int cmdsRecvd = 0; + uint32_t time_0 = GetCountSspClk(); + uint32_t t2r_time =0; + uint32_t r2t_time =0; LED_A_ON(); + bool buttonPressed = false; + + /** Hack for testing + memcpy(reader_mac_buf,csn,8); + exitLoop = true; + end hack **/ + while(!exitLoop) { + LED_B_OFF(); + //Signal tracer + // Can be used to get a trigger for an oscilloscope.. + LED_C_OFF(); + if(!GetIClassCommandFromReader(receivedCmd, &len, 100)) { - DbpString("button press"); + buttonPressed = true; break; } + r2t_time = GetCountSspClk(); + //Signal tracer + LED_C_ON(); // Okay, look at the command now. - if(receivedCmd[0] == 0x0a) { + if(receivedCmd[0] == 0x0a ) { // Reader in anticollission phase resp = resp1; respLen = resp1Len; //order = 1; respdata = &sof; respsize = sizeof(sof); - //resp = resp2; respLen = resp2Len; order = 2; - //DbpString("Hello request from reader:"); } else if(receivedCmd[0] == 0x0c) { // Reader asks for anticollission CSN resp = resp2; respLen = resp2Len; //order = 2; @@ -1167,11 +1174,15 @@ void doIClassSimulation(uint8_t csn[], int breakAfterMacReceived) if (breakAfterMacReceived){ // TODO, actually return this to the caller instead of just // dbprintf:ing ... - Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x"); + 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[3], receivedCmd[4], receivedCmd[5], receivedCmd[6], receivedCmd[7], receivedCmd[8]); + if (reader_mac_buf != NULL) + { + memcpy(reader_mac_buf,receivedCmd+1,8); + } exitLoop = true; } } else if(receivedCmd[0] == 0x00 && len == 1) { @@ -1180,6 +1191,7 @@ void doIClassSimulation(uint8_t csn[], int breakAfterMacReceived) respdata = NULL; respsize = 0; } else { + //#db# Unknown command received from reader (len=5): 26 1 0 f6 a 44 44 44 44 // Never seen this command before Dbprintf("Unknown command received from reader (len=%d): %x %x %x %x %x %x %x %x %x", len, @@ -1192,9 +1204,9 @@ void doIClassSimulation(uint8_t csn[], int breakAfterMacReceived) respsize = 0; } - if(cmdsRecvd > 999) { - DbpString("1000 commands later..."); - break; + if(cmdsRecvd > 100) { + //DbpString("100 commands later..."); + //break; } else { cmdsRecvd++; @@ -1202,63 +1214,68 @@ void doIClassSimulation(uint8_t csn[], int breakAfterMacReceived) if(respLen > 0) { SendIClassAnswer(resp, respLen, 21); + t2r_time = GetCountSspClk(); } - + if (tracing) { - LogTrace(receivedCmd,len, rsamples, Uart.parityBits, TRUE); + LogTrace(receivedCmd,len, (r2t_time-time_0)<< 4, Uart.parityBits,TRUE); + LogTrace(NULL,0, (r2t_time-time_0) << 4, 0,TRUE); + if (respdata != NULL) { - LogTrace(respdata,respsize, rsamples, SwapBits(GetParity(respdata,respsize),respsize), FALSE); + LogTrace(respdata,respsize, (t2r_time-time_0) << 4,SwapBits(GetParity(respdata,respsize),respsize),FALSE); + LogTrace(NULL,0, (t2r_time-time_0) << 4,0,FALSE); + + } - if(traceLen > TRACE_SIZE) { + if(!tracing) { DbpString("Trace full"); - break; + //break; } + } memset(receivedCmd, 0x44, RECV_CMD_SIZE); } - Dbprintf("%x", cmdsRecvd); + //Dbprintf("%x", cmdsRecvd); LED_A_OFF(); LED_B_OFF(); + if(buttonPressed) + { + DbpString("Button pressed"); + } + return buttonPressed; } static int SendIClassAnswer(uint8_t *resp, int respLen, int delay) { - int i = 0, u = 0, d = 0; + int i = 0, d=0;//, u = 0, d = 0; uint8_t b = 0; - // return 0; - // Modulate Manchester - // FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD424); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K); + AT91C_BASE_SSC->SSC_THR = 0x00; FpgaSetupSsc(); - - // send cycle - for(;;) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - volatile uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - (void)b; + while(!BUTTON_PRESS()) { + if((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)){ + b = AT91C_BASE_SSC->SSC_RHR; (void) b; } - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)){ + b = 0x00; if(d < delay) { - b = 0x00; d++; } - else if(i >= respLen) { - b = 0x00; - u++; - } else { - b = resp[i]; - u++; - if(u > 1) { i++; u = 0; } + else { + if( i < respLen){ + b = resp[i]; + //Hack + //b = 0xAC; + } + i++; } AT91C_BASE_SSC->SSC_THR = b; - - if(u > 4) break; - } - if(BUTTON_PRESS()) { - break; } + + if (i > respLen +4) break; } return 0; @@ -1272,7 +1289,6 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, int delay) static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int *wait) { int c; - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); AT91C_BASE_SSC->SSC_THR = 0x00; FpgaSetupSsc(); @@ -1348,12 +1364,12 @@ void CodeIClassCommand(const uint8_t * cmd, int len) b = cmd[i]; for(j = 0; j < 4; j++) { for(k = 0; k < 4; k++) { - if(k == (b & 3)) { - ToSend[++ToSendMax] = 0x0f; - } - else { - ToSend[++ToSendMax] = 0x00; - } + if(k == (b & 3)) { + ToSend[++ToSendMax] = 0x0f; + } + else { + ToSend[++ToSendMax] = 0x00; + } } b >>= 2; } @@ -1457,6 +1473,8 @@ void ReaderIClass(uint8_t arg0) { uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // Reset trace buffer memset(trace, 0x44, RECV_CMD_OFFSET); traceLen = 0;