// same construction as in ISO 14443;
// different initial value (CRC_ICLASS)
#include "iso14443crc.h"
+#include "iso15693tools.h"
static int timeout = 4096;
#define SEC_Y 0x00
#define SEC_Z 0xc0
-// SAME AS IN iso14443a.
-#define RECV_CMD_OFFSET 3032
-#define RECV_RES_OFFSET 3096
-#define DMA_BUFFER_OFFSET 3160
-#define DMA_BUFFER_SIZE 4096
-#define TRACE_LENGTH 3000
-
-uint32_t SwapBits(uint32_t value, int nrbits) {
- int i;
- uint32_t newvalue = 0;
- for(i = 0; i < nrbits; i++) {
- newvalue ^= ((value >> i) & 1) << (nrbits - 1 - i);
- }
- return newvalue;
-}
-
static int SendIClassAnswer(uint8_t *resp, int respLen, int delay);
//-----------------------------------------------------------------------------
// #define RECV_RES_OFFSET 3096
// #define DMA_BUFFER_OFFSET 3160
// #define DMA_BUFFER_SIZE 4096
-// #define TRACE_LENGTH 3000
+// #define TRACE_SIZE 3000
// We won't start recording the frames that we acquire until we trigger;
// a good trigger condition to get started is probably when we see a
// reset traceLen to 0
iso14a_set_tracing(TRUE);
- iso14a_clear_tracelen();
+ iso14a_clear_trace();
iso14a_set_trigger(FALSE);
// The DMA buffer, used to stream samples from the FPGA
trace[traceLen++] = Uart.byteCnt;
memcpy(trace+traceLen, receivedCmd, Uart.byteCnt);
traceLen += Uart.byteCnt;
- if(traceLen > TRACE_LENGTH) break;
+ if(traceLen > TRACE_SIZE) break;
//}
/* And ready to receive another command. */
Uart.state = STATE_UNSYNCD;
trace[traceLen++] = Demod.len;
memcpy(trace+traceLen, receivedResponse, Demod.len);
traceLen += Demod.len;
- if(traceLen > TRACE_LENGTH) break;
+ if(traceLen > TRACE_SIZE) break;
//triggered = TRUE;
LED_D_OFF();
}
-
-void rotateCSN(uint8_t* originalCSN, uint8_t* rotatedCSN, int direction) {
- int i;
- int j = 0;
-
- if(direction == 0) {
- for(i = 0; i < 8; i++) {
- rotatedCSN[i] = (originalCSN[i] >> 3) | (originalCSN[(i+1)%8] << 5);
- }
- } else {
- for(i = 0; i < 8; i++) {
- if(i == 0) { j = 7; } else { j = i - 1; }
- originalCSN[i] = (rotatedCSN[i] << 3) | (rotatedCSN[j] >> 5);
- }
+void rotateCSN(uint8_t* originalCSN, uint8_t* rotatedCSN) {
+ int i;
+ for(i = 0; i < 8; i++) {
+ rotatedCSN[i] = (originalCSN[i] >> 3) | (originalCSN[(i+1)%8] << 5);
}
}
//-----------------------------------------------------------------------------
static int GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen)
{
- // Set FPGA mode to "simulated ISO 14443A tag", no modulation (listen
+ // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen
// only, since we are receiving, not transmitting).
// Signal field is off with the appropriate LED
LED_D_OFF();
//-----------------------------------------------------------------------------
void SimulateIClass(uint8_t arg0, uint8_t *datain)
{
- // DEFINED ABOVE
- // #define RECV_CMD_OFFSET 3032
- // #define RECV_RES_OFFSET 3096
- // #define DMA_BUFFER_OFFSET 3160
- // #define DMA_BUFFER_SIZE 4096
- // #define TRACE_LENGTH 3000
uint8_t simType = arg0;
- int SMALL_BUFFER_OFFSET = 2000;
- bool fullbuffer = FALSE;
- uint32_t parityBits = 0;
-
- iso14a_set_tracing(TRUE);
- iso14a_clear_tracelen();
- iso14a_set_trigger(FALSE);
- // PREPARE PROTOCOL MESSAGES FIRST
-
- // Pointers to tag answers that should be stored in the buffer
- uint8_t *response;
- int responselength;
+ // Enable and clear the trace
+ tracing = TRUE;
+ traceLen = 0;
+ memset(trace, 0x44, TRACE_SIZE);
// CSN followed by two CRC bytes
- uint8_t response1[] = { 0x0f }; // Tag SOF
uint8_t response2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t response3[] = { 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x00 };
- int response1length = 1;
- int response2length = 10;
- int response3length = 10;
+ uint8_t response3[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0, 0x00, 0x00 };
// e-Purse
uint8_t response4[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- int response4length = 8;
if(simType == 0) {
// Use the CSN from commandline
}
// Construct anticollision-CSN
- rotateCSN(response3,response2,0);
+ rotateCSN(response3,response2);
// Compute CRC on both CSNs
ComputeCrc14443(CRC_ICLASS, response2, 8, &response2[8], &response2[9]);
// Reader 81 anticoll. CSN
// Tag CSN
- uint8_t *resp;
- int respLen;
+ uint8_t *resp;
+ int respLen;
+ uint8_t* respdata = NULL;
+ int respsize = 0;
+ uint8_t sof = 0x0f;
// Respond SOF -- takes 8 bytes
- uint8_t *resp1 = (((uint8_t *)BigBuf));
+ uint8_t *resp1 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
int resp1Len;
// Anticollision CSN (rotated CSN)
// 176: Takes 16 bytes for SOF/EOF and 10 * 16 = 160 bytes (2 bytes/bit)
- uint8_t *resp2 = (((uint8_t *)BigBuf) + 10 + SMALL_BUFFER_OFFSET);
+ uint8_t *resp2 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 10);
int resp2Len;
// CSN
// 176: Takes 16 bytes for SOF/EOF and 10 * 16 = 160 bytes (2 bytes/bit)
- uint8_t *resp3 = (((uint8_t *)BigBuf) + 190 + SMALL_BUFFER_OFFSET);
- //int resp3Len; // NOT USED
+ uint8_t *resp3 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 190);
+ int resp3Len;
// e-Purse
// 144: Takes 16 bytes for SOF/EOF and 8 * 16 = 128 bytes (2 bytes/bit)
- uint8_t *resp4 = (((uint8_t *)BigBuf) + 270 + SMALL_BUFFER_OFFSET);
+ uint8_t *resp4 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 370);
int resp4Len;
// + 1720..
- //uint8_t *receivedCmd = (uint8_t *)BigBuf;
- uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
- memset(receivedCmd, 0x44, 64);
+ uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
+ memset(receivedCmd, 0x44, RECV_CMD_SIZE);
int len;
- // Reset trace buffer
- memset(trace, 0x44, RECV_CMD_OFFSET);
-
// Prepare card messages
ToSendMax = 0;
// CSN
CodeIClassTagAnswer(response3, sizeof(response3));
- memcpy(resp3, ToSend, ToSendMax); //resp3Len = ToSendMax; // NOT USED
+ memcpy(resp3, ToSend, ToSendMax); resp3Len = ToSendMax;
// e-Purse
CodeIClassTagAnswer(response4, sizeof(response4));
FpgaSetupSsc();
// To control where we are in the protocol
- //int order = 0;
- // int lastorder; // NOT USED
int cmdsRecvd = 0;
- resp = resp1; respLen = 0;
- response = response1; responselength = response1length;
+
LED_A_ON();
for(;;) {
LED_B_OFF();
if(!GetIClassCommandFromReader(receivedCmd, &len, 100)) {
- DbpString("button press");
+ DbpString("button press");
break;
- }
+ }
- // Okay, look at the command now.
- //lastorder = order; // NOT USED
- if(receivedCmd[0] == 0x0a) {
+ // Okay, look at the command now.
+ if(receivedCmd[0] == 0x0a) {
// Reader in anticollission phase
resp = resp1; respLen = resp1Len; //order = 1;
- response = response1; responselength = response1length;
+ respdata = &sof;
+ respsize = sizeof(sof);
//resp = resp2; respLen = resp2Len; order = 2;
//DbpString("Hello request from reader:");
} else if(receivedCmd[0] == 0x0c) {
// Reader asks for anticollission CSN
resp = resp2; respLen = resp2Len; //order = 2;
- response = response2; responselength = response2length;
+ respdata = response2;
+ respsize = sizeof(response2);
//DbpString("Reader requests anticollission CSN:");
} else if(receivedCmd[0] == 0x81) {
// Reader selects anticollission CSN.
// Tag sends the corresponding real CSN
- resp = resp3; respLen = resp2Len; //order = 3;
- response = response3; responselength = response3length;
+ resp = resp3; respLen = resp3Len; //order = 3;
+ respdata = response3;
+ respsize = sizeof(response3);
//DbpString("Reader selects anticollission CSN:");
} else if(receivedCmd[0] == 0x88) {
// Read e-purse (88 02)
resp = resp4; respLen = resp4Len; //order = 4;
- response = response4; responselength = response4length;
+ respdata = response4;
+ respsize = sizeof(response4);
LED_B_ON();
} else if(receivedCmd[0] == 0x05) {
// Reader random and reader MAC!!!
// Lets store this ;-)
- Dbprintf(" CSN: %02x %02x %02x %02x %02x %02x %02x %02x",
+/*
+ Dbprintf(" CSN: %02x %02x %02x %02x %02x %02x %02x %02x",
response3[0], response3[1], response3[2],
response3[3], response3[4], response3[5],
response3[6], response3[7]);
+*/
Dbprintf("READER AUTH (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x",
len,
receivedCmd[0], receivedCmd[1], receivedCmd[2],
// Do not respond
// We do not know what to answer, so lets keep quit
resp = resp1; respLen = 0; //order = 5;
+ respdata = NULL;
+ respsize = 0;
} else if(receivedCmd[0] == 0x00 && len == 1) {
// Reader ends the session
resp = resp1; respLen = 0; //order = 0;
- } else {
+ respdata = NULL;
+ respsize = 0;
+ } else {
// Never seen this command before
Dbprintf("Unknown command received from reader (len=%d): %x %x %x %x %x %x %x %x %x",
len,
receivedCmd[6], receivedCmd[7], receivedCmd[8]);
// Do not respond
resp = resp1; respLen = 0; //order = 0;
- response = response1; responselength = response1length;
+ respdata = NULL;
+ respsize = 0;
}
if(cmdsRecvd > 999) {
cmdsRecvd++;
}
- if(respLen <= 0) continue;
-
- SendIClassAnswer(resp, respLen, 21);
-
- // Store commands and responses in buffer
- // as long as there is room for it.
- if(traceLen < (SMALL_BUFFER_OFFSET - 32)) {
- if(tracing) {
- LogTrace(receivedCmd,len,0,GetParity(receivedCmd,len),TRUE);
- parityBits = SwapBits(GetParity(response,responselength),responselength);
- LogTrace(response,responselength,0,parityBits,FALSE);
+ if(respLen > 0) {
+ SendIClassAnswer(resp, respLen, 21);
+ }
+
+ if (tracing) {
+ LogTrace(receivedCmd,len, rsamples, Uart.parityBits, TRUE);
+ if (respdata != NULL) {
+ LogTrace(respdata,respsize, rsamples, SwapBits(GetParity(respdata,respsize),respsize), FALSE);
+ }
+ if(traceLen > TRACE_SIZE) {
+ DbpString("Trace full");
+ break;
}
- } else if(!fullbuffer) {
- DbpString("Trace buffer is full now...");
- fullbuffer = TRUE;
}
- memset(receivedCmd, 0x44, 32);
- }
+ memset(receivedCmd, 0x44, RECV_CMD_SIZE);
+ }
- //Dbprintf("Commands received: %d", cmdsRecvd);
+ Dbprintf("%x", cmdsRecvd);
LED_A_OFF();
LED_B_OFF();
}
{
int i = 0, u = 0, d = 0;
uint8_t b = 0;
+ // return 0;
+ // Modulate Manchester
+ // FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD424);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD);
AT91C_BASE_SSC->SSC_THR = 0x00;
FpgaSetupSsc();
LED_A_ON();
// Store reader command in buffer
- if (tracing) LogTrace(frame,len,0,par,TRUE);
+ if (tracing) LogTrace(frame,len,rsamples,par,TRUE);
}
//-----------------------------------------------------------------------------
{
int samples = 0;
if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return FALSE;
- if (tracing) LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE);
+ rsamples += samples;
+ if (tracing) LogTrace(receivedAnswer,Demod.len,rsamples,Demod.parityBits,FALSE);
if(samples == 0) return FALSE;
return Demod.len;
}
// Reader iClass Anticollission
void ReaderIClass(uint8_t arg0) {
- int i = 0;
- int length = 0;
- bool csn_failure = FALSE;
-
uint8_t act_all[] = { 0x0a };
uint8_t identify[] = { 0x0c };
uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t check_csn[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes
LED_A_ON();
for(;;) {
- if(traceLen > TRACE_LENGTH || BUTTON_PRESS()) break;
+
+ if(traceLen > TRACE_SIZE) {
+ DbpString("Trace full");
+ break;
+ }
+
+ if (BUTTON_PRESS()) break;
// Send act_all
ReaderTransmitIClass(act_all, 1);
// Card present?
if(ReaderReceiveIClass(resp)) {
ReaderTransmitIClass(identify, 1);
- if((length = ReaderReceiveIClass(resp))) {
- if(length == 10) {
- // Select card
- memcpy(&select[1],resp,8);
- ReaderTransmitIClass(select, sizeof(select));
-
- if((length = ReaderReceiveIClass(resp))) {
- if(length == 10) {
- rotateCSN(check_csn,&select[1],1);
- csn_failure = FALSE;
- for(i = 0; i < 8; i++) {
- if(check_csn[i] != resp[i]) {
- csn_failure = TRUE;
- break;
- }
- }
-
- if(!csn_failure) {
- Dbprintf(" Selected CSN: %02x %02x %02x %02x %02x %02x %02x %02x",
- check_csn[0], check_csn[1], check_csn[2],
- check_csn[3], check_csn[4], check_csn[5],
- check_csn[6], check_csn[7]);
- }
- // Card selected, whats next... ;-)
-
- }
- }
+ if(ReaderReceiveIClass(resp) == 10) {
+ // Select card
+ memcpy(&select[1],resp,8);
+ ReaderTransmitIClass(select, sizeof(select));
+
+ if(ReaderReceiveIClass(resp) == 10) {
+ Dbprintf(" Selected CSN: %02x %02x %02x %02x %02x %02x %02x %02x",
+ resp[0], resp[1], resp[2],
+ resp[3], resp[4], resp[5],
+ resp[6], resp[7]);
}
+ // Card selected, whats next... ;-)
}
}
WDT_HIT();
}
LED_A_OFF();
+}
+
+void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
+ uint8_t act_all[] = { 0x0a };
+ uint8_t identify[] = { 0x0c };
+ uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ uint8_t readcheck_cc[]= { 0x88, 0x02 };
+ uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 };
+
+ uint16_t crc = 0;
+ uint8_t cardsize=0;
+ bool read_success=false;
+ uint8_t mem=0;
+
+ static struct memory_t{
+ int k16;
+ int book;
+ int k2;
+ int lockauth;
+ int keyaccess;
+ } memory;
+
+ uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes
+ // Reset trace buffer
+ memset(trace, 0x44, RECV_CMD_OFFSET);
+ traceLen = 0;
+
+ // 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);
+
+ // Now give it time to spin up.
+ // Signal field is on with the appropriate LED
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
+ SpinDelay(200);
+
+ LED_A_ON();
+
+ for(int i=0;i<1;i++) {
+
+ if(traceLen > TRACE_SIZE) {
+ DbpString("Trace full");
+ break;
+ }
+
+ if (BUTTON_PRESS()) break;
+
+ // Send act_all
+ ReaderTransmitIClass(act_all, 1);
+ // Card present?
+ if(ReaderReceiveIClass(resp)) {
+ ReaderTransmitIClass(identify, 1);
+ if(ReaderReceiveIClass(resp) == 10) {
+ // Select card
+ memcpy(&select[1],resp,8);
+ ReaderTransmitIClass(select, sizeof(select));
+
+ if(ReaderReceiveIClass(resp) == 10) {
+ Dbprintf(" Selected CSN: %02x %02x %02x %02x %02x %02x %02x %02x",
+ resp[0], resp[1], resp[2],
+ resp[3], resp[4], resp[5],
+ resp[6], resp[7]);
+ }
+ // Card selected
+ Dbprintf("Readcheck on Sector 2");
+ ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));
+ if(ReaderReceiveIClass(resp) == 8) {
+ Dbprintf(" CC: %02x %02x %02x %02x %02x %02x %02x %02x",
+ resp[0], resp[1], resp[2],
+ resp[3], resp[4], resp[5],
+ resp[6], resp[7]);
+ }else return;
+ Dbprintf("Authenticate");
+ //for now replay captured auth (as cc not updated)
+ memcpy(check+5,MAC,4);
+ Dbprintf(" AA: %02x %02x %02x %02x",
+ check[5], check[6], check[7],check[8]);
+ ReaderTransmitIClass(check, sizeof(check));
+ if(ReaderReceiveIClass(resp) == 4) {
+ Dbprintf(" AR: %02x %02x %02x %02x",
+ resp[0], resp[1], resp[2],resp[3]);
+ }else {
+ Dbprintf("Error: Authentication Fail!");
+ return;
+ }
+ Dbprintf("Dump Contents");
+ //first get configuration block
+ read_success=false;
+ read[1]=1;
+ uint8_t *blockno=&read[1];
+ crc = iclass_crc16((char *)blockno,1);
+ read[2] = crc >> 8;
+ read[3] = crc & 0xff;
+ while(!read_success){
+ ReaderTransmitIClass(read, sizeof(read));
+ if(ReaderReceiveIClass(resp) == 10) {
+ read_success=true;
+ mem=resp[5];
+ memory.k16= (mem & 0x80);
+ memory.book= (mem & 0x20);
+ memory.k2= (mem & 0x8);
+ memory.lockauth= (mem & 0x2);
+ memory.keyaccess= (mem & 0x1);
+
+ }
+ }
+ if (memory.k16){
+ cardsize=255;
+ }else cardsize=32;
+ //then loop around remaining blocks
+ for(uint8_t j=0; j<cardsize; j++){
+ read_success=false;
+ uint8_t *blockno=&j;
+ //crc_data[0]=j;
+ read[1]=j;
+ crc = iclass_crc16((char *)blockno,1);
+ read[2] = crc >> 8;
+ read[3] = crc & 0xff;
+ while(!read_success){
+ ReaderTransmitIClass(read, sizeof(read));
+ if(ReaderReceiveIClass(resp) == 10) {
+ read_success=true;
+ Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
+ j, resp[0], resp[1], resp[2],
+ resp[3], resp[4], resp[5],
+ resp[6], resp[7]);
+ }
+ }
+ }
+ }
+ }
+ WDT_HIT();
+ }
+
+ LED_A_OFF();
}
+