diff --git a/armsrc/Makefile b/armsrc/Makefile index d70008e0c..55699b564 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -1,4 +1,4 @@ -#----------------------------------------------------------------------------- + # This code is licensed to you under the terms of the GNU GPL, version 2 or, # at your option, any later version. See the LICENSE.txt file for the text of # the license. diff --git a/armsrc/Makefile.colin b/armsrc/Makefile.colin new file mode 100644 index 000000000..fb2a2a91b --- /dev/null +++ b/armsrc/Makefile.colin @@ -0,0 +1,183 @@ +#----------------------------------------------------------------------------- +# This code is licensed to you under the terms of the GNU GPL, version 2 or, +# at your option, any later version. See the LICENSE.txt file for the text of +# the license. +#----------------------------------------------------------------------------- +# Makefile for armsrc, see ../common/Makefile.common for common settings +#----------------------------------------------------------------------------- + +APP_INCLUDES = apps.h + +#remove one of the following defines and comment out the relevant line +#in the next section to remove that particular feature from compilation. +# NO space,TABs after the "\" sign. +APP_CFLAGS = -DWITH_CRC \ + -DON_DEVICE \ + -DWITH_LF \ + -DWITH_HITAG \ + -DWITH_ISO15693 \ + -DWITH_LEGICRF \ + -DWITH_ISO14443b \ + -DWITH_ISO14443a \ + -DWITH_ICLASS \ + -DWITH_FELICA \ + -DWITH_FLASH \ + -DWITH_SMARTCARD \ + -DWITH_HFSNOOP \ + -DWITH_HF_COLIN \ + -fno-strict-aliasing -ffunction-sections -fdata-sections + +### IMPORTANT - move the commented variable below this line +# -DWITH_LCD \ +# -DWITH_EMV \ +# -DWITH_FPC \ +# +# Standalone Mods +#------------------------------------------------------- +# -DWITH_LF_ICERUN +# -DWITH_LF_SAMYRUN +# -DWITH_LF_PROXBRUTE +# -DWITH_LF_HIDBRUTE +# -DWITH_HF_YOUNG +# -DWITH_HF_MATTYRUN +# -DWITH_HF_COLIN + + +SRC_LCD = fonts.c LCD.c +SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c +SRC_ISO15693 = iso15693.c iso15693tools.c +#SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c +SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c +SRC_ISO14443b = iso14443b.c +SRC_FELICA = felica.c +SRC_CRAPTO1 = crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c +SRC_CRC = crc.c crc16.c crc32.c +SRC_ICLASS = iclass.c optimized_cipher.c +SRC_LEGIC = legicrf.c legic_prng.c +SRC_FLASH = flashmem.c +SRC_SMARTCARD = i2c.c +#SRC_FPC = usart.c +SRC_BEE = bee.c + +#the FPGA bitstream files. Note: order matters! +FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit + +#the zlib source files required for decompressing the fpga config at run time +SRC_ZLIB = inflate.c inffast.c inftrees.c adler32.c zutil.c +#additional defines required to compile zlib +ZLIB_CFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED +APP_CFLAGS += $(ZLIB_CFLAGS) +# zlib includes: +APP_CFLAGS += -I../zlib + +# stdint.h provided locally until GCC 4.5 becomes C99 compliant +APP_CFLAGS += -I. + +# Compile these in thumb mode (small size) +THUMBSRC = start.c \ + protocols.c \ + $(SRC_LCD) \ + $(SRC_ISO15693) \ + $(SRC_LF) \ + $(SRC_ZLIB) \ + $(SRC_LEGIC) \ + $(SRC_FLASH) \ + $(SRC_SMARTCARD) \ + $(SRC_FPC) \ + appmain.c \ + printf.c \ + util.c \ + string.c \ + BigBuf.c \ + ticks.c \ + random.c \ + hfsnoop.c + + +# These are to be compiled in ARM mode +ARMSRC = fpgaloader.c \ + $(SRC_ISO14443a) \ + $(SRC_ISO14443b) \ + $(SRC_CRAPTO1) \ + $(SRC_ICLASS) \ + $(SRC_EMV) \ + $(SRC_CRC) \ + $(SRC_FELICA) \ + parity.c \ + usb_cdc.c \ + cmd.c \ + vtsend.c \ + hf_colin.c \ + lib_AT91SAM7.c + +VERSIONSRC = version.c \ + fpga_version_info.c + +# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC +include ../common/Makefile.common + +COMMON_FLAGS = -Os +OBJS = $(OBJDIR)/fullimage.s19 +FPGA_COMPRESSOR = ../client/fpga_compress + +all: $(OBJS) + +.DELETE_ON_ERROR: + +# version.c should be remade on every compilation +.PHONY: version.c +version.c: default_version.c + perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@ + +fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) + $(FPGA_COMPRESSOR) -v $(filter %.bit,$^) $@ + +$(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z + $(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@ + +$(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) + $(FPGA_COMPRESSOR) $(filter %.bit,$^) $@ + +$(FPGA_COMPRESSOR): + make -C ../client $(notdir $(FPGA_COMPRESSOR)) + +$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) + $(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS) + +$(OBJDIR)/fullimage.nodata.bin: $(OBJDIR)/fullimage.stage1.elf + $(OBJCOPY) -O binary -I elf32-littlearm --remove-section .data $^ $@ + +$(OBJDIR)/fullimage.nodata.o: $(OBJDIR)/fullimage.nodata.bin + $(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=stage1_image $^ $@ + +$(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf + $(OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@ + +$(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin $(FPGA_COMPRESSOR) + $(FPGA_COMPRESSOR) $(filter %.bin,$^) $@ + +$(OBJDIR)/fullimage.data.o: $(OBJDIR)/fullimage.data.bin.z + $(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@ + +$(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o + $(CC) $(LDFLAGS) -Wl,-T,ldscript,-e,_osimage_entry,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ + +tarbin: $(OBJS) + $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf) + +clean: + $(DELETE) $(OBJDIR)$(PATHSEP)*.o + $(DELETE) $(OBJDIR)$(PATHSEP)*.elf + $(DELETE) $(OBJDIR)$(PATHSEP)*.s19 + $(DELETE) $(OBJDIR)$(PATHSEP)*.map + $(DELETE) $(OBJDIR)$(PATHSEP)*.d + $(DELETE) $(OBJDIR)$(PATHSEP)*.z + $(DELETE) $(OBJDIR)$(PATHSEP)*.bin + $(DELETE) version.c + +.PHONY: all clean help +help: + @echo Multi-OS Makefile, you are running on $(DETECTED_OS) + @echo Possible targets: + @echo + all - Build the full image $(OBJDIR)/fullimage.s19 + @echo + clean - Clean $(OBJDIR) diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 1ba31a9c7..f19706af1 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -12,8 +12,6 @@ #define MF1KSZ 1024 #define MF1KSZSIZE 64 -//#define FALSE false -//#define TRUE true #define AUTHENTICATION_TIMEOUT 848 uint8_t cjuid[10]; @@ -27,58 +25,349 @@ int curlline; // Colin's VIGIKPWN sniff/simulate/clone repeat routine for HF Mifare -void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug) { +void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug) +{ uint32_t chunksize = (USB_CMD_DATA_SIZE / 4); uint8_t totalchunks = len / chunksize; uint8_t last_chunksize = len - (totalchunks * chunksize); char chunk[chunksize + 1]; memset(chunk, 0x00, sizeof(chunk)); - if (debug > 0) { + if (debug > 0) + { Dbprintf("len : %d", len); Dbprintf("chunksize : %d bytes", chunksize); Dbprintf("totalchunks : %d", totalchunks); Dbprintf("last_chunksize: %d", last_chunksize); } - for (uint8_t i = 0; i < totalchunks; i++) { + for (uint8_t i = 0; i < totalchunks; i++) + { memset(chunk, 0x00, sizeof(chunk)); memcpy(chunk, &bigar[i * chunksize], chunksize); DbprintfEx(FLAG_RAWPRINT, "%s", chunk); } - if (last_chunksize > 0) { + if (last_chunksize > 0) + { memset(chunk, 0x00, sizeof(chunk)); memcpy(chunk, &bigar[totalchunks * chunksize], last_chunksize); DbprintfEx(FLAG_RAWPRINT, "%s", chunk); } - if (newlines > 0) { + if (newlines > 0) + { DbprintfEx(FLAG_NOLOG, " "); } } -void cjSetCursFRight() { +void cjSetCursFRight() +{ vtsend_cursor_position(NULL, 98, (currfline)); currfline++; } -void cjSetCursRight() { +void cjSetCursRight() +{ vtsend_cursor_position(NULL, 59, (currline)); currline++; } -void cjSetCursLeft() { +void cjSetCursLeft() +{ vtsend_cursor_position(NULL, 0, (curlline)); curlline++; } void cjTabulize() { DbprintfEx(FLAG_RAWPRINT, "\t\t\t"); } -void cjPrintKey(uint64_t key, uint8_t *foundKey, uint16_t sectorNo, uint8_t type) { +void cjPrintKey(uint64_t key, uint8_t *foundKey, uint16_t sectorNo, uint8_t type) +{ char tosendkey[13]; sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[0], foundKey[1], foundKey[2], foundKey[3], foundKey[4], foundKey[5]); cjSetCursRight(); DbprintfEx(FLAG_NOLOG, "SEC: %02x | KEY : %s | TYP: %d", sectorNo, tosendkey, type); } -void RunMod() { +void SpinOff(uint32_t pause) +{ + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); + SpinDelay(pause); +} + +// 0=A, 1=B, 2=C, 3=D +void SpinErr(uint8_t led, uint32_t speed, uint8_t times) +{ + SpinOff(speed); + NTIME(times) + { + switch (led) + { + case 0: + LED_A_INV(); + break; + case 1: + LED_B_INV(); + break; + case 2: + LED_C_INV(); + break; + case 3: + LED_D_INV(); + break; + } + SpinDelay(speed); + } +} + +void SpinDown(uint32_t speed) +{ + SpinOff(speed); + LED_D_ON(); + SpinDelay(speed); + LED_D_OFF(); + LED_C_ON(); + SpinDelay(speed); + LED_C_OFF(); + LED_B_ON(); + SpinDelay(speed); + LED_B_OFF(); + LED_A_ON(); + SpinDelay(speed); + LED_A_OFF(); +} + +void SpinUp(uint32_t speed) +{ + SpinOff(speed); + LED_A_ON(); + SpinDelay(speed); + LED_A_OFF(); + LED_B_ON(); + SpinDelay(speed); + LED_B_OFF(); + LED_C_ON(); + SpinDelay(speed); + LED_C_OFF(); + LED_D_ON(); + SpinDelay(speed); + LED_D_OFF(); +} + +void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate) +{ + + FLASHMEM_SPIBAUDRATE = spibaudrate*1000000; + DbprintfEx(FLAG_NOLOG, "%s---+----[ %s %s[%dKB] %s] (%d)", _GREEN_, _WHITE_, _YELLOW_, buffersize / 1024, _WHITE_, FLASHMEM_SPIBAUDRATE); + uint16_t t = 0; + + LED_B_ON(); + uint8_t *mem = BigBuf_malloc(buffersize); + bool isok = false; + size_t len = 0; + uint32_t startidx = 0; + uint32_t numofbytes = 0x3FFFF; + + if (!FlashInit()) { + return; + } + //Flash_CheckBusy(BUSY_TIMEOUT); + + //Flash_ReadStat1(); + + uint32_t end_time; + uint32_t start_time = end_time = GetTickCount(); + + for (size_t i = 0; i < numofbytes; i += buffersize) + { + len = MIN((numofbytes - i), buffersize); + + //isok = Flash_ReadData(startidx + i, mem, len); + //uint32_t iend_time; + //uint32_t istart_time = iend_time = GetTickCount(); + isok = Flash_ReadDataCont(startidx + i, mem, len); + //iend_time = GetTickCount(); + //DbprintfEx(FLAG_RAWPRINT, "%s%dms%s>", _YELLOW_, iend_time - istart_time, _WHITE_); + //cjSetCursLeft(); + if (!isok) + { + Dbprintf("[FAIL] reading flash memory failed :: | bytes between %d - %d", i, len); + return; + } + //isok = cmd_send(CMD_FLASHMEM_DOWNLOADED, i, len, 0, mem, len); + //if (!isok) + // Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); + t++; + } + end_time = GetTickCount(); + DbprintfEx(FLAG_NOLOG, "%s |--< %s %s%dms%s for FULL_FLASH_READ", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_); + DbprintfEx(FLAG_NOLOG, "%s `--= %s %d runs of %s~%dms%s each", _GREEN_, _WHITE_, t, _YELLOW_, (end_time - start_time) / t, _WHITE_); + DbprintfEx(FLAG_NOLOG, ""); + //cjSetCursLeft(); + LED_B_OFF(); + FlashStop(); +} + +void TestFlashmemRoutine() +{ + DbprintfEx(FLAG_NOLOG, "%s>>%s Will Now Test dumping Full flash [256Kb] (2Mbits)through Bigbuf buffers\n", _GREEN_, _WHITE_); + MF_DBGLEVEL = MF_DBG_NONE; + //DbprintfEx(FLAG_NOLOG, "---------\n%s[A]%s Using NORMAL Reads @Max (24Mhz=MCK/2)\n--------", _GREEN_, _WHITE_); + TestFlashmemSpeed(32768,24); + TestFlashmemSpeed(16384 + 4096 + 4096,24); + TestFlashmemSpeed(16384,24); + TestFlashmemSpeed(4096,24); + TestFlashmemSpeed(1024,24); + //SpinDelay(1000); + //WDT_HIT(); + //DbprintfEx(FLAG_NOLOG, "--------\n%s[B]%s Using FAST Reads @Max (48Mhz=MCK=CPUClock/2=MAXSPI)\n--------", _GREEN_, _WHITE_); + TestFlashmemSpeed(32768,48); + TestFlashmemSpeed(16384 + 4096 + 4096,48); + TestFlashmemSpeed(16384,48); + TestFlashmemSpeed(4096,48); + TestFlashmemSpeed(1024,48); + //SpinDelay(1000); + //WDT_HIT(); + return; +} + +void ReadLastTagFromFlash() +{ + + SpinOff(0); + LED_A_ON(); + LED_B_ON(); + LED_C_ON(); + LED_D_ON(); + uint16_t isok = 0; + uint32_t startidx = 0; + uint16_t len = 1024; + + DbprintfEx(FLAG_NOLOG, "Button HELD ! Using LAST Known TAG for Simulation..."); + cjSetCursLeft(); + + size_t size = len; + uint8_t *mem = BigBuf_malloc(size); + + if (!FlashInit()) + { + return; + } + Flash_CheckBusy(BUSY_TIMEOUT); + + //Flash_ReadStat1(); + + uint32_t end_time; + uint32_t start_time = end_time = GetTickCount(); + + for (size_t i = 0; i < len; i += size) + { + len = MIN((len - i), size); + + // isok = Flash_FastReadDataCont(startidx + i, mem, len); + isok = Flash_ReadDataCont(startidx + i, mem, len); + if (isok == len) + { + //print_result("Chunk: ", mem, len); + emlSetMem(mem, 0, 64); + } + else + { + DbprintfEx(FLAG_NOLOG, "FlashMem reading failed | %d | %d", len, isok); + cjSetCursLeft(); + FlashStop(); + SpinOff(100); + return; + } + } + end_time = GetTickCount(); + DbprintfEx(FLAG_NOLOG, "[OK] Last tag recovered from FLASHMEM set to emulator"); + cjSetCursLeft(); + DbprintfEx(FLAG_NOLOG, "%s[IN]%s %s%dms%s for TAG_FLASH_READ", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_); + cjSetCursLeft(); + FlashStop(); + SpinOff(0); + return; +} + +void WriteTagToFlash(uint8_t index, size_t size) +{ + + SpinOff(0); + LED_A_ON(); + LED_B_ON(); + LED_C_ON(); + LED_D_ON(); + + uint8_t isok = 0; + uint16_t res = 0; + uint32_t len = size; + uint32_t bytes_sent = 0; + uint32_t bytes_remaining = len; + + uint8_t data[(size * (16 * 64))/1024]; + uint8_t buff[PAGESIZE]; + // cnt = 0; + emlGetMem(data, 0, (size * 64)/1024); + + //if (!FlashFastReadInit()){ + if (!FlashInit()) + { + return; + } + + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + Flash_Erase4k(0,0); + + uint32_t end_time; + uint32_t start_time = end_time = GetTickCount(); + + while (bytes_remaining > 0) + { + + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + + uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); + + memcpy(buff, data + bytes_sent, bytes_in_packet); + + bytes_remaining -= bytes_in_packet; + res = Flash_WriteDataCont(bytes_sent + (index * size), buff, bytes_in_packet); + bytes_sent += bytes_in_packet; + + isok = (res == bytes_in_packet) ? 1 : 0; + + if (!isok) + { + DbprintfEx(FLAG_NOLOG, "FlashMem write FAILEd [offset %u]", bytes_sent); + cjSetCursLeft(); + SpinOff(100); + + return; + } + + LED_A_INV(); + LED_B_INV(); + LED_C_INV(); + LED_D_INV(); + } + end_time = GetTickCount(); + + DbprintfEx(FLAG_NOLOG, "[OK] TAG WRITTEN TO FLASH ! [0-to offset %u]", bytes_sent); + cjSetCursLeft(); + DbprintfEx(FLAG_NOLOG, "%s[IN]%s %s%dms%s for TAG_FLASH_WRITE", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_); + cjSetCursLeft(); + + FlashStop(); + + SpinOff(0); + + return; +} + +void RunMod() +{ currline = 20; curlline = 20; currfline = 24; @@ -89,7 +378,7 @@ void RunMod() { uint64_t key64; // Defines current key uint8_t *keyBlock = NULL; // Where the keys will be held in memory. -/* VIGIK EXPIRED DUMP FOR STUDY + /* VIGIK EXPIRED DUMP FOR STUDY Sector 0 121C7F730208040001FA33F5CB2D021D 44001049164916491649000000000000 @@ -125,11 +414,11 @@ KEY A : 1KGIV ; ACCBITS : 796788[00]+VALUE */ -//---------------------------- -// Set of keys to be used. -// This should cover ~98% of -// French VIGIK system @2017 -//---------------------------- + //---------------------------- + // Set of keys to be used. + // This should cover ~98% of + // French VIGIK system @2017 + //---------------------------- #define STKEYS 37 @@ -177,7 +466,8 @@ ACCBITS : 796788[00]+VALUE keyBlock = BigBuf_malloc(STKEYS * 6); int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t); - for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) { + for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) + { num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6)); } @@ -185,10 +475,13 @@ ACCBITS : 796788[00]+VALUE // and why not a simple memset abuse to 0xffize the whole space in one go ? // uint8_t foundKey[2][40][6]; //= [ {0xff} ]; /* C99 abusal 6.7.8.21 uint8_t foundKey[2][40][6]; - for (uint16_t t = 0; t < 2; t++) { - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + for (uint16_t t = 0; t < 2; t++) + { + for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) + { // validKey[t][sectorNo] = false; - for (uint16_t i = 0; i < 6; i++) { + for (uint16_t i = 0; i < 6; i++) + { foundKey[t][sectorNo][i] = 0xff; } } @@ -200,11 +493,6 @@ ACCBITS : 796788[00]+VALUE bool allKeysFound = true; uint32_t size = mfKeysCnt; - LED_A_OFF(); - LED_B_OFF(); - LED_C_OFF(); - LED_D_OFF(); - LED_A_ON(); // banner: vtsend_reset(NULL); @@ -218,7 +506,19 @@ ACCBITS : 796788[00]+VALUE currfline = 24; cjSetCursLeft(); + SpinDown(50); + SpinOff(50); + SpinUp(50); + SpinOff(50); + SpinDown(50); + +#if 0 +TestFlashmemRoutine(); +return; +#endif + failtag: + vtsend_cursor_position_save(NULL); vtsend_set_attribute(NULL, 1); vtsend_set_attribute(NULL, 5); @@ -226,11 +526,32 @@ failtag: vtsend_set_attribute(NULL, 0); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - while (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) { + SpinOff(50); + LED_A_ON(); + uint8_t ticker = 0; + //while (!BUTTON_PRESS() && !iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) + while (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) + { WDT_HIT(); + + ticker++; + if (ticker % 64 == 0) + { + LED_A_INV(); + } + + if (BUTTON_HELD(10) > 0) + { + WDT_HIT(); + DbprintfEx(FLAG_NOLOG, "\t\t\t[ READING FLASH ]"); + ReadLastTagFromFlash(); + goto readysim; + } } + + SpinOff(50); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(200); vtsend_cursor_position_restore(NULL); DbprintfEx(FLAG_NOLOG, "\t\t\t%s[ GOT a Tag ! ]%s", _GREEN_, _WHITE_); cjSetCursLeft(); @@ -239,12 +560,16 @@ failtag: DbprintfEx(FLAG_NOLOG, "\t%sGOT TAG :%s %08x%s", _RED_, _CYAN_, cjcuid, _WHITE_); - if (cjcuid == 0) { + if (cjcuid == 0) + { cjSetCursLeft(); - DbprintfEx(FLAG_NOLOG, "%s>>%s BUG: 0000_CJCUID! Retrying...", _RED_, _WHITE_); + SpinErr(0, 100, 8); goto failtag; } + + SpinOff(50); + LED_B_ON(); cjSetCursRight(); DbprintfEx(FLAG_NOLOG, "--------+--------------------+-------"); cjSetCursRight(); @@ -283,31 +608,38 @@ failtag: // also we could avoid first UID check for every block // then let’s expose this “optimal case” of “well known vigik schemes” : - for (uint8_t type = 0; type < 2 && !err && !trapped; type++) { - for (int sec = 0; sec < sectorsCnt && !err && !trapped; ++sec) { + for (uint8_t type = 0; type < 2 && !err && !trapped; type++) + { + for (int sec = 0; sec < sectorsCnt && !err && !trapped; ++sec) + { key = cjat91_saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64); // key = saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64); - if (key == -1) { + if (key == -1) + { err = 1; allKeysFound = false; // used in “portable” imlementation on microcontroller: it reports back the fail and open the standalone lock // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); break; - } else if (key == -2) { + } + else if (key == -2) + { err = 1; // Can't select card. allKeysFound = false; // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); break; - } else { + } + else + { /* BRACE YOURSELF : AS LONG AS WE TRAP A KNOWN KEY, WE STOP CHECKING AND ENFORCE KNOWN SCHEMES */ // uint8_t tosendkey[12]; - char tosendkey[13]; + char tosendkey[12]; num_to_bytes(key64, 6, foundKey[type][sec]); cjSetCursRight(); DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %012" PRIx64 " ; TYP: %i", sec, key64, type); /*cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sec, type, tosendkey, 12);*/ - - switch (key64) { + switch (key64) + { ///////////////////////////////////////////////////////// // COMMON SCHEME 1 : INFINITRON/HEXACT case 0x484558414354: @@ -328,7 +660,8 @@ failtag: ; // Type 0 / A first uint16_t t = 0; - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) + { num_to_bytes(0x484558414354, 6, foundKey[t][sectorNo]); sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); @@ -474,8 +807,10 @@ failtag: // emlClearMem(); // A very weak one... - for (uint16_t t = 0; t < 2; t++) { - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + for (uint16_t t = 0; t < 2; t++) + { + for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) + { num_to_bytes(key64, 6, foundKey[t][sectorNo]); sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); @@ -509,7 +844,8 @@ failtag: DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _GREEN_, _WHITE_); ; t = 0; - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) + { num_to_bytes(0x414c41524f4e, 6, foundKey[t][sectorNo]); sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); @@ -519,7 +855,8 @@ failtag: ; } t = 1; - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) + { num_to_bytes(0x424c41524f4e, 6, foundKey[t][sectorNo]); sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); @@ -536,21 +873,25 @@ failtag: } } - if (!allKeysFound) { - // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + if (!allKeysFound) + { cjSetCursLeft(); cjTabulize(); DbprintfEx(FLAG_NOLOG, "%s[ FAIL ]%s\r\n->did not found all the keys :'(", _RED_, _WHITE_); cjSetCursLeft(); + SpinErr(1, 100, 8); + SpinOff(100); return; } /* Settings keys to emulator */ emlClearMem(); uint8_t mblock[16]; - for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) + { emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); - for (uint8_t t = 0; t < 2; t++) { + for (uint8_t t = 0; t < 2; t++) + { memcpy(mblock + t * 10, foundKey[t][sectorNo], 6); } emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); @@ -565,27 +906,41 @@ failtag: DbprintfEx(FLAG_NOLOG, "%s>>%s Filling Emulator <- from A keys...", _YELLOW_, _WHITE_); e_MifareECardLoad(sectorsCnt, 0, 0, &filled); - if (filled != 1) { + if (filled != 1) + { cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "%s>>%s W_FAILURE ! %sTrying fallback B keys....", _RED_, _ORANGE_, _WHITE_); /* no trace, no dbg */ e_MifareECardLoad(sectorsCnt, 1, 0, &filled); - if (filled != 1) { + if (filled != 1) + { cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "FATAL:EML_FALLBACKFILL_B"); - // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + SpinErr(2, 100, 8); + SpinOff(100); return; } } + end_time = GetTickCount(); cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "%s>>%s Time for VIGIK break :%s%dms%s", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_); - // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + vtsend_cursor_position_save(NULL); + vtsend_set_attribute(NULL, 1); + vtsend_set_attribute(NULL, 5); + cjTabulize(); + DbprintfEx(FLAG_NOLOG, "[ WRITING FLASH ]"); + cjSetCursLeft(); + cjSetCursLeft(); + + WriteTagToFlash(0,1024); + +readysim: // SIM ? cjSetCursLeft(); @@ -602,12 +957,14 @@ failtag: cjTabulize(); - vtsend_cursor_position_save(NULL); - vtsend_set_attribute(NULL, 1); - vtsend_set_attribute(NULL, 5); DbprintfEx(FLAG_NOLOG, "[ SIMULATION ]"); vtsend_set_attribute(NULL, 0); - Mifare1ksim((FLAG_4B_UID_IN_DATA | FLAG_UID_IN_EMUL ), 0, 0, cjuid); + + SpinOff(100); + LED_C_ON(); + Mifare1ksim(FLAG_4B_UID_IN_DATA | FLAG_UID_IN_EMUL, 0, 0, cjuid); + LED_C_OFF(); + SpinOff(50); vtsend_cursor_position_restore(NULL); DbprintfEx(FLAG_NOLOG, "[ SIMUL ENDED ]%s", _GREEN_, _WHITE_); cjSetCursLeft(); @@ -652,7 +1009,9 @@ failtag: DbprintfEx(FLAG_NOLOG, "- [ LA FIN ] -\r\n%s`-> You can take shell back :) ...", _WHITE_); cjSetCursLeft(); vtsend_set_attribute(NULL, 0); - + SpinErr(3, 100, 16); + SpinDown(75); + SpinOff(100); return; } @@ -660,7 +1019,8 @@ failtag: * - *datain used as error return * - tracing is falsed */ -void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { +void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) +{ MF_DBGLEVEL = MF_DBG_NONE; uint8_t numSectors = arg0; @@ -675,9 +1035,6 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat byte_t dataoutbuf2[16]; // uint8_t uid[10]; - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); @@ -686,23 +1043,30 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat bool isOK = true; // iso14443a_fast_select_card(cjuid, 0); - if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) { + if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) + { isOK = false; if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_RAWPRINT, "Can't select card"); } - for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { + for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) + { ui64Key = emlGetKey(sectorNo, keyType); - if (sectorNo == 0) { - if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { + if (sectorNo == 0) + { + if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) + { isOK = false; if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Sector[%2d]. Auth error", sectorNo); break; } - } else { - if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { + } + else + { + if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) + { isOK = false; if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Sector[%2d]. Auth nested error", sectorNo); @@ -710,29 +1074,38 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat } } - for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - if (isOK && mifare_classic_readblock(pcs, cjcuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { + for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) + { + if (isOK && mifare_classic_readblock(pcs, cjcuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) + { isOK = false; if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Error reading sector %2d block %2d", sectorNo, blockNo); break; }; - if (isOK) { + if (isOK) + { *datain = 1; - if (blockNo < NumBlocksPerSector(sectorNo) - 1) { + if (blockNo < NumBlocksPerSector(sectorNo) - 1) + { emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); - } else { // sector trailer, keep the keys, set only the AC + } + else + { // sector trailer, keep the keys, set only the AC emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); } - } else { + } + else + { *datain = 0; } } } - if (mifare_classic_halt(pcs, cjcuid)) { + if (mifare_classic_halt(pcs, cjcuid)) + { if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Halt error"); }; @@ -741,7 +1114,6 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat crypto1_destroy(pcs); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED\n"); @@ -752,7 +1124,8 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat /* the chk function is a piwi’ed(tm) check that will try all keys for a particular sector. also no tracing no dbg */ -int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key) { +int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key) +{ MF_DBGLEVEL = MF_DBG_NONE; iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); set_tracing(false); @@ -763,40 +1136,41 @@ int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui pcs = &mpcs; // byte_t isOK = 0; - for (int i = 0; i < keyCount; ++i) { - LEDsoff(); + for (int i = 0; i < keyCount; ++i) + { /* no need for anticollision. just verify tag is still here */ // if (!iso14443a_fast_select_card(cjuid, 0)) { - if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) { + if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) + { cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "%sFATAL%s : E_MF_LOSTTAG", _RED_, _WHITE_); return -1; } uint64_t ui64Key = bytes_to_num(datain + i * 6, 6); - if (mifare_classic_auth(pcs, cjcuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { + if (mifare_classic_auth(pcs, cjcuid, blockNo, keyType, ui64Key, AUTH_FIRST)) + { uint8_t dummy_answer = 0; ReaderTransmit(&dummy_answer, 1, NULL); // wait for the card to become ready again SpinDelayUs(AUTHENTICATION_TIMEOUT); continue; } - LED_A_ON(); crypto1_destroy(pcs); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); *key = ui64Key; return i; } - LED_A_ON(); crypto1_destroy(pcs); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); return -1; } -void saMifareMakeTag(void) { - // uint8_t cfail = 0;` +void saMifareMakeTag(void) +{ + uint8_t cfail = 0; cjSetCursLeft(); cjTabulize(); vtsend_cursor_position_save(NULL); @@ -808,8 +1182,8 @@ void saMifareMakeTag(void) { DbprintfEx(FLAG_NOLOG, ">> Write to Special:"); int flags = 0; - LED_A_ON(); // yellow - for (int blockNum = 0; blockNum < 16 * 4; blockNum++) { + for (int blockNum = 0; blockNum < 16 * 4; blockNum++) + { uint8_t mblock[16]; // cnt = 0; emlGetMem(mblock, blockNum, 1); @@ -825,10 +1199,12 @@ void saMifareMakeTag(void) { if (blockNum == 16 * 4 - 1) flags = 0x04 + 0x10; - if (saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock)) { //&& cnt <= retry) { - // cnt++; + if (saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock)) + { //&& cnt <= retry) { + // cnt++; cjSetCursFRight(); - if (currfline > 53) { + if (currfline > 53) + { currfline = 54; } DbprintfEx(FLAG_NOLOG, "Block :%02x %sOK%s", blockNum, _GREEN_, _WHITE_); @@ -836,14 +1212,16 @@ void saMifareMakeTag(void) { // cfail=1; // return; continue; - } else { + } + else + { cjSetCursLeft(); cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "`--> %sFAIL%s : CHN_FAIL_BLK_%02x_NOK", _RED_, _WHITE_, blockNum); cjSetCursFRight(); DbprintfEx(FLAG_NOLOG, "%s>>>>%s STOP AT %02x", _RED_, _WHITE_, blockNum); - + cfail++; break; } cjSetCursFRight(); @@ -855,13 +1233,20 @@ void saMifareMakeTag(void) { break; } */ } + if (cfail == 0) + { + SpinUp(50); + SpinUp(50); + SpinUp(50); + } } //----------------------------------------------------------------------------- // Matt's StandAlone mod. // Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn) //----------------------------------------------------------------------------- -int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { +int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) +{ // params uint8_t needWipe = arg0; @@ -888,30 +1273,32 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; // reset FPGA and LED - if (workFlags & 0x08) { - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + if (workFlags & 0x08) + { iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); // clear_trace(); set_tracing(FALSE); } - while (true) { - // cjSetCursLeft(); + while (true) + { + cjSetCursLeft(); // get UID from chip - if (workFlags & 0x01) { + if (workFlags & 0x01) + { // if (!iso14443a_fast_select_card(cjuid, 0)) { - if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) { + if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) + { if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Can't select card"); break; }; - if (mifare_classic_halt(NULL, cjcuid)) { + if (mifare_classic_halt(NULL, cjcuid)) + { if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Halt error"); break; @@ -919,22 +1306,26 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data }; // reset chip - if (needWipe) { + if (needWipe) + { ReaderTransmitBitsPar(wupC1, 7, 0, NULL); - if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) + { // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "wupC1 error"); break; }; ReaderTransmit(wipeC, sizeof(wipeC), NULL); - if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) + { if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "wipeC error"); break; }; - if (mifare_classic_halt(NULL, cjcuid)) { + if (mifare_classic_halt(NULL, cjcuid)) + { if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Halt error"); break; @@ -943,39 +1334,46 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data // chaud // write block - if (workFlags & 0x02) { + if (workFlags & 0x02) + { ReaderTransmitBitsPar(wupC1, 7, 0, NULL); - if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) + { // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "wupC1 error"); break; }; ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) + { // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "wupC2 errorv"); break; }; } - if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { + if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) + { // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "write block send command error"); break; }; memcpy(d_block, datain, 16); - AddCrc14A(d_block,16); + AddCrc14A(d_block, 16); ReaderTransmit(d_block, sizeof(d_block), NULL); - if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { + if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) + { // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "write block send data error"); break; }; - if (workFlags & 0x04) { - if (mifare_classic_halt(NULL, cjcuid)) { + if (workFlags & 0x04) + { + if (mifare_classic_halt(NULL, cjcuid)) + { // if (MF_DBGLEVEL >= 1) cjSetCursFRight(); @@ -988,12 +1386,10 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data break; } - if ((workFlags & 0x10) || (!isOK)) { + if ((workFlags & 0x10) || (!isOK)) + { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); } return isOK; } - - diff --git a/armsrc/Standalone/hf_colin.h b/armsrc/Standalone/hf_colin.h index 83c152095..dd3da6322 100644 --- a/armsrc/Standalone/hf_colin.h +++ b/armsrc/Standalone/hf_colin.h @@ -16,18 +16,21 @@ #ifndef __HF_COLIN_H #define __HF_COLIN_H -#include // for bool -#include -#include -#include "standalone.h" // standalone definitions + #include "proxmark3.h" #include "mifareutil.h" #include "iso14443a.h" +//#include "printf.h" #include "protocols.h" #include "util.h" +#include "standalone.h" // standalone definitions +#include // for bool +#include +#include +//#include #include "vtsend.h" #include "apps.h" -#include "usb_cmd.h" // mifare1ksim flags +#include "printf.h" #define _RED_ "\x1b[31m" #define _GREEN_ "\x1b[32m" @@ -38,14 +41,20 @@ #define _WHITE_ "\x1b[0m" #define _ORANGE_ _YELLOW_ +#define NTIME(n) for (int _index = 0; _index < n; _index++) + int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key); void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void saMifareMakeTag(void); int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug); +void WriteTagToFlash(uint8_t index, size_t size); const char clearTerm[8] = {0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a, '\0'}; +void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate); + + #define LOGO logo_kigiv const char sub_banner[] = " From Vigik : \"20 years of (un)security without a single update\""; @@ -410,7 +419,7 @@ const char logo_kigiv[] = { 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x0d, 0x0a}; unsigned int logo_kigiv_len = 9303; -const char logo_kigiv_nocolor[] = { +/*const char logo_kigiv_nocolor[] = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, @@ -494,6 +503,6 @@ const char logo_kigiv_nocolor[] = { 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x31, 0x31, 0x0d, 0x0a}; -unsigned int logo_kigiv_nocolor_len = 2153; +unsigned int logo_kigiv_nocolor_len = 2153;*/ #endif /* __HF_COLIN_H */ diff --git a/armsrc/appmain.c b/armsrc/appmain.c index c6e6e0dee..03502f132 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -440,7 +440,7 @@ void printStandAloneModes(void) { DbpString(" LF HID corporate 1000 bruteforce - (Federico dotta & Maurizio Agazzini)"); #endif #if defined(WITH_HF_MATTYRUN) - DbpString(" HF Mifare sniff/clone - aka MattyRun (Matas A. R Medina)"); + DbpString(" HF Mifare sniff/clone - aka MattyRun (Mat�as A. R� Medina)"); #endif #if defined(WITH_HF_COLIN) DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)"); @@ -1160,7 +1160,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); isok = cmd_send(CMD_DOWNLOADED_EML_BIGBUF, i, len, 0, mem + startidx + i, len); if (!isok) - Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); + Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); } // Trigger a finish downloading signal with an ACK frame cmd_send(CMD_ACK, 1, 0, 0, 0, 0); @@ -1171,27 +1171,30 @@ void UsbPacketReceived(uint8_t *packet, int len) { ReadMem(c->arg[0]); break; #ifdef WITH_FLASH - case CMD_READ_FLASH_MEM: { - + case CMD_FLASHMEM_SET_SPIBAUDRATE: + FlashmemSetSpiBaudrate(c->arg[0]); + break; + case CMD_FLASHMEM_READ: { LED_B_ON(); uint16_t isok = 0; uint32_t startidx = c->arg[0]; uint16_t len = c->arg[1]; + //uint8_t fast = c->arg[2]; - Dbprintf("FlashMem read | %d - %d", startidx, len); + Dbprintf("FlashMem read | %d - %d | ", startidx, len); size_t size = MIN(USB_CMD_DATA_SIZE, len); uint8_t *mem = BigBuf_malloc(size); + FlashInit(); + //Flash_CheckBusy(BUSY_TIMEOUT); + for(size_t i = 0; i < len; i += size) { len = MIN((len - i), size); - memset(mem, 0, len); - - Dbprintf("FlashMem reading | %d | %d | %d", startidx + i, i, len); - - isok = Flash_ReadData(startidx + i, mem, len); + Dbprintf("FlashMem reading | %d | %d | %d |", startidx + i, i, len); + isok = Flash_ReadDataCont(startidx + i, mem, len); if ( isok == len ) { print_result("Chunk: ", mem, len); } else { @@ -1199,10 +1202,11 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; } } + FlashStop(); LED_B_OFF(); break; } - case CMD_WRITE_FLASH_MEM: { + case CMD_FLASHMEM_WRITE: { LED_B_ON(); uint8_t isok = 0; uint16_t res = 0; @@ -1212,6 +1216,14 @@ void UsbPacketReceived(uint8_t *packet, int len) { uint32_t tmp = startidx + len; + if (!FlashInit()) + { + break; + } + + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + // inside 256b page? if ( (tmp & 0xFF) != 0) { @@ -1225,27 +1237,28 @@ void UsbPacketReceived(uint8_t *packet, int len) { uint8_t first_len = (~startidx & 0xFF)+1; // first mem page - res = Flash_WriteData(startidx, data, first_len); + res = Flash_WriteDataCont(startidx, data, first_len); // second mem page - res = Flash_WriteData(startidx + first_len, data + first_len, len - first_len); + res = Flash_WriteDataCont(startidx + first_len, data + first_len, len - first_len); isok = (res == (len - first_len)) ? 1 : 0; } else { - res = Flash_WriteData(startidx, data, len); + res = Flash_WriteDataCont(startidx, data, len); isok = (res == len) ? 1 : 0; } } else { - res = Flash_WriteData(startidx, data, len); + res = Flash_WriteDataCont(startidx, data, len); isok = (res == len) ? 1 : 0; } + FlashStop(); cmd_send(CMD_ACK, isok, 0, 0, 0, 0); LED_B_OFF(); break; } - case CMD_WIPE_FLASH_MEM: { + case CMD_FLASHMEM_WIPE: { LED_B_ON(); uint8_t page = c->arg[0]; uint8_t initalwipe = c->arg[1]; @@ -1263,7 +1276,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { LED_B_OFF(); break; } - case CMD_DOWNLOAND_FLASH_MEM: { + case CMD_FLASHMEM_DOWNLOAD: { LED_B_ON(); uint8_t *mem = BigBuf_malloc(USB_CMD_DATA_SIZE); @@ -1271,26 +1284,32 @@ void UsbPacketReceived(uint8_t *packet, int len) { size_t len = 0; uint32_t startidx = c->arg[0]; uint32_t numofbytes = c->arg[1]; + //uint8_t fast = c->arg[2]; + // arg0 = startindex // arg1 = length bytes to transfer // arg2 = RFU + + FlashInit(); + for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); - - isok = Flash_ReadData(startidx + i, mem, len); + + isok = Flash_ReadDataCont(startidx + i, mem, len); if (!isok ) Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len); - - isok = cmd_send(CMD_DOWNLOADED_FLASHMEM, i, len, 0, mem, len); - if (!isok) - Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); - } + isok = cmd_send(CMD_FLASHMEM_DOWNLOADED, i, len, 0, mem, len); + if (!isok) + Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); + } + FlashStop(); + cmd_send(CMD_ACK, 1, 0, 0, 0, 0); LED_B_OFF(); break; } - case CMD_INFO_FLASH_MEM: { + case CMD_FLASHMEM_INFO: { LED_B_ON(); rdv40_validation_t *info = (rdv40_validation_t*)BigBuf_malloc( sizeof(rdv40_validation_t) ); @@ -1392,8 +1411,6 @@ void __attribute__((noreturn)) AppMain(void) { LEDsoff(); - usb_enable(); - // The FPGA gets its clock from us from PCK0 output, so set that up. AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0; AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0; @@ -1429,6 +1446,12 @@ void __attribute__((noreturn)) AppMain(void) { #ifdef WITH_FPC usart_init(); #endif + + // This is made as late as possible to ensure enumeration without timeout + // against device such as http://www.hobbytronics.co.uk/usb-host-board-v2 + usb_disable(); + usb_enable(); + uint8_t rx[sizeof(UsbCommand)]; for(;;) { @@ -1463,7 +1486,6 @@ void __attribute__((noreturn)) AppMain(void) { #if defined (WITH_ISO14443a) && ( defined (WITH_HF_YOUNG) || defined(WITH_HF_COLIN) || defined(WITH_HF_MATTYRUN) ) RunMod(); #endif - } } } diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index 7c5beb47a..a8642dd74 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -1,39 +1,45 @@ #include "flashmem.h" + + /* here: use NCPS2 @ PA10: */ -#define SPI_CSR_NUM 2 // Chip Select register[] 0,1,2,3 (at91samv512 has 4) - -/* PCS_0 for NPCS0, PCS_1 for NPCS1 ... */ -#define PCS_0 ((0<<0)|(1<<1)|(1<<2)|(1<<3)) // 0xE - 1110 -#define PCS_1 ((1<<0)|(0<<1)|(1<<2)|(1<<3)) // 0xD - 1101 -#define PCS_2 ((1<<0)|(1<<1)|(0<<2)|(1<<3)) // 0xB - 1011 -#define PCS_3 ((1<<0)|(1<<1)|(1<<2)|(0<<3)) // 0x7 - 0111 - -// TODO -#if (SPI_CSR_NUM == 0) -#define SPI_MR_PCS PCS_0 -#elif (SPI_CSR_NUM == 1) -#define SPI_MR_PCS PCS_1 -#elif (SPI_CSR_NUM == 2) -#define SPI_MR_PCS PCS_2 -#elif (SPI_CSR_NUM == 3) -#define SPI_MR_PCS PCS_3 -#else -#error "SPI_CSR_NUM invalid" -// not realy - when using an external address decoder... -// but this code takes over the complete SPI-interace anyway -#endif +#define SPI_CSR_NUM 2 +#define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16) +/// Calculates the value of the CSR SCBR field given the baudrate and MCK. +#define SPI_SCBR(baudrate, masterClock) ((uint32_t) ((masterClock) / (baudrate)) << 8) +/// Calculates the value of the CSR DLYBS field given the desired delay (in ns) +#define SPI_DLYBS(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 1000) << 16) +/// Calculates the value of the CSR DLYBCT field given the desired delay (in ns) +#define SPI_DLYBCT(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 32000) << 24) -/* - ȡָԴһλÿʼĶܽоƬȡ - ҳдָÿдΪ1-256ֽڣDzܿԽ256ֽڱ߽ - ָָ뽫CSߣ򲻻ִ -*/ +uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD; -void FlashSetup(void) { - // PA1 -> SPI_NCS3 chip select (MEM) - // PA10 -> SPI_NCS2 chip select (LCD) + +void FlashmemSetSpiBaudrate(uint32_t baudrate){ + FLASHMEM_SPIBAUDRATE = baudrate; + Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE/1000000); +} + +// initialize +bool FlashInit() { + FlashSetup(FLASHMEM_SPIBAUDRATE); + + StartTicks(); + + if (Flash_CheckBusy(BUSY_TIMEOUT)) { + StopTicks(); + return false; + } + + return true; +} + +void FlashSetup(uint32_t baudrate){ + //WDT_DISABLE + AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS; + + // PA10 -> SPI_NCS2 chip select (FLASHMEM) // PA11 -> SPI_NCS0 chip select (FPGA) // PA12 -> SPI_MISO Master-In Slave-Out // PA13 -> SPI_MOSI Master-Out Slave-In @@ -54,27 +60,70 @@ void FlashSetup(void) { //enable the SPI Peripheral clock AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI); + + //reset spi needs double SWRST, see atmel's errata on this case + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; + // Enable SPI AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; // NPCS2 Mode 0 AT91C_BASE_SPI->SPI_MR = - ( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods) - (0xB << 16) | // Peripheral Chip Select (selects SPI_NCS2 or PA10) - ( 0 << 7) | // Local Loopback Disabled - ( 1 << 4) | // Mode Fault Detection disabled - ( 0 << 2) | // Chip selects connected directly to peripheral - ( 0 << 1) | // Fixed Peripheral Select - ( 1 << 0); // Master Mode + (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT: + // If DLYBCS is less than or equal to six, six MCK periods + // will be inserted by default. + SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10) + ( 0 << 7) | // Disable LLB (1=MOSI2MISO test mode) + ( 1 << 4) | // Disable ModeFault Protection + ( 0 << 3) | // makes spi operate at MCK (1 is MCK/2) + ( 0 << 2) | // Chip selects connected directly to peripheral + AT91C_SPI_PS_FIXED | // Fixed Peripheral Select + AT91C_SPI_MSTR; // Master Mode + + uint8_t csaat = 1; + uint32_t dlybct = 0; + if (baudrate > FLASH_MINFAST) { + baudrate = FLASH_FASTBAUD; + //csaat = 0; + dlybct = 1500; + } - // 8 bit AT91C_BASE_SPI->SPI_CSR[2] = - ( 0 << 24) | // Delay between Consecutive Transfers (32 MCK periods) - ( 0 << 16) | // Delay Before SPCK (1 MCK period) - ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud - ( 0 << 4) | // Bits per Transfer (8 bits) - ( 1 << 3) | // Chip Select inactive after transfer - ( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge + SPI_DLYBCT(dlybct,MCK) | // Delay between Consecutive Transfers (32 MCK periods) + SPI_DLYBS(0,MCK) | // Delay Beforce SPCK CLock + SPI_SCBR(baudrate,MCK) | // SPI Baudrate Selection + AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits) + //AT91C_SPI_CSAAT | // Chip Select inactive after transfer + // 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1 + // If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on + // the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been + // transferred in the shifter. This can imply for example, that the second data is sent twice. + // COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay + ( csaat << 3) | + /* Spi modes: + Mode CPOL CPHA NCPHA + 0 0 0 1 clock normally low read on rising edge + 1 0 1 0 clock normally low read on falling edge + 2 1 0 1 clock normally high read on falling edge + 3 1 1 0 clock normally high read on rising edge + However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI + master mode the ATSAM7S512/256/128/64/321/32 does not sample the data + (MISO) on the opposite edge where data clocks out (MOSI) but the same + edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3 + shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and + that the data changes sometime after the rising edge (about 2 ns). To + be consistent with normal SPI operation, it is probably safe to say + that the data changes on the falling edge and should be sampled on the + rising edge. Therefore, it appears that NCPHA should be treated the + same as CPHA. Thus: + Mode CPOL CPHA NCPHA + 0 0 0 0 clock normally low read on rising edge + 1 0 1 1 clock normally low read on falling edge + 2 1 0 0 clock normally high read on falling edge + 3 1 1 1 clock normally high read on rising edge + */ + ( 0 << 1) | // Clock Phase data captured on leading edge, changes on following edge ( 0 << 0); // Clock Polarity inactive state is logic 0 // read first, empty buffer @@ -82,6 +131,7 @@ void FlashSetup(void) { } void FlashStop(void) { + //Bof //* Reset all the Chip Select register AT91C_BASE_SPI->SPI_CSR[0] = 0; AT91C_BASE_SPI->SPI_CSR[1] = 0; @@ -104,24 +154,21 @@ void FlashStop(void) { // send one byte over SPI uint16_t FlashSendByte(uint32_t data) { - uint16_t incoming = 0; - - WDT_HIT(); // wait until SPI is ready for transfer - while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {}; + //if you are checking for incoming data returned then the TXEMPTY flag is redundant + //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {}; // send the data AT91C_BASE_SPI->SPI_TDR = data; + //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){}; + // wait recive transfer is complete - while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0) - WDT_HIT(); + while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0){}; // reading incoming data - incoming = ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF); - - return incoming; + return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF); } // send last byte over SPI @@ -132,41 +179,37 @@ uint16_t FlashSendLastByte(uint32_t data) { // read state register 1 uint8_t Flash_ReadStat1(void) { FlashSendByte(READSTAT1); - uint8_t stat1 = FlashSendLastByte(0xFF); -// if ( MF_DBGLEVEL > 3 ) Dbprintf("stat1 [%02x]", stat1); - return stat1; + return FlashSendLastByte(0xFF); } -// read state register 2 -uint8_t Flash_ReadStat2(void) { - FlashSendByte(READSTAT2); - uint8_t stat2 = FlashSendLastByte(0xFF); -// if ( MF_DBGLEVEL > 3 ) Dbprintf("stat2 [%02x]", stat2); - return stat2; -} +bool Flash_CheckBusy(uint32_t timeout) +{ + WaitUS(WINBOND_WRITE_DELAY); + StartCountUS(); + uint32_t _time = GetCountUS(); -// determine whether FLASHMEM is busy -bool Flash_CheckBusy(uint16_t times) { - bool ret = (Flash_ReadStat1() & BUSY); + if ( MF_DBGLEVEL > 3 ) Dbprintf("Checkbusy in..."); - if (!ret || !times || !(times--)) - return ret; + do + { + if (!(Flash_ReadStat1() & BUSY)) + { + return false; + } + } while ((GetCountUS() - _time) < timeout); - while (times) { - WDT_HIT(); - SpinDelay(1); - ret = (Flash_ReadStat1() & BUSY); - if (!ret) - break; - times--; + if (timeout <= (GetCountUS() - _time)) + { + return true; } - return ret; + + return false; } // read ID out uint8_t Flash_ReadID(void) { - if (Flash_CheckBusy(100)) return 0; + if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0; // Manufacture ID / device ID FlashSendByte(ID); @@ -188,7 +231,7 @@ uint8_t Flash_ReadID(void) { // read unique id for chip. void Flash_UniqueID(uint8_t *uid) { - if (Flash_CheckBusy(100)) return; + if (Flash_CheckBusy(BUSY_TIMEOUT)) return; // reading unique serial number FlashSendByte(UNIQUE_ID); @@ -210,27 +253,72 @@ void Flash_UniqueID(uint8_t *uid) { uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) { if (!FlashInit()) return 0; - - Flash_ReadStat1(); - + // length should never be zero - if (!len || Flash_CheckBusy(100)) return 0; + if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0; - FlashSendByte(READDATA); - FlashSendByte((address >> 16) & 0xFF); - FlashSendByte((address >> 8) & 0xFF); - FlashSendByte((address >> 0) & 0xFF); + + uint8_t cmd = READDATA; + + if(FASTFLASH) { + cmd = FASTREAD; + } + + FlashSendByte(cmd); + Flash_TransferAdresse(address); + + if (FASTFLASH){ + FlashSendByte(DUMMYBYTE); + } uint16_t i = 0; for (; i < (len - 1); i++) out[i] = FlashSendByte(0xFF); out[i] = FlashSendLastByte(0xFF); - + + FlashStop(); return len; } +void Flash_TransferAdresse(uint32_t address){ + FlashSendByte((address >> 16) & 0xFF); + FlashSendByte((address >> 8) & 0xFF); + FlashSendByte((address >> 0) & 0xFF); +} + +/* This ensure we can ReadData without having to cycle through initialization everytime */ +uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { + + // length should never be zero + if (!len) return 0; + + uint8_t cmd = READDATA; + + if(FASTFLASH) { + cmd = FASTREAD; + } + + FlashSendByte(cmd); + Flash_TransferAdresse(address); + + if (FASTFLASH){ + FlashSendByte(DUMMYBYTE); + } + + uint16_t i = 0; + for (; i < (len - 1); i++) + out[i] = FlashSendByte(0xFF); + + out[i] = FlashSendLastByte(0xFF); + + return len; +} + + +//////////////////////////////////////// + // Write data can only program one page. A page has 256 bytes. // if len > 256, it might wrap around and overwrite pos 0. uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { @@ -256,7 +344,7 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { return 0; } - Flash_ReadStat1(); + Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); @@ -275,6 +363,39 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { return len; } +uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) { + + // length should never be zero + if (!len) + return 0; + + // Max 256 bytes write + if (((address & 0xFF) + len) > 256) { + Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len ); + return 0; + } + + // out-of-range + if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { + Dbprintf("Flash_WriteData, block out-of-range"); + return 0; + } + + + FlashSendByte(PAGEPROG); + FlashSendByte((address >> 16) & 0xFF); + FlashSendByte((address >> 8) & 0xFF); + FlashSendByte((address >> 0) & 0xFF); + + uint16_t i = 0; + for (; i < (len - 1); i++) + FlashSendByte(in[i]); + + FlashSendLastByte(in[i]); + + return len; +} + bool Flash_WipeMemoryPage(uint8_t page) { if (!FlashInit()) { if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); @@ -283,7 +404,7 @@ bool Flash_WipeMemoryPage(uint8_t page) { Flash_ReadStat1(); // Each block is 64Kb. One block erase takes 1s ( 1000ms ) - Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(1000); + Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(BUSY_TIMEOUT); FlashStop(); return true; @@ -298,10 +419,10 @@ bool Flash_WipeMemory() { // Each block is 64Kb. Four blocks // one block erase takes 1s ( 1000ms ) - Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(1000); - Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(1000); - Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(1000); - Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(1000); + Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(BUSY_TIMEOUT); FlashStop(); return true; @@ -366,29 +487,18 @@ void Flash_EraseChip(void) { FlashSendLastByte(CHIPERASE); } -// initialize -bool FlashInit(void) { - FlashSetup(); - StartTicks(); - - if (Flash_CheckBusy(100)) { - StopTicks(); - return false; - } - if ( MF_DBGLEVEL > 3 ) Dbprintf("FlashInit OK"); - return true; -} void Flashmem_print_status(void) { DbpString("Flash memory"); + Dbprintf(" Baudrate................%dMHz",FLASHMEM_SPIBAUDRATE/1000000); if (!FlashInit()) { - DbpString(" init....................FAIL"); + DbpString(" Init....................FAIL"); return; } - DbpString(" init....................OK"); + DbpString(" Init....................OK"); uint8_t dev_id = Flash_ReadID(); switch (dev_id) { @@ -414,4 +524,4 @@ void Flashmem_print_status(void) { ); FlashStop(); -} \ No newline at end of file +} diff --git a/armsrc/flashmem.h b/armsrc/flashmem.h index 198e3392d..ae10ea388 100644 --- a/armsrc/flashmem.h +++ b/armsrc/flashmem.h @@ -45,6 +45,7 @@ #define WRITEENABLE 0x06 #define READDATA 0x03 +#define FASTREAD 0x0B #define PAGEPROG 0x02 #define SECTORERASE 0x20 @@ -57,27 +58,17 @@ // Not used or not support command #define RELEASE 0xAB #define POWERDOWN 0xB9 -#define FASTREAD 0x0B #define SUSPEND 0x75 #define RESUME 0x7A +#define BUSY_TIMEOUT 1000000000L -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -// Chip specific instructions // -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - -//~~~~~~~~~~~~~~~~~~~~~~~~~ Winbond ~~~~~~~~~~~~~~~~~~~~~~~~~// #define WINBOND_MANID 0xEF #define WINBOND_DEVID 0x11 #define PAGESIZE 0x100 +#define WINBOND_WRITE_DELAY 0x02 -//~~~~~~~~~~~~~~~~~~~~~~~~ Microchip ~~~~~~~~~~~~~~~~~~~~~~~~// -#define MICROCHIP_MANID 0xBF -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -// Definitions // -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - -#define SPI_CLK 75000000 //Hex equivalent of 75MHz +#define SPI_CLK 48000000 #define BUSY 0x01 #define WRTEN 0x02 @@ -111,15 +102,33 @@ #define MAX_SECTORS 16 + + +#define MCK 48000000 +//#define FLASH_BAUD 24000000 +#define FLASH_MINFAST 24000000 //33000000 +#define FLASH_BAUD MCK/2 +#define FLASH_FASTBAUD MCK +#define FLASH_MINBAUD FLASH_FASTBAUD + +#define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST) + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// extern void Dbprintf(const char *fmt, ...); -void FlashSetup(void); +void FlashmemSetSpiBaudrate(uint32_t baudrate); +bool FlashInit(); +void FlashSetup(uint32_t baudrate); void FlashStop(void); bool Flash_WaitIdle(void); uint8_t Flash_ReadStat1(void); uint8_t Flash_ReadStat2(void); uint16_t FlashSendByte(uint32_t data); +void Flash_TransferAdresse(uint32_t address); + +bool Flash_CheckBusy(uint32_t timeout); + void Flash_WriteEnable(); bool Flash_WipeMemoryPage(uint8_t page); @@ -128,12 +137,17 @@ bool Flash_Erase4k(uint8_t block, uint8_t sector); //bool Flash_Erase32k(uint32_t address); bool Flash_Erase64k(uint8_t block); -bool FlashInit(); void Flash_UniqueID(uint8_t *uid); uint8_t Flash_ReadID(void); uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len); + +uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len); + uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len); +uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len); void Flashmem_print_status(void); + + #endif \ No newline at end of file diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index 2b86bdcfc..43230218f 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -12,7 +12,31 @@ #include "rsa.h" #include "sha1.h" +#define MCK 48000000 +//#define FLASH_BAUD 24000000 +#define FLASH_MINFAST 24000000 //33000000 +#define FLASH_BAUD MCK/2 +#define FLASH_FASTBAUD MCK +#define FLASH_MINBAUD FLASH_FASTBAUD + +#define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST) + static int CmdHelp(const char *Cmd); + +int usage_flashmem_spibaud(void){ + PrintAndLogEx(NORMAL, "Usage: mem spibaud [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " SPI baudrate in MHz [24|48]"); + PrintAndLogEx(NORMAL, " "); + PrintAndLogEx(NORMAL, " If >= 24Mhz, FASTREADS instead of READS instruction will be used."); + PrintAndLogEx(NORMAL, " Reading Flash ID will virtually always fail under 48Mhz setting"); + PrintAndLogEx(NORMAL, " Unless you know what you are doing, please stay at 24Mhz"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem spibaud 48"); + return 0; +} + int usage_flashmem_read(void){ PrintAndLogEx(NORMAL, "Read flash memory on device"); PrintAndLogEx(NORMAL, "Usage: mem read o l "); @@ -107,11 +131,24 @@ int CmdFlashMemRead(const char *Cmd) { return 1; } - UsbCommand c = {CMD_READ_FLASH_MEM, {start_index, len, 0}}; + UsbCommand c = {CMD_FLASHMEM_READ, {start_index, len, 0}}; clearCommandBuffer(); SendCommand(&c); return 0; } + +int CmdFlashmemSpiBaudrate(const char *Cmd) { + + char ctmp = param_getchar(Cmd, 0); + if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_flashmem_spibaud(); + uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10); + baudrate = baudrate*1000000; + if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD ) return usage_flashmem_spibaud(); + UsbCommand c = {CMD_FLASHMEM_SET_SPIBAUDRATE, {baudrate, 0, 0}}; + SendCommand(&c); + return 0; +} + int CmdFlashMemLoad(const char *Cmd){ FILE *f; @@ -189,7 +226,7 @@ int CmdFlashMemLoad(const char *Cmd){ while (bytes_remaining > 0){ uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); - UsbCommand c = {CMD_WRITE_FLASH_MEM, {start_index + bytes_sent, bytes_in_packet, 0}}; + UsbCommand c = {CMD_FLASHMEM_WRITE, {start_index + bytes_sent, bytes_in_packet, 0}}; memcpy(c.d.asBytes, dump + bytes_sent, bytes_in_packet); clearCommandBuffer(); @@ -302,7 +339,7 @@ int CmdFlashMemWipe(const char *Cmd){ //Validations if (errors || cmdp == 0 ) return usage_flashmem_wipe(); - UsbCommand c = {CMD_WIPE_FLASH_MEM, {page, initalwipe, 0}}; + UsbCommand c = {CMD_FLASHMEM_WIPE, {page, initalwipe, 0}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; @@ -347,7 +384,7 @@ int CmdFlashMemInfo(const char *Cmd){ //Validations if (errors ) return usage_flashmem_info(); - UsbCommand c = {CMD_INFO_FLASH_MEM, {0, 0, 0}}; + UsbCommand c = {CMD_FLASHMEM_INFO, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; @@ -476,7 +513,7 @@ int CmdFlashMemInfo(const char *Cmd){ if (shall_write) { // save to mem - c = (UsbCommand){CMD_WRITE_FLASH_MEM, {FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0}}; + c = (UsbCommand){CMD_FLASHMEM_WRITE, {FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0}}; memcpy(c.d.asBytes, sign, sizeof(sign)); clearCommandBuffer(); SendCommand(&c); @@ -508,6 +545,7 @@ int CmdFlashMemInfo(const char *Cmd){ static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, + {"spibaud", CmdFlashmemSpiBaudrate, 1, "Set Flash memory Spi baudrate [rdv40]"}, {"read", CmdFlashMemRead, 1, "Read Flash memory [rdv40]"}, {"info", CmdFlashMemInfo, 1, "Flash memory information [rdv40]"}, {"load", CmdFlashMemLoad, 1, "Load data into flash memory [rdv40]"}, diff --git a/client/cmdmain.c b/client/cmdmain.c index 7c8e3839e..351152179 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -213,7 +213,31 @@ void UsbCommandReceived(UsbCommand* _ch) { memset(s, 0x00, sizeof(s)); size_t len = MIN(c->arg[0], USB_CMD_DATA_SIZE); memcpy(s, c->d.asBytes, len); - + + //#define FLAG_RAWPRINT 0x0111 + //#define FLAG_NOOPT 0x0000 + //#define FLAG_NOLOG 0x0001 + //#define FLAG_NONEWLINE 0x0010 + //#define FLAG_NOPROMPT 0x0100 + uint64_t flag = c->arg[1]; + if (flag > 0) { // FLAG_RAWPRINT) { + switch (flag) { + case FLAG_RAWPRINT: { + printf("%s", s); + } return; break; + case FLAG_NONEWLINE: { + printf("%s\r", s); + } return; break; + case FLAG_NOLOG: { + printf("%s\r\n", s); + } return; break; + // printf("%s", s); + fflush(stdout); + return; + } + } + + // print debug line on same row. escape seq \r if ( c->arg[1] == CMD_MEASURE_ANTENNA_TUNING_HF) { PrintAndLogEx(NORMAL, "\r#db# %s", s); @@ -274,9 +298,9 @@ bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint3 return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_DOWNLOADED_EML_BIGBUF); } case FLASH_MEM: { - UsbCommand c = {CMD_DOWNLOAND_FLASH_MEM, {start_index, bytes, 0}}; + UsbCommand c = {CMD_FLASHMEM_DOWNLOAD, {start_index, bytes, 0}}; SendCommand(&c); - return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_DOWNLOADED_FLASHMEM); + return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_FLASHMEM_DOWNLOADED); } case SIM_MEM: { //UsbCommand c = {CMD_DOWNLOAND_SIM_MEM, {start_index, bytes, 0}}; diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h index 736b11a06..2ced2cd18 100644 --- a/client/hid-flasher/usb_cmd.h +++ b/client/hid-flasher/usb_cmd.h @@ -57,12 +57,12 @@ typedef struct { #define CMD_DOWNLOADED_EML_BIGBUF 0x0111 // RDV40, Flash memory operations -#define CMD_READ_FLASH_MEM 0x0120 -#define CMD_WRITE_FLASH_MEM 0x0121 -#define CMD_WIPE_FLASH_MEM 0x0122 -#define CMD_DOWNLOAND_FLASH_MEM 0x0123 -#define CMD_DOWNLOADED_FLASHMEM 0x0124 -#define CMD_INFO_FLASH_MEM 0x0125 +#define CMD_FLASHMEM_READ 0x0120 +#define CMD_FLASHMEM_WRITE 0x0121 +#define CMD_FLASHMEM_WIPE 0x0122 +#define CMD_FLASHMEM_DOWNLOAD 0x0123 +#define CMD_FLASHMEM_DOWNLOADED 0x0124 +#define CMD_FLASHMEM_INFO 0x0125 // For low-frequency tags #define CMD_READ_TI_TYPE 0x0202 diff --git a/include/common.h b/include/common.h index 8fdb45ab0..8a3f33abd 100644 --- a/include/common.h +++ b/include/common.h @@ -30,6 +30,9 @@ typedef unsigned char byte_t; #define MF_DBG_EXTENDED 4 extern int MF_DBGLEVEL; +// Flashmem spi baudrate +extern uint32_t FLASHMEM_SPIBAUDRATE; + // reader voltage field detector #define MF_MINFIELDV 4000 diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 4de39eef4..51df5896b 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -67,13 +67,17 @@ typedef struct{ #define CMD_DOWNLOAD_EML_BIGBUF 0x0110 #define CMD_DOWNLOADED_EML_BIGBUF 0x0111 + + + // RDV40, Flash memory operations -#define CMD_READ_FLASH_MEM 0x0120 -#define CMD_WRITE_FLASH_MEM 0x0121 -#define CMD_WIPE_FLASH_MEM 0x0122 -#define CMD_DOWNLOAND_FLASH_MEM 0x0123 -#define CMD_DOWNLOADED_FLASHMEM 0x0124 -#define CMD_INFO_FLASH_MEM 0x0125 +#define CMD_FLASHMEM_READ 0x0120 +#define CMD_FLASHMEM_WRITE 0x0121 +#define CMD_FLASHMEM_WIPE 0x0122 +#define CMD_FLASHMEM_DOWNLOAD 0x0123 +#define CMD_FLASHMEM_DOWNLOADED 0x0124 +#define CMD_FLASHMEM_INFO 0x0125 +#define CMD_FLASHMEM_SET_SPIBAUDRATE 0x0126 // RDV40, Smart card operations #define CMD_SMART_RAW 0x0140 diff --git a/tools/mkversion.pl b/tools/mkversion.pl index 6bbc1dfec..1acca6efa 100644 --- a/tools/mkversion.pl +++ b/tools/mkversion.pl @@ -18,13 +18,23 @@ my $fullgitinfo = 'iceman'; my $ctime; # GIT status 0 = dirty, 1 = clean , 2 = undecided my $clean = 2; + # Do we have acces to git command? -my $commandGIT = `bash which git`; +####### +# solves some bug on macos i.e: +## +# perl ../tools/mkversion.pl .. > version.c || cp ../common/default_version.c version.c +# /usr/bin/which: /usr/bin/which: cannot execute binary file +# fatal: No names found, cannot describe anything. +## +# anyway forcing any kind of shell is at least useless, at worst fatal. +my $commandGIT = "env -S which git"; if ( defined($commandGIT) ) { my $githistory = `git fetch --all`; - my $gitversion = `git describe --dirty`; + # now avoiding the "fatal: No names found, cannot describe anything." error by fallbacking to abbrev hash in such case + my $gitversion = `git describe --dirty --always`; my $gitbranch = `git rev-parse --abbrev-ref HEAD`; $clean = $gitversion =~ '-dirty' ? 0 : 1;