//-----------------------------------------------------------------------------
-// Merlok - June 2011
+// Merlok - June 2011, 2012
// Gerhard de Koning Gans - May 2008
// Hagen Fritsch - June 2010
//
#include "apps.h"
#include "util.h"
#include "string.h"
+#include "cmd.h"
#include "iso14443crc.h"
#include "iso14443a.h"
#include "crapto1.h"
#include "mifareutil.h"
-static uint8_t *trace = (uint8_t *) BigBuf;
-static int traceLen = 0;
-static int rsamples = 0;
-static int tracing = TRUE;
static uint32_t iso14a_timeout;
+uint8_t *trace = (uint8_t *) BigBuf+TRACE_OFFSET;
+int traceLen = 0;
+int rsamples = 0;
+int tracing = TRUE;
+uint8_t trigger = 0;
+// the block number for the ISO14443-4 PCB
+static uint8_t iso14_pcb_blocknum = 0;
// CARD TO READER - manchester
// Sequence D: 11110000 modulation with subcarrier during first half
#define SEC_Y 0x00
#define SEC_Z 0xc0
-static const uint8_t OddByteParity[256] = {
+const uint8_t OddByteParity[256] = {
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
};
-uint8_t trigger = 0;
-void iso14a_set_trigger(int enable) {
+
+void iso14a_set_trigger(bool enable) {
trigger = enable;
}
-void iso14a_clear_tracelen(void) {
+void iso14a_clear_trace() {
+ memset(trace, 0x44, TRACE_SIZE);
traceLen = 0;
}
-void iso14a_set_tracing(int enable) {
+
+void iso14a_set_tracing(bool enable) {
tracing = enable;
}
+void iso14a_set_timeout(uint32_t timeout) {
+ iso14a_timeout = timeout;
+}
+
//-----------------------------------------------------------------------------
// Generate the parity value for a byte sequence
//
ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1);
}
-int LogTrace(const uint8_t * btBytes, int iLen, int iSamples, uint32_t dwParity, int bReader)
+// The function LogTrace() is also used by the iClass implementation in iClass.c
+int RAMFUNC LogTrace(const uint8_t * btBytes, int iLen, int iSamples, uint32_t dwParity, int bReader)
{
// Return when trace is full
- if (traceLen >= TRACE_LENGTH) return FALSE;
+ if (traceLen >= TRACE_SIZE) return FALSE;
// Trace the random, i'm curious
rsamples += iSamples;
// The software UART that receives commands from the reader, and its state
// variables.
//-----------------------------------------------------------------------------
-static struct {
- enum {
- STATE_UNSYNCD,
- STATE_START_OF_COMMUNICATION,
- STATE_MILLER_X,
- STATE_MILLER_Y,
- STATE_MILLER_Z,
- STATE_ERROR_WAIT
- } state;
- uint16_t shiftReg;
- int bitCnt;
- int byteCnt;
- int byteCntMax;
- int posCnt;
- int syncBit;
- int parityBits;
- int samples;
- int highCnt;
- int bitBuffer;
- enum {
- DROP_NONE,
- DROP_FIRST_HALF,
- DROP_SECOND_HALF
- } drop;
- uint8_t *output;
-} Uart;
+static tUart Uart;
static RAMFUNC int MillerDecoding(int bit)
{
- int error = 0;
+ //int error = 0;
int bitright;
if(!Uart.bitBuffer) {
// measured a drop in first and second half
// which should not be possible
Uart.state = STATE_ERROR_WAIT;
- error = 0x01;
+ //error = 0x01;
}
Uart.posCnt = 0;
if(Uart.drop == DROP_SECOND_HALF) {
// error, should not happen in SOC
Uart.state = STATE_ERROR_WAIT;
- error = 0x02;
+ //error = 0x02;
}
else {
// correct SOC
// Would be STATE_MILLER_Z
// but Z does not follow X, so error
Uart.state = STATE_ERROR_WAIT;
- error = 0x03;
+ //error = 0x03;
}
if(Uart.drop == DROP_SECOND_HALF) {
// We see a '1' and stay in state X
Uart.bitCnt = 0;
Uart.byteCnt = 0;
Uart.parityBits = 0;
- error = 0;
+ //error = 0;
}
else {
Uart.highCnt = 0;
//=============================================================================
// ISO 14443 Type A - Manchester
//=============================================================================
-
-static struct {
- enum {
- DEMOD_UNSYNCD,
- DEMOD_START_OF_COMMUNICATION,
- DEMOD_MANCHESTER_D,
- DEMOD_MANCHESTER_E,
- DEMOD_MANCHESTER_F,
- DEMOD_ERROR_WAIT
- } state;
- int bitCount;
- int posCount;
- int syncBit;
- int parityBits;
- uint16_t shiftReg;
- int buffer;
- int buff;
- int samples;
- int len;
- enum {
- SUB_NONE,
- SUB_FIRST_HALF,
- SUB_SECOND_HALF
- } sub;
- uint8_t *output;
-} Demod;
+static tDemod Demod;
static RAMFUNC int ManchesterDecoding(int v)
{
int bit;
int modulation;
- int error = 0;
+ //int error = 0;
if(!Demod.buff) {
Demod.buff = 1;
case 0x01: Demod.samples = 0; break;
}
}
- error = 0;
+ //error = 0;
}
}
else {
if(Demod.state!=DEMOD_ERROR_WAIT) {
Demod.state = DEMOD_ERROR_WAIT;
Demod.output[Demod.len] = 0xaa;
- error = 0x01;
+ //error = 0x01;
}
}
else if(modulation) {
else {
Demod.output[Demod.len] = 0xab;
Demod.state = DEMOD_ERROR_WAIT;
- error = 0x02;
+ //error = 0x02;
}
break;
else {
Demod.output[Demod.len] = 0xad;
Demod.state = DEMOD_ERROR_WAIT;
- error = 0x03;
+ //error = 0x03;
}
break;
// triggering so that we start recording at the point that the tag is moved
// near the reader.
//-----------------------------------------------------------------------------
-void RAMFUNC SnoopIso14443a(void)
-{
-// #define RECV_CMD_OFFSET 2032 // original (working as of 21/2/09) values
-// #define RECV_RES_OFFSET 2096 // original (working as of 21/2/09) values
-// #define DMA_BUFFER_OFFSET 2160 // original (working as of 21/2/09) values
-// #define DMA_BUFFER_SIZE 4096 // original (working as of 21/2/09) values
-// #define TRACE_LENGTH 2000 // original (working as of 21/2/09) values
-
- // 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
- // response from the tag.
- int triggered = FALSE; // FALSE to wait first for card
-
- // The command (reader -> tag) that we're receiving.
+void RAMFUNC SnoopIso14443a(uint8_t param) {
+ // param:
+ // bit 0 - trigger from first card answer
+ // bit 1 - trigger from first reader 7-bit request
+
+ LEDsoff();
+ // init trace buffer
+ iso14a_clear_trace();
+
+ // 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
+ // response from the tag.
+ // triggered == FALSE -- to wait first for card
+ int triggered = !(param & 0x03);
+
+ // The command (reader -> tag) that we're receiving.
// The length of a received command will in most cases be no more than 18 bytes.
// So 32 should be enough!
- uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
- // The response (tag -> reader) that we're receiving.
- uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET);
+ uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
+ // The response (tag -> reader) that we're receiving.
+ uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET);
- // As we receive stuff, we copy it from receivedCmd or receivedResponse
- // into trace, along with its length and other annotations.
- //uint8_t *trace = (uint8_t *)BigBuf;
-
- traceLen = 0; // uncommented to fix ISSUE 15 - gerhard - jan2011
-
- // The DMA buffer, used to stream samples from the FPGA
- int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET;
- int lastRxCounter;
- int8_t *upTo;
- int smpl;
- int maxBehindBy = 0;
-
- // Count of samples received so far, so that we can include timing
- // information in the trace buffer.
- int samples = 0;
- int rsamples = 0;
-
- memset(trace, 0x44, RECV_CMD_OFFSET);
-
- // Set up the demodulator for tag -> reader responses.
- Demod.output = receivedResponse;
- Demod.len = 0;
- Demod.state = DEMOD_UNSYNCD;
-
- // Setup for the DMA.
- FpgaSetupSsc();
- upTo = dmaBuf;
- lastRxCounter = DMA_BUFFER_SIZE;
- FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
-
- // And the reader -> tag commands
- memset(&Uart, 0, sizeof(Uart));
- Uart.output = receivedCmd;
- Uart.byteCntMax = 32; // was 100 (greg)////////////////////////////////////////////////////////////////////////
- Uart.state = STATE_UNSYNCD;
+ // As we receive stuff, we copy it from receivedCmd or receivedResponse
+ // into trace, along with its length and other annotations.
+ //uint8_t *trace = (uint8_t *)BigBuf;
+
+ // The DMA buffer, used to stream samples from the FPGA
+ int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET;
+ int8_t *data = dmaBuf;
+ int maxDataLen = 0;
+ int dataLen = 0;
- // And put the FPGA in the appropriate mode
- // Signal field is off with the appropriate LED
- LED_D_OFF();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER);
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+ // Set up the demodulator for tag -> reader responses.
+ Demod.output = receivedResponse;
+ Demod.len = 0;
+ Demod.state = DEMOD_UNSYNCD;
+ // Set up the demodulator for the reader -> tag commands
+ memset(&Uart, 0, sizeof(Uart));
+ Uart.output = receivedCmd;
+ Uart.byteCntMax = 32; // was 100 (greg)//////////////////
+ Uart.state = STATE_UNSYNCD;
- // And now we loop, receiving samples.
- for(;;) {
- LED_A_ON();
- WDT_HIT();
- int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
- (DMA_BUFFER_SIZE-1);
- if(behindBy > maxBehindBy) {
- maxBehindBy = behindBy;
- if(behindBy > 400) {
- Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
- goto done;
- }
- }
- if(behindBy < 1) continue;
+ // Setup for the DMA.
+ FpgaSetupSsc();
+ FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
- LED_A_OFF();
- smpl = upTo[0];
- upTo++;
- lastRxCounter -= 1;
- if(upTo - dmaBuf > DMA_BUFFER_SIZE) {
- upTo -= DMA_BUFFER_SIZE;
- lastRxCounter += DMA_BUFFER_SIZE;
- AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
- AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
- }
+ // And put the FPGA in the appropriate mode
+ // Signal field is off with the appropriate LED
+ LED_D_OFF();
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER);
+ SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
- samples += 4;
- if(MillerDecoding((smpl & 0xF0) >> 4)) {
- rsamples = samples - Uart.samples;
- LED_C_ON();
- if(triggered) {
- trace[traceLen++] = ((rsamples >> 0) & 0xff);
- trace[traceLen++] = ((rsamples >> 8) & 0xff);
- trace[traceLen++] = ((rsamples >> 16) & 0xff);
- trace[traceLen++] = ((rsamples >> 24) & 0xff);
- trace[traceLen++] = ((Uart.parityBits >> 0) & 0xff);
- trace[traceLen++] = ((Uart.parityBits >> 8) & 0xff);
- trace[traceLen++] = ((Uart.parityBits >> 16) & 0xff);
- trace[traceLen++] = ((Uart.parityBits >> 24) & 0xff);
- trace[traceLen++] = Uart.byteCnt;
- memcpy(trace+traceLen, receivedCmd, Uart.byteCnt);
- traceLen += Uart.byteCnt;
- if(traceLen > TRACE_LENGTH) break;
- }
- /* And ready to receive another command. */
- Uart.state = STATE_UNSYNCD;
- /* And also reset the demod code, which might have been */
- /* false-triggered by the commands from the reader. */
- Demod.state = DEMOD_UNSYNCD;
- LED_B_OFF();
- }
+ // Count of samples received so far, so that we can include timing
+ // information in the trace buffer.
+ rsamples = 0;
+ // And now we loop, receiving samples.
+ while(true) {
+ if(BUTTON_PRESS()) {
+ DbpString("cancelled by button");
+ goto done;
+ }
- if(ManchesterDecoding(smpl & 0x0F)) {
- rsamples = samples - Demod.samples;
- LED_B_ON();
-
- // timestamp, as a count of samples
- trace[traceLen++] = ((rsamples >> 0) & 0xff);
- trace[traceLen++] = ((rsamples >> 8) & 0xff);
- trace[traceLen++] = ((rsamples >> 16) & 0xff);
- trace[traceLen++] = 0x80 | ((rsamples >> 24) & 0xff);
- trace[traceLen++] = ((Demod.parityBits >> 0) & 0xff);
- trace[traceLen++] = ((Demod.parityBits >> 8) & 0xff);
- trace[traceLen++] = ((Demod.parityBits >> 16) & 0xff);
- trace[traceLen++] = ((Demod.parityBits >> 24) & 0xff);
- // length
- trace[traceLen++] = Demod.len;
- memcpy(trace+traceLen, receivedResponse, Demod.len);
- traceLen += Demod.len;
- if(traceLen > TRACE_LENGTH) break;
-
- triggered = TRUE;
-
- // And ready to receive another response.
- memset(&Demod, 0, sizeof(Demod));
- Demod.output = receivedResponse;
- Demod.state = DEMOD_UNSYNCD;
- LED_C_OFF();
- }
+ LED_A_ON();
+ WDT_HIT();
- if(BUTTON_PRESS()) {
- DbpString("cancelled_a");
- goto done;
- }
- }
+ int register readBufDataP = data - dmaBuf;
+ int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
+ if (readBufDataP <= dmaBufDataP){
+ dataLen = dmaBufDataP - readBufDataP;
+ } else {
+ dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP + 1;
+ }
+ // test for length of buffer
+ if(dataLen > maxDataLen) {
+ maxDataLen = dataLen;
+ if(dataLen > 400) {
+ Dbprintf("blew circular buffer! dataLen=0x%x", dataLen);
+ goto done;
+ }
+ }
+ if(dataLen < 1) continue;
+
+ // primary buffer was stopped( <-- we lost data!
+ if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
+ AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf;
+ AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
+ }
+ // secondary buffer sets as primary, secondary buffer was stopped
+ if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
+ AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
+ AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
+ }
+
+ LED_A_OFF();
+
+ rsamples += 4;
+ if(MillerDecoding((data[0] & 0xF0) >> 4)) {
+ LED_C_ON();
+
+ // check - if there is a short 7bit request from reader
+ if ((!triggered) && (param & 0x02) && (Uart.byteCnt == 1) && (Uart.bitCnt = 9)) triggered = TRUE;
+
+ if(triggered) {
+ if (!LogTrace(receivedCmd, Uart.byteCnt, 0 - Uart.samples, Uart.parityBits, TRUE)) break;
+ }
+ /* And ready to receive another command. */
+ Uart.state = STATE_UNSYNCD;
+ /* And also reset the demod code, which might have been */
+ /* false-triggered by the commands from the reader. */
+ Demod.state = DEMOD_UNSYNCD;
+ LED_B_OFF();
+ }
+
+ if(ManchesterDecoding(data[0] & 0x0F)) {
+ LED_B_ON();
+
+ if (!LogTrace(receivedResponse, Demod.len, 0 - Demod.samples, Demod.parityBits, FALSE)) break;
+
+ if ((!triggered) && (param & 0x01)) triggered = TRUE;
+
+ // And ready to receive another response.
+ memset(&Demod, 0, sizeof(Demod));
+ Demod.output = receivedResponse;
+ Demod.state = DEMOD_UNSYNCD;
+ LED_C_OFF();
+ }
- DbpString("COMMAND FINISHED");
+ data++;
+ if(data > dmaBuf + DMA_BUFFER_SIZE) {
+ data = dmaBuf;
+ }
+ } // main cycle
- Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt);
- Dbprintf("%x %x %x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);
+ DbpString("COMMAND FINISHED");
done:
- AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
- Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt);
- Dbprintf("%x %x %x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);
- LED_A_OFF();
- LED_B_OFF();
- LED_C_OFF();
- LED_D_OFF();
+ AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
+ Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.byteCnt=%x", maxDataLen, Uart.state, Uart.byteCnt);
+ Dbprintf("Uart.byteCntMax=%x, traceLen=%x, Uart.output[0]=%08x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);
+ LEDsoff();
}
//-----------------------------------------------------------------------------
// Main loop of simulated tag: receive commands from reader, decide what
// response to send, and send it.
//-----------------------------------------------------------------------------
-void SimulateIso14443aTag(int tagType, int TagUid)
+void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd)
{
- // This function contains the tag emulation
-
- // Prepare protocol messages
- // static const uint8_t cmd1[] = { 0x26 };
-// static const uint8_t response1[] = { 0x02, 0x00 }; // Says: I am Mifare 4k - original line - greg
-//
- static const uint8_t response1[] = { 0x44, 0x03 }; // Says: I am a DESFire Tag, ph33r me
-// static const uint8_t response1[] = { 0x44, 0x00 }; // Says: I am a ULTRALITE Tag, 0wn me
-
- // UID response
- // static const uint8_t cmd2[] = { 0x93, 0x20 };
- //static const uint8_t response2[] = { 0x9a, 0xe5, 0xe4, 0x43, 0xd8 }; // original value - greg
+ // Enable and clear the trace
+ tracing = TRUE;
+ iso14a_clear_trace();
-// my desfire
- static const uint8_t response2[] = { 0x88, 0x04, 0x21, 0x3f, 0x4d }; // known uid - note cascade (0x88), 2nd byte (0x04) = NXP/Phillips
+ // This function contains the tag emulation
+ uint8_t sak;
+ // The first response contains the ATQA (note: bytes are transmitted in reverse order).
+ uint8_t response1[2];
+
+ switch (tagType) {
+ case 1: { // MIFARE Classic
+ // Says: I am Mifare 1k - original line
+ response1[0] = 0x04;
+ response1[1] = 0x00;
+ sak = 0x08;
+ } break;
+ case 2: { // MIFARE Ultralight
+ // Says: I am a stupid memory tag, no crypto
+ response1[0] = 0x04;
+ response1[1] = 0x00;
+ sak = 0x00;
+ } break;
+ case 3: { // MIFARE DESFire
+ // Says: I am a DESFire tag, ph33r me
+ response1[0] = 0x04;
+ response1[1] = 0x03;
+ sak = 0x20;
+ } break;
+ case 4: { // ISO/IEC 14443-4
+ // Says: I am a javacard (JCOP)
+ response1[0] = 0x04;
+ response1[1] = 0x00;
+ sak = 0x28;
+ } break;
+ default: {
+ Dbprintf("Error: unkown tagtype (%d)",tagType);
+ return;
+ } break;
+ }
+
+ // The second response contains the (mandatory) first 24 bits of the UID
+ uint8_t response2[5];
+
+ // Check if the uid uses the (optional) part
+ uint8_t response2a[5];
+ if (uid_2nd) {
+ response2[0] = 0x88;
+ num_to_bytes(uid_1st,3,response2+1);
+ num_to_bytes(uid_2nd,4,response2a);
+ response2a[4] = response2a[0] ^ response2a[1] ^ response2a[2] ^ response2a[3];
+
+ // Configure the ATQA and SAK accordingly
+ response1[0] |= 0x40;
+ sak |= 0x04;
+ } else {
+ num_to_bytes(uid_1st,4,response2);
+ // Configure the ATQA and SAK accordingly
+ response1[0] &= 0xBF;
+ sak &= 0xFB;
+ }
-// When reader selects us during cascade1 it will send cmd3
-//uint8_t response3[] = { 0x04, 0x00, 0x00 }; // SAK Select (cascade1) successful response (ULTRALITE)
-uint8_t response3[] = { 0x24, 0x00, 0x00 }; // SAK Select (cascade1) successful response (DESFire)
-ComputeCrc14443(CRC_14443_A, response3, 1, &response3[1], &response3[2]);
+ // Calculate the BitCountCheck (BCC) for the first 4 bytes of the UID.
+ response2[4] = response2[0] ^ response2[1] ^ response2[2] ^ response2[3];
-// send cascade2 2nd half of UID
-static const uint8_t response2a[] = { 0x51, 0x48, 0x1d, 0x80, 0x84 }; // uid - cascade2 - 2nd half (4 bytes) of UID+ BCCheck
-// NOTE : THE CRC on the above may be wrong as I have obfuscated the actual UID
+ // Prepare the mandatory SAK (for 4 and 7 byte UID)
+ uint8_t response3[3];
+ response3[0] = sak;
+ ComputeCrc14443(CRC_14443_A, response3, 1, &response3[1], &response3[2]);
-// When reader selects us during cascade2 it will send cmd3a
-//uint8_t response3a[] = { 0x00, 0x00, 0x00 }; // SAK Select (cascade2) successful response (ULTRALITE)
-uint8_t response3a[] = { 0x20, 0x00, 0x00 }; // SAK Select (cascade2) successful response (DESFire)
-ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
+ // Prepare the optional second SAK (for 7 byte UID), drop the cascade bit
+ uint8_t response3a[3];
+ response3a[0] = sak & 0xFB;
+ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
- static const uint8_t response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce
+ uint8_t response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce
+ uint8_t response6[] = { 0x03, 0x3B, 0x00, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS
+ ComputeCrc14443(CRC_14443_A, response6, 3, &response6[3], &response6[4]);
- uint8_t *resp;
- int respLen;
+ uint8_t *resp;
+ int respLen;
- // Longest possible response will be 16 bytes + 2 CRC = 18 bytes
+ // Longest possible response will be 16 bytes + 2 CRC = 18 bytes
// This will need
// 144 data bits (18 * 8)
// 18 parity bits
// 166 bytes, since every bit that needs to be send costs us a byte
//
- // Respond with card type
- uint8_t *resp1 = (((uint8_t *)BigBuf) + 800);
- int resp1Len;
+ // Respond with card type
+ uint8_t *resp1 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
+ int resp1Len;
- // Anticollision cascade1 - respond with uid
- uint8_t *resp2 = (((uint8_t *)BigBuf) + 970);
- int resp2Len;
+ // Anticollision cascade1 - respond with uid
+ uint8_t *resp2 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 166);
+ int resp2Len;
- // Anticollision cascade2 - respond with 2nd half of uid if asked
- // we're only going to be asked if we set the 1st byte of the UID (during cascade1) to 0x88
- uint8_t *resp2a = (((uint8_t *)BigBuf) + 1140);
- int resp2aLen;
+ // Anticollision cascade2 - respond with 2nd half of uid if asked
+ // we're only going to be asked if we set the 1st byte of the UID (during cascade1) to 0x88
+ uint8_t *resp2a = (((uint8_t *)BigBuf) + 1140);
+ int resp2aLen;
- // Acknowledge select - cascade 1
- uint8_t *resp3 = (((uint8_t *)BigBuf) + 1310);
- int resp3Len;
+ // Acknowledge select - cascade 1
+ uint8_t *resp3 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + (166*2));
+ int resp3Len;
- // Acknowledge select - cascade 2
- uint8_t *resp3a = (((uint8_t *)BigBuf) + 1480);
- int resp3aLen;
+ // Acknowledge select - cascade 2
+ uint8_t *resp3a = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + (166*3));
+ int resp3aLen;
- // Response to a read request - not implemented atm
- uint8_t *resp4 = (((uint8_t *)BigBuf) + 1550);
- int resp4Len;
+ // Response to a read request - not implemented atm
+ uint8_t *resp4 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + (166*4));
+ int resp4Len;
- // Authenticate response - nonce
- uint8_t *resp5 = (((uint8_t *)BigBuf) + 1720);
- int resp5Len;
+ // Authenticate response - nonce
+ uint8_t *resp5 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + (166*5));
+ int resp5Len;
- uint8_t *receivedCmd = (uint8_t *)BigBuf;
- int len;
+ // Authenticate response - nonce
+ uint8_t *resp6 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + (166*6));
+ int resp6Len;
- int i;
- int u;
- uint8_t b;
+ uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
+ int len;
// To control where we are in the protocol
int order = 0;
int happened = 0;
int happened2 = 0;
- int cmdsRecvd = 0;
-
- int fdt_indicator;
+ int cmdsRecvd = 0;
+ uint8_t* respdata = NULL;
+ int respsize = 0;
+ uint8_t nack = 0x04;
- memset(receivedCmd, 0x44, 400);
+ memset(receivedCmd, 0x44, RECV_CMD_SIZE);
// Prepare the responses of the anticollision phase
// there will be not enough time to do this at the moment the reader sends it REQA
// Answer to request
CodeIso14443aAsTag(response1, sizeof(response1));
- memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;
+ memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;
// Send our UID (cascade 1)
CodeIso14443aAsTag(response2, sizeof(response2));
- memcpy(resp2, ToSend, ToSendMax); resp2Len = ToSendMax;
+ memcpy(resp2, ToSend, ToSendMax); resp2Len = ToSendMax;
// Answer to select (cascade1)
CodeIso14443aAsTag(response3, sizeof(response3));
- memcpy(resp3, ToSend, ToSendMax); resp3Len = ToSendMax;
+ memcpy(resp3, ToSend, ToSendMax); resp3Len = ToSendMax;
// Send the cascade 2 2nd part of the uid
CodeIso14443aAsTag(response2a, sizeof(response2a));
- memcpy(resp2a, ToSend, ToSendMax); resp2aLen = ToSendMax;
+ memcpy(resp2a, ToSend, ToSendMax); resp2aLen = ToSendMax;
// Answer to select (cascade 2)
CodeIso14443aAsTag(response3a, sizeof(response3a));
- memcpy(resp3a, ToSend, ToSendMax); resp3aLen = ToSendMax;
+ memcpy(resp3a, ToSend, ToSendMax); resp3aLen = ToSendMax;
// Strange answer is an example of rare message size (3 bits)
CodeStrangeAnswerAsTag();
// Authentication answer (random nonce)
CodeIso14443aAsTag(response5, sizeof(response5));
- memcpy(resp5, ToSend, ToSendMax); resp5Len = ToSendMax;
+ memcpy(resp5, ToSend, ToSendMax); resp5Len = ToSendMax;
- // We need to listen to the high-frequency, peak-detected path.
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
- FpgaSetupSsc();
+ // dummy ATS (pseudo-ATR), answer to RATS
+ CodeIso14443aAsTag(response6, sizeof(response6));
+ memcpy(resp6, ToSend, ToSendMax); resp6Len = ToSendMax;
- cmdsRecvd = 0;
+ // We need to listen to the high-frequency, peak-detected path.
+ SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+ FpgaSetupSsc();
- LED_A_ON();
- for(;;) {
+ cmdsRecvd = 0;
- if(!GetIso14443aCommandFromReader(receivedCmd, &len, 100)) {
- DbpString("button press");
- break;
- }
- // doob - added loads of debug strings so we can see what the reader is saying to us during the sim as hi14alist is not populated
- // Okay, look at the command now.
- lastorder = order;
- i = 1; // first byte transmitted
- if(receivedCmd[0] == 0x26) {
- // Received a REQUEST
+ LED_A_ON();
+ for(;;) {
+
+ if(!GetIso14443aCommandFromReader(receivedCmd, &len, RECV_CMD_SIZE)) {
+ DbpString("button press");
+ break;
+ }
+ // doob - added loads of debug strings so we can see what the reader is saying to us during the sim as hi14alist is not populated
+ // Okay, look at the command now.
+ lastorder = order;
+ if(receivedCmd[0] == 0x26) { // Received a REQUEST
resp = resp1; respLen = resp1Len; order = 1;
- //DbpString("Hello request from reader:");
- } else if(receivedCmd[0] == 0x52) {
- // Received a WAKEUP
+ respdata = response1;
+ respsize = sizeof(response1);
+ } else if(receivedCmd[0] == 0x52) { // Received a WAKEUP
resp = resp1; respLen = resp1Len; order = 6;
-// //DbpString("Wakeup request from reader:");
-
- } else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x93) { // greg - cascade 1 anti-collision
- // Received request for UID (cascade 1)
+ respdata = response1;
+ respsize = sizeof(response1);
+ } else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x93) { // Received request for UID (cascade 1)
resp = resp2; respLen = resp2Len; order = 2;
-// DbpString("UID (cascade 1) request from reader:");
-// DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);
-
-
- } else if(receivedCmd[1] == 0x20 && receivedCmd[0] ==0x95) { // greg - cascade 2 anti-collision
- // Received request for UID (cascade 2)
+ respdata = response2;
+ respsize = sizeof(response2);
+ } else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x95) { // Received request for UID (cascade 2)
resp = resp2a; respLen = resp2aLen; order = 20;
-// DbpString("UID (cascade 2) request from reader:");
-// DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);
-
-
- } else if(receivedCmd[1] == 0x70 && receivedCmd[0] ==0x93) { // greg - cascade 1 select
- // Received a SELECT
+ respdata = response2a;
+ respsize = sizeof(response2a);
+ } else if(receivedCmd[1] == 0x70 && receivedCmd[0] == 0x93) { // Received a SELECT (cascade 1)
resp = resp3; respLen = resp3Len; order = 3;
-// DbpString("Select (cascade 1) request from reader:");
-// DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);
-
-
- } else if(receivedCmd[1] == 0x70 && receivedCmd[0] ==0x95) { // greg - cascade 2 select
- // Received a SELECT
+ respdata = response3;
+ respsize = sizeof(response3);
+ } else if(receivedCmd[1] == 0x70 && receivedCmd[0] == 0x95) { // Received a SELECT (cascade 2)
resp = resp3a; respLen = resp3aLen; order = 30;
-// DbpString("Select (cascade 2) request from reader:");
-// DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);
-
-
- } else if(receivedCmd[0] == 0x30) {
- // Received a READ
+ respdata = response3a;
+ respsize = sizeof(response3a);
+ } else if(receivedCmd[0] == 0x30) { // Received a (plain) READ
resp = resp4; respLen = resp4Len; order = 4; // Do nothing
- Dbprintf("Read request from reader: %x %x %x",
- receivedCmd[0], receivedCmd[1], receivedCmd[2]);
-
-
- } else if(receivedCmd[0] == 0x50) {
- // Received a HALT
- resp = resp1; respLen = 0; order = 5; // Do nothing
- DbpString("Reader requested we HALT!:");
-
- } else if(receivedCmd[0] == 0x60) {
- // Received an authentication request
- resp = resp5; respLen = resp5Len; order = 7;
- Dbprintf("Authenticate request from reader: %x %x %x",
- receivedCmd[0], receivedCmd[1], receivedCmd[2]);
-
- } else if(receivedCmd[0] == 0xE0) {
- // Received a RATS request
- resp = resp1; respLen = 0;order = 70;
- Dbprintf("RATS request from reader: %x %x %x",
- receivedCmd[0], receivedCmd[1], receivedCmd[2]);
- } 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[0], receivedCmd[1], receivedCmd[2],
- receivedCmd[3], receivedCmd[4], receivedCmd[5],
- receivedCmd[6], receivedCmd[7], receivedCmd[8]);
+ Dbprintf("Read request from reader: %x %x",receivedCmd[0],receivedCmd[1]);
+ respdata = &nack;
+ respsize = sizeof(nack); // 4-bit answer
+ } else if(receivedCmd[0] == 0x50) { // Received a HALT
+// DbpString("Reader requested we HALT!:");
// Do not respond
resp = resp1; respLen = 0; order = 0;
- }
+ respdata = NULL;
+ respsize = 0;
+ } else if(receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61) { // Received an authentication request
+ resp = resp5; respLen = resp5Len; order = 7;
+ respdata = response5;
+ respsize = sizeof(response5);
+ } else if(receivedCmd[0] == 0xE0) { // Received a RATS request
+ resp = resp6; respLen = resp6Len; order = 70;
+ respdata = response6;
+ respsize = sizeof(response6);
+ } else {
+ if (order == 7 && len ==8) {
+ uint32_t nr = bytes_to_num(receivedCmd,4);
+ uint32_t ar = bytes_to_num(receivedCmd+4,4);
+ Dbprintf("Auth attempt {nr}{ar}: %08x %08x",nr,ar);
+ } else {
+ // Never seen this command before
+ Dbprintf("Received unknown command (len=%d):",len);
+ Dbhexdump(len,receivedCmd,false);
+ }
+ // Do not respond
+ resp = resp1; respLen = 0; order = 0;
+ respdata = NULL;
+ respsize = 0;
+ }
// Count number of wakeups received after a halt
if(order == 6 && lastorder == 5) { happened++; }
// Look at last parity bit to determine timing of answer
if((Uart.parityBits & 0x01) || receivedCmd[0] == 0x52) {
// 1236, so correction bit needed
- i = 0;
+ //i = 0;
}
- memset(receivedCmd, 0x44, 32);
-
if(cmdsRecvd > 999) {
DbpString("1000 commands later...");
- break;
- }
- else {
+ break;
+ } else {
cmdsRecvd++;
}
- if(respLen <= 0) continue;
- //----------------------------
- u = 0;
- b = 0x00;
- fdt_indicator = FALSE;
-
- EmSendCmd14443aRaw(resp, respLen, receivedCmd[0] == 0x52);
-/* // Modulate Manchester
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD);
- AT91C_BASE_SSC->SSC_THR = 0x00;
- FpgaSetupSsc();
-
- // ### Transmit the response ###
- u = 0;
- b = 0x00;
- fdt_indicator = FALSE;
- for(;;) {
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- volatile uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- (void)b;
- }
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- if(i > respLen) {
- b = 0x00;
- u++;
- } else {
- b = resp[i];
- i++;
- }
- AT91C_BASE_SSC->SSC_THR = b;
-
- if(u > 4) {
- break;
- }
- }
- if(BUTTON_PRESS()) {
- break;
+ if(respLen > 0) {
+ EmSendCmd14443aRaw(resp, respLen, receivedCmd[0] == 0x52);
+ }
+
+ if (tracing) {
+ LogTrace(receivedCmd,len, 0, Uart.parityBits, TRUE);
+ if (respdata != NULL) {
+ LogTrace(respdata,respsize, 0, SwapBits(GetParity(respdata,respsize),respsize), FALSE);
}
- }
-*/
- }
+ if(traceLen > TRACE_SIZE) {
+ DbpString("Trace full");
+ break;
+ }
+ }
+
+ memset(receivedCmd, 0x44, RECV_CMD_SIZE);
+ }
Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
LED_A_OFF();
/* performs iso14443a anticolision procedure
* fills the uid pointer unless NULL
* fills resp_data unless NULL */
-int iso14443a_select_card(uint8_t * uid_ptr, iso14a_card_select_t * resp_data, uint32_t * cuid_ptr) {
+int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, uint32_t* cuid_ptr) {
uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP
uint8_t sel_all[] = { 0x93,0x20 };
uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0
-
- uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes
+ uint8_t* resp = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET); // was 3560 - tied to other size changes
+ byte_t uid_resp[4];
+ size_t uid_resp_len;
uint8_t sak = 0x04; // cascade uid
int cascade_level = 0;
-
int len;
-
- // clear uid
- memset(uid_ptr, 0, 8);
-
+
// Broadcast for a card, WUPA (0x52) will force response from all cards in the field
ReaderTransmitShort(wupa);
// Receive the ATQA
if(!ReaderReceive(resp)) return 0;
-
- if(resp_data)
- memcpy(resp_data->atqa, resp, 2);
+// Dbprintf("atqa: %02x %02x",resp[0],resp[1]);
+
+ if(p_hi14a_card) {
+ memcpy(p_hi14a_card->atqa, resp, 2);
+ p_hi14a_card->uidlen = 0;
+ memset(p_hi14a_card->uid,0,10);
+ }
+ // clear uid
+ if (uid_ptr) {
+ memset(uid_ptr,0,10);
+ }
+
// OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
// which case we need to make a cascade 2 request and select - this is a long UID
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
// SELECT_ALL
ReaderTransmit(sel_all,sizeof(sel_all));
if (!ReaderReceive(resp)) return 0;
- if(uid_ptr) memcpy(uid_ptr + cascade_level*4, resp, 4);
-
+
+ // First backup the current uid
+ memcpy(uid_resp,resp,4);
+ uid_resp_len = 4;
+ // Dbprintf("uid: %02x %02x %02x %02x",uid_resp[0],uid_resp[1],uid_resp[2],uid_resp[3]);
+
// calculate crypto UID
- if(cuid_ptr) *cuid_ptr = bytes_to_num(resp, 4);
+ if(cuid_ptr) {
+ *cuid_ptr = bytes_to_num(uid_resp, 4);
+ }
// Construct SELECT UID command
memcpy(sel_uid+2,resp,5);
// Receive the SAK
if (!ReaderReceive(resp)) return 0;
sak = resp[0];
+
+ // Test if more parts of the uid are comming
+ if ((sak & 0x04) && uid_resp[0] == 0x88) {
+ // Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
+ // http://www.nxp.com/documents/application_note/AN10927.pdf
+ memcpy(uid_ptr, uid_ptr + 1, 3);
+ uid_resp_len = 3;
+ }
+
+ if(uid_ptr) {
+ memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len);
+ }
+
+ if(p_hi14a_card) {
+ memcpy(p_hi14a_card->uid + (cascade_level*3), uid_resp, uid_resp_len);
+ p_hi14a_card->uidlen += uid_resp_len;
+ }
}
- if(resp_data) {
- resp_data->sak = sak;
- resp_data->ats_len = 0;
- }
- //-- this byte not UID, it CT. http://www.nxp.com/documents/application_note/AN10927.pdf page 3
- if (uid_ptr[0] == 0x88) {
- memcpy(uid_ptr, uid_ptr + 1, 7);
- uid_ptr[7] = 0;
+
+ if(p_hi14a_card) {
+ p_hi14a_card->sak = sak;
+ p_hi14a_card->ats_len = 0;
}
- if( (sak & 0x20) == 0)
+ if( (sak & 0x20) == 0) {
return 2; // non iso14443a compliant tag
+ }
// Request for answer to select
- if(resp_data) { // JCOP cards - if reader sent RATS then there is no MIFARE session at all!!!
+ if(p_hi14a_card) { // JCOP cards - if reader sent RATS then there is no MIFARE session at all!!!
AppendCrc14443a(rats, 2);
ReaderTransmit(rats, sizeof(rats));
if (!(len = ReaderReceive(resp))) return 0;
- memcpy(resp_data->ats, resp, sizeof(resp_data->ats));
- resp_data->ats_len = len;
+ memcpy(p_hi14a_card->ats, resp, sizeof(p_hi14a_card->ats));
+ p_hi14a_card->ats_len = len;
}
+ // reset the PCB block number
+ iso14_pcb_blocknum = 0;
return 1;
}
void iso14443a_setup() {
- // Setup SSC
- FpgaSetupSsc();
+ // Set up the synchronous serial port
+ 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);
+ SpinDelay(50);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
// Signal field is on with the appropriate LED
LED_D_ON();
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
- SpinDelay(200);
+ SpinDelay(50);
iso14a_timeout = 2048; //default
}
int iso14_apdu(uint8_t * cmd, size_t cmd_len, void * data) {
uint8_t real_cmd[cmd_len+4];
real_cmd[0] = 0x0a; //I-Block
+ // put block number into the PCB
+ real_cmd[0] |= iso14_pcb_blocknum;
real_cmd[1] = 0x00; //CID: 0 //FIXME: allow multiple selected cards
memcpy(real_cmd+2, cmd, cmd_len);
AppendCrc14443a(real_cmd,cmd_len+2);
ReaderTransmit(real_cmd, cmd_len+4);
size_t len = ReaderReceive(data);
- if(!len)
- return -1; //DATA LINK ERROR
-
+ uint8_t * data_bytes = (uint8_t *) data;
+ if (!len)
+ return 0; //DATA LINK ERROR
+ // if we received an I- or R(ACK)-Block with a block number equal to the
+ // current block number, toggle the current block number
+ else if (len >= 4 // PCB+CID+CRC = 4 bytes
+ && ((data_bytes[0] & 0xC0) == 0 // I-Block
+ || (data_bytes[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
+ && (data_bytes[0] & 0x01) == iso14_pcb_blocknum) // equal block numbers
+ {
+ iso14_pcb_blocknum ^= 1;
+ }
+
return len;
}
-
//-----------------------------------------------------------------------------
// Read an ISO 14443a tag. Send out commands and store answers.
//
//-----------------------------------------------------------------------------
-void ReaderIso14443a(UsbCommand * c, UsbCommand * ack)
+void ReaderIso14443a(UsbCommand * c)
{
iso14a_command_t param = c->arg[0];
uint8_t * cmd = c->d.asBytes;
size_t len = c->arg[1];
-
- if(param & ISO14A_REQUEST_TRIGGER) iso14a_set_trigger(1);
+ uint32_t arg0 = 0;
+ byte_t buf[USB_CMD_DATA_SIZE];
+
+ iso14a_clear_trace();
+ iso14a_set_tracing(true);
+
+ if(param & ISO14A_REQUEST_TRIGGER) {
+ iso14a_set_trigger(1);
+ }
if(param & ISO14A_CONNECT) {
iso14443a_setup();
- ack->arg[0] = iso14443a_select_card(ack->d.asBytes, (iso14a_card_select_t *) (ack->d.asBytes+12), NULL);
- UsbSendPacket((void *)ack, sizeof(UsbCommand));
+ arg0 = iso14443a_select_card(NULL,(iso14a_card_select_t*)buf,NULL);
+ cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(iso14a_card_select_t));
+// UsbSendPacket((void *)ack, sizeof(UsbCommand));
}
if(param & ISO14A_SET_TIMEOUT) {
}
if(param & ISO14A_APDU) {
- ack->arg[0] = iso14_apdu(cmd, len, ack->d.asBytes);
- UsbSendPacket((void *)ack, sizeof(UsbCommand));
+ arg0 = iso14_apdu(cmd, len, buf);
+ cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf));
+// UsbSendPacket((void *)ack, sizeof(UsbCommand));
}
if(param & ISO14A_RAW) {
len += 2;
}
ReaderTransmit(cmd,len);
- ack->arg[0] = ReaderReceive(ack->d.asBytes);
- UsbSendPacket((void *)ack, sizeof(UsbCommand));
+ arg0 = ReaderReceive(buf);
+// UsbSendPacket((void *)ack, sizeof(UsbCommand));
+ cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf));
}
- if(param & ISO14A_REQUEST_TRIGGER) iso14a_set_trigger(0);
+ if(param & ISO14A_REQUEST_TRIGGER) {
+ iso14a_set_trigger(0);
+ }
- if(param & ISO14A_NO_DISCONNECT)
+ if(param & ISO14A_NO_DISCONNECT) {
return;
+ }
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
+
//-----------------------------------------------------------------------------
// Read an ISO 14443a tag. Send out commands and store answers.
//
uint8_t mf_auth[] = { 0x60,0x00,0xf5,0x7b };
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
- uint8_t* receivedAnswer = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes
+ uint8_t* receivedAnswer = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET); // was 3560 - tied to other size changes
traceLen = 0;
tracing = false;
byte_t nt_diff = 0;
LED_A_OFF();
byte_t par = 0;
- byte_t par_mask = 0xff;
+ //byte_t par_mask = 0xff;
byte_t par_low = 0;
int led_on = TRUE;
uint8_t uid[8];
while(TRUE)
{
- LED_C_ON();
+ LED_C_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- SpinDelay(200);
+ SpinDelay(50);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
- LED_C_OFF();
+ LED_C_ON();
+ SpinDelay(2);
// Test if the action was cancelled
if(BUTTON_PRESS()) {
{
if ( (parameter != 0) && (memcmp(nt, nt_noattack, 4) == 0) ) continue;
- isNULL = (nt_attacked[0] == 0) && (nt_attacked[1] == 0) && (nt_attacked[2] == 0) && (nt_attacked[3] == 0);
+ isNULL = !(nt_attacked[0] == 0) && (nt_attacked[1] == 0) && (nt_attacked[2] == 0) && (nt_attacked[3] == 0);
if ( (isNULL != 0 ) && (memcmp(nt, nt_attacked, 4) != 0) ) continue;
if (nt_diff == 0)
{
LED_A_ON();
memcpy(nt_attacked, nt, 4);
- par_mask = 0xf8;
+ //par_mask = 0xf8;
par_low = par & 0x07;
}
LogTrace(par_list, 8, 0, GetParity(par_list, 8), TRUE);
LogTrace(ks_list, 8, 0, GetParity(ks_list, 8), TRUE);
- UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};
- memcpy(ack.d.asBytes + 0, uid, 4);
- memcpy(ack.d.asBytes + 4, nt, 4);
- memcpy(ack.d.asBytes + 8, par_list, 8);
- memcpy(ack.d.asBytes + 16, ks_list, 8);
+ byte_t buf[48];
+// UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};
+ memcpy(buf + 0, uid, 4);
+ memcpy(buf + 4, nt, 4);
+ memcpy(buf + 8, par_list, 8);
+ memcpy(buf + 16, ks_list, 8);
LED_B_ON();
- UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));
+ cmd_send(CMD_ACK,isOK,0,0,buf,48);
+// UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));
LED_B_OFF();
// Thats it...
int cardSTATE = MFEMUL_NOFIELD;
int _7BUID = 0;
int vHf = 0; // in mV
- int nextCycleTimeout = 0;
+ //int nextCycleTimeout = 0;
int res;
// uint32_t timer = 0;
uint32_t selTimer = 0;
uint8_t cardWRBL = 0;
uint8_t cardAUTHSC = 0;
uint8_t cardAUTHKEY = 0xff; // no authentication
- uint32_t cardRn = 0;
+ //uint32_t cardRn = 0;
uint32_t cardRr = 0;
uint32_t cuid = 0;
- uint32_t rn_enc = 0;
+ //uint32_t rn_enc = 0;
uint32_t ans = 0;
uint32_t cardINTREG = 0;
uint8_t cardINTBLOCK = 0;
}
if (cardSTATE != MFEMUL_NOFIELD) {
- res = EmGetCmd(receivedCmd, &len, 100); // (+ nextCycleTimeout)
+ res = EmGetCmd(receivedCmd, &len, RECV_CMD_SIZE); // (+ nextCycleTimeout)
if (res == 2) {
cardSTATE = MFEMUL_NOFIELD;
LEDsoff();
if(res) break;
}
- nextCycleTimeout = 0;
+ //nextCycleTimeout = 0;
// if (len) Dbprintf("len:%d cmd: %02x %02x %02x %02x", len, receivedCmd[0], receivedCmd[1], receivedCmd[2], receivedCmd[3]);
case MFEMUL_AUTH1:{
if (len == 8) {
// --- crypto
- rn_enc = bytes_to_num(receivedCmd, 4);
- cardRn = rn_enc ^ crypto1_word(pcs, rn_enc , 1);
+ //rn_enc = bytes_to_num(receivedCmd, 4);
+ //cardRn = rn_enc ^ crypto1_word(pcs, rn_enc , 1);
cardRr = bytes_to_num(&receivedCmd[4], 4) ^ crypto1_word(pcs, 0, 0);
// test if auth OK
if (cardRr != prng_successor(nonce, 64)){
// LogTrace(NULL, 0, GetDeltaCountUS(), 0, true);
cardSTATE = MFEMUL_AUTH1;
- nextCycleTimeout = 10;
+ //nextCycleTimeout = 10;
break;
}
} else {
// --- crypto
cardSTATE = MFEMUL_AUTH1;
- nextCycleTimeout = 10;
+ //nextCycleTimeout = 10;
break;
}
}
break;
}
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
- nextCycleTimeout = 50;
+ //nextCycleTimeout = 50;
cardSTATE = MFEMUL_WRITEBL2;
cardWRBL = receivedCmd[1];
break;
cardSTATE = MFEMUL_WORK;
break;
}
-
}
-
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
if (MF_DBGLEVEL >= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, traceLen);
}
+
+//-----------------------------------------------------------------------------
+// MIFARE sniffer.
+//
+//-----------------------------------------------------------------------------
+void RAMFUNC SniffMifare(uint8_t param) {
+ // param:
+ // bit 0 - trigger from first card answer
+ // bit 1 - trigger from first reader 7-bit request
+
+ // C(red) A(yellow) B(green)
+ LEDsoff();
+ // init trace buffer
+ iso14a_clear_trace();
+
+ // The command (reader -> tag) that we're receiving.
+ // The length of a received command will in most cases be no more than 18 bytes.
+ // So 32 should be enough!
+ uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
+ // The response (tag -> reader) that we're receiving.
+ uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET);
+
+ // As we receive stuff, we copy it from receivedCmd or receivedResponse
+ // into trace, along with its length and other annotations.
+ //uint8_t *trace = (uint8_t *)BigBuf;
+
+ // The DMA buffer, used to stream samples from the FPGA
+ int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET;
+ int8_t *data = dmaBuf;
+ int maxDataLen = 0;
+ int dataLen = 0;
+
+ // Set up the demodulator for tag -> reader responses.
+ Demod.output = receivedResponse;
+ Demod.len = 0;
+ Demod.state = DEMOD_UNSYNCD;
+
+ // Set up the demodulator for the reader -> tag commands
+ memset(&Uart, 0, sizeof(Uart));
+ Uart.output = receivedCmd;
+ Uart.byteCntMax = 32; // was 100 (greg)//////////////////
+ Uart.state = STATE_UNSYNCD;
+
+ // Setup for the DMA.
+ FpgaSetupSsc();
+ FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
+
+ // And put the FPGA in the appropriate mode
+ // Signal field is off with the appropriate LED
+ LED_D_OFF();
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER);
+ SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+
+ // init sniffer
+ MfSniffInit();
+ int sniffCounter = 0;
+
+ // And now we loop, receiving samples.
+ while(true) {
+ if(BUTTON_PRESS()) {
+ DbpString("cancelled by button");
+ goto done;
+ }
+
+ LED_A_ON();
+ WDT_HIT();
+
+ if (++sniffCounter > 65) {
+ if (MfSniffSend(2000)) {
+ FpgaEnableSscDma();
+ }
+ sniffCounter = 0;
+ }
+
+ int register readBufDataP = data - dmaBuf;
+ int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
+ if (readBufDataP <= dmaBufDataP){
+ dataLen = dmaBufDataP - readBufDataP;
+ } else {
+ dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP + 1;
+ }
+ // test for length of buffer
+ if(dataLen > maxDataLen) {
+ maxDataLen = dataLen;
+ if(dataLen > 400) {
+ Dbprintf("blew circular buffer! dataLen=0x%x", dataLen);
+ goto done;
+ }
+ }
+ if(dataLen < 1) continue;
+
+ // primary buffer was stopped( <-- we lost data!
+ if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
+ AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf;
+ AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
+ Dbprintf("RxEmpty ERROR!!! data length:%d", dataLen); // temporary
+ }
+ // secondary buffer sets as primary, secondary buffer was stopped
+ if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
+ AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
+ AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
+ }
+
+ LED_A_OFF();
+
+ if(MillerDecoding((data[0] & 0xF0) >> 4)) {
+ LED_C_INV();
+ // check - if there is a short 7bit request from reader
+ if (MfSniffLogic(receivedCmd, Uart.byteCnt, Uart.parityBits, Uart.bitCnt, TRUE)) break;
+
+ /* And ready to receive another command. */
+ Uart.state = STATE_UNSYNCD;
+
+ /* And also reset the demod code */
+ Demod.state = DEMOD_UNSYNCD;
+ }
+
+ if(ManchesterDecoding(data[0] & 0x0F)) {
+ LED_C_INV();
+
+ if (MfSniffLogic(receivedResponse, Demod.len, Demod.parityBits, Demod.bitCount, FALSE)) break;
+
+ // And ready to receive another response.
+ memset(&Demod, 0, sizeof(Demod));
+ Demod.output = receivedResponse;
+ Demod.state = DEMOD_UNSYNCD;
+
+ /* And also reset the uart code */
+ Uart.state = STATE_UNSYNCD;
+ }
+
+ data++;
+ if(data > dmaBuf + DMA_BUFFER_SIZE) {
+ data = dmaBuf;
+ }
+ } // main cycle
+
+ DbpString("COMMAND FINISHED");
+
+done:
+ FpgaDisableSscDma();
+ MfSniffEnd();
+
+ Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.byteCnt=%x Uart.byteCntMax=%x", maxDataLen, Uart.state, Uart.byteCnt, Uart.byteCntMax);
+ LEDsoff();
+}
\ No newline at end of file