From: pwpiwi Date: Tue, 25 Aug 2015 05:53:00 +0000 (+0200) Subject: Merge branch 'master' into topaz X-Git-Tag: v2.3.0~20^2~2 X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/8e21541e77dd0909a99a1ed1106a6df87d34a247?hp=db2b81ba11bdb125a7ee22b226729f4c70acb1ad Merge branch 'master' into topaz --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f9546d9..e2196a39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,28 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... -## [Unreleased][unreleased] +## [unreleased][unreleased] + +### Added +- ISO14443a stand-alone operation with ARM CFLAG="WITH_ISO14443a_StandAlone". This code can read & emulate two banks of 14a tag UIDs and write to "magic" cards (Craig Young) +- AWID26 command context added as 'lf awid' containing realtime demodulation as well as cloning/simulation based on tag numbers (Craig Young) +- Added 'hw status'. This command makes the ARM print out some runtime information. (holiman) +- Added 'hw ping'. This command just sends a usb packets and checks if the pm3 is responsive. Can be used to abort certain operations which supports abort over usb. (holiman) +- Added `data hex2bin` and `data bin2hex` for command line conversion between binary and hexadecimal (holiman) + +### Changed +- Revised workflow for StandAloneMode14a (Craig Young) +- EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers) +- 'hw version' only talks to ARM at startup, after that the info is cached. (pwpiwi) + +## [2.2.0][2015-07-12] ### Changed +- Added `hf 14b raw -s` option to auto select a 14b std tag before raw command - Changed `hf 14b write` to `hf 14b sriwrite` as it only applied to sri tags (marshmellow) - Added `hf 14b info` to `hf search` (marshmellow) +- Added compression of fpga config and data, *BOOTROM REFLASH REQUIRED* (piwi) +- Implemented better detection of mifare-tags that are not vulnerable to classic attacks (`hf mf mifare`, `hf mf nested`) (piwi) ### Added - Add `hf 14b info` to find and print info about std 14b tags and sri tags (using 14b raw commands in the client) (marshmellow) diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index a22c0cb0..6b52a589 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -88,6 +88,16 @@ void BigBuf_free_keep_EM(void) } } +void BigBuf_print_status(void) +{ + Dbprintf("Memory"); + Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE); + Dbprintf(" BigBuf_hi .............%d", BigBuf_hi); + Dbprintf("Tracing"); + Dbprintf(" tracing ................%d", tracing); + Dbprintf(" traceLen ...............%d", traceLen); +} + // return the maximum trace length (i.e. the unallocated size of BigBuf) uint16_t BigBuf_max_traceLen(void) diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index b44a1263..05b4180e 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -24,15 +24,15 @@ extern uint8_t *BigBuf_get_addr(void); extern uint8_t *BigBuf_get_EM_addr(void); extern uint16_t BigBuf_max_traceLen(void); -void BigBuf_Clear(void); +extern void BigBuf_Clear(void); extern uint8_t *BigBuf_malloc(uint16_t); extern void BigBuf_free(void); extern void BigBuf_free_keep_EM(void); - -uint16_t BigBuf_get_traceLen(void); -void clear_trace(); -void set_tracing(bool enable); -bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); -int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader); -uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length); +extern void BigBuf_print_status(void); +extern uint16_t BigBuf_get_traceLen(void); +extern void clear_trace(); +extern void set_tracing(bool enable); +extern bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); +extern int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader); +extern uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length); #endif /* __BIGBUF_H */ diff --git a/armsrc/Makefile b/armsrc/Makefile index 1214c949..a59fa073 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -9,17 +9,17 @@ 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 -APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE \ +#in the next section to remove that particular feature from compilation +APP_CFLAGS = -DWITH_ISO14443a_StandAlone -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE \ -fno-strict-aliasing -ffunction-sections -fdata-sections -#-DWITH_LCD +#-DWITH_LCD #SRC_LCD = fonts.c LCD.c SRC_LF = lfops.c hitag2.c lfsampling.c SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c SRC_ISO14443b = iso14443b.c -SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c +SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c #the FPGA bitstream files. Note: order matters! @@ -65,7 +65,7 @@ ARMSRC = fpgaloader.c \ # Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC include ../common/Makefile.common -OBJS = $(OBJDIR)/fullimage.s19 +OBJS = $(OBJDIR)/fullimage.s19 FPGA_COMPRESSOR = ../client/fpga_compress all: $(OBJS) @@ -80,13 +80,13 @@ $(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) $(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 $^ $@ @@ -94,14 +94,14 @@ $(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,$^) $@ - + $(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,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ - + tarbin: $(OBJS) $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 0cbfa249..38afd85d 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -25,10 +25,16 @@ #include #include "lfsampling.h" #include "BigBuf.h" +#include "mifareutil.h" #ifdef WITH_LCD #include "LCD.h" #endif +// Craig Young - 14a stand-alone code +#ifdef WITH_ISO14443a_StandAlone + #include "iso14443a.h" +#endif + #define abs(x) ( ((x)<0) ? -(x) : (x) ) //============================================================================= @@ -293,18 +299,59 @@ void SendVersion(void) cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, 0, VersionString, strlen(VersionString)); } -#ifdef WITH_LF -// samy's sniff and repeat routine -void SamyRun() +// 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) { - DbpString("Stand-alone mode! No PC necessary."); - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + Dbprintf("USB Speed:"); + Dbprintf(" Sending USB packets to client..."); - // 3 possible options? no just 2 for now -#define OPTS 2 + #define USB_SPEED_TEST_MIN_TIME 1500 // in milliseconds + uint8_t *test_data = BigBuf_get_addr(); + uint32_t end_time; - int high[OPTS], low[OPTS]; + uint32_t start_time = end_time = GetTickCount(); + uint32_t bytes_transferred = 0; + + LED_B_ON(); + while(end_time < start_time + USB_SPEED_TEST_MIN_TIME) { + cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, 0, USB_CMD_DATA_SIZE, 0, test_data, USB_CMD_DATA_SIZE); + end_time = GetTickCount(); + bytes_transferred += USB_CMD_DATA_SIZE; + } + LED_B_OFF(); + + Dbprintf(" Time elapsed: %dms", end_time - start_time); + Dbprintf(" Bytes transferred: %d", bytes_transferred); + Dbprintf(" USB Transfer Speed PM3 -> Client = %d Bytes/s", + 1000 * bytes_transferred / (end_time - start_time)); +} + +/** + * Prints runtime information about the PM3. +**/ +void SendStatus(void) +{ + BigBuf_print_status(); + Fpga_print_status(); + printConfig(); //LF Sampling config + printUSBSpeed(); + Dbprintf("Various"); + Dbprintf(" MF_DBGLEVEL......%d", MF_DBGLEVEL); + Dbprintf(" ToSendMax........%d",ToSendMax); + Dbprintf(" ToSendBit........%d",ToSendBit); + + cmd_send(CMD_ACK,1,0,0,0,0); +} + +#if defined(WITH_ISO14443a_StandAlone) || defined(WITH_LF) + +#define OPTS 2 + +void StandAloneMode() +{ + DbpString("Stand-alone mode! No PC necessary."); // Oooh pretty -- notify user we're in elite samy mode now LED(LED_RED, 200); LED(LED_ORANGE, 200); @@ -316,6 +363,270 @@ void SamyRun() LED(LED_ORANGE, 200); LED(LED_RED, 200); +} + +#endif + + + +#ifdef WITH_ISO14443a_StandAlone +void StandAloneMode14a() +{ + StandAloneMode(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + + int selected = 0; + int playing = 0, iGotoRecord = 0, iGotoClone = 0; + int cardRead[OPTS] = {0}; + uint8_t readUID[10] = {0}; + uint32_t uid_1st[OPTS]={0}; + uint32_t uid_2nd[OPTS]={0}; + uint32_t uid_tmp1 = 0; + uint32_t uid_tmp2 = 0; + iso14a_card_select_t hi14a_card[OPTS]; + + 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: %u]...", selected); + /* need this delay to prevent catching some weird data */ + SpinDelay(500); + /* Code for reading from 14a tag */ + uint8_t uid[10] ={0}; + uint32_t cuid; + 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(uid, &hi14a_card[selected], &cuid)) + continue; + else + { + Dbprintf("Read UID:"); Dbhexdump(10,uid,0); + memcpy(readUID,uid,10*sizeof(uint8_t)); + uint8_t *dst = (uint8_t *)&uid_tmp1; + // Set UID byte order + for (int i=0; i<4; i++) + dst[i] = uid[3-i]; + dst = (uint8_t *)&uid_tmp2; + for (int i=0; i<4; i++) + dst[i] = uid[7-i]; + if (uid_1st[(selected+1)%OPTS] == uid_tmp1 && uid_2nd[(selected+1)%OPTS] == uid_tmp2) { + Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping."); + } + else { + if (uid_tmp2) { + Dbprintf("Bank[%d] received a 7-byte UID",selected); + uid_1st[selected] = (uid_tmp1)>>8; + uid_2nd[selected] = (uid_tmp1<<24) + (uid_tmp2>>8); + } + else { + Dbprintf("Bank[%d] received a 4-byte UID",selected); + uid_1st[selected] = uid_tmp1; + uid_2nd[selected] = uid_tmp2; + } + break; + } + } + } + Dbprintf("ATQA = %02X%02X",hi14a_card[selected].atqa[0],hi14a_card[selected].atqa[1]); + Dbprintf("SAK = %02X",hi14a_card[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); + + + // record + Dbprintf("Preparing to Clone card [Bank: %x]; uid: %08x", selected, uid_1st[selected]); + + // wait for button to be released + while(BUTTON_PRESS()) + { + // Delay cloning until card is in place + WDT_HIT(); + } + Dbprintf("Starting clone. [Bank: %u]", 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, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}}; + memcpy(c.d.asBytes, data, 16); + SendCommand(&c); + + Block read is similar: + UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, 0, blockNo}}; + 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->arg[2], c->d.asBytes); + break; + case CMD_MIFARE_CGETBLOCK: + MifareCGetBlock(c->arg[0], c->arg[1], c->arg[2], 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, CSETBLOCK_SINGLE_OPER) to write it + */ + uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0}; + // arg0 = Flags == CSETBLOCK_SINGLE_OPER=0x1F, arg1=returnSlot, arg2=blockNo + MifareCGetBlock(0x3F, 1, 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_1st for bank (2nd is for longer UIDs not supported if classic) + + newBlock0[0] = uid_1st[selected]>>24; + newBlock0[1] = 0xFF & (uid_1st[selected]>>16); + newBlock0[2] = 0xFF & (uid_1st[selected]>>8); + newBlock0[3] = 0xFF & (uid_1st[selected]); + newBlock0[4] = newBlock0[0]^newBlock0[1]^newBlock0[2]^newBlock0[3]; + // arg0 = needWipe, arg1 = workFlags, arg2 = blockNo, datain + MifareCSetBlock(0, 0xFF,0, newBlock0); + MifareCGetBlock(0x3F, 1, 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 + if (playing) + { + 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 data[512] = {0}; // in case there is a read command received we shouldn't break + Dbprintf("Simulating ISO14443a tag with uid[0]: %08x, uid[1]: %08x [Bank: %u]", uid_1st[selected],uid_2nd[selected],selected); + if (hi14a_card[selected].sak == 8 && hi14a_card[selected].atqa[0] == 4 && hi14a_card[selected].atqa[1] == 0) { + DbpString("Mifare Classic"); + SimulateIso14443aTag(1,uid_1st[selected], uid_2nd[selected], data); // Mifare Classic + } + else if (hi14a_card[selected].sak == 0 && hi14a_card[selected].atqa[0] == 0x44 && hi14a_card[selected].atqa[1] == 0) { + DbpString("Mifare Ultralight"); + SimulateIso14443aTag(2,uid_1st[selected],uid_2nd[selected],data); // Mifare Ultralight + } + else if (hi14a_card[selected].sak == 20 && hi14a_card[selected].atqa[0] == 0x44 && hi14a_card[selected].atqa[1] == 3) { + DbpString("Mifare DESFire"); + SimulateIso14443aTag(3,uid_1st[selected],uid_2nd[selected],data); // Mifare DESFire + } + else { + Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation"); + SimulateIso14443aTag(1,uid_1st[selected], uid_2nd[selected], 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); + } + else + while(BUTTON_PRESS()) + WDT_HIT(); + } + } +} +#elif WITH_LF +// samy's sniff and repeat routine +void SamyRun() +{ + StandAloneMode(); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + int high[OPTS], low[OPTS]; int selected = 0; int playing = 0; int cardRead = 0; @@ -326,7 +637,7 @@ void SamyRun() for (;;) { usb_poll(); - WDT_HIT(); + WDT_HIT(); // Was our button held down or pressed? int button_pressed = BUTTON_HELD(1000); @@ -439,8 +750,8 @@ void SamyRun() } } } -#endif +#endif /* OBJECTIVE Listen and detect an external reader. Determine the best location @@ -667,6 +978,7 @@ void UsbPacketReceived(uint8_t *packet, int len) break; case CMD_T55XX_WRITE_BLOCK: T55xxWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); + cmd_send(CMD_ACK,0,0,0,0,0); break; case CMD_T55XX_READ_TRACE: T55xxReadTrace(); @@ -681,6 +993,9 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_EM4X_WRITE_WORD: EM4xWriteWord(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); break; + case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation + CmdAWIDdemodFSK(c->arg[0], 0, 0, 1); + break; #endif #ifdef WITH_HITAG @@ -929,7 +1244,12 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_VERSION: SendVersion(); break; - + case CMD_STATUS: + SendStatus(); + break; + case CMD_PING: + cmd_send(CMD_ACK,0,0,0,0,0); + break; #ifdef WITH_LCD case CMD_LCD_RESET: LCDReset(); @@ -1028,8 +1348,16 @@ void __attribute__((noreturn)) AppMain(void) WDT_HIT(); #ifdef WITH_LF +#ifndef WITH_ISO14443a_StandAlone if (BUTTON_HELD(1000) > 0) SamyRun(); +#endif +#endif +#ifdef WITH_ISO14443a +#ifdef WITH_ISO14443a_StandAlone + if (BUTTON_HELD(1000) > 0) + StandAloneMode14a(); +#endif #endif } } diff --git a/armsrc/apps.h b/armsrc/apps.h index bb094b33..b5638ee1 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -69,6 +69,7 @@ void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream); void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream); void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol); +void CmdAWIDdemodFSK(int findone, int *high, int *low, int ledcontrol); // Realtime demodulation mode for AWID26 void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol); void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol); void CopyIOtoT55x7(uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an ioProx card to T5557/T5567 @@ -121,7 +122,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) //void MifareUWriteBlockCompat(uint8_t arg0,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 MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, 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); void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); diff --git a/armsrc/epa.c b/armsrc/epa.c index 6bd8692e..50c7d878 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -12,10 +12,11 @@ //----------------------------------------------------------------------------- #include "iso14443a.h" +#include "iso14443b.h" #include "epa.h" #include "cmd.h" -// Protocol and Parameter Selection Request +// Protocol and Parameter Selection Request for ISO 14443 type A cards // use regular (1x) speed in both directions // CRC is already included static const uint8_t pps[] = {0xD0, 0x11, 0x00, 0x52, 0xA6}; @@ -100,6 +101,28 @@ static struct { // lengths of the replay APDUs static uint8_t apdu_lengths_replay[5]; +// type of card (ISO 14443 A or B) +static char iso_type = 0; + +//----------------------------------------------------------------------------- +// Wrapper for sending APDUs to type A and B cards +//----------------------------------------------------------------------------- +int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response) +{ + switch(iso_type) + { + case 'a': + return iso14_apdu(apdu, (uint16_t) length, response); + break; + case 'b': + return iso14443b_apdu(apdu, length, response); + break; + default: + return 0; + break; + } +} + //----------------------------------------------------------------------------- // Closes the communication channel and turns off the field //----------------------------------------------------------------------------- @@ -107,6 +130,7 @@ void EPA_Finish() { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); + iso_type = 0; } //----------------------------------------------------------------------------- @@ -204,26 +228,26 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) int rapdu_length = 0; // select the file EF.CardAccess - rapdu_length = iso14_apdu((uint8_t *)apdu_select_binary_cardaccess, + rapdu_length = EPA_APDU((uint8_t *)apdu_select_binary_cardaccess, sizeof(apdu_select_binary_cardaccess), response_apdu); - if (rapdu_length != 6 + if (rapdu_length < 6 || response_apdu[rapdu_length - 4] != 0x90 || response_apdu[rapdu_length - 3] != 0x00) { - Dbprintf("epa - no select cardaccess"); + DbpString("Failed to select EF.CardAccess!"); return -1; } // read the file - rapdu_length = iso14_apdu((uint8_t *)apdu_read_binary, + rapdu_length = EPA_APDU((uint8_t *)apdu_read_binary, sizeof(apdu_read_binary), response_apdu); if (rapdu_length <= 6 || response_apdu[rapdu_length - 4] != 0x90 || response_apdu[rapdu_length - 3] != 0x00) { - Dbprintf("epa - no read cardaccess"); + Dbprintf("Failed to read EF.CardAccess!"); return -1; } @@ -338,7 +362,7 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce) // send it uint8_t response_apdu[262]; - int send_return = iso14_apdu(apdu, + int send_return = EPA_APDU(apdu, sizeof(apdu), response_apdu); // check if the command succeeded @@ -409,7 +433,7 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password) apdu[4] = apdu_length - 5; // send it uint8_t response_apdu[6]; - int send_return = iso14_apdu(apdu, + int send_return = EPA_APDU(apdu, apdu_length, response_apdu); // check if the command succeeded @@ -460,16 +484,13 @@ void EPA_PACE_Replay(UsbCommand *c) return; } - // increase the timeout (at least some cards really do need this!)///////////// - // iso14a_set_timeout(0x0003FFFF); - // response APDU uint8_t response_apdu[300] = {0}; // now replay the data and measure the timings for (int i = 0; i < sizeof(apdu_lengths_replay); i++) { StartCountUS(); - func_return = iso14_apdu(apdus_replay[i].data, + func_return = EPA_APDU(apdus_replay[i].data, apdu_lengths_replay[i], response_apdu); timings[i] = GetCountUS(); @@ -501,18 +522,33 @@ int EPA_Setup() uint8_t pps_response_par[1]; iso14a_card_select_t card_select_info; + // first, look for type A cards // power up the field iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); // select the card return_code = iso14443a_select_card(uid, &card_select_info, NULL); - if (return_code != 1) { - return 1; + if (return_code == 1) { + // send the PPS request + ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL); + return_code = ReaderReceive(pps_response, pps_response_par); + if (return_code != 3 || pps_response[0] != 0xD0) { + return return_code == 0 ? 2 : return_code; + } + Dbprintf("ISO 14443 Type A"); + iso_type = 'a'; + return 0; } - // send the PPS request - ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL); - return_code = ReaderReceive(pps_response, pps_response_par); - if (return_code != 3 || pps_response[0] != 0xD0) { - return return_code == 0 ? 2 : return_code; + + // if we're here, there is no type A card, so we look for type B + // power up the field + iso14443b_setup(); + // select the card + return_code = iso14443b_select_card(); + if (return_code == 1) { + Dbprintf("ISO 14443 Type B"); + iso_type = 'b'; + return 0; } - return 0; + Dbprintf("No card found."); + return 1; } diff --git a/armsrc/epa.h b/armsrc/epa.h index 0c580205..d2ebed57 100644 --- a/armsrc/epa.h +++ b/armsrc/epa.h @@ -19,7 +19,7 @@ typedef struct { uint8_t parameter_id; } pace_version_info_t; -// note: EPA_PACE_Collect_Nonce is declared in apps.h +// note: EPA_PACE_Collect_Nonce and EPA_PACE_Replay are declared in apps.h // general functions void EPA_Finish(); diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 16fed7c5..308dda8c 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -558,3 +558,11 @@ void SetAdcMuxFor(uint32_t whichGpio) HIGH(whichGpio); } + +void Fpga_print_status(void) +{ + Dbprintf("Fgpa"); + if(downloaded_bitstream == FPGA_BITSTREAM_HF) Dbprintf(" mode.............HF"); + else if(downloaded_bitstream == FPGA_BITSTREAM_LF) Dbprintf(" mode.............LF"); + else Dbprintf(" mode.............%d", downloaded_bitstream); +} diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 0bad3809..52d6c677 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -17,6 +17,7 @@ void FpgaGatherVersion(int bitstream_version, char *dst, int len); void FpgaSetupSsc(void); void SetupSpi(int mode); bool FpgaSetupSscDma(uint8_t *buf, int len); +void Fpga_print_status(); #define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; #define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; void SetAdcMuxFor(uint32_t whichGpio); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index a4e5ceaf..9fa9fe4f 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1070,7 +1070,6 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) LED_A_ON(); for(;;) { // Clean receive command buffer - if(!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { DbpString("Button press"); break; diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 33c047d8..82e5dd6a 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -19,6 +19,9 @@ #define RECEIVE_SAMPLES_TIMEOUT 2000 #define ISO14443B_DMA_BUFFER_SIZE 256 +// PCB Block number for APDUs +static uint8_t pcb_blocknum = 0; + //============================================================================= // 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 @@ -311,7 +314,7 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) } } } - + return FALSE; } @@ -321,10 +324,14 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) //----------------------------------------------------------------------------- void SimulateIso14443bTag(void) { - // the only commands we understand is REQB, AFI=0, Select All, N=0: - static const uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; - // ... and REQB, AFI=0, Normal Request, N=0: - static const uint8_t cmd2[] = { 0x05, 0x00, 0x00, 0x71, 0xFF }; + // the only commands we understand is WUPB, AFI=0, Select All, N=1: + static const uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; // WUPB + // ... and REQB, AFI=0, Normal Request, N=1: + static const uint8_t cmd2[] = { 0x05, 0x00, 0x00, 0x71, 0xFF }; // REQB + // ... and HLTB + static const uint8_t cmd3[] = { 0x50, 0xff, 0xff, 0xff, 0xff }; // HLTB + // ... and ATTRIB + static const uint8_t cmd4[] = { 0x1D, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // ATTRIB // ... and we always respond with ATQB, PUPI = 820de174, Application Data = 0x20381922, // supports only 106kBit/s in both directions, max frame size = 32Bytes, @@ -333,6 +340,9 @@ void SimulateIso14443bTag(void) 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22, 0x00, 0x21, 0x85, 0x5e, 0xd7 }; + // response to HLTB and ATTRIB + static const uint8_t response2[] = {0x00, 0x78, 0xF0}; + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); @@ -353,9 +363,15 @@ void SimulateIso14443bTag(void) // prepare the (only one) tag answer: CodeIso14443bAsTag(response1, sizeof(response1)); uint8_t *resp1Code = BigBuf_malloc(ToSendMax); - memcpy(resp1Code, ToSend, ToSendMax); + memcpy(resp1Code, ToSend, ToSendMax); uint16_t resp1CodeLen = ToSendMax; + // prepare the (other) tag answer: + CodeIso14443bAsTag(response2, sizeof(response2)); + uint8_t *resp2Code = BigBuf_malloc(ToSendMax); + memcpy(resp2Code, ToSend, ToSendMax); + uint16_t resp2CodeLen = ToSendMax; + // We need to listen to the high-frequency, peak-detected path. SetAdcMuxFor(GPIO_MUXSEL_HIPKD); FpgaSetupSsc(); @@ -377,22 +393,37 @@ void SimulateIso14443bTag(void) // Good, look at the command now. if ( (len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len) == 0) || (len == sizeof(cmd2) && memcmp(receivedCmd, cmd2, len) == 0) ) { - resp = response1; + resp = response1; respLen = sizeof(response1); - respCode = resp1Code; + respCode = resp1Code; respCodeLen = resp1CodeLen; + } else if ( (len == sizeof(cmd3) && receivedCmd[0] == cmd3[0]) + || (len == sizeof(cmd4) && receivedCmd[0] == cmd4[0]) ) { + resp = response2; + respLen = sizeof(response2); + respCode = resp2Code; + respCodeLen = resp2CodeLen; } else { Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsRecvd); // And print whether the CRC fails, just for good measure uint8_t b1, b2; - ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2); - if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) { - // Not so good, try again. - DbpString("+++CRC fail"); - } else { - DbpString("CRC passes"); + if (len >= 3){ // if crc exists + ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2); + if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) { + // Not so good, try again. + DbpString("+++CRC fail"); + + } else { + DbpString("CRC passes"); + } } - break; + //get rid of compiler warning + respCodeLen = 0; + resp = response1; + respLen = 0; + respCode = resp1Code; + //don't crash at new command just wait and see if reader will send other new cmds. + //break; } cmdsRecvd++; @@ -429,13 +460,13 @@ void SimulateIso14443bTag(void) (void)b; } } - + // trace the response: if (tracing) { uint8_t parity[MAX_PARITY_SIZE]; LogTrace(resp, respLen, 0, 0, parity, FALSE); } - + } } @@ -513,7 +544,7 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq) } else { \ v -= cq; \ } \ - } + } */ // Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq))) #define CHECK_FOR_SUBCARRIER() { \ @@ -547,7 +578,7 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq) } \ } \ } - + switch(Demod.state) { case DEMOD_UNSYNCD: CHECK_FOR_SUBCARRIER(); @@ -645,7 +676,7 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq) Demod.metric -= Demod.thisBit; } (Demod.metricN)++; -*/ +*/ Demod.shiftReg >>= 1; if(Demod.thisBit > 0) { // logic '1' @@ -713,10 +744,10 @@ static void GetSamplesFor14443bDemod(int n, bool quiet) // Allocate memory from BigBuf for some buffers // free all previous allocations first BigBuf_free(); - + // The response (tag -> reader) that we're receiving. uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE); - + // The DMA buffer, used to stream samples from the FPGA int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); @@ -896,6 +927,98 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) } } +/* Sends an APDU to the tag + * TODO: check CRC and preamble + */ +int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response) +{ + uint8_t message_frame[message_length + 4]; + // PCB + message_frame[0] = 0x0A | pcb_blocknum; + pcb_blocknum ^= 1; + // CID + message_frame[1] = 0; + // INF + memcpy(message_frame + 2, message, message_length); + // EDC (CRC) + ComputeCrc14443(CRC_14443_B, message_frame, message_length + 2, &message_frame[message_length + 2], &message_frame[message_length + 3]); + // send + CodeAndTransmit14443bAsReader(message_frame, message_length + 4); + // get response + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT*100, TRUE); + if(Demod.len < 3) + { + return 0; + } + // TODO: Check CRC + // copy response contents + if(response != NULL) + { + memcpy(response, Demod.output, Demod.len); + } + return Demod.len; +} + +/* Perform the ISO 14443 B Card Selection procedure + * Currently does NOT do any collision handling. + * It expects 0-1 cards in the device's range. + * TODO: Support multiple cards (perform anticollision) + * TODO: Verify CRC checksums + */ +int iso14443b_select_card() +{ + // WUPB command (including CRC) + // Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state + static const uint8_t wupb[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; + // ATTRIB command (with space for CRC) + uint8_t attrib[] = { 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}; + + // first, wake up the tag + CodeAndTransmit14443bAsReader(wupb, sizeof(wupb)); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + // ATQB too short? + if (Demod.len < 14) + { + return 2; + } + + // select the tag + // copy the PUPI to ATTRIB + memcpy(attrib + 1, Demod.output + 1, 4); + /* copy the protocol info from ATQB (Protocol Info -> Protocol_Type) into + ATTRIB (Param 3) */ + attrib[7] = Demod.output[10] & 0x0F; + ComputeCrc14443(CRC_14443_B, attrib, 9, attrib + 9, attrib + 10); + CodeAndTransmit14443bAsReader(attrib, sizeof(attrib)); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + // Answer to ATTRIB too short? + if(Demod.len < 3) + { + return 2; + } + // reset PCB block number + pcb_blocknum = 0; + return 1; +} + +// Set up ISO 14443 Type B communication (similar to iso14443a_setup) +void iso14443b_setup() { + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // Set up the synchronous serial port + FpgaSetupSsc(); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + + // Signal field is on with the appropriate LED + LED_D_ON(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); + + // Start the timer + StartCountSspClk(); + + DemodReset(); + UartReset(); +} //----------------------------------------------------------------------------- // Read a SRI512 ISO 14443B tag. @@ -1090,7 +1213,7 @@ void RAMFUNC SnoopIso14443b(void) bool TagIsActive = FALSE; bool ReaderIsActive = FALSE; - + // And now we loop, receiving samples. for(;;) { int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & @@ -1200,16 +1323,18 @@ void SendRawCommand14443B(uint32_t datalen, uint32_t recv, uint8_t powerfield, u SetAdcMuxFor(GPIO_MUXSEL_HIPKD); FpgaSetupSsc(); - set_tracing(TRUE); - - CodeAndTransmit14443bAsReader(data, datalen); + if (datalen){ + set_tracing(TRUE); + + CodeAndTransmit14443bAsReader(data, datalen); - if(recv) { - GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); - uint16_t iLen = MIN(Demod.len, USB_CMD_DATA_SIZE); - cmd_send(CMD_ACK, iLen, 0, 0, Demod.output, iLen); + if(recv) { + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + uint16_t iLen = MIN(Demod.len, USB_CMD_DATA_SIZE); + cmd_send(CMD_ACK, iLen, 0, 0, Demod.output, iLen); + } } - + if(!powerfield) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); diff --git a/armsrc/iso14443b.h b/armsrc/iso14443b.h new file mode 100644 index 00000000..f90c54f3 --- /dev/null +++ b/armsrc/iso14443b.h @@ -0,0 +1,21 @@ +//----------------------------------------------------------------------------- +// Merlok - June 2011 +// Gerhard de Koning Gans - May 2008 +// Hagen Fritsch - June 2010 +// +// 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. +//----------------------------------------------------------------------------- +// Routines to support ISO 14443 type A. +//----------------------------------------------------------------------------- + +#ifndef __ISO14443B_H +#define __ISO14443B_H +#include "common.h" + +int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response); +void iso14443b_setup(); +int iso14443b_select_card(); + +#endif /* __ISO14443B_H */ diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 7e53d4a5..733bc953 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -402,7 +402,7 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol) for(;;) { //wait until SSC_CLK goes HIGH while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) { - if(BUTTON_PRESS() || usb_poll()) { + if(BUTTON_PRESS() || (usb_poll_validate_length() )) { DbpString("Stopped"); return; } @@ -841,6 +841,96 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol) if (ledcontrol) LED_A_OFF(); } +// loop to get raw HID waveform then FSK demodulate the TAG ID from it +void CmdAWIDdemodFSK(int findone, int *high, int *low, int ledcontrol) +{ + uint8_t *dest = BigBuf_get_addr(); + //const size_t sizeOfBigBuff = BigBuf_max_traceLen(); + size_t size; + int idx=0; + // Configure to go in 125Khz listen mode + LFSetupFPGAForADC(95, true); + + while(!BUTTON_PRESS()) { + + WDT_HIT(); + if (ledcontrol) LED_A_ON(); + + DoAcquisition_default(-1,true); + // FSK demodulator + //size = sizeOfBigBuff; //variable size will change after demod so re initialize it before use + size = 50*128*2; //big enough to catch 2 sequences of largest format + idx = AWIDdemodFSK(dest, &size); + + if (idx>0 && size==96){ + // Index map + // 0 10 20 30 40 50 60 + // | | | | | | | + // 01234567 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 - to 96 + // ----------------------------------------------------------------------------- + // 00000001 000 1 110 1 101 1 011 1 101 1 010 0 000 1 000 1 010 0 001 0 110 1 100 0 000 1 000 1 + // premable bbb o bbb o bbw o fff o fff o ffc o ccc o ccc o ccc o ccc o ccc o wxx o xxx o xxx o - to 96 + // |---26 bit---| |-----117----||-------------142-------------| + // b = format bit len, o = odd parity of last 3 bits + // f = facility code, c = card number + // w = wiegand parity + // (26 bit format shown) + + //get raw ID before removing parities + uint32_t rawLo = bytebits_to_byte(dest+idx+64,32); + uint32_t rawHi = bytebits_to_byte(dest+idx+32,32); + uint32_t rawHi2 = bytebits_to_byte(dest+idx,32); + + size = removeParity(dest, idx+8, 4, 1, 88); + // ok valid card found! + + // Index map + // 0 10 20 30 40 50 60 + // | | | | | | | + // 01234567 8 90123456 7890123456789012 3 456789012345678901234567890123456 + // ----------------------------------------------------------------------------- + // 00011010 1 01110101 0000000010001110 1 000000000000000000000000000000000 + // bbbbbbbb w ffffffff cccccccccccccccc w xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // |26 bit| |-117--| |-----142------| + // b = format bit len, o = odd parity of last 3 bits + // f = facility code, c = card number + // w = wiegand parity + // (26 bit format shown) + + uint32_t fc = 0; + uint32_t cardnum = 0; + uint32_t code1 = 0; + uint32_t code2 = 0; + uint8_t fmtLen = bytebits_to_byte(dest,8); + if (fmtLen==26){ + fc = bytebits_to_byte(dest+9, 8); + cardnum = bytebits_to_byte(dest+17, 16); + code1 = bytebits_to_byte(dest+8,fmtLen); + Dbprintf("AWID Found - BitLength: %d, FC: %d, Card: %d - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo); + } else { + cardnum = bytebits_to_byte(dest+8+(fmtLen-17), 16); + if (fmtLen>32){ + code1 = bytebits_to_byte(dest+8,fmtLen-32); + code2 = bytebits_to_byte(dest+8+(fmtLen-32),32); + Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo); + } else{ + code1 = bytebits_to_byte(dest+8,fmtLen); + Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); + } + } + if (findone){ + if (ledcontrol) LED_A_OFF(); + return; + } + // reset + } + idx = 0; + WDT_HIT(); + } + DbpString("Stopped"); + if (ledcontrol) LED_A_OFF(); +} + void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol) { uint8_t *dest = BigBuf_get_addr(); diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 120c0801..6e783769 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -17,7 +17,7 @@ sample_config config = { 1, 8, 1, 95, 0 } ; void printConfig() { - Dbprintf("Sampling config: "); + Dbprintf("LF Sampling config: "); Dbprintf(" [q] divisor: %d ", config.divisor); Dbprintf(" [b] bps: %d ", config.bits_per_sample); Dbprintf(" [d] decimation: %d ", config.decimation); @@ -119,8 +119,7 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) * @param silent - is true, now outputs are made. If false, dbprints the status * @return the number of bits occupied by the samples. */ - -uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold,bool silent) +uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent) { //. uint8_t *dest = BigBuf_get_addr(); @@ -151,8 +150,12 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; LED_D_OFF(); - if (trigger_threshold > 0 && sample < trigger_threshold) + // threshold either high or low values 128 = center 0. if trigger = 178 + if ((trigger_threshold > 0) && (sample < (trigger_threshold+128)) && (sample > (128-trigger_threshold))) // continue; + + //if (trigger_threshold > 0 && sample < trigger_threshold) // + //continue; trigger_threshold = 0; sample_total_numbers++; diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index 6c671ec8..7d3925cd 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -56,4 +56,8 @@ void LFSetupFPGAForADC(int divisor, bool lf_field); void setSamplingConfig(sample_config *sc); sample_config * getSamplingConfig(); + +void printConfig(); + + #endif // LFSAMPLING_H diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index c2d85abb..a3d6609d 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -642,8 +642,8 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat // free eventually allocated BigBuf memory BigBuf_free(); - clear_trace(); - set_tracing(false); + if (calibrate) clear_trace(); + set_tracing(true); // statistics on nonce distance int16_t isOK = 0; @@ -820,18 +820,18 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - set_tracing(TRUE); } //----------------------------------------------------------------------------- // MIFARE check keys. key count up to 85. // //----------------------------------------------------------------------------- -void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) +void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { // params - uint8_t blockNo = arg0; - uint8_t keyType = arg1; + uint8_t blockNo = arg0 & 0xff; + uint8_t keyType = (arg0 >> 8) & 0xff; + bool clearTrace = arg1; uint8_t keyCount = arg2; uint64_t ui64Key = 0; @@ -853,7 +853,7 @@ void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) LED_C_OFF(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); + if (clearTrace) clear_trace(); set_tracing(TRUE); for (i = 0; i < keyCount; i++) { @@ -1143,6 +1143,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai // bit 2 - need HALT after sequence // bit 3 - need init FPGA and field before sequence // bit 4 - need reset FPGA and LED + // bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a) uint8_t workFlags = arg0; uint8_t blockNo = arg2; @@ -1202,7 +1203,12 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai } LED_B_ON(); - cmd_send(CMD_ACK,isOK,0,0,data,18); + if (workFlags & 0x20) { + if (isOK) + memcpy(datain, data, 18); + } + else + cmd_send(CMD_ACK,isOK,0,0,data,18); LED_B_OFF(); if ((workFlags & 0x10) || (!isOK)) { diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 85a34ef6..7a09ce64 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -8,6 +8,7 @@ //----------------------------------------------------------------------------- // code for work with mifare cards. //----------------------------------------------------------------------------- +#include "crapto1.h" #ifndef __MIFAREUTIL_H #define __MIFAREUTIL_H diff --git a/armsrc/util.c b/armsrc/util.c index 8576ddce..1dd8dc75 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -304,11 +304,12 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers void StartTickCount() { -// must be 0x40, but on my cpu - included divider is optimal -// 0x20 - 1 ms / bit -// 0x40 - 2 ms / bit - - AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST + 0x001D; // was 0x003B + // This timer is based on the slow clock. The slow clock frequency is between 22kHz and 40kHz. + // We can determine the actual slow clock frequency by looking at the Main Clock Frequency Register. + uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & 0xffff; // = 16 * main clock frequency (16MHz) / slow clock frequency + // set RealTimeCounter divider to count at 1kHz: + AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf/2)) / mainf); + // note: worst case precision is approx 2.5% } /* diff --git a/client/Makefile b/client/Makefile index f768f3d8..903cbf9e 100644 --- a/client/Makefile +++ b/client/Makefile @@ -90,6 +90,7 @@ CMDSRCS = nonce2key/crapto1.c\ cmdlf.c \ cmdlfio.c \ cmdlfhid.c \ + cmdlfawid.c \ cmdlfem4x.c \ cmdlfhitag.c \ cmdlfti.c \ diff --git a/client/cmddata.c b/client/cmddata.c index bec1b5aa..22da1805 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -24,10 +24,11 @@ #include "usb_cmd.h" #include "crc.h" #include "crc16.h" +#include "loclass/cipherutils.h" uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; -uint8_t g_debugMode; -size_t DemodBufferLen; +uint8_t g_debugMode=0; +size_t DemodBufferLen=0; static int CmdHelp(const char *Cmd); //set the demod buffer with given array of binary (one bit per byte) @@ -1491,9 +1492,9 @@ int CmdFDXBdemodBI(const char *Cmd){ setDemodBuf(BitStream, 128, preambleIndex); - // remove but don't verify parity. (pType = 2) + // remove marker bits (1's every 9th digit after preamble) (pType = 2) size = removeParity(BitStream, preambleIndex + 11, 9, 2, 117); - if ( size <= 103 ) { + if ( size != 104 ) { if (g_debugMode) PrintAndLog("Error removeParity:: %d", size); return 0; } @@ -1943,26 +1944,14 @@ int CmdHpf(const char *Cmd) RepaintGraphWindow(); return 0; } -typedef struct { - uint8_t * buffer; - uint32_t numbits; - uint32_t position; -}BitstreamOut; -bool _headBit( BitstreamOut *stream) -{ - int bytepos = stream->position >> 3; // divide by 8 - int bitpos = (stream->position++) & 7; // mask out 00000111 - return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1; -} - -uint8_t getByte(uint8_t bits_per_sample, BitstreamOut* b) +uint8_t getByte(uint8_t bits_per_sample, BitstreamIn* b) { int i; uint8_t val = 0; for(i =0 ; i < bits_per_sample; i++) { - val |= (_headBit(b) << (7-i)); + val |= (headBit(b) << (7-i)); } return val; } @@ -2002,7 +1991,7 @@ int getSamples(const char *Cmd, bool silent) if(bits_per_sample < 8) { PrintAndLog("Unpacking..."); - BitstreamOut bout = { got, bits_per_sample * n, 0}; + BitstreamIn bout = { got, bits_per_sample * n, 0}; int j =0; for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) { uint8_t sample = getByte(bits_per_sample, &bout); @@ -2265,6 +2254,99 @@ int CmdZerocrossings(const char *Cmd) return 0; } +int usage_data_bin2hex(){ + PrintAndLog("Usage: data bin2hex "); + PrintAndLog(" This function will ignore all characters not 1 or 0 (but stop reading on whitespace)"); + return 0; +} + +/** + * @brief Utility for conversion via cmdline. + * @param Cmd + * @return + */ +int Cmdbin2hex(const char *Cmd) +{ + int bg =0, en =0; + if(param_getptr(Cmd, &bg, &en, 0)) + { + return usage_data_bin2hex(); + } + //Number of digits supplied as argument + size_t length = en - bg +1; + size_t bytelen = (length+7) / 8; + uint8_t* arr = (uint8_t *) malloc(bytelen); + memset(arr, 0, bytelen); + BitstreamOut bout = { arr, 0, 0 }; + + for(; bg <= en ;bg++) + { + char c = Cmd[bg]; + if( c == '1') pushBit(&bout, 1); + else if( c == '0') pushBit(&bout, 0); + else PrintAndLog("Ignoring '%c'", c); + } + + if(bout.numbits % 8 != 0) + { + printf("[padded with %d zeroes]\n", 8-(bout.numbits % 8)); + } + + //Uses printf instead of PrintAndLog since the latter + // adds linebreaks to each printout - this way was more convenient since we don't have to + // allocate a string and write to that first... + for(size_t x = 0; x < bytelen ; x++) + { + printf("%02X", arr[x]); + } + printf("\n"); + free(arr); + return 0; +} + +int usage_data_hex2bin(){ + + PrintAndLog("Usage: data bin2hex "); + PrintAndLog(" This function will ignore all non-hexadecimal characters (but stop reading on whitespace)"); + return 0; + +} + +int Cmdhex2bin(const char *Cmd) +{ + int bg =0, en =0; + if(param_getptr(Cmd, &bg, &en, 0)) + { + return usage_data_hex2bin(); + } + + + while(bg <= en ) + { + char x = Cmd[bg++]; + // capitalize + if (x >= 'a' && x <= 'f') + x -= 32; + // convert to numeric value + if (x >= '0' && x <= '9') + x -= '0'; + else if (x >= 'A' && x <= 'F') + x -= 'A' - 10; + else + continue; + + //Uses printf instead of PrintAndLog since the latter + // adds linebreaks to each printout - this way was more convenient since we don't have to + // allocate a string and write to that first... + + for(int i= 0 ; i < 4 ; ++i) + printf("%d",(x >> (3 - i)) & 1); + } + printf("\n"); + + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, @@ -2273,6 +2355,7 @@ static command_t CommandTable[] = {"askgproxiidemod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II tag from GraphBuffer"}, {"autocorr", CmdAutoCorr, 1, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"}, {"biphaserawdecode",CmdBiphaseDecodeRaw,1, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"}, + {"bin2hex", Cmdbin2hex, 1, "bin2hex -- Converts binary to hexadecimal"}, {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"}, {"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"}, {"dec", CmdDec, 1, "Decimate samples"}, @@ -2287,6 +2370,7 @@ static command_t CommandTable[] = {"getbitstream", CmdGetBitStream, 1, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"}, {"grid", CmdGrid, 1, " -- overlay grid on graph window, use zero value to turn off either"}, {"hexsamples", CmdHexsamples, 0, " [] -- Dump big buffer as hex bytes"}, + {"hex2bin", Cmdhex2bin, 1, "hex2bin -- Converts hexadecimal to binary"}, {"hide", CmdHide, 1, "Hide graph window"}, {"hpf", CmdHpf, 1, "Remove DC offset from trace"}, {"load", CmdLoad, 1, " -- Load trace (to graph window"}, diff --git a/client/cmdhf.c b/client/cmdhf.c index 4777a0f4..ee0b4fd8 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -484,7 +484,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); } uint8_t parityBits = parityBytes[j>>3]; - if (protocol != ISO_14443B && isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { + if (protocol != ISO_14443B && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]); } else { snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x ", frame[j]); diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index d1d668e9..36932cbd 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -132,17 +132,21 @@ int CmdHF14BCmdRaw (const char *Cmd) { bool reply = true; bool crc = false; bool power = false; + bool select = false; + bool SRx = false; char buf[5] = ""; uint8_t data[100] = {0x00}; uint8_t datalen = 0; unsigned int temp; int i = 0; if (strlen(Cmd)<3) { - PrintAndLog("Usage: hf 14b raw [-r] [-c] [-p] <0A 0B 0C ... hex>"); + PrintAndLog("Usage: hf 14b raw [-r] [-c] [-p] [-s || -ss] <0A 0B 0C ... hex>"); PrintAndLog(" -r do not read response"); PrintAndLog(" -c calculate and append CRC"); PrintAndLog(" -p leave the field on after receive"); - return 0; + PrintAndLog(" -s active signal field ON with select"); + PrintAndLog(" -ss active signal field ON with select for SRx ST Microelectronics tags"); + return 0; } // strip @@ -164,6 +168,14 @@ int CmdHF14BCmdRaw (const char *Cmd) { case 'P': power = true; break; + case 's': + case 'S': + select = true; + if (Cmd[i+2]=='s' || Cmd[i+2]=='S') { + SRx = true; + i++; + } + break; default: PrintAndLog("Invalid option"); return 0; @@ -186,7 +198,7 @@ int CmdHF14BCmdRaw (const char *Cmd) { continue; } PrintAndLog("Invalid char on input"); - return 1; + return 0; } if (datalen == 0) { @@ -194,11 +206,58 @@ int CmdHF14BCmdRaw (const char *Cmd) { return 0; } + if (select){ //auto select 14b tag + uint8_t cmd2[16]; + bool crc2 = true; + uint8_t cmdLen; + + if (SRx) { + // REQ SRx + cmdLen = 2; + cmd2[0] = 0x06; + cmd2[1] = 0x00; + } else { + cmdLen = 3; + // REQB + cmd2[0] = 0x05; + cmd2[1] = 0x00; + cmd2[2] = 0x08; + } + + if (HF14BCmdRaw(true, &crc2, true, cmd2, &cmdLen, false)==0) return rawClose(); + + if ( SRx && (cmdLen != 3 || !crc2) ) return rawClose(); + else if (cmd2[0] != 0x50 || cmdLen != 14 || !crc2) return rawClose(); + + uint8_t chipID = 0; + if (SRx) { + // select + chipID = cmd2[0]; + cmd2[0] = 0x0E; + cmd2[1] = chipID; + cmdLen = 2; + } else { + // attrib + cmd2[0] = 0x1D; + // UID from cmd2[1 - 4] + cmd2[5] = 0x00; + cmd2[6] = 0x08; + cmd2[7] = 0x01; + cmd2[8] = 0x00; + cmdLen = 9; + } + + if (HF14BCmdRaw(true, &crc2, true, cmd2, &cmdLen, false)==0) return rawClose(); + + if (cmdLen != 3 || !crc2) return rawClose(); + if (SRx && cmd2[0] != chipID) return rawClose(); + } return HF14BCmdRaw(reply, &crc, power, data, &datalen, true); } +// print full atqb info static void print_atqb_resp(uint8_t *data){ - PrintAndLog (" UID: %s", sprint_hex(data+1,4)); + //PrintAndLog (" UID: %s", sprint_hex(data+1,4)); PrintAndLog (" App Data: %s", sprint_hex(data+5,4)); PrintAndLog (" Protocol: %s", sprint_hex(data+9,3)); uint8_t BitRate = data[9]; @@ -233,18 +292,20 @@ static void print_atqb_resp(uint8_t *data){ else maxFrame = 257; - PrintAndLog ("Max Frame Size: %d%s",maxFrame, (maxFrame == 257) ? "+ RFU" : ""); + PrintAndLog ("Max Frame Size: %u%s",maxFrame, (maxFrame == 257) ? "+ RFU" : ""); uint8_t protocolT = data[10] & 0xF; PrintAndLog (" Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4",(protocolT) ? "" : "not " ); - PrintAndLog ("Frame Wait Int: %d", data[11]>>4); + PrintAndLog ("Frame Wait Int: %u", data[11]>>4); PrintAndLog (" App Data Code: Application is %s",(data[11]&4) ? "Standard" : "Proprietary"); PrintAndLog (" Frame Options: NAD is %ssupported",(data[11]&2) ? "" : "not "); PrintAndLog (" Frame Options: CID is %ssupported",(data[11]&1) ? "" : "not "); + PrintAndLog ("Max Buf Length: %u (MBLI) %s",data[14]>>4, (data[14] & 0xF0) ? "" : "not supported"); return; } +// get SRx chip model (from UID) // from ST Microelectronics char *get_ST_Chip_Model(uint8_t data){ static char model[20]; char *retStr = model; @@ -263,20 +324,86 @@ char *get_ST_Chip_Model(uint8_t data){ return retStr; } -static void print_st_info(uint8_t *data){ +int print_ST_Lock_info(uint8_t model){ + //assume connection open and tag selected... + uint8_t data[16] = {0x00}; + uint8_t datalen = 2; + bool crc = true; + uint8_t resplen; + uint8_t blk1; + data[0] = 0x08; + + if (model == 0x2) { //SR176 has special command: + data[1] = 0xf; + resplen = 4; + } else { + data[1] = 0xff; + resplen = 6; + } + + //std read cmd + if (HF14BCmdRaw(true, &crc, true, data, &datalen, false)==0) return rawClose(); + + if (datalen != resplen || !crc) return rawClose(); + + PrintAndLog("Chip Write Protection Bits:"); + // now interpret the data + switch (model){ + case 0x0: //fall through (SRIX4K special) + case 0x3: //fall through (SRIx4K) + case 0x7: // (SRI4K) + //only need data[3] + blk1 = 9; + PrintAndLog(" raw: %s",printBits(1,data+3)); + PrintAndLog(" 07/08:%slocked", (data[3] & 1) ? " not " : " " ); + for (uint8_t i = 1; i<8; i++){ + PrintAndLog(" %02u:%slocked", blk1, (data[3] & (1 << i)) ? " not " : " " ); + blk1++; + } + break; + case 0x4: //fall through (SRIX512) + case 0x6: //fall through (SRI512) + case 0xC: // (SRT512) + //need data[2] and data[3] + blk1 = 0; + PrintAndLog(" raw: %s",printBits(2,data+2)); + for (uint8_t b=2; b<4; b++){ + for (uint8_t i=0; i<8; i++){ + PrintAndLog(" %02u:%slocked", blk1, (data[b] & (1 << i)) ? " not " : " " ); + blk1++; + } + } + break; + case 0x2: // (SR176) + //need data[2] + blk1 = 0; + PrintAndLog(" raw: %s",printBits(1,data+2)); + for (uint8_t i = 0; i<8; i++){ + PrintAndLog(" %02u/%02u:%slocked", blk1, blk1+1, (data[2] & (1 << i)) ? " " : " not " ); + blk1+=2; + } + break; + default: + return rawClose(); + } + return 1; +} + +// print UID info from SRx chips (ST Microelectronics) +static void print_st_general_info(uint8_t *data){ //uid = first 8 bytes in data - PrintAndLog(" UID: %s", sprint_hex(SwapEndian64(data,8,8),8)); - PrintAndLog(" MFG: %02X, %s", data[6], getTagInfo(data[6])); - PrintAndLog("Chip: %02X, %s", data[5]>>2, get_ST_Chip_Model(data[5]>>2)); + PrintAndLog(" UID: %s", sprint_hex(SwapEndian64(data,8,8),8)); + PrintAndLog(" MFG: %02X, %s", data[6], getTagInfo(data[6])); + PrintAndLog(" Chip: %02X, %s", data[5]>>2, get_ST_Chip_Model(data[5]>>2)); return; } -int HF14BStdInfo(uint8_t *data, uint8_t *datalen){ - +// 14b get and print UID only (general info) +int HF14BStdReader(uint8_t *data, uint8_t *datalen){ //05 00 00 = find one tag in field - //1d xx xx xx xx 20 00 08 01 00 = attrib xx=crc - //a3 = ? (resp 03 e2 c2) - //02 = ? (resp 02 6a d3) + //1d xx xx xx xx 00 08 01 00 = attrib xx=UID (resp 10 [f9 e0]) + //a3 = ? (resp 03 [e2 c2]) + //02 = ? (resp 02 [6a d3]) // 022b (resp 02 67 00 [29 5b]) // 0200a40400 (resp 02 67 00 [29 5b]) // 0200a4040c07a0000002480300 (resp 02 67 00 [29 5b]) @@ -289,24 +416,60 @@ int HF14BStdInfo(uint8_t *data, uint8_t *datalen){ //03 = ? (resp 03 [e3 c2]) //c2 = ? (resp c2 [66 15]) //b2 = ? (resp a3 [e9 67]) + //a2 = ? (resp 02 [6a d3]) bool crc = true; *datalen = 3; //std read cmd data[0] = 0x05; data[1] = 0x00; - data[2] = 0x00; + data[2] = 0x08; - if (HF14BCmdRaw(true, &crc, false, data, datalen, false)==0) return 0; + if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return rawClose(); - if (data[0] != 0x50 || *datalen != 14 || !crc) return 0; + if (data[0] != 0x50 || *datalen != 14 || !crc) return rawClose(); PrintAndLog ("\n14443-3b tag found:"); + PrintAndLog (" UID: %s", sprint_hex(data+1,4)); + + uint8_t cmd2[16]; + uint8_t cmdLen = 3; + bool crc2 = true; + + cmd2[0] = 0x1D; + // UID from data[1 - 4] + cmd2[1] = data[1]; + cmd2[2] = data[2]; + cmd2[3] = data[3]; + cmd2[4] = data[4]; + cmd2[5] = 0x00; + cmd2[6] = 0x08; + cmd2[7] = 0x01; + cmd2[8] = 0x00; + cmdLen = 9; + + // attrib + if (HF14BCmdRaw(true, &crc2, true, cmd2, &cmdLen, false)==0) return rawClose(); + + if (cmdLen != 3 || !crc2) return rawClose(); + // add attrib responce to data + data[14] = cmd2[0]; + rawClose(); + return 1; +} + +// 14b get and print Full Info (as much as we know) +int HF14BStdInfo(uint8_t *data, uint8_t *datalen){ + if (!HF14BStdReader(data,datalen)) return 0; + + //add more info here print_atqb_resp(data); + return 1; } -int HF14B_ST_Info(uint8_t *data, uint8_t *datalen){ +// SRx get and print general info about SRx chip from UID +int HF14B_ST_Reader(uint8_t *data, uint8_t *datalen, bool closeCon){ bool crc = true; *datalen = 2; //wake cmd @@ -326,7 +489,6 @@ int HF14B_ST_Info(uint8_t *data, uint8_t *datalen){ *datalen = 2; //leave power on - // verbose on for now for testing - turn off when functional if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return rawClose(); if (*datalen != 3 || !crc || data[0] != chipID) return rawClose(); @@ -335,19 +497,32 @@ int HF14B_ST_Info(uint8_t *data, uint8_t *datalen){ data[0] = 0x0B; *datalen = 1; - //power off - // verbose on for now for testing - turn off when functional - if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return 0; - rawClose(); - if (*datalen != 10 || !crc) return 0; + //leave power on + if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return rawClose(); + + if (*datalen != 10 || !crc) return rawClose(); + + //power off ? + if (closeCon) rawClose(); PrintAndLog("\n14443-3b ST tag found:"); - print_st_info(data); + print_st_general_info(data); + return 1; +} + +// SRx get and print full info (needs more info...) +int HF14B_ST_Info(uint8_t *data, uint8_t *datalen){ + if (!HF14B_ST_Reader(data, datalen, false)) return 0; + + //add locking bit information here. + if (print_ST_Lock_info(data[5]>>2)) + rawClose(); + return 1; } // test for other 14b type tags (mimic another reader - don't have tags to identify) -int HF14B_Other_Info(uint8_t *data, uint8_t *datalen){ +int HF14B_Other_Reader(uint8_t *data, uint8_t *datalen){ bool crc = true; *datalen = 4; //std read cmd @@ -356,11 +531,12 @@ int HF14B_Other_Info(uint8_t *data, uint8_t *datalen){ data[2] = 0x3f; data[3] = 0x80; - if (HF14BCmdRaw(true, &crc, false, data, datalen, false)!=0) { + if (HF14BCmdRaw(true, &crc, true, data, datalen, false)!=0) { if (*datalen > 2 || !crc) { PrintAndLog ("\n14443-3b tag found:"); PrintAndLog ("Unknown tag type answered to a 0x000b3f80 command ans:"); PrintAndLog ("%s",sprint_hex(data,*datalen)); + rawClose(); return 1; } } @@ -369,11 +545,12 @@ int HF14B_Other_Info(uint8_t *data, uint8_t *datalen){ *datalen = 1; data[0] = 0x0a; - if (HF14BCmdRaw(true, &crc, false, data, datalen, false)!=0) { + if (HF14BCmdRaw(true, &crc, true, data, datalen, false)!=0) { if (*datalen > 0) { PrintAndLog ("\n14443-3b tag found:"); PrintAndLog ("Unknown tag type answered to a 0x0A command ans:"); PrintAndLog ("%s",sprint_hex(data,*datalen)); + rawClose(); return 1; } } @@ -382,19 +559,20 @@ int HF14B_Other_Info(uint8_t *data, uint8_t *datalen){ *datalen = 1; data[0] = 0x0c; - if (HF14BCmdRaw(true, &crc, false, data, datalen, false)!=0) { + if (HF14BCmdRaw(true, &crc, true, data, datalen, false)!=0) { if (*datalen > 0) { PrintAndLog ("\n14443-3b tag found:"); PrintAndLog ("Unknown tag type answered to a 0x0C command ans:"); PrintAndLog ("%s",sprint_hex(data,*datalen)); + rawClose(); return 1; } } - + rawClose(); return 0; - } +// get and print all info known about any known 14b tag int HF14BInfo(bool verbose){ uint8_t data[100]; uint8_t datalen = 5; @@ -407,16 +585,41 @@ int HF14BInfo(bool verbose){ // try unknown 14b read commands (to be identified later) // could be read of calypso, CEPAS, moneo, or pico pass. - if (HF14B_Other_Info(data, &datalen)) return 1; + if (HF14B_Other_Reader(data, &datalen)) return 1; if (verbose) PrintAndLog("no 14443B tag found"); return 0; } +// menu command to get and print all info known about any known 14b tag int CmdHF14Binfo(const char *Cmd){ return HF14BInfo(true); } +// get and print general info about all known 14b chips +int HF14BReader(bool verbose){ + uint8_t data[100]; + uint8_t datalen = 5; + + // try std 14b (atqb) + if (HF14BStdReader(data, &datalen)) return 1; + + // try st 14b + if (HF14B_ST_Reader(data, &datalen, true)) return 1; + + // try unknown 14b read commands (to be identified later) + // could be read of calypso, CEPAS, moneo, or pico pass. + if (HF14B_Other_Reader(data, &datalen)) return 1; + + if (verbose) PrintAndLog("no 14443B tag found"); + return 0; +} + +// menu command to get and print general info about all known 14b chips +int CmdHF14BReader(const char *Cmd){ + return HF14BReader(true); +} + int CmdSriWrite( const char *Cmd){ /* * For SRIX4K blocks 00 - 7F @@ -487,8 +690,9 @@ int CmdSriWrite( const char *Cmd){ static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"info", CmdHF14Binfo, 0, "Find and print info about a 14b type tag (HF ISO 14443b)"}, - {"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443b history"}, + {"info", CmdHF14Binfo, 0, "Find and print details about a 14443B tag"}, + {"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443B history"}, + {"reader", CmdHF14BReader, 0, "Act as a 14443B reader to identify a tag"}, {"sim", CmdHF14BSim, 0, "Fake ISO 14443B tag"}, {"snoop", CmdHF14BSnoop, 0, "Eavesdrop ISO 14443B"}, {"sri512read", CmdSri512Read, 0, "Read contents of a SRI512 tag"}, diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 5ef5273a..16612cba 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -18,7 +18,6 @@ int CmdHF14AMifare(const char *Cmd) uint32_t nt = 0, nr = 0; uint64_t par_list = 0, ks_list = 0, r_key = 0; int16_t isOK = 0; - uint8_t keyBlock[8] = {0}; UsbCommand c = {CMD_READER_MIFARE, {true, 0, 0}}; @@ -74,22 +73,13 @@ start: if (nonce2key(uid, nt, nr, par_list, ks_list, &r_key)) { isOK = 2; PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt); - } else { - printf("------------------------------------------------------------------\n"); - PrintAndLog("Key found:%012"llx" \n", r_key); - - num_to_bytes(r_key, 6, keyBlock); - isOK = mfCheckKeys(0, 0, 1, keyBlock, &r_key); - } - - if (!isOK) - PrintAndLog("Found valid key:%012"llx, r_key); - else - { - if (isOK != 2) PrintAndLog("Found invalid key. "); PrintAndLog("Failing is expected to happen in 25%% of all cases. Trying again with a different reader nonce..."); c.arg[0] = false; goto start; + } else { + isOK = 0; + printf("------------------------------------------------------------------\n"); + PrintAndLog("Found valid key:%012"llx" \n", r_key); } PrintAndLog(""); @@ -689,7 +679,7 @@ int CmdHF14AMfNested(const char *Cmd) for (j = 0; j < 2; j++) { if (e_sector[i].foundKey[j]) continue; - res = mfCheckKeys(FirstBlockOfSector(i), j, 6, keyBlock, &key64); + res = mfCheckKeys(FirstBlockOfSector(i), j, true, 6, keyBlock, &key64); if (!res) { e_sector[i].Key[j] = key64; @@ -973,7 +963,7 @@ int CmdHF14AMfChk(const char *Cmd) uint32_t max_keys = keycnt>USB_CMD_DATA_SIZE/6?USB_CMD_DATA_SIZE/6:keycnt; for (uint32_t c = 0; c < keycnt; c+=max_keys) { uint32_t size = keycnt-c>max_keys?max_keys:keycnt-c; - res = mfCheckKeys(b, t, size, &keyBlock[6*c], &key64); + res = mfCheckKeys(b, t, true, size, &keyBlock[6*c], &key64); if (res != 1) { if (!res) { PrintAndLog("Found valid key:[%012"llx"]",key64); diff --git a/client/cmdhw.c b/client/cmdhw.c index 05ad0c9f..33dc78ae 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -18,6 +18,7 @@ #include "cmdhw.h" #include "cmdmain.h" #include "cmddata.h" +#include "data.h" /* low-level hardware control */ @@ -405,39 +406,72 @@ int CmdTune(const char *Cmd) int CmdVersion(const char *Cmd) { + clearCommandBuffer(); UsbCommand c = {CMD_VERSION}; static UsbCommand resp = {0, {0, 0, 0}}; - + if (resp.arg[0] == 0 && resp.arg[1] == 0) { // no cached information available SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK,&resp,1000) && Cmd != NULL) { + if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { PrintAndLog("Prox/RFID mark3 RFID instrument"); PrintAndLog((char*)resp.d.asBytes); lookupChipID(resp.arg[0], resp.arg[1]); } - } else if (Cmd != NULL) { + } else { + PrintAndLog("[[[ Cached information ]]]\n"); PrintAndLog("Prox/RFID mark3 RFID instrument"); PrintAndLog((char*)resp.d.asBytes); lookupChipID(resp.arg[0], resp.arg[1]); + PrintAndLog(""); + } + return 0; +} + +int CmdStatus(const char *Cmd) +{ + uint8_t speed_test_buffer[USB_CMD_DATA_SIZE]; + sample_buf = speed_test_buffer; + + clearCommandBuffer(); + UsbCommand c = {CMD_STATUS}; + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK,&c,1900)) { + PrintAndLog("Status command failed. USB Speed Test timed out"); + } + return 0; +} + + +int CmdPing(const char *Cmd) +{ + clearCommandBuffer(); + UsbCommand resp; + UsbCommand c = {CMD_PING}; + SendCommand(&c); + if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { + PrintAndLog("Ping successfull"); + }else{ + PrintAndLog("Ping failed"); } - return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, - {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"}, - {"lcd", CmdLCD, 0, " -- Send command/data to LCD"}, - {"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"}, - {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"}, - {"reset", CmdReset, 0, "Reset the Proxmark3"}, - {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, - {"setmux", CmdSetMux, 0, " -- Set the ADC mux to a specific value"}, - {"tune", CmdTune, 0, "Measure antenna tuning"}, - {"version", CmdVersion, 0, "Show version information about the connected Proxmark"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, + {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"}, + {"lcd", CmdLCD, 0, " -- Send command/data to LCD"}, + {"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"}, + {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"}, + {"reset", CmdReset, 0, "Reset the Proxmark3"}, + {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, + {"setmux", CmdSetMux, 0, " -- Set the ADC mux to a specific value"}, + {"tune", CmdTune, 0, "Measure antenna tuning"}, + {"version", CmdVersion, 0, "Show version information about the connected Proxmark"}, + {"status", CmdStatus, 0, "Show runtime status information about the connected Proxmark"}, + {"ping", CmdPing, 0, "Test if the pm3 is responsive"}, + {NULL, NULL, 0, NULL} }; int CmdHW(const char *Cmd) diff --git a/client/cmdlf.c b/client/cmdlf.c index edf02932..4c682a76 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -22,6 +22,7 @@ #include "util.h" #include "cmdlf.h" #include "cmdlfhid.h" +#include "cmdlfawid.h" #include "cmdlfti.h" #include "cmdlfem4x.h" #include "cmdlfhitag.h" @@ -388,7 +389,7 @@ int usage_lf_config() PrintAndLog(" b Sets resolution of bits per sample. Default (max): 8"); PrintAndLog(" d Sets decimation. A value of N saves only 1 in N samples. Default: 1"); PrintAndLog(" a [0|1] Averaging - if set, will average the stored sample value when decimating. Default: 1"); - PrintAndLog(" t Sets trigger threshold. 0 means no threshold"); + PrintAndLog(" t Sets trigger threshold. 0 means no threshold (range: 0-128)"); PrintAndLog("Examples:"); PrintAndLog(" lf config b 8 L"); PrintAndLog(" Samples at 125KHz, 8bps."); @@ -1130,6 +1131,7 @@ static command_t CommandTable[] = {"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"}, {"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"}, {"hid", CmdLFHID, 1, "{ HID RFIDs... }"}, + {"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"}, {"io", CmdLFIO, 1, "{ ioProx tags... }"}, {"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, {"indalaclone", CmdIndalaClone, 0, " ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"}, diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c new file mode 100644 index 00000000..06397e70 --- /dev/null +++ b/client/cmdlfawid.c @@ -0,0 +1,237 @@ +//----------------------------------------------------------------------------- +// Authored by Craig Young based on cmdlfhid.c structure +// +// cmdlfhid.c is Copyright (C) 2010 iZsh +// +// 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. +//----------------------------------------------------------------------------- +// Low frequency AWID26 commands +//----------------------------------------------------------------------------- + +#include // sscanf +#include "proxmark3.h" // Definitions, USB controls, etc +#include "ui.h" // PrintAndLog +#include "cmdparser.h" // CmdsParse, CmdsHelp +#include "cmdlfawid.h" // AWID function declarations +#include "lfdemod.h" // parityTest +#include "cmdmain.h" +static int CmdHelp(const char *Cmd); + + +int usage_lf_awid_fskdemod(void) { + PrintAndLog("Enables AWID26 compatible reader mode printing details of scanned AWID26 tags."); + PrintAndLog("By default, values are printed and logged until the button is pressed or another USB command is issued."); + PrintAndLog("If the ['1'] option is provided, reader mode is exited after reading a single AWID26 card."); + PrintAndLog(""); + PrintAndLog("Usage: lf awid fskdemod ['1']"); + PrintAndLog(" Options : "); + PrintAndLog(" 1 : (optional) stop after reading a single card"); + PrintAndLog(""); + PrintAndLog(" sample : lf awid fskdemod"); + PrintAndLog(" : lf awid fskdemod 1"); + return 0; +} + +int usage_lf_awid_sim(void) { + PrintAndLog("Enables simulation of AWID26 card with specified facility-code and card number."); + PrintAndLog("Simulation runs until the button is pressed or another USB command is issued."); + PrintAndLog("Per AWID26 format, the facility-code is 8-bit and the card number is 16-bit. Larger values are truncated."); + PrintAndLog(""); + PrintAndLog("Usage: lf awid sim "); + PrintAndLog(" Options : "); + PrintAndLog(" : 8-bit value representing the AWID facility code"); + PrintAndLog(" : 16-bit value representing the AWID card number"); + PrintAndLog(""); + PrintAndLog(" sample : lf awid sim 224 1337"); + return 0; +} + +int usage_lf_awid_clone(void) { + PrintAndLog("Enables cloning of AWID26 card with specified facility-code and card number onto T55x7."); + PrintAndLog("The T55x7 must be on the antenna when issuing this command. T55x7 blocks are calculated and printed in the process."); + PrintAndLog("Per AWID26 format, the facility-code is 8-bit and the card number is 16-bit. Larger values are truncated."); + PrintAndLog(""); + PrintAndLog("Usage: lf awid clone "); + PrintAndLog(" Options : "); + PrintAndLog(" : 8-bit value representing the AWID facility code"); + PrintAndLog(" : 16-bit value representing the AWID card number"); + PrintAndLog(""); + PrintAndLog(" sample : lf awid clone 224 1337"); + return 0; +} + +int CmdAWIDDemodFSK(const char *Cmd) +{ + int findone=0; + if(Cmd[0]=='1') findone=1; + if (Cmd[0]=='h' || Cmd[0] == 'H') return usage_lf_awid_fskdemod(); + UsbCommand c={CMD_AWID_DEMOD_FSK}; + c.arg[0]=findone; + SendCommand(&c); + return 0; +} + +int getAWIDBits(unsigned int fc, unsigned int cn, uint8_t *AWIDBits) +{ + int i; + uint32_t fcode=(fc & 0x000000FF), cnum=(cn & 0x0000FFFF), uBits=0; + if (fcode != fc) + PrintAndLog("NOTE: Facility code truncated for AWID26 format (8-bit facility code)"); + if (cnum!=cn) + PrintAndLog("NOTE: Card number was truncated for AWID26 format (16-bit card number)"); + + AWIDBits[0] = 0x01; // 6-bit Preamble with 2 parity bits + AWIDBits[1] = 0x1D; // First byte from card format (26-bit) plus parity bits + AWIDBits[2] = 0x80; // Set the next two bits as 0b10 to finish card format + uBits = (fcode<<4) + (cnum>>12); + if (!parityTest(uBits,12,0)) + AWIDBits[2] |= (1<<5); // If not already even parity, set bit to make even + uBits = AWIDBits[2]>>5; + if (!parityTest(uBits, 3, 1)) + AWIDBits[2] |= (1<<4); + uBits = fcode>>5; // first 3 bits of facility-code + AWIDBits[2] += (uBits<<1); + if (!parityTest(uBits, 3, 1)) + AWIDBits[2]++; // Set parity bit to make odd parity + uBits = (fcode & 0x1C)>>2; + AWIDBits[3] = 0; + if (!parityTest(uBits,3,1)) + AWIDBits[3] |= (1<<4); + AWIDBits[3] += (uBits<<5); + uBits = ((fcode & 0x3)<<1) + ((cnum & 0x8000)>>15); // Grab/shift 2 LSBs from facility code and add shifted MSB from cardnum + if (!parityTest(uBits,3,1)) + AWIDBits[3]++; // Set LSB for parity + AWIDBits[3]+= (uBits<<1); + uBits = (cnum & 0x7000)>>12; + AWIDBits[4] = uBits<<5; + if (!parityTest(uBits,3,1)) + AWIDBits[4] |= (1<<4); + uBits = (cnum & 0x0E00)>>9; + AWIDBits[4] += (uBits<<1); + if (!parityTest(uBits,3,1)) + AWIDBits[4]++; // Set LSB for parity + uBits = (cnum & 0x1C0)>>6; // Next bits from card number + AWIDBits[5]=(uBits<<5); + if (!parityTest(uBits,3,1)) + AWIDBits[5] |= (1<<4); // Set odd parity bit as needed + uBits = (cnum & 0x38)>>3; + AWIDBits[5]+= (uBits<<1); + if (!parityTest(uBits,3,1)) + AWIDBits[5]++; // Set odd parity bit as needed + uBits = (cnum & 0x7); // Last three bits from card number! + AWIDBits[6] = (uBits<<5); + if (!parityTest(uBits,3,1)) + AWIDBits[6] |= (1<<4); + uBits = (cnum & 0x0FFF); + if (!parityTest(uBits,12,1)) + AWIDBits[6] |= (1<<3); + else + AWIDBits[6]++; + for (i = 7; i<12; i++) + AWIDBits[i]=0x11; + return 1; +} + +int CmdAWIDSim(const char *Cmd) +{ + uint32_t fcode = 0, cnum = 0, fc=0, cn=0, i=0; + uint8_t *BS, BitStream[12]; + uint64_t arg1 = (10<<8) + 8; // fcHigh = 10, fcLow = 8 + uint64_t arg2 = 50; // clk RF/50 invert=0 + BS = BitStream; + if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) { + return usage_lf_awid_sim(); + } + + fcode=(fc & 0x000000FF); + cnum=(cn & 0x0000FFFF); + if (fc!=fcode) + PrintAndLog("Facility-Code (%u) truncated to 8-bits: %u",fc,fcode); + if (cn!=cnum) + PrintAndLog("Card number (%u) truncated to 16-bits: %u",cn,cnum); + PrintAndLog("Emulating AWID26 -- FC: %u; CN: %u\n",fcode,cnum); + PrintAndLog("Press pm3-button to abort simulation or run another command"); + // AWID uses: fcHigh: 10, fcLow: 8, clk: 50, invert: 0 + if (getAWIDBits(fc, cn, BS)) { + PrintAndLog("Running 'lf simfsk c 50 H 10 L 8 d %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x'", + BS[0],BS[1],BS[2],BS[3],BS[4],BS[5],BS[6], + BS[7],BS[8],BS[9],BS[10],BS[11]); + } else + PrintAndLog("Error with tag bitstream generation."); + UsbCommand c; + c.cmd = CMD_FSK_SIM_TAG; + c.arg[0] = arg1; // fcHigh<<8 + fcLow + c.arg[1] = arg2; // Inversion and clk setting + c.arg[2] = 96; // Bitstream length: 96-bits == 12 bytes + for (i=0; i < 96; i++) + c.d.asBytes[i] = (BS[i/8] & (1<<(7-(i%8))))?1:0; + SendCommand(&c); + return 0; +} + +int CmdAWIDClone(const char *Cmd) +{ + uint32_t fc=0,cn=0,blocks[4] = {0x00107060, 0, 0, 0x11111111}, i=0; + uint8_t BitStream[12]; + uint8_t *BS=BitStream; + UsbCommand c, resp; + + if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) { + return usage_lf_awid_clone(); + } + + if ((fc & 0xFF) != fc) { + fc &= 0xFF; + PrintAndLog("Facility-Code Truncated to 8-bits (AWID26): %u", fc); + } + if ((cn & 0xFFFF) != cn) { + cn &= 0xFFFF; + PrintAndLog("Card Number Truncated to 16-bits (AWID26): %u", cn); + } + if (getAWIDBits(fc,cn,BS)) { + PrintAndLog("Preparing to clone AWID26 to T55x7 with FC: %u, CN: %u (Raw: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x)", + fc,cn, BS[0],BS[1],BS[2],BS[3],BS[4],BS[5],BS[6],BS[7],BS[8],BS[9],BS[10],BS[11]); + blocks[1] = (BS[0]<<24) + (BS[1]<<16) + (BS[2]<<8) + (BS[3]); + blocks[2] = (BS[4]<<24) + (BS[5]<<16) + (BS[6]<<8) + (BS[7]); + PrintAndLog("Block 0: 0x%08x", blocks[0]); + PrintAndLog("Block 1: 0x%08x", blocks[1]); + PrintAndLog("Block 2: 0x%08x", blocks[2]); + PrintAndLog("Block 3: 0x%08x", blocks[3]); + for (i=0; i<4; i++) { + c.cmd = CMD_T55XX_WRITE_BLOCK; + c.arg[0] = blocks[i]; + c.arg[1] = i; + c.arg[2] = 0; + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){ + PrintAndLog("Error occurred, device did not respond during write operation."); + return -1; + } + + } + } + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"fskdemod", CmdAWIDDemodFSK, 0, "['1'] Realtime AWID FSK demodulator (option '1' for one tag only)"}, + {"sim", CmdAWIDSim, 0, " -- AWID tag simulator"}, + {"clone", CmdAWIDClone, 0, " -- Clone AWID to T55x7 (tag must be in range of antenna)"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFAWID(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfawid.h b/client/cmdlfawid.h new file mode 100644 index 00000000..00622927 --- /dev/null +++ b/client/cmdlfawid.h @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 iZsh +// +// 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. +//----------------------------------------------------------------------------- +// Low frequency AWID commands +//----------------------------------------------------------------------------- + +#ifndef CMDLFAWID_H__ +#define CMDLFAWID_H__ + +int CmdLFAWID(const char *Cmd); +//int CmdAWIDDemod(const char *Cmd); +int CmdAWIDDemodFSK(const char *Cmd); +int CmdAWIDSim(const char *Cmd); +int CmdAWIDClone(const char *Cmd); +int getAWIDBits(unsigned int fc, unsigned int cn, uint8_t *AWIDBits); +int usage_lf_awid_fskdemod(void); +int usage_lf_awid_clone(void); +int usage_lf_awid_sim(void); + +#endif diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index b357e71c..2291735c 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -242,6 +242,7 @@ int CmdT55xxReadBlock(const char *Cmd) { c.d.asBytes[0] = 0x1; } + clearCommandBuffer(); SendCommand(&c); if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) { PrintAndLog("command execution time out"); @@ -670,6 +671,7 @@ int CmdT55xxWriteBlock(const char *Cmd) } UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {data, block, 0}}; + UsbCommand resp; c.d.asBytes[0] = 0x0; PrintAndLog("Writing to block: %d data : 0x%08X", block, data); @@ -680,7 +682,12 @@ int CmdT55xxWriteBlock(const char *Cmd) c.d.asBytes[0] = 0x1; PrintAndLog("pwd : 0x%08X", password); } + clearCommandBuffer(); SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){ + PrintAndLog("Error occurred, device did not ACK write operation. (May be due to old firmware)"); + return -1; + } return 0; } @@ -878,6 +885,7 @@ int AquireData( uint8_t block ){ // c.d.asBytes[0] = 0x1; // } + clearCommandBuffer(); SendCommand(&c); if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) { PrintAndLog("command execution time out"); diff --git a/client/cmdmain.c b/client/cmdmain.c index 512aa13c..deced558 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -97,8 +97,9 @@ void storeCommand(UsbCommand *command) memcpy(destination, command, sizeof(UsbCommand)); cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; //increment head and wrap - } + + /** * @brief getCommand gets a command from an internal circular buffer. * @param response location to write command @@ -117,9 +118,9 @@ int getCommand(UsbCommand* response) cmd_tail = (cmd_tail +1 ) % CMD_BUFFER_SIZE; return 1; - } + /** * Waits for a certain response type. This method waits for a maximum of * ms_timeout milliseconds for a specified response command. @@ -131,33 +132,34 @@ int getCommand(UsbCommand* response) */ bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) { - UsbCommand resp; + UsbCommand resp; - if (response == NULL) - response = &resp; - - - // Wait until the command is received - for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) { + if (response == NULL) { + response = &resp; + } + // Wait until the command is received + for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) { while(getCommand(response)) { - if(response->cmd == cmd){ - return true; - } - } - msleep(10); // XXX ugh - if (dm_seconds == 200) { // Two seconds elapsed - PrintAndLog("Waiting for a response from the proxmark..."); - PrintAndLog("Don't forget to cancel its operation first by pressing on the button"); - } + if(response->cmd == cmd){ + return true; + } + } + msleep(10); // XXX ugh + if (dm_seconds == 200) { // Two seconds elapsed + PrintAndLog("Waiting for a response from the proxmark..."); + PrintAndLog("Don't forget to cancel its operation first by pressing on the button"); + } } - return false; + return false; } + bool WaitForResponse(uint32_t cmd, UsbCommand* response) { return WaitForResponseTimeout(cmd,response,-1); } + //----------------------------------------------------------------------------- // Entry point into our code: called whenever the user types a command and // then presses Enter, which the full command line that they typed. @@ -166,6 +168,7 @@ void CommandReceived(char *Cmd) { CmdsParse(CommandTable, Cmd); } + //----------------------------------------------------------------------------- // Entry point into our code: called whenever we received a packet over USB // that we weren't necessarily expecting, for example a debug print. @@ -189,12 +192,13 @@ void UsbCommandReceived(UsbCommand *UC) case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: { memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]); + return; } break; default: + storeCommand(UC); break; } - storeCommand(UC); } diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h index b3a7f4ec..f4013bab 100644 --- a/client/hid-flasher/usb_cmd.h +++ b/client/hid-flasher/usb_cmd.h @@ -84,6 +84,7 @@ typedef struct { #define CMD_FSK_SIM_TAG 0x021E #define CMD_ASK_SIM_TAG 0x021F #define CMD_PSK_SIM_TAG 0x0220 +#define CMD_AWID_DEMOD_FSK 0x0221 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ diff --git a/client/lualibs/commands.lua b/client/lualibs/commands.lua index 4c7bc638..64f16e44 100644 --- a/client/lualibs/commands.lua +++ b/client/lualibs/commands.lua @@ -20,7 +20,8 @@ local _commands = { CMD_BUFF_CLEAR = 0x0105, CMD_READ_MEM = 0x0106, CMD_VERSION = 0x0107, - + CMD_STATUS = 0x0108, + CMD_PING = 0x0109, --// For low-frequency tags CMD_READ_TI_TYPE = 0x0202, CMD_WRITE_TI_TYPE = 0x0203, @@ -54,6 +55,7 @@ local _commands = { CMD_FSK_SIM_TAG = 0x021E, CMD_ASK_SIM_TAG = 0x021F, CMD_PSK_SIM_TAG = 0x0220, + CMD_AWID_DEMOD_FSK = 0x0221, --/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ diff --git a/client/mifarehost.c b/client/mifarehost.c index 95453ebf..eb145123 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -181,7 +181,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo crypto1_get_lfsr(statelists[0].head.slhead + i, &key64); num_to_bytes(key64, 6, keyBlock); key64 = 0; - if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, 1, keyBlock, &key64)) { + if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, 1, keyBlock, &key64)) { num_to_bytes(key64, 6, resultKey); break; } @@ -193,11 +193,11 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo return 0; } -int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){ +int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){ *key = 0; - UsbCommand c = {CMD_MIFARE_CHKKEYS, {blockNo, keyType, keycnt}}; + UsbCommand c = {CMD_MIFARE_CHKKEYS, {((blockNo & 0xff) | ((keyType&0xff)<<8)), clear_trace, keycnt}}; memcpy(c.d.asBytes, keyBlock, 6 * keycnt); SendCommand(&c); diff --git a/client/mifarehost.h b/client/mifarehost.h index a11f11d5..f6ffab3f 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -50,7 +50,7 @@ typedef struct { extern char logHexFileName[FILE_PATH_SIZE]; int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate); -int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key); +int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key); int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount); int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); diff --git a/client/nonce2key/nonce2key.c b/client/nonce2key/nonce2key.c index 111f58cd..70d874fe 100644 --- a/client/nonce2key/nonce2key.c +++ b/client/nonce2key/nonce2key.c @@ -133,7 +133,7 @@ int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_ key64 = *(last_keylist + i); num_to_bytes(key64, 6, keyBlock); key64 = 0; - if (!mfCheckKeys(0, 0, 1, keyBlock, &key64)) { + if (!mfCheckKeys(0, 0, false, 1, keyBlock, &key64)) { *key = key64; free(last_keylist); last_keylist = NULL; diff --git a/client/scripts/mifare_autopwn.lua b/client/scripts/mifare_autopwn.lua index eb98ffbf..9cc865f0 100644 --- a/client/scripts/mifare_autopwn.lua +++ b/client/scripts/mifare_autopwn.lua @@ -88,10 +88,33 @@ function mfcrack_inner() while not core.ukbhit() do local result = core.WaitForResponseTimeout(cmds.CMD_ACK,1000) if result then - -- Unpacking the three arg-parameters - local count,cmd,isOK = bin.unpack('LL',result) - if isOK ~= 1 then return nil, "Error occurred" end + --[[ + I don't understand, they cmd and args are defined as uint32_t, however, + looking at the returned data, they all look like 64-bit things: + + print("result", bin.unpack("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH", result)) + + FF 00 00 00 00 00 00 00 <-- 64 bits of data + FE FF FF FF 00 00 00 00 <-- 64 bits of data + 00 00 00 00 00 00 00 00 <-- 64 bits of data + 00 00 00 00 00 00 00 00 <-- 64 bits of data + 04 7F 12 E2 00 <-- this is where 'data' starts + + So below I use LI to pick out the "FEFF FFFF", don't know why it works.. + --]] + -- Unpacking the arg-parameters + local count,cmd,isOK = bin.unpack('LI',result) + --print("response", isOK)--FF FF FF FF + if isOK == 0xFFFFFFFF then + return nil, "Button pressed. Aborted." + elseif isOK == 0xFFFFFFFE then + return nil, "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys." + elseif isOK == 0xFFFFFFFD then + return nil, "Card is not vulnerable to Darkside attack (its random number generator is not predictable). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys." + elseif isOK ~= 1 then + return nil, "Error occurred" + end -- The data-part is left diff --git a/client/util.h b/client/util.h index 2d2beaf4..94021c2c 100644 --- a/client/util.h +++ b/client/util.h @@ -47,6 +47,7 @@ char * printBits(size_t const size, void const * const ptr); uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize); char param_getchar(const char *line, int paramnum); +int param_getptr(const char *line, int *bg, int *en, int paramnum); uint8_t param_get8(const char *line, int paramnum); uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base); uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base); diff --git a/common/lfdemod.c b/common/lfdemod.c index f13a567c..a3a7a500 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -580,7 +580,7 @@ int IOdemodFSK(uint8_t *dest, size_t size) // by marshmellow // takes a array of binary values, start position, length of bits per parity (includes parity bit), -// Parity Type (1 for odd; 0 for even; 2 for just drop it), and binary Length (length to run) +// Parity Type (1 for odd; 0 for even; 2 Always 1's), and binary Length (length to run) size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen) { uint32_t parityWd = 0; @@ -590,10 +590,12 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p parityWd = (parityWd << 1) | BitStream[startIdx+word+bit]; BitStream[j++] = (BitStream[startIdx+word+bit]); } - j--; + j--; // overwrite parity with next data // if parity fails then return 0 - if (pType != 2) { - if (parityTest(parityWd, pLen, pType) == 0) return -1; + if (pType == 2) { // then marker bit which should be a 1 + if (!BitStream[j]) return 0; + } else { + if (parityTest(parityWd, pLen, pType) == 0) return 0; } bitCnt+=(pLen-1); parityWd = 0; diff --git a/common/usb_cdc.c b/common/usb_cdc.c index ccbb3c50..e13ddbe2 100644 --- a/common/usb_cdc.c +++ b/common/usb_cdc.c @@ -293,31 +293,47 @@ bool usb_poll() return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank); } +/** + In github PR #129, some users appears to get a false positive from + usb_poll, which returns true, but the usb_read operation + still returns 0. + This check is basically the same as above, but also checks + that the length available to read is non-zero, thus hopefully fixes the + bug. +**/ +bool usb_poll_validate_length() +{ + + if (!usb_check()) return false; + if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false; + return (pUdp->UDP_CSR[AT91C_EP_OUT] >> 16) > 0; +} + //*---------------------------------------------------------------------------- //* \fn usb_read //* \brief Read available data from Endpoint OUT //*---------------------------------------------------------------------------- uint32_t usb_read(byte_t* data, size_t len) { - byte_t bank = btReceiveBank; + byte_t bank = btReceiveBank; uint32_t packetSize, nbBytesRcv = 0; - uint32_t time_out = 0; + uint32_t time_out = 0; while (len) { if (!usb_check()) break; if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) { packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len); - len -= packetSize; + len -= packetSize; while(packetSize--) data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT]; pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(bank); if (bank == AT91C_UDP_RX_DATA_BK0) { bank = AT91C_UDP_RX_DATA_BK1; - } else { + } else { bank = AT91C_UDP_RX_DATA_BK0; - } + } } - if (time_out++ == 0x1fff) break; + if (time_out++ == 0x1fff) break; } btReceiveBank = bank; diff --git a/common/usb_cdc.h b/common/usb_cdc.h index 59e73a47..c42da8db 100644 --- a/common/usb_cdc.h +++ b/common/usb_cdc.h @@ -41,6 +41,7 @@ void usb_disable(); void usb_enable(); bool usb_check(); bool usb_poll(); +bool usb_poll_validate_length(); uint32_t usb_read(byte_t* data, size_t len); uint32_t usb_write(const byte_t* data, const size_t len); diff --git a/doc/RFID_Antenna-Basic-Form.stl b/doc/RFID_Antenna-Basic-Form.stl new file mode 100755 index 00000000..6679ae8b Binary files /dev/null and b/doc/RFID_Antenna-Basic-Form.stl differ diff --git a/doc/RFID_Antenna-With-Lanyard-Hook.stl b/doc/RFID_Antenna-With-Lanyard-Hook.stl new file mode 100755 index 00000000..62f5397a Binary files /dev/null and b/doc/RFID_Antenna-With-Lanyard-Hook.stl differ diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 524554e9..f443e970 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -60,6 +60,8 @@ typedef struct{ #define CMD_BUFF_CLEAR 0x0105 #define CMD_READ_MEM 0x0106 #define CMD_VERSION 0x0107 +#define CMD_STATUS 0x0108 +#define CMD_PING 0x0109 // For low-frequency tags #define CMD_READ_TI_TYPE 0x0202 @@ -95,6 +97,7 @@ typedef struct{ #define CMD_FSK_SIM_TAG 0x021E #define CMD_ASK_SIM_TAG 0x021F #define CMD_PSK_SIM_TAG 0x0220 +#define CMD_AWID_DEMOD_FSK 0x0221 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */