From 81cd0474cb4dc85fcc78f70ad238cb684851f75f Mon Sep 17 00:00:00 2001 From: "roel@libnfc.org" Date: Fri, 29 Jun 2012 10:24:05 +0000 Subject: [PATCH] fixed a lot of simulation issues --- armsrc/appmain.c | 2 +- armsrc/apps.h | 16 +++- armsrc/iclass.c | 96 ++++++++++++---------- armsrc/iso14443.c | 36 ++++---- armsrc/iso14443a.c | 200 +++++++++++++++++++++++++++++++++++---------- armsrc/iso14443a.h | 6 -- armsrc/util.c | 9 ++ armsrc/util.h | 1 + client/cmdhf14a.c | 78 ++++++++++++++++-- client/util.c | 2 +- 10 files changed, 326 insertions(+), 120 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 362759a7..b107f594 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -706,7 +706,7 @@ void UsbPacketReceived(uint8_t *packet, int len) ReaderIso14443a(c, &ack); break; case CMD_SIMULATE_TAG_ISO_14443a: - SimulateIso14443aTag(c->arg[0], c->arg[1]); // ## Simulate iso14443a tag - pass tag type & UID + SimulateIso14443aTag(c->arg[0], c->arg[1], c->arg[2]); // ## Simulate iso14443a tag - pass tag type & UID break; case CMD_READER_MIFARE: diff --git a/armsrc/apps.h b/armsrc/apps.h index 1dd7134d..ebfa0bdd 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -18,7 +18,19 @@ typedef unsigned char byte_t; // The large multi-purpose buffer, typically used to hold A/D samples, // maybe processed in some way. -uint32_t BigBuf[8000]; +uint32_t BigBuf[10000]; +// BIG CHANGE - UNDERSTAND THIS BEFORE WE COMMIT +#define TRACE_OFFSET 0 +#define TRACE_SIZE 3000 +#define RECV_CMD_OFFSET 3032 +#define RECV_CMD_SIZE 64 +#define RECV_RES_OFFSET 3096 +#define RECV_RES_SIZE 64 +#define DMA_BUFFER_OFFSET 3160 +#define DMA_BUFFER_SIZE 4096 +#define FREE_BUFFER_OFFSET 7256 +#define FREE_BUFFER_SIZE 2744 + extern const uint8_t OddByteParity[256]; extern uint8_t *trace; // = (uint8_t *) BigBuf; extern int traceLen; // = 0; @@ -113,7 +125,7 @@ void RAMFUNC SnoopIso14443(void); /// iso14443a.h void RAMFUNC SnoopIso14443a(void); -void SimulateIso14443aTag(int tagType, int TagUid); // ## simulate iso14443a tag +void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd); // ## simulate iso14443a tag void ReaderIso14443a(UsbCommand * c, UsbCommand * ack); // Also used in iclass.c int LogTrace(const uint8_t * btBytes, int iLen, int iSamples, uint32_t dwParity, int bReader); diff --git a/armsrc/iclass.c b/armsrc/iclass.c index e4b1a488..6f81526b 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -60,22 +60,6 @@ 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); //----------------------------------------------------------------------------- @@ -687,7 +671,7 @@ void RAMFUNC SnoopIClass(void) // #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 @@ -816,7 +800,7 @@ void RAMFUNC SnoopIClass(void) 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; @@ -848,7 +832,7 @@ void RAMFUNC SnoopIClass(void) 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; @@ -1011,6 +995,11 @@ void SimulateIClass(uint8_t arg0, uint8_t *datain) { uint8_t simType = arg0; + // Enable and clear the trace + tracing = TRUE; + traceLen = 0; + memset(trace, 0x44, TRACE_SIZE); + // CSN followed by two CRC bytes uint8_t response2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t response3[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0, 0x00, 0x00 }; @@ -1037,31 +1026,34 @@ void SimulateIClass(uint8_t arg0, uint8_t *datain) // 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) + 800); + 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) + 810); + 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) + 990); + 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) + 1170); + uint8_t *resp4 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 370); int resp4Len; // + 1720.. - uint8_t *receivedCmd = (uint8_t *)BigBuf; - memset(receivedCmd, 0x44, 400); + uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET); + memset(receivedCmd, 0x44, RECV_CMD_SIZE); int len; // Prepare card messages @@ -1094,36 +1086,46 @@ void SimulateIClass(uint8_t arg0, uint8_t *datain) for(;;) { LED_B_OFF(); if(!GetIClassCommandFromReader(receivedCmd, &len, 100)) { - DbpString("button press"); + DbpString("button press"); break; - } + } - // Okay, look at the command now. - if(receivedCmd[0] == 0x0a) { + // Okay, look at the command now. + if(receivedCmd[0] == 0x0a) { // Reader in anticollission phase resp = resp1; respLen = resp1Len; //order = 1; + 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; + 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 = 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; + 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", 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], @@ -1133,15 +1135,14 @@ void SimulateIClass(uint8_t arg0, uint8_t *datain) // 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 if(receivedCmd[0] == 0x50) { - // Received a HALT - resp = resp1; respLen = 0; order = 5; // Do nothing - DbpString("Reader requested we HALT!:"); -*/ - } 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, @@ -1150,10 +1151,10 @@ void SimulateIClass(uint8_t arg0, uint8_t *datain) receivedCmd[6], receivedCmd[7], receivedCmd[8]); // Do not respond resp = resp1; respLen = 0; //order = 0; + respdata = NULL; + respsize = 0; } - memset(receivedCmd, 0x44, 32); - if(cmdsRecvd > 999) { DbpString("1000 commands later..."); break; @@ -1162,10 +1163,19 @@ void SimulateIClass(uint8_t arg0, uint8_t *datain) cmdsRecvd++; } - if(respLen <= 0) continue; + if(respLen > 0) { + SendIClassAnswer(resp, respLen, 21); + } + + if (tracing) { + LogTrace(receivedCmd,len, 0, Uart.parityBits, TRUE); + if (respdata != NULL) { + LogTrace(respdata,respsize, 0, SwapBits(GetParity(respdata,respsize),respsize), FALSE); + } + } - SendIClassAnswer(resp, respLen, 21); - } + memset(receivedCmd, 0x44, RECV_CMD_SIZE); + } Dbprintf("%x", cmdsRecvd); LED_A_OFF(); @@ -1428,7 +1438,7 @@ void ReaderIClass(uint8_t arg0) { LED_A_ON(); for(;;) { - if(traceLen > TRACE_LENGTH || BUTTON_PRESS()) break; + if(traceLen > TRACE_SIZE || BUTTON_PRESS()) break; // Send act_all ReaderTransmitIClass(act_all, 1); diff --git a/armsrc/iso14443.c b/armsrc/iso14443.c index b8104d87..9452ae83 100644 --- a/armsrc/iso14443.c +++ b/armsrc/iso14443.c @@ -22,7 +22,7 @@ #define DEMOD_TRACE_SIZE 4096 #define READER_TAG_BUFFER_SIZE 2048 #define TAG_READER_BUFFER_SIZE 2048 -#define DMA_BUFFER_SIZE 1024 +#define DEMOD_DMA_BUFFER_SIZE 1024 //============================================================================= // An ISO 14443 Type B tag. We listen for commands from the reader, using @@ -652,8 +652,8 @@ static void GetSamplesFor14443Demod(int weTx, int n, int quiet) // Setup for the DMA. dmaBuf = (int8_t *)(BigBuf + 32); upTo = dmaBuf; - lastRxCounter = DMA_BUFFER_SIZE; - FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); + lastRxCounter = DEMOD_DMA_BUFFER_SIZE; + FpgaSetupSscDma((uint8_t *)dmaBuf, DEMOD_DMA_BUFFER_SIZE); // Signal field is ON with the appropriate LED: if (weTx) LED_D_ON(); else LED_D_OFF(); @@ -666,20 +666,20 @@ static void GetSamplesFor14443Demod(int weTx, int n, int quiet) int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR; if(behindBy > max) max = behindBy; - while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (DMA_BUFFER_SIZE-1)) + while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (DEMOD_DMA_BUFFER_SIZE-1)) > 2) { ci = upTo[0]; cq = upTo[1]; upTo += 2; - if(upTo - dmaBuf > DMA_BUFFER_SIZE) { - upTo -= DMA_BUFFER_SIZE; + if(upTo - dmaBuf > DEMOD_DMA_BUFFER_SIZE) { + upTo -= DEMOD_DMA_BUFFER_SIZE; AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo; - AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; + AT91C_BASE_PDC_SSC->PDC_RNCR = DEMOD_DMA_BUFFER_SIZE; } lastRxCounter -= 2; if(lastRxCounter <= 0) { - lastRxCounter += DMA_BUFFER_SIZE; + lastRxCounter += DEMOD_DMA_BUFFER_SIZE; } samples += 2; @@ -1028,7 +1028,7 @@ void ReadSTMemoryIso14443(uint32_t parameter,uint32_t dwLast) * 0-4095 : Demodulated samples receive (4096 bytes) - DEMOD_TRACE_SIZE * 4096-6143 : Last Received command, 2048 bytes (reader->tag) - READER_TAG_BUFFER_SIZE * 6144-8191 : Last Received command, 2048 bytes(tag->reader) - TAG_READER_BUFFER_SIZE - * 8192-9215 : DMA Buffer, 1024 bytes (samples) - DMA_BUFFER_SIZE + * 8192-9215 : DMA Buffer, 1024 bytes (samples) - DEMOD_DMA_BUFFER_SIZE */ void RAMFUNC SnoopIso14443(void) { @@ -1077,7 +1077,7 @@ void RAMFUNC SnoopIso14443(void) Dbprintf(" Trace: %i bytes", DEMOD_TRACE_SIZE); Dbprintf(" Reader -> tag: %i bytes", READER_TAG_BUFFER_SIZE); Dbprintf(" tag -> Reader: %i bytes", TAG_READER_BUFFER_SIZE); - Dbprintf(" DMA: %i bytes", DMA_BUFFER_SIZE); + Dbprintf(" DMA: %i bytes", DEMOD_DMA_BUFFER_SIZE); // And put the FPGA in the appropriate mode @@ -1091,18 +1091,18 @@ void RAMFUNC SnoopIso14443(void) // Setup for the DMA. FpgaSetupSsc(); upTo = dmaBuf; - lastRxCounter = DMA_BUFFER_SIZE; - FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); + lastRxCounter = DEMOD_DMA_BUFFER_SIZE; + FpgaSetupSscDma((uint8_t *)dmaBuf, DEMOD_DMA_BUFFER_SIZE); LED_A_ON(); // And now we loop, receiving samples. for(;;) { int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & - (DMA_BUFFER_SIZE-1); + (DEMOD_DMA_BUFFER_SIZE-1); if(behindBy > maxBehindBy) { maxBehindBy = behindBy; - if(behindBy > (DMA_BUFFER_SIZE-2)) { // TODO: understand whether we can increase/decrease as we want or not? + if(behindBy > (DEMOD_DMA_BUFFER_SIZE-2)) { // TODO: understand whether we can increase/decrease as we want or not? Dbprintf("blew circular buffer! behindBy=0x%x", behindBy); goto done; } @@ -1113,11 +1113,11 @@ void RAMFUNC SnoopIso14443(void) cq = upTo[1]; upTo += 2; lastRxCounter -= 2; - if(upTo - dmaBuf > DMA_BUFFER_SIZE) { - upTo -= DMA_BUFFER_SIZE; - lastRxCounter += DMA_BUFFER_SIZE; + if(upTo - dmaBuf > DEMOD_DMA_BUFFER_SIZE) { + upTo -= DEMOD_DMA_BUFFER_SIZE; + lastRxCounter += DEMOD_DMA_BUFFER_SIZE; AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo; - AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; + AT91C_BASE_PDC_SSC->PDC_RNCR = DEMOD_DMA_BUFFER_SIZE; } samples += 2; diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 13a00aba..7ff13ae9 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -104,7 +104,7 @@ void AppendCrc14443a(uint8_t* data, int len) int 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; @@ -624,7 +624,7 @@ void RAMFUNC SnoopIso14443a(void) // #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 +// #define TRACE_SIZE 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 @@ -656,7 +656,7 @@ void RAMFUNC SnoopIso14443a(void) int samples = 0; int rsamples = 0; - memset(trace, 0x44, RECV_CMD_OFFSET); + memset(trace, 0x44, TRACE_SIZE); // Set up the demodulator for tag -> reader responses. Demod.output = receivedResponse; @@ -724,7 +724,7 @@ void RAMFUNC SnoopIso14443a(void) 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; @@ -751,7 +751,7 @@ void RAMFUNC SnoopIso14443a(void) 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; @@ -964,15 +964,102 @@ static int EmSendCmd14443aRaw(uint8_t *resp, int respLen, int correctionNeeded); // 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) { + // Enable and clear the trace + tracing = TRUE; + traceLen = 0; + memset(trace, 0x44, TRACE_SIZE); + // 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; + } + + // Calculate the BitCountCheck (BCC) for the first 4 bytes of the UID. + response2[4] = response2[0] ^ response2[1] ^ response2[2] ^ response2[3]; + + // 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]); + + // 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]); + + +/* + // Check if the uid uses the (optional) second part + if (uid_2nd) { + // Configure the ATQA and SAK accordingly + response1[0] |= 0x40; + sak |= 0x04; + } +*/ + +//static const uint8_t response2a[] = { 0x51, 0x48, 0x1d, 0x80, 0x84 }; // uid - cascade2 - 2nd half (4 bytes) of UID+ BCCheck + // 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 +// 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 @@ -980,29 +1067,29 @@ void SimulateIso14443aTag(int tagType, int TagUid) //static const uint8_t response2[] = { 0x9a, 0xe5, 0xe4, 0x43, 0xd8 }; // original value - greg // my desfire - static const uint8_t response2[] = { 0x88, 0x04, 0x21, 0x3f, 0x4d }; // known uid - note cascade (0x88), 2nd byte (0x04) = NXP/Phillips +// uint8_t response2[] = { 0x88, 0x04, 0x21, 0x3f, 0x4d }; // known uid - note cascade (0x88), 2nd byte (0x04) = NXP/Phillips // 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]); +//uint8_t response3[] = { 0x24, 0x00, 0x00 }; // SAK Select (cascade1) successful response (DESFire) +//ComputeCrc14443(CRC_14443_A, response3, 1, &response3[1], &response3[2]); // 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 +//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 // 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]); +//uint8_t response3a[] = { 0x20, 0x00, 0x00 }; // SAK Select (cascade2) successful response (DESFire) +//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 *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 @@ -1016,11 +1103,11 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); // // Respond with card type - uint8_t *resp1 = (((uint8_t *)BigBuf) + 800); + uint8_t *resp1 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET); int resp1Len; // Anticollision cascade1 - respond with uid - uint8_t *resp2 = (((uint8_t *)BigBuf) + 970); + uint8_t *resp2 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 166); int resp2Len; // Anticollision cascade2 - respond with 2nd half of uid if asked @@ -1029,22 +1116,23 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); int resp2aLen; // Acknowledge select - cascade 1 - uint8_t *resp3 = (((uint8_t *)BigBuf) + 1310); + uint8_t *resp3 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + (166*2)); int resp3Len; // Acknowledge select - cascade 2 - uint8_t *resp3a = (((uint8_t *)BigBuf) + 1480); + 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); + uint8_t *resp4 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + (166*4)); int resp4Len; // Authenticate response - nonce - uint8_t *resp5 = (((uint8_t *)BigBuf) + 1720); + uint8_t *resp5 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + (166*5)); int resp5Len; - uint8_t *receivedCmd = (uint8_t *)BigBuf; + uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET); +// uint8_t *receivedCmd = (uint8_t *)BigBuf; int len; //int i; @@ -1059,11 +1147,14 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); int happened = 0; int happened2 = 0; - int cmdsRecvd = 0; + int cmdsRecvd = 0; + uint8_t* respdata = NULL; + int respsize = 0; + uint8_t nack = 0x04; //int fdt_indicator; - 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 @@ -1105,7 +1196,7 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); LED_A_ON(); for(;;) { - if(!GetIso14443aCommandFromReader(receivedCmd, &len, 100)) { + if(!GetIso14443aCommandFromReader(receivedCmd, &len, RECV_CMD_SIZE)) { DbpString("button press"); break; } @@ -1116,73 +1207,88 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); if(receivedCmd[0] == 0x26) { // Received a REQUEST resp = resp1; respLen = resp1Len; order = 1; + respdata = response1; + respsize = sizeof(response1); //DbpString("Hello request from reader:"); } else if(receivedCmd[0] == 0x52) { // Received a WAKEUP resp = resp1; respLen = resp1Len; order = 6; // //DbpString("Wakeup request from reader:"); - + respdata = response1; + respsize = sizeof(response1); } else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x93) { // greg - cascade 1 anti-collision // 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]); - - + respdata = response2; + respsize = sizeof(response2); } else if(receivedCmd[1] == 0x20 && receivedCmd[0] ==0x95) { // greg - cascade 2 anti-collision // 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]); - + respdata = response2a; + respsize = sizeof(response2a); } else if(receivedCmd[1] == 0x70 && receivedCmd[0] ==0x93) { // greg - cascade 1 select // Received a SELECT resp = resp3; respLen = resp3Len; order = 3; // DbpString("Select (cascade 1) request from reader:"); // DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]); - + respdata = response3; + respsize = sizeof(response3); } else if(receivedCmd[1] == 0x70 && receivedCmd[0] ==0x95) { // greg - cascade 2 select // Received a SELECT resp = resp3a; respLen = resp3aLen; order = 30; // DbpString("Select (cascade 2) request from reader:"); // DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]); - + respdata = response3a; + respsize = sizeof(response3a); } else if(receivedCmd[0] == 0x30) { // Received a READ resp = resp4; respLen = resp4Len; order = 4; // Do nothing Dbprintf("Read request from reader: %x %x %x", receivedCmd[0], receivedCmd[1], receivedCmd[2]); - + respdata = &nack; + respsize = sizeof(nack); // 4-bit answer } else if(receivedCmd[0] == 0x50) { // Received a HALT resp = resp1; respLen = 0; order = 5; // Do nothing DbpString("Reader requested we HALT!:"); + respdata = NULL; + respsize = 0; } 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]); + respdata = NULL; + respsize = 0; } 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", + 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[0], receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5], receivedCmd[6], receivedCmd[7], receivedCmd[8]); // 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++; } @@ -1196,7 +1302,6 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); //i = 0; } - memset(receivedCmd, 0x44, 32); if(cmdsRecvd > 999) { DbpString("1000 commands later..."); @@ -1206,13 +1311,22 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); cmdsRecvd++; } - if(respLen <= 0) continue; - //---------------------------- - //u = 0; - //b = 0x00; - //fdt_indicator = FALSE; + if(respLen > 0) { + //---------------------------- + //u = 0; + //b = 0x00; + //fdt_indicator = FALSE; + 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); + } + } - EmSendCmd14443aRaw(resp, respLen, receivedCmd[0] == 0x52); + memset(receivedCmd, 0x44, RECV_CMD_SIZE); /* // Modulate Manchester FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD); AT91C_BASE_SSC->SSC_THR = 0x00; @@ -2079,7 +2193,7 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) } 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(); diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 2510a117..28184bb9 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -14,12 +14,6 @@ #define __ISO14443A_H #include "common.h" -// BIG CHANGE - UNDERSTAND THIS BEFORE WE COMMIT -#define RECV_CMD_OFFSET 3032 -#define RECV_RES_OFFSET 3096 -#define DMA_BUFFER_OFFSET 3160 -#define DMA_BUFFER_SIZE 4096 -#define TRACE_LENGTH 3000 // mifare reader over DMA buffer (SnoopIso14443a())!!! #define MIFARE_BUFF_OFFSET 3560 // \/ \/ \/ // card emulator memory diff --git a/armsrc/util.c b/armsrc/util.c index 00dbdbb8..3870a6c6 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -12,6 +12,15 @@ #include "util.h" #include "string.h" +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; +} + void num_to_bytes(uint64_t n, size_t len, uint8_t* dest) { while (len--) { diff --git a/armsrc/util.h b/armsrc/util.h index 14403232..661b472d 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -28,6 +28,7 @@ #define BUTTON_DOUBLE_CLICK -2 #define BUTTON_ERROR -99 +uint32_t SwapBits(uint32_t value, int nrbits); void num_to_bytes(uint64_t n, size_t len, uint8_t* dest); uint64_t bytes_to_num(uint8_t* src, size_t len); diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 537b7181..cf7570dd 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -202,18 +202,84 @@ int CmdHF14AReader(const char *Cmd) // ## simulate iso14443a tag // ## greg - added ability to specify tag UID int CmdHF14ASim(const char *Cmd) -{ - +{ + UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{0,0,0}}; + + // Retrieve the tag type + uint8_t tagtype = param_get8ex(Cmd,0,0,10); + + // When no argument was given, just print help message + if (tagtype == 0) { + PrintAndLog(""); + PrintAndLog(" Emulating ISO/IEC 14443 type A tag with 4 or 7 byte UID"); + PrintAndLog(""); + PrintAndLog(" syntax: hf 14a sim "); + PrintAndLog(" types: 1 = MIFARE Classic"); + PrintAndLog(" 2 = MIFARE Ultralight"); + PrintAndLog(" 3 = MIFARE DESFIRE"); + PrintAndLog(" 4 = ISO/IEC 14443-4"); + PrintAndLog(""); + return 1; + } + + // Store the tag type + c.arg[0] = tagtype; + + // Retrieve the full 4 or 7 byte long uid + uint64_t long_uid = param_get64ex(Cmd,1,0,16); + + // Are we handling the (optional) second part uid? + if (long_uid > 0xffffffff) { + PrintAndLog("Emulating ISO/IEC 14443 type A tag with 7 byte UID (%014llx)",long_uid); + // Store the second part + c.arg[2] = (long_uid & 0xffffffff); + long_uid >>= 32; + // Store the first part, ignore the first byte, it is replaced by cascade byte (0x88) + c.arg[1] = (long_uid & 0xffffff); + } else { + PrintAndLog("Emulating ISO/IEC 14443 type A tag with 4 byte UID (%08x)",long_uid); + // Only store the first part + c.arg[1] = long_uid & 0xffffffff; + } +/* + // At lease save the mandatory first part of the UID + c.arg[0] = long_uid & 0xffffffff; + + + // At lease save the mandatory first part of the UID + c.arg[0] = long_uid & 0xffffffff; + + if (c.arg[1] == 0) { + PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]); + } + + switch (c.arg[0]) { + case 1: { + PrintAndLog("Emulating ISO/IEC 14443-3 type A tag with 4 byte UID"); + UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16)}; + } break; + case 2: { + PrintAndLog("Emulating ISO/IEC 14443-4 type A tag with 7 byte UID"); + } break; + default: { + PrintAndLog("Error: unkown tag type (%d)",c.arg[0]); + PrintAndLog("syntax: hf 14a sim ",c.arg[0]); + PrintAndLog(" type1: 4 ",c.arg[0]); + + return 1; + } break; + } +*/ +/* unsigned int hi = 0, lo = 0; int n = 0, i = 0; while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { hi= (hi << 4) | (lo >> 28); lo= (lo << 4) | (n & 0xf); } - - // c.arg should be set to *Cmd or convert *Cmd to the correct format for a uid - UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a, {hi, lo, 0}}; - PrintAndLog("Emulating 14443A TAG with UID %x%16x", hi, lo); +*/ +// UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16)}; +// PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]); SendCommand(&c); return 0; } diff --git a/client/util.c b/client/util.c index ae213e43..be947b8a 100644 --- a/client/util.c +++ b/client/util.c @@ -166,7 +166,7 @@ uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base) int bg, en; if (!param_getptr(line, &bg, &en, paramnum)) - return strtol(&line[bg], NULL, base); + return strtoll(&line[bg], NULL, base); else return deflt; -- 2.39.2