X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/84c02e97e0925a44daece47ce19c265e22d5c772..41dab153055c6bdbbea436b01e7fcf87354c435a:/armsrc/iso14443a.c?ds=inline diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index d39fbdd4..02d912e7 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -5,11 +5,12 @@ //----------------------------------------------------------------------------- #include #include "apps.h" -#include "../common/iso14443_crc.c" +#include "iso14443crc.h" static BYTE *trace = (BYTE *) BigBuf; static int traceLen = 0; static int rsamples = 0; +static BOOL tracing = TRUE; typedef enum { SEC_D = 1, @@ -92,6 +93,11 @@ BOOL LogTrace(const BYTE * btBytes, int iLen, int iSamples, DWORD dwParity, BOOL return TRUE; } +BOOL LogTraceInfo(byte_t* data, size_t len) +{ + return LogTrace(data,len,0,GetParity(data,len),TRUE); +} + //----------------------------------------------------------------------------- // The software UART that receives commands from the reader, and its state // variables. @@ -735,13 +741,13 @@ void SnoopIso14443a(void) DbpString("COMMAND FINISHED"); - DbpIntegers(maxBehindBy, Uart.state, Uart.byteCnt); - DbpIntegers(Uart.byteCntMax, traceLen, (int)Uart.output[0]); + Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt); + Dbprintf("%x %x %x", Uart.byteCntMax, traceLen, (int)Uart.output[0]); done: AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; - DbpIntegers(maxBehindBy, Uart.state, Uart.byteCnt); - DbpIntegers(Uart.byteCntMax, traceLen, (int)Uart.output[0]); + Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt); + Dbprintf("%x %x %x", Uart.byteCntMax, traceLen, (int)Uart.output[0]); LED_A_OFF(); LED_B_OFF(); LED_C_OFF(); @@ -1138,8 +1144,8 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); } else if(receivedCmd[0] == 0x30) { // Received a READ resp = resp4; respLen = resp4Len; order = 4; // Do nothing - DbpString("Read request from reader:"); - DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]); + Dbprintf("Read request from reader: %x %x %x", + receivedCmd[0], receivedCmd[1], receivedCmd[2]); } else if(receivedCmd[0] == 0x50) { @@ -1150,21 +1156,20 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); } else if(receivedCmd[0] == 0x60) { // Received an authentication request resp = resp5; respLen = resp5Len; order = 7; - DbpString("Authenticate request from reader:"); - DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]); + Dbprintf("Authenticate request from reader: %x %x %x", + receivedCmd[0], receivedCmd[1], receivedCmd[2]); } else if(receivedCmd[0] == 0xE0) { // Received a RATS request resp = resp1; respLen = 0;order = 70; - DbpString("RATS request from reader:"); - DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]); + Dbprintf("RATS request from reader: %x %x %x", + receivedCmd[0], receivedCmd[1], receivedCmd[2]); } else { // Never seen this command before - DbpString("Unknown command received from reader:"); - DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]); - DbpIntegers(receivedCmd[3], receivedCmd[4], receivedCmd[5]); - DbpIntegers(receivedCmd[6], receivedCmd[7], receivedCmd[8]); - + Dbprintf("Unknown command received from reader: %x %x %x %x %x %x %x %x %x", + receivedCmd[0], receivedCmd[1], receivedCmd[2], + receivedCmd[3], receivedCmd[3], receivedCmd[4], + receivedCmd[5], receivedCmd[6], receivedCmd[7]); // Do not respond resp = resp1; respLen = 0; order = 0; } @@ -1228,7 +1233,7 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); } - DbpIntegers(happened, happened2, cmdsRecvd); + Dbprintf("%x %x %x", happened, happened2, cmdsRecvd); LED_A_OFF(); } @@ -1548,7 +1553,7 @@ void ReaderTransmitShort(const BYTE* bt) TransmitFor14443a(ToSend, ToSendMax, &samples, &wait); // Store reader command in buffer - LogTrace(bt,1,0,GetParity(bt,1),TRUE); + if (tracing) LogTrace(bt,1,0,GetParity(bt,1),TRUE); } void ReaderTransmitPar(BYTE* frame, int len, DWORD par) @@ -1558,14 +1563,13 @@ void ReaderTransmitPar(BYTE* frame, int len, DWORD par) // This is tied to other size changes // BYTE* frame_addr = ((BYTE*)BigBuf) + 2024; - CodeIso14443aAsReaderPar(frame,len,par); // Select the card TransmitFor14443a(ToSend, ToSendMax, &samples, &wait); // Store reader command in buffer - LogTrace(frame,len,0,par,TRUE); + if (tracing) LogTrace(frame,len,0,par,TRUE); } @@ -1579,7 +1583,7 @@ BOOL ReaderReceive(BYTE* receivedAnswer) { int samples = 0; if (!GetIso14443aAnswerFromTag(receivedAnswer,100,&samples,0)) return FALSE; - LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE); + if (tracing) LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE); return TRUE; } @@ -1689,6 +1693,160 @@ void ReaderIso14443a(DWORD parameter) // Thats it... FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - DbpIntegers(rsamples, 0xCC, 0xCC); + Dbprintf("%x %x %x", rsamples, 0xCC, 0xCC); DbpString("ready.."); } + +//----------------------------------------------------------------------------- +// Read an ISO 14443a tag. Send out commands and store answers. +// +//----------------------------------------------------------------------------- +void ReaderMifare(DWORD parameter) +{ + + // Anticollision + BYTE wupa[] = { 0x52 }; + BYTE sel_all[] = { 0x93,0x20 }; + BYTE sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + + // Mifare AUTH + BYTE mf_auth[] = { 0x60,0x00,0xf5,0x7b }; + BYTE mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + + BYTE* receivedAnswer = (((BYTE *)BigBuf) + 3560); // was 3560 - tied to other size changes + traceLen = 0; + tracing = false; + + // 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); + + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaSetupSsc(); + + // Now give it time to spin up. + // Signal field is on with the appropriate LED + LED_D_ON(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); + SpinDelay(200); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + // Broadcast for a card, WUPA (0x52) will force response from all cards in the field + ReaderTransmitShort(wupa); + // Receive the ATQA + ReaderReceive(receivedAnswer); + // Transmit SELECT_ALL + ReaderTransmit(sel_all,sizeof(sel_all)); + // Receive the UID + ReaderReceive(receivedAnswer); + // Construct SELECT UID command + // First copy the 5 bytes (Mifare Classic) after the 93 70 + memcpy(sel_uid+2,receivedAnswer,5); + // Secondly compute the two CRC bytes at the end + AppendCrc14443a(sel_uid,7); + + byte_t nt_diff = 0; + LED_A_OFF(); + byte_t par = 0; + byte_t par_mask = 0xff; + byte_t par_low = 0; + BOOL led_on = TRUE; + + tracing = FALSE; + byte_t nt[4]; + byte_t nt_attacked[4]; + byte_t par_list[8]; + byte_t ks_list[8]; + num_to_bytes(parameter,4,nt_attacked); + + while(TRUE) + { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(200); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); + + // Broadcast for a card, WUPA (0x52) will force response from all cards in the field + ReaderTransmitShort(wupa); + + // Test if the action was cancelled + if(BUTTON_PRESS()) { + break; + } + + // Receive the ATQA + if (!ReaderReceive(receivedAnswer)) continue; + + // Transmit SELECT_ALL + ReaderTransmit(sel_all,sizeof(sel_all)); + + // Receive the UID + if (!ReaderReceive(receivedAnswer)) continue; + + // Transmit SELECT_UID + ReaderTransmit(sel_uid,sizeof(sel_uid)); + + // Receive the SAK + if (!ReaderReceive(receivedAnswer)) continue; + + // Transmit MIFARE_CLASSIC_AUTH + ReaderTransmit(mf_auth,sizeof(mf_auth)); + + // Receive the (16 bit) "random" nonce + if (!ReaderReceive(receivedAnswer)) continue; + memcpy(nt,receivedAnswer,4); + + // Transmit reader nonce and reader answer + ReaderTransmitPar(mf_nr_ar,sizeof(mf_nr_ar),par); + + // Receive 4 bit answer + if (ReaderReceive(receivedAnswer)) + { + if (nt_diff == 0) + { + LED_A_ON(); + memcpy(nt_attacked,nt,4); + par_mask = 0xf8; + par_low = par & 0x07; + } + + if (memcmp(nt,nt_attacked,4) != 0) continue; + + led_on = !led_on; + if(led_on) LED_B_ON(); else LED_B_OFF(); + par_list[nt_diff] = par; + ks_list[nt_diff] = receivedAnswer[0]^0x05; + + // Test if the information is complete + if (nt_diff == 0x07) break; + + nt_diff = (nt_diff+1) & 0x07; + mf_nr_ar[3] = nt_diff << 5; + par = par_low; + } else { + if (nt_diff == 0) + { + par++; + } else { + par = (((par>>3)+1) << 3) | par_low; + } + } + } + + LogTraceInfo(sel_uid+2,4); + LogTraceInfo(nt,4); + LogTraceInfo(par_list,8); + LogTraceInfo(ks_list,8); + + // Thats it... + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + tracing = TRUE; +}