]> git.cryptolib.org Git - avr-crypto-lib.git/blob - A5_1.c
ff1bb9606e816ebfd4bd4aa09973ad9183a6f229
[avr-crypto-lib.git] / A5_1.c
1 /* 
2  * File:                A5_1.c
3  * Author:      Daniel Otte
4  * Date:        24.06.2006
5  * License: GPL
6  * Description: Implementation of the A5/1 stream cipher algorithm, as used in GSM.
7  * ! Warning, this is weak crypto !
8  * 
9  */
10  
11 #include <stdint.h>
12 #include <string.h>
13 #include "A5_1.h"
14 #include <avr/pgmspace.h>
15
16 uint8_t a5_1_clock_core(a5_1_ctx_t *c, uint8_t clockoverride);
17
18
19 /*
20  * length is length of key in bytes!
21  */
22
23 void a5_1_init(a5_1_ctx_t *c, void* key, uint8_t keylength_b, void* iv, uint8_t ivlength_b){
24         uint8_t i,t;
25         memset(c->r1, 0, 3);
26         memset(c->r2, 0, 3);
27         memset(c->r3, 0, 3);
28         for(i=0; i<keylength_b; ++i){
29                 t=((uint8_t*)key)[i/8];
30                 t=1&(t>>i);
31                 c->r1[0] ^= t;
32                 c->r2[0] ^= t;
33                 c->r3[0] ^= t;
34                 a5_1_clock_core(c, 0x7);
35         }
36         for(i=0; i<ivlength_b; ++i){
37                 t=((uint8_t*)iv)[i/8];
38                 t=1&(t>>i);
39                 c->r1[0] ^= t;
40                 c->r2[0] ^= t;
41                 c->r3[0] ^= t;
42                 a5_1_clock_core(c, 0x7);
43         }
44         for(i=0; i<100; ++i)
45                 a5_1_clock_core(c,0);
46 }
47
48 static
49 void shiftreg(uint8_t* d){
50         uint8_t c, c2;
51         c=d[0]>>7;
52         d[0] <<= 1;
53         c2=d[1]>>7;
54         d[1] = (d[1]<<1) | c;
55         d[2] = (d[2]<<1) | c2;
56
57
58         uint8_t parity3_lut[] PROGMEM = {0, 1, 1, 0,
59                                              1, 0, 0, 1};       
60         uint8_t clock_lut[] PROGMEM =  {0x7, 0x6, 0x5, 0x3,
61                                             0x3, 0x5, 0x6, 0x7}; 
62                                             
63 uint8_t a5_1_clock_core(a5_1_ctx_t *c, uint8_t clockoverride){
64         uint8_t ret,clk,fb;
65         ret = (0x04&c->r1[2]) | (0x20&c->r2[2]) | (0x40&c->r3[2]);
66         ret = ret^(ret>>6);
67         ret &= 0x7;
68         ret = pgm_read_byte(parity3_lut+ret);
69         clk = (0x08&c->r1[1]) | (0x10&c->r2[1]) | (0x20&c->r3[1]);
70         clk >>= 3;
71         clk = pgm_read_byte(clock_lut+clk);
72         clk |= clockoverride;
73         
74         if(clk&1){
75                 fb = c->r1[2] ^ (1&((c->r1[1])>>5));
76                 fb &= 0x7;
77                 fb = pgm_read_byte(parity3_lut+fb);
78                 shiftreg(c->r1);
79                 c->r1[0] |= fb;
80                 c->r1[2] &= 0x07;
81         }
82         clk>>=1;
83         if(clk&1){
84                 fb = c->r2[2]>>4 ;
85                 fb &= 0x7;
86                 fb = pgm_read_byte(parity3_lut+fb);
87                 shiftreg(c->r2);
88                 c->r2[0] |= fb;
89                 c->r2[2] &= 0x3F;
90         
91         }
92         clk>>=1;
93         if(clk&1){
94                 fb = (c->r3[2]>>4) ^ (1&((c->r3[0])>>7));
95                 fb &= 0x7;
96                 fb = pgm_read_byte(parity3_lut+fb);
97                 shiftreg(c->r3);
98                 c->r3[0] |= fb;
99                 c->r3[2] &= 0x7F;
100         }
101         return ret;
102 }
103
104 uint8_t a5_1_clock(a5_1_ctx_t *c){
105         return a5_1_clock_core(c, 0);
106 }
107
108
109 uint8_t a5_1_gen(a5_1_ctx_t *c){
110         uint8_t ret=0;
111         ret = a5_1_clock(c);
112         ret <<= 1;
113         ret = a5_1_clock(c);
114         ret <<= 1;
115         ret = a5_1_clock(c);
116         ret <<= 1;
117         ret = a5_1_clock(c);
118         ret <<= 1;
119         ret = a5_1_clock(c);
120         ret <<= 1;
121         ret = a5_1_clock(c);
122         ret <<= 1;
123         ret = a5_1_clock(c);
124         ret <<= 1;
125         ret = a5_1_clock(c);
126         return ret;
127 }
128
129
130
131