//-----------------------------------------------------------------------------\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
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
//-----------------------------------------------------------------------------\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
\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
// And now we loop, receiving samples.\r
for(;;) {\r
WDT_HIT();\r
- int behindBy = (lastRxCounter - PDC_RX_COUNTER(SSC_BASE)) &\r
+ int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &\r
(DMA_BUFFER_SIZE-1);\r
if(behindBy > maxBehindBy) {\r
maxBehindBy = behindBy;\r
if(upTo - dmaBuf > DMA_BUFFER_SIZE) {\r
upTo -= DMA_BUFFER_SIZE;\r
lastRxCounter += DMA_BUFFER_SIZE;\r
- PDC_RX_NEXT_POINTER(SSC_BASE) = (DWORD)upTo;\r
- PDC_RX_NEXT_COUNTER(SSC_BASE) = DMA_BUFFER_SIZE;\r
+ AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD)upTo;\r
+ AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;\r
}\r
\r
samples += 4;\r
\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
- PDC_CONTROL(SSC_BASE) = PDC_RX_DISABLE;\r
- DbpIntegers(maxBehindBy, Uart.state, Uart.byteCnt);\r
- DbpIntegers(Uart.byteCntMax, traceLen, (int)Uart.output[0]);\r
+ AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;\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
\r
if(BUTTON_PRESS()) return FALSE;\r
\r
- if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
- SSC_TRANSMIT_HOLDING = 0x00;\r
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
+ AT91C_BASE_SSC->SSC_THR = 0x00;\r
}\r
- if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
- BYTE b = (BYTE)SSC_RECEIVE_HOLDING;\r
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
+ BYTE b = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
if(MillerDecoding((b & 0xf0) >> 4)) {\r
*len = Uart.byteCnt;\r
return TRUE;\r
} 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
} 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
\r
// Modulate Manchester\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD);\r
- SSC_TRANSMIT_HOLDING = 0x00;\r
+ AT91C_BASE_SSC->SSC_THR = 0x00;\r
FpgaSetupSsc();\r
\r
// ### Transmit the response ###\r
b = 0x00;\r
fdt_indicator = FALSE;\r
for(;;) {\r
- if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
- volatile BYTE b = (BYTE)SSC_RECEIVE_HOLDING;\r
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
+ volatile BYTE b = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
(void)b;\r
}\r
- if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
if(i > respLen) {\r
b = 0x00;\r
u++;\r
b = resp[i];\r
i++;\r
}\r
- SSC_TRANSMIT_HOLDING = b;\r
+ AT91C_BASE_SSC->SSC_THR = b;\r
\r
if(u > 4) {\r
break;\r
\r
}\r
\r
- DbpIntegers(happened, happened2, cmdsRecvd);\r
+ Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);\r
LED_A_OFF();\r
}\r
\r
//-----------------------------------------------------------------------------\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(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
- SSC_TRANSMIT_HOLDING = 0x00; // For exact timing!\r
- c++;\r
- }\r
- if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
- volatile DWORD r = SSC_RECEIVE_HOLDING;\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(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
- SSC_TRANSMIT_HOLDING = cmd[c];\r
- c++;\r
- if(c >= len) {\r
- break;\r
- }\r
- }\r
- if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
- volatile DWORD r = SSC_RECEIVE_HOLDING;\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
// 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
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
\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
Demod.state = DEMOD_UNSYNCD;\r
\r
BYTE b;\r
- *elapsed = 0;\r
+ if (elapsed) *elapsed = 0;\r
\r
c = 0;\r
for(;;) {\r
WDT_HIT();\r
\r
- if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
- SSC_TRANSMIT_HOLDING = 0x00; // To make use of exact timing of next command from reader!!\r
- (*elapsed)++;\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
+ if (elapsed) (*elapsed)++;\r
}\r
- if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
if(c < 512) { c++; } else { return FALSE; }\r
- b = (BYTE)SSC_RECEIVE_HOLDING;\r
+ b = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
if(ManchesterDecoding((b & 0xf0) >> 4)) {\r
*samples = ((c - 1) << 3) + 4;\r
return TRUE;\r
}\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
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