From d7e24e7c5f3481a45d79de49ad3de2ef0d81437e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 28 Sep 2016 21:37:08 +0200 Subject: [PATCH] CHG: 'hf list legic' doesn't print the parity now. CHG: 'hf legic read' the device side timings is starting to look much better. HUGE Thanks to @will-rbnt for endless checks and logic analyser feedback. Without his effort this would not work. What does work? We can now use ANY IV in legic. The PM3 Master version is flawed, will only work with IV=0x55. ---still broke--- my crc implementation.. I know I'm about to look into it. --- armsrc/legicrf.c | 51 +++++++++++++++++++-------------------------- armsrc/ticks.c | 1 - client/cmdhf.c | 2 +- client/cmdhflegic.c | 12 +---------- 4 files changed, 24 insertions(+), 42 deletions(-) diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index 97c14b69..d2e2e856 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -72,7 +72,7 @@ static void setup_timer(void) { #define RWD_TIME_1 120 // READER_TIME_PAUSE 20us off, 80us on = 100us 80 * 1.5 == 120ticks #define RWD_TIME_0 60 // READER_TIME_PAUSE 20us off, 40us on = 60us 40 * 1.5 == 60ticks #define RWD_TIME_PAUSE 30 // 20us == 20 * 1.5 == 30ticks */ -#define TAG_BIT_PERIOD 150 // 100us == 100 * 1.5 == 150ticks +#define TAG_BIT_PERIOD 143 // 100us == 100 * 1.5 == 150ticks #define TAG_FRAME_WAIT 495 // 330us from READER frame end to TAG frame start. 330 * 1.5 == 495 #define RWD_TIME_FUZZ 20 // rather generous 13us, since the peak detector + hysteresis fuzz quite a bit @@ -278,7 +278,7 @@ static void frame_receiveAsReader(struct legic_frame * const f, uint8_t bits) { uint8_t i = bits, edges = 0; uint16_t lsfr = 0; - uint32_t the_bit = 1, next_bit_at = 0, data; + uint32_t the_bit = 1, next_bit_at = 0, data = 0; int old_level = 0, level = 0; @@ -287,22 +287,17 @@ static void frame_receiveAsReader(struct legic_frame * const f, uint8_t bits) { // calibrate the prng. legic_prng_forward(2); - - // precompute the cipher uint8_t prngstart = legic_prng_count() ; - data = lsfr = legic_prng_get_bits(bits); //FIXED time between sending frame and now listening frame. 330us // 387 = 0x19 0001 1001 - // 480 = 0x19 - // 500 = 0x1C 0001 1100 uint32_t starttime = GET_TICKS; //uint16_t mywait = TAG_FRAME_WAIT - (starttime - sendFrameStop); //uint16_t mywait = 495 - (starttime - sendFrameStop); if ( bits == 6) { - //Dbprintf("6 WAIT %d", 495 - 9 - 9 ); - WaitTicks( 495 - 9 - 9 ); + //WaitTicks( 495 - 9 - 9 ); + WaitTicks( 475 ); } else { //Dbprintf("x WAIT %d", mywait ); //WaitTicks( mywait ); @@ -313,7 +308,6 @@ static void frame_receiveAsReader(struct legic_frame * const f, uint8_t bits) { while ( i-- ){ edges = 0; - uint8_t adjust = 0; while ( GET_TICKS < next_bit_at) { level = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN); @@ -322,11 +316,6 @@ static void frame_receiveAsReader(struct legic_frame * const f, uint8_t bits) { ++edges; old_level = level; - - if(edges > 20 && adjust == 0) { - next_bit_at -= 15; - adjust = 1; - } } next_bit_at += TAG_BIT_PERIOD; @@ -345,10 +334,10 @@ static void frame_receiveAsReader(struct legic_frame * const f, uint8_t bits) { uint8_t cmdbytes[] = { bits, - BYTEx(data,0), - BYTEx(data,1), - BYTEx(data, 0) ^ BYTEx(lsfr,0), - BYTEx(data, 1) ^ BYTEx(lsfr,1), + BYTEx(data, 0), + BYTEx(data, 1), + BYTEx(data, 0) ^ BYTEx(lsfr, 0), + BYTEx(data, 1) ^ BYTEx(lsfr, 1), prngstart, legic_prng_count() }; @@ -360,7 +349,7 @@ static uint32_t setup_phase_reader(uint8_t iv) { // Switch on carrier and let the tag charge for 1ms HIGH(GPIO_SSC_DOUT); - WaitUS(100); + WaitUS(1000); ResetTicks(); @@ -375,9 +364,10 @@ static uint32_t setup_phase_reader(uint8_t iv) { frame_receiveAsReader(¤t_frame, 6); - // fixed delay before sending ack. - WaitTicks(366); // 244us - legic_prng_forward(1); //240us / 100 == 2.4 iterations + // 292us (438t) - fixed delay before sending ack. + // minus log and stuff 100tick? + WaitTicks(338); + legic_prng_forward(3); // Send obsfuscated acknowledgment frame. // 0x19 = 0x18 MIM22, 0x01 LSB READCMD @@ -388,6 +378,8 @@ static uint32_t setup_phase_reader(uint8_t iv) { case 0x3D: frame_sendAsReader(0x39, 6); break; default: break; } + + legic_prng_forward(2); return current_frame.data; } @@ -440,16 +432,14 @@ int legic_read_byte(int byte_index, int cmd_sz) { // (us)| ticks // ------------- // 330 | 495 - // 460 | 690 - // 258 | 387 // 244 | 366 - WaitTicks(495); - legic_prng_forward(3); // 460 / 100 = 4.6 iterations + WaitTicks(366); frame_sendAsReader(cmd, cmd_sz); frame_receiveAsReader(¤t_frame, 12); byte = BYTEx(current_frame.data, 0); + calcCrc = legic4Crc(LEGIC_READ, byte_index, byte, cmd_sz); crc = BYTEx(current_frame.data, 1); @@ -457,6 +447,9 @@ int legic_read_byte(int byte_index, int cmd_sz) { Dbprintf("!!! crc mismatch: expected %x but got %x !!!", calcCrc, crc); return -1; } + + legic_prng_forward(4); + WaitTicks(40); return byte; } @@ -572,7 +565,7 @@ int LegicRfReader(int offset, int bytes, int iv) { // Start setup and read bytes. setup_phase_reader(iv); - + LED_B_ON(); while (byte_index < bytes) { int r = legic_read_byte(byte_index + offset, cmd_sz); @@ -775,7 +768,7 @@ void LegicRfRawWriter(int address, int byte, int iv) { void LegicRfInfo(void){ LegicCommonInit(); - uint32_t tag_type = setup_phase_reader(0x55); + uint32_t tag_type = setup_phase_reader(0x1); uint8_t cmd_sz = 0; uint16_t card_sz = 0; diff --git a/armsrc/ticks.c b/armsrc/ticks.c index d183c707..555685cc 100644 --- a/armsrc/ticks.c +++ b/armsrc/ticks.c @@ -8,7 +8,6 @@ //----------------------------------------------------------------------------- // Timers, Clocks functions used in LF or Legic where you would need detailed time. //----------------------------------------------------------------------------- - #include "ticks.h" // attempt at high resolution microsecond timer diff --git a/client/cmdhf.c b/client/cmdhf.c index b2408782..845cfd5d 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -664,7 +664,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); } uint8_t parityBits = parityBytes[j>>3]; - if (protocol != ISO_14443B && protocol != ISO_7816_4 && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { + if (protocol != LEGIC && protocol != ISO_14443B && protocol != ISO_7816_4 && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]); } else { snprintf(line[j/16]+(( j % 16) * 4),110, "%02x ", frame[j]); diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 031265fa..5bc24e9b 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -410,18 +410,8 @@ int CmdLegicRFRead(const char *Cmd) { IV |= 0x01; // IV must be odd PrintAndLog("LSB of IV must be SET"); } - PrintAndLog("Current IV: 0x%02x", IV); + PrintAndLog("Using IV: 0x%02x", IV); - // get some prng bytes from - uint8_t temp[32]; - legic_prng_init(IV); - for ( uint8_t j = 0; j < sizeof(temp); ++j) { - temp[j] = legic_prng_get_bit(1); - legic_prng_forward(1); - //PrintAndLog("PRNG: %s", sprint_hex(temp, sizeof(temp))); - } - PrintAndLog("PRNG: %s", sprint_bin(temp, sizeof(temp))); - UsbCommand c = {CMD_READER_LEGIC_RF, {offset, len, IV}}; clearCommandBuffer(); SendCommand(&c); -- 2.39.2