diff --git a/armsrc/Makefile b/armsrc/Makefile index e11e7ae83..7e7822433 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -21,15 +21,13 @@ APP_CFLAGS = -DWITH_CRC \ -DWITH_ISO14443a \ -DWITH_ICLASS \ -DWITH_HFSNOOP \ - -DWITH_HF_YOUNG \ - -DWITH_LF_SAMYRUN \ -fno-strict-aliasing -ffunction-sections -fdata-sections ### IMPORTANT - move the commented variable below this line # -DWITH_LCD \ # # Standalone Mods #------------------------------------------------------- -# -DWITH_ICEMAN +# -DWITH_LF_ICERUN # -DWITH_LF_SAMYRUN # -DWITH_LF_PROXBRUTE # -DWITH_LF_HIDCORP @@ -78,6 +76,9 @@ THUMBSRC = start.c \ random.c \ hfsnoop.c +# Standalone/hf_young.c \ +# Standalone/lf_samyrun.c + # These are to be compiled in ARM mode ARMSRC = fpgaloader.c \ $(SRC_ISO14443a) \ diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 1ba3ae185..381a346b2 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -26,12 +26,6 @@ #include "LCD.h" #endif -// Craig Young - 14a stand-alone code -#ifdef WITH_HF_YOUNG - #include "iso14443a.h" - #include "protocols.h" -#endif - //============================================================================= // A buffer where we can queue things up to be sent through the FPGA, for // any purpose (fake tag, as reader, whatever). We go MSB first, since that @@ -44,8 +38,7 @@ int ToSendMax = -1; static int ToSendBit; struct common_area common_area __attribute__((section(".commonarea"))); -void ToSendReset(void) -{ +void ToSendReset(void) { ToSendMax = -1; ToSendBit = 8; } @@ -68,7 +61,7 @@ void ToSendStuffBit(int b) { } } -void PrintToSendBuffer(void){ +void PrintToSendBuffer(void) { DbpString("Printing ToSendBuffer:"); Dbhexdump(ToSendMax, ToSend, 0); } @@ -99,7 +92,7 @@ void print_result(char *name, uint8_t *buf, size_t len) { // Debug print functions, to go out over USB, to the usual PC-side client. //============================================================================= -void DbpStringEx(char *str, uint32_t cmd){ +void DbpStringEx(char *str, uint32_t cmd) { byte_t len = strlen(str); cmd_send(CMD_DEBUG_PRINT_STRING,len, cmd,0,(byte_t*)str,len); } @@ -168,8 +161,7 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) { // in ADC units (0 to 1023). Also a routine to average 32 samples and // return that. //----------------------------------------------------------------------------- -static int ReadAdc(int ch) -{ +static int ReadAdc(int ch) { uint32_t d; AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; @@ -199,8 +191,8 @@ static int ReadAdc(int ch) return d; } -int AvgAdc(int ch) // was static - merlok -{ +// was static - merlok +int AvgAdc(int ch) { int i, a = 0; for(i = 0; i < 32; i++) a += ReadAdc(ch); @@ -208,7 +200,6 @@ int AvgAdc(int ch) // was static - merlok return (a + 15) >> 5; } - void MeasureAntennaTuning(void) { uint8_t LF_Results[256]; @@ -275,7 +266,6 @@ void MeasureAntennaTuningHf(void) { DbpString("cancelled"); } - void ReadMem(int addr) { const uint8_t *data = ((uint8_t *)addr); @@ -287,8 +277,7 @@ void ReadMem(int addr) { extern struct version_information version_information; /* bootrom version information is pointed to from _bootphase1_version_pointer */ extern char *_bootphase1_version_pointer, _flash_start, _flash_end, _bootrom_start, _bootrom_end, __data_src_start__; -void SendVersion(void) -{ +void SendVersion(void) { char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */ char VersionString[USB_CMD_DATA_SIZE] = { '\0' }; @@ -320,41 +309,9 @@ void SendVersion(void) cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, 0, VersionString, strlen(VersionString)); } -// detection of which Standalone Modes is installed -// (iceman) -void printStandAloneModes(void){ - #if defined(WITH_HF_YOUNG) || defined(WITH_LF_SAMYRUN) - DbpString("Installed StandAlone Mods"); - #endif - #if defined(WITH_ICEMAN) - DbpString("LF sniff/clone/simulation - aka IceRun (iceman)"); - #endif - #if defined(WITH_HF_YOUNG) // WITH_HF_YOUNG - DbpString("HF Mifare sniff/simulation - (Craig Young)"); - #endif - #if defined(WITH_LF_SAMYRUN) // - DbpString("LF HID26 standalone - aka SamyRun (Samy Kamkar)"); - #endif - #if defined(WITH_LF_PROXBRUTE) - DbpString("LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)"); - #endif - #if defined(WITH_LF_HIDCORP) - DbpString("LF HID corporate 1000 bruteforce - (Federi Codotta)"); - #endif - #if defined(WITH_HF_MATTYRUN) - DbpString("HF Mifare sniff/clone - aka MattyRun (Matta Real)"); - #endif - - //.. add your own standalone detection based on with compiler directive you are used. - // don't "reuse" the already taken ones, this will make things easier when trying to detect the different modes - // 2017-08-06 must adapt the makefile and have individual compilation flags for all mods - // -} - // measure the USB Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time. // Note: this mimics GetFromBigbuf(), i.e. we have the overhead of the UsbCommand structure included. -void printUSBSpeed(void) -{ +void printUSBSpeed(void) { Dbprintf("USB Speed:"); Dbprintf(" Sending USB packets to client..."); @@ -397,11 +354,8 @@ void SendStatus(void) { cmd_send(CMD_ACK,1,0,0,0,0); } -#if defined(WITH_HF_YOUNG) || defined(WITH_LF_SAMYRUN) - -#define OPTS 2 -void StandAloneMode() -{ +// Show some leds in a pattern to identify StandAlone mod is running +void StandAloneMode(void) { DbpString("Stand-alone mode! No PC necessary."); // Oooh pretty -- notify user we're in elite samy mode now LED(LED_RED, 200); @@ -414,393 +368,37 @@ void StandAloneMode() LED(LED_ORANGE, 200); LED(LED_RED, 200); } -#endif - -#ifdef WITH_HF_YOUNG - -typedef struct { - uint8_t uid[10]; - uint8_t uidlen; - uint8_t atqa[2]; - uint8_t sak; -} __attribute__((__packed__)) card_clone_t; - -void StandAloneMode14a() -{ - StandAloneMode(); - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - - int selected = 0, playing = 0, iGotoRecord = 0, iGotoClone = 0; - int cardRead[OPTS] = {0}; - - card_clone_t uids[OPTS]; - iso14a_card_select_t card[OPTS]; - uint8_t params = (MAGIC_SINGLE | MAGIC_DATAIN); - - LED(selected + 1, 0); - - for (;;) - { - usb_poll(); - WDT_HIT(); - SpinDelay(300); - - if (iGotoRecord == 1 || cardRead[selected] == 0) - { - iGotoRecord = 0; - LEDsoff(); - LED(selected + 1, 0); - LED(LED_RED2, 0); - - // record - Dbprintf("Enabling iso14443a reader mode for [Bank: %d]...", selected); - /* need this delay to prevent catching some weird data */ - SpinDelay(500); - iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); - - for ( ; ; ) - { - WDT_HIT(); - if (BUTTON_PRESS()) { - if (cardRead[selected]) { - Dbprintf("Button press detected -- replaying card in bank[%d]", selected); - break; - } - else if (cardRead[(selected+1) % OPTS]) { - Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected+1)%OPTS); - selected = (selected+1) % OPTS; - break; // playing = 1; - } - else { - Dbprintf("Button press detected but no stored tag to play. (Ignoring button)"); - SpinDelay(300); - } - } - if (!iso14443a_select_card(NULL, &card[selected], NULL, true, 0)) - continue; - else - { - Dbprintf("Read UID:"); - Dbhexdump(card[selected].uidlen, card[selected].uid, 0); - - if (memcmp(uids[(selected+1)%OPTS].uid, card[selected].uid, card[selected].uidlen ) == 0 ) { - Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping."); - } - else { - - uids[selected].sak = card[selected].sak; - uids[selected].uidlen = card[selected].uidlen; - memcpy(uids[selected].uid , card[selected].uid, uids[selected].uidlen); - memcpy(uids[selected].atqa, card[selected].atqa, 2); - - if (uids[selected].uidlen > 4) - Dbprintf("Bank[%d] received a 7-byte UID", selected); - else - Dbprintf("Bank[%d] received a 4-byte UID", selected); - break; - } - } - } - Dbprintf("ATQA = %02X%02X", uids[selected].atqa[0], uids[selected].atqa[1]); - Dbprintf("SAK = %02X", uids[selected].sak); - LEDsoff(); - LED(LED_GREEN, 200); - LED(LED_ORANGE, 200); - LED(LED_GREEN, 200); - LED(LED_ORANGE, 200); - - LEDsoff(); - LED(selected + 1, 0); - - // Next state is replay: - playing = 1; - - cardRead[selected] = 1; - } - /* MF Classic UID clone */ - else if (iGotoClone==1) - { - iGotoClone=0; - LEDsoff(); - LED(selected + 1, 0); - LED(LED_ORANGE, 250); - - // magiccards holds 4bytes uid. *usually* - uint32_t tmpuid = bytes_to_num(uids[selected].uid, 4); - - // record - Dbprintf("Preparing to Clone card [Bank: %d]; uid: %08x", selected, tmpuid); - - // wait for button to be released - // Delay cloning until card is in place - while(BUTTON_PRESS()) - WDT_HIT(); - - Dbprintf("Starting clone. [Bank: %d]", selected); - // need this delay to prevent catching some weird data - SpinDelay(500); - // Begin clone function here: - /* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards: - UsbCommand c = {CMD_MIFARE_CSETBLOCK, {params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0}}; - memcpy(c.d.asBytes, data, 16); - SendCommand(&c); - - Block read is similar: - UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, blockNo, 0}}; - We need to imitate that call with blockNo 0 to set a uid. - - The get and set commands are handled in this file: - // Work with "magic Chinese" card - case CMD_MIFARE_CSETBLOCK: - MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes); - break; - case CMD_MIFARE_CGETBLOCK: - MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes); - break; - - mfCSetUID provides example logic for UID set workflow: - -Read block0 from card in field with MifareCGetBlock() - -Configure new values without replacing reserved bytes - memcpy(block0, uid, 4); // Copy UID bytes from byte array - // Mifare UID BCC - block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // BCC on byte 5 - Bytes 5-7 are reserved SAK and ATQA for mifare classic - -Use mfCSetBlock(0, block0, oldUID, wantWipe, MAGIC_SINGLE) to write it - */ - uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0}; - // arg0 = Flags, arg1=blockNo - MifareCGetBlock(params, 0, oldBlock0); - if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) { - Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected); - playing = 1; - } - else { - Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0], oldBlock0[1], oldBlock0[2], oldBlock0[3]); - memcpy(newBlock0, oldBlock0, 16); - - // Copy uid for bank (2nd is for longer UIDs not supported if classic) - memcpy(newBlock0, uids[selected].uid, 4); - newBlock0[4] = newBlock0[0] ^ newBlock0[1] ^ newBlock0[2] ^ newBlock0[3]; - - // arg0 = workFlags, arg1 = blockNo, datain - MifareCSetBlock(params, 0, newBlock0); - MifareCGetBlock(params, 0, testBlock0); - - if (memcmp(testBlock0, newBlock0, 16)==0) { - DbpString("Cloned successfull!"); - cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it - playing = 0; - iGotoRecord = 1; - selected = (selected + 1) % OPTS; - } else { - Dbprintf("Clone failed. Back to replay mode on bank[%d]", selected); - playing = 1; - } - } - LEDsoff(); - LED(selected + 1, 0); - } - // Change where to record (or begin playing) - else if (playing==1) // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected]) - { - LEDsoff(); - LED(selected + 1, 0); - - // Begin transmitting - LED(LED_GREEN, 0); - DbpString("Playing"); - for ( ; ; ) { - WDT_HIT(); - int button_action = BUTTON_HELD(1000); - if (button_action == 0) { // No button action, proceed with sim - - uint8_t flags = FLAG_4B_UID_IN_DATA; - uint8_t data[USB_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break - - memcpy(data, uids[selected].uid, uids[selected].uidlen); - - uint64_t tmpuid = bytes_to_num(uids[selected].uid, uids[selected].uidlen); - - if ( uids[selected].uidlen == 7 ) { - flags = FLAG_7B_UID_IN_DATA; - Dbprintf("Simulating ISO14443a tag with uid: %014" PRIx64 " [Bank: %d]", tmpuid, selected); - } else { - Dbprintf("Simulating ISO14443a tag with uid: %08" PRIx64 " [Bank: %d]", tmpuid, selected); - } - - if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0) { - DbpString("Mifare Classic 1k"); - SimulateIso14443aTag(1, flags, data); - } else if (uids[selected].sak == 0x18 && uids[selected].atqa[0] == 0x02 && uids[selected].atqa[1] == 0) { - DbpString("Mifare Classic 4k (4b uid)"); - SimulateIso14443aTag(8, flags, data); - } else if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) { - DbpString("Mifare Classic 4k (7b uid)"); - SimulateIso14443aTag(8, flags, data); - } else if (uids[selected].sak == 0x00 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) { - DbpString("Mifare Ultralight"); - SimulateIso14443aTag(2, flags, data); - } else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0x03) { - DbpString("Mifare DESFire"); - SimulateIso14443aTag(3, flags, data); - } - else { - Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation"); - SimulateIso14443aTag(1, flags, data); - } - } - else if (button_action == BUTTON_SINGLE_CLICK) { - selected = (selected + 1) % OPTS; - Dbprintf("Done playing. Switching to record mode on bank %d", selected); - iGotoRecord = 1; - break; - } - else if (button_action == BUTTON_HOLD) { - Dbprintf("Playtime over. Begin cloning..."); - iGotoClone = 1; - break; - } - WDT_HIT(); - } - - /* We pressed a button so ignore it here with a delay */ - SpinDelay(300); - LEDsoff(); - LED(selected + 1, 0); - - } - } -} -#elif WITH_LF_SAMYRUN -// samy's sniff and repeat routine for LF -void SamyRun() -{ - StandAloneMode(); - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - - int high[OPTS], low[OPTS]; - int selected = 0; - int playing = 0; - int cardRead = 0; - - // Turn on selected LED - LED(selected + 1, 0); - - for (;;) { - - WDT_HIT(); - - // exit from SammyRun, send a usbcommand. - if (usb_poll_validate_length()) { - break; - } - - // Was our button held down or pressed? - int button_pressed = BUTTON_HELD(1000); - SpinDelay(300); - - // Button was held for a second, begin recording - if (button_pressed > 0 && cardRead == 0) - { - LEDsoff(); - LED(selected + 1, 0); - LED(LED_RED2, 0); - - // record - DbpString("Starting recording"); - - // wait for button to be released - while(BUTTON_PRESS()) - WDT_HIT(); - - /* need this delay to prevent catching some weird data */ - SpinDelay(500); - - CmdHIDdemodFSK(1, &high[selected], &low[selected], 0); - Dbprintf("Recorded %x %x %08x", selected, high[selected], low[selected]); - - LEDsoff(); - LED(selected + 1, 0); - // Finished recording - // If we were previously playing, set playing off - // so next button push begins playing what we recorded - playing = 0; - cardRead = 1; - } - else if (button_pressed > 0 && cardRead == 1) { - LEDsoff(); - LED(selected + 1, 0); - LED(LED_ORANGE, 0); - - // record - Dbprintf("Cloning %x %x %08x", selected, high[selected], low[selected]); - - // wait for button to be released - while(BUTTON_PRESS()) - WDT_HIT(); - - /* need this delay to prevent catching some weird data */ - SpinDelay(500); - - CopyHIDtoT55x7(0, high[selected], low[selected], 0); - Dbprintf("Cloned %x %x %08x", selected, high[selected], low[selected]); - - LEDsoff(); - LED(selected + 1, 0); - // Finished recording - - // If we were previously playing, set playing off - // so next button push begins playing what we recorded - playing = 0; - cardRead = 0; - } - - // Change where to record (or begin playing) - else if (button_pressed) { - // Next option if we were previously playing - if (playing) - selected = (selected + 1) % OPTS; - playing = !playing; - - LEDsoff(); - LED(selected + 1, 0); - - // Begin transmitting - if (playing) - { - LED(LED_GREEN, 0); - DbpString("Playing"); - // wait for button to be released - while(BUTTON_PRESS()) - WDT_HIT(); - - Dbprintf("%x %x %08x", selected, high[selected], low[selected]); - CmdHIDsimTAG(high[selected], low[selected], 0); - DbpString("Done playing"); - - if (BUTTON_HELD(1000) > 0) { - DbpString("Exiting"); - LEDsoff(); - return; - } - - /* We pressed a button so ignore it here with a delay */ - SpinDelay(300); - - // when done, we're done playing, move to next option - selected = (selected + 1) % OPTS; - playing = !playing; - LEDsoff(); - LED(selected + 1, 0); - } - else - while(BUTTON_PRESS()) - WDT_HIT(); - } - } +// detection of which Standalone Modes is installed +// (iceman) +void printStandAloneModes(void) { + #if defined(WITH_HF_YOUNG) || defined(WITH_LF_SAMYRUN) + DbpString("Installed StandAlone Mods"); + #endif + #if defined(WITH_LF_ICERUN) + DbpString(" LF sniff/clone/simulation - aka IceRun (iceman)"); + #endif + #if defined(WITH_HF_YOUNG) + DbpString(" HF Mifare sniff/simulation - (Craig Young)"); + #endif + #if defined(WITH_LF_SAMYRUN) + DbpString(" LF HID26 standalone - aka SamyRun (Samy Kamkar)"); + #endif + #if defined(WITH_LF_PROXBRUTE) + DbpString(" LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)"); + #endif + #if defined(WITH_LF_HIDCORP) + DbpString(" LF HID corporate 1000 bruteforce - (Federi Codotta)"); + #endif + #if defined(WITH_HF_MATTYRUN) + DbpString(" HF Mifare sniff/clone - aka MattyRun (Matta Real)"); + #endif + + //.. add your own standalone detection based on with compiler directive you are used. + // don't "reuse" the already taken ones, this will make things easier when trying to detect the different modes + // 2017-08-06 must adapt the makefile and have individual compilation flags for all mods + // } -#endif /* OBJECTIVE Listen and detect an external reader. Determine the best location @@ -950,8 +548,7 @@ void ListenReaderField(int limit) { } } -void UsbPacketReceived(uint8_t *packet, int len) -{ +void UsbPacketReceived(uint8_t *packet, int len) { UsbCommand *c = (UsbCommand *)packet; //Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d",len,c->cmd,c->arg[0],c->arg[1],c->arg[2]); @@ -1203,6 +800,9 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES: MifareAcquireEncryptedNonces(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; + case CMD_MIFARE_ACQUIRE_NONCES: + MifareAcquireNonces(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; case CMD_MIFARE_NESTED: MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; @@ -1305,7 +905,7 @@ void UsbPacketReceived(uint8_t *packet, int len) #ifdef WITH_ICLASS // Makes use of ISO14443a FPGA Firmware case CMD_SNOOP_ICLASS: - SnoopIClass(); + SniffIClass(); break; case CMD_SIMULATE_TAG_ICLASS: SimulateIClass(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); @@ -1502,8 +1102,7 @@ void UsbPacketReceived(uint8_t *packet, int len) } } -void __attribute__((noreturn)) AppMain(void) -{ +void __attribute__((noreturn)) AppMain(void) { SpinDelay(100); clear_trace(); if(common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) { @@ -1554,17 +1153,15 @@ void __attribute__((noreturn)) AppMain(void) } WDT_HIT(); -#ifdef WITH_LF_SAMYRUN -#ifndef WITH_HF_YOUNG - if (BUTTON_HELD(1000) > 0) - SamyRun(); -#endif -#endif -#ifdef WITH_ISO14443a -#ifdef WITH_HF_YOUNG - if (BUTTON_HELD(1000) > 0) - StandAloneMode14a(); + if (BUTTON_HELD(1000) > 0) { +#if defined (WITH_LF) && defined (WITH_LF_SAMYRUN) + RunMod(); #endif + +#if defined (WITH_ISO14443a) && defined (WITH_HF_YOUNG) + RunMod(); #endif + + } } } diff --git a/armsrc/apps.h b/armsrc/apps.h index 311609b88..1fd974e5d 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -30,6 +30,7 @@ extern "C" { #include "desfire.h" #include "iso14443b.h" #include "emvcard.h" +#include "Standalone/standalone.h" extern const uint8_t OddByteParity[256]; extern int rsamples; // = 0; @@ -43,7 +44,6 @@ extern uint8_t trigger; /// appmain.h void ReadMem(int addr); void __attribute__((noreturn)) AppMain(void); -void SamyRun(void); //void DbpIntegers(int a, int b, int c); void DbpString(char *str); void Dbprintf(const char *fmt, ...); @@ -64,6 +64,9 @@ void ListenReaderField(int limit); extern int ToSendMax; extern uint8_t ToSend[]; +extern void StandAloneMode(void); +extern void printStandAloneModes(void); + /// lfops.h extern uint8_t decimation; extern uint8_t bits_per_sample ; @@ -139,6 +142,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain); +void MifareAcquireNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain); void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); @@ -195,7 +199,7 @@ void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8 void SetDebugIso15693(uint32_t flag); // iclass.h -void RAMFUNC SnoopIClass(void); +void RAMFUNC SniffIClass(void); void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void ReaderIClass(uint8_t arg0); void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC); diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index b205555b2..01bacb709 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -11,6 +11,7 @@ //----------------------------------------------------------------------------- #include "fpgaloader.h" +extern void DbpString(char *str); extern void Dbprintf(const char *fmt, ...); // remember which version of the bitstream we have already downloaded to the FPGA @@ -32,8 +33,7 @@ static const uint8_t _bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0 // Used to write the FPGA config word // May also be used to write to other SPI attached devices like an LCD //----------------------------------------------------------------------------- -void SetupSpi(int mode) -{ +void SetupSpi(int mode) { // PA10 -> SPI_NCS2 chip select (LCD) // PA11 -> SPI_NCS0 chip select (FPGA) // PA12 -> SPI_MISO Master-In Slave-Out @@ -163,13 +163,11 @@ bool FpgaSetupSscDma(uint8_t *buf, int len) { return true; } - //---------------------------------------------------------------------------- // Uncompress (inflate) the FPGA data. Returns one decompressed byte with // each call. //---------------------------------------------------------------------------- -static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8_t *output_buffer) -{ +static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8_t *output_buffer) { if (fpga_image_ptr == compressed_fpga_stream->next_out) { // need more data compressed_fpga_stream->next_out = output_buffer; compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN; @@ -182,9 +180,7 @@ static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8 if (res < 0) return res; } - uncompressed_bytes_cnt++; - return *fpga_image_ptr++; } @@ -193,8 +189,7 @@ static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8 // are combined into one big file: // 288 bytes from FPGA file 1, followed by 288 bytes from FGPA file 2, etc. //---------------------------------------------------------------------------- -static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) -{ +static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { while((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % FPGA_BITSTREAM_MAX != (bitstream_version - 1)) { // skip undesired data belonging to other bitstream_versions get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); @@ -203,25 +198,19 @@ static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga return get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); } - -static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size) -{ +static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size) { return BigBuf_malloc(items*size); } - -static void fpga_inflate_free(voidpf opaque, voidpf address) -{ - // free eventually allocated BigBuf memory +// free eventually allocated BigBuf memory +static void fpga_inflate_free(voidpf opaque, voidpf address) { BigBuf_free(); BigBuf_Clear_ext(false); } - //---------------------------------------------------------------------------- // Initialize decompression of the respective (HF or LF) FPGA stream //---------------------------------------------------------------------------- -static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) -{ +static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE]; uncompressed_bytes_cnt = 0; @@ -248,9 +237,7 @@ static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_s return false; } - -static void DownloadFPGA_byte(unsigned char w) -{ +static void DownloadFPGA_byte(unsigned char w) { #define SEND_BIT(x) { if(w & (1<PIO_OER = GPIO_FPGA_ON; @@ -340,28 +326,26 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp comp LED_D_OFF(); } - /* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence * 00 09 0f f0 0f f0 0f f0 0f f0 00 00 01 * After that the format is 1 byte section type (ASCII character), 2 byte length * (big endian), bytes content. Except for section 'e' which has 4 bytes * length. */ -static int bitparse_find_section(int bitstream_version, char section_name, unsigned int *section_length, z_streamp compressed_fpga_stream, uint8_t *output_buffer) -{ +static int bitparse_find_section(int bitstream_version, char section_name, uint32_t *section_length, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { int result = 0; #define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section uint16_t numbytes = 0; while(numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) { char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); numbytes++; - unsigned int current_length = 0; - if(current_name < 'a' || current_name > 'e') { + uint32_t current_length = 0; + if (current_name < 'a' || current_name > 'e') { /* Strange section name, abort */ break; } current_length = 0; - switch(current_name) { + switch (current_name) { case 'e': /* Four byte length field */ current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24; @@ -373,12 +357,12 @@ static int bitparse_find_section(int bitstream_version, char section_name, unsig numbytes += 2; } - if(current_name != 'e' && current_length > 255) { + if (current_name != 'e' && current_length > 255) { /* Maybe a parse error */ break; } - if(current_name == section_name) { + if (current_name == section_name) { /* Found it */ *section_length = current_length; result = 1; @@ -390,33 +374,32 @@ static int bitparse_find_section(int bitstream_version, char section_name, unsig numbytes++; } } - return result; } - //---------------------------------------------------------------------------- // Check which FPGA image is currently loaded (if any). If necessary // decompress and load the correct (HF or LF) image to the FPGA //---------------------------------------------------------------------------- -void FpgaDownloadAndGo(int bitstream_version) -{ - z_stream compressed_fpga_stream; - uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00}; +void FpgaDownloadAndGo(int bitstream_version) { // check whether or not the bitstream is already loaded if (downloaded_bitstream == bitstream_version) return; + + z_stream compressed_fpga_stream; + uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00}; + bool verbose = (MF_DBGLEVEL > 3); + // make sure that we have enough memory to decompress - BigBuf_free(); BigBuf_Clear_ext(false); + BigBuf_free(); BigBuf_Clear_ext(verbose); - if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) { + if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) return; - } - unsigned int bitstream_length; - if(bitparse_find_section(bitstream_version, 'e', &bitstream_length, &compressed_fpga_stream, output_buffer)) { + uint32_t bitstream_length; + if (bitparse_find_section(bitstream_version, 'e', &bitstream_length, &compressed_fpga_stream, output_buffer)) { DownloadFPGA(bitstream_version, bitstream_length, &compressed_fpga_stream, output_buffer); downloaded_bitstream = bitstream_version; } @@ -427,16 +410,14 @@ void FpgaDownloadAndGo(int bitstream_version) BigBuf_free(); BigBuf_Clear_ext(false); } - //----------------------------------------------------------------------------- // Gather version information from FPGA image. Needs to decompress the begin // of the respective (HF or LF) image. // Note: decompression makes use of (i.e. overwrites) BigBuf[]. It is therefore // advisable to call this only once and store the results for later use. //----------------------------------------------------------------------------- -void FpgaGatherVersion(int bitstream_version, char *dst, int len) -{ - unsigned int fpga_info_len; +void FpgaGatherVersion(int bitstream_version, char *dst, int len) { + uint32_t fpga_info_len; char tempstr[40] = {0x00}; z_stream compressed_fpga_stream; uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00}; @@ -449,7 +430,7 @@ void FpgaGatherVersion(int bitstream_version, char *dst, int len) if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) return; - if(bitparse_find_section(bitstream_version, 'a', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { + if (bitparse_find_section(bitstream_version, 'a', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { for (uint16_t i = 0; i < fpga_info_len; i++) { char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer); if (i < sizeof(tempstr)) { @@ -462,7 +443,7 @@ void FpgaGatherVersion(int bitstream_version, char *dst, int len) strncat(dst, "HF ", len-1); } strncat(dst, "FPGA image built", len-1); - if(bitparse_find_section(bitstream_version, 'b', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { + if (bitparse_find_section(bitstream_version, 'b', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { strncat(dst, " for ", len-1); for (uint16_t i = 0; i < fpga_info_len; i++) { char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer); @@ -472,7 +453,7 @@ void FpgaGatherVersion(int bitstream_version, char *dst, int len) } strncat(dst, tempstr, len-1); } - if(bitparse_find_section(bitstream_version, 'c', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { + if (bitparse_find_section(bitstream_version, 'c', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { strncat(dst, " on ", len-1); for (uint16_t i = 0; i < fpga_info_len; i++) { char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer); @@ -482,7 +463,7 @@ void FpgaGatherVersion(int bitstream_version, char *dst, int len) } strncat(dst, tempstr, len-1); } - if(bitparse_find_section(bitstream_version, 'd', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { + if (bitparse_find_section(bitstream_version, 'd', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { strncat(dst, " at ", len-1); for (uint16_t i = 0; i < fpga_info_len; i++) { char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer); @@ -498,16 +479,14 @@ void FpgaGatherVersion(int bitstream_version, char *dst, int len) inflateEnd(&compressed_fpga_stream); } - //----------------------------------------------------------------------------- // Send a 16 bit command/data pair to the FPGA. // The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 // where C is the 4 bit command and D is the 12 bit data //----------------------------------------------------------------------------- -void FpgaSendCommand(uint16_t cmd, uint16_t v) -{ +void FpgaSendCommand(uint16_t cmd, uint16_t v) { SetupSpi(SPI_FPGA_MODE); - while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete + while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete AT91C_BASE_SPI->SPI_TDR = AT91C_SPI_LASTXFER | cmd | v; // send the data } //----------------------------------------------------------------------------- @@ -515,8 +494,7 @@ void FpgaSendCommand(uint16_t cmd, uint16_t v) // vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to // avoid changing this function's occurence everywhere in the source code. //----------------------------------------------------------------------------- -void FpgaWriteConfWord(uint8_t v) -{ +void FpgaWriteConfWord(uint8_t v) { FpgaSendCommand(FPGA_CMD_SET_CONFREG, v); } @@ -525,8 +503,7 @@ void FpgaWriteConfWord(uint8_t v) // closable, but should only close one at a time. Not an FPGA thing, but // the samples from the ADC always flow through the FPGA. //----------------------------------------------------------------------------- -void SetAdcMuxFor(uint32_t whichGpio) -{ +void SetAdcMuxFor(uint32_t whichGpio) { AT91C_BASE_PIOA->PIO_OER = GPIO_MUXSEL_HIPKD | GPIO_MUXSEL_LOPKD | @@ -548,14 +525,28 @@ void SetAdcMuxFor(uint32_t whichGpio) } void Fpga_print_status(void) { - Dbprintf("Fgpa"); + DbpString("Fgpa"); switch(downloaded_bitstream) { - case FPGA_BITSTREAM_HF: Dbprintf(" mode....................HF"); break; - case FPGA_BITSTREAM_LF: Dbprintf(" mode....................LF"); break; - default: Dbprintf(" mode....................%d", downloaded_bitstream); break; + case FPGA_BITSTREAM_HF: DbpString(" mode....................HF"); break; + case FPGA_BITSTREAM_LF: DbpString(" mode....................LF"); break; + default: Dbprintf(" mode....................%d", downloaded_bitstream); break; } } int FpgaGetCurrent() { return downloaded_bitstream; } + +// Turns off the antenna, +// log message +// if HF, Disable SSC DMA +// turn off trace and leds off. +void switch_off() { + if (MF_DBGLEVEL > 3) Dbprintf("switch_off"); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(100); + if (downloaded_bitstream == FPGA_BITSTREAM_HF ) + FpgaDisableSscDma(); + set_tracing(false); + LEDsoff(); +} \ No newline at end of file diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 1f9b3ac8d..1b4f83b07 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -14,7 +14,6 @@ #include "common.h" // standard definitions #include "proxmark3.h" // common area -//#include "util.h" #include "string.h" #include "BigBuf.h" // bigbuf mem #include "zlib.h" // uncompress @@ -33,6 +32,8 @@ int FpgaGetCurrent(); #define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; void SetAdcMuxFor(uint32_t whichGpio); +extern void switch_off(); + // definitions for multiple FPGA config files support #define FPGA_BITSTREAM_MAX 2 // the total number of FPGA bitstreams (configs) #define FPGA_BITSTREAM_ERR 0 diff --git a/armsrc/iclass.c b/armsrc/iclass.c index b2dbdc062..ab60aea08 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -60,7 +60,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf); // The software UART that receives commands from the reader, and its state // variables. //----------------------------------------------------------------------------- -static struct { +typedef struct { enum { STATE_UNSYNCD, STATE_START_OF_COMMUNICATION, @@ -69,7 +69,7 @@ static struct { uint16_t shiftReg; int bitCnt; int byteCnt; - int byteCntMax; +// int byteCntMax; int posCnt; int nOutOfCnt; int OutOfCnt; @@ -81,8 +81,69 @@ static struct { int bitBuffer; int dropPosition; uint8_t *output; -} Uart; +} tUart; +typedef struct { + enum { + DEMOD_UNSYNCD, + DEMOD_START_OF_COMMUNICATION, + DEMOD_START_OF_COMMUNICATION2, + DEMOD_START_OF_COMMUNICATION3, + DEMOD_SOF_COMPLETE, + DEMOD_MANCHESTER_D, + DEMOD_MANCHESTER_E, + DEMOD_END_OF_COMMUNICATION, + DEMOD_END_OF_COMMUNICATION2, + DEMOD_MANCHESTER_F, + DEMOD_ERROR_WAIT + } state; + int bitCount; + int posCount; + int syncBit; + uint16_t shiftReg; + int buffer; + int buffer2; + int buffer3; + int buff; + int samples; + int len; + enum { + SUB_NONE, + SUB_FIRST_HALF, + SUB_SECOND_HALF, + SUB_BOTH + } sub; + uint8_t *output; +} tDemod; + +static tUart Uart; +static void UartReset(){ + Uart.state = STATE_UNSYNCD; + Uart.shiftReg = 0; + Uart.bitCnt = 0; + Uart.byteCnt = 0; + Uart.posCnt = 0; + Uart.nOutOfCnt = 0; + Uart.OutOfCnt = 0; + Uart.syncBit = 0; + Uart.samples = 0; + Uart.highCnt = 0; + Uart.swapper = 0; + Uart.counter = 0; + Uart.bitBuffer = 0; + Uart.dropPosition = 0; +} +static void UartInit(uint8_t *data){ + Uart.output = data; + UartReset(); +} + + +/* +* READER TO CARD +* 1 out of 4 Decoding +* 1 out of 256 Decoding +*/ static RAMFUNC int OutOfNDecoding(int bit) { //int error = 0; int bitright; @@ -263,10 +324,13 @@ static RAMFUNC int OutOfNDecoding(int bit) { Uart.posCnt = 1; // apparently we are busy with our first half bit period Uart.syncBit = bit & 8; Uart.samples = 3; + if (!Uart.syncBit) { Uart.syncBit = bit & 4; Uart.samples = 2; } else if (bit & 4) { Uart.syncBit = bit & 4; Uart.samples = 2; bit <<= 2; } + if (!Uart.syncBit) { Uart.syncBit = bit & 2; Uart.samples = 1; } else if (bit & 2) { Uart.syncBit = bit & 2; Uart.samples = 1; bit <<= 1; } + if (!Uart.syncBit) { Uart.syncBit = bit & 1; Uart.samples = 0; if (Uart.syncBit && (Uart.bitBuffer & 8)) { Uart.syncBit = 8; @@ -300,40 +364,83 @@ static RAMFUNC int OutOfNDecoding(int bit) { //============================================================================= // Manchester //============================================================================= +static tDemod Demod; +static void DemodReset() { + Demod.bitCount = 0; + Demod.posCount = 0; + Demod.syncBit = 0; + Demod.shiftReg = 0; + Demod.buffer = 0; + Demod.buffer2 = 0; + Demod.buffer3 = 0; + Demod.buff = 0; + Demod.samples = 0; + Demod.len = 0; + Demod.sub = SUB_NONE; + Demod.state = DEMOD_UNSYNCD; +} +static void DemodInit(uint8_t *data) { + Demod.output = data; + DemodReset(); +} -static struct { - enum { - DEMOD_UNSYNCD, - DEMOD_START_OF_COMMUNICATION, - DEMOD_START_OF_COMMUNICATION2, - DEMOD_START_OF_COMMUNICATION3, - DEMOD_SOF_COMPLETE, - DEMOD_MANCHESTER_D, - DEMOD_MANCHESTER_E, - DEMOD_END_OF_COMMUNICATION, - DEMOD_END_OF_COMMUNICATION2, - DEMOD_MANCHESTER_F, - DEMOD_ERROR_WAIT - } state; - int bitCount; - int posCount; - int syncBit; - uint16_t shiftReg; - int buffer; - int buffer2; - int buffer3; - int buff; - int samples; - int len; - enum { - SUB_NONE, - SUB_FIRST_HALF, - SUB_SECOND_HALF, - SUB_BOTH - } sub; - uint8_t *output; -} Demod; +// UART debug +// it adds the debug values which will be put in the tracelog, +// visible on client when running 'hf list iclass' +/* +pm3 --> hf li iclass +Recorded Activity (TraceLen = 162 bytes) + Start | End | Src | Data (! denotes parity error) | CRC | Annotation | +------------|------------|-----|-----------------------------------------------------------------|-----|--------------------| + 0 | 0 | Rdr |0a | | ACTALL + 1280 | 1280 | Tag |bb! 33! bb! 01 02 04 08 bb! | ok | + 1280 | 1280 | Rdr |0c | | IDENTIFY + 1616 | 1616 | Tag |bb! 33! bb! 00! 02 00! 02 bb! | ok | + 1616 | 1616 | Rdr |0a | | ACTALL + 2336 | 2336 | Tag |bb! d4! bb! 02 08 00! 08 bb! | ok | + 2336 | 2336 | Rdr |0c | | IDENTIFY + 2448 | 2448 | Tag |bb! 33! bb! 00! 00! 00! 02 bb! | ok | + 2448 | 2448 | Rdr |0a | | ACTALL + 2720 | 2720 | Tag |bb! d4! bb! 08 0b 01 04 bb! | ok | + 2720 | 2720 | Rdr |0c | | IDENTIFY + 3232 | 3232 | Tag |bb! d4! bb! 02 02 08 04 bb! | ok | +*/ +static void uart_debug(int error, int bit) { + Demod.output[Demod.len] = 0xBB; + Demod.len++; + Demod.output[Demod.len] = error & 0xFF; + Demod.len++; + Demod.output[Demod.len] = 0xBB; + Demod.len++; + Demod.output[Demod.len] = bit & 0xFF; + Demod.len++; + Demod.output[Demod.len] = Demod.buffer & 0xFF; + Demod.len++; + // Look harder ;-) + Demod.output[Demod.len] = Demod.buffer2 & 0xFF; + Demod.len++; + Demod.output[Demod.len] = Demod.syncBit & 0xFF; + Demod.len++; + Demod.output[Demod.len] = 0xBB; + Demod.len++; +} +/* +* CARD TO READER +* in ISO15693-2 mode - Manchester +* in ISO 14443b - BPSK coding +* +* Timings: +* ISO 15693-2 +* Tout = 330 µs, Tprog 1 = 4 to 15 ms, Tslot = 330 µs + (number of slots x 160 µs) +* ISO 14443a +* Tout = 100 µs, Tprog = 4 to 15 ms, Tslot = 100 µs+ (number of slots x 80 µs) +* ISO 14443b + Tout = 76 µs, Tprog = 4 to 15 ms, Tslot = 119 µs+ (number of slots x 150 µs) +* +* +* So for current implementation in ISO15693, its 330 µs from end of reader, to start of card. +*/ static RAMFUNC int ManchesterDecoding(int v) { int bit; int modulation; @@ -344,6 +451,7 @@ static RAMFUNC int ManchesterDecoding(int v) { Demod.buffer2 = Demod.buffer3; Demod.buffer3 = v; + // too few bits? if (Demod.buff < 3) { Demod.buff++; return false; @@ -382,8 +490,9 @@ static RAMFUNC int ManchesterDecoding(int v) { Demod.bitCount = 0; Demod.shiftReg = 0; Demod.samples = 0; + if (Demod.posCount) { - //if(trigger) LED_A_OFF(); // Not useful in this case... + switch (Demod.syncBit) { case 0x08: Demod.samples = 3; break; case 0x04: Demod.samples = 2; break; @@ -399,182 +508,146 @@ static RAMFUNC int ManchesterDecoding(int v) { if (!(Demod.buffer2 & Demod.syncBit) || !(Demod.buffer3 & Demod.syncBit)) { Demod.state = DEMOD_UNSYNCD; error = 0x88; + uart_debug(error, bit); return false; } - // TODO: use this error value to print? Ask Holiman. - // 2016-01-08 iceman } error = 0; } - } else { - modulation = bit & Demod.syncBit; - modulation |= ((bit << 1) ^ ((Demod.buffer & 0x08) >> 3)) & Demod.syncBit; + return false; + } - Demod.samples += 4; + // state is DEMOD is in SYNC from here on. + + modulation = bit & Demod.syncBit; + modulation |= ((bit << 1) ^ ((Demod.buffer & 0x08) >> 3)) & Demod.syncBit; + Demod.samples += 4; - if (Demod.posCount == 0) { - Demod.posCount = 1; - if (modulation) - Demod.sub = SUB_FIRST_HALF; - else - Demod.sub = SUB_NONE; + if (Demod.posCount == 0) { + Demod.posCount = 1; + Demod.sub = (modulation) ? SUB_FIRST_HALF : SUB_NONE; + return false; + } + + Demod.posCount = 0; + + if (modulation) { + + if (Demod.sub == SUB_FIRST_HALF) + Demod.sub = SUB_BOTH; + else + Demod.sub = SUB_SECOND_HALF; + } + + if (Demod.sub == SUB_NONE) { + if (Demod.state == DEMOD_SOF_COMPLETE) { + Demod.output[Demod.len] = 0x0f; + Demod.len++; + Demod.state = DEMOD_UNSYNCD; + return true; } else { - Demod.posCount = 0; - /*(modulation && (Demod.sub == SUB_FIRST_HALF)) { - if(Demod.state!=DEMOD_ERROR_WAIT) { - Demod.state = DEMOD_ERROR_WAIT; - Demod.output[Demod.len] = 0xaa; - error = 0x01; - } - }*/ - //else if(modulation) { - if (modulation) { - if (Demod.sub == SUB_FIRST_HALF) - Demod.sub = SUB_BOTH; - else - Demod.sub = SUB_SECOND_HALF; - } - else if (Demod.sub == SUB_NONE) { - if (Demod.state == DEMOD_SOF_COMPLETE) { - Demod.output[Demod.len] = 0x0f; - Demod.len++; - Demod.state = DEMOD_UNSYNCD; -// error = 0x0f; - return true; - } else { - Demod.state = DEMOD_ERROR_WAIT; - error = 0x33; - } - /*if(Demod.state!=DEMOD_ERROR_WAIT) { - Demod.state = DEMOD_ERROR_WAIT; - Demod.output[Demod.len] = 0xaa; - error = 0x01; - }*/ - } - - switch (Demod.state) { - case DEMOD_START_OF_COMMUNICATION: - if (Demod.sub == SUB_BOTH) { - //Demod.state = DEMOD_MANCHESTER_D; - Demod.state = DEMOD_START_OF_COMMUNICATION2; - Demod.posCount = 1; - Demod.sub = SUB_NONE; - } else { - Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_ERROR_WAIT; - error = 0xd2; - } - break; - case DEMOD_START_OF_COMMUNICATION2: - if (Demod.sub == SUB_SECOND_HALF) { - Demod.state = DEMOD_START_OF_COMMUNICATION3; - } else { - Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_ERROR_WAIT; - error = 0xd3; - } - break; - case DEMOD_START_OF_COMMUNICATION3: - if (Demod.sub == SUB_SECOND_HALF) { -// Demod.state = DEMOD_MANCHESTER_D; - Demod.state = DEMOD_SOF_COMPLETE; - //Demod.output[Demod.len] = Demod.syncBit & 0xFF; - //Demod.len++; - } else { - Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_ERROR_WAIT; - error = 0xd4; - } - break; - case DEMOD_SOF_COMPLETE: - case DEMOD_MANCHESTER_D: - case DEMOD_MANCHESTER_E: - // OPPOSITE FROM ISO14443 - 11110000 = 0 (1 in 14443) - // 00001111 = 1 (0 in 14443) - if (Demod.sub == SUB_SECOND_HALF) { // SUB_FIRST_HALF - Demod.bitCount++; - Demod.shiftReg = (Demod.shiftReg >> 1) ^ 0x100; - Demod.state = DEMOD_MANCHESTER_D; - } else if (Demod.sub == SUB_FIRST_HALF) { // SUB_SECOND_HALF - Demod.bitCount++; - Demod.shiftReg >>= 1; - Demod.state = DEMOD_MANCHESTER_E; - } else if (Demod.sub == SUB_BOTH) { - Demod.state = DEMOD_MANCHESTER_F; - } else { - Demod.state = DEMOD_ERROR_WAIT; - error = 0x55; - } - break; - - case DEMOD_MANCHESTER_F: - // Tag response does not need to be a complete byte! - if (Demod.len > 0 || Demod.bitCount > 0) { - if (Demod.bitCount > 1) { // was > 0, do not interpret last closing bit, is part of EOF - Demod.shiftReg >>= (9 - Demod.bitCount); // right align data - Demod.output[Demod.len] = Demod.shiftReg & 0xff; - Demod.len++; - } - - Demod.state = DEMOD_UNSYNCD; - return true; - } else { - Demod.output[Demod.len] = 0xad; - Demod.state = DEMOD_ERROR_WAIT; - error = 0x03; - } - break; - - case DEMOD_ERROR_WAIT: - Demod.state = DEMOD_UNSYNCD; - break; - - default: - Demod.output[Demod.len] = 0xdd; - Demod.state = DEMOD_UNSYNCD; - break; - } - - /*if (Demod.bitCount >= 9) { - Demod.output[Demod.len] = Demod.shiftReg & 0xff; - Demod.len++; - - Demod.parityBits <<= 1; - Demod.parityBits ^= ((Demod.shiftReg >> 8) & 0x01); - - Demod.bitCount = 0; - Demod.shiftReg = 0; - }*/ - if (Demod.bitCount >= 8) { - Demod.shiftReg >>= 1; - Demod.output[Demod.len] = (Demod.shiftReg & 0xff); - Demod.len++; - Demod.bitCount = 0; - Demod.shiftReg = 0; - } - - if (error) { - Demod.output[Demod.len] = 0xBB; - Demod.len++; - Demod.output[Demod.len] = error & 0xFF; - Demod.len++; - Demod.output[Demod.len] = 0xBB; - Demod.len++; - Demod.output[Demod.len] = bit & 0xFF; - Demod.len++; - Demod.output[Demod.len] = Demod.buffer & 0xFF; - Demod.len++; - // Look harder ;-) - Demod.output[Demod.len] = Demod.buffer2 & 0xFF; - Demod.len++; - Demod.output[Demod.len] = Demod.syncBit & 0xFF; - Demod.len++; - Demod.output[Demod.len] = 0xBB; - Demod.len++; - return true; - } + Demod.state = DEMOD_ERROR_WAIT; + error = 0x33; } - } // end (state != UNSYNCED) + } + + switch (Demod.state) { + + case DEMOD_START_OF_COMMUNICATION: + if (Demod.sub == SUB_BOTH) { + + Demod.state = DEMOD_START_OF_COMMUNICATION2; + Demod.posCount = 1; + Demod.sub = SUB_NONE; + } else { + Demod.output[Demod.len] = 0xab; + Demod.state = DEMOD_ERROR_WAIT; + error = 0xd2; + } + break; + + case DEMOD_START_OF_COMMUNICATION2: + if (Demod.sub == SUB_SECOND_HALF) { + Demod.state = DEMOD_START_OF_COMMUNICATION3; + } else { + Demod.output[Demod.len] = 0xab; + Demod.state = DEMOD_ERROR_WAIT; + error = 0xd3; + } + break; + + case DEMOD_START_OF_COMMUNICATION3: + if (Demod.sub == SUB_SECOND_HALF) { + Demod.state = DEMOD_SOF_COMPLETE; + } else { + Demod.output[Demod.len] = 0xab; + Demod.state = DEMOD_ERROR_WAIT; + error = 0xd4; + } + break; + + case DEMOD_SOF_COMPLETE: + case DEMOD_MANCHESTER_D: + case DEMOD_MANCHESTER_E: + // OPPOSITE FROM ISO14443 - 11110000 = 0 (1 in 14443) + // 00001111 = 1 (0 in 14443) + if (Demod.sub == SUB_SECOND_HALF) { // SUB_FIRST_HALF + Demod.bitCount++; + Demod.shiftReg = (Demod.shiftReg >> 1) ^ 0x100; + Demod.state = DEMOD_MANCHESTER_D; + } else if (Demod.sub == SUB_FIRST_HALF) { // SUB_SECOND_HALF + Demod.bitCount++; + Demod.shiftReg >>= 1; + Demod.state = DEMOD_MANCHESTER_E; + } else if (Demod.sub == SUB_BOTH) { + Demod.state = DEMOD_MANCHESTER_F; + } else { + Demod.state = DEMOD_ERROR_WAIT; + error = 0x55; + } + break; + + case DEMOD_MANCHESTER_F: + // Tag response does not need to be a complete byte! + if (Demod.len > 0 || Demod.bitCount > 0) { + if (Demod.bitCount > 1) { // was > 0, do not interpret last closing bit, is part of EOF + Demod.shiftReg >>= (9 - Demod.bitCount); // right align data + Demod.output[Demod.len] = Demod.shiftReg & 0xff; + Demod.len++; + } + + Demod.state = DEMOD_UNSYNCD; + return true; + } else { + Demod.output[Demod.len] = 0xad; + Demod.state = DEMOD_ERROR_WAIT; + error = 0x03; + } + break; + + case DEMOD_ERROR_WAIT: + Demod.state = DEMOD_UNSYNCD; + break; + + default: + Demod.output[Demod.len] = 0xdd; + Demod.state = DEMOD_UNSYNCD; + break; + } + + if (Demod.bitCount >= 8) { + Demod.shiftReg >>= 1; + Demod.output[Demod.len] = (Demod.shiftReg & 0xff); + Demod.len++; + Demod.bitCount = 0; + Demod.shiftReg = 0; + } + + if (error) { + uart_debug(error, bit); + return true; + } + return false; } @@ -589,18 +662,28 @@ static RAMFUNC int ManchesterDecoding(int v) { // near the reader. //----------------------------------------------------------------------------- // turn off afterwards -void RAMFUNC SnoopIClass(void) { +void RAMFUNC SniffIClass(void) { + LEDsoff(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // Set up the synchronous serial port + FpgaSetupSsc(); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - // Setup for the DMA. - FpgaSetupSsc(); - - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - - // free all BigBuf memory - BigBuf_free(); + // Signal field is off with the appropriate LED + LED_D_OFF(); + + // put the FPGA in the appropriate mode + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER); + SpinDelay(50); + + // Start the timer + StartCountSspClk(); + // free all BigBuf memory + BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(true); @@ -612,163 +695,169 @@ void RAMFUNC SnoopIClass(void) { // The length of a received command will in most cases be no more than 18 bytes. // So 32 should be enough! #define ICLASS_BUFFER_SIZE 32 - uint8_t readerToTagCmd[ICLASS_BUFFER_SIZE]; + uint8_t *readerToTagCmd = BigBuf_malloc(ICLASS_BUFFER_SIZE); // The response (tag -> reader) that we're receiving. - uint8_t tagToReaderResponse[ICLASS_BUFFER_SIZE]; + uint8_t *tagToReaderResponse = BigBuf_malloc(ICLASS_BUFFER_SIZE); // The DMA buffer, used to stream samples from the FPGA uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); - uint8_t *upTo = dmaBuf; + uint8_t *data = dmaBuf; - int lastRxCounter = DMA_BUFFER_SIZE; - int smpl, maxBehindBy = 0; - - // Count of samples received so far, so that we can include timing - // information in the trace buffer. - int samples = 0; - - // global variable (apps.h) - rsamples = 0; + uint8_t previous_data = 0; + int maxDataLen = 0; + int datalen = 0; + bool TagIsActive = false; + bool ReaderIsActive = false; // Set up the demodulator for tag -> reader responses. - Demod.output = tagToReaderResponse; - Demod.len = 0; - Demod.state = DEMOD_UNSYNCD; + DemodInit(tagToReaderResponse); + + // And the reader -> tag commands + UartInit(readerToTagCmd); // Setup and start DMA. if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); + if (MF_DBGLEVEL > 1) DbpString("FpgaSetupSscDma failed. Exiting"); return; } - - // And the reader -> tag commands - memset(&Uart, 0, sizeof(Uart)); - Uart.output = readerToTagCmd; - Uart.byteCntMax = 32; // was 100 (greg)//////////////////////////////////////////////////////////////////////// - Uart.state = STATE_UNSYNCD; - - // 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); - SpinDelay(20); - + uint32_t time_0 = GetCountSspClk(); uint32_t time_start = 0, time_stop = 0; - int div = 0, decbyte = 0, decbyter = 0; + int div = 0; - // And now we loop, receiving samples. - for(;;) { + uint32_t rsamples = 0; + + DbpString("Starting to sniff"); + + // loop and listen + while (!BUTTON_PRESS()) { WDT_HIT(); LED_A_ON(); - int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & (DMA_BUFFER_SIZE-1); - - if ( behindBy > maxBehindBy) { - maxBehindBy = behindBy; - if ( behindBy > (9 * DMA_BUFFER_SIZE / 10)) { - Dbprintf("blew circular buffer! behindBy=0x%x", behindBy); - goto done; - } - } - if( behindBy < 1) continue; - + // number of bytes we have processed so far + int register readBufDataP = data - dmaBuf; + // number of bytes already transferred + 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; + + // test for length of buffer + if (datalen > maxDataLen) { + maxDataLen = datalen; + if (datalen > (9 * DMA_BUFFER_SIZE / 10)) { + Dbprintf("blew circular buffer! datalen=%d", datalen); + break; + } + } + 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(); - 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; - } - - //samples += 4; - samples += 1; - - if(smpl & 0xF) - decbyte ^= (1 << (3 - div)); - - // FOR READER SIDE COMMUMICATION... - decbyter <<= 2; - decbyter ^= (smpl & 0x30); div++; + // + Dbprintf("iced: prev %, curr %u, div %i", previous_data, *data, div); - if (( div + 1) % 2 == 0) { - smpl = decbyter; - if ( OutOfNDecoding((smpl & 0xF0) >> 4)) { - rsamples = samples - Uart.samples; - time_stop = (GetCountSspClk() - time_0) << 4; - LED_C_ON(); + // need two samples to feed OutOfNDecoding + if (rsamples & 0x01) { - //if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,true)) break; - //if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, true)) break; - //uint8_t parity[Uart.byteCnt/8]; - //GetParity(Uart.output, Uart.byteCnt, parity); - //LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, parity, true); - LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true); + // no need to try decoding reader data if the tag is sending + // READER TO CARD + if (!TagIsActive) { - /* 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(); - Uart.byteCnt = 0; - } else { - time_start = (GetCountSspClk() - time_0) << 4; + if (MF_DBGLEVEL > 1) DbpString("reader -> card"); + + uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); + + // FOR READER SIDE COMMUMICATION... + //readerbyte <<= 2; // make space for two new bits. + + // 76543210 + // xor ( sample & 00110000 ) only bit 5,4 wanted. ( one out of four? + //readerbyte ^= (sample & 0x30); + // 00110000 -> 0011 + if ( OutOfNDecoding((readerdata & 0xF0) >> 4)) { + + LED_C_INV(); + + time_stop = (GetCountSspClk() - time_0) << 4; + + LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true); + + // reset the demod code, which might have been false-triggered by the commands from the reader. + DemodReset(); + // ready to receive another command. + UartInit(readerToTagCmd); + } else { + time_start = (GetCountSspClk() - time_0) << 4; + } + //readerbyte = 0; + ReaderIsActive = (Uart.state != STATE_UNSYNCD); } - decbyter = 0; } if (div > 3) { - smpl = decbyte; - if (ManchesterDecoding(smpl & 0x0F)) { - time_stop = (GetCountSspClk() - time_0) << 4; - - rsamples = samples - Demod.samples; - LED_B_ON(); - - //uint8_t parity[Demod.len/8]; - //GetParity(Demod.output, Demod.len, parity); - //LogTrace(Demod.output, Demod.len, time_start, time_stop, parity, false); - LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false); - - // And ready to receive another response. - memset(&Demod, 0, sizeof(Demod)); - Demod.output = tagToReaderResponse; - Demod.state = DEMOD_UNSYNCD; - LED_C_OFF(); - } else { - time_start = (GetCountSspClk() - time_0) << 4; - } - div = 0; - decbyte = 0x00; + if (MF_DBGLEVEL > 1) DbpString("div > 3"); + + // no need to try decoding tag data if the reader is sending - and we cannot afford the time + // CARD TO READER + if (!ReaderIsActive) { + + // xor ( + // if (sample & 0xF) + // tagbyte ^= (1 << (3 - div)); + uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); + if (ManchesterDecoding(tagdata)) { + LED_C_INV(); + + time_stop = (GetCountSspClk() - time_0) << 4; + + LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false); + + // ready to receive another response. + DemodReset(); + // reset the Uart decode including its (now outdated) input buffer + UartInit(readerToTagCmd); + + } else { + time_start = (GetCountSspClk() - time_0) << 4; + } + + div = 0; + //tagbyte = 00; + TagIsActive = (Demod.state != DEMOD_UNSYNCD); + } } - if (BUTTON_PRESS()) { - DbpString("cancelled_a"); - goto done; - } - } + previous_data = *data; + rsamples++; + data++; + if(data == dmaBuf + DMA_BUFFER_SIZE) + data = dmaBuf; + + } // end main loop - DbpString("COMMAND FINISHED"); - - Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt); - Dbprintf("%x %x %x", Uart.byteCntMax, BigBuf_get_traceLen(), (int)Uart.output[0]); - -done: - FpgaDisableSscDma(); - Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt); - Dbprintf("%x %x %x", Uart.byteCntMax, BigBuf_get_traceLen(), (int)Uart.output[0]); - LEDsoff(); - set_tracing(false); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + if (MF_DBGLEVEL >= 1) { + Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.bytecn=%x", maxDataLen, Uart.state, Uart.byteCnt); + Dbprintf("tracelen=%x, Uart.output[0]=%x", BigBuf_get_traceLen(), (int)Uart.output[0]); + } + switch_off(); } void rotateCSN(uint8_t* originalCSN, uint8_t* rotatedCSN) { @@ -782,26 +871,23 @@ void rotateCSN(uint8_t* originalCSN, uint8_t* rotatedCSN) { // Stop when button is pressed // Or return TRUE when command is captured //----------------------------------------------------------------------------- -static bool GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) { - - // Now run a `software UART' on the stream of incoming samples. - Uart.output = received; - Uart.byteCntMax = maxLen; - Uart.state = STATE_UNSYNCD; - +static bool GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) { // 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(); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); + // Now run a `software UART' on the stream of incoming samples. + UartInit(received); + // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; while (!BUTTON_PRESS()) { WDT_HIT(); - // if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) + //if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) // AT91C_BASE_SSC->SSC_THR = 0x00; if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { @@ -984,11 +1070,9 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain } else { // We may want a mode here where we hardcode the csns to use (from proxclone). // That will speed things up a little, but not required just yet. - Dbprintf("The mode is not implemented, reserved for future use"); + DbpString("The mode is not implemented, reserved for future use"); } - Dbprintf("Done..."); - set_tracing(false); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + switch_off(); } void AppendCrc(uint8_t* data, int len) { ComputeCrc14443(CRC_ICLASS, data, len, data+len, data+len+1); @@ -1005,7 +1089,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { BigBuf_free_keep_EM(); State cipher_state; -// State cipher_state_reserve; + uint8_t *csn = BigBuf_get_EM_addr(); uint8_t *emulator = csn; uint8_t sof_data[] = { 0x0F} ; @@ -1085,27 +1169,41 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { // First card answer: SOF CodeIClassTagSOF(); memcpy(resp_sof, ToSend, ToSendMax); resp_sof_Len = ToSendMax; - DbpString("SOF"); PrintToSendBuffer(); - + if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { + DbpString("SOF"); + PrintToSendBuffer(); + } + // Anticollision CSN CodeIClassTagAnswer(anticoll_data, sizeof(anticoll_data)); memcpy(resp_anticoll, ToSend, ToSendMax); resp_anticoll_len = ToSendMax; - DbpString("ANTI COLL CSN"); PrintToSendBuffer(); - + if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { + DbpString("ANTI COLL CSN"); + PrintToSendBuffer(); + } + // CSN CodeIClassTagAnswer(csn_data, sizeof(csn_data)); memcpy(resp_csn, ToSend, ToSendMax); resp_csn_len = ToSendMax; - DbpString("CSN"); PrintToSendBuffer(); + if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { + DbpString("CSN"); + PrintToSendBuffer(); + } // e-Purse CodeIClassTagAnswer(card_challenge_data, sizeof(card_challenge_data)); memcpy(resp_cc, ToSend, ToSendMax); resp_cc_len = ToSendMax; - DbpString("e-Purse"); PrintToSendBuffer(); - + if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { + DbpString("e-Purse"); + PrintToSendBuffer(); + } // Application Issuer Area CodeIClassTagAnswer(aia_data, sizeof(aia_data)); memcpy(resp_aia, ToSend, ToSendMax); resp_aia_len = ToSendMax; - DbpString("Application Issuer Data"); PrintToSendBuffer(); + if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { + DbpString("Application Issuer Data"); + PrintToSendBuffer(); + } //This is used for responding to READ-block commands or other data which is dynamically generated //First the 'trace'-data, not encoded for FPGA @@ -1137,7 +1235,11 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { WDT_HIT(); response_delay = 1; - + receivedCmd[0] = 0; receivedCmd[1] = 0; receivedCmd[2] = 0; receivedCmd[3] = 0; + receivedCmd[4] = 0; receivedCmd[5] = 0; receivedCmd[6] = 0; receivedCmd[7] = 0; + receivedCmd[8] = 0; receivedCmd[9] = 0; receivedCmd[10] = 0; receivedCmd[11] = 0; + receivedCmd[12] = 0;receivedCmd[13] = 0;receivedCmd[14] = 0; receivedCmd[15] = 0; + //Signal tracer, can be used to get a trigger for an oscilloscope.. LED_B_OFF(); LED_C_OFF(); @@ -1292,17 +1394,11 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { t2r_time = (GetCountSspClk() - time_0) << 4; } - //uint8_t parity[MAX_PARITY_SIZE]; - //GetParity(receivedCmd, len, parity); - //LogTrace(receivedCmd, len, (r2t_time - time_0)<< 4, (r2t_time - time_0) << 4, parity, true); - LogTrace(receivedCmd, len, (r2t_time - time_0)<< 4, (r2t_time - time_0) << 4, NULL, true); if (trace_data != NULL) { - //GetParity(trace_data, trace_data_size, parity); - //LogTrace(trace_data, trace_data_size, t2r_time, t2r_time, parity, false); LogTrace(trace_data, trace_data_size, t2r_time, t2r_time, NULL, false); - DbpString("trace written"); + if ( MF_DBGLEVEL == MF_DBG_EXTENDED) DbpString("trace written"); } } @@ -1489,16 +1585,13 @@ void ReaderTransmitIClass(uint8_t* frame, int len) { //----------------------------------------------------------------------------- static int GetIClassAnswer(uint8_t* receivedResponse, int maxLen, int *samples, int *elapsed) { // buffer needs to be 512 bytes - // maxLen is not used... int c = 0; bool skip = false; // Setup UART/DEMOD to receive - Demod.output = receivedResponse; - Demod.len = 0; - Demod.state = DEMOD_UNSYNCD; + DemodInit(receivedResponse); if (elapsed) *elapsed = 0; @@ -1513,7 +1606,8 @@ static int GetIClassAnswer(uint8_t* receivedResponse, int maxLen, int *samples, WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; // To make use of exact timing of next command from reader!! + AT91C_BASE_SSC->SSC_THR = 0x00; + // To make use of exact timing of next command from reader!! if (elapsed) (*elapsed)++; } @@ -1524,8 +1618,7 @@ static int GetIClassAnswer(uint8_t* receivedResponse, int maxLen, int *samples, b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - skip = !skip; - + skip = !skip; if (skip) continue; if (ManchesterDecoding(b & 0x0f)) { @@ -1541,7 +1634,7 @@ static int GetIClassAnswer(uint8_t* receivedResponse, int maxLen, int *samples, int ReaderReceiveIClass(uint8_t* receivedAnswer) { int samples = 0; - if (!GetIClassAnswer(receivedAnswer, 160, &samples, NULL)) + if (!GetIClassAnswer(receivedAnswer, 0, &samples, NULL)) return false; rsamples += samples; @@ -1574,6 +1667,10 @@ void setupIclassReader() { // Signal field is on with the appropriate LED FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); SpinDelay(20); + + // Start the timer + StartCountSspClk(); + LED_A_ON(); } @@ -1598,17 +1695,15 @@ bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* re uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) { // act_all... - - static uint8_t act_all[] = { ICLASS_CMD_ACTALL }; - static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 }; - static uint8_t select[] = { ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static uint8_t readcheck_cc[]= { ICLASS_CMD_READCHECK_KD, 0x02 }; + static uint8_t act_all[] = { ICLASS_CMD_ACTALL }; + static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 }; + static uint8_t select[] = { ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 }; if (use_credit_key) readcheck_cc[0] = ICLASS_CMD_READCHECK_KC; - uint8_t resp[ICLASS_BUFFER_SIZE]; - + uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; uint8_t read_status = 0; // Send act_all @@ -1621,7 +1716,7 @@ uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) { ReaderTransmitIClass(identify, 1); //We expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC - uint8_t len = ReaderReceiveIClass(resp); + uint8_t len = ReaderReceiveIClass(resp); if (len != 10) return read_status;//Fail //Copy the Anti-collision CSN to our select-packet @@ -1685,7 +1780,6 @@ void ReaderIClass(uint8_t arg0) { uint8_t flagReadCC = arg0 & FLAG_ICLASS_READER_CC; uint8_t flagReadAA = arg0 & FLAG_ICLASS_READER_AA; - set_tracing(true); setupIclassReader(); uint16_t tryCnt = 0; @@ -1716,7 +1810,7 @@ void ReaderIClass(uint8_t arg0) { result_status |= FLAG_ICLASS_READER_CONF; memcpy(card_data+8, resp, 8); } else { - Dbprintf("Failed to dump config block"); + DbpString("Failed to dump config block"); } } @@ -1726,7 +1820,7 @@ void ReaderIClass(uint8_t arg0) { result_status |= FLAG_ICLASS_READER_AA; memcpy(card_data+(8*5), resp, 8); } else { - //Dbprintf("Failed to dump AA block"); + //DbpString("Failed to dump AA block"); } } @@ -1762,10 +1856,7 @@ void ReaderIClass(uint8_t arg0) { cmd_send(CMD_ACK, 0, 0, 0, card_data, 0); out: - LEDsoff(); - Dbprintf("Done..."); - set_tracing(false); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + switch_off(); } // turn off afterwards @@ -1800,7 +1891,6 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { uint8_t resp[ICLASS_BUFFER_SIZE]; setupIclassReader(); - set_tracing(true); while (!BUTTON_PRESS()) { @@ -1813,27 +1903,27 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { memcpy(check+5, MAC, 4); if (!sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 5)) { - Dbprintf("Error: Authentication Fail!"); + DbpString("Error: Authentication Fail!"); continue; } //first get configuration block (block 1) crc = block_crc_LUT[1]; - read[1]=1; + read[1] = 1; read[2] = crc >> 8; read[3] = crc & 0xff; if (!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10)) { - Dbprintf("Dump config (block 1) failed"); + DbpString("Dump config (block 1) failed"); continue; } - mem = resp[5]; - memory.k16 = (mem & 0x80); - memory.book = (mem & 0x20); - memory.k2 = (mem & 0x8); - memory.lockauth = (mem & 0x2); - memory.keyaccess = (mem & 0x1); + mem = resp[5]; + memory.k16 = (mem & 0x80); + memory.book = (mem & 0x20); + memory.k2 = (mem & 0x8); + memory.lockauth = (mem & 0x2); + memory.keyaccess = (mem & 0x1); cardsize = memory.k16 ? 255 : 32; @@ -1903,10 +1993,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { 0 ); - LEDsoff(); - Dbprintf("Done..."); - set_tracing(false); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + switch_off(); } // turn off afterwards @@ -1916,7 +2003,7 @@ void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType) { size_t isOK = 0; isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 6); cmd_send(CMD_ACK,isOK,0,0,0,0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + switch_off(); } // used with function select_and_auth (cmdhficlass.c) @@ -1933,9 +2020,9 @@ void iClass_Authentication(uint8_t *MAC) { bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata) { uint8_t readcmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockNo, 0x00, 0x00}; //0x88, 0x00 // can i use 0C? char bl = blockNo; - uint16_t rdCrc = iclass_crc16(&bl, 1); - readcmd[2] = rdCrc >> 8; - readcmd[3] = rdCrc & 0xff; + uint16_t crc = iclass_crc16(&bl, 1); + readcmd[2] = crc >> 8; + readcmd[3] = crc & 0xff; uint8_t resp[] = {0,0,0,0,0,0,0,0,0,0}; bool isOK = sendCmdGetResponseWithRetries(readcmd, sizeof(readcmd), resp, 10, 10); @@ -1949,7 +2036,7 @@ void iClass_ReadBlk(uint8_t blockno) { bool isOK = false; isOK = iClass_ReadBlock(blockno, readblockdata); cmd_send(CMD_ACK, isOK, 0, 0, readblockdata, 8); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + switch_off(); } // turn off afterwards @@ -1961,43 +2048,42 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks) { BigBuf_free(); uint8_t *dataout = BigBuf_malloc(255*8); if (dataout == NULL){ - Dbprintf("out of memory"); + DbpString("out of memory"); OnError(1); return; } - memset(dataout,0xFF,255*8); + // fill mem with 0xFF + memset(dataout, 0xFF, 255*8); for (;blkCnt < numblks; blkCnt++) { isOK = iClass_ReadBlock(blockno + blkCnt, readblockdata); + + // 0xBB is the internal debug separator byte.. if (!isOK || (readblockdata[0] == 0xBB || readblockdata[7] == 0xBB || readblockdata[2] == 0xBB)) { //try again isOK = iClass_ReadBlock(blockno + blkCnt, readblockdata); if (!isOK) { Dbprintf("Block %02X failed to read", blkCnt + blockno); - break; - } + break; + } } memcpy(dataout + (blkCnt * 8), readblockdata, 8); } //return pointer to dump memory in arg3 cmd_send(CMD_ACK, isOK, blkCnt, BigBuf_max_traceLen(), 0, 0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + switch_off(); BigBuf_free(); } bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) { uint8_t write[] = { ICLASS_CMD_UPDATE, blockNo, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - //uint8_t readblockdata[10]; - //write[1] = blockNo; memcpy(write+2, data, 12); // data + mac char *wrCmd = (char *)(write+1); - uint16_t wrCrc = iclass_crc16(wrCmd, 13); - write[14] = wrCrc >> 8; - write[15] = wrCrc & 0xff; + uint16_t crc = iclass_crc16(wrCmd, 13); + write[14] = crc >> 8; + write[15] = crc & 0xff; uint8_t resp[] = {0,0,0,0,0,0,0,0,0,0}; - bool isOK = false; - isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 10); + bool isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 10); if (isOK) { //if reader responded correctly //Dbprintf("WriteResp: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",resp[0],resp[1],resp[2],resp[3],resp[4],resp[5],resp[6],resp[7],resp[8],resp[9]); @@ -2007,8 +2093,7 @@ bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) { if (blockNo != 3 && blockNo != 4) { //error try again isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 10); - } - + } } } return isOK; @@ -2023,9 +2108,7 @@ void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) { Dbprintf("Write block [%02x] failed", blockNo); cmd_send(CMD_ACK,isOK,0,0,0,0); - LEDsoff(); - set_tracing(false); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + switch_off(); } // turn off afterwards @@ -2047,11 +2130,10 @@ void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) { } } if (written == total_block) - Dbprintf("Clone complete"); + DbpString("Clone complete"); else - Dbprintf("Clone incomplete"); + DbpString("Clone incomplete"); cmd_send(CMD_ACK,1,0,0,0,0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + switch_off(); } \ No newline at end of file diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 3f6dc4de4..3e8fddb53 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -213,8 +213,7 @@ void UartReset() { Uart.parityBits = 0; // holds 8 parity bits Uart.startTime = 0; Uart.endTime = 0; - - Uart.byteCntMax = 0; + Uart.posCnt = 0; Uart.syncBit = 9999; } @@ -344,15 +343,11 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { } } } - } - + } } - return false; // not finished yet, need more data } - - //============================================================================= // ISO 14443 Type A - Manchester decoder //============================================================================= @@ -425,7 +420,7 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non else if ((Demod.twoBits & 0x01DC) == 0x01C0) Demod.syncBit = 1; else if ((Demod.twoBits & 0x00EE) == 0x00E0) Demod.syncBit = 0; if (Demod.syncBit != 0xFFFF) { - Demod.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8); + Demod.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8); Demod.startTime -= Demod.syncBit; Demod.bitCount = offset; // number of decoded data bits Demod.state = DEMOD_MANCHESTER_DATA; @@ -505,11 +500,10 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non // "hf 14a sniff" //----------------------------------------------------------------------------- void RAMFUNC SniffIso14443a(uint8_t param) { + LEDsoff(); // param: // bit 0 - trigger from first card answer // bit 1 - trigger from first reader 7-bit request - LEDsoff(); - iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); // Allocate memory from BigBuf for some buffers @@ -528,8 +522,8 @@ void RAMFUNC SniffIso14443a(uint8_t param) { // The DMA buffer, used to stream samples from the FPGA uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); - uint8_t *data = dmaBuf; + uint8_t previous_data = 0; int maxDataLen = 0; int dataLen = 0; @@ -554,33 +548,31 @@ void RAMFUNC SniffIso14443a(uint8_t param) { // triggered == false -- to wait first for card bool triggered = !(param & 0x03); - // And now we loop, receiving samples. - for(uint32_t rsamples = 0; true; ) { + uint32_t rsamples = 0; - if(BUTTON_PRESS()) { - DbpString("cancelled by button"); - break; - } - - LED_A_ON(); - WDT_HIT(); + DbpString("Starting to sniff"); + + // loop and listen + while (!BUTTON_PRESS()) { + WDT_HIT(); + LED_A_ON(); int register readBufDataP = data - dmaBuf; int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; - if (readBufDataP <= dmaBufDataP){ + if (readBufDataP <= dmaBufDataP) dataLen = dmaBufDataP - readBufDataP; - } else { + else dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; - } + // test for length of buffer - if(dataLen > maxDataLen) { + if (dataLen > maxDataLen) { maxDataLen = dataLen; - if(dataLen > (9 * DMA_BUFFER_SIZE / 10)) { + if (dataLen > (9 * DMA_BUFFER_SIZE / 10)) { Dbprintf("blew circular buffer! dataLen=%d", dataLen); break; } } - if(dataLen < 1) continue; + if (dataLen < 1) continue; // primary buffer was stopped( <-- we lost data! if (!AT91C_BASE_PDC_SSC->PDC_RCR) { @@ -596,9 +588,9 @@ void RAMFUNC SniffIso14443a(uint8_t param) { LED_A_OFF(); - if (rsamples & 0x01) { // Need two samples to feed Miller and Manchester-Decoder + if (rsamples & 0x01) { // Need two samples to feed Miller and Manchester-Decoder - if(!TagIsActive) { // no need to try decoding reader data if the tag is sending + if (!TagIsActive) { // no need to try decoding reader data if the tag is sending uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); if (MillerDecoding(readerdata, (rsamples-1)*4)) { LED_C_ON(); @@ -606,7 +598,7 @@ void RAMFUNC SniffIso14443a(uint8_t param) { // check - if there is a short 7bit request from reader if ((!triggered) && (param & 0x02) && (Uart.len == 1) && (Uart.bitCount == 7)) triggered = true; - if(triggered) { + if (triggered) { if (!LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, @@ -614,9 +606,9 @@ void RAMFUNC SniffIso14443a(uint8_t param) { Uart.parity, true)) break; } - /* And ready to receive another command. */ + /* ready to receive another command. */ UartReset(); - /* And also reset the demod code, which might have been */ + /* reset the demod code, which might have been */ /* false-triggered by the commands from the reader. */ DemodReset(); LED_B_OFF(); @@ -624,9 +616,10 @@ void RAMFUNC SniffIso14443a(uint8_t param) { ReaderIsActive = (Uart.state != STATE_UNSYNCD); } - if(!ReaderIsActive) { // no need to try decoding tag data if the reader is sending - and we cannot afford the time + // no need to try decoding tag data if the reader is sending - and we cannot afford the time + if (!ReaderIsActive) { uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); - if(ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) { + if (ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) { LED_B_ON(); if (!LogTrace(receivedResponse, @@ -638,9 +631,9 @@ void RAMFUNC SniffIso14443a(uint8_t param) { if ((!triggered) && (param & 0x01)) triggered = true; - // And ready to receive another response. + // ready to receive another response. DemodReset(); - // And reset the Miller decoder including itS (now outdated) input buffer + // reset the Miller decoder including its (now outdated) input buffer UartInit(receivedCmd, receivedCmdPar); LED_C_OFF(); } @@ -651,19 +644,16 @@ void RAMFUNC SniffIso14443a(uint8_t param) { previous_data = *data; rsamples++; data++; - if(data == dmaBuf + DMA_BUFFER_SIZE) { + if (data == dmaBuf + DMA_BUFFER_SIZE) { data = dmaBuf; } - } // main cycle + } // end main loop if (MF_DBGLEVEL >= 1) { Dbprintf("maxDataLen=%d, Uart.state=%x, Uart.len=%d", maxDataLen, Uart.state, Uart.len); Dbprintf("traceLen=%d, Uart.output[0]=%08x", BigBuf_get_traceLen(), (uint32_t)Uart.output[0]); } - FpgaDisableSscDma(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); + switch_off(); } //----------------------------------------------------------------------------- @@ -779,9 +769,9 @@ int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len) while (!BUTTON_PRESS()) { WDT_HIT(); - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - if(MillerDecoding(b, 0)) { + if (MillerDecoding(b, 0)) { *len = Uart.len; return true; } @@ -1050,11 +1040,11 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { tag_response_info_t* p_response; LED_A_ON(); - for(;;) { + for (;;) { WDT_HIT(); // Clean receive command buffer - if(!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { + if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); break; } @@ -1062,19 +1052,19 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { // Okay, look at the command now. lastorder = order; - if(receivedCmd[0] == ISO14443A_CMD_REQA) { // Received a REQUEST + if (receivedCmd[0] == ISO14443A_CMD_REQA) { // Received a REQUEST p_response = &responses[0]; order = 1; - } else if(receivedCmd[0] == ISO14443A_CMD_WUPA) { // Received a WAKEUP + } else if (receivedCmd[0] == ISO14443A_CMD_WUPA) { // Received a WAKEUP p_response = &responses[0]; order = 6; - } else if(receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received request for UID (cascade 1) + } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received request for UID (cascade 1) p_response = &responses[1]; order = 2; - } else if(receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received request for UID (cascade 2) + } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received request for UID (cascade 2) p_response = &responses[2]; order = 20; - } else if(receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1) + } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1) p_response = &responses[3]; order = 3; - } else if(receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2) + } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2) p_response = &responses[4]; order = 30; - } else if(receivedCmd[0] == ISO14443A_CMD_READBLOCK) { // Received a (plain) READ + } else if (receivedCmd[0] == ISO14443A_CMD_READBLOCK) { // Received a (plain) READ uint8_t block = receivedCmd[1]; // if Ultralight or NTAG (4 byte blocks) if ( tagType == 7 || tagType == 2 ) { @@ -1096,7 +1086,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { // We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below p_response = NULL; } - } else if(receivedCmd[0] == MIFARE_ULEV1_FASTREAD) { // Received a FAST READ (ranged read) + } else if (receivedCmd[0] == MIFARE_ULEV1_FASTREAD) { // Received a FAST READ (ranged read) uint8_t emdata[MAX_FRAME_SIZE]; // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] int start = (receivedCmd[1]+12) * 4; @@ -1105,7 +1095,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { AppendCrc14443a(emdata, len); EmSendCmd(emdata, len+2); p_response = NULL; - } else if(receivedCmd[0] == MIFARE_ULEV1_READSIG && tagType == 7) { // Received a READ SIGNATURE -- + } else if (receivedCmd[0] == MIFARE_ULEV1_READSIG && tagType == 7) { // Received a READ SIGNATURE -- // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] uint16_t start = 4 * 4; uint8_t emdata[34]; @@ -1149,7 +1139,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { } } p_response = NULL; - } else if(receivedCmd[0] == MIFARE_ULEV1_CHECKTEAR && tagType == 7) { // Received a CHECK_TEARING_EVENT -- + } else if (receivedCmd[0] == MIFARE_ULEV1_CHECKTEAR && tagType == 7) { // Received a CHECK_TEARING_EVENT -- // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] uint8_t emdata[3]; uint8_t index = receivedCmd[1]; @@ -1163,10 +1153,10 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { EmSendCmd(emdata, sizeof(emdata)); } p_response = NULL; - } else if(receivedCmd[0] == ISO14443A_CMD_HALT) { // Received a HALT + } else if (receivedCmd[0] == ISO14443A_CMD_HALT) { // Received a HALT LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); p_response = NULL; - } else if(receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) { // Received an authentication request + } else if (receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) { // Received an authentication request if ( tagType == 7 ) { // IF NTAG /EV1 0x60 == GET_VERSION, not a authentication request. uint8_t emdata[10]; emlGetMemBt( emdata, 0, 8 ); @@ -1190,7 +1180,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { //p_response = &responses[5]; order = 7; } - } else if(receivedCmd[0] == ISO14443A_CMD_RATS) { // Received a RATS request + } else if (receivedCmd[0] == ISO14443A_CMD_RATS) { // Received a RATS request if (tagType == 1 || tagType == 2) { // RATS not supported EmSend4bit(CARD_NACK_NA); p_response = NULL; @@ -1345,21 +1335,11 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { } // Count number of wakeups received after a halt - if(order == 6 && lastorder == 5) { happened++; } + if (order == 6 && lastorder == 5) { happened++; } // Count number of other messages after a halt - if(order != 6 && lastorder == 5) { happened2++; } + if (order != 6 && lastorder == 5) { happened2++; } - // comment this limit if you want to simulation longer - if (!tracing) { - DbpString("Trace Full. Simulation stopped."); - break; - } - // comment this limit if you want to simulation longer - if(cmdsRecvd > 999) { - DbpString("1000 commands later..."); - break; - } cmdsRecvd++; if (p_response != NULL) { @@ -1381,19 +1361,17 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { } } - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); + cmd_send(CMD_ACK,1,0,0,0,0); + switch_off(); + BigBuf_free_keep_EM(); - LED_A_OFF(); - + if (MF_DBGLEVEL >= 4){ Dbprintf("-[ Wake ups after halt [%d]", happened); Dbprintf("-[ Messages after halt [%d]", happened2); Dbprintf("-[ Num of received cmd [%d]", cmdsRecvd); Dbprintf("-[ Num of moebius tries [%d]", moebius_count); } - - cmd_send(CMD_ACK,1,0,0,0,0); } // prepare a delayed transfer. This simply shifts ToSend[] by a number @@ -1433,21 +1411,23 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); - uint32_t ThisTransferTime = 0; - if (timing) { - if(*timing == 0) { // Measure time + if (*timing == 0) // Measure time *timing = (GetCountSspClk() + 8) & 0xfffffff8; - } else { + else PrepareDelayedTransfer(*timing & 0x00000007); // Delay transfer (fine tuning - up to 7 MF clock ticks) - } - if(MF_DBGLEVEL >= 4 && GetCountSspClk() >= (*timing & 0xfffffff8)) Dbprintf("TransmitFor14443a: Missed timing"); - while(GetCountSspClk() < (*timing & 0xfffffff8)); // Delay transfer (multiple of 8 MF clock ticks) + + if(MF_DBGLEVEL >= 4 && GetCountSspClk() >= (*timing & 0xfffffff8)) + Dbprintf("TransmitFor14443a: Missed timing"); + while (GetCountSspClk() < (*timing & 0xfffffff8)) {}; // Delay transfer (multiple of 8 MF clock ticks) LastTimeProxToAirStart = *timing; } else { + + uint32_t ThisTransferTime = 0; + ThisTransferTime = ((MAX(NextTransferTime, GetCountSspClk()) & 0xfffffff8) + 8); - while(GetCountSspClk() < ThisTransferTime); + while (GetCountSspClk() < ThisTransferTime); LastTimeProxToAirStart = ThisTransferTime; } @@ -1455,13 +1435,11 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing // clear TXRDY AT91C_BASE_SSC->SSC_THR = SEC_Y; - uint16_t c = 0; - for(;;) { + uint16_t c = 0; + while (c < len) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = cmd[c]; c++; - if(c >= len) - break; } } @@ -3087,21 +3065,17 @@ void RAMFUNC SniffMifare(uint8_t param) { return; } + // Signal field is off with the appropriate LED LED_D_OFF(); MfSniffInit(); - - // And now we loop, receiving samples. - for(uint32_t sniffCounter = 0;; ) { - - LED_A_ON(); + + uint32_t sniffCounter = 0; + // loop and listen + while (!BUTTON_PRESS()) { WDT_HIT(); - - if(BUTTON_PRESS()) { - DbpString("cancelled by button"); - break; - } - + LED_A_ON(); + if ((sniffCounter & 0x0000FFFF) == 0) { // from time to time // check if a transaction is completed (timeout after 2000ms). // if yes, stop the DMA transfer and send what we have so far to the client @@ -3119,9 +3093,11 @@ void RAMFUNC SniffMifare(uint8_t param) { } } } - - int register readBufDataP = data - dmaBuf; // number of bytes we have processed so far - int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; // number of bytes already transferred + + // number of bytes we have processed so far + int register readBufDataP = data - dmaBuf; + // number of bytes already transferred + int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; if (readBufDataP <= dmaBufDataP) // we are processing the same block of data which is currently being transferred dataLen = dmaBufDataP - readBufDataP; // number of bytes still to be processed @@ -3155,21 +3131,21 @@ void RAMFUNC SniffMifare(uint8_t param) { if (sniffCounter & 0x01) { // no need to try decoding tag data if the reader is sending - if(!TagIsActive) { + if (!TagIsActive) { uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); if(MillerDecoding(readerdata, (sniffCounter-1)*4)) { LED_C_INV(); if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, true)) break; - UartInit(receivedCmd, receivedCmdPar); DemodReset(); + UartInit(receivedCmd, receivedCmdPar); } ReaderIsActive = (Uart.state != STATE_UNSYNCD); } // no need to try decoding tag data if the reader is sending - if(!ReaderIsActive) { + if (!ReaderIsActive) { uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); if(ManchesterDecoding(tagdata, 0, (sniffCounter-1)*4)) { LED_C_INV(); @@ -3192,11 +3168,9 @@ void RAMFUNC SniffMifare(uint8_t param) { } // main cycle - if (MF_DBGLEVEL >= 1) Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.len=%x", maxDataLen, Uart.state, Uart.len); + if (MF_DBGLEVEL >= 1) + Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.len=%x", maxDataLen, Uart.state, Uart.len); - FpgaDisableSscDma(); MfSniffEnd(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); + switch_off(); } diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 4c479561b..6441b4844 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -71,7 +71,7 @@ typedef struct { uint16_t shiftReg; int16_t bitCount; uint16_t len; - uint16_t byteCntMax; + //uint16_t byteCntMax; uint16_t posCnt; uint16_t syncBit; uint8_t parityBits; diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 729bdfc72..302709bb1 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -45,13 +45,11 @@ static void iso14b_set_timeout(uint32_t timeout); static void iso14b_set_maxframesize(uint16_t size); -static void switch_off(void); // the block number for the ISO14443-4 PCB (used with APDUs) static uint8_t pcb_blocknum = 0; static uint32_t iso14b_timeout = FWT_TIMEOUT_14B; - //============================================================================= // An ISO 14443 Type B tag. We listen for commands from the reader, using // a UART kind of thing that's implemented in software. When we get a @@ -170,14 +168,6 @@ static void iso14b_set_maxframesize(uint16_t size) { Uart.byteCntMax = size; if(MF_DBGLEVEL >= 3) Dbprintf("ISO14443B Max frame size set to %d bytes", Uart.byteCntMax); } -static void switch_off(void){ - if (MF_DBGLEVEL > 3) Dbprintf("switch_off"); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(100); - FpgaDisableSscDma(); - set_tracing(false); - LEDsoff(); -} void AppendCrc14443b(uint8_t* data, int len) { ComputeCrc14443(CRC_14443_B, data, len, data+len, data+len+1); @@ -543,8 +533,7 @@ static void TransmitFor14443b_AsTag( uint8_t *response, uint16_t len) { AT91C_BASE_SSC->SSC_THR = response[++i]; } if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - b = AT91C_BASE_SSC->SSC_RHR; - (void)b; + b = AT91C_BASE_SSC->SSC_RHR;(void)b; } } @@ -560,18 +549,18 @@ void SimulateIso14443bTag(uint32_t pupi) { ///////////// setup device. FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - // allocate command receive buffer - BigBuf_free(); - BigBuf_Clear_ext(false); - clear_trace(); //sim - set_tracing(true); - // connect Demodulated Signal to ADC: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); // Set up the synchronous serial port FpgaSetupSsc(); ///////////// + + // allocate command receive buffer + BigBuf_free(); + BigBuf_Clear_ext(false); + clear_trace(); //sim + set_tracing(true); uint16_t len, cmdsReceived = 0; int cardSTATE = SIM_NOFIELD; @@ -712,13 +701,9 @@ void SimulateIso14443bTag(uint32_t pupi) { } ++cmdsReceived; - // iceman, could add a switch to turn this on/off (if off, no logging?) - if(cmdsReceived > 1000) { - DbpString("14B Simulate, 1000 commands later..."); - break; - } } - if (MF_DBGLEVEL >= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); + if (MF_DBGLEVEL >= 2) + Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); switch_off(); //simulate } @@ -1022,7 +1007,6 @@ static void GetTagSamplesFor14443bDemod() { LogTrace(Demod.output, Demod.len, time_0, time_stop, NULL, false); } - //----------------------------------------------------------------------------- // Transmit the command (to the tag) that was placed in ToSend[]. //----------------------------------------------------------------------------- @@ -1382,17 +1366,16 @@ void iso14443b_setup() { //----------------------------------------------------------------------------- void ReadSTMemoryIso14443b(uint8_t numofblocks) { - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - // Make sure that we start from off, since the tags are stateful; // confusing things will happen if we don't reset them between reads. - switch_off(); // before ReadStMemory + switch_off(); + + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); set_tracing(true); - uint8_t i = 0x00; - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaSetupSsc(); // Now give it time to spin up. @@ -1400,6 +1383,8 @@ void ReadSTMemoryIso14443b(uint8_t numofblocks) LED_D_ON(); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ); SpinDelay(20); + + uint8_t i = 0x00; // First command: wake up the tag using the INITIATE command uint8_t cmd1[] = {ISO14443B_INITIATE, 0x00, 0x97, 0x5b}; @@ -1673,12 +1658,13 @@ void RAMFUNC SnoopIso14443b(void) { } } - switch_off(); // Snoop + switch_off(); - DbpString("Snoop statistics:"); - Dbprintf(" Uart State: %x ByteCount: %i ByteCountMax: %i", Uart.state, Uart.byteCnt, Uart.byteCntMax); - Dbprintf(" Trace length: %i", BigBuf_get_traceLen()); - + if (MF_DBGLEVEL >= 2) { + DbpString("Snoop statistics:"); + Dbprintf(" Uart State: %x ByteCount: %i ByteCountMax: %i", Uart.state, Uart.byteCnt, Uart.byteCntMax); + Dbprintf(" Trace length: %i", BigBuf_get_traceLen()); + } // free mem refs. if ( upTo ) upTo = NULL; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 83d7aef55..b7ae8b433 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -598,6 +598,109 @@ int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) { (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0; } +#define AUTHENTICATION_TIMEOUT 848 //848 // card times out 1ms after wrong authentication (according to NXP documentation) +#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication + +void MifareAcquireNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain) { + + uint32_t cuid = 0; + uint8_t uid[10] = {0x00}; + uint8_t cascade_levels = 0; + uint8_t answer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t par[1] = {0x00}; + int16_t isOK = 0; + uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; + uint32_t timeout = 0; + uint8_t blockNo = arg0 & 0xff; + uint8_t keyType = (arg0 >> 8) & 0xff; + bool initialize = flags & 0x0001; + bool field_off = flags & 0x0004; + + LED_A_ON(); + LED_C_OFF(); + + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); + + if (initialize) { + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + } + + LED_C_ON(); + + uint8_t dummy_answer = 0; + uint16_t num_nonces = 0; + bool have_uid = false; + for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE-4; i += 4 ) { + + // Test if the action was cancelled + if(BUTTON_PRESS()) { + isOK = 2; + field_off = true; + break; + } + + if (!have_uid) { // need a full select cycle to get the uid first + iso14a_card_select_t card_info; + if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); + continue; + } + switch (card_info.uidlen) { + case 4 : cascade_levels = 1; break; + case 7 : cascade_levels = 2; break; + case 10: cascade_levels = 3; break; + default: break; + } + have_uid = true; + } else { // no need for anticollision. We can directly select the card + if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); + continue; + } + } + + // Transmit MIFARE_CLASSIC_AUTH + uint8_t dcmd[4] = {0x60 + (keyType & 0x01), blockNo, 0x00, 0x00}; + AppendCrc14443a(dcmd, 2); + ReaderTransmit(dcmd, sizeof(dcmd), NULL); + int len = ReaderReceive(answer, par); + + // send a dummy byte as reader response in order to trigger the cards authentication timeout + ReaderTransmit(&dummy_answer, 1, NULL); + timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT; + + if (len != 4) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error"); + continue; + } + + num_nonces++; + + // Save the tag nonce (nt) + buf[i] = answer[0]; + buf[i+1] = answer[1]; + buf[i+2] = answer[2]; + buf[i+3] = answer[3]; + + // wait for the card to become ready again + while (GetCountSspClk() < timeout) {}; + } + + LED_C_OFF(); + LED_B_ON(); + cmd_send(CMD_ACK, isOK, cuid, num_nonces-1, buf, sizeof(buf)); + LED_B_OFF(); + + if (MF_DBGLEVEL >= 3) DbpString("AcquireNonces finished"); + + if (field_off) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); + } +} //----------------------------------------------------------------------------- // acquire encrypted nonces in order to perform the attack described in @@ -605,8 +708,6 @@ int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) { // Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on // Computer and Communications Security, 2015 //----------------------------------------------------------------------------- -#define AUTHENTICATION_TIMEOUT 848 //848 // card times out 1ms after wrong authentication (according to NXP documentation) -#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain) { @@ -691,15 +792,16 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, // nested authentication uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL); + + // send a dummy byte as reader response in order to trigger the cards authentication timeout + ReaderTransmit(&dummy_answer, 1, NULL); + timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT; + if (len != 4) { if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len); continue; } - // send a dummy byte as reader response in order to trigger the cards authentication timeout - ReaderTransmit(&dummy_answer, 1, NULL); - timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT; - num_nonces++; if (num_nonces % 2) { memcpy(buf+i, receivedAnswer, 4); @@ -1019,7 +1121,7 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT; // wait for the card to become ready again - while(GetCountSspClk() < timeout); + while(GetCountSspClk() < timeout) {}; continue; } diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index b1e72bb7e..b71ab2305 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -556,9 +556,7 @@ void OnSuccess(){ pcb_blocknum = 0; ReaderTransmit(deselect_cmd, 3 , NULL); mifare_ultra_halt(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); + switch_off(); } void OnError(uint8_t reason){ diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index f4c447569..7f6bb936e 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -193,7 +193,7 @@ int usage_hf_iclass_replay(void) { PrintAndLog(" hf iclass replay 00112233"); return 0; } -int usage_hf_iclass_snoop(void) { +int usage_hf_iclass_sniff(void) { PrintAndLog("HELP: Snoops the communication between reader and tag"); PrintAndLog("Usage: hf iclass snoop [h]"); PrintAndLog("Samples:"); @@ -230,10 +230,9 @@ int CmdHFiClassList(const char *Cmd) { return 0; } -int CmdHFiClassSnoop(const char *Cmd) { +int CmdHFiClassSniff(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_hf_iclass_snoop(); - + if (cmdp == 'h' || cmdp == 'H') return usage_hf_iclass_sniff(); UsbCommand c = {CMD_SNOOP_ICLASS}; SendCommand(&c); return 0; @@ -263,7 +262,7 @@ int CmdHFiClassSim(const char *Cmd) { uint8_t numberOfCSNs = 0; if (simType == 2) { - UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}}; + UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType, NUM_CSNS}}; UsbCommand resp = {0}; /* @@ -325,7 +324,7 @@ int CmdHFiClassSim(const char *Cmd) { } uint8_t num_mac_responses = resp.arg[1]; - PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS); + PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses, NUM_CSNS); size_t datalen = NUM_CSNS*24; /* @@ -351,7 +350,7 @@ int CmdHFiClassSim(const char *Cmd) { saveFile("iclass_mac_attack", "bin", dump, datalen); free(dump); } else { - UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}}; + UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType, numberOfCSNs}}; memcpy(c.d.asBytes, CSN, 8); clearCommandBuffer(); SendCommand(&c); @@ -392,7 +391,10 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) { } if (readStatus & FLAG_ICLASS_READER_AA) { bool legacy = true; - PrintAndLog(" AppIA: %s",sprint_hex(data+8*5,8)); + PrintAndLog(" AppIA: %s", sprint_hex(data+8*5,8)); + + //if ( memcmp(data+8*5, '\xff\xff\xff\xff\xff\xff\xff\xff',8) != 0 ) + // legacy = false; for (int i = 0; i<8; i++) { if (data[8*5+i] != 0xFF) { legacy = false; @@ -1731,7 +1733,7 @@ static command_t CommandTable[] = { {"readtagfile", CmdHFiClassReadTagFile, 1, "[options..] Display Content from tagfile"}, {"replay", CmdHFiClassReader_Replay, 0, " Read an iClass tag via Reply Attack"}, {"sim", CmdHFiClassSim, 0, "[options..] Simulate iClass tag"}, - {"snoop", CmdHFiClassSnoop, 0, " Eavesdrop iClass communication"}, + {"sniff", CmdHFiClassSniff, 0, " Eavesdrop iClass communication"}, {"writeblk", CmdHFiClass_WriteBlock, 0, "[options..] Authenticate and Write iClass block"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdhficlass.h b/client/cmdhficlass.h index a6740c7a5..e596e3417 100644 --- a/client/cmdhficlass.h +++ b/client/cmdhficlass.h @@ -8,7 +8,6 @@ //----------------------------------------------------------------------------- // High frequency iClass support //----------------------------------------------------------------------------- - #ifndef CMDHFICLASS_H__ #define CMDHFICLASS_H__ @@ -55,10 +54,11 @@ extern int CmdHFiClass_ReadBlock(const char *Cmd); extern int CmdHFiClass_TestMac(const char *Cmd); extern int CmdHFiClassManageKeys(const char *Cmd); extern int CmdHFiClass_loclass(const char *Cmd); -extern int CmdHFiClassSnoop(const char *Cmd); +extern int CmdHFiClassSniff(const char *Cmd); extern int CmdHFiClassSim(const char *Cmd); extern int CmdHFiClassWriteKeyFile(const char *Cmd); extern int CmdHFiClass_WriteBlock(const char *Cmd); + void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize); void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite); #endif diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index ba92922fe..b2dffca0a 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1100,14 +1100,16 @@ int CmdHF14AMfNestedHard(const char *Cmd) { } } - uint64_t key64 = 0; - // check if we can authenticate to sector - int res = mfCheckKeys(blockNo, keyType, true, 1, key, &key64); - if (res) { - PrintAndLog("Key is wrong. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A'); - return 3; - } - + if ( !know_target_key ) { + uint64_t key64 = 0; + // check if we can authenticate to sector + int res = mfCheckKeys(blockNo, keyType, true, 1, key, &key64); + if (res) { + PrintAndLog("Key is wrong. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A'); + return 3; + } + } + PrintAndLog("--target block no:%3d, target key type:%c, known target key: 0x%02x%02x%02x%02x%02x%02x%s, file action: %s, Slow: %s, Tests: %d ", trgBlockNo, trgKeyType?'B':'A', @@ -2444,7 +2446,7 @@ int CmdHF14AMfCSave(const char *Cmd) { } //needs nt, ar, at, Data to decrypt -int CmdHf14MfDecryptBytes(const char *Cmd){ +int CmdHf14AMfDecryptBytes(const char *Cmd){ uint8_t data[50]; uint32_t nt = param_get32ex(Cmd,0,0,16); uint32_t ar_enc = param_get32ex(Cmd,1,0,16); @@ -2498,6 +2500,83 @@ int CmdHf14AMfSetMod(const char *Cmd) { return 0; } +int CmdHF14AMfice(const char *Cmd) { + + uint8_t blockNo = 0; + uint8_t keyType = 0; + uint8_t trgBlockNo = 0; + uint8_t trgKeyType = 1; + bool slow = false; + bool initialize = true; + bool acquisition_completed = false; + uint32_t flags = 0; + uint32_t total_num_nonces = 0; + FILE *fnonces = NULL; + UsbCommand resp; + + uint32_t part_limit = 3000; + uint32_t limit = param_get32ex(Cmd, 0, 50000, 10); + + printf("Collecting %u nonces \n", limit); + + if ((fnonces = fopen("nonces.bin","wb")) == NULL) { + PrintAndLog("Could not create file nonces.bin"); + return 3; + } + + clearCommandBuffer(); + + uint64_t t1 = msclock(); + + do { + if (ukbhit()) { + int gc = getchar(); (void)gc; + printf("\naborted via keyboard!\n"); + break; + } + + flags = 0; + flags |= initialize ? 0x0001 : 0; + flags |= slow ? 0x0002 : 0; + UsbCommand c = {CMD_MIFARE_ACQUIRE_NONCES, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags}}; + clearCommandBuffer(); + SendCommand(&c); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) goto out; + if (resp.arg[0]) goto out; + + uint32_t items = resp.arg[2]; + if (fnonces) { + fwrite(resp.d.asBytes, 1, items*4, fnonces); + fflush(fnonces); + } + + total_num_nonces += items; + if ( total_num_nonces > part_limit ) { + printf("Total nonces %u\n", total_num_nonces); + part_limit += 3000; + } + + acquisition_completed = ( total_num_nonces > limit); + + initialize = false; + + } while (!acquisition_completed); + +out: + printf("time: %" PRIu64 " seconds\n", (msclock()-t1)/1000); + + if ( fnonces ) { + fflush(fnonces); + fclose(fnonces); + } + + UsbCommand c = {CMD_MIFARE_ACQUIRE_NONCES, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, 4}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, @@ -2526,8 +2605,9 @@ static command_t CommandTable[] = { {"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"}, {"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"}, {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"}, - {"decrypt", CmdHf14MfDecryptBytes, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"}, + {"decrypt", CmdHf14AMfDecryptBytes, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"}, {"setmod", CmdHf14AMfSetMod, 0, "Set MIFARE Classic EV1 load modulation strength"}, + {"ice", CmdHF14AMfice, 0, "collect Mifare Classic nonces to file"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 687f12513..01420b96b 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -119,7 +119,7 @@ void hardnested_print_progress(uint32_t nonces, char *activity, float brute_forc } else { sprintf(brute_force_time_string, "%2.0fd", brute_force_time/(60*60*24)); } - PrintAndLog(" %7.0f | %7d | %-55s | %15.0f | %5s", (float)total_time/1000.0, nonces, activity, brute_force, brute_force_time_string); + PrintAndLog(" %7.0f | %7u | %-55s | %15.0f | %5s", (float)total_time/1000.0, nonces, activity, brute_force, brute_force_time_string); } } diff --git a/common/protocols.h b/common/protocols.h index 02c20de59..20752cad5 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -119,19 +119,26 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. 90 00 = OK 6x xx = ERROR */ - -#define ICLASS_CMD_ACTALL 0x0A -#define ICLASS_CMD_READ_OR_IDENTIFY 0x0C -#define ICLASS_CMD_SELECT 0x81 -#define ICLASS_CMD_PAGESEL 0x84 -#define ICLASS_CMD_READCHECK_KD 0x88 -#define ICLASS_CMD_READCHECK_KC 0x18 -#define ICLASS_CMD_CHECK 0x05 -#define ICLASS_CMD_DETECT 0x0F +// these cmds are adjusted to ISO15693 and Manchester encoding requests. +// for instance ICLASS_CMD_SELECT 0x81 tells if ISO14443b/BPSK coding/106 kbits/s +// for instance ICLASS_CMD_SELECT 0x41 tells if ISO14443b/BPSK coding/423 kbits/s +// #define ICLASS_CMD_HALT 0x00 -#define ICLASS_CMD_UPDATE 0x87 -#define ICLASS_CMD_ACT 0x8E +#define ICLASS_CMD_SELECT_15 0x01 +#define ICLASS_CMD_ACTALL 0x0A +#define ICLASS_CMD_DETECT 0x0F + +#define ICLASS_CMD_CHECK 0x05 #define ICLASS_CMD_READ4 0x06 +#define ICLASS_CMD_READ_OR_IDENTIFY 0x0C + +#define ICLASS_CMD_SELECT 0x81 +#define ICLASS_CMD_PAGESEL 0x84 +#define ICLASS_CMD_UPDATE 0x87 +#define ICLASS_CMD_READCHECK_KC 0x18 +#define ICLASS_CMD_READCHECK_KD 0x88 +#define ICLASS_CMD_ACT 0x8E + #define ISO14443A_CMD_REQA 0x26 diff --git a/include/usb_cmd.h b/include/usb_cmd.h index b2189ef27..88f8652bf 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -190,6 +190,7 @@ typedef struct{ #define CMD_READER_MIFARE 0x0611 #define CMD_MIFARE_NESTED 0x0612 #define CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES 0x0613 +#define CMD_MIFARE_ACQUIRE_NONCES 0x0614 #define CMD_MIFARE_READBL 0x0620 #define CMD_MIFAREU_READBL 0x0720