]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - armsrc/iso14443a.c
Client cleanup and restructuring. Stage 1...
[proxmark3-svn] / armsrc / iso14443a.c
index dbada07678f727f3ae801a200ee7dfe6c1544923..02d912e7b3136f60a73d27dabac3dd467af609c5 100644 (file)
@@ -5,7 +5,12 @@
 //-----------------------------------------------------------------------------\r
 #include <proxmark3.h>\r
 #include "apps.h"\r
-#include "../common/iso14443_crc.c"\r
+#include "iso14443crc.h"\r
+\r
+static BYTE *trace = (BYTE *) BigBuf;\r
+static int traceLen = 0;\r
+static int rsamples = 0;\r
+static BOOL tracing = TRUE;\r
 \r
 typedef enum {\r
        SEC_D = 1,\r
@@ -16,6 +21,83 @@ typedef enum {
        SEC_Z = 6\r
 } SecType;\r
 \r
+static const BYTE OddByteParity[256] = {\r
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1\r
+};\r
+\r
+// BIG CHANGE - UNDERSTAND THIS BEFORE WE COMMIT\r
+#define RECV_CMD_OFFSET   3032\r
+#define RECV_RES_OFFSET   3096\r
+#define DMA_BUFFER_OFFSET 3160\r
+#define DMA_BUFFER_SIZE   4096\r
+#define TRACE_LENGTH      3000\r
+\r
+//-----------------------------------------------------------------------------\r
+// Generate the parity value for a byte sequence\r
+// \r
+//-----------------------------------------------------------------------------\r
+DWORD GetParity(const BYTE * pbtCmd, int iLen)\r
+{\r
+  int i;\r
+  DWORD dwPar = 0;\r
+  \r
+  // Generate the encrypted data\r
+  for (i = 0; i < iLen; i++) {\r
+    // Save the encrypted parity bit\r
+    dwPar |= ((OddByteParity[pbtCmd[i]]) << i);\r
+  }\r
+  return dwPar;\r
+}\r
+\r
+static void AppendCrc14443a(BYTE* data, int len)\r
+{\r
+  ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1);\r
+}\r
+\r
+BOOL LogTrace(const BYTE * btBytes, int iLen, int iSamples, DWORD dwParity, BOOL bReader)\r
+{\r
+  // Return when trace is full\r
+  if (traceLen >= TRACE_LENGTH) return FALSE;\r
+  \r
+  // Trace the random, i'm curious\r
+  rsamples += iSamples;\r
+  trace[traceLen++] = ((rsamples >> 0) & 0xff);\r
+  trace[traceLen++] = ((rsamples >> 8) & 0xff);\r
+  trace[traceLen++] = ((rsamples >> 16) & 0xff);\r
+  trace[traceLen++] = ((rsamples >> 24) & 0xff);\r
+  if (!bReader) {\r
+    trace[traceLen - 1] |= 0x80;\r
+  }\r
+  trace[traceLen++] = ((dwParity >> 0) & 0xff);\r
+  trace[traceLen++] = ((dwParity >> 8) & 0xff);\r
+  trace[traceLen++] = ((dwParity >> 16) & 0xff);\r
+  trace[traceLen++] = ((dwParity >> 24) & 0xff);\r
+  trace[traceLen++] = iLen;\r
+  memcpy(trace + traceLen, btBytes, iLen);\r
+  traceLen += iLen;\r
+  return TRUE;\r
+}\r
+\r
+BOOL LogTraceInfo(byte_t* data, size_t len)\r
+{\r
+  return LogTrace(data,len,0,GetParity(data,len),TRUE);\r
+}\r
+\r
 //-----------------------------------------------------------------------------\r
 // The software UART that receives commands from the reader, and its state\r
 // variables.\r
@@ -509,15 +591,6 @@ static BOOL ManchesterDecoding(int v)
 //-----------------------------------------------------------------------------\r
 void SnoopIso14443a(void)\r
 {\r
-\r
-       // BIG CHANGE - UNDERSTAND THIS BEFORE WE COMMIT\r
-\r
-       #define RECV_CMD_OFFSET         3032\r
-       #define RECV_RES_OFFSET         3096\r
-       #define DMA_BUFFER_OFFSET       3160\r
-       #define DMA_BUFFER_SIZE         4096\r
-       #define TRACE_LENGTH            3000\r
-\r
 //     #define RECV_CMD_OFFSET         2032    // original (working as of 21/2/09) values\r
 //     #define RECV_RES_OFFSET         2096    // original (working as of 21/2/09) values\r
 //     #define DMA_BUFFER_OFFSET       2160    // original (working as of 21/2/09) values\r
@@ -538,8 +611,8 @@ void SnoopIso14443a(void)
 \r
     // As we receive stuff, we copy it from receivedCmd or receivedResponse\r
     // into trace, along with its length and other annotations.\r
-    BYTE *trace = (BYTE *)BigBuf;\r
-    int traceLen = 0;\r
+    //BYTE *trace = (BYTE *)BigBuf;\r
+    //int traceLen = 0;\r
 \r
     // The DMA buffer, used to stream samples from the FPGA\r
     SBYTE *dmaBuf = ((SBYTE *)BigBuf) + DMA_BUFFER_OFFSET;\r
@@ -668,13 +741,13 @@ void SnoopIso14443a(void)
 \r
     DbpString("COMMAND FINISHED");\r
 \r
-    DbpIntegers(maxBehindBy, Uart.state, Uart.byteCnt);\r
-    DbpIntegers(Uart.byteCntMax, traceLen, (int)Uart.output[0]);\r
+    Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt);\r
+    Dbprintf("%x %x %x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);\r
 \r
 done:\r
     AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;\r
-    DbpIntegers(maxBehindBy, Uart.state, Uart.byteCnt);\r
-    DbpIntegers(Uart.byteCntMax, traceLen, (int)Uart.output[0]);\r
+    Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt);\r
+    Dbprintf("%x %x %x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);\r
     LED_A_OFF();\r
     LED_B_OFF();\r
        LED_C_OFF();\r
@@ -1071,8 +1144,8 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
                } else if(receivedCmd[0] == 0x30) {\r
                        // Received a READ\r
                        resp = resp4; respLen = resp4Len; order = 4; // Do nothing\r
-                       DbpString("Read request from reader:");\r
-                       DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
+                       Dbprintf("Read request from reader: %x %x %x",\r
+                               receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
 \r
 \r
                } else if(receivedCmd[0] == 0x50) {\r
@@ -1083,21 +1156,20 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
                } else if(receivedCmd[0] == 0x60) {\r
                        // Received an authentication request\r
                        resp = resp5; respLen = resp5Len; order = 7;\r
-                       DbpString("Authenticate request from reader:");\r
-                       DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
+                       Dbprintf("Authenticate request from reader: %x %x %x",\r
+                               receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
 \r
                } else if(receivedCmd[0] == 0xE0) {\r
                        // Received a RATS request\r
                        resp = resp1; respLen = 0;order = 70;\r
-                       DbpString("RATS request from reader:");\r
-                       DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
+                       Dbprintf("RATS request from reader: %x %x %x",\r
+                               receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
         } else {\r
             // Never seen this command before\r
-                       DbpString("Unknown command received from reader:");\r
-                       DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
-                       DbpIntegers(receivedCmd[3], receivedCmd[4], receivedCmd[5]);\r
-                       DbpIntegers(receivedCmd[6], receivedCmd[7], receivedCmd[8]);\r
-\r
+               Dbprintf("Unknown command received from reader: %x %x %x %x %x %x %x %x %x",\r
+                       receivedCmd[0], receivedCmd[1], receivedCmd[2],\r
+                       receivedCmd[3], receivedCmd[3], receivedCmd[4],\r
+                       receivedCmd[5], receivedCmd[6], receivedCmd[7]);\r
                        // Do not respond\r
                        resp = resp1; respLen = 0; order = 0;\r
         }\r
@@ -1161,7 +1233,7 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
 \r
     }\r
 \r
-       DbpIntegers(happened, happened2, cmdsRecvd);\r
+       Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);\r
        LED_A_OFF();\r
 }\r
 \r
@@ -1170,40 +1242,42 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
 //-----------------------------------------------------------------------------\r
 static void TransmitFor14443a(const BYTE *cmd, int len, int *samples, int *wait)\r
 {\r
-    int c;\r
-\r
-    FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
-\r
-       if(*wait < 10) { *wait = 10; }\r
-\r
-    for(c = 0; c < *wait;) {\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-            AT91C_BASE_SSC->SSC_THR = 0x00;            // For exact timing!\r
-            c++;\r
-        }\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
-            volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
-            (void)r;\r
-        }\r
-        WDT_HIT();\r
+  int c;\r
+  \r
+  FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
+  \r
+       if (wait)\r
+    if(*wait < 10)\r
+      *wait = 10;\r
+  \r
+  for(c = 0; c < *wait;) {\r
+    if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
+      AT91C_BASE_SSC->SSC_THR = 0x00;          // For exact timing!\r
+      c++;\r
     }\r
-\r
-    c = 0;\r
-    for(;;) {\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-            AT91C_BASE_SSC->SSC_THR = cmd[c];\r
-            c++;\r
-            if(c >= len) {\r
-                break;\r
-            }\r
-        }\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
-            volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
-            (void)r;\r
-        }\r
-        WDT_HIT();\r
+    if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
+      volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
+      (void)r;\r
+    }\r
+    WDT_HIT();\r
+  }\r
+  \r
+  c = 0;\r
+  for(;;) {\r
+    if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
+      AT91C_BASE_SSC->SSC_THR = cmd[c];\r
+      c++;\r
+      if(c >= len) {\r
+        break;\r
+      }\r
     }\r
-       *samples = (c + *wait) << 3;\r
+    if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
+      volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
+      (void)r;\r
+    }\r
+    WDT_HIT();\r
+  }\r
+       if (samples) *samples = (c + *wait) << 3;\r
 }\r
 \r
 //-----------------------------------------------------------------------------\r
@@ -1290,11 +1364,11 @@ void ArbitraryFromReader(const BYTE *cmd, int parity, int len)
 // Code a 7-bit command without parity bit\r
 // This is especially for 0x26 and 0x52 (REQA and WUPA)\r
 //-----------------------------------------------------------------------------\r
-void ShortFrameFromReader(const BYTE *cmd)\r
+void ShortFrameFromReader(const BYTE bt)\r
 {\r
        int j;\r
        int last;\r
-    BYTE b;\r
+  BYTE b;\r
 \r
        ToSendReset();\r
 \r
@@ -1302,7 +1376,7 @@ void ShortFrameFromReader(const BYTE *cmd)
        Sequence(SEC_Z);\r
        last = 0;\r
 \r
-       b = cmd[0];\r
+       b = bt;\r
        for(j = 0; j < 7; j++) {\r
                if(b & 1) {\r
                        // Sequence X\r
@@ -1346,86 +1420,81 @@ void ShortFrameFromReader(const BYTE *cmd)
 \r
 //-----------------------------------------------------------------------------\r
 // Prepare reader command to send to FPGA\r
-//\r
+// \r
 //-----------------------------------------------------------------------------\r
-void CodeIso14443aAsReader(const BYTE *cmd, int len)\r
+void CodeIso14443aAsReaderPar(const BYTE * cmd, int len, DWORD dwParity)\r
 {\r
-    int i, j;\r
-       int last;\r
-       int oddparity;\r
-    BYTE b;\r
-\r
-    ToSendReset();\r
-\r
-       // Start of Communication (Seq. Z)\r
-       Sequence(SEC_Z);\r
-       last = 0;\r
-\r
-       for(i = 0; i < len; i++) {\r
-        // Data bits\r
-        b = cmd[i];\r
-        oddparity = 0x01;\r
-        for(j = 0; j < 8; j++) {\r
-            oddparity ^= (b & 1);\r
-            if(b & 1) {\r
-                               // Sequence X\r
-                               Sequence(SEC_X);\r
-                               last = 1;\r
-            } else {\r
-                if(last == 0) {\r
-                                       // Sequence Z\r
-                                       Sequence(SEC_Z);\r
-                               }\r
-                               else {\r
-                                       // Sequence Y\r
-                                       Sequence(SEC_Y);\r
-                                       last = 0;\r
-                               }\r
-            }\r
-            b >>= 1;\r
+  int i, j;\r
+  int last;\r
+  BYTE b;\r
+  \r
+  ToSendReset();\r
+  \r
+  // Start of Communication (Seq. Z)\r
+  Sequence(SEC_Z);\r
+  last = 0;\r
+  \r
+  // Generate send structure for the data bits\r
+  for (i = 0; i < len; i++) {\r
+    // Get the current byte to send\r
+    b = cmd[i];\r
+    \r
+    for (j = 0; j < 8; j++) {\r
+      if (b & 1) {\r
+        // Sequence X\r
+        Sequence(SEC_X);\r
+        last = 1;\r
+      } else {\r
+        if (last == 0) {\r
+          // Sequence Z\r
+          Sequence(SEC_Z);\r
+        } else {\r
+          // Sequence Y\r
+          Sequence(SEC_Y);\r
+          last = 0;\r
         }\r
-\r
-               // Parity bit\r
-               if(oddparity) {\r
-                       // Sequence X\r
-                       Sequence(SEC_X);\r
-                       last = 1;\r
-               } else {\r
-                       if(last == 0) {\r
-                               // Sequence Z\r
-                               Sequence(SEC_Z);\r
-                       }\r
-                       else {\r
-                               // Sequence Y\r
-                               Sequence(SEC_Y);\r
-                               last = 0;\r
-                       }\r
-               }\r
+      }\r
+      b >>= 1;\r
     }\r
-\r
-       // End of Communication\r
-       if(last == 0) {\r
-               // Sequence Z\r
-               Sequence(SEC_Z);\r
-       }\r
-       else {\r
-               // Sequence Y\r
-               Sequence(SEC_Y);\r
-               last = 0;\r
-       }\r
-       // Sequence Y\r
-       Sequence(SEC_Y);\r
-\r
-       // Just to be sure!\r
-       Sequence(SEC_Y);\r
-       Sequence(SEC_Y);\r
-       Sequence(SEC_Y);\r
-\r
-    // Convert from last character reference to length\r
-    ToSendMax++;\r
+    \r
+    // Get the parity bit\r
+    if ((dwParity >> i) & 0x01) {\r
+      // Sequence X\r
+      Sequence(SEC_X);\r
+      last = 1;\r
+    } else {\r
+      if (last == 0) {\r
+        // Sequence Z\r
+        Sequence(SEC_Z);\r
+      } else {\r
+        // Sequence Y\r
+        Sequence(SEC_Y);\r
+        last = 0;\r
+      }\r
+    }\r
+  }\r
+  \r
+  // End of Communication\r
+  if (last == 0) {\r
+    // Sequence Z\r
+    Sequence(SEC_Z);\r
+  } else {\r
+    // Sequence Y\r
+    Sequence(SEC_Y);\r
+    last = 0;\r
+  }\r
+  // Sequence Y\r
+  Sequence(SEC_Y);\r
+  \r
+  // Just to be sure!\r
+  Sequence(SEC_Y);\r
+  Sequence(SEC_Y);\r
+  Sequence(SEC_Y);\r
+  \r
+  // Convert from last character reference to length\r
+  ToSendMax++;\r
 }\r
 \r
-\r
 //-----------------------------------------------------------------------------\r
 // Wait a certain time for tag response\r
 //  If a response is captured return TRUE\r
@@ -1448,7 +1517,7 @@ static BOOL GetIso14443aAnswerFromTag(BYTE *receivedResponse, int maxLen, int *s
     Demod.state = DEMOD_UNSYNCD;\r
 \r
        BYTE b;\r
-       *elapsed = 0;\r
+       if (elapsed) *elapsed = 0;\r
 \r
        c = 0;\r
        for(;;) {\r
@@ -1456,7 +1525,7 @@ static BOOL GetIso14443aAnswerFromTag(BYTE *receivedResponse, int maxLen, int *s
 \r
         if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
             AT91C_BASE_SSC->SSC_THR = 0x00;  // To make use of exact timing of next command from reader!!\r
-                       (*elapsed)++;\r
+                       if (elapsed) (*elapsed)++;\r
         }\r
         if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
                        if(c < 512) { c++; } else { return FALSE; }\r
@@ -1473,6 +1542,51 @@ static BOOL GetIso14443aAnswerFromTag(BYTE *receivedResponse, int maxLen, int *s
     }\r
 }\r
 \r
+void ReaderTransmitShort(const BYTE* bt)\r
+{\r
+  int wait = 0;\r
+  int samples = 0;\r
+\r
+  ShortFrameFromReader(*bt);\r
+  \r
+  // Select the card\r
+  TransmitFor14443a(ToSend, ToSendMax, &samples, &wait);               \r
+  \r
+  // Store reader command in buffer\r
+  if (tracing) LogTrace(bt,1,0,GetParity(bt,1),TRUE);\r
+}\r
+\r
+void ReaderTransmitPar(BYTE* frame, int len, DWORD par)\r
+{\r
+  int wait = 0;\r
+  int samples = 0;\r
+  \r
+  // This is tied to other size changes\r
+  //   BYTE* frame_addr = ((BYTE*)BigBuf) + 2024; \r
+  CodeIso14443aAsReaderPar(frame,len,par);\r
+  \r
+  // Select the card\r
+  TransmitFor14443a(ToSend, ToSendMax, &samples, &wait);               \r
+  \r
+  // Store reader command in buffer\r
+  if (tracing) LogTrace(frame,len,0,par,TRUE);\r
+}\r
+\r
+\r
+void ReaderTransmit(BYTE* frame, int len)\r
+{\r
+  // Generate parity and redirect\r
+  ReaderTransmitPar(frame,len,GetParity(frame,len));\r
+}\r
+\r
+BOOL ReaderReceive(BYTE* receivedAnswer)\r
+{\r
+  int samples = 0;\r
+  if (!GetIso14443aAnswerFromTag(receivedAnswer,100,&samples,0)) return FALSE;\r
+  if (tracing) LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE);\r
+  return TRUE;\r
+}\r
+\r
 //-----------------------------------------------------------------------------\r
 // Read an ISO 14443a tag. Send out commands and store answers.\r
 //\r
@@ -1480,339 +1594,259 @@ static BOOL GetIso14443aAnswerFromTag(BYTE *receivedResponse, int maxLen, int *s
 void ReaderIso14443a(DWORD parameter)\r
 {\r
        // Anticollision\r
-       static const BYTE cmd1[]       = { 0x52 }; // or 0x26\r
-       static const BYTE cmd2[]       = { 0x93,0x20 };\r
-       // UID = 0x2a,0x69,0x8d,0x43,0x8d, last two bytes are CRC bytes\r
-       BYTE cmd3[] = { 0x93,0x70,0x2a,0x69,0x8d,0x43,0x8d,0x52,0x55 };\r
-\r
-       // For Ultralight add an extra anticollission layer -> 95 20 and then 95 70\r
-\r
-       // greg - here we will add our cascade level 2 anticolission and select functions to deal with ultralight               // and 7-byte UIDs in generall...\r
-       BYTE cmd4[] = {0x95,0x20};      // ask for cascade 2 select\r
-       // 95 20\r
-       //BYTE cmd3a[] = { 0x95,0x70,0x2a,0x69,0x8d,0x43,0x8d,0x52,0x55 };\r
-       // 95 70\r
-\r
-       // cascade 2 select\r
-       BYTE cmd5[] = { 0x95,0x70,0x2a,0x69,0x8d,0x43,0x8d,0x52,0x55 };\r
-\r
-\r
-       // RATS (request for answer to select)\r
-       //BYTE cmd6[] = { 0xe0,0x50,0xbc,0xa5 };  // original RATS\r
-       BYTE cmd6[] = { 0xe0,0x21,0xb2,0xc7 };  // Desfire RATS\r
+       BYTE wupa[]       = { 0x52 };\r
+       BYTE sel_all[]    = { 0x93,0x20 };\r
+       BYTE sel_uid[]    = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };\r
+       BYTE sel_all_c2[] = { 0x95,0x20 };\r
+       BYTE sel_uid_c2[] = { 0x95,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };\r
 \r
        // Mifare AUTH\r
-       BYTE cmd7[] = { 0x60, 0x00, 0x00, 0x00 };\r
-\r
-       int reqaddr = 2024;                                     // was 2024 - tied to other size changes\r
-       int reqsize = 60;\r
-\r
-       BYTE *req1 = (((BYTE *)BigBuf) + reqaddr);\r
-    int req1Len;\r
-\r
-    BYTE *req2 = (((BYTE *)BigBuf) + reqaddr + reqsize);\r
-    int req2Len;\r
-\r
-    BYTE *req3 = (((BYTE *)BigBuf) + reqaddr + (reqsize * 2));\r
-    int req3Len;\r
-\r
-// greg added req 4 & 5 to deal with cascade 2 section\r
-    BYTE *req4 = (((BYTE *)BigBuf) + reqaddr + (reqsize * 3));\r
-    int req4Len;\r
-\r
-    BYTE *req5 = (((BYTE *)BigBuf) + reqaddr + (reqsize * 4));\r
-    int req5Len;\r
-\r
-    BYTE *req6 = (((BYTE *)BigBuf) + reqaddr + (reqsize * 5));\r
-    int req6Len;\r
-\r
-    BYTE *req7 = (((BYTE *)BigBuf) + reqaddr + (reqsize * 6));\r
-    int req7Len;\r
-\r
-       BYTE *receivedAnswer = (((BYTE *)BigBuf) + 3560);       // was 3560 - tied to other size changes\r
-\r
-       BYTE *trace = (BYTE *)BigBuf;\r
-       int traceLen = 0;\r
-       int rsamples = 0;\r
-\r
-       memset(trace, 0x44, 2000);                              // was 2000 - tied to oter size chnages\r
-       // setting it to 3000 causes no tag responses to be detected (2900 is ok)\r
-       // setting it to 1000 causes no tag responses to be detected\r
-\r
-       // Prepare some commands!\r
-    ShortFrameFromReader(cmd1);\r
-    memcpy(req1, ToSend, ToSendMax); req1Len = ToSendMax;\r
-\r
-       CodeIso14443aAsReader(cmd2, sizeof(cmd2));\r
-    memcpy(req2, ToSend, ToSendMax); req2Len = ToSendMax;\r
-\r
-       CodeIso14443aAsReader(cmd3, sizeof(cmd3));\r
-    memcpy(req3, ToSend, ToSendMax); req3Len = ToSendMax;\r
-\r
-\r
-       CodeIso14443aAsReader(cmd4, sizeof(cmd4));              // 4 is cascade 2 request\r
-    memcpy(req4, ToSend, ToSendMax); req4Len = ToSendMax;\r
-\r
-\r
-       CodeIso14443aAsReader(cmd5, sizeof(cmd5));      // 5 is cascade 2 select\r
-    memcpy(req5, ToSend, ToSendMax); req5Len = ToSendMax;\r
-\r
-\r
-       CodeIso14443aAsReader(cmd6, sizeof(cmd6));\r
-    memcpy(req6, ToSend, ToSendMax); req6Len = ToSendMax;\r
+       BYTE mf_auth[]    = { 0x60,0x00,0xf5,0x7b };\r
+//     BYTE mf_nr_ar[]   = { 0x00,0x00,0x00,0x00 };\r
+  \r
+  BYTE* receivedAnswer = (((BYTE *)BigBuf) + 3560);    // was 3560 - tied to other size changes\r
+  traceLen = 0;\r
 \r
        // Setup SSC\r
        FpgaSetupSsc();\r
 \r
        // Start from off (no field generated)\r
-    // Signal field is off with the appropriate LED\r
-    LED_D_OFF();\r
-    FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-    SpinDelay(200);\r
+  // Signal field is off with the appropriate LED\r
+  LED_D_OFF();\r
+  FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+  SpinDelay(200);\r
 \r
-    SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
-    FpgaSetupSsc();\r
+  SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
+  FpgaSetupSsc();\r
 \r
        // Now give it time to spin up.\r
-    // Signal field is on with the appropriate LED\r
-    LED_D_ON();\r
-    FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
+  // Signal field is on with the appropriate LED\r
+  LED_D_ON();\r
+  FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
        SpinDelay(200);\r
 \r
        LED_A_ON();\r
        LED_B_OFF();\r
        LED_C_OFF();\r
 \r
-       int samples = 0;\r
-       int tsamples = 0;\r
-       int wait = 0;\r
-       int elapsed = 0;\r
-\r
-       for(;;) {\r
-               // Send WUPA (or REQA)\r
-               TransmitFor14443a(req1, req1Len, &tsamples, &wait);\r
-               // Store answer in buffer\r
-               trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-               trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-               trace[traceLen++] = 1;\r
-               memcpy(trace+traceLen, cmd1, 1);\r
-               traceLen += 1;\r
-               if(traceLen > TRACE_LENGTH) goto done;\r
-\r
-               while(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) {\r
-                       if(BUTTON_PRESS()) goto done;\r
-\r
-                       // No answer, just continue polling\r
-                       TransmitFor14443a(req1, req1Len, &tsamples, &wait);\r
-                       // Store answer in buffer\r
-                       trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-                       trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-                       trace[traceLen++] = 1;\r
-                       memcpy(trace+traceLen, cmd1, 1);\r
-                       traceLen += 1;\r
-                       if(traceLen > TRACE_LENGTH) goto done;\r
-               }\r
-\r
-               // Store answer in buffer\r
-               rsamples = rsamples + (samples - Demod.samples);\r
-               trace[traceLen++] = ((rsamples >>  0) & 0xff);\r
-               trace[traceLen++] = ((rsamples >>  8) & 0xff);\r
-               trace[traceLen++] = ((rsamples >> 16) & 0xff);\r
-               trace[traceLen++] = 0x80 | ((rsamples >> 24) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >>  0) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >>  8) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >> 16) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >> 24) & 0xff);\r
-               trace[traceLen++] = Demod.len;\r
-               memcpy(trace+traceLen, receivedAnswer, Demod.len);\r
-               traceLen += Demod.len;\r
-               if(traceLen > TRACE_LENGTH) goto done;\r
-\r
-               // Ask for card UID\r
-               TransmitFor14443a(req2, req2Len, &tsamples, &wait);\r
-               // Store answer in buffer\r
-               trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-               trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-               trace[traceLen++] = 2;\r
-               memcpy(trace+traceLen, cmd2, 2);\r
-               traceLen += 2;\r
-               if(traceLen > TRACE_LENGTH) goto done;\r
-\r
-               if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) {\r
-                       continue;\r
-               }\r
+       while(traceLen < TRACE_LENGTH)\r
+  {\r
+    // Broadcast for a card, WUPA (0x52) will force response from all cards in the field\r
+    ReaderTransmitShort(wupa);\r
+    \r
+    // Test if the action was cancelled\r
+    if(BUTTON_PRESS()) {\r
+      break;\r
+    }\r
+    \r
+    // Receive the ATQA\r
+    if (!ReaderReceive(receivedAnswer)) continue;\r
 \r
-               // Store answer in buffer\r
-               rsamples = rsamples + (samples - Demod.samples);\r
-               trace[traceLen++] = ((rsamples >>  0) & 0xff);\r
-               trace[traceLen++] = ((rsamples >>  8) & 0xff);\r
-               trace[traceLen++] = ((rsamples >> 16) & 0xff);\r
-               trace[traceLen++] = 0x80 | ((rsamples >> 24) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >>  0) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >>  8) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >> 16) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >> 24) & 0xff);\r
-               trace[traceLen++] = Demod.len;\r
-               memcpy(trace+traceLen, receivedAnswer, Demod.len);\r
-               traceLen += Demod.len;\r
-               if(traceLen > TRACE_LENGTH) goto done;\r
+    // Transmit SELECT_ALL\r
+    ReaderTransmit(sel_all,sizeof(sel_all));\r
 \r
+    // Receive the UID\r
+    if (!ReaderReceive(receivedAnswer)) continue;\r
+    \r
                // Construct SELECT UID command\r
                // First copy the 5 bytes (Mifare Classic) after the 93 70\r
-               memcpy(cmd3+2,receivedAnswer,5);\r
+               memcpy(sel_uid+2,receivedAnswer,5);\r
                // Secondly compute the two CRC bytes at the end\r
-               ComputeCrc14443(CRC_14443_A, cmd3, 7, &cmd3[7], &cmd3[8]);\r
-               // Prepare the bit sequence to modulate the subcarrier\r
-               // Store answer in buffer\r
-               trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-               trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-               trace[traceLen++] = 9;\r
-               memcpy(trace+traceLen, cmd3, 9);\r
-               traceLen += 9;\r
-               if(traceLen > TRACE_LENGTH) goto done;\r
-               CodeIso14443aAsReader(cmd3, sizeof(cmd3));\r
-               memcpy(req3, ToSend, ToSendMax); req3Len = ToSendMax;\r
-\r
-               // Select the card\r
-               TransmitFor14443a(req3, req3Len, &samples, &wait);\r
-               if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) {\r
-                       continue;\r
-               }\r
-\r
-               // Store answer in buffer\r
-               rsamples = rsamples + (samples - Demod.samples);\r
-               trace[traceLen++] = ((rsamples >>  0) & 0xff);\r
-               trace[traceLen++] = ((rsamples >>  8) & 0xff);\r
-               trace[traceLen++] = ((rsamples >> 16) & 0xff);\r
-               trace[traceLen++] = 0x80 | ((rsamples >> 24) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >>  0) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >>  8) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >> 16) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >> 24) & 0xff);\r
-               trace[traceLen++] = Demod.len;\r
-               memcpy(trace+traceLen, receivedAnswer, Demod.len);\r
-               traceLen += Demod.len;\r
-               if(traceLen > TRACE_LENGTH) goto done;\r
-\r
-// OK we have selected at least at cascade 1, lets see if first byte of UID was 0x88 in\r
-// which case we need to make a cascade 2 request and select - this is a long UID\r
-               if (receivedAnswer[0] == 0x88)\r
+    AppendCrc14443a(sel_uid,7);\r
+\r
+    // Transmit SELECT_UID\r
+    ReaderTransmit(sel_uid,sizeof(sel_uid));\r
+    \r
+    // Receive the SAK\r
+    if (!ReaderReceive(receivedAnswer)) continue;\r
+\r
+    // OK we have selected at least at cascade 1, lets see if first byte of UID was 0x88 in\r
+    // which case we need to make a cascade 2 request and select - this is a long UID\r
+    // When the UID is not complete, the 3nd bit (from the right) is set in the SAK. \r
+               if (receivedAnswer[0] &= 0x04)\r
                {\r
-               // Do cascade level 2 stuff\r
-               ///////////////////////////////////////////////////////////////////\r
-               // First issue a '95 20' identify request\r
-               // Ask for card UID (part 2)\r
-               TransmitFor14443a(req4, req4Len, &tsamples, &wait);\r
-               // Store answer in buffer\r
-               trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-               trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-               trace[traceLen++] = 2;\r
-               memcpy(trace+traceLen, cmd4, 2);\r
-               traceLen += 2;\r
-               if(traceLen > TRACE_LENGTH) {\r
-               DbpString("Bugging out, just popped tracelength");\r
-               goto done;}\r
-\r
-               if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) {\r
-                       continue;\r
-               }\r
-               // Store answer in buffer\r
-               rsamples = rsamples + (samples - Demod.samples);\r
-               trace[traceLen++] = ((rsamples >>  0) & 0xff);\r
-               trace[traceLen++] = ((rsamples >>  8) & 0xff);\r
-               trace[traceLen++] = ((rsamples >> 16) & 0xff);\r
-               trace[traceLen++] = 0x80 | ((rsamples >> 24) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >>  0) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >>  8) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >> 16) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >> 24) & 0xff);\r
-               trace[traceLen++] = Demod.len;\r
-               memcpy(trace+traceLen, receivedAnswer, Demod.len);\r
-               traceLen += Demod.len;\r
-               if(traceLen > TRACE_LENGTH) goto done;\r
-               //////////////////////////////////////////////////////////////////\r
-               // Then Construct SELECT UID (cascasde 2) command\r
-               DbpString("Just about to copy the UID out of the cascade 2 id req");\r
-               // First copy the 5 bytes (Mifare Classic) after the 95 70\r
-               memcpy(cmd5+2,receivedAnswer,5);\r
-               // Secondly compute the two CRC bytes at the end\r
-               ComputeCrc14443(CRC_14443_A, cmd4, 7, &cmd5[7], &cmd5[8]);\r
-               // Prepare the bit sequence to modulate the subcarrier\r
-               // Store answer in buffer\r
-               trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-               trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-               trace[traceLen++] = 9;\r
-               memcpy(trace+traceLen, cmd5, 9);\r
-               traceLen += 9;\r
-               if(traceLen > TRACE_LENGTH) goto done;\r
-               CodeIso14443aAsReader(cmd5, sizeof(cmd5));\r
-               memcpy(req5, ToSend, ToSendMax); req5Len = ToSendMax;\r
-\r
-               // Select the card\r
-               TransmitFor14443a(req4, req4Len, &samples, &wait);\r
-               if(!GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) {\r
-                       continue;\r
-               }\r
-\r
-               // Store answer in buffer\r
-               rsamples = rsamples + (samples - Demod.samples);\r
-               trace[traceLen++] = ((rsamples >>  0) & 0xff);\r
-               trace[traceLen++] = ((rsamples >>  8) & 0xff);\r
-               trace[traceLen++] = ((rsamples >> 16) & 0xff);\r
-               trace[traceLen++] = 0x80 | ((rsamples >> 24) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >>  0) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >>  8) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >> 16) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >> 24) & 0xff);\r
-               trace[traceLen++] = Demod.len;\r
-               memcpy(trace+traceLen, receivedAnswer, Demod.len);\r
-               traceLen += Demod.len;\r
-               if(traceLen > TRACE_LENGTH) goto done;\r
-\r
+      // Transmit SELECT_ALL\r
+      ReaderTransmit(sel_all_c2,sizeof(sel_all_c2));\r
+      \r
+      // Receive the UID\r
+      if (!ReaderReceive(receivedAnswer)) continue;\r
+      \r
+      // Construct SELECT UID command\r
+      memcpy(sel_uid_c2+2,receivedAnswer,5);\r
+      // Secondly compute the two CRC bytes at the end\r
+      AppendCrc14443a(sel_uid_c2,7);\r
+      \r
+      // Transmit SELECT_UID\r
+      ReaderTransmit(sel_uid_c2,sizeof(sel_uid_c2));\r
+      \r
+      // Receive the SAK\r
+      if (!ReaderReceive(receivedAnswer)) continue;\r
                }\r
 \r
-               // Secondly compute the two CRC bytes at the end\r
-               ComputeCrc14443(CRC_14443_A, cmd7, 2, &cmd7[2], &cmd7[3]);\r
-               CodeIso14443aAsReader(cmd7, sizeof(cmd7));\r
-               memcpy(req7, ToSend, ToSendMax); req7Len = ToSendMax;\r
-               // Send authentication request (Mifare Classic)\r
-               TransmitFor14443a(req7, req7Len, &samples, &wait);\r
-               trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-               trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0; trace[traceLen++] = 0;\r
-               trace[traceLen++] = 4;\r
-               memcpy(trace+traceLen, cmd7, 4);\r
-               traceLen += 4;\r
-               if(traceLen > TRACE_LENGTH) goto done;\r
-               if(GetIso14443aAnswerFromTag(receivedAnswer, 100, &samples, &elapsed)) {\r
-                       rsamples++;\r
-                       // We received probably a random, continue and trace!\r
-               }\r
-               else {\r
-                       // Received nothing\r
-                       continue;\r
-               }\r
+    // Transmit MIFARE_CLASSIC_AUTH\r
+    ReaderTransmit(mf_auth,sizeof(mf_auth));\r
 \r
-               // Trace the random, i'm curious\r
-               rsamples = rsamples + (samples - Demod.samples);\r
-               trace[traceLen++] = ((rsamples >>  0) & 0xff);\r
-               trace[traceLen++] = ((rsamples >>  8) & 0xff);\r
-               trace[traceLen++] = ((rsamples >> 16) & 0xff);\r
-               trace[traceLen++] = 0x80 | ((rsamples >> 24) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >>  0) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >>  8) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >> 16) & 0xff);\r
-               trace[traceLen++] = ((Demod.parityBits >> 24) & 0xff);\r
-               trace[traceLen++] = Demod.len;\r
-               memcpy(trace+traceLen, receivedAnswer, Demod.len);\r
-               traceLen += Demod.len;\r
-               if(traceLen > TRACE_LENGTH) goto done;\r
-\r
-               // Thats it...\r
+    // Receive the (16 bit) "random" nonce\r
+    if (!ReaderReceive(receivedAnswer)) continue;\r
        }\r
 \r
-done:\r
+  // Thats it...\r
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
        LEDsoff();\r
-       DbpIntegers(rsamples, 0xCC, 0xCC);\r
+       Dbprintf("%x %x %x", rsamples, 0xCC, 0xCC);\r
        DbpString("ready..");\r
 }\r
+\r
+//-----------------------------------------------------------------------------\r
+// Read an ISO 14443a tag. Send out commands and store answers.\r
+//\r
+//-----------------------------------------------------------------------------\r
+void ReaderMifare(DWORD parameter)\r
+{\r
+  \r
+       // Anticollision\r
+       BYTE wupa[]       = { 0x52 };\r
+       BYTE sel_all[]    = { 0x93,0x20 };\r
+       BYTE sel_uid[]    = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };\r
+  \r
+       // Mifare AUTH\r
+       BYTE mf_auth[]    = { 0x60,0x00,0xf5,0x7b };\r
+  BYTE mf_nr_ar[]   = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };\r
+  \r
+  BYTE* receivedAnswer = (((BYTE *)BigBuf) + 3560);    // was 3560 - tied to other size changes\r
+  traceLen = 0;\r
+  tracing = false;\r
+  \r
+       // Setup SSC\r
+       FpgaSetupSsc();\r
+  \r
+       // Start from off (no field generated)\r
+  // Signal field is off with the appropriate LED\r
+  LED_D_OFF();\r
+  FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+  SpinDelay(200);\r
+  \r
+  SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
+  FpgaSetupSsc();\r
+  \r
+       // Now give it time to spin up.\r
+  // Signal field is on with the appropriate LED\r
+  LED_D_ON();\r
+  FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
+       SpinDelay(200);\r
+  \r
+       LED_A_ON();\r
+       LED_B_OFF();\r
+       LED_C_OFF();\r
+  \r
+  // Broadcast for a card, WUPA (0x52) will force response from all cards in the field\r
+  ReaderTransmitShort(wupa);\r
+  // Receive the ATQA\r
+  ReaderReceive(receivedAnswer);\r
+  // Transmit SELECT_ALL\r
+  ReaderTransmit(sel_all,sizeof(sel_all));\r
+  // Receive the UID\r
+  ReaderReceive(receivedAnswer);\r
+  // Construct SELECT UID command\r
+  // First copy the 5 bytes (Mifare Classic) after the 93 70\r
+  memcpy(sel_uid+2,receivedAnswer,5);\r
+  // Secondly compute the two CRC bytes at the end\r
+  AppendCrc14443a(sel_uid,7);\r
+    \r
+  byte_t nt_diff = 0;\r
+  LED_A_OFF();\r
+  byte_t par = 0;\r
+  byte_t par_mask = 0xff;\r
+  byte_t par_low = 0;\r
+  BOOL led_on = TRUE;\r
+  \r
+  tracing = FALSE;\r
+  byte_t nt[4];\r
+  byte_t nt_attacked[4];\r
+  byte_t par_list[8];\r
+  byte_t ks_list[8];\r
+  num_to_bytes(parameter,4,nt_attacked);\r
+\r
+  while(TRUE)\r
+  {\r
+    FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+    SpinDelay(200);\r
+    FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
+    \r
+    // Broadcast for a card, WUPA (0x52) will force response from all cards in the field\r
+    ReaderTransmitShort(wupa);\r
+    \r
+    // Test if the action was cancelled\r
+    if(BUTTON_PRESS()) {\r
+      break;\r
+    }\r
+    \r
+    // Receive the ATQA\r
+    if (!ReaderReceive(receivedAnswer)) continue;\r
+    \r
+    // Transmit SELECT_ALL\r
+    ReaderTransmit(sel_all,sizeof(sel_all));\r
+    \r
+    // Receive the UID\r
+    if (!ReaderReceive(receivedAnswer)) continue;\r
+    \r
+    // Transmit SELECT_UID\r
+    ReaderTransmit(sel_uid,sizeof(sel_uid));\r
+    \r
+    // Receive the SAK\r
+    if (!ReaderReceive(receivedAnswer)) continue;\r
+    \r
+    // Transmit MIFARE_CLASSIC_AUTH\r
+    ReaderTransmit(mf_auth,sizeof(mf_auth));\r
+    \r
+    // Receive the (16 bit) "random" nonce\r
+    if (!ReaderReceive(receivedAnswer)) continue;\r
+    memcpy(nt,receivedAnswer,4);\r
+\r
+    // Transmit reader nonce and reader answer\r
+    ReaderTransmitPar(mf_nr_ar,sizeof(mf_nr_ar),par);\r
+    \r
+    // Receive 4 bit answer\r
+    if (ReaderReceive(receivedAnswer))\r
+    {\r
+      if (nt_diff == 0)        \r
+      {\r
+        LED_A_ON();\r
+        memcpy(nt_attacked,nt,4);\r
+        par_mask = 0xf8;\r
+        par_low = par & 0x07;\r
+      }\r
+\r
+      if (memcmp(nt,nt_attacked,4) != 0) continue;\r
+\r
+      led_on = !led_on;\r
+      if(led_on) LED_B_ON(); else LED_B_OFF();\r
+      par_list[nt_diff] = par;\r
+      ks_list[nt_diff] = receivedAnswer[0]^0x05;\r
+      \r
+      // Test if the information is complete\r
+      if (nt_diff == 0x07) break;\r
+      \r
+      nt_diff = (nt_diff+1) & 0x07;\r
+      mf_nr_ar[3] = nt_diff << 5;\r
+      par = par_low;\r
+    } else {\r
+      if (nt_diff == 0)\r
+      {\r
+        par++;\r
+      } else {\r
+        par = (((par>>3)+1) << 3) | par_low;\r
+      }\r
+    }\r
+  }\r
+  \r
+  LogTraceInfo(sel_uid+2,4);\r
+  LogTraceInfo(nt,4);\r
+  LogTraceInfo(par_list,8);\r
+  LogTraceInfo(ks_list,8);\r
+  \r
+  // Thats it...\r
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+       LEDsoff();\r
+  tracing = TRUE;\r
+}\r
Impressum, Datenschutz