X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/81cd0474cb4dc85fcc78f70ad238cb684851f75f..c3963755b7bdb05523e694fbecca4dca2ad0112b:/armsrc/iclass.c diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 6f81526b..c827ed51 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -45,6 +45,7 @@ // same construction as in ISO 14443; // different initial value (CRC_ICLASS) #include "iso14443crc.h" +#include "iso15693tools.h" static int timeout = 4096; @@ -691,7 +692,7 @@ void RAMFUNC SnoopIClass(void) // reset traceLen to 0 iso14a_set_tracing(TRUE); - iso14a_clear_tracelen(); + iso14a_clear_trace(); iso14a_set_trigger(FALSE); // The DMA buffer, used to stream samples from the FPGA @@ -1168,9 +1169,13 @@ void SimulateIClass(uint8_t arg0, uint8_t *datain) } if (tracing) { - LogTrace(receivedCmd,len, 0, Uart.parityBits, TRUE); + LogTrace(receivedCmd,len, rsamples, Uart.parityBits, TRUE); if (respdata != NULL) { - LogTrace(respdata,respsize, 0, SwapBits(GetParity(respdata,respsize),respsize), FALSE); + LogTrace(respdata,respsize, rsamples, SwapBits(GetParity(respdata,respsize),respsize), FALSE); + } + if(traceLen > TRACE_SIZE) { + DbpString("Trace full"); + break; } } @@ -1345,7 +1350,7 @@ void ReaderTransmitIClass(uint8_t* frame, int len) LED_A_ON(); // Store reader command in buffer - if (tracing) LogTrace(frame,len,0,par,TRUE); + if (tracing) LogTrace(frame,len,rsamples,par,TRUE); } //----------------------------------------------------------------------------- @@ -1403,7 +1408,8 @@ int ReaderReceiveIClass(uint8_t* receivedAnswer) { int samples = 0; if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return FALSE; - if (tracing) LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE); + rsamples += samples; + if (tracing) LogTrace(receivedAnswer,Demod.len,rsamples,Demod.parityBits,FALSE); if(samples == 0) return FALSE; return Demod.len; } @@ -1412,7 +1418,7 @@ int ReaderReceiveIClass(uint8_t* receivedAnswer) void ReaderIClass(uint8_t arg0) { uint8_t act_all[] = { 0x0a }; uint8_t identify[] = { 0x0c }; - //uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes @@ -1438,74 +1444,180 @@ void ReaderIClass(uint8_t arg0) { LED_A_ON(); for(;;) { - if(traceLen > TRACE_SIZE || BUTTON_PRESS()) break; + + if(traceLen > TRACE_SIZE) { + DbpString("Trace full"); + break; + } + + if (BUTTON_PRESS()) break; // Send act_all ReaderTransmitIClass(act_all, 1); // Card present? if(ReaderReceiveIClass(resp)) { ReaderTransmitIClass(identify, 1); - if(ReaderReceiveIClass(resp)) { - //ReaderTransmitIClass(select, sizeof(select)); + if(ReaderReceiveIClass(resp) == 10) { + // Select card + memcpy(&select[1],resp,8); + ReaderTransmitIClass(select, sizeof(select)); + + if(ReaderReceiveIClass(resp) == 10) { + Dbprintf(" Selected CSN: %02x %02x %02x %02x %02x %02x %02x %02x", + resp[0], resp[1], resp[2], + resp[3], resp[4], resp[5], + resp[6], resp[7]); + } + // Card selected, whats next... ;-) } } WDT_HIT(); } LED_A_OFF(); +} -/* if(resp_data) - memcpy(resp_data->atqa, resp, 2); +void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { + uint8_t act_all[] = { 0x0a }; + uint8_t identify[] = { 0x0c }; + uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t readcheck_cc[]= { 0x88, 0x02 }; + uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 }; - // 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)); - if (!ReaderReceive(resp)) return 0; - if(uid_ptr) memcpy(uid_ptr + cascade_level*4, resp, 4); - - // calculate crypto UID - if(cuid_ptr) *cuid_ptr = bytes_to_num(resp, 4); + uint16_t crc = 0; + uint8_t cardsize=0; + bool read_success=false; + uint8_t mem=0; + + static struct memory_t{ + int k16; + int book; + int k2; + int lockauth; + int keyaccess; + } memory; + + uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes - // Construct SELECT UID command - memcpy(sel_uid+2,resp,5); - AppendCrc14443a(sel_uid,7); - ReaderTransmit(sel_uid,sizeof(sel_uid)); + // Reset trace buffer + memset(trace, 0x44, RECV_CMD_OFFSET); + traceLen = 0; - // Receive the SAK - if (!ReaderReceive(resp)) return 0; - sak = resp[0]; - } - if(resp_data) { - resp_data->sak = sak; - resp_data->ats_len = 0; - } - //-- this byte not UID, it CT. http://www.nxp.com/documents/application_note/AN10927.pdf page 3 - if (uid_ptr[0] == 0x88) { - memcpy(uid_ptr, uid_ptr + 1, 7); - uid_ptr[7] = 0; - } + // Setup SSC + FpgaSetupSsc(); + // Start from off (no field generated) + // Signal field is off with the appropriate LED + LED_D_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(200); - if( (sak & 0x20) == 0) - return 2; // non iso14443a compliant tag + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - // Request for answer to select - if(resp_data) { // JCOP cards - if reader sent RATS then there is no MIFARE session at all!!! - AppendCrc14443a(rats, 2); - ReaderTransmit(rats, sizeof(rats)); - - if (!(len = ReaderReceive(resp))) return 0; + // Now give it time to spin up. + // Signal field is on with the appropriate LED + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); + SpinDelay(200); + + LED_A_ON(); + + for(int i=0;i<1;i++) { + + if(traceLen > TRACE_SIZE) { + DbpString("Trace full"); + break; + } - memcpy(resp_data->ats, resp, sizeof(resp_data->ats)); - resp_data->ats_len = len; + if (BUTTON_PRESS()) break; + + // Send act_all + ReaderTransmitIClass(act_all, 1); + // Card present? + if(ReaderReceiveIClass(resp)) { + ReaderTransmitIClass(identify, 1); + if(ReaderReceiveIClass(resp) == 10) { + // Select card + memcpy(&select[1],resp,8); + ReaderTransmitIClass(select, sizeof(select)); + + if(ReaderReceiveIClass(resp) == 10) { + Dbprintf(" Selected CSN: %02x %02x %02x %02x %02x %02x %02x %02x", + resp[0], resp[1], resp[2], + resp[3], resp[4], resp[5], + resp[6], resp[7]); + } + // Card selected + Dbprintf("Readcheck on Sector 2"); + ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); + if(ReaderReceiveIClass(resp) == 8) { + Dbprintf(" CC: %02x %02x %02x %02x %02x %02x %02x %02x", + resp[0], resp[1], resp[2], + resp[3], resp[4], resp[5], + resp[6], resp[7]); + }else return; + Dbprintf("Authenticate"); + //for now replay captured auth (as cc not updated) + memcpy(check+5,MAC,4); + Dbprintf(" AA: %02x %02x %02x %02x", + check[5], check[6], check[7],check[8]); + ReaderTransmitIClass(check, sizeof(check)); + if(ReaderReceiveIClass(resp) == 4) { + Dbprintf(" AR: %02x %02x %02x %02x", + resp[0], resp[1], resp[2],resp[3]); + }else { + Dbprintf("Error: Authentication Fail!"); + return; + } + Dbprintf("Dump Contents"); + //first get configuration block + read_success=false; + read[1]=1; + uint8_t *blockno=&read[1]; + crc = iclass_crc16((char *)blockno,1); + read[2] = crc >> 8; + read[3] = crc & 0xff; + while(!read_success){ + ReaderTransmitIClass(read, sizeof(read)); + if(ReaderReceiveIClass(resp) == 10) { + read_success=true; + mem=resp[5]; + memory.k16= (mem & 0x80); + memory.book= (mem & 0x20); + memory.k2= (mem & 0x8); + memory.lockauth= (mem & 0x2); + memory.keyaccess= (mem & 0x1); + + } + } + if (memory.k16){ + cardsize=255; + }else cardsize=32; + //then loop around remaining blocks + for(uint8_t j=0; j> 8; + read[3] = crc & 0xff; + while(!read_success){ + ReaderTransmitIClass(read, sizeof(read)); + if(ReaderReceiveIClass(resp) == 10) { + read_success=true; + Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x", + j, resp[0], resp[1], resp[2], + resp[3], resp[4], resp[5], + resp[6], resp[7]); + } + } + } + } + } + WDT_HIT(); } -*/ + + LED_A_OFF(); }