]> git.cryptolib.org Git - avr-crypto-lib.git/blob - cast5.c
51e9e93823988c42fcaccecfe8e8557ec3834bdd
[avr-crypto-lib.git] / cast5.c
1 /* cast5.c */
2 /*
3     This file is part of the Crypto-avr-lib/microcrypt-lib.
4     Copyright (C) 2008  Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 /* 
20  * \file        cast5.c
21  * \author      Daniel Otte
22  * \email       daniel.otte@rub.de
23  * \date        2006-07-26
24  * \par License:
25  *  GPLv3 or later
26  * \brief Implementation of the CAST5 (aka CAST-128) cipher algorithm as described in RFC 2144
27  * 
28  */
29  
30  #include <stdint.h>
31  #include <string.h>
32  #include "cast5.h"
33  #include "config.h"
34  #include "debug.h"
35  
36  #undef DEBUG
37  
38  #ifdef DEBUG
39   #include "uart.h"
40  #endif
41  
42 #include "cast5-sbox.h"
43
44
45  
46 #define S5(x) pgm_read_dword(&s5[(x)])
47 #define S6(x) pgm_read_dword(&s6[(x)])
48 #define S7(x) pgm_read_dword(&s7[(x)])
49 #define S8(x) pgm_read_dword(&s8[(x)])
50
51  
52 void cast5_init_A(uint8_t *dest, uint8_t *src, bool bmode){
53         uint8_t mask = bmode?0x8:0;
54         *((uint32_t*)(&dest[0x0])) = *((uint32_t*)(&src[0x0^mask])) ^ S5(src[0xD^mask]) ^ S6(src[0xF^mask]) ^ S7(src[0xC^mask]) ^ S8(src[0xE^mask]) ^ S7(src[0x8^mask]);
55         *((uint32_t*)(&dest[0x4])) = *((uint32_t*)(&src[0x8^mask])) ^ S5(dest[0x0]) ^ S6(dest[0x2]) ^ S7(dest[0x1]) ^ S8(dest[0x3]) ^ S8(src[0xA^mask]);
56         *((uint32_t*)(&dest[0x8])) = *((uint32_t*)(&src[0xC^mask])) ^ S5(dest[0x7]) ^ S6(dest[0x6]) ^ S7(dest[0x5]) ^ S8(dest[0x4]) ^ S5(src[0x9^mask]);
57         *((uint32_t*)(&dest[0xC])) = *((uint32_t*)(&src[0x4^mask])) ^ S5(dest[0xA]) ^ S6(dest[0x9]) ^ S7(dest[0xB]) ^ S8(dest[0x8]) ^ S6(src[0xB^mask]);
58 }
59
60 void cast5_init_M(uint8_t *dest, uint8_t *src, bool nmode, bool xmode){
61         uint8_t nmt[] = {0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4}; /* nmode table */
62         uint8_t xmt[4][4] = {{0x2, 0x6, 0x9, 0xC}, {0x8, 0xD, 0x3, 0x7}, {0x3, 0x7, 0x8, 0xD}, {0x9, 0xC, 0x2, 0x6}};
63         #define NMT(x) (src[nmode?nmt[(x)]:(x)])
64         #define XMT(x) (src[xmt[(xmode<<1) + nmode][(x)]])
65         *((uint32_t*)(&dest[0x0])) = S5(NMT(0x8)) ^ S6(NMT(0x9)) ^ S7(NMT(0x7)) ^ S8(NMT(0x6)) ^ S5(XMT(0));
66         *((uint32_t*)(&dest[0x4])) = S5(NMT(0xA)) ^ S6(NMT(0xB)) ^ S7(NMT(0x5)) ^ S8(NMT(0x4)) ^ S6(XMT(1));
67         *((uint32_t*)(&dest[0x8])) = S5(NMT(0xC)) ^ S6(NMT(0xD)) ^ S7(NMT(0x3)) ^ S8(NMT(0x2)) ^ S7(XMT(2));
68         *((uint32_t*)(&dest[0xC])) = S5(NMT(0xE)) ^ S6(NMT(0xF)) ^ S7(NMT(0x1)) ^ S8(NMT(0x0)) ^ S8(XMT(3));
69 }
70
71 #define S5B(x) pgm_read_byte(3+(uint8_t*)(&s5[(x)]))
72 #define S6B(x) pgm_read_byte(3+(uint8_t*)(&s6[(x)]))
73 #define S7B(x) pgm_read_byte(3+(uint8_t*)(&s7[(x)]))
74 #define S8B(x) pgm_read_byte(3+(uint8_t*)(&s8[(x)]))
75
76 void cast5_init_rM(uint8_t *klo, uint8_t *khi, uint8_t offset, uint8_t *src, bool nmode, bool xmode){
77         uint8_t nmt[] = {0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4}; /* nmode table */
78         uint8_t xmt[4][4] = {{0x2, 0x6, 0x9, 0xC}, {0x8, 0xD, 0x3, 0x7}, {0x3, 0x7, 0x8, 0xD}, {0x9, 0xC, 0x2, 0x6}};
79         uint8_t t, h=0; 
80         t = S5B(NMT(0x8)) ^ S6B(NMT(0x9)) ^ S7B(NMT(0x7)) ^ S8B(NMT(0x6)) ^ S5B(XMT(0));
81                 klo[offset*2] |= (t & 0x0f);
82                 h |= (t&0x10); h>>=1;
83         t = S5B(NMT(0xA)) ^ S6B(NMT(0xB)) ^ S7B(NMT(0x5)) ^ S8B(NMT(0x4)) ^ S6B(XMT(1));
84                 klo[offset*2] |= (t<<4) & 0xf0;
85                 h |= t&0x10; h>>=1;
86         t = S5B(NMT(0xC)) ^ S6B(NMT(0xD)) ^ S7B(NMT(0x3)) ^ S8B(NMT(0x2)) ^ S7B(XMT(2));
87                 klo[offset*2+1] |= t&0xf;
88                 h |= t&0x10; h>>=1;
89         t = S5B(NMT(0xE)) ^ S6B(NMT(0xF)) ^ S7B(NMT(0x1)) ^ S8B(NMT(0x0)) ^ S8B(XMT(3));
90                 klo[offset*2+1] |= t<<4;
91                 h |= t&0x10; h >>=1;
92         #ifdef DEBUG
93                 uart_putstr("\r\n\t h="); uart_hexdump(&h,1);
94         #endif
95         khi[offset>>1] |= h<<((offset&0x1)?4:0);
96 }
97
98 #define S_5X(s) pgm_read_dword(&s5[BPX[(s)]])
99 #define S_6X(s) pgm_read_dword(&s6[BPX[(s)]])
100 #define S_7X(s) pgm_read_dword(&s7[BPX[(s)]])
101 #define S_8X(s) pgm_read_dword(&s8[BPX[(s)]])
102
103 #define S_5Z(s) pgm_read_dword(&s5[BPZ[(s)]])
104 #define S_6Z(s) pgm_read_dword(&s6[BPZ[(s)]])
105 #define S_7Z(s) pgm_read_dword(&s7[BPZ[(s)]])
106 #define S_8Z(s) pgm_read_dword(&s8[BPZ[(s)]])
107
108
109
110 /**
111  * \brief sets up round keys (context) for cast5 en/decryption.
112  * @param s Pointer to cast5 context.
113  * @param key Pointer to binary key.
114  * @param keylength length of keydata in bits.
115  */
116 void cast5_init(cast5_ctx_t* s, uint8_t* key, uint8_t keylength){
117          /* we migth return if the key is valid and if setup was sucessfull */
118         uint32_t x[4], z[4];
119         #define BPX ((uint8_t*)&(x[0]))
120         #define BPZ ((uint8_t*)&(z[0]))
121         s->shortkey = (keylength<=80);
122         /* littel endian only! */
123         memset(&(x[0]), 0 ,16); /* set x to zero */
124         if(keylength > 128)
125                 keylength=128;
126         memcpy(&(x[0]), key, (keylength+7)/8);
127         
128
129         /* todo: merge a and b and compress the whole stuff */
130         /***** A *****/
131         cast5_init_A((uint8_t*)(&z[0]), (uint8_t*)(&x[0]), false);      
132         /***** M *****/
133         cast5_init_M((uint8_t*)(&(s->mask[0])), (uint8_t*)(&z[0]), false, false);
134         /***** B *****/
135         cast5_init_A((uint8_t*)(&x[0]), (uint8_t*)(&z[0]), true);
136         /***** N *****/
137         cast5_init_M((uint8_t*)(&(s->mask[4])), (uint8_t*)(&x[0]), true, false);
138         /***** A *****/
139         cast5_init_A((uint8_t*)(&z[0]), (uint8_t*)(&x[0]), false);
140         /***** N' *****/
141         cast5_init_M((uint8_t*)(&(s->mask[8])), (uint8_t*)(&z[0]), true, true);
142         /***** B *****/
143         cast5_init_A((uint8_t*)(&x[0]), (uint8_t*)(&z[0]), true);
144         /***** M' *****/
145         cast5_init_M((uint8_t*)(&(s->mask[12])), (uint8_t*)(&x[0]), false, true);
146         
147         /* that were the masking keys, now the rotation keys */
148         /* set the keys to zero */
149         memset(&(s->rotl[0]),0,8);
150         s->roth[0]=s->roth[1]=0;
151         /***** A *****/
152         cast5_init_A((uint8_t*)(&z[0]), (uint8_t*)(&x[0]), false);
153         /***** M *****/
154         cast5_init_rM(&(s->rotl[0]), &(s->roth[0]), 0, (uint8_t*)(&z[0]), false, false);
155         /***** B *****/
156         cast5_init_A((uint8_t*)(&x[0]), (uint8_t*)(&z[0]), true);
157         /***** N *****/
158         cast5_init_rM(&(s->rotl[0]), &(s->roth[0]), 1, (uint8_t*)(&x[0]), true, false);
159         /***** A *****/
160         cast5_init_A((uint8_t*)(&z[0]), (uint8_t*)(&x[0]), false);
161         /***** N' *****/
162         cast5_init_rM(&(s->rotl[0]), &(s->roth[0]), 2, (uint8_t*)(&z[0]), true, true);
163         /***** B *****/
164         cast5_init_A((uint8_t*)(&x[0]), (uint8_t*)(&z[0]), true);
165         /***** M' *****/
166         cast5_init_rM(&(s->rotl[0]), &(s->roth[0]), 3, (uint8_t*)(&x[0]), false, true);
167         /* done ;-) */
168 }
169
170
171
172 /********************************************************************************************************/
173
174 #define ROTL32(a,n) ((a)<<(n) | (a)>>(32-(n)))
175 #define CHANGE_ENDIAN32(x) ((x)<<24 | (x)>>24 | ((x)&0xff00)<<8 | ((x)&0xff0000)>>8 )
176
177 typedef uint32_t cast5_f_t(uint32_t,uint32_t,uint8_t);
178
179 #define IA 3
180 #define IB 2
181 #define IC 1
182 #define ID 0
183
184
185 uint32_t cast5_f1(uint32_t d, uint32_t m, uint8_t r){
186         uint32_t t;
187         t = ROTL32((d + m),r);
188 #ifdef DEBUG
189         uint32_t ia,ib,ic,id;
190         uart_putstr("\r\n f1("); uart_hexdump(&d, 4); uart_putc(',');
191                 uart_hexdump(&m , 4); uart_putc(','); uart_hexdump(&r, 1);uart_putstr("): I=");
192                 uart_hexdump(&t, 4);
193         ia = pgm_read_dword(&s1[((uint8_t*)&t)[IA]] );
194         ib = pgm_read_dword(&s2[((uint8_t*)&t)[IB]] );
195         ic = pgm_read_dword(&s3[((uint8_t*)&t)[IC]] );
196         id = pgm_read_dword(&s4[((uint8_t*)&t)[ID]] );
197         uart_putstr("\r\n\tIA="); uart_hexdump(&ia, 4);
198         uart_putstr("\r\n\tIB="); uart_hexdump(&ib, 4);
199         uart_putstr("\r\n\tIC="); uart_hexdump(&ic, 4);
200         uart_putstr("\r\n\tID="); uart_hexdump(&id, 4);
201
202         return (((ia ^ ib) - ic) + id);
203
204 #else
205         
206         return (((pgm_read_dword(&s1[((uint8_t*)&t)[IA]] ) ^ pgm_read_dword(&s2[((uint8_t*)&t)[IB]] )) 
207                 - pgm_read_dword(&s3[((uint8_t*)&t)[IC]] )) + pgm_read_dword(&s4[((uint8_t*)&t)[ID]]));
208
209 #endif
210 }
211
212
213 uint32_t cast5_f2(uint32_t d, uint32_t m, uint8_t r){
214         uint32_t t;
215         t = ROTL32((d ^ m),r);
216 #ifdef DEBUG
217         uint32_t ia,ib,ic,id;
218         uart_putstr("\r\n f2("); uart_hexdump(&d, 4); uart_putc(',');
219                 uart_hexdump(&m , 4); uart_putc(','); uart_hexdump(&r, 1);uart_putstr("): I=");
220                 uart_hexdump(&t, 4);
221
222         ia = pgm_read_dword(&s1[((uint8_t*)&t)[IA]] );
223         ib = pgm_read_dword(&s2[((uint8_t*)&t)[IB]] );
224         ic = pgm_read_dword(&s3[((uint8_t*)&t)[IC]] );
225         id = pgm_read_dword(&s4[((uint8_t*)&t)[ID]] );
226         
227         uart_putstr("\r\n\tIA="); uart_hexdump(&ia, 4);
228         uart_putstr("\r\n\tIB="); uart_hexdump(&ib, 4);
229         uart_putstr("\r\n\tIC="); uart_hexdump(&ic, 4);
230         uart_putstr("\r\n\tID="); uart_hexdump(&id, 4);
231
232         return (((ia - ib) + ic) ^ id);
233 #else
234         
235         return (((pgm_read_dword(&s1[((uint8_t*)&t)[IA]]) 
236                 - pgm_read_dword(&s2[((uint8_t*)&t)[IB]]) ) 
237                     + pgm_read_dword(&s3[((uint8_t*)&t)[IC]]) ) 
238                     ^ pgm_read_dword(&s4[((uint8_t*)&t)[ID]]) );
239
240 #endif
241 }
242
243 uint32_t cast5_f3(uint32_t d, uint32_t m, uint8_t r){
244         uint32_t t;
245         t = ROTL32((m - d),r);
246
247 #ifdef DEBUG
248         uint32_t ia,ib,ic,id;
249
250         uart_putstr("\r\n f3("); uart_hexdump(&d, 4); uart_putc(',');
251                 uart_hexdump(&m , 4); uart_putc(','); uart_hexdump(&r, 1);uart_putstr("): I=");
252                 uart_hexdump(&t, 4);
253
254         ia = pgm_read_dword(&s1[((uint8_t*)&t)[IA]] );
255         ib = pgm_read_dword(&s2[((uint8_t*)&t)[IB]] );
256         ic = pgm_read_dword(&s3[((uint8_t*)&t)[IC]] );
257         id = pgm_read_dword(&s4[((uint8_t*)&t)[ID]] );
258         
259         uart_putstr("\r\n\tIA="); uart_hexdump(&ia, 4);
260         uart_putstr("\r\n\tIB="); uart_hexdump(&ib, 4);
261         uart_putstr("\r\n\tIC="); uart_hexdump(&ic, 4);
262         uart_putstr("\r\n\tID="); uart_hexdump(&id, 4);
263         return (((ia + ib) ^ ic) - id);
264 #else
265         return ((pgm_read_dword(&s1[((uint8_t*)&t)[IA]] ) + pgm_read_dword(&s2[((uint8_t*)&t)[IB]] )) 
266                 ^ pgm_read_dword(&s3[((uint8_t*)&t)[IC]] )) - pgm_read_dword(&s4[((uint8_t*)&t)[ID]] );
267
268 #endif
269 }
270
271 /*************************************************************************/
272
273 /**
274  * \brief encrypts a datablock with cast5
275  * @param s Pointer to cast5 roundkeys (context)
276  * @param block Pointer to datablock
277  */
278 void cast5_enc(cast5_ctx_t *s, void* block){
279         uint32_t l,r, x, y;
280         uint8_t i;
281         cast5_f_t* f[]={cast5_f1,cast5_f2,cast5_f3};
282         l=((uint32_t*)block)[0];
283         r=((uint32_t*)block)[1];
284 //      uart_putstr("\r\n round[-1] = ");
285 //      uart_hexdump(&r, 4);
286         for (i=0;i<(s->shortkey?12:16);++i){
287                 x = r;
288                 y = (f[i%3])(CHANGE_ENDIAN32(r), CHANGE_ENDIAN32(s->mask[i]), 
289                         (((s->roth[i>>3]) & (1<<(i&0x7)))?0x10:0x00) 
290                          + ( ((s->rotl[i>>1])>>((i&1)?4:0)) & 0x0f) );
291                 r = l ^ CHANGE_ENDIAN32(y);
292 //              uart_putstr("\r\n round["); DEBUG_B(i); uart_putstr("] = ");
293 //              uart_hexdump(&r, 4);
294                 l = x;
295         }
296         ((uint32_t*)block)[0]=r;
297         ((uint32_t*)block)[1]=l;
298 }
299
300 /*************************************************************************/
301
302 /**
303  * \brief decrypts a datablock with cast5
304  * @param s Pointer to cast5 roundkeys (context)
305  * @param block Pointer to datablock
306  */
307 void cast5_dec(cast5_ctx_t *s, void* block){
308         uint32_t l,r, x, y;
309         int8_t i, rounds;
310         cast5_f_t* f[]={cast5_f1,cast5_f2,cast5_f3};
311         l=((uint32_t*)block)[0];
312         r=((uint32_t*)block)[1];
313         rounds = (s->shortkey?12:16);
314         for (i=rounds-1; i>=0 ;--i){
315                 x = r;
316                 y = (f[i%3])(CHANGE_ENDIAN32(r), CHANGE_ENDIAN32(s->mask[i]), 
317                         (((s->roth[i>>3]) & (1<<(i&0x7)))?0x10:0x00) 
318                          + ( ((s->rotl[i>>1])>>((i&1)?4:0)) & 0x0f) );
319                 r = l ^ CHANGE_ENDIAN32(y);
320                 l = x;
321         }
322         ((uint32_t*)block)[0]=r;
323         ((uint32_t*)block)[1]=l;
324 }
325
326
327 /*********************************************************************************************************/
328 /*********************************************************************************************************/
329 /*********************************************************************************************************/
330
331 #if 0
332
333 void cast5_old_init(cast5_ctx_t* s, uint8_t* key, uint8_t keylength){
334          /* we migth return if the key is valid and if setup was sucessfull */
335         uint32_t x[4], z[4], t;
336         #define BPX ((uint8_t*)&(x[0]))
337         #define BPZ ((uint8_t*)&(z[0]))
338         s->shortkey = (keylength<=80);
339         /* littel endian only! */
340         memset(&(x[0]), 0 ,16); /* set x to zero */
341         memcpy(&(x[0]), key, keylength/8);
342         
343
344         /* todo: merge a and b and compress the whole stuff */
345         /***** A *****/
346         z[0] = x[0] ^ S_5X(0xD) ^ S_6X(0xF) ^ S_7X(0xC) ^ S_8X(0xE) ^ S_7X(0x8);        
347         z[1] = x[2] ^ S_5Z(0x0) ^ S_6Z(0x2) ^ S_7Z(0x1) ^ S_8Z(0x3) ^ S_8X(0xA);
348         z[2] = x[3] ^ S_5Z(0x7) ^ S_6Z(0x6) ^ S_7Z(0x5) ^ S_8Z(0x4) ^ S_5X(0x9);
349         z[3] = x[1] ^ S_5Z(0xA) ^ S_6Z(0x9) ^ S_7Z(0xB) ^ S_8Z(0x8) ^ S_6X(0xB);
350         /***** M *****/
351         s->mask[0] = S_5Z(0x8) ^ S_6Z(0x9) ^ S_7Z(0x7) ^ S_8Z(0x6) ^ S_5Z(0x2);
352         s->mask[1] = S_5Z(0xA) ^ S_6Z(0xB) ^ S_7Z(0x5) ^ S_8Z(0x4) ^ S_6Z(0x6);
353         s->mask[2] = S_5Z(0xC) ^ S_6Z(0xD) ^ S_7Z(0x3) ^ S_8Z(0x2) ^ S_7Z(0x9);
354         s->mask[3] = S_5Z(0xE) ^ S_6Z(0xF) ^ S_7Z(0x1) ^ S_8Z(0x0) ^ S_8Z(0xC);
355         /***** B *****/
356         x[0] = z[2] ^ S_5Z(0x5) ^ S_6Z(0x7) ^ S_7Z(0x4) ^ S_8Z(0x6) ^ S_7Z(0x0);
357         x[1] = z[0] ^ S_5X(0x0) ^ S_6X(0x2) ^ S_7X(0x1) ^ S_8X(0x3) ^ S_8Z(0x2);
358         x[2] = z[1] ^ S_5X(0x7) ^ S_6X(0x6) ^ S_7X(0x5) ^ S_8X(0x4) ^ S_5Z(0x1);
359         x[3] = z[3] ^ S_5X(0xA) ^ S_6X(0x9) ^ S_7X(0xB) ^ S_8X(0x8) ^ S_6Z(0x3);
360         /***** N *****/
361         s->mask[4] = S_5X(0x3) ^ S_6X(0x2) ^ S_7X(0xC) ^ S_8X(0xD) ^ S_5X(0x8);
362         s->mask[5] = S_5X(0x1) ^ S_6X(0x0) ^ S_7X(0xE) ^ S_8X(0xF) ^ S_6X(0xD);
363         s->mask[6] = S_5X(0x7) ^ S_6X(0x6) ^ S_7X(0x8) ^ S_8X(0x9) ^ S_7X(0x3);
364         s->mask[7] = S_5X(0x5) ^ S_6X(0x4) ^ S_7X(0xA) ^ S_8X(0xB) ^ S_8X(0x7);
365         /***** A *****/
366         z[0] = x[0] ^ S_5X(0xD) ^ S_6X(0xF) ^ S_7X(0xC) ^ S_8X(0xE) ^ S_7X(0x8);
367         z[1] = x[2] ^ S_5Z(0x0) ^ S_6Z(0x2) ^ S_7Z(0x1) ^ S_8Z(0x3) ^ S_8X(0xA);
368         z[2] = x[3] ^ S_5Z(0x7) ^ S_6Z(0x6) ^ S_7Z(0x5) ^ S_8Z(0x4) ^ S_5X(0x9);
369         z[3] = x[1] ^ S_5Z(0xA) ^ S_6Z(0x9) ^ S_7Z(0xB) ^ S_8Z(0x8) ^ S_6X(0xB);
370         /***** N' *****/
371         s->mask[8] = S_5Z(0x3) ^ S_6Z(0x2) ^ S_7Z(0xC) ^ S_8Z(0xD) ^ S_5Z(0x9);
372         s->mask[9] = S_5Z(0x1) ^ S_6Z(0x0) ^ S_7Z(0xE) ^ S_8Z(0xF) ^ S_6Z(0xC);
373         s->mask[10] = S_5Z(0x7) ^ S_6Z(0x6) ^ S_7Z(0x8) ^ S_8Z(0x9) ^ S_7Z(0x2);
374         s->mask[11] = S_5Z(0x5) ^ S_6Z(0x4) ^ S_7Z(0xA) ^ S_8Z(0xB) ^ S_8Z(0x6);
375         /***** B *****/
376         x[0] = z[2] ^ S_5Z(0x5) ^ S_6Z(0x7) ^ S_7Z(0x4) ^ S_8Z(0x6) ^ S_7Z(0x0);
377         x[1] = z[0] ^ S_5X(0x0) ^ S_6X(0x2) ^ S_7X(0x1) ^ S_8X(0x3) ^ S_8Z(0x2);
378         x[2] = z[1] ^ S_5X(0x7) ^ S_6X(0x6) ^ S_7X(0x5) ^ S_8X(0x4) ^ S_5Z(0x1);
379         x[3] = z[3] ^ S_5X(0xA) ^ S_6X(0x9) ^ S_7X(0xB) ^ S_8X(0x8) ^ S_6Z(0x3);
380         /***** M' *****/
381         s->mask[12] = S_5X(0x8) ^ S_6X(0x9) ^ S_7X(0x7) ^ S_8X(0x6) ^ S_5X(0x3);
382         s->mask[13] = S_5X(0xA) ^ S_6X(0xB) ^ S_7X(0x5) ^ S_8X(0x4) ^ S_6X(0x7);
383         s->mask[14] = S_5X(0xC) ^ S_6X(0xD) ^ S_7X(0x3) ^ S_8X(0x2) ^ S_7X(0x8);
384         s->mask[15] = S_5X(0xE) ^ S_6X(0xF) ^ S_7X(0x1) ^ S_8X(0x0) ^ S_8X(0xD);
385
386         /* that were the masking keys, now the rotation keys */
387         /* set the keys to zero */
388         memset(&(s->rotl[0]),0,8);
389         s->roth[0]=s->roth[1]=0;
390         /***** A *****/
391         z[0] = x[0] ^ S_5X(0xD) ^ S_6X(0xF) ^ S_7X(0xC) ^ S_8X(0xE) ^ S_7X(0x8);
392         z[1] = x[2] ^ S_5Z(0x0) ^ S_6Z(0x2) ^ S_7Z(0x1) ^ S_8Z(0x3) ^ S_8X(0xA);
393         z[2] = x[3] ^ S_5Z(0x7) ^ S_6Z(0x6) ^ S_7Z(0x5) ^ S_8Z(0x4) ^ S_5X(0x9);
394         z[3] = x[1] ^ S_5Z(0xA) ^ S_6Z(0x9) ^ S_7Z(0xB) ^ S_8Z(0x8) ^ S_6X(0xB);
395         /***** M *****/
396         t = S_5Z(0x8) ^ S_6Z(0x9) ^ S_7Z(0x7) ^ S_8Z(0x6) ^ S_5Z(0x2);
397         t >>= 24;
398         s->rotl[0] |= t & 0x0f;         
399         s->roth[0] |= (t >> 4) & (1<<0);
400         t = S_5Z(0xA) ^ S_6Z(0xB) ^ S_7Z(0x5) ^ S_8Z(0x4) ^ S_6Z(0x6);
401         t >>= 24;
402         s->rotl[0] |= (t<<4) & 0xf0;
403         s->roth[0] |= (t >> 3) & (1<<1);
404         t = S_5Z(0xC) ^ S_6Z(0xD) ^ S_7Z(0x3) ^ S_8Z(0x2) ^ S_7Z(0x9);
405         t >>= 24;
406         s->rotl[1] |= t & 0x0f;         
407         s->roth[0] |= (t >> 2) & (1<<2);
408         t = S_5Z(0xE) ^ S_6Z(0xF) ^ S_7Z(0x1) ^ S_8Z(0x0) ^ S_8Z(0xC);
409         t >>= 24;
410         s->rotl[1] |= (t<<4) & 0xf0;
411         s->roth[0] |= (t >> 1) & (1<<3);
412         /***** B *****/
413         x[0] = z[2] ^ S_5Z(0x5) ^ S_6Z(0x7) ^ S_7Z(0x4) ^ S_8Z(0x6) ^ S_7Z(0x0);
414         x[1] = z[0] ^ S_5X(0x0) ^ S_6X(0x2) ^ S_7X(0x1) ^ S_8X(0x3) ^ S_8Z(0x2);
415         x[2] = z[1] ^ S_5X(0x7) ^ S_6X(0x6) ^ S_7X(0x5) ^ S_8X(0x4) ^ S_5Z(0x1);
416         x[3] = z[3] ^ S_5X(0xA) ^ S_6X(0x9) ^ S_7X(0xB) ^ S_8X(0x8) ^ S_6Z(0x3);
417         /***** N *****/
418         t = S_5X(0x3) ^ S_6X(0x2) ^ S_7X(0xC) ^ S_8X(0xD) ^ S_5X(0x8);
419         t >>= 24;
420         s->rotl[2] |= t & 0x0f;         
421         s->roth[0] |= t & (1<<4);
422         t = S_5X(0x1) ^ S_6X(0x0) ^ S_7X(0xE) ^ S_8X(0xF) ^ S_6X(0xD);
423         t >>= 24;
424         s->rotl[2] |= (t<<4) & 0xf0;            
425         s->roth[0] |= (t<<1) & (1<<5);
426         t = S_5X(0x7) ^ S_6X(0x6) ^ S_7X(0x8) ^ S_8X(0x9) ^ S_7X(0x3);
427         t >>= 24;
428         s->rotl[3] |= t & 0x0f;         
429         s->roth[0] |= (t<<2) & (1<<6);
430         t = S_5X(0x5) ^ S_6X(0x4) ^ S_7X(0xA) ^ S_8X(0xB) ^ S_8X(0x7);
431         t >>= 24;
432         s->rotl[3] |= (t<<4) & 0xf0;            
433         s->roth[0] |= (t<<3) & (1<<7);
434         /***** A *****/
435         z[0] = x[0] ^ S_5X(0xD) ^ S_6X(0xF) ^ S_7X(0xC) ^ S_8X(0xE) ^ S_7X(0x8);
436         z[1] = x[2] ^ S_5Z(0x0) ^ S_6Z(0x2) ^ S_7Z(0x1) ^ S_8Z(0x3) ^ S_8X(0xA);
437         z[2] = x[3] ^ S_5Z(0x7) ^ S_6Z(0x6) ^ S_7Z(0x5) ^ S_8Z(0x4) ^ S_5X(0x9);
438         z[3] = x[1] ^ S_5Z(0xA) ^ S_6Z(0x9) ^ S_7Z(0xB) ^ S_8Z(0x8) ^ S_6X(0xB);
439         /***** N' *****/
440         t = S_5Z(0x3) ^ S_6Z(0x2) ^ S_7Z(0xC) ^ S_8Z(0xD) ^ S_5Z(0x9);
441         t >>= 24;
442         s->rotl[4] |= t & 0x0f;         
443         s->roth[1] |= (t>>4) & (1<<0);
444         t = S_5Z(0x1) ^ S_6Z(0x0) ^ S_7Z(0xE) ^ S_8Z(0xF) ^ S_6Z(0xC);
445         t >>= 24;
446         s->rotl[4] |= (t<<4) & 0xf0;            
447         s->roth[1] |= (t>>3) & (1<<1);
448         t = S_5Z(0x7) ^ S_6Z(0x6) ^ S_7Z(0x8) ^ S_8Z(0x9) ^ S_7Z(0x2);
449         t >>= 24;
450         s->rotl[5] |= t & 0x0f;         
451         s->roth[1] |= (t>>2) & (1<<2);
452         t = S_5Z(0x5) ^ S_6Z(0x4) ^ S_7Z(0xA) ^ S_8Z(0xB) ^ S_8Z(0x6);
453         t >>= 24;
454         s->rotl[5] |= (t<<4) & 0xf0;            
455         s->roth[1] |= (t>>1) & (1<<3);
456         /***** B *****/
457         x[0] = z[2] ^ S_5Z(0x5) ^ S_6Z(0x7) ^ S_7Z(0x4) ^ S_8Z(0x6) ^ S_7Z(0x0);
458         x[1] = z[0] ^ S_5X(0x0) ^ S_6X(0x2) ^ S_7X(0x1) ^ S_8X(0x3) ^ S_8Z(0x2);
459         x[2] = z[1] ^ S_5X(0x7) ^ S_6X(0x6) ^ S_7X(0x5) ^ S_8X(0x4) ^ S_5Z(0x1);
460         x[3] = z[3] ^ S_5X(0xA) ^ S_6X(0x9) ^ S_7X(0xB) ^ S_8X(0x8) ^ S_6Z(0x3);
461         /***** M' *****/
462         t = S_5X(0x8) ^ S_6X(0x9) ^ S_7X(0x7) ^ S_8X(0x6) ^ S_5X(0x3);
463         t >>= 24;
464         s->rotl[6] |= t & 0x0f;         
465         s->roth[1] |= t & (1<<4);
466         t = S_5X(0xA) ^ S_6X(0xB) ^ S_7X(0x5) ^ S_8X(0x4) ^ S_6X(0x7);
467         t >>= 24;
468         s->rotl[6] |= (t<<4) & 0xf0;            
469         s->roth[1] |= (t<<1) & (1<<5);
470         t = S_5X(0xC) ^ S_6X(0xD) ^ S_7X(0x3) ^ S_8X(0x2) ^ S_7X(0x8);
471         t >>= 24;
472         s->rotl[7] |= t & 0x0f;         
473         s->roth[1] |= (t<<2) & (1<<6);
474         t = S_5X(0xE) ^ S_6X(0xF) ^ S_7X(0x1) ^ S_8X(0x0) ^ S_8X(0xD);
475         t >>= 24;
476         s->rotl[7] |= (t<<4) & 0xf0;            
477         s->roth[1] |= (t<<3) & (1<<7);
478         
479         /* done ;-) */
480 }
481
482 #endif
483
484
485
486