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