From 32cfae439e0e2270638617fa09bf1026b0cf0e50 Mon Sep 17 00:00:00 2001 From: "roel@libnfc.org" Date: Wed, 30 Dec 2009 00:11:50 +0000 Subject: [PATCH] mifare firmware update --- armsrc/appmain.c | 6 ++ armsrc/apps.h | 12 +++- armsrc/iso14443a.c | 167 +++++++++++++++++++++++++++++++++++++++++++-- armsrc/util.c | 18 +++++ 4 files changed, 197 insertions(+), 6 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 9026f721..11047b1c 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -593,6 +593,12 @@ void UsbPacketReceived(BYTE *packet, int len) break; #endif +#ifdef WITH_ISO14443a + case CMD_READER_MIFARE: + ReaderMifare(c->arg[0]); + break; +#endif + #ifdef WITH_ISO14443b case CMD_SNOOP_ISO_14443: SnoopIso14443(); diff --git a/armsrc/apps.h b/armsrc/apps.h index d90d595a..95080eae 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -7,6 +7,10 @@ #ifndef __APPS_H #define __APPS_H +#include "stdint.h" +#include "stddef.h" +typedef unsigned char byte_t; + // The large multi-purpose buffer, typically used to hold A/D samples, // maybe processed in some way. DWORD BigBuf[12000]; @@ -82,14 +86,15 @@ void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen); void SimulateIso14443Tag(void); void AcquireRawAdcSamplesIso14443(DWORD parameter); void ReadSRI512Iso14443(DWORD parameter); -void ReadSRIX4KIso14443(DWORD parameter); -void ReadSTMemoryIso14443(DWORD parameter,DWORD dwLast); +void ReadSRIX4KIso14443(DWORD parameter); +void ReadSTMemoryIso14443(DWORD parameter,DWORD dwLast); void SnoopIso14443(void); /// iso14443a.h void SnoopIso14443a(void); void SimulateIso14443aTag(int tagType, int TagUid); // ## simulate iso14443a tag void ReaderIso14443a(DWORD parameter); +void ReaderMifare(DWORD parameter); /// iso15693.h void AcquireRawAdcSamplesIso15693(void); @@ -111,6 +116,9 @@ void *memcpy(void *dest, const void *src, int len); void *memset(void *dest, int c, int len); int memcmp(const void *av, const void *bv, int len); char *strncat(char *dest, const char *src, unsigned int n); +void num_to_bytes(uint64_t n, size_t len, byte_t* dest); +uint64_t bytes_to_num(byte_t* src, size_t len); + void SpinDelay(int ms); void SpinDelayUs(int us); void LED(int led, int ms); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index d39fbdd4..4c04571e 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -10,6 +10,7 @@ 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. @@ -1548,7 +1554,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 +1564,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 +1584,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; } @@ -1692,3 +1697,157 @@ void ReaderIso14443a(DWORD parameter) DbpIntegers(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; +} diff --git a/armsrc/util.c b/armsrc/util.c index 3cad25f4..e6332a7b 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -64,6 +64,24 @@ char* strncat(char *dest, const char *src, unsigned int n) return dest; } +void num_to_bytes(uint64_t n, size_t len, byte_t* dest) +{ + while (len--) { + dest[len] = (byte_t) n; + n >>= 8; + } +} + +uint64_t bytes_to_num(byte_t* src, size_t len) +{ + uint64_t num = 0; + while (len--) + { + num = (num << 8) | (*src); + src++; + } + return num; +} void LEDsoff() { -- 2.39.2