From: Martin Holst Swende Date: Sun, 15 Nov 2015 12:22:26 +0000 (+0100) Subject: Merge pull request #143 from marshmellow42/master X-Git-Tag: v2.3.0~15 X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/9983a929430904ddeb18ec3aded0afad964272ba?hp=fa0503b03f06bc917b5dcb00d08334cc9c3c68dc Merge pull request #143 from marshmellow42/master lfops cleanup, t55xx additions/fixes, PCF7931 input cleanup --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 80c16ffa..a3a0799e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] ### Added +- Added viking demod to `lf search` (marshmellow) +- `data askvikingdemod` demod viking id tag from graphbuffer (marshmellow) +- `lf t55xx resetread` added reset then read command - should allow determining start +of stream transmissions (marshmellow) +- `lf t55xx wakeup` added wake with password (AOR) to allow lf search or standard lf read after (iceman, marshmellow) - `hf iclass managekeys` to save, load and manage iclass keys. (adjusted most commands to accept a loaded key in memory) (marshmellow) - `hf iclass readblk` to select, authenticate, and read 1 block from an iclass card (marshmellow) - `hf iclass writeblk` to select, authenticate, and write 1 block to an iclass card (or picopass) (marshmellow + others) @@ -21,6 +26,13 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added option c to 'hf list' (mark CRC bytes) (piwi) ### Changed +- Adjusted lf em410x em410xsim to accept a clock argument +- Adjusted lf t55xx dump to allow overriding the safety check and warning text (marshmellow) +- Adjusted lf t55xx write input variables (marshmellow) +- Adjusted lf t55xx read with password safety check and warning text and adjusted the input variables (marshmellow & iceman) +- Adjusted LF FSK demod to account for cross threshold fluctuations (898 count waves will adjust the 9 to 8 now...) more accurate. +- Adjusted timings for t55xx commands. more reliable now. (marshmellow & iceman) +- `lf cmdread` adjusted input methods and added help text (marshmellow & iceman) - changed `lf config t ` to be 0 - 128 and will trigger on + or - threshold value (marshmellow) - `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to muliple pages for the larger tags yet) - Revised workflow for StandAloneMode14a (Craig Young) diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index 6b52a589..8f9ee4be 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -50,9 +50,15 @@ uint8_t *BigBuf_get_EM_addr(void) // clear ALL of BigBuf void BigBuf_Clear(void) +{ + BigBuf_Clear_ext(true); +} +// clear ALL of BigBuf +void BigBuf_Clear_ext(bool verbose) { memset(BigBuf,0,BIGBUF_SIZE); - Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE); + if (verbose) + Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE); } diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index 05b4180e..13432e7e 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -25,6 +25,7 @@ extern uint8_t *BigBuf_get_addr(void); extern uint8_t *BigBuf_get_EM_addr(void); extern uint16_t BigBuf_max_traceLen(void); extern void BigBuf_Clear(void); +extern void BigBuf_Clear_ext(bool verbose); extern uint8_t *BigBuf_malloc(uint16_t); extern void BigBuf_free(void); extern void BigBuf_free_keep_EM(void); diff --git a/armsrc/Makefile b/armsrc/Makefile index 3c6c14c6..69ea2300 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -15,7 +15,7 @@ APP_CFLAGS = -DWITH_ISO14443a_StandAlone -DWITH_LF -DWITH_ISO15693 -DWITH_ISO144 #-DWITH_LCD #SRC_LCD = fonts.c LCD.c -SRC_LF = lfops.c hitag2.c lfsampling.c +SRC_LF = lfops.c hitag2.c lfsampling.c pcf7931.c lfdemod.c protocols.c SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c SRC_ISO14443b = iso14443b.c @@ -52,7 +52,6 @@ THUMBSRC = start.c \ # These are to be compiled in ARM mode ARMSRC = fpgaloader.c \ legicrf.c \ - lfdemod.c \ $(SRC_ISO14443a) \ $(SRC_ISO14443b) \ $(SRC_CRAPTO1) \ diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 8c2aefbb..e7324723 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -26,6 +26,7 @@ #include "lfsampling.h" #include "BigBuf.h" #include "mifareutil.h" +#include "pcf7931.h" #ifdef WITH_LCD #include "LCD.h" #endif @@ -945,7 +946,7 @@ void UsbPacketReceived(uint8_t *packet, int len) CmdIOdemodFSK(c->arg[0], 0, 0, 1); break; case CMD_IO_CLONE_TAG: - CopyIOtoT55x7(c->arg[0], c->arg[1], c->d.asBytes[0]); + CopyIOtoT55x7(c->arg[0], c->arg[1]); break; case CMD_EM410X_DEMOD: CmdEM410xdemod(c->arg[0], 0, 0, 1); @@ -974,21 +975,22 @@ void UsbPacketReceived(uint8_t *packet, int len) CopyIndala224toT55x7(c->d.asDwords[0], c->d.asDwords[1], c->d.asDwords[2], c->d.asDwords[3], c->d.asDwords[4], c->d.asDwords[5], c->d.asDwords[6]); break; case CMD_T55XX_READ_BLOCK: - T55xxReadBlock(c->arg[1], c->arg[2],c->d.asBytes[0]); + T55xxReadBlock(c->arg[0], c->arg[1], c->arg[2]); 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(); + case CMD_T55XX_WAKEUP: + T55xxWakeUp(c->arg[0]); + break; + case CMD_T55XX_RESET_READ: + T55xxResetRead(); break; case CMD_PCF7931_READ: ReadPCF7931(); - cmd_send(CMD_ACK,0,0,0,0,0); break; case CMD_PCF7931_WRITE: - WritePCF7931(c->d.asDwords[0],c->d.asDwords[1],c->d.asDwords[2],c->d.asDwords[3],c->d.asDwords[4],c->d.asDwords[5],c->d.asDwords[6], c->d.asDwords[9], c->d.asDwords[7]-128,c->d.asDwords[8]-128, c->arg[0], c->arg[1], c->arg[2]); + WritePCF7931(c->d.asBytes[0],c->d.asBytes[1],c->d.asBytes[2],c->d.asBytes[3],c->d.asBytes[4],c->d.asBytes[5],c->d.asBytes[6], c->d.asBytes[9], c->d.asBytes[7]-128,c->d.asBytes[8]-128, c->arg[0], c->arg[1], c->arg[2]); break; case CMD_EM4X_READ_WORD: EM4xReadWord(c->arg[1], c->arg[2],c->d.asBytes[0]); @@ -998,7 +1000,7 @@ void UsbPacketReceived(uint8_t *packet, int len) break; case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation CmdAWIDdemodFSK(c->arg[0], 0, 0, 1); - break; + break; #endif #ifdef WITH_HITAG diff --git a/armsrc/apps.h b/armsrc/apps.h index 2cfd31d7..4f3b50c6 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -58,7 +58,7 @@ extern uint8_t bits_per_sample ; extern bool averaging; void AcquireRawAdcSamples125k(int divisor); -void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,uint8_t *command); +void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command); void ReadTItag(void); void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc); @@ -73,24 +73,18 @@ 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 +void CopyIOtoT55x7(uint32_t hi, uint32_t lo); // Clone an ioProx card to T5557/T5567 void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen); void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567 void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo); -void CopyIndala64toT55x7(int hi, int lo); // Clone Indala 64-bit tag by UID to T55x7 -void CopyIndala224toT55x7(int uid1, int uid2, int uid3, int uid4, int uid5, int uid6, int uid7); // Clone Indala 224-bit tag by UID to T55x7 +void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7 +void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7 +void T55xxResetRead(void); void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMode); -void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode ); -void T55xxReadTrace(void); -int DemodPCF7931(uint8_t **outBlocks); -int IsBlock0PCF7931(uint8_t *Block); -int IsBlock1PCF7931(uint8_t *Block); -void ReadPCF7931(); -void SendCmdPCF7931(uint32_t * tab); -bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p); -bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p); -bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab); -void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data); +void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd); +void T55xxWakeUp(uint32_t Pwd); +void TurnReadLFOn(); +//void T55xxReadTrace(void); void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode); void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index d7f91c53..01b88178 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -16,6 +16,7 @@ #include "string.h" #include "lfdemod.h" #include "lfsampling.h" +#include "protocols.h" #include "usb_cdc.h" //test /** @@ -25,7 +26,7 @@ * @param period_1 * @param command */ -void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, uint8_t *command) +void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command) { int divisor_used = 95; // 125 KHz @@ -648,7 +649,6 @@ static void biphaseSimBit(uint8_t c, int *n, uint8_t clock, uint8_t *phase) memset(dest+(*n), c ^ *phase, clock); *phase ^= 1; } - } // args clock, ask/man or askraw, invert, transmission separator @@ -768,7 +768,7 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol) // Configure to go in 125Khz listen mode LFSetupFPGAForADC(95, true); - while(!BUTTON_PRESS()) { + while(!BUTTON_PRESS() && !usb_poll_validate_length()) { WDT_HIT(); if (ledcontrol) LED_A_ON(); @@ -857,7 +857,7 @@ void CmdAWIDdemodFSK(int findone, int *high, int *low, int ledcontrol) // Configure to go in 125Khz listen mode LFSetupFPGAForADC(95, true); - while(!BUTTON_PRESS()) { + while(!BUTTON_PRESS() && !usb_poll_validate_length()) { WDT_HIT(); if (ledcontrol) LED_A_ON(); @@ -948,7 +948,7 @@ void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol) // Configure to go in 125Khz listen mode LFSetupFPGAForADC(95, true); - while(!BUTTON_PRESS()) { + while(!BUTTON_PRESS() && !usb_poll_validate_length()) { WDT_HIT(); if (ledcontrol) LED_A_ON(); @@ -1007,7 +1007,7 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) // Configure to go in 125Khz listen mode LFSetupFPGAForADC(95, true); - while(!BUTTON_PRESS()) { + while(!BUTTON_PRESS() && !usb_poll_validate_length()) { WDT_HIT(); if (ledcontrol) LED_A_ON(); DoAcquisition_default(-1,true); @@ -1062,237 +1062,225 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) } /*------------------------------ - * T5555/T5557/T5567 routines + * T5555/T5557/T5567/T5577 routines *------------------------------ */ -/* T55x7 configuration register definitions */ -#define T55x7_POR_DELAY 0x00000001 -#define T55x7_ST_TERMINATOR 0x00000008 -#define T55x7_PWD 0x00000010 -#define T55x7_MAXBLOCK_SHIFT 5 -#define T55x7_AOR 0x00000200 -#define T55x7_PSKCF_RF_2 0 -#define T55x7_PSKCF_RF_4 0x00000400 -#define T55x7_PSKCF_RF_8 0x00000800 -#define T55x7_MODULATION_DIRECT 0 -#define T55x7_MODULATION_PSK1 0x00001000 -#define T55x7_MODULATION_PSK2 0x00002000 -#define T55x7_MODULATION_PSK3 0x00003000 -#define T55x7_MODULATION_FSK1 0x00004000 -#define T55x7_MODULATION_FSK2 0x00005000 -#define T55x7_MODULATION_FSK1a 0x00006000 -#define T55x7_MODULATION_FSK2a 0x00007000 -#define T55x7_MODULATION_MANCHESTER 0x00008000 -#define T55x7_MODULATION_BIPHASE 0x00010000 -#define T55x7_BITRATE_RF_8 0 -#define T55x7_BITRATE_RF_16 0x00040000 -#define T55x7_BITRATE_RF_32 0x00080000 -#define T55x7_BITRATE_RF_40 0x000C0000 -#define T55x7_BITRATE_RF_50 0x00100000 -#define T55x7_BITRATE_RF_64 0x00140000 -#define T55x7_BITRATE_RF_100 0x00180000 -#define T55x7_BITRATE_RF_128 0x001C0000 - -/* T5555 (Q5) configuration register definitions */ -#define T5555_ST_TERMINATOR 0x00000001 -#define T5555_MAXBLOCK_SHIFT 0x00000001 -#define T5555_MODULATION_MANCHESTER 0 -#define T5555_MODULATION_PSK1 0x00000010 -#define T5555_MODULATION_PSK2 0x00000020 -#define T5555_MODULATION_PSK3 0x00000030 -#define T5555_MODULATION_FSK1 0x00000040 -#define T5555_MODULATION_FSK2 0x00000050 -#define T5555_MODULATION_BIPHASE 0x00000060 -#define T5555_MODULATION_DIRECT 0x00000070 -#define T5555_INVERT_OUTPUT 0x00000080 -#define T5555_PSK_RF_2 0 -#define T5555_PSK_RF_4 0x00000100 -#define T5555_PSK_RF_8 0x00000200 -#define T5555_USE_PWD 0x00000400 -#define T5555_USE_AOR 0x00000800 -#define T5555_BITRATE_SHIFT 12 -#define T5555_FAST_WRITE 0x00004000 -#define T5555_PAGE_SELECT 0x00008000 +/* NOTE: T55x7/T5555 configuration register definitions moved to protocols.h */ /* - * Relevant times in microsecond + * Relevant communication times in microsecond * To compensate antenna falling times shorten the write times * and enlarge the gap ones. + * Q5 tags seems to have issues when these values changes. */ #define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (or 15fc) #define WRITE_GAP 20*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (or 10fc) #define WRITE_0 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (or 24fc) #define WRITE_1 50*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (or 56fc) 432 for T55x7; 448 for E5550 +#define READ_GAP 52*8 -#define T55xx_SAMPLES_SIZE 12000 // 32 x 32 x 10 (32 bit times numofblock (7), times clock skip..) +// VALUES TAKEN FROM EM4x function: SendForward +// START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle) +// WRITE_GAP = 128; (16*8) +// WRITE_1 = 256 32*8; (32*8) -// Write one bit to card -void T55xxWriteBit(int bit) -{ - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz +// These timings work for 4469/4269/4305 (with the 55*8 above) +// WRITE_0 = 23*8 , 9*8 SpinDelayUs(23*8); + +// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) +// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz +// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) +// T0 = TIMER_CLOCK1 / 125000 = 192 +// 1 Cycle = 8 microseconds(us) == 1 field clock + +void TurnReadLFOn(int delay) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - if (bit == 0) - SpinDelayUs(WRITE_0); + // Give it a bit of time for the resonant antenna to settle. + SpinDelayUs(delay); //155*8 //50*8 +} + +// Write one bit to card +void T55xxWriteBit(int bit) { + if (!bit) + TurnReadLFOn(WRITE_0); else - SpinDelayUs(WRITE_1); + TurnReadLFOn(WRITE_1); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); SpinDelayUs(WRITE_GAP); } +// Send T5577 reset command then read stream (see if we can identify the start of the stream) +void T55xxResetRead(void) { + LED_A_ON(); + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_ext(false); + + // Set up FPGA, 125kHz + LFSetupFPGAForADC(95, true); + + // Trigger T55x7 in mode. + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelayUs(START_GAP); + + // reset tag - op code 00 + T55xxWriteBit(0); + T55xxWriteBit(0); + + // Turn field on to read the response + TurnReadLFOn(READ_GAP); + + // Acquisition + doT55x7Acquisition(BigBuf_max_traceLen()); + + // Turn the field off + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off + cmd_send(CMD_ACK,0,0,0,0,0); + LED_A_OFF(); +} + // Write one card block in page 0, no lock -void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMode) -{ +void T55xxWriteBlockExt(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { + LED_A_ON(); + bool PwdMode = arg & 0x1; + uint8_t Page = (arg & 0x2)>>1; uint32_t i = 0; // Set up FPGA, 125kHz - // Wait for config.. (192+8190xPOW)x8 == 67ms - LFSetupFPGAForADC(0, true); + LFSetupFPGAForADC(95, true); - // Now start writting + // Trigger T55x7 in mode. FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); SpinDelayUs(START_GAP); - // Opcode + // Opcode 10 T55xxWriteBit(1); - T55xxWriteBit(0); //Page 0 - if (PwdMode == 1){ - // Pwd + T55xxWriteBit(Page); //Page 0 + if (PwdMode){ + // Send Pwd for (i = 0x80000000; i != 0; i >>= 1) T55xxWriteBit(Pwd & i); } - // Lock bit + // Send Lock bit T55xxWriteBit(0); - // Data + // Send Data for (i = 0x80000000; i != 0; i >>= 1) T55xxWriteBit(Data & i); - // Block + // Send Block number for (i = 0x04; i != 0; i >>= 1) T55xxWriteBit(Block & i); - // Now perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550, + // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550, // so wait a little more) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - SpinDelay(20); + TurnReadLFOn(20 * 1000); + //could attempt to do a read to confirm write took + // as the tag should repeat back the new block + // until it is reset, but to confirm it we would + // need to know the current block 0 config mode + + // turn field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_A_OFF(); } -void TurnReadLFOn(){ - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - // Give it a bit of time for the resonant antenna to settle. - SpinDelayUs(8*150); +// Write one card block in page 0, no lock +void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { + T55xxWriteBlockExt(Data, Block, Pwd, arg); + cmd_send(CMD_ACK,0,0,0,0,0); } - // Read one card block in page 0 -void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode) -{ +void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { + LED_A_ON(); + bool PwdMode = arg0 & 0x1; + uint8_t Page = (arg0 & 0x2) >> 1; uint32_t i = 0; - uint8_t *dest = BigBuf_get_addr(); - uint16_t bufferlength = BigBuf_max_traceLen(); - if ( bufferlength > T55xx_SAMPLES_SIZE ) - bufferlength = T55xx_SAMPLES_SIZE; + bool RegReadMode = (Block == 0xFF); - // Clear destination buffer before sending the command - memset(dest, 0x80, bufferlength); + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_ext(false); - // Set up FPGA, 125kHz - // Wait for config.. (192+8190xPOW)x8 == 67ms - LFSetupFPGAForADC(0, true); + //make sure block is at max 7 + Block &= 0x7; + + // Set up FPGA, 125kHz to power up the tag + LFSetupFPGAForADC(95, true); + + // Trigger T55x7 Direct Access Mode with start gap FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); SpinDelayUs(START_GAP); - // Opcode + // Opcode 1[page] T55xxWriteBit(1); - T55xxWriteBit(0); //Page 0 - if (PwdMode == 1){ - // Pwd + T55xxWriteBit(Page); //Page 0 + + if (PwdMode){ + // Send Pwd for (i = 0x80000000; i != 0; i >>= 1) T55xxWriteBit(Pwd & i); } - // Lock bit + // Send a zero bit separation T55xxWriteBit(0); - // Block - for (i = 0x04; i != 0; i >>= 1) - T55xxWriteBit(Block & i); + + // Send Block number (if direct access mode) + if (!RegReadMode) + for (i = 0x04; i != 0; i >>= 1) + T55xxWriteBit(Block & i); // Turn field on to read the response - TurnReadLFOn(); - // Now do the acquisition - i = 0; - for(;;) { - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { - AT91C_BASE_SSC->SSC_THR = 0x43; - LED_D_ON(); - } - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - i++; - LED_D_OFF(); - if (i >= bufferlength) break; - } - } + TurnReadLFOn(READ_GAP); - cmd_send(CMD_ACK,0,0,0,0,0); + // Acquisition + doT55x7Acquisition(12000); + + // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - LED_D_OFF(); + cmd_send(CMD_ACK,0,0,0,0,0); + LED_A_OFF(); } -// Read card traceability data (page 1) -void T55xxReadTrace(void){ - +void T55xxWakeUp(uint32_t Pwd){ + LED_B_ON(); uint32_t i = 0; - uint8_t *dest = BigBuf_get_addr(); - uint16_t bufferlength = BigBuf_max_traceLen(); - if ( bufferlength > T55xx_SAMPLES_SIZE ) - bufferlength= T55xx_SAMPLES_SIZE; - - // Clear destination buffer before sending the command - memset(dest, 0x80, bufferlength); - - LFSetupFPGAForADC(0, true); + + // Set up FPGA, 125kHz + LFSetupFPGAForADC(95, true); + + // Trigger T55x7 Direct Access Mode FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); SpinDelayUs(START_GAP); - - // Opcode + + // Opcode 10 T55xxWriteBit(1); - T55xxWriteBit(1); //Page 1 + T55xxWriteBit(0); //Page 0 - // Turn field on to read the response - TurnReadLFOn(); + // Send Pwd + for (i = 0x80000000; i != 0; i >>= 1) + T55xxWriteBit(Pwd & i); - // Now do the acquisition - for(;;) { - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { - AT91C_BASE_SSC->SSC_THR = 0x43; - LED_D_ON(); - } - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - i++; - LED_D_OFF(); + // Turn and leave field on to let the begin repeating transmission + TurnReadLFOn(20*1000); +} - if (i >= bufferlength) break; - } - } +/*-------------- Cloning routines -----------*/ - cmd_send(CMD_ACK,0,0,0,0,0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - LED_D_OFF(); +void WriteT55xx(uint32_t *blockdata, uint8_t startblock, uint8_t numblocks) { + // write last block first and config block last (if included) + for (uint8_t i = numblocks+startblock; i > startblock; i--) { + //Dbprintf("write- Blk: %d, d:%08X",i-1,blockdata[i-1]); + T55xxWriteBlockExt(blockdata[i-1],i-1,0,0); + } } -/*-------------- Cloning routines -----------*/ // Copy HID id to card and setup block 0 config -void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) -{ - int data1=0, data2=0, data3=0, data4=0, data5=0, data6=0; //up to six blocks for long format - int last_block = 0; +void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) { + uint32_t data[] = {0,0,0,0,0,0,0}; + //int data1=0, data2=0, data3=0, data4=0, data5=0, data6=0; //up to six blocks for long format + uint8_t last_block = 0; - if (longFMT){ + if (longFMT) { // Ensure no more than 84 bits supplied if (hi2>0xFFFFF) { DbpString("Tags can only have 84 bits."); @@ -1300,140 +1288,91 @@ void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) } // Build the 6 data blocks for supplied 84bit ID last_block = 6; - data1 = 0x1D96A900; // load preamble (1D) & long format identifier (9E manchester encoded) - for (int i=0;i<4;i++) { - if (hi2 & (1<<(19-i))) - data1 |= (1<<(((3-i)*2)+1)); // 1 -> 10 - else - data1 |= (1<<((3-i)*2)); // 0 -> 01 - } - - data2 = 0; - for (int i=0;i<16;i++) { - if (hi2 & (1<<(15-i))) - data2 |= (1<<(((15-i)*2)+1)); // 1 -> 10 - else - data2 |= (1<<((15-i)*2)); // 0 -> 01 - } - - data3 = 0; - for (int i=0;i<16;i++) { - if (hi & (1<<(31-i))) - data3 |= (1<<(((15-i)*2)+1)); // 1 -> 10 - else - data3 |= (1<<((15-i)*2)); // 0 -> 01 - } - - data4 = 0; - for (int i=0;i<16;i++) { - if (hi & (1<<(15-i))) - data4 |= (1<<(((15-i)*2)+1)); // 1 -> 10 - else - data4 |= (1<<((15-i)*2)); // 0 -> 01 - } - - data5 = 0; - for (int i=0;i<16;i++) { - if (lo & (1<<(31-i))) - data5 |= (1<<(((15-i)*2)+1)); // 1 -> 10 - else - data5 |= (1<<((15-i)*2)); // 0 -> 01 - } - - data6 = 0; - for (int i=0;i<16;i++) { - if (lo & (1<<(15-i))) - data6 |= (1<<(((15-i)*2)+1)); // 1 -> 10 - else - data6 |= (1<<((15-i)*2)); // 0 -> 01 - } - } - else { + // load preamble (1D) & long format identifier (9E manchester encoded) + data[1] = 0x1D96A900 | (manchesterEncode2Bytes((hi2 >> 16) & 0xF) & 0xFF); + // load raw id from hi2, hi, lo to data blocks (manchester encoded) + data[2] = manchesterEncode2Bytes(hi2 & 0xFFFF); + data[3] = manchesterEncode2Bytes(hi >> 16); + data[4] = manchesterEncode2Bytes(hi & 0xFFFF); + data[5] = manchesterEncode2Bytes(lo >> 16); + data[6] = manchesterEncode2Bytes(lo & 0xFFFF); + } else { // Ensure no more than 44 bits supplied if (hi>0xFFF) { DbpString("Tags can only have 44 bits."); return; } - // Build the 3 data blocks for supplied 44bit ID last_block = 3; - - data1 = 0x1D000000; // load preamble - - for (int i=0;i<12;i++) { - if (hi & (1<<(11-i))) - data1 |= (1<<(((11-i)*2)+1)); // 1 -> 10 - else - data1 |= (1<<((11-i)*2)); // 0 -> 01 - } - - data2 = 0; - for (int i=0;i<16;i++) { - if (lo & (1<<(31-i))) - data2 |= (1<<(((15-i)*2)+1)); // 1 -> 10 - else - data2 |= (1<<((15-i)*2)); // 0 -> 01 - } - - data3 = 0; - for (int i=0;i<16;i++) { - if (lo & (1<<(15-i))) - data3 |= (1<<(((15-i)*2)+1)); // 1 -> 10 - else - data3 |= (1<<((15-i)*2)); // 0 -> 01 - } + // load preamble + data[1] = 0x1D000000 | (manchesterEncode2Bytes(hi) & 0xFFFFFF); + data[2] = manchesterEncode2Bytes(lo >> 16); + data[3] = manchesterEncode2Bytes(lo & 0xFFFF); } + // load chip config block + data[0] = T55x7_BITRATE_RF_50 | T55x7_MODULATION_FSK2a | last_block << T55x7_MAXBLOCK_SHIFT; + + //TODO add selection of chip for Q5 or T55x7 + // data[0] = (((50-2)/2)<> 32), 1, 0, 0); - T55xxWriteBlock((uint32_t)id, 2, 0, 0); - - // Config for EM410x (RF/64, Manchester, Maxblock=2) - if (card) { - // Clock rate is stored in bits 8-15 of the card value - clock = (card & 0xFF00) >> 8; - Dbprintf("Clock rate: %d", clock); - switch (clock) - { - case 32: - clock = T55x7_BITRATE_RF_32; - break; - case 16: - clock = T55x7_BITRATE_RF_16; - break; - case 0: - // A value of 0 is assumed to be 64 for backwards-compatibility - // Fall through... - case 64: - clock = T55x7_BITRATE_RF_64; - break; - default: + uint32_t data[] = {0, id>>32, id & 0xFFFFFFFF}; + + clock = (card & 0xFF00) >> 8; + clock = (clock == 0) ? 64 : clock; + Dbprintf("Clock rate: %d", clock); + if (card & 0xFF) { //t55x7 + clock = GetT55xxClockBit(clock); + if (clock == 0) { Dbprintf("Invalid clock rate: %d", clock); return; } - - // Writing configuration for T55x7 tag - T55xxWriteBlock(clock | - T55x7_MODULATION_MANCHESTER | - 2 << T55x7_MAXBLOCK_SHIFT, - 0, 0, 0); + data[0] = clock | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT); + } else { //t5555 (Q5) + clock = (clock-2)>>1; //n = (RF-2)/2 + data[0] = (clock << T5555_BITRATE_SHIFT) | T5555_MODULATION_MANCHESTER | (2 << T5555_MAXBLOCK_SHIFT); } - else - // Writing configuration for T5555(Q5) tag - T55xxWriteBlock(0x1F << T5555_BITRATE_SHIFT | - T5555_MODULATION_MANCHESTER | - 2 << T5555_MAXBLOCK_SHIFT, - 0, 0, 0); + + WriteT55xx(data, 0, 3); LED_D_OFF(); Dbprintf("Tag %s written with 0x%08x%08x\n", card ? "T55x7":"T5555", (uint32_t)(id >> 32), (uint32_t)id); } -// Clone Indala 64-bit tag by UID to T55x7 -void CopyIndala64toT55x7(int hi, int lo) -{ - - //Program the 2 data blocks for supplied 64bit UID - // and the block 0 for Indala64 format - T55xxWriteBlock(hi,1,0,0); - T55xxWriteBlock(lo,2,0,0); - //Config for Indala (RF/32;PSK1 with RF/2;Maxblock=2) - T55xxWriteBlock(T55x7_BITRATE_RF_32 | - T55x7_MODULATION_PSK1 | - 2 << T55x7_MAXBLOCK_SHIFT, - 0, 0, 0); - //Alternative config for Indala (Extended mode;RF/32;PSK1 with RF/2;Maxblock=2;Inverse data) - // T5567WriteBlock(0x603E1042,0); - - DbpString("DONE!"); - -} - -void CopyIndala224toT55x7(int uid1, int uid2, int uid3, int uid4, int uid5, int uid6, int uid7) -{ - - //Program the 7 data blocks for supplied 224bit UID - // and the block 0 for Indala224 format - T55xxWriteBlock(uid1,1,0,0); - T55xxWriteBlock(uid2,2,0,0); - T55xxWriteBlock(uid3,3,0,0); - T55xxWriteBlock(uid4,4,0,0); - T55xxWriteBlock(uid5,5,0,0); - T55xxWriteBlock(uid6,6,0,0); - T55xxWriteBlock(uid7,7,0,0); - //Config for Indala (RF/32;PSK1 with RF/2;Maxblock=7) - T55xxWriteBlock(T55x7_BITRATE_RF_32 | - T55x7_MODULATION_PSK1 | - 7 << T55x7_MAXBLOCK_SHIFT, - 0,0,0); - //Alternative config for Indala (Extended mode;RF/32;PSK1 with RF/2;Maxblock=7;Inverse data) - // T5567WriteBlock(0x603E10E2,0); - - DbpString("DONE!"); - -} - - -#define abs(x) ( ((x)<0) ? -(x) : (x) ) -#define max(x,y) ( x GraphBuffer[0]) { - while(i < GraphTraceLen) { - if( !(GraphBuffer[i] > GraphBuffer[i-1]) && GraphBuffer[i] > lmax) - break; - i++; - } - dir = 0; - } - else { - while(i < GraphTraceLen) { - if( !(GraphBuffer[i] < GraphBuffer[i-1]) && GraphBuffer[i] < lmin) - break; - i++; - } - dir = 1; - } - - lastval = i++; - half_switch = 0; - pmc = 0; - block_done = 0; - - for (bitidx = 0; i < GraphTraceLen; i++) - { - if ( (GraphBuffer[i-1] > GraphBuffer[i] && dir == 1 && GraphBuffer[i] > lmax) || (GraphBuffer[i-1] < GraphBuffer[i] && dir == 0 && GraphBuffer[i] < lmin)) - { - lc = i - lastval; - lastval = i; - - // Switch depending on lc length: - // Tolerance is 1/8 of clock rate (arbitrary) - if (abs(lc-clock/4) < tolerance) { - // 16T0 - if((i - pmc) == lc) { /* 16T0 was previous one */ - /* It's a PMC ! */ - i += (128+127+16+32+33+16)-1; - lastval = i; - pmc = 0; - block_done = 1; - } - else { - pmc = i; - } - } else if (abs(lc-clock/2) < tolerance) { - // 32TO - if((i - pmc) == lc) { /* 16T0 was previous one */ - /* It's a PMC ! */ - i += (128+127+16+32+33)-1; - lastval = i; - pmc = 0; - block_done = 1; - } - else if(half_switch == 1) { - BitStream[bitidx++] = 0; - half_switch = 0; - } - else - half_switch++; - } else if (abs(lc-clock) < tolerance) { - // 64TO - BitStream[bitidx++] = 1; - } else { - // Error - warnings++; - if (warnings > 10) - { - Dbprintf("Error: too many detection errors, aborting."); - return 0; - } - } - - if(block_done == 1) { - if(bitidx == 128) { - for(j=0; j<16; j++) { - Blocks[num_blocks][j] = 128*BitStream[j*8+7]+ - 64*BitStream[j*8+6]+ - 32*BitStream[j*8+5]+ - 16*BitStream[j*8+4]+ - 8*BitStream[j*8+3]+ - 4*BitStream[j*8+2]+ - 2*BitStream[j*8+1]+ - BitStream[j*8]; - } - num_blocks++; - } - bitidx = 0; - block_done = 0; - half_switch = 0; - } - if(i < GraphTraceLen) - { - if (GraphBuffer[i-1] > GraphBuffer[i]) dir=0; - else dir = 1; - } - } - if(bitidx==255) - bitidx=0; - warnings = 0; - if(num_blocks == 4) break; - } - memcpy(outBlocks, Blocks, 16*num_blocks); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - - return num_blocks; -} - -int IsBlock0PCF7931(uint8_t *Block) { - // Assume RFU means 0 :) - if((memcmp(Block, "\x00\x00\x00\x00\x00\x00\x00\x01", 8) == 0) && memcmp(Block+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) // PAC enabled - return 1; - if((memcmp(Block+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) && Block[7] == 0) // PAC disabled, can it *really* happen ? - return 1; - return 0; -} - -int IsBlock1PCF7931(uint8_t *Block) { - // Assume RFU means 0 :) - if(Block[10] == 0 && Block[11] == 0 && Block[12] == 0 && Block[13] == 0) - if((Block[14] & 0x7f) <= 9 && Block[15] <= 9) - return 1; - - return 0; -} - -#define ALLOC 16 - -void ReadPCF7931() { - uint8_t Blocks[8][17]; - uint8_t tmpBlocks[4][16]; - int i, j, ind, ind2, n; - int num_blocks = 0; - int max_blocks = 8; - int ident = 0; - int error = 0; - int tries = 0; - - memset(Blocks, 0, 8*17*sizeof(uint8_t)); - - do { - memset(tmpBlocks, 0, 4*16*sizeof(uint8_t)); - n = DemodPCF7931((uint8_t**)tmpBlocks); - if(!n) - error++; - if(error==10 && num_blocks == 0) { - Dbprintf("Error, no tag or bad tag"); - return; - } - else if (tries==20 || error==10) { - Dbprintf("Error reading the tag"); - Dbprintf("Here is the partial content"); - goto end; - } - - for(i=0; i= 0; ind--,ind2--) { - if(ind2 < 0) - ind2 = max_blocks; - if(!Blocks[ind2][ALLOC]) { // Block ind2 not already found - // Dbprintf("Tmp %d -> Block %d", ind, ind2); - memcpy(Blocks[ind2], tmpBlocks[ind], 16); - Blocks[ind2][ALLOC] = 1; - num_blocks++; - if(num_blocks == max_blocks) goto end; - } - } - for(ind=i+1,ind2=j+1; ind < n; ind++,ind2++) { - if(ind2 > max_blocks) - ind2 = 0; - if(!Blocks[ind2][ALLOC]) { // Block ind2 not already found - // Dbprintf("Tmp %d -> Block %d", ind, ind2); - memcpy(Blocks[ind2], tmpBlocks[ind], 16); - Blocks[ind2][ALLOC] = 1; - num_blocks++; - if(num_blocks == max_blocks) goto end; - } - } - } - } - } - } - } - tries++; - if (BUTTON_PRESS()) return; - } while (num_blocks != max_blocks); - end: - Dbprintf("-----------------------------------------"); - Dbprintf("Memory content:"); - Dbprintf("-----------------------------------------"); - for(i=0; i", i); - } - Dbprintf("-----------------------------------------"); - - - return ; -} - - //----------------------------------- // EM4469 / EM4305 routines //----------------------------------- @@ -1961,14 +1567,8 @@ void SendForward(uint8_t fwd_bit_count) { LED_D_ON(); - //Field on - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - - // Give it a bit of time for the resonant antenna to settle. - // And for the tag to fully power up - SpinDelay(150); + // Set up FPGA, 125kHz + LFSetupFPGAForADC(95, true); // force 1st mod pulse (start gap must be longer for 4305) fwd_bit_sz--; //prepare next bit modulation @@ -2013,7 +1613,11 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { uint8_t fwd_bit_count; uint8_t *dest = BigBuf_get_addr(); - int m=0, i=0; + uint16_t bufferlength = BigBuf_max_traceLen(); + uint32_t i = 0; + + // Clear destination buffer before sending the command + memset(dest, 0x80, bufferlength); //If password mode do login if (PwdMode == 1) EM4xLogin(Pwd); @@ -2022,9 +1626,6 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { fwd_bit_count = Prepare_Cmd( FWD_CMD_READ ); fwd_bit_count += Prepare_Addr( Address ); - m = BigBuf_max_traceLen(); - // Clear destination buffer before sending the command - memset(dest, 128, m); // Connect the A/D to the peak-detected low-frequency path. SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Now set up the SSC to get the ADC samples that are now streaming at us. @@ -2041,10 +1642,11 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; i++; - if (i >= m) break; + if (i >= bufferlength) break; } } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off + cmd_send(CMD_ACK,0,0,0,0,0); LED_D_OFF(); } @@ -2067,261 +1669,3 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_D_OFF(); } - - -#define T0_PCF 8 //period for the pcf7931 in us - -/* Write on a byte of a PCF7931 tag - * @param address : address of the block to write - @param byte : address of the byte to write - @param data : data to write - */ -void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) -{ - - uint32_t tab[1024]={0}; // data times frame - uint32_t u = 0; - uint8_t parity = 0; - bool comp = 0; - - - //BUILD OF THE DATA FRAME - - //alimentation of the tag (time for initializing) - AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab); - - //PMC - Dbprintf("Initialization delay : %d us", init_delay); - AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab); - - Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p); - - //password indication bit - AddBitPCF7931(1, tab, l, p); - - - //password (on 56 bits) - Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1,pass2,pass3,pass4,pass5,pass6,pass7); - AddBytePCF7931(pass1, tab, l, p); - AddBytePCF7931(pass2, tab, l, p); - AddBytePCF7931(pass3, tab, l, p); - AddBytePCF7931(pass4, tab, l, p); - AddBytePCF7931(pass5, tab, l, p); - AddBytePCF7931(pass6, tab, l, p); - AddBytePCF7931(pass7, tab, l, p); - - - //programming mode (0 or 1) - AddBitPCF7931(0, tab, l, p); - - //block adress on 6 bits - Dbprintf("Block address : %02x", address); - for (u=0; u<6; u++) - { - if (address&(1< 0xFFFF){ - tab[u] -= 0xFFFF; - comp = 0; - } - } - } - - SendCmdPCF7931(tab); -} - - - -/* Send a trame to a PCF7931 tags - * @param tab : array of the data frame - */ - -void SendCmdPCF7931(uint32_t * tab){ - uint16_t u=0; - uint16_t tempo=0; - - Dbprintf("SENDING DATA FRAME..."); - - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU ); - - LED_A_ON(); - - // steal this pin from the SSP and use it to control the modulation - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - - //initialization of the timer - AT91C_BASE_PMC->PMC_PCER |= (0x1 << 12) | (0x1 << 13) | (0x1 << 14); - AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; - AT91C_BASE_TCB->TCB_BCR = 1; - - - tempo = AT91C_BASE_TC0->TC_CV; - for(u=0;tab[u]!= 0;u+=3){ - - - // modulate antenna - HIGH(GPIO_SSC_DOUT); - while(tempo != tab[u]){ - tempo = AT91C_BASE_TC0->TC_CV; - } - - // stop modulating antenna - LOW(GPIO_SSC_DOUT); - while(tempo != tab[u+1]){ - tempo = AT91C_BASE_TC0->TC_CV; - } - - - // modulate antenna - HIGH(GPIO_SSC_DOUT); - while(tempo != tab[u+2]){ - tempo = AT91C_BASE_TC0->TC_CV; - } - - - } - - LED_A_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(200); - - - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable - DbpString("FINISH !"); - DbpString("(Could be usefull to send the same trame many times)"); - LED(0xFFFF, 1000); -} - - -/* Add a byte for building the data frame of PCF7931 tags - * @param b : byte to add - * @param tab : array of the data frame - * @param l : offset on low pulse width - * @param p : offset on low pulse positioning - */ - -bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){ - - uint32_t u; - for (u=0; u<8; u++) - { - if (byte&(1< 0) && (sample < (trigger_threshold+128)) && (sample > (128-trigger_threshold))) // continue; - //if (trigger_threshold > 0 && sample < trigger_threshold) // - //continue; - trigger_threshold = 0; sample_total_numbers++; @@ -252,3 +248,59 @@ uint32_t SnoopLF() { return ReadLF(false, true); } + +/** +* acquisition of T55x7 LF signal. Similart to other LF, but adjusted with @marshmellows thresholds +* the data is collected in BigBuf. +**/ +void doT55x7Acquisition(size_t sample_size) { + + #define T55xx_READ_UPPER_THRESHOLD 128+40 // 40 grph + #define T55xx_READ_TOL 5 + + uint8_t *dest = BigBuf_get_addr(); + uint16_t bufsize = BigBuf_max_traceLen(); + + if ( bufsize > sample_size ) + bufsize = sample_size; + + uint16_t i = 0; + bool startFound = false; + bool highFound = false; + uint8_t curSample = 0; + uint8_t firstSample = 0; + uint16_t skipCnt = 0; + while(!BUTTON_PRESS() && skipCnt<1000) { + WDT_HIT(); + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { + AT91C_BASE_SSC->SSC_THR = 0x43; + LED_D_ON(); + } + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + LED_D_OFF(); + + // skip until the first high sample above threshold + if (!startFound && curSample > T55xx_READ_UPPER_THRESHOLD) { + if (curSample > firstSample) + firstSample = curSample; + highFound = true; + } else if (!highFound) { + skipCnt++; + continue; + } + + // skip until first high samples begin to change + if (startFound || curSample < firstSample-T55xx_READ_TOL){ + // if just found start - recover last sample + if (!startFound) { + dest[i++] = firstSample; + startFound = true; + } + // collect samples + dest[i++] = curSample; + if (i >= bufsize-1) break; + } + } + } +} diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index 7d3925cd..bd8ad1d0 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -1,6 +1,12 @@ #ifndef LFSAMPLING_H #define LFSAMPLING_H +/** +* acquisition of T55x7 LF signal. Similart to other LF, but adjusted with @marshmellows thresholds +* the data is collected in BigBuf. +**/ +void doT55x7Acquisition(size_t sample_size); + /** * Initializes the FPGA for reader-mode (field on), and acquires the samples. * @return number of bits sampled @@ -41,7 +47,6 @@ uint32_t DoAcquisition_config( bool silent); **/ void LFSetupFPGAForADC(int divisor, bool lf_field); - /** * Called from the USB-handler to set the sampling configuration * The sampling config is used for std reading and snooping. diff --git a/armsrc/pcf7931.c b/armsrc/pcf7931.c new file mode 100644 index 00000000..3093a5e5 --- /dev/null +++ b/armsrc/pcf7931.c @@ -0,0 +1,526 @@ +#include "proxmark3.h" +#include "apps.h" +#include "lfsampling.h" +#include "pcf7931.h" +#include "string.h" + +#define T0_PCF 8 //period for the pcf7931 in us +#define ALLOC 16 + +#define abs(x) ( ((x)<0) ? -(x) : (x) ) +#define max(x,y) ( x 18000 ) + GraphTraceLen = 18000; + + + int i, j, lastval, bitidx, half_switch; + int clock = 64; + int tolerance = clock / 8; + int pmc, block_done; + int lc, warnings = 0; + int num_blocks = 0; + int lmin=128, lmax=128; + uint8_t dir; + + LFSetupFPGAForADC(95, true); + DoAcquisition_default(0, true); + + lmin = 64; + lmax = 192; + + i = 2; + + /* Find first local max/min */ + if(dest[1] > dest[0]) { + while(i < GraphTraceLen) { + if( !(dest[i] > dest[i-1]) && dest[i] > lmax) + break; + i++; + } + dir = 0; + } + else { + while(i < GraphTraceLen) { + if( !(dest[i] < dest[i-1]) && dest[i] < lmin) + break; + i++; + } + dir = 1; + } + + lastval = i++; + half_switch = 0; + pmc = 0; + block_done = 0; + + for (bitidx = 0; i < GraphTraceLen; i++) + { + if ( (dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin)) + { + lc = i - lastval; + lastval = i; + + // Switch depending on lc length: + // Tolerance is 1/8 of clock rate (arbitrary) + if (abs(lc-clock/4) < tolerance) { + // 16T0 + if((i - pmc) == lc) { /* 16T0 was previous one */ + /* It's a PMC ! */ + i += (128+127+16+32+33+16)-1; + lastval = i; + pmc = 0; + block_done = 1; + } + else { + pmc = i; + } + } else if (abs(lc-clock/2) < tolerance) { + // 32TO + if((i - pmc) == lc) { /* 16T0 was previous one */ + /* It's a PMC ! */ + i += (128+127+16+32+33)-1; + lastval = i; + pmc = 0; + block_done = 1; + } + else if(half_switch == 1) { + bits[bitidx++] = 0; + half_switch = 0; + } + else + half_switch++; + } else if (abs(lc-clock) < tolerance) { + // 64TO + bits[bitidx++] = 1; + } else { + // Error + warnings++; + if (warnings > 10) + { + Dbprintf("Error: too many detection errors, aborting."); + return 0; + } + } + + if(block_done == 1) { + if(bitidx == 128) { + for(j=0; j<16; j++) { + blocks[num_blocks][j] = 128*bits[j*8+7]+ + 64*bits[j*8+6]+ + 32*bits[j*8+5]+ + 16*bits[j*8+4]+ + 8*bits[j*8+3]+ + 4*bits[j*8+2]+ + 2*bits[j*8+1]+ + bits[j*8]; + + } + num_blocks++; + } + bitidx = 0; + block_done = 0; + half_switch = 0; + } + if(i < GraphTraceLen) + dir =(dest[i-1] > dest[i]) ? 0 : 1; + } + if(bitidx==255) + bitidx=0; + warnings = 0; + if(num_blocks == 4) break; + } + memcpy(outBlocks, blocks, 16*num_blocks); + return num_blocks; +} + +int IsBlock0PCF7931(uint8_t *Block) { + // Assume RFU means 0 :) + if((memcmp(Block, "\x00\x00\x00\x00\x00\x00\x00\x01", 8) == 0) && memcmp(Block+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) // PAC enabled + return 1; + if((memcmp(Block+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) && Block[7] == 0) // PAC disabled, can it *really* happen ? + return 1; + return 0; +} + +int IsBlock1PCF7931(uint8_t *Block) { + // Assume RFU means 0 :) + if(Block[10] == 0 && Block[11] == 0 && Block[12] == 0 && Block[13] == 0) + if((Block[14] & 0x7f) <= 9 && Block[15] <= 9) + return 1; + + return 0; +} + +void ReadPCF7931() { + uint8_t Blocks[8][17]; + uint8_t tmpBlocks[4][16]; + int i, j, ind, ind2, n; + int num_blocks = 0; + int max_blocks = 8; + int ident = 0; + int error = 0; + int tries = 0; + + memset(Blocks, 0, 8*17*sizeof(uint8_t)); + + do { + memset(tmpBlocks, 0, 4*16*sizeof(uint8_t)); + n = DemodPCF7931((uint8_t**)tmpBlocks); + if(!n) + error++; + if(error==10 && num_blocks == 0) { + Dbprintf("Error, no tag or bad tag"); + return; + } + else if (tries==20 || error==10) { + Dbprintf("Error reading the tag"); + Dbprintf("Here is the partial content"); + goto end; + } + + for(i=0; i= 0; ind--,ind2--) { + if(ind2 < 0) + ind2 = max_blocks; + if(!Blocks[ind2][ALLOC]) { // Block ind2 not already found + // Dbprintf("Tmp %d -> Block %d", ind, ind2); + memcpy(Blocks[ind2], tmpBlocks[ind], 16); + Blocks[ind2][ALLOC] = 1; + num_blocks++; + if(num_blocks == max_blocks) goto end; + } + } + for(ind=i+1,ind2=j+1; ind < n; ind++,ind2++) { + if(ind2 > max_blocks) + ind2 = 0; + if(!Blocks[ind2][ALLOC]) { // Block ind2 not already found + // Dbprintf("Tmp %d -> Block %d", ind, ind2); + memcpy(Blocks[ind2], tmpBlocks[ind], 16); + Blocks[ind2][ALLOC] = 1; + num_blocks++; + if(num_blocks == max_blocks) goto end; + } + } + } + } + } + } + } + tries++; + if (BUTTON_PRESS()) return; + } while (num_blocks != max_blocks); + end: + Dbprintf("-----------------------------------------"); + Dbprintf("Memory content:"); + Dbprintf("-----------------------------------------"); + for(i=0; i", i); + } + Dbprintf("-----------------------------------------"); + + cmd_send(CMD_ACK,0,0,0,0,0); +} + + +/* Write on a byte of a PCF7931 tag + * @param address : address of the block to write + @param byte : address of the byte to write + @param data : data to write + */ +void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) +{ + + uint32_t tab[1024]={0}; // data times frame + uint32_t u = 0; + uint8_t parity = 0; + bool comp = 0; + + //BUILD OF THE DATA FRAME + + //alimentation of the tag (time for initializing) + AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab); + + //PMC + Dbprintf("Initialization delay : %d us", init_delay); + AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab); + + Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p); + + //password indication bit + AddBitPCF7931(1, tab, l, p); + + + //password (on 56 bits) + Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1,pass2,pass3,pass4,pass5,pass6,pass7); + AddBytePCF7931(pass1, tab, l, p); + AddBytePCF7931(pass2, tab, l, p); + AddBytePCF7931(pass3, tab, l, p); + AddBytePCF7931(pass4, tab, l, p); + AddBytePCF7931(pass5, tab, l, p); + AddBytePCF7931(pass6, tab, l, p); + AddBytePCF7931(pass7, tab, l, p); + + //programming mode (0 or 1) + AddBitPCF7931(0, tab, l, p); + + //block adress on 6 bits + Dbprintf("Block address : %02x", address); + for (u=0; u<6; u++) + { + if (address&(1< 0xFFFF){ + tab[u] -= 0xFFFF; + comp = 0; + } + } + } + + SendCmdPCF7931(tab); +} + + + +/* Send a trame to a PCF7931 tags + * @param tab : array of the data frame + */ + +void SendCmdPCF7931(uint32_t * tab){ + uint16_t u=0; + uint16_t tempo=0; + + Dbprintf("SENDING DATA FRAME..."); + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU ); + + LED_A_ON(); + + // steal this pin from the SSP and use it to control the modulation + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + + //initialization of the timer + AT91C_BASE_PMC->PMC_PCER |= (0x1 << 12) | (0x1 << 13) | (0x1 << 14); + AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; + AT91C_BASE_TCB->TCB_BCR = 1; + + + tempo = AT91C_BASE_TC0->TC_CV; + for(u=0;tab[u]!= 0;u+=3){ + + + // modulate antenna + HIGH(GPIO_SSC_DOUT); + while(tempo != tab[u]){ + tempo = AT91C_BASE_TC0->TC_CV; + } + + // stop modulating antenna + LOW(GPIO_SSC_DOUT); + while(tempo != tab[u+1]){ + tempo = AT91C_BASE_TC0->TC_CV; + } + + + // modulate antenna + HIGH(GPIO_SSC_DOUT); + while(tempo != tab[u+2]){ + tempo = AT91C_BASE_TC0->TC_CV; + } + + + } + + LED_A_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(200); + + + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable + DbpString("FINISH !"); + DbpString("(Could be usefull to send the same trame many times)"); + LED(0xFFFF, 1000); +} + + +/* Add a byte for building the data frame of PCF7931 tags + * @param b : byte to add + * @param tab : array of the data frame + * @param l : offset on low pulse width + * @param p : offset on low pulse positioning + */ + +bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){ + + uint32_t u; + for (u=0; u<8; u++) + { + if (byte&(1<>31); - if (DemodBuffer[idx] == 0) { - uid2=(uid2<<1)|0; - showbits[idx]='0'; - } else { - uid2=(uid2<<1)|1; - showbits[idx]='1'; - } - } - showbits[idx]='\0'; - PrintAndLog("Indala UID=%s (%x%08x)", showbits, uid1, uid2); - } - else { - uid3=0; - uid4=0; - uid5=0; - uid6=0; - uid7=0; - for( idx=0; idx>31); - uid2=(uid2<<1)|(uid3>>31); - uid3=(uid3<<1)|(uid4>>31); - uid4=(uid4<<1)|(uid5>>31); - uid5=(uid5<<1)|(uid6>>31); - uid6=(uid6<<1)|(uid7>>31); - if (DemodBuffer[idx] == 0) { - uid7=(uid7<<1)|0; - showbits[idx]='0'; - } - else { - uid7=(uid7<<1)|1; - showbits[idx]='1'; - } - } - showbits[idx]='\0'; - PrintAndLog("Indala UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7); + uid1=bytebits_to_byte(DemodBuffer,32); + uid2=bytebits_to_byte(DemodBuffer+32,32); + if (DemodBufferLen==64) { + PrintAndLog("Indala UID=%s (%x%08x)", sprint_bin(DemodBuffer,DemodBufferLen), uid1, uid2); + } else { + uid3=bytebits_to_byte(DemodBuffer+64,32); + uid4=bytebits_to_byte(DemodBuffer+96,32); + uid5=bytebits_to_byte(DemodBuffer+128,32); + uid6=bytebits_to_byte(DemodBuffer+160,32); + uid7=bytebits_to_byte(DemodBuffer+192,32); + PrintAndLog("Indala UID=%s (%x%08x%08x%08x%08x%08x%08x)", + sprint_bin(DemodBuffer,DemodBufferLen), uid1, uid2, uid3, uid4, uid5, uid6, uid7); } if (g_debugMode){ PrintAndLog("DEBUG: printing demodbuffer:"); @@ -2353,6 +2343,7 @@ static command_t CommandTable[] = {"askedgedetect", CmdAskEdgeDetect, 1, "[threshold] Adjust Graph for manual ask demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"}, {"askem410xdemod", CmdAskEM410xDemod, 1, "[clock] [invert<0|1>] [maxErr] -- Demodulate an EM410x tag from GraphBuffer (args optional)"}, {"askgproxiidemod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II tag from GraphBuffer"}, + {"askvikingdemod", CmdVikingDemod, 1, "Demodulate a Viking 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"}, diff --git a/client/cmddata.h b/client/cmddata.h index fcc51a6b..c3303c54 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -17,6 +17,7 @@ int CmdData(const char *Cmd); void printDemodBuff(void); void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx); int CmdAskEM410xDemod(const char *Cmd); +int CmdVikingDemod(const char *Cmd); int CmdG_Prox_II_Demod(const char *Cmd); int Cmdaskrawdemod(const char *Cmd); int Cmdaskmandemod(const char *Cmd); diff --git a/client/cmdlf.c b/client/cmdlf.c index edf6c3a9..616d932a 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -33,17 +33,82 @@ static int CmdHelp(const char *Cmd); + + +int usage_lf_cmdread() +{ + PrintAndLog("Usage: lf cmdread d z o c [H] "); + PrintAndLog("Options: "); + PrintAndLog(" h This help"); + PrintAndLog(" L Low frequency (125 KHz)"); + PrintAndLog(" H High frequency (134 KHz)"); + PrintAndLog(" d delay OFF period"); + PrintAndLog(" z time period ZERO"); + PrintAndLog(" o time period ONE"); + PrintAndLog(" c Command bytes"); + PrintAndLog(" ************* All periods in microseconds"); + PrintAndLog("Examples:"); + PrintAndLog(" lf cmdread d 80 z 100 o 200 c 11000"); + PrintAndLog(" lf cmdread d 80 z 100 o 100 c 11000 H"); + return 0; +} + /* send a command before reading */ int CmdLFCommandRead(const char *Cmd) { - static char dummy[3]; - - dummy[0]= ' '; - + static char dummy[3] = {0x20,0x00,0x00}; UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K}; - sscanf(Cmd, "%"lli" %"lli" %"lli" %s %s", &c.arg[0], &c.arg[1], &c.arg[2],(char*)(&c.d.asBytes),(char*)(&dummy+1)); - // in case they specified 'h' + bool errors = FALSE; + //uint8_t divisor = 95; //125khz + uint8_t cmdp = 0; + int strLength = 0; + while(param_getchar(Cmd, cmdp) != 0x00) + { + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + return usage_lf_cmdread(); + case 'H': + //divisor = 88; + dummy[1]='h'; + cmdp++; + break; + case 'L': + cmdp++; + break; + case 'c': + strLength = param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes); + cmdp+=2; + break; + case 'd': + c.arg[0] = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp+=2; + break; + case 'z': + c.arg[1] = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp+=2; + break; + case 'o': + c.arg[2] = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp+=2; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = 1; + break; + } + if(errors) break; + } + // No args + if(cmdp == 0) errors = 1; + + //Validations + if(errors) return usage_lf_cmdread(); + + // in case they specified 'H' strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy); + + clearCommandBuffer(); SendCommand(&c); return 0; } @@ -493,7 +558,12 @@ int CmdLFRead(const char *Cmd) //And ship it to device UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {arg1,0,0}}; SendCommand(&c); - WaitForResponse(CMD_ACK,NULL); + //WaitForResponse(CMD_ACK,NULL); + if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) { + PrintAndLog("command execution time out"); + return 1; + } + return 0; } @@ -1085,6 +1155,12 @@ int CmdLFfind(const char *Cmd) return 1; } + ans=CmdVikingDemod(""); + if (ans>0) { + PrintAndLog("\nValid Viking ID Found!"); + return 1; + } + ans=CmdPSKNexWatch(""); if (ans>0) { PrintAndLog("\nValid NexWatch ID Found!"); @@ -1126,13 +1202,17 @@ int CmdLFfind(const char *Cmd) static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"cmdread", CmdLFCommandRead, 0, " <'0' period> <'1' period> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"}, + {"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"}, {"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"}, + {"hid", CmdLFHID, 1, "{ HID RFIDs... }"}, + {"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"}, + {"io", CmdLFIO, 1, "{ ioProx tags... }"}, + {"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"}, + {"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"}, + {"ti", CmdLFTI, 1, "{ TI RFIDs... }"}, + {"cmdread", CmdLFCommandRead, 0, " ['H'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'H' for 134)"}, {"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"}, {"read", CmdLFRead, 0, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"}, @@ -1143,11 +1223,7 @@ static command_t CommandTable[] = {"simpsk", CmdLFpskSim, 0, "[1|2|3] [c ] [i] [r ] [d ] -- Simulate LF PSK tag from demodbuffer or input"}, {"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, {"snoop", CmdLFSnoop, 0, "['l'|'h'|] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"}, - {"ti", CmdLFTI, 1, "{ TI RFIDs... }"}, - {"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"}, {"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"}, - {"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"}, - {"pcf7931", CmdLFPCF7931, 1, "{PCF7931 RFIDs...}"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index eddeec56..7ff8037b 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -73,22 +73,23 @@ int CmdEM410xSim(const char *Cmd) uint8_t uid[5] = {0x00}; if (cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: lf em4x 410xsim "); + PrintAndLog("Usage: lf em4x em410xsim "); PrintAndLog(""); - PrintAndLog(" sample: lf em4x 410xsim 0F0368568B"); + PrintAndLog(" sample: lf em4x em410xsim 0F0368568B"); return 0; } + /* clock is 64 in EM410x tags */ + uint8_t clock = 64; if (param_gethex(Cmd, 0, uid, 10)) { PrintAndLog("UID must include 10 HEX symbols"); return 0; } - - PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X", uid[0],uid[1],uid[2],uid[3],uid[4]); + param_getdec(Cmd,1, &clock); + + PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X clock: %d", uid[0],uid[1],uid[2],uid[3],uid[4],clock); PrintAndLog("Press pm3-button to about simulation"); - /* clock is 64 in EM410x tags */ - int clock = 64; /* clear our graph */ ClearGraph(0); @@ -197,21 +198,13 @@ int CmdEM410xWrite(const char *Cmd) } // Check Clock - if (card == 1) - { - // Default: 64 - if (clock == 0) - clock = 64; - - // Allowed clock rates: 16, 32 and 64 - if ((clock != 16) && (clock != 32) && (clock != 64)) { - PrintAndLog("Error! Clock rate %d not valid. Supported clock rates are 16, 32 and 64.\n", clock); - return 0; - } - } - else if (clock != 0) - { - PrintAndLog("Error! Clock rate is only supported on T55x7 tags.\n"); + // Default: 64 + if (clock == 0) + clock = 64; + + // Allowed clock rates: 16, 32, 40 and 64 + if ((clock != 16) && (clock != 32) && (clock != 64) && (clock != 40)) { + PrintAndLog("Error! Clock rate %d not valid. Supported clock rates are 16, 32, 40 and 64.\n", clock); return 0; } @@ -221,11 +214,11 @@ int CmdEM410xWrite(const char *Cmd) // provide for backwards-compatibility for older firmware, and to avoid // having to add another argument to CMD_EM410X_WRITE_TAG, we just store // the clock rate in bits 8-15 of the card value - card = (card & 0xFF) | (((uint64_t)clock << 8) & 0xFF00); - } - else if (card == 0) + card = (card & 0xFF) | ((clock << 8) & 0xFF00); + } else if (card == 0) { PrintAndLog("Writing %s tag with UID 0x%010" PRIx64, "T5555", id, clock); - else { + card = (card & 0xFF) | ((clock << 8) & 0xFF00); + } else { PrintAndLog("Error! Bad card type selected.\n"); return 0; } @@ -608,7 +601,7 @@ static command_t CommandTable[] = {"help", CmdHelp, 1, "This help"}, {"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"}, {"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"}, - {"em410xsim", CmdEM410xSim, 0, " -- Simulate EM410x tag"}, + {"em410xsim", CmdEM410xSim, 0, " [clock rate] -- Simulate EM410x tag"}, {"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, {"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, {"em410xwrite", CmdEM410xWrite, 0, " <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"}, diff --git a/client/cmdlfpcf7931.c b/client/cmdlfpcf7931.c index b1e1ae9e..ffaf946f 100644 --- a/client/cmdlfpcf7931.c +++ b/client/cmdlfpcf7931.c @@ -8,11 +8,11 @@ //----------------------------------------------------------------------------- // Low frequency PCF7931 commands //----------------------------------------------------------------------------- - #include #include #include "proxmark3.h" #include "ui.h" +#include "util.h" #include "graph.h" #include "cmdparser.h" #include "cmddata.h" @@ -22,115 +22,158 @@ static int CmdHelp(const char *Cmd); -struct pcf7931_config configPcf = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},17500,{0,0}}; +#define PCF7931_DEFAULT_INITDELAY 17500 +#define PCF7931_DEFAULT_OFFSET_WIDTH 0 +#define PCF7931_DEFAULT_OFFSET_POSITION 0 + +// Default values - Configuration +struct pcf7931_config configPcf = { + {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, + PCF7931_DEFAULT_INITDELAY, + PCF7931_DEFAULT_OFFSET_WIDTH, + PCF7931_DEFAULT_OFFSET_POSITION + }; + +// Resets the configuration settings to default values. +int pcf7931_resetConfig(){ + memset(configPcf.Pwd, 0xFF, sizeof(configPcf.Pwd) ); + configPcf.InitDelay = PCF7931_DEFAULT_INITDELAY; + configPcf.OffsetWidth = PCF7931_DEFAULT_OFFSET_WIDTH; + configPcf.OffsetPosition = PCF7931_DEFAULT_OFFSET_POSITION; + return 0; +} -int CmdLFPCF7931Read(const char *Cmd) -{ - UsbCommand c = {CMD_PCF7931_READ}; - SendCommand(&c); - UsbCommand resp; - WaitForResponse(CMD_ACK,&resp); - return 0; +int pcf7931_printConfig(){ + PrintAndLog("Password (LSB first on bytes) : %s", sprint_hex( configPcf.Pwd, sizeof(configPcf.Pwd))); + PrintAndLog("Tag initialization delay : %d us", configPcf.InitDelay); + PrintAndLog("Offset low pulses width : %d us", configPcf.OffsetWidth); + PrintAndLog("Offset low pulses position : %d us", configPcf.OffsetPosition); + return 0; +} + +int usage_pcf7931_read(){ + PrintAndLog("Usage: lf pcf7931 read [h] "); + PrintAndLog("This command tries to read a PCF7931 tag."); + PrintAndLog("Options:"); + PrintAndLog(" h This help"); + PrintAndLog("Examples:"); + PrintAndLog(" lf pcf7931 read"); + return 0; +} + +int usage_pcf7931_write(){ + PrintAndLog("Usage: lf pcf7931 write [h] "); + PrintAndLog("This command tries to write a PCF7931 tag."); + PrintAndLog("Options:"); + PrintAndLog(" h This help"); + PrintAndLog(" blockaddress Block to save [0-7]"); + PrintAndLog(" byteaddress Index of byte inside block to write [0-15]"); + PrintAndLog(" data one byte of data (hex)"); + PrintAndLog("Examples:"); + PrintAndLog(" lf pcf7931 write 2 1 FF"); + return 0; } -int CmdLFPCF7931Config(const char *Cmd) -{ - int res = 0; - res = sscanf(Cmd, "%02x %02x %02x %02x %02x %02x %02x %d %d %d", &configPcf.password[0], &configPcf.password[1], &configPcf.password[2], &configPcf.password[3], &configPcf.password[4], &configPcf.password[5], &configPcf.password[6], &configPcf.init_delay, &configPcf.offset[0], &configPcf.offset[1]); - - if (res >= 7 || res < 1){ - if(res == 7) configPcf.init_delay = 17500; //default value - - if(res<=8){ - configPcf.offset[0] = 0; //default value - configPcf.offset[1] = 0; //default value - } - - if(res < 1){ - PrintAndLog("Usage: [...] "); - PrintAndLog("The time offsets could be usefull to correct slew rate generated by the antenna."); - } - - PrintAndLog("Current configuration :"); - PrintAndLog("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", configPcf.password[0], configPcf.password[1], configPcf.password[2], configPcf.password[3], configPcf.password[4], configPcf.password[5], configPcf.password[6]); - PrintAndLog("Tag initialization delay : %d us", configPcf.init_delay); - PrintAndLog("Offsets : %d us on the low pulses width, %d us on the low pulses positions", configPcf.offset[0], configPcf.offset[1]); - - return 0; - } - - //default values - configPcf.password[0] = 0xFF; - configPcf.password[1] = 0xFF; - configPcf.password[2] = 0xFF; - configPcf.password[3] = 0xFF; - configPcf.password[4] = 0xFF; - configPcf.password[5] = 0xFF; - configPcf.password[6] = 0xFF; - - configPcf.init_delay = 17500; - configPcf.offset[0] = 0; - configPcf.offset[1] = 0; - - PrintAndLog("Incorrect format"); - PrintAndLog("Examples of right usage : lf pcf7931 config 11 22 33 44 55 66 77 20000"); - PrintAndLog(" lf pcf7931 config FF FF FF FF FF FF FF 17500 -10 30"); - return 0; +int usage_pcf7931_config(){ + PrintAndLog("Usage: lf pcf7931 config [h] [r] "); + PrintAndLog("This command tries to set the configuration used with PCF7931 commands"); + PrintAndLog("The time offsets could be useful to correct slew rate generated by the antenna"); + PrintAndLog("Caling without some parameter will print the current configuration."); + PrintAndLog("Options:"); + PrintAndLog(" h This help"); + PrintAndLog(" r Reset configuration to default values"); + PrintAndLog(" pwd Password, hex, 7bytes, LSB-order"); + PrintAndLog(" delay Tag initialization delay (in us) decimal"); + PrintAndLog(" offset Low pulses width (in us) decimal"); + PrintAndLog(" offset Low pulses position (in us) decimal"); + PrintAndLog("Examples:"); + PrintAndLog(" lf pcf7931 config"); + PrintAndLog(" lf pcf7931 config r"); + PrintAndLog(" lf pcf7931 config 11223344556677 20000"); + PrintAndLog(" lf pcf7931 config 11223344556677 17500 -10 30"); + return 0; } +int CmdLFPCF7931Read(const char *Cmd){ + uint8_t ctmp = param_getchar(Cmd, 0); + if ( ctmp == 'H' || ctmp == 'h' ) return usage_pcf7931_read(); -int CmdLFPCF7931Write(const char *Cmd) -{ - UsbCommand c = {CMD_PCF7931_WRITE}; - - int res = 0; - res = sscanf(Cmd, "%x %x %x", &c.arg[0], &c.arg[1], &c.arg[2]); - - if(res < 1) { - PrintAndLog("Please specify the block address in hex"); - return 0; - } - if (res == 1){ - PrintAndLog("Please specify the byte address in hex"); - return 0; - } - if(res == 2) { - PrintAndLog("Please specify the data in hex (1 byte)"); - return 0; - } - if(res == 3) { - uint8_t n=0; - for(n=0;n<7;n++) c.d.asDwords[n] = configPcf.password[n]; - c.d.asDwords[7] = (configPcf.offset[0]+128); - c.d.asDwords[8] = (configPcf.offset[1]+128); - c.d.asDwords[9] = configPcf.init_delay; - SendCommand(&c); - return 0; - } - - PrintAndLog("INCORRECT FORMAT"); - return 0; + UsbCommand resp; + UsbCommand c = {CMD_PCF7931_READ, {0, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) { + PrintAndLog("command execution time out"); + return 1; + } + return 0; } +int CmdLFPCF7931Config(const char *Cmd){ + + uint8_t ctmp = param_getchar(Cmd, 0); + if ( ctmp == 0) return pcf7931_printConfig(); + if ( ctmp == 'H' || ctmp == 'h' ) return usage_pcf7931_config(); + if ( ctmp == 'R' || ctmp == 'r' ) return pcf7931_resetConfig(); + + if ( param_gethex(Cmd, 0, configPcf.Pwd, 14) ) return usage_pcf7931_config(); + + configPcf.InitDelay = (param_get32ex(Cmd,1,0,10) & 0xFFFF); + configPcf.OffsetWidth = (int)(param_get32ex(Cmd,2,0,10) & 0xFFFF); + configPcf.OffsetPosition = (int)(param_get32ex(Cmd,3,0,10) & 0xFFFF); + + pcf7931_printConfig(); + return 0; +} + +int CmdLFPCF7931Write(const char *Cmd){ + + uint8_t ctmp = param_getchar(Cmd, 0); + if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_pcf7931_write(); + + uint8_t block = 0, bytepos = 0, data = 0; + + if ( param_getdec(Cmd, 0, &block) ) return usage_pcf7931_write(); + if ( param_getdec(Cmd, 1, &bytepos) ) return usage_pcf7931_write(); + + if ( (block > 7) || (bytepos > 15) ) return usage_pcf7931_write(); + + data = param_get8ex(Cmd, 2, 0, 16); + + PrintAndLog("Writing block: %d", block); + PrintAndLog(" pos: %d", bytepos); + PrintAndLog(" data: 0x%02X", data); + + UsbCommand c = {CMD_PCF7931_WRITE, { block, bytepos, data} }; + memcpy(c.d.asDwords, configPcf.Pwd, sizeof(configPcf.Pwd) ); + c.d.asDwords[7] = (configPcf.OffsetWidth + 128); + c.d.asDwords[8] = (configPcf.OffsetPosition + 128); + c.d.asDwords[9] = configPcf.InitDelay; + + clearCommandBuffer(); + SendCommand(&c); + //no ack? + return 0; +} static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"read", CmdLFPCF7931Read, 1, "Read content of a PCF7931 transponder"}, - {"write", CmdLFPCF7931Write, 1, "Write data on a PCF7931 transponder. Usage : lf pcf7931 write "}, - {"config", CmdLFPCF7931Config, 1, "Configure the password, the tags initialization delay and time offsets (optional)"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"read", CmdLFPCF7931Read, 0, "Read content of a PCF7931 transponder"}, + {"write", CmdLFPCF7931Write, 0, "Write data on a PCF7931 transponder."}, + {"config", CmdLFPCF7931Config, 1, "Configure the password, the tags initialization delay and time offsets (optional)"}, + {NULL, NULL, 0, NULL} }; int CmdLFPCF7931(const char *Cmd) { - CmdsParse(CommandTable, Cmd); - return 0; + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } diff --git a/client/cmdlfpcf7931.h b/client/cmdlfpcf7931.h index 78eaff5d..e093039c 100644 --- a/client/cmdlfpcf7931.h +++ b/client/cmdlfpcf7931.h @@ -13,17 +13,23 @@ #define CMDLFPCF7931_H__ struct pcf7931_config{ - uint8_t password[7]; - uint16_t init_delay; - int16_t offset[2]; + uint8_t Pwd[7]; + uint16_t InitDelay; + int16_t OffsetWidth; + int16_t OffsetPosition; }; +int pcf7931_resetConfig(); +int pcf7931_printConfig(); + +int usage_pcf7931_read(); +int usage_pcf7931_write(); +int usage_pcf7931_config(); + int CmdLFPCF7931(const char *Cmd); int CmdLFPCF7931Read(const char *Cmd); - int CmdLFPCF7931Write(const char *Cmd); - int CmdLFPCF7931Config(const char *Cmd); #endif diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 88754724..55b4ab65 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -28,13 +28,21 @@ #define CONFIGURATION_BLOCK 0x00 #define TRACE_BLOCK 0x01 +#define REGULAR_READ_MODE_BLOCK 0xFF // Default configuration t55xx_conf_block_t config = { .modulation = DEMOD_ASK, .inverted = FALSE, .offset = 0x00, .block0 = 0x00}; +t55xx_conf_block_t Get_t55xx_Config(){ + return config; +} +void Set_t55xx_Config(t55xx_conf_block_t conf){ + config = conf; +} + int usage_t55xx_config(){ PrintAndLog("Usage: lf t55xx config [d ] [i 1] [o ]"); - PrintAndLog("Options: "); + PrintAndLog("Options:"); PrintAndLog(" h This help"); PrintAndLog(" b <8|16|32|40|50|64|100|128> Set bitrate"); PrintAndLog(" d Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A"); @@ -49,31 +57,41 @@ int usage_t55xx_config(){ return 0; } int usage_t55xx_read(){ - PrintAndLog("Usage: lf t55xx read "); - PrintAndLog(" , block number to read. Between 0-7"); - PrintAndLog(" , OPTIONAL password (8 hex characters)"); + PrintAndLog("Usage: lf t55xx read [b ] [p ] "); + PrintAndLog("Options:"); + PrintAndLog(" b - block number to read. Between 0-7"); + PrintAndLog(" p - OPTIONAL password (8 hex characters)"); + PrintAndLog(" o - OPTIONAL override safety check"); + PrintAndLog(" 1 - OPTIONAL read Page 1 instead of Page 0"); + PrintAndLog(" ****WARNING****"); + PrintAndLog(" Use of read with password on a tag not configured for a pwd"); + PrintAndLog(" can damage the tag"); PrintAndLog(""); PrintAndLog("Examples:"); - PrintAndLog(" lf t55xx read 0 - read data from block 0"); - PrintAndLog(" lf t55xx read 0 feedbeef - read data from block 0 password feedbeef"); + PrintAndLog(" lf t55xx read b 0 - read data from block 0"); + PrintAndLog(" lf t55xx read b 0 p feedbeef - read data from block 0 password feedbeef"); + PrintAndLog(" lf t55xx read b 0 p feedbeef o - read data from block 0 password feedbeef safety check"); PrintAndLog(""); return 0; } int usage_t55xx_write(){ - PrintAndLog("Usage: lf t55xx wr [password]"); - PrintAndLog(" , block number to write. Between 0-7"); - PrintAndLog(" , 4 bytes of data to write (8 hex characters)"); - PrintAndLog(" [password], OPTIONAL password 4bytes (8 hex characters)"); + PrintAndLog("Usage: lf t55xx wr [b ] [d ] [p ] [1]"); + PrintAndLog("Options:"); + PrintAndLog(" b - block number to write. Between 0-7"); + PrintAndLog(" d - 4 bytes of data to write (8 hex characters)"); + PrintAndLog(" p - OPTIONAL password 4bytes (8 hex characters)"); + PrintAndLog(" 1 - OPTIONAL write Page 1 instead of Page 0"); PrintAndLog(""); PrintAndLog("Examples:"); - PrintAndLog(" lf t55xx wr 3 11223344 - write 11223344 to block 3"); - PrintAndLog(" lf t55xx wr 3 11223344 feedbeef - write 11223344 to block 3 password feedbeef"); + PrintAndLog(" lf t55xx wr b 3 d 11223344 - write 11223344 to block 3"); + PrintAndLog(" lf t55xx wr b 3 d 11223344 p feedbeef - write 11223344 to block 3 password feedbeef"); PrintAndLog(""); return 0; } int usage_t55xx_trace() { PrintAndLog("Usage: lf t55xx trace [1]"); - PrintAndLog(" [graph buffer data], if set, use Graphbuffer otherwise read data from tag."); + PrintAndLog("Options:"); + PrintAndLog(" [graph buffer data] - if set, use Graphbuffer otherwise read data from tag."); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx trace"); @@ -83,7 +101,8 @@ int usage_t55xx_trace() { } int usage_t55xx_info() { PrintAndLog("Usage: lf t55xx info [1]"); - PrintAndLog(" [graph buffer data], if set, use Graphbuffer otherwise read data from tag."); + PrintAndLog("Options:"); + PrintAndLog(" [graph buffer data] - if set, use Graphbuffer otherwise read data from tag."); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx info"); @@ -92,17 +111,21 @@ int usage_t55xx_info() { return 0; } int usage_t55xx_dump(){ - PrintAndLog("Usage: lf t55xx dump "); - PrintAndLog(" , OPTIONAL password 4bytes (8 hex symbols)"); + PrintAndLog("Usage: lf t55xx dump [o]"); + PrintAndLog("Options:"); + PrintAndLog(" - OPTIONAL password 4bytes (8 hex symbols)"); + PrintAndLog(" o - OPTIONAL override, force pwd read despite danger to card"); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx dump"); - PrintAndLog(" lf t55xx dump feedbeef"); + PrintAndLog(" lf t55xx dump feedbeef o"); PrintAndLog(""); return 0; } int usage_t55xx_detect(){ - PrintAndLog("Usage: lf t55xx detect"); + PrintAndLog("Usage: lf t55xx detect [1]"); + PrintAndLog("Options:"); + PrintAndLog(" [graph buffer data] - if set, use Graphbuffer otherwise read data from tag."); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx detect"); @@ -110,18 +133,29 @@ int usage_t55xx_detect(){ PrintAndLog(""); return 0; } +int usage_t55xx_wakup(){ + PrintAndLog("Usage: lf t55xx wakeup [h] p "); + PrintAndLog("This commands send the Answer-On-Request command and leaves the readerfield ON afterwards."); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" p - password 4bytes (8 hex symbols)"); + PrintAndLog(""); + PrintAndLog("Examples:"); + PrintAndLog(" lf t55xx wakeup p 11223344 - send wakeup password"); + return 0; +} static int CmdHelp(const char *Cmd); int CmdT55xxSetConfig(const char *Cmd) { uint8_t offset = 0; - bool errors = FALSE; - uint8_t cmdp = 0; char modulation[5] = {0x00}; char tmp = 0x00; uint8_t bitRate = 0; uint8_t rates[9] = {8,16,32,40,50,64,100,128,0}; + uint8_t cmdp = 0; + bool errors = FALSE; while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { tmp = param_getchar(Cmd, cmdp); @@ -201,64 +235,91 @@ int CmdT55xxSetConfig(const char *Cmd) { } // No args - if (cmdp == 0) { - printConfiguration( config ); - return 0; - } + if (cmdp == 0) return printConfiguration( config ); + //Validations - if (errors) - return usage_t55xx_config(); + if (errors) return usage_t55xx_config(); - config.block0 = 0; - printConfiguration ( config ); - return 0; + config.block0 = 0; + return printConfiguration ( config ); } -int CmdT55xxReadBlock(const char *Cmd) { - int block = -1; - int password = 0xFFFFFFFF; //default to blank Block 7 - - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') - return usage_t55xx_read(); - - int res = sscanf(Cmd, "%d %x", &block, &password); +int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32_t password){ + //Password mode + if ( usepwd ) { + // try reading the config block and verify that PWD bit is set before doing this! + if ( !override ) { + if ( !AquireData(0, CONFIGURATION_BLOCK, false, 0 ) ) return 0; + if ( !tryDetectModulation() ) { + PrintAndLog("Safety Check: Could not detect if PWD bit is set in config block. Exits."); + return 0; + } else { + PrintAndLog("Safety Check: PWD bit is NOT set in config block. Reading without password..."); + usepwd = false; + page1 = false; + } + } else { + PrintAndLog("Safety Check Overriden - proceeding despite risk"); + } + } - if ( res < 1 || res > 2 ) - return usage_t55xx_read(); + if (!AquireData(page1, block, usepwd, password) ) return 0; + if (!DecodeT55xxBlock()) return 0; - - if ((block < 0) | (block > 7)) { - PrintAndLog("Block must be between 0 and 7"); - return 1; - } - - UsbCommand c = {CMD_T55XX_READ_BLOCK, {0, block, 0}}; - c.d.asBytes[0] = 0x0; + char blk[10]={0}; + sprintf(blk,"%d", block); + printT55xxBlock(blk); + return 1; +} - //Password mode - if ( res == 2 ) { - c.arg[2] = password; - c.d.asBytes[0] = 0x1; +int CmdT55xxReadBlock(const char *Cmd) { + uint8_t block = REGULAR_READ_MODE_BLOCK; + uint32_t password = 0; //default to blank Block 7 + bool usepwd = false; + bool override = false; + bool page1 = false; + bool errors = false; + uint8_t cmdp = 0; + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_t55xx_read(); + case 'b': + case 'B': + errors |= param_getdec(Cmd, cmdp+1, &block); + cmdp += 2; + break; + case 'o': + case 'O': + override = true; + cmdp++; + break; + case 'p': + case 'P': + password = param_get32ex(Cmd, cmdp+1, 0, 16); + usepwd = true; + cmdp += 2; + break; + case '1': + page1 = true; + cmdp++; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } } + if (errors) return usage_t55xx_read(); - clearCommandBuffer(); - SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) { - PrintAndLog("command execution time out"); - return 2; + if (block > 7 && block != REGULAR_READ_MODE_BLOCK ) { + PrintAndLog("Block must be between 0 and 7"); + return 0; } - - uint8_t got[12000]; - GetFromBigBuf(got,sizeof(got),0); - WaitForResponse(CMD_ACK,NULL); - setGraphBuf(got, 12000); - DemodBufferLen=0; - if (!DecodeT55xxBlock()) return 3; - char blk[10]={0}; - sprintf(blk,"%d", block); - printT55xxBlock(blk); - return 0; + PrintAndLog("Reading Page %d:", page1); + PrintAndLog("blk | hex data | binary"); + return T55xxReadBlock(block, page1, usepwd, override, password); } bool DecodeT55xxBlock(){ @@ -269,9 +330,6 @@ bool DecodeT55xxBlock(){ uint8_t bitRate[8] = {8,16,32,40,50,64,100,128}; DemodBufferLen = 0x00; - //trim 1/2 a clock from beginning - snprintf(cmdStr, sizeof(buf),"%d", bitRate[config.bitrate]/2 ); - CmdLtrim(cmdStr); switch( config.modulation ){ case DEMOD_FSK: snprintf(cmdStr, sizeof(buf),"%d %d", bitRate[config.bitrate], config.inverted ); @@ -323,17 +381,17 @@ int CmdT55xxDetect(const char *Cmd){ return usage_t55xx_detect(); if (strlen(Cmd)==0) - AquireData( CONFIGURATION_BLOCK ); + if ( !AquireData(0, CONFIGURATION_BLOCK, false, 0) ) + return 0; if ( !tryDetectModulation() ) PrintAndLog("Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'"); - return 0; + return 1; } // detect configuration? bool tryDetectModulation(){ - char cmdStr[8] = {0}; uint8_t hits = 0; t55xx_conf_block_t tests[15]; int bitRate=0; @@ -341,8 +399,6 @@ bool tryDetectModulation(){ save_restoreGB(1); if (GetFskClock("", FALSE, FALSE)){ fskClocks(&fc1, &fc2, &clk, FALSE); - sprintf(cmdStr,"%d", clk/2); - CmdLtrim(cmdStr); if ( FSKrawDemod("0 0", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate)){ tests[hits].modulation = DEMOD_FSK; if (fc1==8 && fc2 == 5) @@ -369,8 +425,6 @@ bool tryDetectModulation(){ } else { clk = GetAskClock("", FALSE, FALSE); if (clk>0) { - sprintf(cmdStr,"%d", clk/2); - CmdLtrim(cmdStr); if ( ASKDemod("0 0 0", FALSE, FALSE, 1) && test(DEMOD_ASK, &tests[hits].offset, &bitRate)) { tests[hits].modulation = DEMOD_ASK; tests[hits].bitrate = bitRate; @@ -404,8 +458,6 @@ bool tryDetectModulation(){ save_restoreGB(0); clk = GetNrzClock("", FALSE, FALSE); if (clk>0) { - sprintf(cmdStr,"%d", clk/2); - CmdLtrim(cmdStr); if ( NRZrawDemod("0 0 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate)) { tests[hits].modulation = DEMOD_NRZ; tests[hits].bitrate = bitRate; @@ -427,9 +479,6 @@ bool tryDetectModulation(){ save_restoreGB(0); clk = GetPskClock("", FALSE, FALSE); if (clk>0) { - PrintAndLog("clk %d",clk); - sprintf(cmdStr,"%d", clk/2); - CmdLtrim(cmdStr); if ( PSKDemod("0 0 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate)) { tests[hits].modulation = DEMOD_PSK1; tests[hits].bitrate = bitRate; @@ -491,7 +540,7 @@ bool tryDetectModulation(){ bool testModulation(uint8_t mode, uint8_t modread){ switch( mode ){ case DEMOD_FSK: - if (modread > 3 && modread < 8) return TRUE; + if (modread >= DEMOD_FSK1 && modread <= DEMOD_FSK2a) return TRUE; break; case DEMOD_ASK: if (modread == DEMOD_ASK) return TRUE; @@ -615,14 +664,14 @@ void printT55xxBlock(const char *blockNum){ bits[i - config.offset]=DemodBuffer[i]; blockData = PackBits(0, 32, bits); - PrintAndLog("[%s] 0x%08X %s", blockNum, blockData, sprint_bin(bits,32)); + PrintAndLog(" %s | %08X | %s", blockNum, blockData, sprint_bin(bits,32)); } int special(const char *Cmd) { uint32_t blockData = 0; uint8_t bits[32] = {0x00}; - PrintAndLog("[OFFSET] [DATA] [BINARY]"); + PrintAndLog("OFFSET | DATA | BINARY"); PrintAndLog("----------------------------------------------------"); int i,j = 0; for (; j < 64; ++j){ @@ -632,86 +681,142 @@ int special(const char *Cmd) { blockData = PackBits(0, 32, bits); - PrintAndLog("[%02d] 0x%08X %s",j , blockData, sprint_bin(bits,32)); + PrintAndLog(" %02d | 0x%08X | %s",j , blockData, sprint_bin(bits,32)); } return 0; } -void printConfiguration( t55xx_conf_block_t b){ +int printConfiguration( t55xx_conf_block_t b){ PrintAndLog("Modulation : %s", GetSelectedModulationStr(b.modulation) ); PrintAndLog("Bit Rate : %s", GetBitRateStr(b.bitrate) ); PrintAndLog("Inverted : %s", (b.inverted) ? "Yes" : "No" ); PrintAndLog("Offset : %d", b.offset); PrintAndLog("Block0 : 0x%08X", b.block0); PrintAndLog(""); + return 0; } -int CmdT55xxWriteBlock(const char *Cmd) -{ - int block = 8; //default to invalid block - int data = 0xFFFFFFFF; //default to blank Block - int password = 0xFFFFFFFF; //default to blank Block 7 - - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') { - usage_t55xx_write(); - return 0; +int CmdT55xxWakeUp(const char *Cmd) { + uint32_t password = 0; + uint8_t cmdp = 0; + bool errors = true; + while(param_getchar(Cmd, cmdp) != 0x00) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_t55xx_wakup(); + case 'p': + case 'P': + password = param_get32ex(Cmd, cmdp+1, 0xFFFFFFFF, 16); + cmdp += 2; + errors = false; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } } - - int res = sscanf(Cmd, "%d %x %x",&block, &data, &password); - - if ( res < 2 || res > 3) { - usage_t55xx_write(); - return 1; + if (errors) return usage_t55xx_wakup(); + + UsbCommand c = {CMD_T55XX_WAKEUP, {password, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + PrintAndLog("Wake up command sent. Try read now"); + return 0; +} + +int CmdT55xxWriteBlock(const char *Cmd) { + uint8_t block = 0xFF; //default to invalid block + uint32_t data = 0xFFFFFFFF; //default to blank Block + uint32_t password = 0xFFFFFFFF; //default to blank Block 7 + bool usepwd = false; + bool page1 = false; + bool gotdata = false; + bool errors = false; + uint8_t cmdp = 0; + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_t55xx_write(); + case 'b': + case 'B': + errors |= param_getdec(Cmd, cmdp+1, &block); + cmdp += 2; + break; + case 'd': + case 'D': + data = param_get32ex(Cmd, cmdp+1, 0, 16); + gotdata = true; + cmdp += 2; + break; + case 'p': + case 'P': + password = param_get32ex(Cmd, cmdp+1, 0, 16); + usepwd = true; + cmdp += 2; + break; + case '1': + page1 = true; + cmdp++; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } } + if (errors || !gotdata) return usage_t55xx_write(); if (block > 7) { PrintAndLog("Block number must be between 0 and 7"); - return 1; + return 0; } UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {data, block, 0}}; UsbCommand resp; - c.d.asBytes[0] = 0x0; + c.d.asBytes[0] = (page1) ? 0x2 : 0; - PrintAndLog("Writing to block: %d data : 0x%08X", block, data); + PrintAndLog("Writing to page: %d block: %d data : 0x%08X", page1, block, data); //Password mode - if (res == 3) { + if (usepwd) { c.arg[2] = password; - c.d.asBytes[0] = 0x1; + 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; } - return 0; + return 1; } -int CmdT55xxReadTrace(const char *Cmd) -{ +int CmdT55xxReadTrace(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); - + bool pwdmode = false; + uint32_t password = 0; if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') return usage_t55xx_trace(); if (strlen(Cmd)==0) - AquireData( TRACE_BLOCK ); + if ( !AquireData( TRACE_BLOCK, REGULAR_READ_MODE_BLOCK, pwdmode, password ) ) + return 0; - if (!DecodeT55xxBlock()) return 1; + if (!DecodeT55xxBlock()) return 0; + + if ( !DemodBufferLen) return 0; - if ( !DemodBufferLen) return 1; - RepaintGraphWindow(); uint8_t repeat = 0; if (config.offset > 5) repeat = 32; uint8_t si = config.offset+repeat; - uint32_t bl0 = PackBits(si, 32, DemodBuffer); - uint32_t bl1 = PackBits(si+32, 32, DemodBuffer); + uint32_t bl1 = PackBits(si, 32, DemodBuffer); + uint32_t bl2 = PackBits(si+32, 32, DemodBuffer); uint32_t acl = PackBits(si, 8, DemodBuffer); si += 8; uint32_t mfc = PackBits(si, 8, DemodBuffer); si += 8; @@ -732,7 +837,7 @@ int CmdT55xxReadTrace(const char *Cmd) if ( acl != 0xE0 ) { PrintAndLog("The modulation is most likely wrong since the ACL is not 0xE0. "); - return 1; + return 0; } PrintAndLog(""); @@ -749,8 +854,8 @@ int CmdT55xxReadTrace(const char *Cmd) PrintAndLog(" Die Number : %d", dw); PrintAndLog("-------------------------------------------------------------"); PrintAndLog(" Raw Data - Page 1"); - PrintAndLog(" Block 0 : 0x%08X %s", bl0, sprint_bin(DemodBuffer+config.offset+repeat,32) ); - PrintAndLog(" Block 1 : 0x%08X %s", bl1, sprint_bin(DemodBuffer+config.offset+repeat+32,32) ); + PrintAndLog(" Block 1 : 0x%08X %s", bl1, sprint_bin(DemodBuffer+config.offset+repeat,32) ); + PrintAndLog(" Block 2 : 0x%08X %s", bl2, sprint_bin(DemodBuffer+config.offset+repeat+32,32) ); PrintAndLog("-------------------------------------------------------------"); /* @@ -779,13 +884,16 @@ int CmdT55xxInfo(const char *Cmd){ Normal mode Extended mode */ + bool pwdmode = false; + uint32_t password = 0; char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') return usage_t55xx_info(); if (strlen(Cmd)==0) - AquireData( CONFIGURATION_BLOCK ); + if ( !AquireData( 0, CONFIGURATION_BLOCK, pwdmode, password ) ) + return 1; if (!DecodeT55xxBlock()) return 1; @@ -836,67 +944,59 @@ int CmdT55xxInfo(const char *Cmd){ int CmdT55xxDump(const char *Cmd){ - char s[20] = {0x00}; - uint8_t pwd[4] = {0x00}; - + uint32_t password = 0; char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'h' || cmdp == 'H') { - usage_t55xx_dump(); - return 0; - } - - bool hasPwd = ( strlen(Cmd) > 0); - if ( hasPwd ){ - if (param_gethex(Cmd, 0, pwd, 8)) { - PrintAndLog("password must include 8 HEX symbols"); - return 1; - } + bool override = false; + if ( cmdp == 'h' || cmdp == 'H') return usage_t55xx_dump(); + + bool usepwd = ( strlen(Cmd) > 0); + if ( usepwd ){ + password = param_get32ex(Cmd, 0, 0, 16); + if (param_getchar(Cmd, 1) =='o' ) + override = true; } - for ( int i = 0; i <8; ++i){ - memset(s,0,sizeof(s)); + PrintAndLog("Reading Page 0:"); + PrintAndLog("blk | hex data | binary"); + for ( uint8_t i = 0; i <8; ++i){ + T55xxReadBlock(i, 0, usepwd, override, password); + /*memset(s,0,sizeof(s)); if ( hasPwd ) { - sprintf(s,"%d %02x%02x%02x%02x", i, pwd[0],pwd[1],pwd[2],pwd[3]); + if ( override ) { + sprintf(s,"b %d p %02x%02x%02x%02x o", i, pwd[0],pwd[1],pwd[2],pwd[3]); + } else { + sprintf(s,"b %d p %02x%02x%02x%02x", i, pwd[0],pwd[1],pwd[2],pwd[3]); + } } else { - sprintf(s,"%d", i); + sprintf(s,"b %d", i); } - CmdT55xxReadBlock(s); + CmdT55xxReadBlock(s);*/ } - return 0; + PrintAndLog("Reading Page 1:"); + PrintAndLog("blk | hex data | binary"); + for ( uint8_t i = 0; i<4; i++){ + T55xxReadBlock(i, 1, usepwd, override, password); + } + return 1; } -int AquireData( uint8_t block ){ - - UsbCommand c; - - if ( block == CONFIGURATION_BLOCK ) - c.cmd = CMD_T55XX_READ_BLOCK; - else if (block == TRACE_BLOCK ) - c.cmd = CMD_T55XX_READ_TRACE; - - c.arg[0] = 0x00; - c.arg[1] = 0x00; - c.arg[2] = 0x00; - c.d.asBytes[0] = 0x0; +int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ){ - //Password mode - // if ( res == 2 ) { - // c.arg[2] = password; - // c.d.asBytes[0] = 0x1; - // } + uint8_t arg0 = (page<<1) | pwdmode; + UsbCommand c = {CMD_T55XX_READ_BLOCK, {arg0, block, password}}; clearCommandBuffer(); SendCommand(&c); if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) { PrintAndLog("command execution time out"); - return 1; + return 0; } uint8_t got[12000]; GetFromBigBuf(got,sizeof(got),0); WaitForResponse(CMD_ACK,NULL); - setGraphBuf(got, 12000); - return 0; + setGraphBuf(got, sizeof(got)); + return 1; } char * GetBitRateStr(uint32_t id){ @@ -1072,17 +1172,36 @@ uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bits){ return tmp; } +int CmdResetRead(const char *Cmd) { + UsbCommand c = {CMD_T55XX_RESET_READ, {0,0,0}}; + + clearCommandBuffer(); + SendCommand(&c); + if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) { + PrintAndLog("command execution time out"); + return 0; + } + + uint8_t got[BIGBUF_SIZE-1]; + GetFromBigBuf(got,sizeof(got),0); + WaitForResponse(CMD_ACK,NULL); + setGraphBuf(got, sizeof(got)); + return 1; +} + static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, - {"detect", CmdT55xxDetect, 0, "[1] Try detecting the tag modulation from reading the configuration block."}, - {"read", CmdT55xxReadBlock, 0, " [password] -- Read T55xx block data (page 0) [optional password]"}, - {"write", CmdT55xxWriteBlock,0, " [password] -- Write T55xx block data (page 0) [optional password]"}, - {"trace", CmdT55xxReadTrace, 0, "[1] Show T55xx traceability data (page 1/ blk 0-1)"}, - {"info", CmdT55xxInfo, 0, "[1] Show T55xx configuration data (page 0/ blk 0)"}, - {"dump", CmdT55xxDump, 0, "[password] Dump T55xx card block 0-7. [optional password]"}, - {"special", special, 0, "Show block changes with 64 different offsets"}, + {"help", CmdHelp, 1, "This help"}, + {"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, + {"detect", CmdT55xxDetect, 0, "[1] Try detecting the tag modulation from reading the configuration block."}, + {"read", CmdT55xxReadBlock, 0, "b p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]"}, + {"resetread",CmdResetRead, 0, "Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)"}, + {"write", CmdT55xxWriteBlock,0, "b d p [password] [1] -- Write T55xx block data. Optional [p password], [page1]"}, + {"trace", CmdT55xxReadTrace, 0, "[1] Show T55xx traceability data (page 1/ blk 0-1)"}, + {"info", CmdT55xxInfo, 0, "[1] Show T55xx configuration data (page 0/ blk 0)"}, + {"dump", CmdT55xxDump, 0, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"}, + {"special", special, 0, "Show block changes with 64 different offsets"}, + {"wakeup", CmdT55xxWakeUp, 0, "Send AOR wakeup command"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index 364f0271..d5134079 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -39,6 +39,9 @@ typedef struct { RF_128 = 0x07, } bitrate; } t55xx_conf_block_t; +t55xx_conf_block_t Get_t55xx_Config(); +void Set_t55xx_Config(t55xx_conf_block_t conf); + int CmdLFT55XX(const char *Cmd); int CmdT55xxSetConfig(const char *Cmd); @@ -47,6 +50,7 @@ int CmdT55xxWriteBlock(const char *Cmd); int CmdT55xxReadTrace(const char *Cmd); int CmdT55xxInfo(const char *Cmd); int CmdT55xxDetect(const char *Cmd); +int CmdResetRead(const char *Cmd); char * GetBitRateStr(uint32_t id); char * GetSaferStr(uint32_t id); @@ -55,12 +59,12 @@ char * GetModelStrFromCID(uint32_t cid); char * GetSelectedModulationStr( uint8_t id); uint32_t PackBits(uint8_t start, uint8_t len, uint8_t *bitstream); void printT55xxBlock(const char *demodStr); -void printConfiguration( t55xx_conf_block_t b); +int printConfiguration( t55xx_conf_block_t b); bool DecodeT55xxBlock(); bool tryDetectModulation(); bool test(uint8_t mode, uint8_t *offset, int *fndBitRate); int special(const char *Cmd); -int AquireData( uint8_t block ); +int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ); #endif diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h index 2f521f62..c8b576fd 100644 --- a/client/hid-flasher/usb_cmd.h +++ b/client/hid-flasher/usb_cmd.h @@ -73,7 +73,7 @@ typedef struct { #define CMD_INDALA_CLONE_TAG_L 0x0213 #define CMD_T55XX_READ_BLOCK 0x0214 #define CMD_T55XX_WRITE_BLOCK 0x0215 -#define CMD_T55XX_READ_TRACE 0x0216 +#define CMD_T55XX_RESET_READ 0x0216 #define CMD_PCF7931_READ 0x0217 #define CMD_EM4X_READ_WORD 0x0218 #define CMD_EM4X_WRITE_WORD 0x0219 @@ -85,6 +85,7 @@ typedef struct { #define CMD_ASK_SIM_TAG 0x021F #define CMD_PSK_SIM_TAG 0x0220 #define CMD_AWID_DEMOD_FSK 0x0221 +#define CMD_T55XX_WAKEUP 0x0224 /* 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 5f34976f..8cdcfb34 100644 --- a/client/lualibs/commands.lua +++ b/client/lualibs/commands.lua @@ -44,7 +44,7 @@ local _commands = { CMD_INDALA_CLONE_TAG_L = 0x0213, CMD_T55XX_READ_BLOCK = 0x0214, CMD_T55XX_WRITE_BLOCK = 0x0215, - CMD_T55XX_READ_TRACE = 0x0216, + CMD_T55XX_RESET_READ = 0x0216, CMD_PCF7931_READ = 0x0217, CMD_EM4X_READ_WORD = 0x0218, CMD_EM4X_WRITE_WORD = 0x0219, @@ -56,7 +56,7 @@ local _commands = { CMD_ASK_SIM_TAG = 0x021F, CMD_PSK_SIM_TAG = 0x0220, CMD_AWID_DEMOD_FSK = 0x0221, - + CMD_T55XX_WAKEUP = 0x0224, --/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ --// For the 13.56 MHz tags diff --git a/client/scripting.c b/client/scripting.c index 6b26ec59..a188ecf0 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -18,6 +18,7 @@ #include "util.h" #include "nonce2key/nonce2key.h" #include "../common/iso15693tools.h" +#include "iso14443crc.h" #include "../common/crc16.h" #include "../common/crc64.h" #include "../common/sha1.h" @@ -228,6 +229,27 @@ static int l_iso15693_crc(lua_State *L) return 1; } +static int l_iso14443b_crc(lua_State *L) +{ + /* void ComputeCrc14443(int CrcType, + const unsigned char *Data, int Length, + unsigned char *TransmitFirst, + unsigned char *TransmitSecond) + */ + unsigned char buf[USB_CMD_DATA_SIZE]; + size_t len = 0; + const char *data = luaL_checklstring(L, 1, &len); + if (USB_CMD_DATA_SIZE < len) + len = USB_CMD_DATA_SIZE-2; + + for (int i = 0; i < len; i += 2) { + sscanf(&data[i], "%02x", (unsigned int *)&buf[i / 2]); + } + ComputeCrc14443(CRC_14443_B, buf, len, &buf[len], &buf[len+1]); + + lua_pushlstring(L, (const char *)&buf, len+2); + return 1; +} /* Simple AES 128 cbc hook up to OpenSSL. params: key, input @@ -426,6 +448,7 @@ int set_pm3_libraries(lua_State *L) {"clearCommandBuffer", l_clearCommandBuffer}, {"console", l_CmdConsole}, {"iso15693_crc", l_iso15693_crc}, + {"iso14443b_crc", l_iso14443b_crc}, {"aes128_decrypt", l_aes128decrypt_cbc}, {"aes128_decrypt_ecb", l_aes128decrypt_ecb}, {"aes128_encrypt", l_aes128encrypt_cbc}, diff --git a/common/lfdemod.c b/common/lfdemod.c index a3a7a500..32feab6a 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -282,6 +282,16 @@ int manrawdecode(uint8_t * BitStream, size_t *size, uint8_t invert) return bestErr; } +uint32_t manchesterEncode2Bytes(uint16_t datain) { + uint32_t output = 0; + uint8_t curBit = 0; + for (uint8_t i=0; i<16; i++) { + curBit = (datain >> (15-i) & 1); + output |= (1<<(((15-i)*2)+curBit)); + } + return output; +} + //by marshmellow //encode binary data into binary manchester int ManchesterEncode(uint8_t *BitStream, size_t size) @@ -369,7 +379,9 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow if (fclow==0) fclow=8; //set the threshold close to 0 (graph) or 128 std to avoid static uint8_t threshold_value = 123; - + size_t preLastSample = 0; + size_t LastSample = 0; + size_t currSample = 0; // sync to first lo-hi transition, and threshold // Need to threshold first sample @@ -389,13 +401,22 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow // Check for 0->1 transition if (dest[idx-1] < dest[idx]) { // 0 -> 1 transition - if ((idx-last_transition)<(fclow-2)){ //0-5 = garbage noise + preLastSample = LastSample; + LastSample = currSample; + currSample = idx-last_transition; + if (currSample < (fclow-2)){ //0-5 = garbage noise //do nothing with extra garbage - } else if ((idx-last_transition) < (fchigh-1)) { //6-8 = 8 waves + } else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves + if (LastSample > (fchigh-2) && preLastSample < (fchigh-1)){ + dest[numBits-1]=1; //correct last 9 wave surrounded by 8 waves + } dest[numBits++]=1; - } else if ((idx-last_transition) > (fchigh+1) && !numBits) { //12 + and first bit = garbage + + } else if (currSample > (fchigh+1) && !numBits) { //12 + and first bit = garbage //do nothing with beginning garbage - } else { //9+ = 10 waves + } else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's + dest[numBits++]=1; + } else { //9+ = 10 sample waves dest[numBits++]=0; } last_transition = idx; @@ -576,6 +597,25 @@ int IOdemodFSK(uint8_t *dest, size_t size) return (int) startIdx; } return -5; +} + +// by marshmellow +// find viking preamble 0xF200 in already demoded data +int VikingDemod_AM(uint8_t *dest, size_t *size) { + //make sure buffer has data + if (*size < 64*2) return -2; + + size_t startIdx = 0; + uint8_t preamble[] = {1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx); + if (errChk == 0) return -4; //preamble not found + uint32_t checkCalc = bytebits_to_byte(dest+startIdx,8) ^ bytebits_to_byte(dest+startIdx+8,8) ^ bytebits_to_byte(dest+startIdx+16,8) + ^ bytebits_to_byte(dest+startIdx+24,8) ^ bytebits_to_byte(dest+startIdx+32,8) ^ bytebits_to_byte(dest+startIdx+40,8) + ^ bytebits_to_byte(dest+startIdx+48,8) ^ bytebits_to_byte(dest+startIdx+56,8); + if ( checkCalc != 0xA8 ) return -5; + if (*size != 64) return -6; + //return start position + return (int) startIdx; } // by marshmellow @@ -1033,63 +1073,20 @@ void psk2TOpsk1(uint8_t *BitStream, size_t size) int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert) { //26 bit 40134 format (don't know other formats) - int i; - int long_wait=29;//29 leading zeros in format - int start; - int first = 0; - int first2 = 0; - int bitCnt = 0; - int ii; - // Finding the start of a UID - for (start = 0; start <= *size - 250; start++) { - first = bitStream[start]; - for (i = start; i < start + long_wait; i++) { - if (bitStream[i] != first) { - break; - } - } - if (i == (start + long_wait)) { - break; - } - } - if (start == *size - 250 + 1) { - // did not find start sequence - return -1; - } - // Inverting signal if needed - if (first == 1) { - for (i = start; i < *size; i++) { - bitStream[i] = !bitStream[i]; - } - *invert = 1; - }else *invert=0; - - int iii; - //found start once now test length by finding next one - for (ii=start+29; ii <= *size - 250; ii++) { - first2 = bitStream[ii]; - for (iii = ii; iii < ii + long_wait; iii++) { - if (bitStream[iii] != first2) { - break; - } - } - if (iii == (ii + long_wait)) { - break; - } - } - if (ii== *size - 250 + 1){ - // did not find second start sequence - return -2; - } - bitCnt=ii-start; + uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; + uint8_t preamble_i[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0}; + size_t startidx = 0; + if (!preambleSearch(bitStream, preamble, sizeof(preamble), size, &startidx)){ + // if didn't find preamble try again inverting + if (!preambleSearch(bitStream, preamble_i, sizeof(preamble_i), size, &startidx)) return -1; + *invert ^= 1; + } + if (*size != 64 && *size != 224) return -2; + if (*invert==1) + for (size_t i = startidx; i < *size; i++) + bitStream[i] ^= 1; - // Dumping UID - i = start; - for (ii = 0; ii < bitCnt; ii++) { - bitStream[ii] = bitStream[i++]; - } - *size=bitCnt; - return 1; + return (int) startidx; } // by marshmellow - demodulate NRZ wave (both similar enough) diff --git a/common/lfdemod.h b/common/lfdemod.h index d16aab9e..cc4fa27a 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -27,9 +27,9 @@ uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t f int DetectNRZClock(uint8_t dest[], size_t size, int clock); int DetectPSKClock(uint8_t dest[], size_t size, int clock); int DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low); -uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo); int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow); int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo); +uint32_t manchesterEncode2Bytes(uint16_t datain); int ManchesterEncode(uint8_t *BitStream, size_t size); int manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert); int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int maxErr); @@ -41,13 +41,15 @@ void psk1TOpsk2(uint8_t *BitStream, size_t size); size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen); //tag specific -int FDXBdemodBI(uint8_t *dest, size_t *size); int AWIDdemodFSK(uint8_t *dest, size_t *size); +uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo); +int FDXBdemodBI(uint8_t *dest, size_t *size); int gProxII_Demod(uint8_t BitStream[], size_t *size); int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo); int IOdemodFSK(uint8_t *dest, size_t size); int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert); -int PyramiddemodFSK(uint8_t *dest, size_t *size); int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo); +int PyramiddemodFSK(uint8_t *dest, size_t *size); +int VikingDemod_AM(uint8_t *dest, size_t *size); #endif diff --git a/common/protocols.c b/common/protocols.c index 0a523da3..0d95cf08 100644 --- a/common/protocols.c +++ b/common/protocols.c @@ -3,13 +3,36 @@ #include #include #include "protocols.h" + +// ATA55xx shared presets & routines +uint32_t GetT55xxClockBit(uint32_t clock) { + switch (clock) { + case 128: + return T55x7_BITRATE_RF_128; + case 100: + return T55x7_BITRATE_RF_100; + case 64: + return T55x7_BITRATE_RF_64; + case 50: + return T55x7_BITRATE_RF_50; + case 40: + return T55x7_BITRATE_RF_40; + case 32: + return T55x7_BITRATE_RF_32; + case 16: + return T55x7_BITRATE_RF_16; + case 8: + return T55x7_BITRATE_RF_8; + default: + return 0; + } +} + #ifndef ON_DEVICE #include "ui.h" #define prnt PrintAndLog -#endif - - +// iclass / picopass chip config structures and shared routines typedef struct { uint8_t app_limit; //[8] uint8_t otp[2]; //[9-10] @@ -18,8 +41,7 @@ typedef struct { uint8_t mem_config; //[13] uint8_t eas; //[14] uint8_t fuses; //[15] -}picopass_conf_block; - +} picopass_conf_block; typedef struct { uint8_t csn[8]; @@ -28,32 +50,17 @@ typedef struct { uint8_t key_d[8]; uint8_t key_c[8]; uint8_t app_issuer_area[8]; +} picopass_hdr; -}picopass_hdr; - - -//#define prnt printf -/*void prnt(char *fmt,...) -{ - va_list argptr; - va_start(argptr, fmt); - vprintf(fmt, argptr); - printf(" "); // cleaning prompt - va_end(argptr); - printf("\n"); -} -*/ -uint8_t isset(uint8_t val, uint8_t mask) -{ +uint8_t isset(uint8_t val, uint8_t mask) { return (val & mask); } -uint8_t notset(uint8_t val, uint8_t mask){ +uint8_t notset(uint8_t val, uint8_t mask) { return !(val & mask); } -void fuse_config(const picopass_hdr *hdr) -{ +void fuse_config(const picopass_hdr *hdr) { uint8_t fuses = hdr->conf.fuses; if (isset(fuses,FUSE_FPERS))prnt(" Mode: Personalization [Programmable]"); @@ -104,8 +111,7 @@ void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t * } } -void mem_app_config(const picopass_hdr *hdr) -{ +void mem_app_config(const picopass_hdr *hdr) { uint8_t mem = hdr->conf.mem_config; uint8_t chip = hdr->conf.chip_config; uint8_t applimit = hdr->conf.app_limit; @@ -118,28 +124,25 @@ void mem_app_config(const picopass_hdr *hdr) prnt(" AA1: blocks 06-%02X", applimit); prnt(" AA2: blocks %02X-%02X", applimit+1, max_blk); } -void print_picopass_info(const picopass_hdr *hdr) -{ +void print_picopass_info(const picopass_hdr *hdr) { fuse_config(hdr); mem_app_config(hdr); } -void printIclassDumpInfo(uint8_t* iclass_dump) -{ -// picopass_hdr hdr; -// memcpy(&hdr, iclass_dump, sizeof(picopass_hdr)); +void printIclassDumpInfo(uint8_t* iclass_dump) { print_picopass_info((picopass_hdr *) iclass_dump); } /* -void test() -{ +void test() { picopass_hdr hdr = {0x27,0xaf,0x48,0x01,0xf9,0xff,0x12,0xe0,0x12,0xff,0xff,0xff,0x7f,0x1f,0xff,0x3c}; prnt("Picopass configuration:"); print_picopass_info(&hdr); } -int main(int argc, char *argv[]) -{ +int main(int argc, char *argv[]) { test(); return 0; } */ + +#endif +//ON_DEVICE diff --git a/common/protocols.h b/common/protocols.h index dd023bb8..cdcf720b 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -210,8 +210,60 @@ NXP/Philips CUSTOM COMMANDS #define FUSE_FPROD0 0x02 #define FUSE_RA 0x01 - void printIclassDumpInfo(uint8_t* iclass_dump); void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb); -#endif // PROTOCOLS_H +/* T55x7 configuration register definitions */ +#define T55x7_POR_DELAY 0x00000001 +#define T55x7_ST_TERMINATOR 0x00000008 +#define T55x7_PWD 0x00000010 +#define T55x7_MAXBLOCK_SHIFT 5 +#define T55x7_AOR 0x00000200 +#define T55x7_PSKCF_RF_2 0 +#define T55x7_PSKCF_RF_4 0x00000400 +#define T55x7_PSKCF_RF_8 0x00000800 +#define T55x7_MODULATION_DIRECT 0 +#define T55x7_MODULATION_PSK1 0x00001000 +#define T55x7_MODULATION_PSK2 0x00002000 +#define T55x7_MODULATION_PSK3 0x00003000 +#define T55x7_MODULATION_FSK1 0x00004000 +#define T55x7_MODULATION_FSK2 0x00005000 +#define T55x7_MODULATION_FSK1a 0x00006000 +#define T55x7_MODULATION_FSK2a 0x00007000 +#define T55x7_MODULATION_MANCHESTER 0x00008000 +#define T55x7_MODULATION_BIPHASE 0x00010000 +#define T55x7_MODULATION_DIPHASE 0x00018000 +#define T55x7_BITRATE_RF_8 0 +#define T55x7_BITRATE_RF_16 0x00040000 +#define T55x7_BITRATE_RF_32 0x00080000 +#define T55x7_BITRATE_RF_40 0x000C0000 +#define T55x7_BITRATE_RF_50 0x00100000 +#define T55x7_BITRATE_RF_64 0x00140000 +#define T55x7_BITRATE_RF_100 0x00180000 +#define T55x7_BITRATE_RF_128 0x001C0000 + +/* T5555 (Q5) configuration register definitions */ +#define T5555_ST_TERMINATOR 0x00000001 +#define T5555_MAXBLOCK_SHIFT 0x00000001 +#define T5555_MODULATION_MANCHESTER 0 +#define T5555_MODULATION_PSK1 0x00000010 +#define T5555_MODULATION_PSK2 0x00000020 +#define T5555_MODULATION_PSK3 0x00000030 +#define T5555_MODULATION_FSK1 0x00000040 +#define T5555_MODULATION_FSK2 0x00000050 +#define T5555_MODULATION_BIPHASE 0x00000060 +#define T5555_MODULATION_DIRECT 0x00000070 +#define T5555_INVERT_OUTPUT 0x00000080 +#define T5555_PSK_RF_2 0 +#define T5555_PSK_RF_4 0x00000100 +#define T5555_PSK_RF_8 0x00000200 +#define T5555_USE_PWD 0x00000400 +#define T5555_USE_AOR 0x00000800 +#define T5555_BITRATE_SHIFT 12 //(RF=2n+2) ie 64=2*0x1F+2 or n = (RF-2)/2 +#define T5555_FAST_WRITE 0x00004000 +#define T5555_PAGE_SELECT 0x00008000 + +uint32_t GetT55xxClockBit(uint32_t clock); + +#endif +// PROTOCOLS_H diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 88e2afe3..b8a12966 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -85,7 +85,7 @@ typedef struct{ #define CMD_INDALA_CLONE_TAG_L 0x0213 #define CMD_T55XX_READ_BLOCK 0x0214 #define CMD_T55XX_WRITE_BLOCK 0x0215 -#define CMD_T55XX_READ_TRACE 0x0216 +#define CMD_T55XX_RESET_READ 0x0216 #define CMD_PCF7931_READ 0x0217 #define CMD_PCF7931_WRITE 0x0222 #define CMD_EM4X_READ_WORD 0x0218 @@ -99,6 +99,7 @@ typedef struct{ #define CMD_ASK_SIM_TAG 0x021F #define CMD_PSK_SIM_TAG 0x0220 #define CMD_AWID_DEMOD_FSK 0x0221 +#define CMD_T55XX_WAKEUP 0x0224 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */