diff --git a/A5_1.c b/A5_1.c index 6e64078..ff1bb96 100644 --- a/A5_1.c +++ b/A5_1.c @@ -9,32 +9,104 @@ */ #include +#include #include "A5_1.h" +#include + +uint8_t a5_1_clock_core(a5_1_ctx_t *c, uint8_t clockoverride); + /* * length is length of key in bytes! */ -#define BYTEn(p,s) (*(((uint8_t*)&(p))+s)) -void a5_1_init(a5_1_ctx_t *c, uint8_t *key, uint8_t length); - -bool a5_1_clock(a5_1_ctx_t *c){ - bool x1,x2,x3, maj; - x1 = PARITY_LOOKUP & (1<< ((BYTEn(c->r1,2)+BYTEn(c->r1,1)>>5) & 0x7); - x2 = PARITY_LOOKUP & (1<< (BYTEn(c->r2,2)>>4)); - x3 = PARITY_LLOKUP & (1<< ((BYTEn(c->r3,2)>>4+BYTEn(c->r3,0)>>7) & 0x7)); - maj = (((c->r1 & (1<r2 & (1<r3 & (1<=2; - if (((c->r1 & (1<>R1_CLK) == maj) - c->r1 = c->r1<<1 + x1; - if (((c->r2 & (1<>R2_CLK) == maj) - c->r2 = c->r2<<1 + x2; - if (((c->r3 & (1<>R3_CLK) == maj) - c->r3 = c->r3<<1 + x3; - - return ((c->r1)>>(R1_LENGTH-1)+(c->r2)>>(R2_LENGTH-1)+(c->r3)>>(R3_LENGTH-1))&0x1; +void a5_1_init(a5_1_ctx_t *c, void* key, uint8_t keylength_b, void* iv, uint8_t ivlength_b){ + uint8_t i,t; + memset(c->r1, 0, 3); + memset(c->r2, 0, 3); + memset(c->r3, 0, 3); + for(i=0; i>i); + c->r1[0] ^= t; + c->r2[0] ^= t; + c->r3[0] ^= t; + a5_1_clock_core(c, 0x7); + } + for(i=0; i>i); + c->r1[0] ^= t; + c->r2[0] ^= t; + c->r3[0] ^= t; + a5_1_clock_core(c, 0x7); + } + for(i=0; i<100; ++i) + a5_1_clock_core(c,0); } -uint8_t a5_1_gen(a5_ 1_ctx_t *c){ +static +void shiftreg(uint8_t* d){ + uint8_t c, c2; + c=d[0]>>7; + d[0] <<= 1; + c2=d[1]>>7; + d[1] = (d[1]<<1) | c; + d[2] = (d[2]<<1) | c2; +} + + uint8_t parity3_lut[] PROGMEM = {0, 1, 1, 0, + 1, 0, 0, 1}; + uint8_t clock_lut[] PROGMEM = {0x7, 0x6, 0x5, 0x3, + 0x3, 0x5, 0x6, 0x7}; + +uint8_t a5_1_clock_core(a5_1_ctx_t *c, uint8_t clockoverride){ + uint8_t ret,clk,fb; + ret = (0x04&c->r1[2]) | (0x20&c->r2[2]) | (0x40&c->r3[2]); + ret = ret^(ret>>6); + ret &= 0x7; + ret = pgm_read_byte(parity3_lut+ret); + clk = (0x08&c->r1[1]) | (0x10&c->r2[1]) | (0x20&c->r3[1]); + clk >>= 3; + clk = pgm_read_byte(clock_lut+clk); + clk |= clockoverride; + + if(clk&1){ + fb = c->r1[2] ^ (1&((c->r1[1])>>5)); + fb &= 0x7; + fb = pgm_read_byte(parity3_lut+fb); + shiftreg(c->r1); + c->r1[0] |= fb; + c->r1[2] &= 0x07; + } + clk>>=1; + if(clk&1){ + fb = c->r2[2]>>4 ; + fb &= 0x7; + fb = pgm_read_byte(parity3_lut+fb); + shiftreg(c->r2); + c->r2[0] |= fb; + c->r2[2] &= 0x3F; + + } + clk>>=1; + if(clk&1){ + fb = (c->r3[2]>>4) ^ (1&((c->r3[0])>>7)); + fb &= 0x7; + fb = pgm_read_byte(parity3_lut+fb); + shiftreg(c->r3); + c->r3[0] |= fb; + c->r3[2] &= 0x7F; + } + return ret; +} + +uint8_t a5_1_clock(a5_1_ctx_t *c){ + return a5_1_clock_core(c, 0); +} + + +uint8_t a5_1_gen(a5_1_ctx_t *c){ uint8_t ret=0; ret = a5_1_clock(c); ret <<= 1; diff --git a/A5_1.h b/A5_1.h index 8803198..a6f963a 100644 --- a/A5_1.h +++ b/A5_1.h @@ -35,12 +35,13 @@ #define PARITY_LOOKUP 0x96 typedef struct { - uint32_t r1,r2,r3; /* the three regs, 19,22,23 bit in length */ + /* we are wasting one byte here but this allows a much faster implementation */ + uint8_t r1[3], r2[3], r3[3]; /* the three regs, 19,22,23 bit in length */ } a5_1_ctx_t; -void a5_1_init(a5_1_ctx_t *c, uint8_t *key, uint8_t length); -bool a5_1_clock(a5_1_ctx_t *c); -uint8_t a5_1_gen(a5_ 1_ctx_t *c); +void a5_1_init(a5_1_ctx_t *c, void* key, uint8_t keylength_b, void* iv, uint8_t ivlength_b); +uint8_t a5_1_clock(a5_1_ctx_t *c); +uint8_t a5_1_gen(a5_1_ctx_t *c); #endif