]> git.cryptolib.org Git - avr-crypto-lib.git/blob - cast6/cast6.c
5d21e5b5da03b35e8f1d3534398d3b5561e4dc12
[avr-crypto-lib.git] / cast6 / cast6.c
1 /* 
2  * File:        cast6.c
3  * Author:      Daniel Otte
4  * Date:        09.09.2006
5  * License: GPL
6  * Description: Implementation of the CAST6 (aka CAST-256) cipher algorithm as described in RFC 2612
7  * 
8  */
9
10 #include <stdint.h>
11 #include <string.h>
12 #include <avr/pgmspace.h>
13 #include "cast6.h"
14 #include "cast6-sbox.h"
15
16 #define CHANGE_ENDIAN32(x) (((x)<<24 | (x)>>24 | ((x)&0xff00)<<8 | ((x)&0xff0000)>>8)&0xffffffff)
17
18
19 static
20 uint8_t kr(uint8_t i, const cast6_ctx_t *ctx){
21         uint8_t ret;
22         ret = ctx->krx[i/2];
23         if(i&1){
24                 ret >>= 4;
25         }else{
26                 ret &= 0x0f;
27         }
28         /* now get the high bit */
29         ret |= ((ctx->krx[24+i/8])&(1<<(i%8)))?0x10:0x00;
30         return ret;
31 }
32
33 static
34 void set_kr(uint8_t value, uint8_t i, cast6_ctx_t *ctx){
35         value &= 0x1F;
36         
37         (ctx->krx[i/2]) &= 0xF0>>((i&1)*4); /* clear the location where v should go */
38         (ctx->krx[i/2]) |= (value&0x0f)<<((i&1)*4); 
39         
40         /* now set the high bit */
41         (ctx->krx[24+i/8]) &= ~(1<<(i%8)); /* clear the location where v should go */
42         (ctx->krx[24+i/8]) |= (value>>4)<<(i%8); 
43 }
44
45 #define ROTL32(a,n) (((a)<<(n))|((a)>>(32-(n))))
46 #define ROTR32(a,n) (((a)>>(n))|((a)<<(32-(n))))
47
48 #define S1(a) (pgm_read_dword(&(s1[(a)])))
49 #define S2(a) (pgm_read_dword(&(s2[(a)])))
50 #define S3(a) (pgm_read_dword(&(s3[(a)])))
51 #define S4(a) (pgm_read_dword(&(s4[(a)])))
52
53 #define A ((uint8_t)(v>>(8*3)))
54 #define B ((uint8_t)(v>>(8*2)))
55 #define C ((uint8_t)(v>>(8*1)))
56 #define D ((uint8_t)(v>>(8*0)))
57
58
59 static
60 uint32_t f1(uint32_t v, uint8_t kri, uint32_t kmi){
61         uint32_t o;
62         kri &= 0x1F;
63         v  = ROTL32(kmi+v, kri);
64         o  = S1(A);
65         o ^= S2(B);
66         o -= S3(C);
67         o += S4(D);
68         return o;
69 }
70
71 static
72 uint32_t f2(uint32_t v, uint8_t kri, uint32_t kmi){
73         uint32_t o;
74         kri &= 0x1F;
75         v  = ROTL32(kmi^v, kri);
76         o  = S1(A);
77         o -= S2(B);
78         o += S3(C);
79         o ^= S4(D);
80         return o;
81 }
82
83 static
84 uint32_t f3(uint32_t v, uint8_t kri, uint32_t kmi){
85         uint32_t o;
86         kri &= 0x1F;
87         v  = ROTL32(kmi-v, kri);
88         o  = S1(A);
89         o += S2(B);
90         o ^= S3(C);
91         o -= S4(D);
92         return o;
93 }
94
95 #undef A
96 #undef B
97 #undef C
98 #undef D
99
100 #define A (((uint32_t*)buffer)[0])
101 #define B (((uint32_t*)buffer)[1])
102 #define C (((uint32_t*)buffer)[2])
103 #define D (((uint32_t*)buffer)[3])
104
105 static
106 void q(void *buffer, uint8_t i, const cast6_ctx_t *ctx){
107         C ^= f1(D, kr(i*4+0, ctx), ctx->km[i][0]);
108         B ^= f2(C, kr(i*4+1, ctx), ctx->km[i][1]);
109         A ^= f3(B, kr(i*4+2, ctx), ctx->km[i][2]);
110         D ^= f1(A, kr(i*4+3, ctx), ctx->km[i][3]);
111 }
112
113 static
114 void qbar(void *buffer, uint8_t i, const cast6_ctx_t *ctx){
115         D ^= f1(A, kr(i*4+3, ctx), ctx->km[i][3]);
116         A ^= f3(B, kr(i*4+2, ctx), ctx->km[i][2]);
117         B ^= f2(C, kr(i*4+1, ctx), ctx->km[i][1]);
118         C ^= f1(D, kr(i*4+0, ctx), ctx->km[i][0]);
119 }
120
121 void cast6_enc(void *buffer, const cast6_ctx_t *ctx){
122         uint8_t i;
123         for(i=0; i<32/4; ++i){
124                 ((uint32_t*)buffer)[i] = CHANGE_ENDIAN32(((uint32_t*)buffer)[i]);
125         }
126         for(i=0; i<6; ++i){
127                 q(buffer, i, ctx);
128         }
129         for(i=6; i<12; ++i){
130                 qbar(buffer, i, ctx);
131         }
132         for(i=0; i<32/4; ++i){
133                 ((uint32_t*)buffer)[i] = CHANGE_ENDIAN32(((uint32_t*)buffer)[i]);
134         }
135 }
136
137 void cast6_dec(void *buffer, const cast6_ctx_t *ctx){
138         uint8_t i;
139         for(i=0; i<32/4; ++i){
140                 ((uint32_t*)buffer)[i] = CHANGE_ENDIAN32(((uint32_t*)buffer)[i]);
141         }
142         for(i=12; i>6; --i){
143                 q(buffer, i-1, ctx);
144         }
145         for(i=6; i>0; --i){
146                 qbar(buffer, i-1, ctx);
147         }
148         for(i=0; i<32/4; ++i){
149                 ((uint32_t*)buffer)[i] = CHANGE_ENDIAN32(((uint32_t*)buffer)[i]);
150         }
151 }
152
153
154 #undef A
155 #undef B
156 #undef C
157 #undef D
158
159 #define A (((uint32_t*)buffer)[0])
160 #define B (((uint32_t*)buffer)[1])
161 #define C (((uint32_t*)buffer)[2])
162 #define D (((uint32_t*)buffer)[3])
163 #define E (((uint32_t*)buffer)[4])
164 #define F (((uint32_t*)buffer)[5])
165 #define G (((uint32_t*)buffer)[6])
166 #define H (((uint32_t*)buffer)[7])
167
168 /*
169  * we might later make it optional to use this small thing
170 static
171 void w(void *buffer, uint8_t *tr, uint32_t *tm){
172         G ^= f1(H, (tr[0]&0x0f)+(tr[5]&0x01)?0x10:0x00, tm[0]);
173         F ^= f2(G, (tr[0]>>4)  +(tr[5]&0x02)?0x10:0x00, tm[1]);
174         E ^= f3(F, (tr[1]&0x0f)+(tr[5]&0x04)?0x10:0x00, tm[2]);
175         D ^= f1(E, (tr[1]>>4)  +(tr[5]&0x08)?0x10:0x00, tm[3]);
176         C ^= f2(D, (tr[2]&0x0f)+(tr[5]&0x10)?0x10:0x00, tm[4]);
177         B ^= f3(C, (tr[2]>>4)  +(tr[5]&0x20)?0x10:0x00, tm[5]);
178         A ^= f1(B, (tr[3]&0x0f)+(tr[5]&0x40)?0x10:0x00, tm[6]);
179         H ^= f2(A, (tr[3]>>4)  +(tr[5]&0x80)?0x10:0x00, tm[7]);
180 }
181 */
182 static
183 void w(void *buffer, uint8_t *tr, uint32_t *tm){
184         G ^= f1(H, tr[0], tm[0]);
185         F ^= f2(G, tr[1], tm[1]);
186         E ^= f3(F, tr[2], tm[2]);
187         D ^= f1(E, tr[3], tm[3]);
188         C ^= f2(D, tr[4], tm[4]);
189         B ^= f3(C, tr[5], tm[5]);
190         A ^= f1(B, tr[6], tm[6]);
191         H ^= f2(A, tr[7], tm[7]);
192 }
193
194 /*
195 void dump_ctx(const cast6_ctx_t *ctx){
196         uint8_t i,t;
197         cli_putstr_P(PSTR("\r\n DBG:"));
198         for(i=0; i<12; ++i){
199                 cli_putstr_P(PSTR("\r\n DBG:"));
200                 cli_putstr_P(PSTR(" rotk1="));
201                 t=kr(i*4+0, ctx);
202                 cli_hexdump(&t,1);
203                 cli_putstr_P(PSTR("          rotk2="));
204                 t=kr(i*4+1, ctx);
205                 cli_hexdump(&t,1);
206                 cli_putstr_P(PSTR("          rotk3="));
207                 t=kr(i*4+2, ctx);
208                 cli_hexdump(&t,1);
209                 cli_putstr_P(PSTR("          rotk4="));
210                 t=kr(i*4+3, ctx);
211                 cli_hexdump(&t,1);
212                 cli_putstr_P(PSTR("\r\n     "));
213                 cli_putstr_P(PSTR(" mask1="));
214                 cli_hexdump(&(ctx->km[i][0]),4);
215                 cli_putstr_P(PSTR(" mask2="));
216                 cli_hexdump(&(ctx->km[i][1]),4);
217                 cli_putstr_P(PSTR(" mask3="));
218                 cli_hexdump(&(ctx->km[i][2]),4);
219                 cli_putstr_P(PSTR(" mask4="));
220                 cli_hexdump(&(ctx->km[i][3]),4);
221                 cli_putstr_P(PSTR("\r\n;-----"));
222         }
223 }
224 */
225
226 #define CR 19
227 #define CM 0x5A827999
228 #define MR 17 
229 #define MM 0x6ED9EBA1
230
231 void cast6_init(const void *key, uint16_t keysize_b, cast6_ctx_t *ctx){
232         uint8_t  buffer[32];
233         uint8_t  cr=CR, tr[8];
234         uint32_t cm=CM, tm[8];
235         uint8_t i,j;
236         
237         memset(buffer, 0, 32);
238         memcpy(buffer, key, (keysize_b+7)/8);
239         for(i=0; i<32/4; ++i){
240                 ((uint32_t*)buffer)[i] = CHANGE_ENDIAN32(((uint32_t*)buffer)[i]);
241         }
242
243         for(i=0; i<24; ++i){
244                 for(j=0; j<8; ++j){
245                         tm[j] = cm;
246                         cm += MM;
247                         tr[j] = cr&0x1F;
248                         cr += MR;
249                 }
250                 w(buffer, tr, tm);
251
252                 if(i&1){
253                         j=i/2;
254                         ctx->km[j][0]=H;
255                         ctx->km[j][1]=F;
256                         ctx->km[j][2]=D;
257                         ctx->km[j][3]=B;
258                         set_kr(buffer[0*4],j*4+0,ctx);
259                         set_kr(buffer[2*4],j*4+1,ctx);
260                         set_kr(buffer[4*4],j*4+2,ctx);
261                         set_kr(buffer[6*4],j*4+3,ctx);
262                 }
263         }
264 }
265
266
267