From dd8e45133090d9684a7f0d37ef59137e6b7159a9 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sun, 16 Jun 2019 15:35:10 +1000 Subject: [PATCH 01/18] T55xx downlink Modes Changes : - Added t55xx downlink protocols (long leading reference, leading 0 and 1 of 4) - Added function to all read to call differnet downlink functions (to match write) - Update functions to support using differnet downlink modes. - Added support for calling downlink modes for lf t55 read, write and detect - Added new function lf t55 bruteforcedl to support downlink modes as well as try each mode for each password in password file. for functions with downlink mode extenstion. e - OPTIONAL downlink encoding '0' fixed-bit-length (default), '1' Long Zero Reference, '2' Leading Zero, '3' 1 of 4 --- armsrc/lfops.c | 442 +++++++++++++++++++++++++++++++++++++++++++- client/cmdlft55xx.c | 332 +++++++++++++++++++++++++++++++-- client/cmdlft55xx.h | 3 +- 3 files changed, 755 insertions(+), 22 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 81fdd7a6..36efe729 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1203,6 +1203,8 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) #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 15*8 +// Long Leading Reference +#define Reference_llr (136+18)*8 // Needs to be WRITR_0 + 136 clocks. void TurnReadLFOn(int delay) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); @@ -1220,6 +1222,265 @@ void T55xxWriteBit(int bit) { WaitUS(WRITE_GAP); } +void T55xxWrite_LLR (void) +{ + TurnReadLFOn (Reference_llr); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitUS(WRITE_GAP); +} + +#define START_GAPlz 31*8 +#define WRITE_GAPlz 20*8 +#define WRITElz_0 18*8 +#define WRITElz_1 40*8 +#define READ_GAP 15*8 + +void T55xxWriteBit_Leading0(int bit) { + if (!bit) + TurnReadLFOn(WRITElz_0); + else + TurnReadLFOn(WRITElz_1); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitUS(WRITE_GAPlz); +// WaitUS(160); +} + +#define START_GAP1of4 31*8 // SPEC: 1*8 to 50*8 - typ 10*8 (or 15fc) +#define WRITE_GAP1of4 20*8 // SPEC: 1*8 to 20*8 - typ 10*8 (or 10fc) +// 00 = reference // 8 * 8 - - 68 * 8 +#define WRITE1of4_00 18*8 // SPEC: 8*8 to 68*8 - typ 24*8 (or 24fc) +#define WRITE1of4_01 34*8 // SPEC: dref+9 - dref+16 - dref+24 +#define WRITE1of4_10 50*8 // SPEC: dref+25 - dref+32 - dref+40 +#define WRITE1of4_11 66*8 // SPEC: dref+41 - dref+48 - dref+56 +#define READ1of4_GAP 15*8 + +void T55xxWriteBit_1of4(int bits) { + + switch (bits) + { + case 0 : TurnReadLFOn(WRITE1of4_00); break; + case 1 : TurnReadLFOn(WRITE1of4_01); break; + case 2 : TurnReadLFOn(WRITE1of4_10); break; + case 3 : TurnReadLFOn(WRITE1of4_11); break; + default: + TurnReadLFOn(WRITE1of4_00); + } + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitUS(WRITE_GAP1of4); +// WaitUS(160); +} + +void T55xxWriteBlockExt_Leading0 (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; + bool testMode = arg & 0x4; + uint32_t i = 0; + + // Set up FPGA, 125kHz + LFSetupFPGAForADC(95, true); + StartTicks(); + // make sure tag is fully powered up... + WaitMS(5); + // Trigger T55x7 in mode. + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + WaitUS(START_GAPlz); + + + /* + 0 : Leading Zero + 11 : Opcode + 00 : Fixed 00 if protected write (i.e. have password) + <32 bit Password> + 0 : Lock Bit + <32 bit data> + <3 bit addr> + + Standard Write : 0 1p L <32 data bits> <3 bit addr> + 0 10 0 00000000000000000000000000000000 001 + Protected Write: 0 1p 00 <32 pwd bits> L <32 data bits> <3 bit addr> + 0 10 00 00000000000000000000000000000000 0 00000000000000000000000000000000 001 + Wake Up 0 10 00 <32 pwd bits> + Protected Read 0 1p 00 <32 pwd bits> 0 <3 bit addr> + Standard Read 0 1p 0 <3 bit addr> + Page 0/1 read 0 1p + Reset 0 00 + + */ + T55xxWriteBit_Leading0 (0); //T55xxWriteBit(0); + + + if (testMode) Dbprintf("TestMODE"); + // Std Opcode 10 + T55xxWriteBit_Leading0 (testMode ? 0 : 1); + T55xxWriteBit_Leading0 (testMode ? 1 : Page); //Page 0 + + + if (PwdMode) { + // Leading zero - insert two fixed 00 between opcode and password + T55xxWriteBit_Leading0 (0); + T55xxWriteBit_Leading0 (0); + // Send Pwd + for (i = 0x80000000; i != 0; i >>= 1) + T55xxWriteBit_Leading0 (Pwd & i); + } + + // Send Lock bit + T55xxWriteBit_Leading0 (0); + + // Send Data + for (i = 0x80000000; i != 0; i >>= 1) + T55xxWriteBit_Leading0(Data & i); + + // Send Block number + for (i = 0x04; i != 0; i >>= 1) + T55xxWriteBit_Leading0 (Block & i); + + // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550, + // so wait a little more) + // "there is a clock delay before programming" + // - programming takes ~5.6ms for t5577 ~18ms for E5550 or t5567 + // so we should wait 1 clock + 5.6ms then read response? + // but we need to know we are dealing with t5577 vs t5567 vs e5550 (or q5) marshmellow... + if (testMode) { + //TESTMODE TIMING TESTS: + // <566us does nothing + // 566-568 switches between wiping to 0s and doing nothing + // 5184 wipes and allows 1 block to be programmed. + // indefinite power on wipes and then programs all blocks with bitshifted data sent. + TurnReadLFOn(5184); + + } else { + 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 for + // modulation clock an other details to demod the response... + // response should be (for t55x7) a 0 bit then (ST if on) + // block data written in on repeat until reset. + + //DoPartialAcquisition(20, true, 12000); + } + + // turn field off + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_A_OFF(); + +} +void T55xxWriteBlockExt_1of4 (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; + bool testMode = arg & 0x4; + int bitpos; + uint8_t bits; + + // Set up FPGA, 125kHz + LFSetupFPGAForADC(95, true); + StartTicks(); + // make sure tag is fully powered up... + WaitMS(5); + // Trigger T55x7 in mode. + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + + WaitUS(START_GAP1of4); + + + /* + 00 : 1 if 4 + 11 : Opcode + 00 : Fixed 00 if protected write (i.e. have password) + <32 bit Password> + 0 : Lock Bit + <32 bit data> + <3 bit addr> + + Standard Write : 00 1p L <32 data bits> <3 bit addr> + 00 10 0 00000000000000000000000000000000 001 + Protected Write: 00 1p 00 <32 pwd bits> L <32 data bits> <3 bit addr> + 00 10 00 00000000000000000000000000000000 0 00000000000000000000000000000000 001 + Wake Up 00 10 00 <32 pwd bits> + Protected Read 00 1p 00 <32 pwd bits> 0 <3 bit addr> + Standard Read 00 1p 0 <3 bit addr> + Page 0/1 read 00 1p + Reset 00 00 + + */ + T55xxWriteBit_1of4 (0); //Send Reference 00 + + if (testMode) Dbprintf("TestMODE"); + // Std Opcode 10 + if (testMode) bits = 0; else bits = 2; // 0x or 1x + if (testMode) bits |= 1; else bits += (Page); // x0 or x1 + T55xxWriteBit_1of4 (bits); + + if (PwdMode) { + // 1 of 4 00 - insert two fixed 00 between opcode and password + T55xxWriteBit_1of4 (0); // 00 + + // Send Pwd + for (bitpos = 31; bitpos >= 1; bitpos -= 2) { // 2 bits at a time + bits = (((Pwd >> bitpos) & 1) << 1) + ((Pwd >> (bitpos-1)) & 1); + T55xxWriteBit_1of4 (bits); + } + } + + // Send Lock bit + bits = 0; // Add lock bit (Not Set) to the next 2 bits + + // Send Data - offset by 1 bit due to lock bit + // 2 bits at a time - Initilised with lock bit above + for (bitpos = 31; bitpos >= 1; bitpos -= 2) { + bits |= ((Data >> bitpos) & 1); // Add Low bit + T55xxWriteBit_1of4 (bits); + bits = ((Data >> (bitpos-1)) & 1) << 1; // Set next high bit + } + + // Send Block number + bits |= ((Block >> 2) & 1); + T55xxWriteBit_1of4 (bits); + bits = (Block & 3);// 1) & 2) + (Block & 1); + T55xxWriteBit_1of4 (bits); + + // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550, + // so wait a little more) + // "there is a clock delay before programming" + // - programming takes ~5.6ms for t5577 ~18ms for E5550 or t5567 + // so we should wait 1 clock + 5.6ms then read response? + // but we need to know we are dealing with t5577 vs t5567 vs e5550 (or q5) marshmellow... + if (testMode) { + //TESTMODE TIMING TESTS: + // <566us does nothing + // 566-568 switches between wiping to 0s and doing nothing + // 5184 wipes and allows 1 block to be programmed. + // indefinite power on wipes and then programs all blocks with bitshifted data sent. + TurnReadLFOn(5184); + + } else { + 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 for + // modulation clock an other details to demod the response... + // response should be (for t55x7) a 0 bit then (ST if on) + // block data written in on repeat until reset. + + //DoPartialAcquisition(20, true, 12000); + } + + // turn field off + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_A_OFF(); + +} + // Send T5577 reset command then read stream (see if we can identify the start of the stream) void T55xxResetRead(void) { LED_A_ON(); @@ -1324,12 +1585,34 @@ void T55xxWriteBlockExt(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg // 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); +// arg 8 bit 00000000 +// 0000000x Password +// 000000x0 Page +// 00000x00 Test Mode +// 000xx000 (0x18) where xx : 00 - Normal Write, 01 - Long Leading Reference +// 10 - Leading 0, 11 - 1 of 4 + uint8_t downlink_mode; + + downlink_mode = (arg >> 3) & 0x03; + + switch (downlink_mode) + { + case 0 : T55xxWriteBlockExt (Data, Block, Pwd, arg); break; + case 1 : T55xxWrite_LLR (); + T55xxWriteBlockExt (Data, Block, Pwd, arg); + break; + case 2 : T55xxWriteBlockExt_Leading0 (Data, Block, Pwd, arg); break; + case 3 : T55xxWriteBlockExt_1of4 (Data, Block, Pwd, arg); break; + + default: + T55xxWriteBlockExt (Data, Block, Pwd, arg); + } + cmd_send(CMD_ACK,0,0,0,0,0); } // Read one card block in page [page] -void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { +void T55xxReadBlockExt (uint16_t arg0, uint8_t Block, uint32_t Pwd) { LED_A_ON(); bool PwdMode = arg0 & 0x1; uint8_t Page = (arg0 & 0x2) >> 1; @@ -1379,10 +1662,163 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - cmd_send(CMD_ACK,0,0,0,0,0); +// cmd_send(CMD_ACK,0,0,0,0,0); LED_A_OFF(); } +void T55xxReadBlockExt_Leading0 (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; + bool RegReadMode = (Block == 0xFF);//regular read mode + + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_ext(false); + + //make sure block is at max 7 + Block &= 0x7; + + // Set up FPGA, 125kHz to power up the tag + LFSetupFPGAForADC(95, true); + StartTicks(); + // make sure tag is fully powered up... + WaitMS(5); + // Trigger T55x7 Direct Access Mode with start gap + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitUS(START_GAPlz); + + T55xxWriteBit_Leading0 (0); + + // Opcode 1[page] + T55xxWriteBit_Leading0 (1); + T55xxWriteBit_Leading0 (Page); //Page 0 + + if (PwdMode){ + // Send Pwd + T55xxWriteBit_Leading0 (0); + T55xxWriteBit_Leading0 (0); + + for (i = 0x80000000; i != 0; i >>= 1) + T55xxWriteBit_Leading0 (Pwd & i); + } + // Send a zero bit separation + T55xxWriteBit_Leading0(0); + + // Send Block number (if direct access mode) + if (!RegReadMode) + for (i = 0x04; i != 0; i >>= 1) + T55xxWriteBit_Leading0(Block & i); + + // Turn field on to read the response + // 137*8 seems to get to the start of data pretty well... + // but we want to go past the start and let the repeating data settle in... + TurnReadLFOn(210*8); + + // Acquisition + // Now do the acquisition + DoPartialAcquisition(0, true, 12000, 0); + + // Turn the field off + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off +// cmd_send(CMD_ACK,0,0,0,0,0); + LED_A_OFF(); +} + +void T55xxReadBlockExt_1of4 (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; + bool RegReadMode = (Block == 0xFF);//regular read mode + uint8_t bits; + int bitpos; + + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_ext(false); + + //make sure block is at max 7 + Block &= 0x7; + + // Set up FPGA, 125kHz to power up the tag + LFSetupFPGAForADC(95, true); + StartTicks(); + // make sure tag is fully powered up... + WaitMS(5); + // Trigger T55x7 Direct Access Mode with start gap + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitUS(START_GAP1of4); + + T55xxWriteBit_1of4 (0); // 2 Bit 00 leading reference + + // Opcode 1[page] + bits = 2 + Page; + T55xxWriteBit_1of4 (bits); + + if (PwdMode) { + // 1 of 4 00 - insert two fixed 00 between opcode and password + T55xxWriteBit_1of4 (0); // 00 + + // Send Pwd + for (bitpos = 31; bitpos >= 1; bitpos -= 2) { // 2 bits at a time + bits = (((Pwd >> bitpos) & 1) << 1) + ((Pwd >> (bitpos-1)) & 1); + T55xxWriteBit_1of4 (bits); + } + } + + // Send Lock bit + bits = 0; // Add lock bit (Not Set) to the next 2 bits + + // Send Block number (if direct access mode) + if (!RegReadMode){ + // Send Block number + bits += ((Block >> 2) & 1); + T55xxWriteBit_1of4 (bits); + bits = (Block & 3); // + (Block & 1); + T55xxWriteBit_1of4 (bits); + } + + // Turn field on to read the response + // 137*8 seems to get to the start of data pretty well... + // but we want to go past the start and let the repeating data settle in... + TurnReadLFOn(210*8); + + // Acquisition + // Now do the acquisition + DoPartialAcquisition(0, true, 12000, 0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off +// cmd_send(CMD_ACK,0,0,0,0,0); + LED_A_OFF(); +} + +void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) { +// arg0 16 bit 00000000 +// 0000000x Password +// 000000x0 Page +// 00000x00 +// 000xx000 (0x18) where xx : 00 - Normal Write, 01 - Long Leading Reference +// 10 - Leading 0, 11 - 1 of 4 + uint8_t downlink_mode; + + downlink_mode = (arg0 >> 3) & 0x03; + + // downlink mode id set to match the 2 bit as per Tech Sheet + switch (downlink_mode) + { + case 0 : T55xxReadBlockExt (arg0, Block, Pwd); break; + case 1 : T55xxWrite_LLR (); + T55xxReadBlockExt (arg0, Block, Pwd); + break; + case 2 : T55xxReadBlockExt_Leading0 (arg0, Block, Pwd); break; + case 3 : T55xxReadBlockExt_1of4 (arg0, Block, Pwd); break; + default: + T55xxReadBlockExt (arg0, Block, Pwd) ; + } + +// T55xxReadBlockExt (arg0, Block, Pwd) ; + cmd_send(CMD_ACK,0,0,0,0,0); +} + void T55xxWakeUp(uint32_t Pwd){ LED_B_ON(); uint32_t i = 0; diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index b286c392..25df4c76 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -67,6 +67,8 @@ int usage_t55xx_read(){ PrintAndLog(" p - OPTIONAL password (8 hex characters)"); PrintAndLog(" o - OPTIONAL override safety check"); PrintAndLog(" 1 - OPTIONAL read Page 1 instead of Page 0"); + PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed-bit-length (default), '1' Long Zero Reference"); + PrintAndLog(" '2' Leading Zero, '3' 1 of 4 "); PrintAndLog(" ****WARNING****"); PrintAndLog(" Use of read with password on a tag not configured for a pwd"); PrintAndLog(" can damage the tag"); @@ -86,6 +88,8 @@ int usage_t55xx_write(){ PrintAndLog(" p - OPTIONAL password 4bytes (8 hex characters)"); PrintAndLog(" 1 - OPTIONAL write Page 1 instead of Page 0"); PrintAndLog(" t - OPTIONAL test mode write - ****DANGER****"); + PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed-bit-length (default), '1' Long Zero Reference"); + PrintAndLog(" '2' Leading Zero, '3' 1 of 4 "); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx write b 3 d 11223344 - write 11223344 to block 3"); @@ -132,6 +136,8 @@ int usage_t55xx_detect(){ PrintAndLog("Options:"); PrintAndLog(" 1 - if set, use Graphbuffer otherwise read data from tag."); PrintAndLog(" p - OPTIONAL password (8 hex characters)"); + PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed-bit-length (default), '1' Long Zero Reference"); + PrintAndLog(" '2' Leading Zero, '3' 1 of 4 "); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx detect"); @@ -182,6 +188,24 @@ int usage_t55xx_bruteforce(){ PrintAndLog(""); return 0; } +int usage_t55xx_bruteforce_downlink(){ + PrintAndLog("This command uses A) bruteforce to scan a number range"); + PrintAndLog(" B) a dictionary attack"); + PrintAndLog("Usage: lf t55xx bruteforce [i <*.dic>]"); + PrintAndLog(" password must be 4 bytes (8 hex symbols)"); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" r - 4 byte hex value to start and end pwd search at"); + PrintAndLog(" i <*.dic> - loads a default keys dictionary file <*.dic>"); + PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed-bit-length (default), '1' Long Zero Reference"); + PrintAndLog(" '2' Leading Zero, '3' 1 of 4 "); + PrintAndLog(""); + PrintAndLog("Examples:"); + PrintAndLog(" lf t55xx bruteforce aaaaaaaa bbbbbbbb"); + PrintAndLog(" lf t55xx bruteforce i default_pwd.dic"); + PrintAndLog(""); + return 0; +} int usage_t55xx_wipe(){ PrintAndLog("Usage: lf t55xx wipe [h] [Q5]"); PrintAndLog("This commands wipes a tag, fills blocks 1-7 with zeros and a default configuration block"); @@ -311,12 +335,12 @@ int CmdT55xxSetConfig(const char *Cmd) { return printConfiguration ( config ); } -int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32_t password){ +int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32_t password, uint8_t downlink_mode){ //Password mode if ( usepwd ) { // try reading the config block and verify that PWD bit is set before doing this! if ( !override ) { - if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0 ) ) return 0; + if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0,downlink_mode ) ) return 0; if ( !tryDetectModulation() ) { PrintAndLog("Safety Check: Could not detect if PWD bit is set in config block. Exits."); return 0; @@ -330,7 +354,7 @@ int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32 } } - if (!AquireData(page1, block, usepwd, password) ) return 0; + if (!AquireData(page1, block, usepwd, password,downlink_mode) ) return 0; if (!DecodeT55xxBlock()) return 0; char blk[10]={0}; @@ -342,6 +366,8 @@ int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32 int CmdT55xxReadBlock(const char *Cmd) { uint8_t block = REGULAR_READ_MODE_BLOCK; uint32_t password = 0; //default to blank Block 7 + uint8_t downlink_mode = 0; + bool usepwd = false; bool override = false; bool page1 = false; @@ -372,6 +398,12 @@ int CmdT55xxReadBlock(const char *Cmd) { page1 = true; cmdp++; break; + case 'e': + case 'E': + downlink_mode = param_getchar(Cmd, cmdp+1) - '0'; + if (downlink_mode > 3) downlink_mode = 0; + cmdp +=2; + break; default: PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -386,7 +418,7 @@ int CmdT55xxReadBlock(const char *Cmd) { } printT5xxHeader(page1); - return T55xxReadBlock(block, page1, usepwd, override, password); + return T55xxReadBlock(block, page1, usepwd, override, password, downlink_mode); } bool DecodeT55xxBlock(){ @@ -465,6 +497,7 @@ int CmdT55xxDetect(const char *Cmd){ bool usepwd = false; uint32_t password = 0; uint8_t cmdp = 0; + uint8_t downlink_mode = 0; while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch(param_getchar(Cmd, cmdp)) { @@ -482,6 +515,12 @@ int CmdT55xxDetect(const char *Cmd){ useGB = true; cmdp++; break; + case 'e': + case 'E': + downlink_mode = param_getchar(Cmd, cmdp+1) - '0'; + if (downlink_mode > 3) downlink_mode = 0; + cmdp +=2; + break; default: PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -491,13 +530,24 @@ int CmdT55xxDetect(const char *Cmd){ if (errors) return usage_t55xx_detect(); if ( !useGB) { - if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password) ) + if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password,downlink_mode) ) return 0; } if ( !tryDetectModulation() ) PrintAndLog("Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'"); - + else { + // Add downlink mode to reference. + switch (downlink_mode) { + case 0 : PrintAndLog ("Downlink : e 0 - Default/Fixed Bit Length"); break; + case 1 : PrintAndLog ("Downlink : e 1 - Long Leading Reference"); break; + case 2 : PrintAndLog ("Downlink : e 2 - Leading Zero Reference"); break; + case 3 : PrintAndLog ("Downlink : e 3 - 1 of 4 Coding"); break; + // default: + + // No default action + } + } return 1; } @@ -898,6 +948,8 @@ int CmdT55xxWriteBlock(const char *Cmd) { uint8_t block = 0xFF; //default to invalid block uint32_t data = 0; //default to blank Block uint32_t password = 0; //default to blank Block 7 + uint32_t downlink_mode = 0; + bool usepwd = false; bool page1 = false; bool gotdata = false; @@ -935,6 +987,12 @@ int CmdT55xxWriteBlock(const char *Cmd) { page1 = true; cmdp++; break; + case 'e': + case 'E': + downlink_mode = param_getchar(Cmd, cmdp+1) - '0'; + if (downlink_mode > 3) downlink_mode = 0; + cmdp +=2; + break; default: PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -952,17 +1010,19 @@ int CmdT55xxWriteBlock(const char *Cmd) { UsbCommand resp; c.d.asBytes[0] = (page1) ? 0x2 : 0; c.d.asBytes[0] |= (testMode) ? 0x4 : 0; - + c.d.asBytes[0] |= (downlink_mode << 3); + char pwdStr[16] = {0}; snprintf(pwdStr, sizeof(pwdStr), "pwd: 0x%08X", password); PrintAndLog("Writing page %d block: %02d data: 0x%08X %s", page1, block, data, (usepwd) ? pwdStr : "" ); - + //Password mode if (usepwd) { c.arg[2] = password; c.d.asBytes[0] |= 0x1; } + clearCommandBuffer(); SendCommand(&c); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){ @@ -980,7 +1040,7 @@ int CmdT55xxReadTrace(const char *Cmd) { return usage_t55xx_trace(); if (strlen(Cmd)==0) - if ( !AquireData( T55x7_PAGE1, REGULAR_READ_MODE_BLOCK, pwdmode, password ) ) + if ( !AquireData( T55x7_PAGE1, REGULAR_READ_MODE_BLOCK, pwdmode, password,0 ) ) return 0; if ( config.Q5 ) { @@ -1144,7 +1204,7 @@ int CmdT55xxInfo(const char *Cmd){ return usage_t55xx_info(); if (strlen(Cmd)==0) - if ( !AquireData( T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, pwdmode, password ) ) + if ( !AquireData( T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, pwdmode, password,0 ) ) return 1; if (!DecodeT55xxBlock()) return 1; @@ -1212,20 +1272,21 @@ int CmdT55xxDump(const char *Cmd){ printT5xxHeader(0); for ( uint8_t i = 0; i <8; ++i) - T55xxReadBlock(i, 0, usepwd, override, password); + T55xxReadBlock(i, 0, usepwd, override, password,0); printT5xxHeader(1); for ( uint8_t i = 0; i<4; i++) - T55xxReadBlock(i, 1, usepwd, override, password); + T55xxReadBlock(i, 1, usepwd, override, password,0); return 1; } -int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ){ +int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint8_t downlink_mode ){ // arg0 bitmodes: // bit0 = pwdmode // bit1 = page to read from uint8_t arg0 = (page<<1) | pwdmode; + arg0 |= (downlink_mode << 3); UsbCommand c = {CMD_T55XX_READ_BLOCK, {arg0, block, password}}; clearCommandBuffer(); @@ -1397,6 +1458,7 @@ int CmdT55xxBruteForce(const char *Cmd) { char buf[9]; char filename[FILE_PATH_SIZE]={0}; int keycnt = 0; + uint8_t downlink_mode = 0; int ch; uint8_t stKeyBlock = 20; uint8_t *keyBlock = NULL, *p = NULL; @@ -1480,7 +1542,7 @@ int CmdT55xxBruteForce(const char *Cmd) { PrintAndLog("Testing %08X", testpwd); - if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd)) { + if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd,downlink_mode)) { PrintAndLog("Aquireing data from device failed. Quitting"); free(keyBlock); return 0; @@ -1525,7 +1587,7 @@ int CmdT55xxBruteForce(const char *Cmd) { return 0; } - if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, i)) { + if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, i,downlink_mode)) { PrintAndLog("Aquireing data from device failed. Quitting"); free(keyBlock); return 0; @@ -1547,6 +1609,239 @@ int CmdT55xxBruteForce(const char *Cmd) { return 0; } +int CmdT55xxBruteForce_downlink(const char *Cmd) { + + // load a default pwd file. + char buf[9]; + char filename[FILE_PATH_SIZE]={0}; + int keycnt = 0; + uint8_t downlink_mode = 0; + int ch; + uint8_t stKeyBlock = 20; + uint8_t *keyBlock = NULL, *p = NULL; + uint32_t start_password = 0x00000000; //start password + uint32_t end_password = 0xFFFFFFFF; //end password + bool found = false; + uint8_t cmdp = 0; + int cmd_offset = 0; + int errors = 0; + int len; + bool use_file = false; + bool use_range = false; + bool try_all_dl_modes = false; + uint8_t dl_mode = 0; + + keyBlock = calloc(stKeyBlock, 6); + if (keyBlock == NULL) return 1; + + PrintAndLog("New Downlink Supprt"); + + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_t55xx_bruteforce_downlink(); + case 'e': + case 'E': + downlink_mode = param_getchar(Cmd, cmdp+1) - '0'; + if (downlink_mode == 4) try_all_dl_modes = true; + if (downlink_mode > 3) downlink_mode = 0; + cmdp +=2; + cmd_offset += 4; + PrintAndLog ("DL Mode : %d",downlink_mode); + break; + case 'i': + case 'I': + if (use_range) { + PrintAndLog ("use Range or File"); + return 0; + } + use_file = true; + len = strlen(Cmd+2); + if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; + memcpy(filename, Cmd+cmd_offset+2, len); + cmdp += 2; + // PrintAndLog (" File : [%s]",filename); + break; + case 'r': + case 'R': + if (use_file) { + PrintAndLog ("use Range or File"); + return 0; + } + use_range = true; // = param_get32ex(Cmd, cmdp+1, 0, 16); + start_password = param_get32ex(Cmd, cmdp+1, 0, 16); + end_password = param_get32ex(Cmd, cmdp+2, 0, 16); + cmdp += 3; + cmd_offset += 20; // 8 + 8 + 1 + 1 + 1 + // PrintAndLog (" Range : [%0X] - [%0X]",start_password,end_password); + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + +// if (cmdp == 'i' || cmdp == 'I') { + + if (use_file) + { + FILE * f = fopen( filename , "r"); + + if ( !f ) { + PrintAndLog("File: %s: not found or locked.", filename); + free(keyBlock); + return 1; + } + + while( fgets(buf, sizeof(buf), f) ) { + if (strlen(buf) < 8 || buf[7] == '\n') continue; + + while (fgetc(f) != '\n' && !feof(f)) ; //goto next line + + //The line start with # is comment, skip + if( buf[0]=='#' ) continue; + + if (!isxdigit((unsigned char)buf[0])) { + PrintAndLog("File content error. '%s' must include 8 HEX symbols", buf); + continue; + } + + buf[8] = 0; + + if ( stKeyBlock - keycnt < 2) { + p = realloc(keyBlock, 6*(stKeyBlock+=10)); + if (!p) { + PrintAndLog("Cannot allocate memory for defaultKeys"); + free(keyBlock); + fclose(f); + return 2; + } + keyBlock = p; + } + memset(keyBlock + 4 * keycnt, 0, 4); + num_to_bytes(strtoll(buf, NULL, 16), 4, keyBlock + 4*keycnt); + PrintAndLog("chk custom pwd[%2d] %08X", keycnt, bytes_to_num(keyBlock + 4*keycnt, 4)); + keycnt++; + memset(buf, 0, sizeof(buf)); + } + fclose(f); + + if (keycnt == 0) { + PrintAndLog("No keys found in file"); + free(keyBlock); + return 1; + } + PrintAndLog("Loaded %d keys", keycnt); + + // loop + uint64_t testpwd = 0x00; + for (uint16_t c = 0; c < keycnt; ++c ) { + + if (ukbhit()) { + ch = getchar(); + (void)ch; + printf("\naborted via keyboard!\n"); + free(keyBlock); + return 0; + } + + testpwd = bytes_to_num(keyBlock + 4*c, 4); + + PrintAndLog("Testing %08X", testpwd); + + // Try each downlink_mode of asked to + // donwlink_mode will = 0 if > 3 or set to 0, so loop from 0 - 3 + for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++) + { + if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd,dl_mode)) { + PrintAndLog("Aquireing data from device failed. Quitting"); + free(keyBlock); + return 0; + } + + found = tryDetectModulation(); + + if ( found ) { + PrintAndLog("Found valid password: [%08X]", testpwd); + free(keyBlock); + // Add downlink mode to reference. + switch (dl_mode) { + case 0 : PrintAndLog ("Downlink : e 0 - Default/Fixed Bit Length"); break; + case 1 : PrintAndLog ("Downlink : e 1 - Long Leading Reference"); break; + case 2 : PrintAndLog ("Downlink : e 2 - Leading Zero Reference"); break; + case 3 : PrintAndLog ("Downlink : e 3 - 1 of 4 Coding"); break; + } + return 0; + } + if (!try_all_dl_modes) // Exit loop + dl_mode = 4; + } + } + PrintAndLog("Password NOT found."); + free(keyBlock); + return 0; + } + + if (use_range) + { + // incremental pwd range search + // start_password = param_get32ex(Cmd, 0, 0, 16); + // end_password = param_get32ex(Cmd, 1, 0, 16); + + if ( start_password >= end_password ) { + free(keyBlock); + return usage_t55xx_bruteforce_downlink(); + } + PrintAndLog("Search password range [%08X -> %08X]", start_password, end_password); + + uint32_t i = start_password; + + while ((!found) && (i <= end_password)) { + + printf("."); + fflush(stdout); + if (ukbhit()) { + ch = getchar(); + (void)ch; + printf("\naborted via keyboard!\n"); + free(keyBlock); + return 0; + } + + if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, i,downlink_mode)) { + PrintAndLog("Aquireing data from device failed. Quitting"); + free(keyBlock); + return 0; + } + found = tryDetectModulation(); + + if (found) break; + i++; + } + + PrintAndLog(""); + + if (found) { + PrintAndLog("Found valid password: [%08x]", i); + // Add downlink mode to reference. + switch (downlink_mode) { + case 0 : PrintAndLog ("Downlink : e 0 - Default/Fixed Bit Length"); break; + case 1 : PrintAndLog ("Downlink : e 1 - Long Leading Reference"); break; + case 2 : PrintAndLog ("Downlink : e 2 - Leading Zero Reference"); break; + case 3 : PrintAndLog ("Downlink : e 3 - 1 of 4 Coding"); break; + } + } + else + PrintAndLog("Password NOT found. Last tried: [%08x]", --i); + + free(keyBlock); + } + return 0; +} + // note length of data returned is different for different chips. // some return all page 1 (64 bits) and others return just that block (32 bits) // unfortunately the 64 bits makes this more likely to get a false positive... @@ -1558,7 +1853,7 @@ bool tryDetectP1(bool getData) { bool st = true; if ( getData ) { - if ( !AquireData(T55x7_PAGE1, 1, false, 0) ) + if ( !AquireData(T55x7_PAGE1, 1, false, 0,0) ) return false; } @@ -1687,7 +1982,7 @@ int CmdT55xxDetectPage1(const char *Cmd){ if (errors) return usage_t55xx_detectP1(); if ( !useGB ) { - if ( !AquireData(T55x7_PAGE1, 1, usepwd, password) ) + if ( !AquireData(T55x7_PAGE1, 1, usepwd, password,0) ) return false; } bool success = tryDetectP1(false); @@ -1697,7 +1992,8 @@ int CmdT55xxDetectPage1(const char *Cmd){ static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"bruteforce",CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, + {"bruteforce",CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, + {"bruteforcedl",CmdT55xxBruteForce_downlink,0, "r [i <*.dic>] [e ] Simple bruteforce attack to find password"}, {"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, {"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."}, {"p1detect", CmdT55xxDetectPage1,1, "[1] Try detecting if this is a t55xx tag by reading page 1"}, diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index 2ae3e69b..1ba4dca4 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -74,6 +74,7 @@ void Set_t55xx_Config(t55xx_conf_block_t conf); extern int CmdLFT55XX(const char *Cmd); extern int CmdT55xxBruteForce(const char *Cmd); +extern int CmdT55xxBruteForce_downlink(const char *Cmd); extern int CmdT55xxSetConfig(const char *Cmd); extern int CmdT55xxReadBlock(const char *Cmd); extern int CmdT55xxWriteBlock(const char *Cmd); @@ -98,7 +99,7 @@ bool tryDetectModulation(void); extern bool tryDetectP1(bool getData); bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5); int special(const char *Cmd); -int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ); +int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password,uint8_t downlink_mode ); void printT55x7Trace( t55x7_tracedata_t data, uint8_t repeat ); void printT5555Trace( t5555_tracedata_t data, uint8_t repeat ); From 6dd0ff3035ed40ab47f22d76dbc22942a492dca3 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Mon, 17 Jun 2019 21:37:50 +1000 Subject: [PATCH 02/18] Update cmdlft55xx.c Minor Cleanup --- client/cmdlft55xx.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 25df4c76..a05838b4 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -67,8 +67,8 @@ int usage_t55xx_read(){ PrintAndLog(" p - OPTIONAL password (8 hex characters)"); PrintAndLog(" o - OPTIONAL override safety check"); PrintAndLog(" 1 - OPTIONAL read Page 1 instead of Page 0"); - PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed-bit-length (default), '1' Long Zero Reference"); - PrintAndLog(" '2' Leading Zero, '3' 1 of 4 "); + PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed bit length (default), '1' long leading reference"); + PrintAndLog(" '2' leading zero, '3' 1 of 4 coding reference"); PrintAndLog(" ****WARNING****"); PrintAndLog(" Use of read with password on a tag not configured for a pwd"); PrintAndLog(" can damage the tag"); @@ -88,8 +88,8 @@ int usage_t55xx_write(){ PrintAndLog(" p - OPTIONAL password 4bytes (8 hex characters)"); PrintAndLog(" 1 - OPTIONAL write Page 1 instead of Page 0"); PrintAndLog(" t - OPTIONAL test mode write - ****DANGER****"); - PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed-bit-length (default), '1' Long Zero Reference"); - PrintAndLog(" '2' Leading Zero, '3' 1 of 4 "); + PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed bit length (default), '1' long leading reference"); + PrintAndLog(" '2' leading zero, '3' 1 of 4 coding reference"); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx write b 3 d 11223344 - write 11223344 to block 3"); @@ -136,8 +136,8 @@ int usage_t55xx_detect(){ PrintAndLog("Options:"); PrintAndLog(" 1 - if set, use Graphbuffer otherwise read data from tag."); PrintAndLog(" p - OPTIONAL password (8 hex characters)"); - PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed-bit-length (default), '1' Long Zero Reference"); - PrintAndLog(" '2' Leading Zero, '3' 1 of 4 "); + PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed bit length (default), '1' long leading reference"); + PrintAndLog(" '2' leading zero, '3' 1 of 4 coding reference"); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx detect"); @@ -196,9 +196,10 @@ int usage_t55xx_bruteforce_downlink(){ PrintAndLog("Options:"); PrintAndLog(" h - this help"); PrintAndLog(" r - 4 byte hex value to start and end pwd search at"); - PrintAndLog(" i <*.dic> - loads a default keys dictionary file <*.dic>"); - PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed-bit-length (default), '1' Long Zero Reference"); - PrintAndLog(" '2' Leading Zero, '3' 1 of 4 "); + PrintAndLog(" i <*.dic> - loads a default keys dictionary file <*.dic>"); + PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed bit length (default)"); + PrintAndLog(" '1' long leading reference, '2' leading zero "); + PrintAndLog(" '3' 1 of 4 coding reference, '4' special - try all downlink modes"); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx bruteforce aaaaaaaa bbbbbbbb"); From be1b97d81fe44d9227a5c581fd279fed062a18cd Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Mon, 17 Jun 2019 22:01:25 +1000 Subject: [PATCH 03/18] Update cmdlft55xx.c Fixed bruteforce filename --- client/cmdlft55xx.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index a05838b4..da8fc703 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1635,8 +1635,6 @@ int CmdT55xxBruteForce_downlink(const char *Cmd) { keyBlock = calloc(stKeyBlock, 6); if (keyBlock == NULL) return 1; - PrintAndLog("New Downlink Supprt"); - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch(param_getchar(Cmd, cmdp)) { case 'h': @@ -1649,7 +1647,6 @@ int CmdT55xxBruteForce_downlink(const char *Cmd) { if (downlink_mode > 3) downlink_mode = 0; cmdp +=2; cmd_offset += 4; - PrintAndLog ("DL Mode : %d",downlink_mode); break; case 'i': case 'I': @@ -1661,8 +1658,11 @@ int CmdT55xxBruteForce_downlink(const char *Cmd) { len = strlen(Cmd+2); if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; memcpy(filename, Cmd+cmd_offset+2, len); + // Drop any characters after space + char *p = strstr(filename," "); + if (p) *p = 0; cmdp += 2; - // PrintAndLog (" File : [%s]",filename); + // PrintAndLog (" File : [%s]",filename); break; case 'r': case 'R': @@ -1670,12 +1670,11 @@ int CmdT55xxBruteForce_downlink(const char *Cmd) { PrintAndLog ("use Range or File"); return 0; } - use_range = true; // = param_get32ex(Cmd, cmdp+1, 0, 16); + use_range = true; start_password = param_get32ex(Cmd, cmdp+1, 0, 16); end_password = param_get32ex(Cmd, cmdp+2, 0, 16); cmdp += 3; - cmd_offset += 20; // 8 + 8 + 1 + 1 + 1 - // PrintAndLog (" Range : [%0X] - [%0X]",start_password,end_password); + cmd_offset += 20; break; default: PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); @@ -1684,9 +1683,6 @@ int CmdT55xxBruteForce_downlink(const char *Cmd) { } } - -// if (cmdp == 'i' || cmdp == 'I') { - if (use_file) { FILE * f = fopen( filename , "r"); @@ -1753,7 +1749,7 @@ int CmdT55xxBruteForce_downlink(const char *Cmd) { PrintAndLog("Testing %08X", testpwd); - // Try each downlink_mode of asked to + // Try each downlink_mode if asked to // donwlink_mode will = 0 if > 3 or set to 0, so loop from 0 - 3 for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++) { @@ -1768,7 +1764,7 @@ int CmdT55xxBruteForce_downlink(const char *Cmd) { if ( found ) { PrintAndLog("Found valid password: [%08X]", testpwd); free(keyBlock); - // Add downlink mode to reference. + // Add downlink mode for reference. switch (dl_mode) { case 0 : PrintAndLog ("Downlink : e 0 - Default/Fixed Bit Length"); break; case 1 : PrintAndLog ("Downlink : e 1 - Long Leading Reference"); break; @@ -1788,9 +1784,6 @@ int CmdT55xxBruteForce_downlink(const char *Cmd) { if (use_range) { - // incremental pwd range search - // start_password = param_get32ex(Cmd, 0, 0, 16); - // end_password = param_get32ex(Cmd, 1, 0, 16); if ( start_password >= end_password ) { free(keyBlock); @@ -1827,7 +1820,7 @@ int CmdT55xxBruteForce_downlink(const char *Cmd) { if (found) { PrintAndLog("Found valid password: [%08x]", i); - // Add downlink mode to reference. + // Add downlink mode for reference. switch (downlink_mode) { case 0 : PrintAndLog ("Downlink : e 0 - Default/Fixed Bit Length"); break; case 1 : PrintAndLog ("Downlink : e 1 - Long Leading Reference"); break; From 6763dc17a3f76370c766bfdb39179bde3ff7619f Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Tue, 18 Jun 2019 21:17:12 +1000 Subject: [PATCH 04/18] Cleanup Code Update downlink option from e to r fixed long leading reference added downling option to original bruteforce --- armsrc/lfops.c | 23 ++- client/cmdlft55xx.c | 379 ++++++++++---------------------------------- client/cmdlft55xx.h | 1 - 3 files changed, 103 insertions(+), 300 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 36efe729..112a1173 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1519,6 +1519,10 @@ void T55xxWriteBlockExt(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg uint8_t Page = (arg & 0x2)>>1; bool testMode = arg & 0x4; uint32_t i = 0; + uint8_t downlink_mode; + + downlink_mode = (arg >> 3) & 0x03; + // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); @@ -1529,6 +1533,9 @@ void T55xxWriteBlockExt(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(START_GAP); + // Long Leading Reference, same as fixed/default just with leading reference + if (downlink_mode == 1) T55xxWrite_LLR (); + if (testMode) Dbprintf("TestMODE"); // Std Opcode 10 T55xxWriteBit(testMode ? 0 : 1); @@ -1597,8 +1604,8 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { switch (downlink_mode) { - case 0 : T55xxWriteBlockExt (Data, Block, Pwd, arg); break; - case 1 : T55xxWrite_LLR (); + case 0 :// T55xxWriteBlockExt (Data, Block, Pwd, arg); break; + case 1 : // T55xxWrite_LLR (); T55xxWriteBlockExt (Data, Block, Pwd, arg); break; case 2 : T55xxWriteBlockExt_Leading0 (Data, Block, Pwd, arg); break; @@ -1618,7 +1625,10 @@ void T55xxReadBlockExt (uint16_t arg0, uint8_t Block, uint32_t Pwd) { uint8_t Page = (arg0 & 0x2) >> 1; uint32_t i = 0; bool RegReadMode = (Block == 0xFF);//regular read mode - + uint8_t downlink_mode; + + downlink_mode = (arg0 >> 3) & 0x03; + //clear buffer now so it does not interfere with timing later BigBuf_Clear_ext(false); @@ -1634,6 +1644,9 @@ void T55xxReadBlockExt (uint16_t arg0, uint8_t Block, uint32_t Pwd) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(START_GAP); + // Long Leading Reference, same as fixed/default just with leading reference + if (downlink_mode == 1) T55xxWrite_LLR (); + // Opcode 1[page] T55xxWriteBit(1); T55xxWriteBit(Page); //Page 0 @@ -1805,8 +1818,8 @@ void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) { // downlink mode id set to match the 2 bit as per Tech Sheet switch (downlink_mode) { - case 0 : T55xxReadBlockExt (arg0, Block, Pwd); break; - case 1 : T55xxWrite_LLR (); + case 0 :// T55xxReadBlockExt (arg0, Block, Pwd); break; + case 1 : // T55xxWrite_LLR (); T55xxReadBlockExt (arg0, Block, Pwd); break; case 2 : T55xxReadBlockExt_Leading0 (arg0, Block, Pwd); break; diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index da8fc703..ed980f9b 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -67,7 +67,7 @@ int usage_t55xx_read(){ PrintAndLog(" p - OPTIONAL password (8 hex characters)"); PrintAndLog(" o - OPTIONAL override safety check"); PrintAndLog(" 1 - OPTIONAL read Page 1 instead of Page 0"); - PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed bit length (default), '1' long leading reference"); + PrintAndLog(" r - OPTIONAL downlink encoding '0' fixed bit length (default), '1' long leading reference"); PrintAndLog(" '2' leading zero, '3' 1 of 4 coding reference"); PrintAndLog(" ****WARNING****"); PrintAndLog(" Use of read with password on a tag not configured for a pwd"); @@ -88,7 +88,7 @@ int usage_t55xx_write(){ PrintAndLog(" p - OPTIONAL password 4bytes (8 hex characters)"); PrintAndLog(" 1 - OPTIONAL write Page 1 instead of Page 0"); PrintAndLog(" t - OPTIONAL test mode write - ****DANGER****"); - PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed bit length (default), '1' long leading reference"); + PrintAndLog(" r - OPTIONAL downlink encoding '0' fixed bit length (default), '1' long leading reference"); PrintAndLog(" '2' leading zero, '3' 1 of 4 coding reference"); PrintAndLog(""); PrintAndLog("Examples:"); @@ -136,7 +136,7 @@ int usage_t55xx_detect(){ PrintAndLog("Options:"); PrintAndLog(" 1 - if set, use Graphbuffer otherwise read data from tag."); PrintAndLog(" p - OPTIONAL password (8 hex characters)"); - PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed bit length (default), '1' long leading reference"); + PrintAndLog(" r - OPTIONAL downlink encoding '0' fixed bit length (default), '1' long leading reference"); PrintAndLog(" '2' leading zero, '3' 1 of 4 coding reference"); PrintAndLog(""); PrintAndLog("Examples:"); @@ -168,7 +168,7 @@ int usage_t55xx_wakup(){ PrintAndLog(" - [required] password 4bytes (8 hex symbols)"); PrintAndLog(""); PrintAndLog("Examples:"); - PrintAndLog(" lf t55xx wakeup 11223344 - send wakeup password"); + PrintAndLog(" lf t55xx wakeup 11223344 - send wakeup password"); return 0; } int usage_t55xx_bruteforce(){ @@ -178,32 +178,16 @@ int usage_t55xx_bruteforce(){ PrintAndLog(" password must be 4 bytes (8 hex symbols)"); PrintAndLog("Options:"); PrintAndLog(" h - this help"); + PrintAndLog(" r - OPTIONAL downlink encoding '0' fixed bit length (default)"); + PrintAndLog(" '1' long leading reference, '2' leading zero "); + PrintAndLog(" '3' 1 of 4 coding reference, '4' special - try all downlink modes"); PrintAndLog(" - 4 byte hex value to start pwd search at"); PrintAndLog(" - 4 byte hex value to end pwd search at"); PrintAndLog(" i <*.dic> - loads a default keys dictionary file <*.dic>"); PrintAndLog(""); PrintAndLog("Examples:"); - PrintAndLog(" lf t55xx bruteforce aaaaaaaa bbbbbbbb"); - PrintAndLog(" lf t55xx bruteforce i default_pwd.dic"); - PrintAndLog(""); - return 0; -} -int usage_t55xx_bruteforce_downlink(){ - PrintAndLog("This command uses A) bruteforce to scan a number range"); - PrintAndLog(" B) a dictionary attack"); - PrintAndLog("Usage: lf t55xx bruteforce [i <*.dic>]"); - PrintAndLog(" password must be 4 bytes (8 hex symbols)"); - PrintAndLog("Options:"); - PrintAndLog(" h - this help"); - PrintAndLog(" r - 4 byte hex value to start and end pwd search at"); - PrintAndLog(" i <*.dic> - loads a default keys dictionary file <*.dic>"); - PrintAndLog(" e - OPTIONAL downlink encoding '0' fixed bit length (default)"); - PrintAndLog(" '1' long leading reference, '2' leading zero "); - PrintAndLog(" '3' 1 of 4 coding reference, '4' special - try all downlink modes"); - PrintAndLog(""); - PrintAndLog("Examples:"); - PrintAndLog(" lf t55xx bruteforce aaaaaaaa bbbbbbbb"); - PrintAndLog(" lf t55xx bruteforce i default_pwd.dic"); + PrintAndLog(" lf t55xx bruteforce [r 2] aaaaaaaa bbbbbbbb"); + PrintAndLog(" lf t55xx bruteforce [r 2] i default_pwd.dic"); PrintAndLog(""); return 0; } @@ -399,8 +383,8 @@ int CmdT55xxReadBlock(const char *Cmd) { page1 = true; cmdp++; break; - case 'e': - case 'E': + case 'r': + case 'R': downlink_mode = param_getchar(Cmd, cmdp+1) - '0'; if (downlink_mode > 3) downlink_mode = 0; cmdp +=2; @@ -516,8 +500,8 @@ int CmdT55xxDetect(const char *Cmd){ useGB = true; cmdp++; break; - case 'e': - case 'E': + case 'r': + case 'R': downlink_mode = param_getchar(Cmd, cmdp+1) - '0'; if (downlink_mode > 3) downlink_mode = 0; cmdp +=2; @@ -540,13 +524,10 @@ int CmdT55xxDetect(const char *Cmd){ else { // Add downlink mode to reference. switch (downlink_mode) { - case 0 : PrintAndLog ("Downlink : e 0 - Default/Fixed Bit Length"); break; - case 1 : PrintAndLog ("Downlink : e 1 - Long Leading Reference"); break; - case 2 : PrintAndLog ("Downlink : e 2 - Leading Zero Reference"); break; - case 3 : PrintAndLog ("Downlink : e 3 - 1 of 4 Coding"); break; - // default: - - // No default action + case 0 : PrintAndLog ("Downlink : r 0 - default/fixed bit length"); break; + case 1 : PrintAndLog ("Downlink : r 1 - long leading reference"); break; + case 2 : PrintAndLog ("Downlink : r 2 - leading zero reference"); break; + case 3 : PrintAndLog ("Downlink : r 3 - 1 of 4 coding reference"); break; } } return 1; @@ -988,8 +969,8 @@ int CmdT55xxWriteBlock(const char *Cmd) { page1 = true; cmdp++; break; - case 'e': - case 'E': + case 'r': + case 'R': downlink_mode = param_getchar(Cmd, cmdp+1) - '0'; if (downlink_mode > 3) downlink_mode = 0; cmdp +=2; @@ -1459,16 +1440,29 @@ int CmdT55xxBruteForce(const char *Cmd) { char buf[9]; char filename[FILE_PATH_SIZE]={0}; int keycnt = 0; - uint8_t downlink_mode = 0; int ch; uint8_t stKeyBlock = 20; uint8_t *keyBlock = NULL, *p = NULL; uint32_t start_password = 0x00000000; //start password uint32_t end_password = 0xFFFFFFFF; //end password bool found = false; - + uint8_t downlink_mode = 0; + bool try_all_dl_modes = false; + uint8_t dl_mode = 0; + uint8_t cmd_offset = 0; + int cmd_opt = 0; + char cmdp = param_getchar(Cmd, 0); + if (cmdp == 'h' || cmdp == 'H') return usage_t55xx_bruteforce(); + if (cmdp == 'r' || cmdp == 'R') { + downlink_mode = param_getchar(Cmd, 1) - '0'; // get 2nd option, as this is fixed order. + if (downlink_mode == 4) try_all_dl_modes = true; + if (downlink_mode > 3) downlink_mode = 0; + cmd_opt += 2; // To help start/end passwords for range to be found + cmd_offset += 4; // r x To help the string offset for filename start position in cmd + cmdp = param_getchar(Cmd, 2); // get 3rd option, as this is fixed order. + } keyBlock = calloc(stKeyBlock, 6); if (keyBlock == NULL) return 1; @@ -1477,7 +1471,7 @@ int CmdT55xxBruteForce(const char *Cmd) { int len = strlen(Cmd+2); if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; - memcpy(filename, Cmd+2, len); + memcpy(filename, Cmd+2+cmd_offset, len); FILE * f = fopen( filename , "r"); @@ -1542,20 +1536,32 @@ int CmdT55xxBruteForce(const char *Cmd) { testpwd = bytes_to_num(keyBlock + 4*c, 4); PrintAndLog("Testing %08X", testpwd); + + // Try each downlink_mode if asked to + // donwlink_mode will = 0 if > 3 or set to 0, so loop from 0 - 3 + for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++){ + if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd, dl_mode)) { + PrintAndLog("Aquireing data from device failed. Quitting"); + free(keyBlock); + return 0; + } - if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd,downlink_mode)) { - PrintAndLog("Aquireing data from device failed. Quitting"); - free(keyBlock); - return 0; - } + found = tryDetectModulation(); - found = tryDetectModulation(); - - if ( found ) { - PrintAndLog("Found valid password: [%08X]", testpwd); - free(keyBlock); - return 0; - } + if ( found ) { + PrintAndLog("Found valid password: [%08X]", testpwd); + free(keyBlock); + switch (dl_mode) { + case 0 : PrintAndLog ("Downlink : r 0 - default/fixed bit length"); break; + case 1 : PrintAndLog ("Downlink : r 1 - long leading reference"); break; + case 2 : PrintAndLog ("Downlink : r 2 - leading zero reference"); break; + case 3 : PrintAndLog ("Downlink : r 3 - 1 of 4 coding reference"); break; + } + return 0; + } + if (!try_all_dl_modes) // Exit loop if not trying all downlink modes + dl_mode = 4; + } } PrintAndLog("Password NOT found."); free(keyBlock); @@ -1565,8 +1571,8 @@ int CmdT55xxBruteForce(const char *Cmd) { // Try to read Block 7, first :) // incremental pwd range search - start_password = param_get32ex(Cmd, 0, 0, 16); - end_password = param_get32ex(Cmd, 1, 0, 16); + start_password = param_get32ex(Cmd, cmd_opt , 0, 16); + end_password = param_get32ex(Cmd, cmd_opt+1 , 0, 16); if ( start_password >= end_password ) { free(keyBlock); @@ -1587,225 +1593,10 @@ int CmdT55xxBruteForce(const char *Cmd) { free(keyBlock); return 0; } - - if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, i,downlink_mode)) { - PrintAndLog("Aquireing data from device failed. Quitting"); - free(keyBlock); - return 0; - } - found = tryDetectModulation(); - - if (found) break; - i++; - } - - PrintAndLog(""); - - if (found) - PrintAndLog("Found valid password: [%08x]", i); - else - PrintAndLog("Password NOT found. Last tried: [%08x]", --i); - - free(keyBlock); - return 0; -} - -int CmdT55xxBruteForce_downlink(const char *Cmd) { - - // load a default pwd file. - char buf[9]; - char filename[FILE_PATH_SIZE]={0}; - int keycnt = 0; - uint8_t downlink_mode = 0; - int ch; - uint8_t stKeyBlock = 20; - uint8_t *keyBlock = NULL, *p = NULL; - uint32_t start_password = 0x00000000; //start password - uint32_t end_password = 0xFFFFFFFF; //end password - bool found = false; - uint8_t cmdp = 0; - int cmd_offset = 0; - int errors = 0; - int len; - bool use_file = false; - bool use_range = false; - bool try_all_dl_modes = false; - uint8_t dl_mode = 0; - - keyBlock = calloc(stKeyBlock, 6); - if (keyBlock == NULL) return 1; - - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_t55xx_bruteforce_downlink(); - case 'e': - case 'E': - downlink_mode = param_getchar(Cmd, cmdp+1) - '0'; - if (downlink_mode == 4) try_all_dl_modes = true; - if (downlink_mode > 3) downlink_mode = 0; - cmdp +=2; - cmd_offset += 4; - break; - case 'i': - case 'I': - if (use_range) { - PrintAndLog ("use Range or File"); - return 0; - } - use_file = true; - len = strlen(Cmd+2); - if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; - memcpy(filename, Cmd+cmd_offset+2, len); - // Drop any characters after space - char *p = strstr(filename," "); - if (p) *p = 0; - cmdp += 2; - // PrintAndLog (" File : [%s]",filename); - break; - case 'r': - case 'R': - if (use_file) { - PrintAndLog ("use Range or File"); - return 0; - } - use_range = true; - start_password = param_get32ex(Cmd, cmdp+1, 0, 16); - end_password = param_get32ex(Cmd, cmdp+2, 0, 16); - cmdp += 3; - cmd_offset += 20; - break; - default: - PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - - if (use_file) - { - FILE * f = fopen( filename , "r"); - - if ( !f ) { - PrintAndLog("File: %s: not found or locked.", filename); - free(keyBlock); - return 1; - } - - while( fgets(buf, sizeof(buf), f) ) { - if (strlen(buf) < 8 || buf[7] == '\n') continue; - - while (fgetc(f) != '\n' && !feof(f)) ; //goto next line - - //The line start with # is comment, skip - if( buf[0]=='#' ) continue; - - if (!isxdigit((unsigned char)buf[0])) { - PrintAndLog("File content error. '%s' must include 8 HEX symbols", buf); - continue; - } - - buf[8] = 0; - - if ( stKeyBlock - keycnt < 2) { - p = realloc(keyBlock, 6*(stKeyBlock+=10)); - if (!p) { - PrintAndLog("Cannot allocate memory for defaultKeys"); - free(keyBlock); - fclose(f); - return 2; - } - keyBlock = p; - } - memset(keyBlock + 4 * keycnt, 0, 4); - num_to_bytes(strtoll(buf, NULL, 16), 4, keyBlock + 4*keycnt); - PrintAndLog("chk custom pwd[%2d] %08X", keycnt, bytes_to_num(keyBlock + 4*keycnt, 4)); - keycnt++; - memset(buf, 0, sizeof(buf)); - } - fclose(f); - - if (keycnt == 0) { - PrintAndLog("No keys found in file"); - free(keyBlock); - return 1; - } - PrintAndLog("Loaded %d keys", keycnt); - - // loop - uint64_t testpwd = 0x00; - for (uint16_t c = 0; c < keycnt; ++c ) { - - if (ukbhit()) { - ch = getchar(); - (void)ch; - printf("\naborted via keyboard!\n"); - free(keyBlock); - return 0; - } - - testpwd = bytes_to_num(keyBlock + 4*c, 4); - - PrintAndLog("Testing %08X", testpwd); - - // Try each downlink_mode if asked to - // donwlink_mode will = 0 if > 3 or set to 0, so loop from 0 - 3 - for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++) - { - if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd,dl_mode)) { - PrintAndLog("Aquireing data from device failed. Quitting"); - free(keyBlock); - return 0; - } - - found = tryDetectModulation(); - - if ( found ) { - PrintAndLog("Found valid password: [%08X]", testpwd); - free(keyBlock); - // Add downlink mode for reference. - switch (dl_mode) { - case 0 : PrintAndLog ("Downlink : e 0 - Default/Fixed Bit Length"); break; - case 1 : PrintAndLog ("Downlink : e 1 - Long Leading Reference"); break; - case 2 : PrintAndLog ("Downlink : e 2 - Leading Zero Reference"); break; - case 3 : PrintAndLog ("Downlink : e 3 - 1 of 4 Coding"); break; - } - return 0; - } - if (!try_all_dl_modes) // Exit loop - dl_mode = 4; - } - } - PrintAndLog("Password NOT found."); - free(keyBlock); - return 0; - } - - if (use_range) - { - - if ( start_password >= end_password ) { - free(keyBlock); - return usage_t55xx_bruteforce_downlink(); - } - PrintAndLog("Search password range [%08X -> %08X]", start_password, end_password); - - uint32_t i = start_password; - - while ((!found) && (i <= end_password)) { - - printf("."); - fflush(stdout); - if (ukbhit()) { - ch = getchar(); - (void)ch; - printf("\naborted via keyboard!\n"); - free(keyBlock); - return 0; - } - - if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, i,downlink_mode)) { + // Try each downlink_mode if asked to + // donwlink_mode will = 0 if > 3 or set to 0, so loop from 0 - 3 + for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++){ + if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, i,dl_mode)) { PrintAndLog("Aquireing data from device failed. Quitting"); free(keyBlock); return 0; @@ -1813,29 +1604,30 @@ int CmdT55xxBruteForce_downlink(const char *Cmd) { found = tryDetectModulation(); if (found) break; - i++; + if (!try_all_dl_modes) // Exit loop if not trying all downlink modes + dl_mode = 4; } - - PrintAndLog(""); - - if (found) { - PrintAndLog("Found valid password: [%08x]", i); - // Add downlink mode for reference. - switch (downlink_mode) { - case 0 : PrintAndLog ("Downlink : e 0 - Default/Fixed Bit Length"); break; - case 1 : PrintAndLog ("Downlink : e 1 - Long Leading Reference"); break; - case 2 : PrintAndLog ("Downlink : e 2 - Leading Zero Reference"); break; - case 3 : PrintAndLog ("Downlink : e 3 - 1 of 4 Coding"); break; - } - } - else - PrintAndLog("Password NOT found. Last tried: [%08x]", --i); - - free(keyBlock); + if (found) break; + i++; } + + if (found){ + PrintAndLog("Found valid password: [%08x]", i); + switch (dl_mode) { + case 0 : PrintAndLog ("Downlink : r 0 - default/fixed bit length"); break; + case 1 : PrintAndLog ("Downlink : r 1 - long leading reference"); break; + case 2 : PrintAndLog ("Downlink : r 2 - leading Zero reference"); break; + case 3 : PrintAndLog ("Downlink : r 3 - 1 of 4 coding reference"); break; + } + } + else{ + PrintAndLog(""); + PrintAndLog("Password NOT found. Last tried: [%08x]", --i); + } + + free(keyBlock); return 0; } - // note length of data returned is different for different chips. // some return all page 1 (64 bits) and others return just that block (32 bits) // unfortunately the 64 bits makes this more likely to get a false positive... @@ -1987,7 +1779,6 @@ int CmdT55xxDetectPage1(const char *Cmd){ static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"bruteforce",CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, - {"bruteforcedl",CmdT55xxBruteForce_downlink,0, "r [i <*.dic>] [e ] Simple bruteforce attack to find password"}, {"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, {"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."}, {"p1detect", CmdT55xxDetectPage1,1, "[1] Try detecting if this is a t55xx tag by reading page 1"}, diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index 1ba4dca4..4541bd3a 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -74,7 +74,6 @@ void Set_t55xx_Config(t55xx_conf_block_t conf); extern int CmdLFT55XX(const char *Cmd); extern int CmdT55xxBruteForce(const char *Cmd); -extern int CmdT55xxBruteForce_downlink(const char *Cmd); extern int CmdT55xxSetConfig(const char *Cmd); extern int CmdT55xxReadBlock(const char *Cmd); extern int CmdT55xxWriteBlock(const char *Cmd); From 4be71814b4a7f5647a01d55882664c5889f4e605 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sat, 22 Jun 2019 15:26:56 +1000 Subject: [PATCH 05/18] T55xx Downlink - Updates Improved code. --- CHANGELOG.md | 28 ++ armsrc/lfops.c | 799 ++++++++++++++++---------------------------- client/cmdlft55xx.c | 57 ++-- 3 files changed, 341 insertions(+), 543 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 399f87f9..55f1d1f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,34 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] +## T55xx Downlink Protocol - 22 Jun 2019 + +# armsrc/lfops + +### Added +- Added typedef T55xx_Timing to hold downlink timings. +- Added Timing Records for long leading reference (llr), Leading 0 and 1 of 4 +- Added some constant defines for code readability +- Added function T55xx_SetBits to build a bit stream for writing to T55xx +- Added function T55xx_SendCMD to build the bit stream and send to T55xx + +### Changed +- Converted Timing for default/fixed bit to T55xx_Timing +- Updated T55xxWriteBit (and calls) to support all downlink protocols +- Updated T55xxWriteBlock to call T55xx_SendCMD (removed local bit writes) +- Updated T55xxReadBlock to call T55xx_SendCMD (removed local bit writes) + +# client/cmdlft55xx + +### Added +- Added function T55xx_Print_DownlinkMode to print downlink mode information when uesd + +### Changes +- Added downlink mode options r [ 0 (or missing) default/fixed bit, 1 long leading, leading 0 and 1 of 4 ] +- Added r 4 option to bruteforce to try all downlink modes (0,1,2 and 3) +- Updated help messages for each support functions t55xx_read, t55xx_write, t55_detect, t55xx_bruteforce + + ### Changed - Changed hf mfp security. Now it works in all the modes. (drHatson) - `hf fido` - show/check DER certificate and signatures (Merlok) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 112a1173..c1f32f87 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1198,13 +1198,90 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) * and enlarge the gap ones. * Q5 tags seems to have issues when these values changes. */ + /* + // Original Timings for reference + #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 15*8 -// Long Leading Reference -#define Reference_llr (136+18)*8 // Needs to be WRITR_0 + 136 clocks. +*/ + +// Structure to hold Timing values. In future will be simplier to add user changable timings. +typedef struct { + uint16_t START_GAP; + uint16_t WRITE_GAP; + uint16_t WRITE_0; + uint16_t WRITE_1; + uint16_t WRITE_2; + uint16_t WRITE_3; + uint16_t READ_GAP; +} T55xx_Timing; + +/* + T5577 Timeing from datasheet for reference + + Fixed bit length + ---------------- + Normal Down Link Fast Downlink + Min Typ Max Min Typ Max + Start gap 8 15 50 8 15 50 + Write gap 8 10 20 8 10 20 + 0 data 16 24 32 8 12 16 + 1 data 48 56 64 24 28 32 + + + Long Leading Reference + ---------------------- + Normal Down Link Fast Downlink + Min Typ Max Min Typ Max + Start gap 8 10 50 8 10 50 + Write gap 8 10 20 8 10 20 + Reference(r) 152 160 168 140 144 148 + 136 + 0 data 132 + 0 data + 0 data r - 143 r - 136 r - 128 r - 135 r - 132 r - 124 + 1 data r - 111 r - 104 r - 96 r - 119 r - 116 r - 112 + + + Leading Zero Reference + ---------------------- + Normal Down Link Fast Downlink + Min Typ Max Min Typ Max + Start gap 8 10 50 8 10 50 + Write gap 8 10 20 8 10 20 + Reference(r) 12 - 72 8 - 68 + 0 data r - 7 r r + 8 r - 3 r r + 4 + 1 data r + 9 r + 16 r + 24 r + 5 r + 8 r + 12 + + + 1 of 4 Coding + ------------- + Normal Down Link Fast Downlink + Min Typ Max Min Typ Max + Start gap 8 10 50 8 10 50 + Write gap 8 10 20 8 10 20 + Reference(r) 8 - 68 12 - 72 + 00 data r - 7 r r + 8 r - 3 r r + 4 + 01 data r + 9 r + 16 r + 24 r + 5 r + 8 r + 12 + 10 data r + 25 r + 32 r + 40 r + 13 r + 16 r + 20 + 11 data r + 41 r + 48 r + 56 r + 21 r + 24 r + 28 + +*/ + +// Set Initial/Default Values. Note: *8 can occure when used. This should keep things simplier here. +T55xx_Timing T55xx_Timing_FixedBit = { 31 * 8 , 20 * 8 , 18 * 8 , 50 * 8 , 0 , 0 , 15 * 8 }; +T55xx_Timing T55xx_Timing_LLR = { 31 * 8 , 20 * 8 , 18 * 8 , 50 * 8 , 0 , 0 , 15 * 8 }; +T55xx_Timing T55xx_Timing_Leading0 = { 31 * 8 , 20 * 8 , 18 * 8 , 40 * 8 , 0 , 0 , 15 * 8 }; +T55xx_Timing T55xx_Timing_1of4 = { 31 * 8 , 20 * 8 , 18 * 8 , 34 * 8 , 50 * 8 , 66 * 8 , 15 * 8 }; + + +// Some defines for readability +#define T55xx_LongLeadingReference 4 // Value to tell Write Bit to send long reference +#define T55xx_DLMode_Fixed 0 // Default Mode +#define T55xx_DLMode_LLR 1 // Long Leading Reference +#define T55xx_DLMode_Leading0 2 // Leading Zero +#define T55xx_DLMode_1of4 3 // 1 of 4 void TurnReadLFOn(int delay) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); @@ -1213,272 +1290,59 @@ void TurnReadLFOn(int delay) { } // Write one bit to card -void T55xxWriteBit(int bit) { - if (!bit) - TurnReadLFOn(WRITE_0); - else - TurnReadLFOn(WRITE_1); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(WRITE_GAP); -} +void T55xxWriteBit(int bit, T55xx_Timing *Timings) { -void T55xxWrite_LLR (void) -{ - TurnReadLFOn (Reference_llr); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(WRITE_GAP); -} + // If bit = 4 Send Long Leading Reference which is 138 + WRITE_0 -#define START_GAPlz 31*8 -#define WRITE_GAPlz 20*8 -#define WRITElz_0 18*8 -#define WRITElz_1 40*8 -#define READ_GAP 15*8 - -void T55xxWriteBit_Leading0(int bit) { - if (!bit) - TurnReadLFOn(WRITElz_0); - else - TurnReadLFOn(WRITElz_1); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(WRITE_GAPlz); -// WaitUS(160); -} - -#define START_GAP1of4 31*8 // SPEC: 1*8 to 50*8 - typ 10*8 (or 15fc) -#define WRITE_GAP1of4 20*8 // SPEC: 1*8 to 20*8 - typ 10*8 (or 10fc) -// 00 = reference // 8 * 8 - - 68 * 8 -#define WRITE1of4_00 18*8 // SPEC: 8*8 to 68*8 - typ 24*8 (or 24fc) -#define WRITE1of4_01 34*8 // SPEC: dref+9 - dref+16 - dref+24 -#define WRITE1of4_10 50*8 // SPEC: dref+25 - dref+32 - dref+40 -#define WRITE1of4_11 66*8 // SPEC: dref+41 - dref+48 - dref+56 -#define READ1of4_GAP 15*8 - -void T55xxWriteBit_1of4(int bits) { - - switch (bits) - { - case 0 : TurnReadLFOn(WRITE1of4_00); break; - case 1 : TurnReadLFOn(WRITE1of4_01); break; - case 2 : TurnReadLFOn(WRITE1of4_10); break; - case 3 : TurnReadLFOn(WRITE1of4_11); break; - default: - TurnReadLFOn(WRITE1of4_00); + switch (bit){ + case 0 : TurnReadLFOn(Timings->WRITE_0); break; // Send bit 0/00 + case 1 : TurnReadLFOn(Timings->WRITE_1); break; // Send bit 1/01 + case 2 : TurnReadLFOn(Timings->WRITE_2); break; // Send bits 10 + case 3 : TurnReadLFOn(Timings->WRITE_3); break; // Send bits 11 + case 4 : TurnReadLFOn(Timings->WRITE_0 + (136 * 8)); break; // Send Long Leading Reference } - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(WRITE_GAP1of4); -// WaitUS(160); + WaitUS(Timings->WRITE_GAP); } -void T55xxWriteBlockExt_Leading0 (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; - bool testMode = arg & 0x4; - uint32_t i = 0; - - // Set up FPGA, 125kHz - LFSetupFPGAForADC(95, true); - StartTicks(); - // make sure tag is fully powered up... - WaitMS(5); - // Trigger T55x7 in mode. - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); +// Function to abstract an Arbitrary length byte array to store bit pattern. +// bit_array - Array to hold data/bit pattern +// start_offset - bit location to start storing new bits. +// data - upto 32 bits of data to store +// num_bits - how many bits (low x bits of data) Max 32 bits at a time +// max_len - how many bytes can the bit_array hold (ensure no buffer overflow) +// returns "Next" bit offset / bits stored (for next store) +int T55xx_SetBits (uint8_t *bit_array, int start_offset, uint32_t data , int num_bits, int max_len) +{ + int bit,byte_idx, bit_idx; + int offset; + int NextOffset = start_offset; - WaitUS(START_GAPlz); - - - /* - 0 : Leading Zero - 11 : Opcode - 00 : Fixed 00 if protected write (i.e. have password) - <32 bit Password> - 0 : Lock Bit - <32 bit data> - <3 bit addr> + // Check if data will fit. + if ((start_offset + num_bits) <= (max_len*8)) { + + // Loop through the data and store + for (offset = (num_bits-1); offset >= 0; offset--) { + + bit = (data >> offset) & 1; // Get data bit value (0/1) + byte_idx = (NextOffset / 8); // Get Array Byte Index to Store + bit_idx = NextOffset - (byte_idx * 8); // Get Bit Index to set/clr - Standard Write : 0 1p L <32 data bits> <3 bit addr> - 0 10 0 00000000000000000000000000000000 001 - Protected Write: 0 1p 00 <32 pwd bits> L <32 data bits> <3 bit addr> - 0 10 00 00000000000000000000000000000000 0 00000000000000000000000000000000 001 - Wake Up 0 10 00 <32 pwd bits> - Protected Read 0 1p 00 <32 pwd bits> 0 <3 bit addr> - Standard Read 0 1p 0 <3 bit addr> - Page 0/1 read 0 1p - Reset 0 00 - - */ - T55xxWriteBit_Leading0 (0); //T55xxWriteBit(0); - - - if (testMode) Dbprintf("TestMODE"); - // Std Opcode 10 - T55xxWriteBit_Leading0 (testMode ? 0 : 1); - T55xxWriteBit_Leading0 (testMode ? 1 : Page); //Page 0 - - - if (PwdMode) { - // Leading zero - insert two fixed 00 between opcode and password - T55xxWriteBit_Leading0 (0); - T55xxWriteBit_Leading0 (0); - // Send Pwd - for (i = 0x80000000; i != 0; i >>= 1) - T55xxWriteBit_Leading0 (Pwd & i); - } - - // Send Lock bit - T55xxWriteBit_Leading0 (0); + // If set (1) we OR, if clear (0) we AND with inverse + // Dbprintf ("Add Bit : %d at byte %d bit %d",bit,byte_idx,bit_idx); + if (bit == 1) + bit_array[byte_idx] |= (1 << bit_idx); // Set the bit to 1 + + else + bit_array[byte_idx] &= (0xff ^ (1 << bit_idx)); // Set the bit to 0 (clr) - // Send Data - for (i = 0x80000000; i != 0; i >>= 1) - T55xxWriteBit_Leading0(Data & i); - - // Send Block number - for (i = 0x04; i != 0; i >>= 1) - T55xxWriteBit_Leading0 (Block & i); - - // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550, - // so wait a little more) - // "there is a clock delay before programming" - // - programming takes ~5.6ms for t5577 ~18ms for E5550 or t5567 - // so we should wait 1 clock + 5.6ms then read response? - // but we need to know we are dealing with t5577 vs t5567 vs e5550 (or q5) marshmellow... - if (testMode) { - //TESTMODE TIMING TESTS: - // <566us does nothing - // 566-568 switches between wiping to 0s and doing nothing - // 5184 wipes and allows 1 block to be programmed. - // indefinite power on wipes and then programs all blocks with bitshifted data sent. - TurnReadLFOn(5184); - - } else { - 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 for - // modulation clock an other details to demod the response... - // response should be (for t55x7) a 0 bit then (ST if on) - // block data written in on repeat until reset. - - //DoPartialAcquisition(20, true, 12000); - } - - // turn field off - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_A_OFF(); - -} -void T55xxWriteBlockExt_1of4 (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; - bool testMode = arg & 0x4; - int bitpos; - uint8_t bits; - - // Set up FPGA, 125kHz - LFSetupFPGAForADC(95, true); - StartTicks(); - // make sure tag is fully powered up... - WaitMS(5); - // Trigger T55x7 in mode. - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - - - WaitUS(START_GAP1of4); - - - /* - 00 : 1 if 4 - 11 : Opcode - 00 : Fixed 00 if protected write (i.e. have password) - <32 bit Password> - 0 : Lock Bit - <32 bit data> - <3 bit addr> - - Standard Write : 00 1p L <32 data bits> <3 bit addr> - 00 10 0 00000000000000000000000000000000 001 - Protected Write: 00 1p 00 <32 pwd bits> L <32 data bits> <3 bit addr> - 00 10 00 00000000000000000000000000000000 0 00000000000000000000000000000000 001 - Wake Up 00 10 00 <32 pwd bits> - Protected Read 00 1p 00 <32 pwd bits> 0 <3 bit addr> - Standard Read 00 1p 0 <3 bit addr> - Page 0/1 read 00 1p - Reset 00 00 - - */ - T55xxWriteBit_1of4 (0); //Send Reference 00 - - if (testMode) Dbprintf("TestMODE"); - // Std Opcode 10 - if (testMode) bits = 0; else bits = 2; // 0x or 1x - if (testMode) bits |= 1; else bits += (Page); // x0 or x1 - T55xxWriteBit_1of4 (bits); - - if (PwdMode) { - // 1 of 4 00 - insert two fixed 00 between opcode and password - T55xxWriteBit_1of4 (0); // 00 - - // Send Pwd - for (bitpos = 31; bitpos >= 1; bitpos -= 2) { // 2 bits at a time - bits = (((Pwd >> bitpos) & 1) << 1) + ((Pwd >> (bitpos-1)) & 1); - T55xxWriteBit_1of4 (bits); - } - } - - // Send Lock bit - bits = 0; // Add lock bit (Not Set) to the next 2 bits - - // Send Data - offset by 1 bit due to lock bit - // 2 bits at a time - Initilised with lock bit above - for (bitpos = 31; bitpos >= 1; bitpos -= 2) { - bits |= ((Data >> bitpos) & 1); // Add Low bit - T55xxWriteBit_1of4 (bits); - bits = ((Data >> (bitpos-1)) & 1) << 1; // Set next high bit - } - - // Send Block number - bits |= ((Block >> 2) & 1); - T55xxWriteBit_1of4 (bits); - bits = (Block & 3);// 1) & 2) + (Block & 1); - T55xxWriteBit_1of4 (bits); - - // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550, - // so wait a little more) - // "there is a clock delay before programming" - // - programming takes ~5.6ms for t5577 ~18ms for E5550 or t5567 - // so we should wait 1 clock + 5.6ms then read response? - // but we need to know we are dealing with t5577 vs t5567 vs e5550 (or q5) marshmellow... - if (testMode) { - //TESTMODE TIMING TESTS: - // <566us does nothing - // 566-568 switches between wiping to 0s and doing nothing - // 5184 wipes and allows 1 block to be programmed. - // indefinite power on wipes and then programs all blocks with bitshifted data sent. - TurnReadLFOn(5184); - - } else { - 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 for - // modulation clock an other details to demod the response... - // response should be (for t55x7) a 0 bit then (ST if on) - // block data written in on repeat until reset. - - //DoPartialAcquisition(20, true, 12000); - } - - // turn field off - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_A_OFF(); - + NextOffset++; + } + } + else + Dbprintf ("Too Many Bits to fit into bit buffer"); + return NextOffset; } // Send T5577 reset command then read stream (see if we can identify the start of the stream) @@ -1495,13 +1359,13 @@ void T55xxResetRead(void) { // Trigger T55x7 in mode. FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(START_GAP); + WaitUS(T55xx_Timing_FixedBit.START_GAP); // reset tag - op code 00 - T55xxWriteBit(0); - T55xxWriteBit(0); + T55xxWriteBit(0,&T55xx_Timing_FixedBit); + T55xxWriteBit(0,&T55xx_Timing_FixedBit); - TurnReadLFOn(READ_GAP); + TurnReadLFOn(T55xx_Timing_FixedBit.READ_GAP); // Acquisition DoPartialAcquisition(0, true, BigBuf_max_traceLen(), 0); @@ -1512,18 +1376,85 @@ void T55xxResetRead(void) { LED_A_OFF(); } -// Write one card block in page 0, no lock -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; - bool testMode = arg & 0x4; - uint32_t i = 0; - uint8_t downlink_mode; +// Send one downlink command to the card +void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { //, bool read_cmd) {//, struct T55xx_Timing *Timing) { - downlink_mode = (arg >> 3) & 0x03; + /* + arg bits + xxxxxxx1 0x01 PwdMode + xxxxxx1x 0x02 Page + xxxxx1xx 0x04 testMode + xxx11xxx 0x18 downlink mode + xx1xxxxx 0x20 reg_readmode + x1xxxxxx 0x40 called for a read, so no data packet + + */ + bool PwdMode = ((arg & 0x01) == 0x01); + uint8_t Page = (arg & 0x02) >> 1; + bool testMode = ((arg & 0x04) == 0x04); + uint8_t downlink_mode = (arg >> 3) & 0x03;; + bool reg_readmode = ((arg & 0x20) == 0x20); + bool read_cmd = ((arg & 0x40) == 0x40); + + int i = 0; + uint8_t BitStream[10]; // Max Downlink Command size ~75 bits, so 10 bytes (80 bits) + uint8_t BitStreamLen; + int byte_idx, bit_idx; + T55xx_Timing *Timing; + // Assigning Downlink Timeing for write + switch (downlink_mode) + { + case T55xx_DLMode_Fixed : Timing = &T55xx_Timing_FixedBit; break; + case T55xx_DLMode_LLR : Timing = &T55xx_Timing_LLR; break; + case T55xx_DLMode_Leading0 : Timing = &T55xx_Timing_Leading0; break; + case T55xx_DLMode_1of4 : Timing = &T55xx_Timing_1of4; break; + default: + Timing = &T55xx_Timing_FixedBit; + } + + // Build Bit Stream to send. + memset (BitStream,0x00,sizeof(BitStream)); + + BitStreamLen = 0; + + // Add Leading 0 and 1 of 4 reference bit + if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); + + // Add extra reference 0 for 1 of 4 + if (downlink_mode == T55xx_DLMode_1of4) + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); + + // Add Opcode + if (testMode) Dbprintf("TestMODE"); + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 0 : 1 , 1,sizeof(BitStream)); + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 1 : Page , 1,sizeof(BitStream)); + + if (PwdMode) { + + // Leading 0 and 1 of 4 00 fixed bits if passsword used + if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) { + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); + } + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Pwd, 32,sizeof(BitStream)); + + } + // Add Lock bit + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); + + // Add Data if a write command + if (!read_cmd) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Data, 32,sizeof(BitStream)); + + // Add Address + if (!reg_readmode) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Block, 3,sizeof(BitStream)); + + + + // Send Bits to T55xx + // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); StartTicks(); @@ -1531,31 +1462,56 @@ void T55xxWriteBlockExt(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg WaitMS(5); // Trigger T55x7 in mode. FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(START_GAP); + WaitUS(Timing->START_GAP); - // Long Leading Reference, same as fixed/default just with leading reference - if (downlink_mode == 1) T55xxWrite_LLR (); - if (testMode) Dbprintf("TestMODE"); - // Std Opcode 10 - T55xxWriteBit(testMode ? 0 : 1); - T55xxWriteBit(testMode ? 1 : Page); //Page 0 + // If long leading 0 send long reference pulse + if (downlink_mode == T55xx_DLMode_LLR) + T55xxWriteBit (T55xx_LongLeadingReference,Timing); // Send Long Leading Start Reference - if (PwdMode) { - // Send Pwd - for (i = 0x80000000; i != 0; i >>= 1) - T55xxWriteBit(Pwd & i); + uint8_t SendBits; + + if (downlink_mode == T55xx_DLMode_1of4) { // 1 of 4 need to send 2 bits at a time + for (i = 0; i < BitStreamLen; i+=2) { + byte_idx = i / 8; + bit_idx = i - (byte_idx * 8); + SendBits = ((BitStream[byte_idx] >> bit_idx) & 1) << 1; + + byte_idx = (i+1) / 8; + bit_idx = (i+1) - (byte_idx * 8); + SendBits += (BitStream[byte_idx] >> bit_idx) & 1; + + T55xxWriteBit (SendBits,Timing); + } } - // Send Lock bit - T55xxWriteBit(0); + else { + for (i = 0; i < BitStreamLen; i++) { + byte_idx = i / 8; + bit_idx = i - (byte_idx * 8); + SendBits = (BitStream[byte_idx] >> bit_idx) & 1; + T55xxWriteBit (SendBits,Timing); + } + } + +} - // Send Data - for (i = 0x80000000; i != 0; i >>= 1) - T55xxWriteBit(Data & i); - - // Send Block number - for (i = 0x04; i != 0; i >>= 1) - T55xxWriteBit(Block & i); +// Write one card block in page 0, no lock +void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { + /* + arg bits + xxxxxxx1 0x01 PwdMode + xxxxxx1x 0x02 Page + xxxxx1xx 0x04 testMode + xxx11xxx 0x18 downlink mode + xx1xxxxx 0x20 reg_readmode + x1xxxxxx 0x40 called for a read, so no data packet + */ + + bool testMode = ((arg & 0x04) == 0x04); + arg &= (0xff ^ 0x40); // Called for a write, so ensure it is clear/0 + + LED_A_ON (); + T55xx_SendCMD (Data, Block, Pwd, arg) ;//, false); // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550, // so wait a little more) @@ -1584,86 +1540,43 @@ void T55xxWriteBlockExt(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg //DoPartialAcquisition(20, true, 12000); } - // turn field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - 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 arg) { -// arg 8 bit 00000000 -// 0000000x Password -// 000000x0 Page -// 00000x00 Test Mode -// 000xx000 (0x18) where xx : 00 - Normal Write, 01 - Long Leading Reference -// 10 - Leading 0, 11 - 1 of 4 - uint8_t downlink_mode; - - downlink_mode = (arg >> 3) & 0x03; - - switch (downlink_mode) - { - case 0 :// T55xxWriteBlockExt (Data, Block, Pwd, arg); break; - case 1 : // T55xxWrite_LLR (); - T55xxWriteBlockExt (Data, Block, Pwd, arg); - break; - case 2 : T55xxWriteBlockExt_Leading0 (Data, Block, Pwd, arg); break; - case 3 : T55xxWriteBlockExt_1of4 (Data, Block, Pwd, arg); break; - default: - T55xxWriteBlockExt (Data, Block, Pwd, arg); - } - cmd_send(CMD_ACK,0,0,0,0,0); + + LED_A_OFF (); } // Read one card block in page [page] -void T55xxReadBlockExt (uint16_t arg0, uint8_t Block, uint32_t Pwd) { +void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) {//, struct T55xx_Timing *Timing) { + LED_A_ON(); - bool PwdMode = arg0 & 0x1; - uint8_t Page = (arg0 & 0x2) >> 1; - uint32_t i = 0; - bool RegReadMode = (Block == 0xFF);//regular read mode - uint8_t downlink_mode; - - downlink_mode = (arg0 >> 3) & 0x03; - - //clear buffer now so it does not interfere with timing later - BigBuf_Clear_ext(false); + /* + arg bits + xxxxxxx1 0x01 PwdMode + xxxxxx1x 0x02 Page + xxxxx1xx 0x04 testMode + xxx11xxx 0x18 downlink mode + xx1xxxxx 0x20 reg_readmode + x1xxxxxx 0x40 called for a read, so no data packet + */ + + // Set Read Flag to ensure SendCMD does not add "data" to the packet + arg0 |= 0x40; + + + if (Block == 0xff) arg0 |= 0x20; + //make sure block is at max 7 Block &= 0x7; - - // Set up FPGA, 125kHz to power up the tag - LFSetupFPGAForADC(95, true); - StartTicks(); - // make sure tag is fully powered up... - WaitMS(5); - // Trigger T55x7 Direct Access Mode with start gap - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(START_GAP); - - // Long Leading Reference, same as fixed/default just with leading reference - if (downlink_mode == 1) T55xxWrite_LLR (); + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_ext(false); + + T55xx_SendCMD (0, Block, Pwd, arg0); //, true); + - // Opcode 1[page] - T55xxWriteBit(1); - T55xxWriteBit(Page); //Page 0 - - if (PwdMode){ - // Send Pwd - for (i = 0x80000000; i != 0; i >>= 1) - T55xxWriteBit(Pwd & i); - } - // Send a zero bit separation - T55xxWriteBit(0); - - // 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 // 137*8 seems to get to the start of data pretty well... // but we want to go past the start and let the repeating data settle in... @@ -1675,163 +1588,11 @@ void T55xxReadBlockExt (uint16_t arg0, uint8_t Block, uint32_t Pwd) { // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off -// cmd_send(CMD_ACK,0,0,0,0,0); + cmd_send(CMD_ACK,0,0,0,0,0); + LED_A_OFF(); } -void T55xxReadBlockExt_Leading0 (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; - bool RegReadMode = (Block == 0xFF);//regular read mode - - //clear buffer now so it does not interfere with timing later - BigBuf_Clear_ext(false); - - //make sure block is at max 7 - Block &= 0x7; - - // Set up FPGA, 125kHz to power up the tag - LFSetupFPGAForADC(95, true); - StartTicks(); - // make sure tag is fully powered up... - WaitMS(5); - // Trigger T55x7 Direct Access Mode with start gap - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(START_GAPlz); - - T55xxWriteBit_Leading0 (0); - - // Opcode 1[page] - T55xxWriteBit_Leading0 (1); - T55xxWriteBit_Leading0 (Page); //Page 0 - - if (PwdMode){ - // Send Pwd - T55xxWriteBit_Leading0 (0); - T55xxWriteBit_Leading0 (0); - - for (i = 0x80000000; i != 0; i >>= 1) - T55xxWriteBit_Leading0 (Pwd & i); - } - // Send a zero bit separation - T55xxWriteBit_Leading0(0); - - // Send Block number (if direct access mode) - if (!RegReadMode) - for (i = 0x04; i != 0; i >>= 1) - T55xxWriteBit_Leading0(Block & i); - - // Turn field on to read the response - // 137*8 seems to get to the start of data pretty well... - // but we want to go past the start and let the repeating data settle in... - TurnReadLFOn(210*8); - - // Acquisition - // Now do the acquisition - DoPartialAcquisition(0, true, 12000, 0); - - // Turn the field off - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off -// cmd_send(CMD_ACK,0,0,0,0,0); - LED_A_OFF(); -} - -void T55xxReadBlockExt_1of4 (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; - bool RegReadMode = (Block == 0xFF);//regular read mode - uint8_t bits; - int bitpos; - - //clear buffer now so it does not interfere with timing later - BigBuf_Clear_ext(false); - - //make sure block is at max 7 - Block &= 0x7; - - // Set up FPGA, 125kHz to power up the tag - LFSetupFPGAForADC(95, true); - StartTicks(); - // make sure tag is fully powered up... - WaitMS(5); - // Trigger T55x7 Direct Access Mode with start gap - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(START_GAP1of4); - - T55xxWriteBit_1of4 (0); // 2 Bit 00 leading reference - - // Opcode 1[page] - bits = 2 + Page; - T55xxWriteBit_1of4 (bits); - - if (PwdMode) { - // 1 of 4 00 - insert two fixed 00 between opcode and password - T55xxWriteBit_1of4 (0); // 00 - - // Send Pwd - for (bitpos = 31; bitpos >= 1; bitpos -= 2) { // 2 bits at a time - bits = (((Pwd >> bitpos) & 1) << 1) + ((Pwd >> (bitpos-1)) & 1); - T55xxWriteBit_1of4 (bits); - } - } - - // Send Lock bit - bits = 0; // Add lock bit (Not Set) to the next 2 bits - - // Send Block number (if direct access mode) - if (!RegReadMode){ - // Send Block number - bits += ((Block >> 2) & 1); - T55xxWriteBit_1of4 (bits); - bits = (Block & 3); // + (Block & 1); - T55xxWriteBit_1of4 (bits); - } - - // Turn field on to read the response - // 137*8 seems to get to the start of data pretty well... - // but we want to go past the start and let the repeating data settle in... - TurnReadLFOn(210*8); - - // Acquisition - // Now do the acquisition - DoPartialAcquisition(0, true, 12000, 0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off -// cmd_send(CMD_ACK,0,0,0,0,0); - LED_A_OFF(); -} - -void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) { -// arg0 16 bit 00000000 -// 0000000x Password -// 000000x0 Page -// 00000x00 -// 000xx000 (0x18) where xx : 00 - Normal Write, 01 - Long Leading Reference -// 10 - Leading 0, 11 - 1 of 4 - uint8_t downlink_mode; - - downlink_mode = (arg0 >> 3) & 0x03; - - // downlink mode id set to match the 2 bit as per Tech Sheet - switch (downlink_mode) - { - case 0 :// T55xxReadBlockExt (arg0, Block, Pwd); break; - case 1 : // T55xxWrite_LLR (); - T55xxReadBlockExt (arg0, Block, Pwd); - break; - case 2 : T55xxReadBlockExt_Leading0 (arg0, Block, Pwd); break; - case 3 : T55xxReadBlockExt_1of4 (arg0, Block, Pwd); break; - default: - T55xxReadBlockExt (arg0, Block, Pwd) ; - } - -// T55xxReadBlockExt (arg0, Block, Pwd) ; - cmd_send(CMD_ACK,0,0,0,0,0); -} - void T55xxWakeUp(uint32_t Pwd){ LED_B_ON(); uint32_t i = 0; @@ -1844,15 +1605,16 @@ void T55xxWakeUp(uint32_t Pwd){ // Trigger T55x7 Direct Access Mode FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(START_GAP); + WaitUS(T55xx_Timing_FixedBit.START_GAP); // Opcode 10 - T55xxWriteBit(1); - T55xxWriteBit(0); //Page 0 + T55xxWriteBit(1,&T55xx_Timing_FixedBit); + T55xxWriteBit(0,&T55xx_Timing_FixedBit); //Page 0 // Send Pwd + for (i = 0x80000000; i != 0; i >>= 1) - T55xxWriteBit(Pwd & i); + T55xxWriteBit(Pwd & i,&T55xx_Timing_FixedBit); // Turn and leave field on to let the begin repeating transmission TurnReadLFOn(20*1000); @@ -1863,7 +1625,8 @@ void T55xxWakeUp(uint32_t Pwd){ 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--) { - T55xxWriteBlockExt(blockdata[i-1],i-1,0,0); + T55xxWriteBlock(blockdata[i-1],i-1,0,0);//,false); //,&T55xx_Timing_FixedBit); + // T55xx_SendCMD (blockdata[i-1],i-1,0,0);//,false); //,&T55xx_Timing_FixedBit); } } diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index ed980f9b..c64e5ef2 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -311,13 +311,13 @@ int CmdT55xxSetConfig(const char *Cmd) { } // No args - if (cmdp == 0) return printConfiguration( config ); + if (cmdp == 0) return printConfiguration( config); //Validations if (errors) return usage_t55xx_config(); config.block0 = 0; - return printConfiguration ( config ); + return printConfiguration ( config); } int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32_t password, uint8_t downlink_mode){ @@ -476,6 +476,25 @@ bool DecodeT5555TraceBlock() { return (bool) ASKDemod("64 0 1", false, false, 1); } +void T55xx_Print_DownlinkMode (uint8_t downlink_mode) +{ + char Msg[80]; + sprintf (Msg,"Downlink Mode used : "); + + switch (downlink_mode) { + case 0 : strcat (Msg,"default/fixed bit length"); break; + case 1 : strcat (Msg,"long leading reference (r 1)"); break; + case 2 : strcat (Msg,"leading zero reference (r 2)"); break; + case 3 : strcat (Msg,"1 of 4 coding reference (r 3)"); break; + default : + strcat (Msg,"default/fixed bit length"); break; + + } + + PrintAndLog (Msg); + +} + int CmdT55xxDetect(const char *Cmd){ bool errors = false; bool useGB = false; @@ -522,13 +541,8 @@ int CmdT55xxDetect(const char *Cmd){ if ( !tryDetectModulation() ) PrintAndLog("Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'"); else { - // Add downlink mode to reference. - switch (downlink_mode) { - case 0 : PrintAndLog ("Downlink : r 0 - default/fixed bit length"); break; - case 1 : PrintAndLog ("Downlink : r 1 - long leading reference"); break; - case 2 : PrintAndLog ("Downlink : r 2 - leading zero reference"); break; - case 3 : PrintAndLog ("Downlink : r 3 - 1 of 4 coding reference"); break; - } + // Add downlink mode for reference. + T55xx_Print_DownlinkMode (downlink_mode); } return 1; } @@ -681,7 +695,8 @@ bool tryDetectModulation(){ config.block0 = tests[0].block0; config.Q5 = tests[0].Q5; config.ST = tests[0].ST; - printConfiguration( config ); + + printConfiguration( config); return true; } @@ -689,7 +704,7 @@ bool tryDetectModulation(){ PrintAndLog("Found [%d] possible matches for modulation.",hits); for(int i=0; i 3 or set to 0, so loop from 0 - 3 for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++){ if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd, dl_mode)) { - PrintAndLog("Aquireing data from device failed. Quitting"); + PrintAndLog("Acquiring data from device failed. Quitting"); free(keyBlock); return 0; } @@ -1551,12 +1566,9 @@ int CmdT55xxBruteForce(const char *Cmd) { if ( found ) { PrintAndLog("Found valid password: [%08X]", testpwd); free(keyBlock); - switch (dl_mode) { - case 0 : PrintAndLog ("Downlink : r 0 - default/fixed bit length"); break; - case 1 : PrintAndLog ("Downlink : r 1 - long leading reference"); break; - case 2 : PrintAndLog ("Downlink : r 2 - leading zero reference"); break; - case 3 : PrintAndLog ("Downlink : r 3 - 1 of 4 coding reference"); break; - } + + T55xx_Print_DownlinkMode (dl_mode); + return 0; } if (!try_all_dl_modes) // Exit loop if not trying all downlink modes @@ -1597,7 +1609,7 @@ int CmdT55xxBruteForce(const char *Cmd) { // donwlink_mode will = 0 if > 3 or set to 0, so loop from 0 - 3 for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++){ if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, i,dl_mode)) { - PrintAndLog("Aquireing data from device failed. Quitting"); + PrintAndLog("Acquiring data from device failed. Quitting"); free(keyBlock); return 0; } @@ -1613,12 +1625,7 @@ int CmdT55xxBruteForce(const char *Cmd) { if (found){ PrintAndLog("Found valid password: [%08x]", i); - switch (dl_mode) { - case 0 : PrintAndLog ("Downlink : r 0 - default/fixed bit length"); break; - case 1 : PrintAndLog ("Downlink : r 1 - long leading reference"); break; - case 2 : PrintAndLog ("Downlink : r 2 - leading Zero reference"); break; - case 3 : PrintAndLog ("Downlink : r 3 - 1 of 4 coding reference"); break; - } + T55xx_Print_DownlinkMode (downlink_mode); } else{ PrintAndLog(""); From 99c52f9d85cf952d6a13dbd0be35cb6be1f50cdf Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sun, 23 Jun 2019 22:23:08 +1000 Subject: [PATCH 06/18] Update CHANGELOG.md Change Log Update --- CHANGELOG.md | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55f1d1f9..19a20557 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,33 +4,11 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] -## T55xx Downlink Protocol - 22 Jun 2019 - -# armsrc/lfops - +## T55xx Downlink Protocol ### Added -- Added typedef T55xx_Timing to hold downlink timings. -- Added Timing Records for long leading reference (llr), Leading 0 and 1 of 4 -- Added some constant defines for code readability -- Added function T55xx_SetBits to build a bit stream for writing to T55xx -- Added function T55xx_SendCMD to build the bit stream and send to T55xx - -### Changed -- Converted Timing for default/fixed bit to T55xx_Timing -- Updated T55xxWriteBit (and calls) to support all downlink protocols -- Updated T55xxWriteBlock to call T55xx_SendCMD (removed local bit writes) -- Updated T55xxReadBlock to call T55xx_SendCMD (removed local bit writes) - -# client/cmdlft55xx - -### Added -- Added function T55xx_Print_DownlinkMode to print downlink mode information when uesd - -### Changes -- Added downlink mode options r [ 0 (or missing) default/fixed bit, 1 long leading, leading 0 and 1 of 4 ] -- Added r 4 option to bruteforce to try all downlink modes (0,1,2 and 3) -- Updated help messages for each support functions t55xx_read, t55xx_write, t55_detect, t55xx_bruteforce - +- Added downlink reference mode option r [ 0 - (or missing) default/fixed bit, 1 - long leading, 2 - leading 0 and 3 - 1 of 4 ] +- Added special option r 4 to bruteforce, to try all downlink modes (0,1,2 and 3) for each password +- Support added to lf t55xx detect, read, write, bruteforce ### Changed - Changed hf mfp security. Now it works in all the modes. (drHatson) From d3521ae609658fa00955c8fd57f69eb84ce7a7cd Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Mon, 24 Jun 2019 08:42:57 +0200 Subject: [PATCH 07/18] Update CHANGELOG.md --- CHANGELOG.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19a20557..9439399a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,6 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] -## T55xx Downlink Protocol -### Added -- Added downlink reference mode option r [ 0 - (or missing) default/fixed bit, 1 - long leading, 2 - leading 0 and 3 - 1 of 4 ] -- Added special option r 4 to bruteforce, to try all downlink modes (0,1,2 and 3) for each password -- Support added to lf t55xx detect, read, write, bruteforce - ### Changed - Changed hf mfp security. Now it works in all the modes. (drHatson) - `hf fido` - show/check DER certificate and signatures (Merlok) @@ -39,6 +33,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added Mifare Mini, Mifare 2K and 4K support to `hf mf sim` (piwi) - Added Legic detection to `hf search` (dnet) - Added Home (Pos1) and End key bindings to the plot GUI (based on @mcd1992) +- Added downlink reference mode option r [ 0 - (or missing) default/fixed bit, 1 - long leading, 2 - leading 0 and 3 - 1 of 4 ] to `lf t55xx detect`, `lf t55xx read`, `lf t55xx write`, and `lf t55xx bruteforce` +- Added special option `r 4` to bruteforce, to try all downlink modes (0,1,2 and 3) for each password + ## [v3.1.0][2018-10-10] From e220fc63aaa4f61ca2f91216c4420c18612dd544 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Tue, 25 Jun 2019 18:56:32 +1000 Subject: [PATCH 08/18] Update lfops.c --- armsrc/lfops.c | 50 +------------------------------------------------- 1 file changed, 1 insertion(+), 49 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index c1f32f87..c56d08f9 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1219,55 +1219,7 @@ typedef struct { uint16_t READ_GAP; } T55xx_Timing; -/* - T5577 Timeing from datasheet for reference - - Fixed bit length - ---------------- - Normal Down Link Fast Downlink - Min Typ Max Min Typ Max - Start gap 8 15 50 8 15 50 - Write gap 8 10 20 8 10 20 - 0 data 16 24 32 8 12 16 - 1 data 48 56 64 24 28 32 - - - Long Leading Reference - ---------------------- - Normal Down Link Fast Downlink - Min Typ Max Min Typ Max - Start gap 8 10 50 8 10 50 - Write gap 8 10 20 8 10 20 - Reference(r) 152 160 168 140 144 148 - 136 + 0 data 132 + 0 data - 0 data r - 143 r - 136 r - 128 r - 135 r - 132 r - 124 - 1 data r - 111 r - 104 r - 96 r - 119 r - 116 r - 112 - - - Leading Zero Reference - ---------------------- - Normal Down Link Fast Downlink - Min Typ Max Min Typ Max - Start gap 8 10 50 8 10 50 - Write gap 8 10 20 8 10 20 - Reference(r) 12 - 72 8 - 68 - 0 data r - 7 r r + 8 r - 3 r r + 4 - 1 data r + 9 r + 16 r + 24 r + 5 r + 8 r + 12 - - - 1 of 4 Coding - ------------- - Normal Down Link Fast Downlink - Min Typ Max Min Typ Max - Start gap 8 10 50 8 10 50 - Write gap 8 10 20 8 10 20 - Reference(r) 8 - 68 12 - 72 - 00 data r - 7 r r + 8 r - 3 r r + 4 - 01 data r + 9 r + 16 r + 24 r + 5 r + 8 r + 12 - 10 data r + 25 r + 32 r + 40 r + 13 r + 16 r + 20 - 11 data r + 41 r + 48 r + 56 r + 21 r + 24 r + 28 - -*/ + // Set Initial/Default Values. Note: *8 can occure when used. This should keep things simplier here. T55xx_Timing T55xx_Timing_FixedBit = { 31 * 8 , 20 * 8 , 18 * 8 , 50 * 8 , 0 , 0 , 15 * 8 }; From 50764caadcf78a3657ca014d4710fd2521dbd534 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Tue, 25 Jun 2019 19:28:06 +1000 Subject: [PATCH 09/18] Update lfops.c --- armsrc/lfops.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index efa75652..819653f0 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1206,8 +1206,8 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) #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 -======= +*/ /* Q5 timing datasheet: * Type | MIN | Typical | Max | * Start_Gap | 10*8 | ? | 50*8 | @@ -1240,7 +1240,7 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) * Write_0 Fast Mode | 8*8 | 12*8 | 16*8 | * Write_1 Fast Mode | 24*8 | 28*8 | 32*8 | */ - +/* //note startgap must be sent after tag has been powered up for more than 3ms (per T5557 ds) #define START_GAP 31*8 //31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (or 15fc) - T5557: 10*8 to 50*8 #define WRITE_GAP 20*8 //20*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (or 10fc) - T5557: 8*8 to 30*8 typ 50-150us @@ -1271,11 +1271,11 @@ T55xx_Timing T55xx_Timing_1of4 = { 31 * 8 , 20 * 8 , 18 * 8 , 34 * 8 , 5 // Some defines for readability -#define T55xx_LongLeadingReference 4 // Value to tell Write Bit to send long reference #define T55xx_DLMode_Fixed 0 // Default Mode #define T55xx_DLMode_LLR 1 // Long Leading Reference #define T55xx_DLMode_Leading0 2 // Leading Zero #define T55xx_DLMode_1of4 3 // 1 of 4 +#define T55xx_LongLeadingReference 4 // Value to tell Write Bit to send long reference void TurnReadLFOn(int delay) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); @@ -1324,7 +1324,7 @@ int T55xx_SetBits (uint8_t *bit_array, int start_offset, uint32_t data , in bit_idx = NextOffset - (byte_idx * 8); // Get Bit Index to set/clr // If set (1) we OR, if clear (0) we AND with inverse - // Dbprintf ("Add Bit : %d at byte %d bit %d",bit,byte_idx,bit_idx); + // Dbprintf ("Add Bit : %d at byte %d bit %d",bit,byte_idx,bit_idx); if (bit == 1) bit_array[byte_idx] |= (1 << bit_idx); // Set the bit to 1 From 5a9964829e8e6ef8382ed8b61dc71b1705a270f7 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Tue, 25 Jun 2019 20:46:10 +1000 Subject: [PATCH 10/18] Resolved Conflicts --- armsrc/lfops.c | 45 ++++++++++----------------------------------- 1 file changed, 10 insertions(+), 35 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 819653f0..19bf6555 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1307,32 +1307,17 @@ void T55xxWriteBit(int bit, T55xx_Timing *Timings) { // num_bits - how many bits (low x bits of data) Max 32 bits at a time // max_len - how many bytes can the bit_array hold (ensure no buffer overflow) // returns "Next" bit offset / bits stored (for next store) -int T55xx_SetBits (uint8_t *bit_array, int start_offset, uint32_t data , int num_bits, int max_len) +//int T55xx_SetBits (uint8_t *bit_array, int start_offset, uint32_t data , int num_bits, int max_len) +int T55xx_SetBits (bool *bit_array, int start_offset, uint32_t data , int num_bits, int max_len) { - int bit,byte_idx, bit_idx; int offset; int NextOffset = start_offset; // Check if data will fit. - if ((start_offset + num_bits) <= (max_len*8)) { - + if ((start_offset + num_bits) <= (max_len*8)) { // Loop through the data and store - for (offset = (num_bits-1); offset >= 0; offset--) { - - bit = (data >> offset) & 1; // Get data bit value (0/1) - byte_idx = (NextOffset / 8); // Get Array Byte Index to Store - bit_idx = NextOffset - (byte_idx * 8); // Get Bit Index to set/clr - - // If set (1) we OR, if clear (0) we AND with inverse - // Dbprintf ("Add Bit : %d at byte %d bit %d",bit,byte_idx,bit_idx); - if (bit == 1) - bit_array[byte_idx] |= (1 << bit_idx); // Set the bit to 1 - - else - bit_array[byte_idx] &= (0xff ^ (1 << bit_idx)); // Set the bit to 0 (clr) - - NextOffset++; - } + for (offset = (num_bits-1); offset >= 0; offset--) + bit_array[NextOffset++] = (data >> offset) & 1; } else Dbprintf ("Too Many Bits to fit into bit buffer"); @@ -1390,11 +1375,11 @@ void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { bool reg_readmode = ((arg & 0x20) == 0x20); bool read_cmd = ((arg & 0x40) == 0x40); - int i = 0; - uint8_t BitStream[10]; // Max Downlink Command size ~75 bits, so 10 bytes (80 bits) + int i = 0; + bool BitStream[100]; // Max Downlink Command size ~75 bits, so 10 bytes (80 bits) uint8_t BitStreamLen; - int byte_idx, bit_idx; T55xx_Timing *Timing; + uint8_t SendBits; // Assigning Downlink Timeing for write @@ -1463,26 +1448,16 @@ void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { if (downlink_mode == T55xx_DLMode_LLR) T55xxWriteBit (T55xx_LongLeadingReference,Timing); // Send Long Leading Start Reference - uint8_t SendBits; if (downlink_mode == T55xx_DLMode_1of4) { // 1 of 4 need to send 2 bits at a time for (i = 0; i < BitStreamLen; i+=2) { - byte_idx = i / 8; - bit_idx = i - (byte_idx * 8); - SendBits = ((BitStream[byte_idx] >> bit_idx) & 1) << 1; - - byte_idx = (i+1) / 8; - bit_idx = (i+1) - (byte_idx * 8); - SendBits += (BitStream[byte_idx] >> bit_idx) & 1; - + SendBits = (BitStream[i] << 1) + BitStream[i+1]; T55xxWriteBit (SendBits,Timing); } } else { for (i = 0; i < BitStreamLen; i++) { - byte_idx = i / 8; - bit_idx = i - (byte_idx * 8); - SendBits = (BitStream[byte_idx] >> bit_idx) & 1; + SendBits = (BitStream[i]); T55xxWriteBit (SendBits,Timing); } } From 2994ab10d64e4121a1894b8f01e350be4fc1e988 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Tue, 25 Jun 2019 20:52:29 +1000 Subject: [PATCH 11/18] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 037bab99..a3421c77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] +## T55xx Downlink Protocol +### Added +- Added downlink reference mode option r [ 0 - (default) fixed bit, 1 - long leading, 2 - leading 0 and 3 - 1 of 4 ] +Supported commands lf t55xx detect, read, write, bruteforce (with special r 4 to try all downlink modes) (mwalker33) + + ### Changed - Changed hf mfp security. Now it works in all the modes. (drHatson) - `hf fido` - show/check DER certificate and signatures (Merlok) From 59f75a789546405310e6ba06c01d9c6582a69071 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Tue, 25 Jun 2019 18:37:25 +0200 Subject: [PATCH 12/18] Update CHANGELOG.md --- CHANGELOG.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3421c77..037bab99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,6 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] -## T55xx Downlink Protocol -### Added -- Added downlink reference mode option r [ 0 - (default) fixed bit, 1 - long leading, 2 - leading 0 and 3 - 1 of 4 ] -Supported commands lf t55xx detect, read, write, bruteforce (with special r 4 to try all downlink modes) (mwalker33) - - ### Changed - Changed hf mfp security. Now it works in all the modes. (drHatson) - `hf fido` - show/check DER certificate and signatures (Merlok) From 7db36608a266a1f0f46dd4032cede2930e221d51 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Wed, 26 Jun 2019 11:34:31 +1000 Subject: [PATCH 13/18] Code improved for less memory --- armsrc/lfops.c | 236 ++++++++++++++++++++++++------------------------- 1 file changed, 117 insertions(+), 119 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 19bf6555..95fa9e7c 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1261,21 +1261,22 @@ typedef struct { uint16_t READ_GAP; } T55xx_Timing; - - // Set Initial/Default Values. Note: *8 can occure when used. This should keep things simplier here. T55xx_Timing T55xx_Timing_FixedBit = { 31 * 8 , 20 * 8 , 18 * 8 , 50 * 8 , 0 , 0 , 15 * 8 }; T55xx_Timing T55xx_Timing_LLR = { 31 * 8 , 20 * 8 , 18 * 8 , 50 * 8 , 0 , 0 , 15 * 8 }; T55xx_Timing T55xx_Timing_Leading0 = { 31 * 8 , 20 * 8 , 18 * 8 , 40 * 8 , 0 , 0 , 15 * 8 }; T55xx_Timing T55xx_Timing_1of4 = { 31 * 8 , 20 * 8 , 18 * 8 , 34 * 8 , 50 * 8 , 66 * 8 , 15 * 8 }; - // Some defines for readability #define T55xx_DLMode_Fixed 0 // Default Mode #define T55xx_DLMode_LLR 1 // Long Leading Reference #define T55xx_DLMode_Leading0 2 // Leading Zero #define T55xx_DLMode_1of4 3 // 1 of 4 #define T55xx_LongLeadingReference 4 // Value to tell Write Bit to send long reference +// Macro for code readability +#define BitStream_Byte(X) ((X) / 8) +#define BitStream_Bit(X) ((X) - ((X) / 8) * 8) + void TurnReadLFOn(int delay) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); @@ -1299,7 +1300,6 @@ void T55xxWriteBit(int bit, T55xx_Timing *Timings) { WaitUS(Timings->WRITE_GAP); } - // Function to abstract an Arbitrary length byte array to store bit pattern. // bit_array - Array to hold data/bit pattern // start_offset - bit location to start storing new bits. @@ -1308,22 +1308,129 @@ void T55xxWriteBit(int bit, T55xx_Timing *Timings) { // max_len - how many bytes can the bit_array hold (ensure no buffer overflow) // returns "Next" bit offset / bits stored (for next store) //int T55xx_SetBits (uint8_t *bit_array, int start_offset, uint32_t data , int num_bits, int max_len) -int T55xx_SetBits (bool *bit_array, int start_offset, uint32_t data , int num_bits, int max_len) +int T55xx_SetBits (uint8_t *BitStream, uint8_t start_offset, uint32_t data , uint8_t num_bits, uint8_t max_len) { - int offset; - int NextOffset = start_offset; + int8_t offset; + int8_t NextOffset = start_offset; // Check if data will fit. if ((start_offset + num_bits) <= (max_len*8)) { // Loop through the data and store - for (offset = (num_bits-1); offset >= 0; offset--) - bit_array[NextOffset++] = (data >> offset) & 1; + for (offset = (num_bits-1); offset >= 0; offset--) { + + if ((data >> offset) & 1) BitStream[BitStream_Byte(NextOffset)] |= (1 << BitStream_Bit(NextOffset)); // Set the bit to 1 + else BitStream[BitStream_Byte(NextOffset)] &= (0xff ^ (1 << BitStream_Bit(NextOffset))); // Set the bit to 0 + + NextOffset++; + } } else Dbprintf ("Too Many Bits to fit into bit buffer"); + return NextOffset; } +// Send one downlink command to the card +void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { //, bool read_cmd) {//, struct T55xx_Timing *Timing) { + + /* + arg bits + xxxxxxx1 0x01 PwdMode + xxxxxx1x 0x02 Page + xxxxx1xx 0x04 testMode + xxx11xxx 0x18 downlink mode + xx1xxxxx 0x20 reg_readmode + x1xxxxxx 0x40 called for a read, so no data packet + + */ + bool PwdMode = ((arg & 0x01) == 0x01); + uint8_t Page = (arg & 0x02) >> 1; + bool testMode = ((arg & 0x04) == 0x04); + uint8_t downlink_mode = (arg >> 3) & 0x03; + bool reg_readmode = ((arg & 0x20) == 0x20); + bool read_cmd = ((arg & 0x40) == 0x40); + uint8_t i = 0; + uint8_t BitStream[10]; // Max Downlink Command size ~74 bits, so 10 bytes (80 bits) + uint8_t BitStreamLen; + T55xx_Timing *Timing; + uint8_t SendBits; + + // Assigning Downlink Timeing for write + switch (downlink_mode) + { + case T55xx_DLMode_Fixed : Timing = &T55xx_Timing_FixedBit; break; + case T55xx_DLMode_LLR : Timing = &T55xx_Timing_LLR; break; + case T55xx_DLMode_Leading0 : Timing = &T55xx_Timing_Leading0; break; + case T55xx_DLMode_1of4 : Timing = &T55xx_Timing_1of4; break; + default: + Timing = &T55xx_Timing_FixedBit; + } + + // Build Bit Stream to send. + memset (BitStream,0x00,sizeof(BitStream)); + + BitStreamLen = 0; + + // Add Leading 0 and 1 of 4 reference bit + if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); + + // Add extra reference 0 for 1 of 4 + if (downlink_mode == T55xx_DLMode_1of4) + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); + + // Add Opcode + if (testMode) Dbprintf("TestMODE"); + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 0 : 1 , 1,sizeof(BitStream)); + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 1 : Page , 1,sizeof(BitStream)); + + if (PwdMode) { + // Leading 0 and 1 of 4 00 fixed bits if passsword used + if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) { + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); + } + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Pwd, 32,sizeof(BitStream)); + } + + // Add Lock bit 0 + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); + + // Add Data if a write command + if (!read_cmd) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Data, 32,sizeof(BitStream)); + + // Add Address + if (!reg_readmode) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Block, 3,sizeof(BitStream)); + + // Send Bits to T55xx + // Set up FPGA, 125kHz + LFSetupFPGAForADC(95, true); + StartTicks(); + // make sure tag is fully powered up... + WaitMS(5); + // Trigger T55x7 in mode. + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitUS(Timing->START_GAP); + + // If long leading 0 send long reference pulse + if (downlink_mode == T55xx_DLMode_LLR) + T55xxWriteBit (T55xx_LongLeadingReference,Timing); // Send Long Leading Start Reference + + if (downlink_mode == T55xx_DLMode_1of4) { // 1 of 4 need to send 2 bits at a time + for ( i = 0; i < BitStreamLen; i+=2 ) { + SendBits = (BitStream[BitStream_Byte(i )] >> (BitStream_Bit(i )) & 1) << 1; // Bit i + SendBits += (BitStream[BitStream_Byte(i+1)] >> (BitStream_Bit(i+1)) & 1); // Bit i+1; + T55xxWriteBit (SendBits & 3,Timing); + } + } + else { + for (i = 0; i < BitStreamLen; i++) { + SendBits = (BitStream[BitStream_Byte(i)] >> BitStream_Bit(i)); + T55xxWriteBit (SendBits & 1,Timing); + } + } +} + // Send T5577 reset command then read stream (see if we can identify the start of the stream) void T55xxResetRead(void) { LED_A_ON(); @@ -1355,115 +1462,6 @@ void T55xxResetRead(void) { LED_A_OFF(); } -// Send one downlink command to the card -void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { //, bool read_cmd) {//, struct T55xx_Timing *Timing) { - - /* - arg bits - xxxxxxx1 0x01 PwdMode - xxxxxx1x 0x02 Page - xxxxx1xx 0x04 testMode - xxx11xxx 0x18 downlink mode - xx1xxxxx 0x20 reg_readmode - x1xxxxxx 0x40 called for a read, so no data packet - - */ - bool PwdMode = ((arg & 0x01) == 0x01); - uint8_t Page = (arg & 0x02) >> 1; - bool testMode = ((arg & 0x04) == 0x04); - uint8_t downlink_mode = (arg >> 3) & 0x03;; - bool reg_readmode = ((arg & 0x20) == 0x20); - bool read_cmd = ((arg & 0x40) == 0x40); - - int i = 0; - bool BitStream[100]; // Max Downlink Command size ~75 bits, so 10 bytes (80 bits) - uint8_t BitStreamLen; - T55xx_Timing *Timing; - uint8_t SendBits; - - - // Assigning Downlink Timeing for write - switch (downlink_mode) - { - case T55xx_DLMode_Fixed : Timing = &T55xx_Timing_FixedBit; break; - case T55xx_DLMode_LLR : Timing = &T55xx_Timing_LLR; break; - case T55xx_DLMode_Leading0 : Timing = &T55xx_Timing_Leading0; break; - case T55xx_DLMode_1of4 : Timing = &T55xx_Timing_1of4; break; - default: - Timing = &T55xx_Timing_FixedBit; - } - - // Build Bit Stream to send. - memset (BitStream,0x00,sizeof(BitStream)); - - BitStreamLen = 0; - - // Add Leading 0 and 1 of 4 reference bit - if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); - - // Add extra reference 0 for 1 of 4 - if (downlink_mode == T55xx_DLMode_1of4) - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); - - // Add Opcode - if (testMode) Dbprintf("TestMODE"); - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 0 : 1 , 1,sizeof(BitStream)); - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 1 : Page , 1,sizeof(BitStream)); - - if (PwdMode) { - - // Leading 0 and 1 of 4 00 fixed bits if passsword used - if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) { - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); - } - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Pwd, 32,sizeof(BitStream)); - - } - // Add Lock bit - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); - - // Add Data if a write command - if (!read_cmd) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Data, 32,sizeof(BitStream)); - - // Add Address - if (!reg_readmode) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Block, 3,sizeof(BitStream)); - - - - // Send Bits to T55xx - - // Set up FPGA, 125kHz - LFSetupFPGAForADC(95, true); - StartTicks(); - // make sure tag is fully powered up... - WaitMS(5); - // Trigger T55x7 in mode. - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(Timing->START_GAP); - - - // If long leading 0 send long reference pulse - if (downlink_mode == T55xx_DLMode_LLR) - T55xxWriteBit (T55xx_LongLeadingReference,Timing); // Send Long Leading Start Reference - - - if (downlink_mode == T55xx_DLMode_1of4) { // 1 of 4 need to send 2 bits at a time - for (i = 0; i < BitStreamLen; i+=2) { - SendBits = (BitStream[i] << 1) + BitStream[i+1]; - T55xxWriteBit (SendBits,Timing); - } - } - else { - for (i = 0; i < BitStreamLen; i++) { - SendBits = (BitStream[i]); - T55xxWriteBit (SendBits,Timing); - } - } - -} - // Write one card block in page 0, no lock void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { /* @@ -1518,6 +1516,7 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { } // Read one card block in page [page] +//void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) {//, struct T55xx_Timing *Timing) { void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) {//, struct T55xx_Timing *Timing) { LED_A_ON(); @@ -1613,7 +1612,6 @@ void T55xxWakeUp(uint32_t Pwd){ T55xxWriteBit(0,&T55xx_Timing_FixedBit); //Page 0 // Send Pwd - for (i = 0x80000000; i != 0; i >>= 1) T55xxWriteBit(Pwd & i,&T55xx_Timing_FixedBit); From 28597bb6c742c6d717d33aebdbb5b0ba98bc95eb Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Thu, 27 Jun 2019 16:57:28 +1000 Subject: [PATCH 14/18] Update lfops.c moved wakeup and reset to call T55xx_SendCMD. Small code improvements --- armsrc/lfops.c | 110 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 34 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 95fa9e7c..16a46910 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1274,8 +1274,8 @@ T55xx_Timing T55xx_Timing_1of4 = { 31 * 8 , 20 * 8 , 18 * 8 , 34 * 8 , 5 #define T55xx_DLMode_1of4 3 // 1 of 4 #define T55xx_LongLeadingReference 4 // Value to tell Write Bit to send long reference // Macro for code readability -#define BitStream_Byte(X) ((X) / 8) -#define BitStream_Bit(X) ((X) - ((X) / 8) * 8) +#define BitStream_Byte(X) ((X) >> 3) +#define BitStream_Bit(X) ((X) & 7) void TurnReadLFOn(int delay) { @@ -1288,7 +1288,7 @@ void TurnReadLFOn(int delay) { void T55xxWriteBit(int bit, T55xx_Timing *Timings) { // If bit = 4 Send Long Leading Reference which is 138 + WRITE_0 - + // Dbprintf ("Bits : %d",bit); switch (bit){ case 0 : TurnReadLFOn(Timings->WRITE_0); break; // Send bit 0/00 case 1 : TurnReadLFOn(Timings->WRITE_1); break; // Send bit 1/01 @@ -1324,14 +1324,16 @@ int T55xx_SetBits (uint8_t *BitStream, uint8_t start_offset, uint32_t data , uin NextOffset++; } } - else - Dbprintf ("Too Many Bits to fit into bit buffer"); - + else{ + // Note: This should never happen unless some code changes cause it. + // So short message for coders when testing. + Dbprintf ("T55 too many bits"); + } return NextOffset; } // Send one downlink command to the card -void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { //, bool read_cmd) {//, struct T55xx_Timing *Timing) { +void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { /* arg bits @@ -1339,16 +1341,19 @@ void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { xxxxxx1x 0x02 Page xxxxx1xx 0x04 testMode xxx11xxx 0x18 downlink mode - xx1xxxxx 0x20 reg_readmode + xx1xxxxx 0x20 !reg_readmode x1xxxxxx 0x40 called for a read, so no data packet - + 1xxxxxxx 0x80 reset + */ bool PwdMode = ((arg & 0x01) == 0x01); - uint8_t Page = (arg & 0x02) >> 1; + bool Page = (arg & 0x02); bool testMode = ((arg & 0x04) == 0x04); uint8_t downlink_mode = (arg >> 3) & 0x03; bool reg_readmode = ((arg & 0x20) == 0x20); bool read_cmd = ((arg & 0x40) == 0x40); + bool reset = (arg & 0x80); + uint8_t i = 0; uint8_t BitStream[10]; // Max Downlink Command size ~74 bits, so 10 bytes (80 bits) uint8_t BitStreamLen; @@ -1379,29 +1384,35 @@ void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { if (downlink_mode == T55xx_DLMode_1of4) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); - // Add Opcode - if (testMode) Dbprintf("TestMODE"); - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 0 : 1 , 1,sizeof(BitStream)); - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 1 : Page , 1,sizeof(BitStream)); + // Add Opcode + if (reset) { + // Reset : r*) 00 + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 2,sizeof(BitStream)); + } + else + { + if (testMode) Dbprintf("TestMODE"); + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 0 : 1 , 1,sizeof(BitStream)); + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 1 : Page , 1,sizeof(BitStream)); - if (PwdMode) { - // Leading 0 and 1 of 4 00 fixed bits if passsword used - if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) { - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); - } - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Pwd, 32,sizeof(BitStream)); - } + if (PwdMode) { + // Leading 0 and 1 of 4 00 fixed bits if passsword used + if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) { + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 2,sizeof(BitStream)); + } + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Pwd, 32,sizeof(BitStream)); + } - // Add Lock bit 0 - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); + // Add Lock bit 0 + if (!reg_readmode) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); - // Add Data if a write command - if (!read_cmd) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Data, 32,sizeof(BitStream)); - - // Add Address - if (!reg_readmode) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Block, 3,sizeof(BitStream)); + // Add Data if a write command + if (!read_cmd) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Data, 32,sizeof(BitStream)); + // Add Address + if (!reg_readmode) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Block, 3,sizeof(BitStream)); + } + // Send Bits to T55xx // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); @@ -1434,6 +1445,7 @@ void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { // 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_keep_EM(); @@ -1452,6 +1464,15 @@ void T55xxResetRead(void) { T55xxWriteBit(0,&T55xx_Timing_FixedBit); TurnReadLFOn(T55xx_Timing_FixedBit.READ_GAP); +*/ + + // send r* 00 + uint8_t arg = 0x80; // SendCMD will add correct reference mode based on flags (when added). + + // Add in downlink_mode when ready + // arg |= 0x00; // dlmode << 3 (00 default - 08 leading 0 - 10 Fixed - 18 1 of 4 ) + + T55xx_SendCMD (0, 0, 0, arg); //, true); // Acquisition DoPartialAcquisition(0, true, BigBuf_max_traceLen(), 0); @@ -1470,8 +1491,9 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { xxxxxx1x 0x02 Page xxxxx1xx 0x04 testMode xxx11xxx 0x18 downlink mode - xx1xxxxx 0x20 reg_readmode + xx1xxxxx 0x20 !reg_readmode x1xxxxxx 0x40 called for a read, so no data packet + 1xxxxxxx 0x80 reset */ bool testMode = ((arg & 0x04) == 0x04); @@ -1516,7 +1538,6 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { } // Read one card block in page [page] -//void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) {//, struct T55xx_Timing *Timing) { void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) {//, struct T55xx_Timing *Timing) { LED_A_ON(); @@ -1527,14 +1548,15 @@ void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) {//, struct T55 xxxxxx1x 0x02 Page xxxxx1xx 0x04 testMode xxx11xxx 0x18 downlink mode - xx1xxxxx 0x20 reg_readmode + xx1xxxxx 0x20 !reg_readmode x1xxxxxx 0x40 called for a read, so no data packet + 1xxxxxxx 0x80 reset */ // Set Read Flag to ensure SendCMD does not add "data" to the packet arg0 |= 0x40; - + // RegRead Mode true of block 0xff if (Block == 0xff) arg0 |= 0x20; //make sure block is at max 7 @@ -1595,8 +1617,8 @@ void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) {//, struct T55 void T55xxWakeUp(uint32_t Pwd){ LED_B_ON(); + /* uint32_t i = 0; - // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); StartTicks(); @@ -1614,6 +1636,26 @@ void T55xxWakeUp(uint32_t Pwd){ // Send Pwd for (i = 0x80000000; i != 0; i >>= 1) T55xxWriteBit(Pwd & i,&T55xx_Timing_FixedBit); +*/ + /* + arg bits + xxxxxxx1 0x01 PwdMode + xxxxxx1x 0x02 Page + xxxxx1xx 0x04 testMode + xxx11xxx 0x18 downlink mode + xx1xxxxx 0x20 !reg_readmode + x1xxxxxx 0x40 called for a read, so no data packet + 1xxxxxxx 0x80 reset + */ + + // r* 10 (00) r* for llr , L0 and 1/4 - (00) for L0 and 1/4 - All handled in SendCMD + // So, default Opcode 10 and pwd. + uint8_t arg = 0x01 | 0x40 | 0x20; //Password Read Call no data | reg_read no block + + // Add in downlink_mode when ready + // arg |= 0x00; // dlmode << 3 (00 default - 08 leading 0 - 10 Fixed - 18 1 of 4 ) + + T55xx_SendCMD (0, 0, Pwd, arg); //, true); // Turn and leave field on to let the begin repeating transmission TurnReadLFOn(20*1000); From d7569065cb7464f42005b2fdbc17feef7d2f129b Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Wed, 3 Jul 2019 19:58:49 +1000 Subject: [PATCH 15/18] Code tidy removed commented code --- armsrc/lfops.c | 72 -------------------------------------------------- 1 file changed, 72 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 16a46910..4a7de24d 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1445,26 +1445,6 @@ void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { // 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_keep_EM(); - - // Set up FPGA, 125kHz - LFSetupFPGAForADC(95, true); - StartTicks(); - // make sure tag is fully powered up... - WaitMS(5); - - // Trigger T55x7 in mode. - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(T55xx_Timing_FixedBit.START_GAP); - - // reset tag - op code 00 - T55xxWriteBit(0,&T55xx_Timing_FixedBit); - T55xxWriteBit(0,&T55xx_Timing_FixedBit); - - TurnReadLFOn(T55xx_Timing_FixedBit.READ_GAP); -*/ // send r* 00 uint8_t arg = 0x80; // SendCMD will add correct reference mode based on flags (when added). @@ -1566,39 +1546,7 @@ void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) {//, struct T55 BigBuf_Clear_ext(false); T55xx_SendCMD (0, Block, Pwd, arg0); //, true); - -/* -// the send has been moved to the above SendCMD Call -======= - // Set up FPGA, 125kHz to power up the tag - LFSetupFPGAForADC(95, true); - StartTicks(); - // make sure tag is fully powered up... - WaitMS(5); - // Trigger T55x7 Direct Access Mode with start gap - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(START_GAP); - - // Opcode 1[page] - T55xxWriteBit(1); - T55xxWriteBit(Page); //Page 0 - - if (PwdMode) { - // Send Pwd - for (i = 0x80000000; i != 0; i >>= 1) - T55xxWriteBit(Pwd & i); - } - // Send a zero bit separation - T55xxWriteBit(0); - - // 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 // 137*8 seems to get to the start of data pretty well... // but we want to go past the start and let the repeating data settle in... @@ -1617,26 +1565,6 @@ void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) {//, struct T55 void T55xxWakeUp(uint32_t Pwd){ LED_B_ON(); - /* - uint32_t i = 0; - // Set up FPGA, 125kHz - LFSetupFPGAForADC(95, true); - StartTicks(); - // make sure tag is fully powered up... - WaitMS(5); - - // Trigger T55x7 Direct Access Mode - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(T55xx_Timing_FixedBit.START_GAP); - - // Opcode 10 - T55xxWriteBit(1,&T55xx_Timing_FixedBit); - T55xxWriteBit(0,&T55xx_Timing_FixedBit); //Page 0 - - // Send Pwd - for (i = 0x80000000; i != 0; i >>= 1) - T55xxWriteBit(Pwd & i,&T55xx_Timing_FixedBit); -*/ /* arg bits xxxxxxx1 0x01 PwdMode From dcd936a1da12a50a4084f4445d8ebbb080b5bc36 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sat, 6 Jul 2019 15:20:25 +1000 Subject: [PATCH 16/18] Update lfops.c Fixed lf t55 reset --- armsrc/lfops.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 4a7de24d..c6aecf0f 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1201,11 +1201,13 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) /* // Original Timings for reference +//note startgap must be sent after tag has been powered up for more than 3ms (per T5557 ds) #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 15*8 */ /* Q5 timing datasheet: @@ -1240,15 +1242,6 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) * Write_0 Fast Mode | 8*8 | 12*8 | 16*8 | * Write_1 Fast Mode | 24*8 | 28*8 | 32*8 | */ -/* -//note startgap must be sent after tag has been powered up for more than 3ms (per T5557 ds) -#define START_GAP 31*8 //31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (or 15fc) - T5557: 10*8 to 50*8 -#define WRITE_GAP 20*8 //20*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (or 10fc) - T5557: 8*8 to 30*8 typ 50-150us -#define WRITE_0 18*8 //18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (or 24fc) - T5557: 16*8 to 31*8 typ 24*8 -#define WRITE_1 50*8 //50*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (or 56fc) - T5557: 48*8 to 63*8 typ 54*8 432 for T55x7; 448 for E5550 - -#define READ_GAP 15*8 -*/ // Structure to hold Timing values. In future will be simplier to add user changable timings. typedef struct { @@ -1374,7 +1367,7 @@ void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { // Build Bit Stream to send. memset (BitStream,0x00,sizeof(BitStream)); - BitStreamLen = 0; + BitStreamLen = 0; // Ensure 0 bit index to start. // Add Leading 0 and 1 of 4 reference bit if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) @@ -1427,8 +1420,8 @@ void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { if (downlink_mode == T55xx_DLMode_LLR) T55xxWriteBit (T55xx_LongLeadingReference,Timing); // Send Long Leading Start Reference - if (downlink_mode == T55xx_DLMode_1of4) { // 1 of 4 need to send 2 bits at a time - for ( i = 0; i < BitStreamLen; i+=2 ) { + if (downlink_mode == T55xx_DLMode_1of4) { // 1 of 4 need to send 2 bits at a time + for ( i = 0; i < BitStreamLen-1; i+=2 ) { SendBits = (BitStream[BitStream_Byte(i )] >> (BitStream_Bit(i )) & 1) << 1; // Bit i SendBits += (BitStream[BitStream_Byte(i+1)] >> (BitStream_Bit(i+1)) & 1); // Bit i+1; T55xxWriteBit (SendBits & 3,Timing); @@ -1452,8 +1445,13 @@ void T55xxResetRead(void) { // Add in downlink_mode when ready // arg |= 0x00; // dlmode << 3 (00 default - 08 leading 0 - 10 Fixed - 18 1 of 4 ) + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_keep_EM(); + T55xx_SendCMD (0, 0, 0, arg); //, true); + TurnReadLFOn(T55xx_Timing_FixedBit.READ_GAP); + // Acquisition DoPartialAcquisition(0, true, BigBuf_max_traceLen(), 0); From bdc97796459e46419e72468b2e92d46f0a10a56e Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sun, 7 Jul 2019 05:00:08 +1000 Subject: [PATCH 17/18] Update lfops.c boundary length check --- armsrc/lfops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index c6aecf0f..ed83df48 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1420,7 +1420,7 @@ void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { if (downlink_mode == T55xx_DLMode_LLR) T55xxWriteBit (T55xx_LongLeadingReference,Timing); // Send Long Leading Start Reference - if (downlink_mode == T55xx_DLMode_1of4) { // 1 of 4 need to send 2 bits at a time + if ((downlink_mode == T55xx_DLMode_1of4) && (BitStreamLen > 0)) { // 1 of 4 need to send 2 bits at a time for ( i = 0; i < BitStreamLen-1; i+=2 ) { SendBits = (BitStream[BitStream_Byte(i )] >> (BitStream_Bit(i )) & 1) << 1; // Bit i SendBits += (BitStream[BitStream_Byte(i+1)] >> (BitStream_Bit(i+1)) & 1); // Bit i+1; From 347efc12741e72e6ce3a3c4f3ed554fae0cefc73 Mon Sep 17 00:00:00 2001 From: jmorsch Date: Thu, 11 Jul 2019 13:01:36 -0400 Subject: [PATCH 18/18] whitespace cleaning --- armsrc/lfops.c | 172 ++++++++++++++++++++++++------------------------- 1 file changed, 86 insertions(+), 86 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index ed83df48..c9947d97 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1264,7 +1264,7 @@ T55xx_Timing T55xx_Timing_1of4 = { 31 * 8 , 20 * 8 , 18 * 8 , 34 * 8 , 5 #define T55xx_DLMode_Fixed 0 // Default Mode #define T55xx_DLMode_LLR 1 // Long Leading Reference #define T55xx_DLMode_Leading0 2 // Leading Zero -#define T55xx_DLMode_1of4 3 // 1 of 4 +#define T55xx_DLMode_1of4 3 // 1 of 4 #define T55xx_LongLeadingReference 4 // Value to tell Write Bit to send long reference // Macro for code readability #define BitStream_Byte(X) ((X) >> 3) @@ -1281,14 +1281,14 @@ void TurnReadLFOn(int delay) { void T55xxWriteBit(int bit, T55xx_Timing *Timings) { // If bit = 4 Send Long Leading Reference which is 138 + WRITE_0 - // Dbprintf ("Bits : %d",bit); + // Dbprintf ("Bits : %d",bit); switch (bit){ case 0 : TurnReadLFOn(Timings->WRITE_0); break; // Send bit 0/00 case 1 : TurnReadLFOn(Timings->WRITE_1); break; // Send bit 1/01 case 2 : TurnReadLFOn(Timings->WRITE_2); break; // Send bits 10 - case 3 : TurnReadLFOn(Timings->WRITE_3); break; // Send bits 11 - case 4 : TurnReadLFOn(Timings->WRITE_0 + (136 * 8)); break; // Send Long Leading Reference - } + case 3 : TurnReadLFOn(Timings->WRITE_3); break; // Send bits 11 + case 4 : TurnReadLFOn(Timings->WRITE_0 + (136 * 8)); break; // Send Long Leading Reference + } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(Timings->WRITE_GAP); } @@ -1303,31 +1303,31 @@ void T55xxWriteBit(int bit, T55xx_Timing *Timings) { //int T55xx_SetBits (uint8_t *bit_array, int start_offset, uint32_t data , int num_bits, int max_len) int T55xx_SetBits (uint8_t *BitStream, uint8_t start_offset, uint32_t data , uint8_t num_bits, uint8_t max_len) { - int8_t offset; - int8_t NextOffset = start_offset; + int8_t offset; + int8_t NextOffset = start_offset; - // Check if data will fit. - if ((start_offset + num_bits) <= (max_len*8)) { - // Loop through the data and store - for (offset = (num_bits-1); offset >= 0; offset--) { + // Check if data will fit. + if ((start_offset + num_bits) <= (max_len*8)) { + // Loop through the data and store + for (offset = (num_bits-1); offset >= 0; offset--) { - if ((data >> offset) & 1) BitStream[BitStream_Byte(NextOffset)] |= (1 << BitStream_Bit(NextOffset)); // Set the bit to 1 - else BitStream[BitStream_Byte(NextOffset)] &= (0xff ^ (1 << BitStream_Bit(NextOffset))); // Set the bit to 0 + if ((data >> offset) & 1) BitStream[BitStream_Byte(NextOffset)] |= (1 << BitStream_Bit(NextOffset)); // Set the bit to 1 + else BitStream[BitStream_Byte(NextOffset)] &= (0xff ^ (1 << BitStream_Bit(NextOffset))); // Set the bit to 0 - NextOffset++; - } - } - else{ - // Note: This should never happen unless some code changes cause it. - // So short message for coders when testing. - Dbprintf ("T55 too many bits"); - } - return NextOffset; + NextOffset++; + } + } + else { + // Note: This should never happen unless some code changes cause it. + // So short message for coders when testing. + Dbprintf ("T55 too many bits"); + } + return NextOffset; } // Send one downlink command to the card void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { - + /* arg bits xxxxxxx1 0x01 PwdMode @@ -1337,32 +1337,32 @@ void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { xx1xxxxx 0x20 !reg_readmode x1xxxxxx 0x40 called for a read, so no data packet 1xxxxxxx 0x80 reset - + */ - bool PwdMode = ((arg & 0x01) == 0x01); - bool Page = (arg & 0x02); - bool testMode = ((arg & 0x04) == 0x04); - uint8_t downlink_mode = (arg >> 3) & 0x03; - bool reg_readmode = ((arg & 0x20) == 0x20); - bool read_cmd = ((arg & 0x40) == 0x40); - bool reset = (arg & 0x80); - - uint8_t i = 0; + bool PwdMode = ((arg & 0x01) == 0x01); + bool Page = (arg & 0x02); + bool testMode = ((arg & 0x04) == 0x04); + uint8_t downlink_mode = (arg >> 3) & 0x03; + bool reg_readmode = ((arg & 0x20) == 0x20); + bool read_cmd = ((arg & 0x40) == 0x40); + bool reset = (arg & 0x80); + + uint8_t i = 0; uint8_t BitStream[10]; // Max Downlink Command size ~74 bits, so 10 bytes (80 bits) uint8_t BitStreamLen; T55xx_Timing *Timing; uint8_t SendBits; - + // Assigning Downlink Timeing for write switch (downlink_mode) { case T55xx_DLMode_Fixed : Timing = &T55xx_Timing_FixedBit; break; - case T55xx_DLMode_LLR : Timing = &T55xx_Timing_LLR; break; + case T55xx_DLMode_LLR : Timing = &T55xx_Timing_LLR; break; case T55xx_DLMode_Leading0 : Timing = &T55xx_Timing_Leading0; break; case T55xx_DLMode_1of4 : Timing = &T55xx_Timing_1of4; break; default: Timing = &T55xx_Timing_FixedBit; - } + } // Build Bit Stream to send. memset (BitStream,0x00,sizeof(BitStream)); @@ -1370,42 +1370,42 @@ void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { BitStreamLen = 0; // Ensure 0 bit index to start. // Add Leading 0 and 1 of 4 reference bit - if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) + if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); // Add extra reference 0 for 1 of 4 - if (downlink_mode == T55xx_DLMode_1of4) + if (downlink_mode == T55xx_DLMode_1of4) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); // Add Opcode - if (reset) { - // Reset : r*) 00 - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 2,sizeof(BitStream)); - } - else - { - if (testMode) Dbprintf("TestMODE"); - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 0 : 1 , 1,sizeof(BitStream)); - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 1 : Page , 1,sizeof(BitStream)); - - if (PwdMode) { - // Leading 0 and 1 of 4 00 fixed bits if passsword used - if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) { - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 2,sizeof(BitStream)); - } - BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Pwd, 32,sizeof(BitStream)); - } + if (reset) { + // Reset : r*) 00 + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 2,sizeof(BitStream)); + } + else + { + if (testMode) Dbprintf("TestMODE"); + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 0 : 1 , 1,sizeof(BitStream)); + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 1 : Page , 1,sizeof(BitStream)); - // Add Lock bit 0 - if (!reg_readmode) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); + if (PwdMode) { + // Leading 0 and 1 of 4 00 fixed bits if passsword used + if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) { + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 2,sizeof(BitStream)); + } + BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Pwd, 32,sizeof(BitStream)); + } - // Add Data if a write command - if (!read_cmd) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Data, 32,sizeof(BitStream)); + // Add Lock bit 0 + if (!reg_readmode) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream)); + + // Add Data if a write command + if (!read_cmd) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Data, 32,sizeof(BitStream)); + + // Add Address + if (!reg_readmode) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Block, 3,sizeof(BitStream)); + } - // Add Address - if (!reg_readmode) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Block, 3,sizeof(BitStream)); - } - // Send Bits to T55xx // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); @@ -1420,18 +1420,18 @@ void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { if (downlink_mode == T55xx_DLMode_LLR) T55xxWriteBit (T55xx_LongLeadingReference,Timing); // Send Long Leading Start Reference - if ((downlink_mode == T55xx_DLMode_1of4) && (BitStreamLen > 0)) { // 1 of 4 need to send 2 bits at a time + if ((downlink_mode == T55xx_DLMode_1of4) && (BitStreamLen > 0)) { // 1 of 4 need to send 2 bits at a time for ( i = 0; i < BitStreamLen-1; i+=2 ) { SendBits = (BitStream[BitStream_Byte(i )] >> (BitStream_Bit(i )) & 1) << 1; // Bit i - SendBits += (BitStream[BitStream_Byte(i+1)] >> (BitStream_Bit(i+1)) & 1); // Bit i+1; + SendBits += (BitStream[BitStream_Byte(i+1)] >> (BitStream_Bit(i+1)) & 1); // Bit i+1; T55xxWriteBit (SendBits & 3,Timing); } } else { for (i = 0; i < BitStreamLen; i++) { - SendBits = (BitStream[BitStream_Byte(i)] >> BitStream_Bit(i)); + SendBits = (BitStream[BitStream_Byte(i)] >> BitStream_Bit(i)); T55xxWriteBit (SendBits & 1,Timing); - } + } } } @@ -1439,11 +1439,11 @@ void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { void T55xxResetRead(void) { LED_A_ON(); - // send r* 00 - uint8_t arg = 0x80; // SendCMD will add correct reference mode based on flags (when added). + // send r* 00 + uint8_t arg = 0x80; // SendCMD will add correct reference mode based on flags (when added). - // Add in downlink_mode when ready - // arg |= 0x00; // dlmode << 3 (00 default - 08 leading 0 - 10 Fixed - 18 1 of 4 ) + // Add in downlink_mode when ready + // arg |= 0x00; // dlmode << 3 (00 default - 08 leading 0 - 10 Fixed - 18 1 of 4 ) //clear buffer now so it does not interfere with timing later BigBuf_Clear_keep_EM(); @@ -1474,7 +1474,7 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { 1xxxxxxx 0x80 reset */ - bool testMode = ((arg & 0x04) == 0x04); + bool testMode = ((arg & 0x04) == 0x04); arg &= (0xff ^ 0x40); // Called for a write, so ensure it is clear/0 LED_A_ON (); @@ -1509,7 +1509,7 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { } // turn field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - + cmd_send(CMD_ACK,0,0,0,0,0); LED_A_OFF (); @@ -1517,7 +1517,7 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { // Read one card block in page [page] void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) {//, struct T55xx_Timing *Timing) { - + LED_A_ON(); /* @@ -1530,11 +1530,11 @@ void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) {//, struct T55 x1xxxxxx 0x40 called for a read, so no data packet 1xxxxxxx 0x80 reset */ - + // Set Read Flag to ensure SendCMD does not add "data" to the packet arg0 |= 0x40; - // RegRead Mode true of block 0xff + // RegRead Mode true of block 0xff if (Block == 0xff) arg0 |= 0x20; //make sure block is at max 7 @@ -1542,7 +1542,7 @@ void T55xxReadBlock (uint16_t arg0, uint8_t Block, uint32_t Pwd) {//, struct T55 //clear buffer now so it does not interfere with timing later BigBuf_Clear_ext(false); - + T55xx_SendCMD (0, Block, Pwd, arg0); //, true); // Turn field on to read the response @@ -1573,13 +1573,13 @@ void T55xxWakeUp(uint32_t Pwd){ x1xxxxxx 0x40 called for a read, so no data packet 1xxxxxxx 0x80 reset */ - - // r* 10 (00) r* for llr , L0 and 1/4 - (00) for L0 and 1/4 - All handled in SendCMD - // So, default Opcode 10 and pwd. - uint8_t arg = 0x01 | 0x40 | 0x20; //Password Read Call no data | reg_read no block - - // Add in downlink_mode when ready - // arg |= 0x00; // dlmode << 3 (00 default - 08 leading 0 - 10 Fixed - 18 1 of 4 ) + + // r* 10 (00) r* for llr , L0 and 1/4 - (00) for L0 and 1/4 - All handled in SendCMD + // So, default Opcode 10 and pwd. + uint8_t arg = 0x01 | 0x40 | 0x20; //Password Read Call no data | reg_read no block + + // Add in downlink_mode when ready + // arg |= 0x00; // dlmode << 3 (00 default - 08 leading 0 - 10 Fixed - 18 1 of 4 ) T55xx_SendCMD (0, 0, Pwd, arg); //, true); @@ -1592,8 +1592,8 @@ void T55xxWakeUp(uint32_t Pwd){ 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--) { - T55xxWriteBlock(blockdata[i-1],i-1,0,0);//,false); //,&T55xx_Timing_FixedBit); - // T55xx_SendCMD (blockdata[i-1],i-1,0,0);//,false); //,&T55xx_Timing_FixedBit); + T55xxWriteBlock(blockdata[i-1],i-1,0,0);//,false); //,&T55xx_Timing_FixedBit); + //T55xx_SendCMD (blockdata[i-1],i-1,0,0);//,false); //,&T55xx_Timing_FixedBit); } }