X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/c649c43389d23fef7d28541739c89d22ad1f5250..9015ae0f5dec6a7922ff6ce30eb62ad7a0e6cf5b:/armsrc/legicrf.c diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index b1c6b196..766bd443 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -1,5 +1,6 @@ //----------------------------------------------------------------------------- // (c) 2009 Henryk Plötz +// 2016 Iceman // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -85,7 +86,7 @@ static void setup_timer(void) { #define FUZZ_EQUAL(value, target, fuzz) ((value) > ((target)-(fuzz)) && (value) < ((target)+(fuzz))) #ifndef SHORT_COIL -# define SHORT_COIL LOW(GPIO_SSC_DOUT); +# define SHORT_COIL LOW(GPIO_SSC_DOUT); #endif #ifndef OPEN_COIL # define OPEN_COIL HIGH(GPIO_SSC_DOUT); @@ -102,7 +103,7 @@ static void setup_timer(void) { WaitTicks( (RWD_TIME_PAUSE) ); \ OPEN_COIL; \ WaitTicks((x)); \ - } while (0) + } while (0); #endif // ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces. @@ -140,14 +141,13 @@ static void frame_clean(struct legic_frame * const f) { /* Generate Keystream */ uint32_t get_key_stream(int skip, int count) { - uint32_t key = 0; + int i; // Use int to enlarge timer tc to 32bit legic_prng_bc += prng_timer->TC_CV; // reset the prng timer. - ResetTimer(prng_timer); /* If skip == -1, forward prng time based */ if(skip == -1) { @@ -161,55 +161,41 @@ uint32_t get_key_stream(int skip, int count) { i = (count == 6) ? -1 : legic_read_count; - /* Write Time Data into LOG */ - // uint8_t *BigBuf = BigBuf_get_addr(); - // BigBuf[OFFSET_LOG+128+i] = legic_prng_count(); - // BigBuf[OFFSET_LOG+256+i*4] = (legic_prng_bc >> 0) & 0xff; - // BigBuf[OFFSET_LOG+256+i*4+1] = (legic_prng_bc >> 8) & 0xff; - // BigBuf[OFFSET_LOG+256+i*4+2] = (legic_prng_bc >>16) & 0xff; - // BigBuf[OFFSET_LOG+256+i*4+3] = (legic_prng_bc >>24) & 0xff; - // BigBuf[OFFSET_LOG+384+i] = count; + // log + //uint8_t cmdbytes[] = {bits, BYTEx(data, 0), BYTEx(data, 1), BYTEx(send, 0), BYTEx(send, 1), legic_prng_count()}; + //LogTrace(cmdbytes, sizeof(cmdbytes), starttime, GET_TICKS, NULL, TRUE); /* Generate KeyStream */ - for(i=0; iPIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - /* Use time to crypt frame */ - if(crypt) { - legic_prng_forward(2); /* TAG_FRAME_WAIT -> shift by 2 */ - response ^= legic_prng_get_bits(bits); - } + /* TAG_FRAME_WAIT -> shift by 2 */ + legic_prng_forward(2); + response ^= legic_prng_get_bits(bits); /* Wait for the frame start */ - WaitUS( TAG_FRAME_WAIT ); + WaitTicks( TAG_FRAME_WAIT ); - uint8_t bit = 0; - for(int i = 0; i < bits; i++) { - - bit = response & 1; - response >>= 1; - - if (bit) - HIGH(GPIO_SSC_DOUT); + for (; mask < BITMASK(bits); mask <<= 1) { + if (response & mask) + OPEN_COIL else - LOW(GPIO_SSC_DOUT); - - WaitUS(100); + SHORT_COIL + WaitTicks(TAG_BIT_PERIOD); } - LOW(GPIO_SSC_DOUT); + SHORT_COIL; } /* Send a frame in reader mode, the FPGA must have been set up by @@ -225,9 +211,9 @@ void frame_sendAsReader(uint32_t data, uint8_t bits){ for (; mask < BITMASK(bits); mask <<= 1) { if (send & mask) - COIL_PULSE(RWD_TIME_1); + COIL_PULSE(RWD_TIME_1) else - COIL_PULSE(RWD_TIME_0); + COIL_PULSE(RWD_TIME_0) } // Final pause to mark the end of the frame @@ -279,13 +265,8 @@ static void frame_receiveAsReader(struct legic_frame * const f, uint8_t bits) { //FIXED time between sending frame and now listening frame. 330us uint32_t starttime = GET_TICKS; - //if ( bits == 6 || bits == 7) { - // its about 9+9 ticks delay from end-send to here. - //WaitTicks( 495 - 9 - 9 ); - WaitTicks( 477 ); - //} else { -// WaitTicks( 477 ); -// } + // its about 9+9 ticks delay from end-send to here. + WaitTicks( 477 ); next_bit_at = GET_TICKS + TAG_BIT_PERIOD; @@ -324,7 +305,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(1000); + WaitUS(5000); ResetTicks(); @@ -370,7 +351,7 @@ static void LegicCommonInit(void) { AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; // reserve a cardmem, meaning we can use the tracelog function in bigbuff easier. - cardmem = BigBuf_malloc(LEGIC_CARD_MEMSIZE); + cardmem = BigBuf_get_EM_addr(); memset(cardmem, 0x00, LEGIC_CARD_MEMSIZE); clear_trace(); @@ -399,10 +380,10 @@ int legic_read_byte( uint16_t index, uint8_t cmd_sz) { uint8_t byte, crc, calcCrc = 0; uint32_t cmd = (index << 1) | LEGIC_READ; - - //WaitTicks(366); - WaitTicks(330); - //WaitTicks(50); + + // 90ticks = 60us (should be 100us but crc calc takes time.) + //WaitTicks(330); // 330ticks prng(4) - works + WaitTicks(240); // 240ticks prng(3) - works frame_sendAsReader(cmd, cmd_sz); frame_receiveAsReader(¤t_frame, 12); @@ -417,7 +398,7 @@ int legic_read_byte( uint16_t index, uint8_t cmd_sz) { return -1; } - legic_prng_forward(4); + legic_prng_forward(3); return byte; } @@ -438,11 +419,11 @@ int legic_write_byte(uint8_t byte, uint16_t addr, uint8_t addr_sz) { crc_update(&legic_crc, addr, addr_sz); crc_update(&legic_crc, byte, 8); uint32_t crc = crc_finish(&legic_crc); - uint32_t crc2 = legic4Crc(LEGIC_WRITE, addr, byte, addr_sz+1); - if ( crc != crc2 ) + if ( crc != crc2 ) { Dbprintf("crc is missmatch"); - + return 1; + } // send write command uint32_t cmd = ((crc <<(addr_sz+1+8)) //CRC |(byte <<(addr_sz+1)) //Data @@ -451,13 +432,12 @@ int legic_write_byte(uint8_t byte, uint16_t addr, uint8_t addr_sz) { uint32_t cmd_sz = addr_sz+1+8+4; //crc+data+cmd - legic_prng_forward(2); /* we wait anyways */ + legic_prng_forward(2); - WaitUS(TAG_FRAME_WAIT); + WaitTicks(330); frame_sendAsReader(cmd, cmd_sz); - - // wllm-rbnt doesnt have these + AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_DIN; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DIN; @@ -465,19 +445,19 @@ int legic_write_byte(uint8_t byte, uint16_t addr, uint8_t addr_sz) { int t, old_level = 0, edges = 0; int next_bit_at = 0; - WaitUS(TAG_FRAME_WAIT); + WaitTicks(TAG_FRAME_WAIT); for( t = 0; t < 80; ++t) { edges = 0; next_bit_at += TAG_BIT_PERIOD; while(timer->TC_CV < next_bit_at) { - int level = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN); + volatile uint32_t level = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN); if(level != old_level) edges++; old_level = level; } - if(edges > 20 && edges < 60) { /* expected are 42 edges */ + if(edges > 20 ) { /* expected are 42 edges */ int t = timer->TC_CV; int c = t / TAG_BIT_PERIOD; @@ -493,8 +473,6 @@ int legic_write_byte(uint8_t byte, uint16_t addr, uint8_t addr_sz) { int LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { - len &= 0x3FF; - uint16_t i = 0; uint8_t isOK = 1; legic_card_select_t card; @@ -530,7 +508,7 @@ OUT: WDT_HIT(); switch_off_tag_rwd(); LEDsoff(); - cmd_send(CMD_ACK,isOK,len,0,cardmem,len); + cmd_send(CMD_ACK, isOK, len, 0, cardmem, len); return 0; } @@ -618,6 +596,7 @@ void LegicRfWriter(uint16_t offset, uint16_t bytes, uint8_t iv) { LED_B_ON(); setup_phase_reader(iv); + int r = 0; while(byte_index < bytes) { @@ -769,7 +748,7 @@ void LegicRfInfo(void){ } cmd_send(CMD_ACK, 1, 0, 0, buf, sizeof(legic_card_select_t)); - + OUT: switch_off_tag_rwd(); LEDsoff(); @@ -782,26 +761,26 @@ static void frame_handle_tag(struct legic_frame const * const f) { uint8_t *BigBuf = BigBuf_get_addr(); - /* First Part of Handshake (IV) */ - if(f->bits == 7) { + /* First Part of Handshake (IV) */ + if(f->bits == 7) { + + LED_C_ON(); - LED_C_ON(); - // Reset prng timer ResetTimer(prng_timer); - - legic_prng_init(f->data); - frame_send_tag(0x3d, 6, 1); /* 0x3d^0x26 = 0x1B */ - legic_state = STATE_IV; - legic_read_count = 0; - legic_prng_bc = 0; - legic_prng_iv = f->data; - - + + legic_prng_init(f->data); + frame_send_tag(0x3d, 6); /* 0x3d^0x26 = 0x1B */ + legic_state = STATE_IV; + legic_read_count = 0; + legic_prng_bc = 0; + legic_prng_iv = f->data; + + ResetTimer(timer); WaitUS(280); - return; - } + return; + } /* 0x19==??? */ if(legic_state == STATE_IV) { @@ -835,7 +814,7 @@ static void frame_handle_tag(struct legic_frame const * const f) //Dbprintf("Data:%03.3x, key:%03.3x, addr: %03.3x, read_c:%u", f->data, key, addr, read_c); legic_prng_forward(legic_reqresp_drift); - frame_send_tag(hash | data, 12, 1); + frame_send_tag(hash | data, 12); ResetTimer(timer); legic_prng_forward(2);