Added encryptio boolena indicator to silc_cipher_set_key.
[crypto.git] / lib / silccrypt / aes.c
1 /* Modified for SILC -Pekka */
2 /* Includes key scheduling in C always, and encryption and decryption in C
3    when assembler optimized version cannot be used. */
4 /*
5  ---------------------------------------------------------------------------
6  Copyright (c) 1998-2006, Brian Gladman, Worcester, UK. All rights reserved.
7
8  LICENSE TERMS
9
10  The free distribution and use of this software in both source and binary
11  form is allowed (with or without changes) provided that:
12
13    1. distributions of this source code include the above copyright
14       notice, this list of conditions and the following disclaimer;
15
16    2. distributions in binary form include the above copyright
17       notice, this list of conditions and the following disclaimer
18       in the documentation and/or other associated materials;
19
20    3. the copyright holder's name is not used to endorse products
21       built using this software without specific written permission.
22
23  ALTERNATIVELY, provided that this notice is retained in full, this product
24  may be distributed under the terms of the GNU General Public License (GPL),
25  in which case the provisions of the GPL apply INSTEAD OF those given above.
26
27  DISCLAIMER
28
29  This software is provided 'as is' with no explicit or implied warranties
30  in respect of its properties, including, but not limited to, correctness
31  and/or fitness for purpose.
32  ---------------------------------------------------------------------------
33  Issue 09/09/2006
34 */
35
36 #include "silc.h"
37 #include "rijndael_internal.h"
38 #include "aes.h"
39
40 /*
41  * SILC Crypto API for AES
42  */
43
44 /* Sets the key for the cipher. */
45
46 SILC_CIPHER_API_SET_KEY(aes)
47 {
48   if (encryption)
49     aes_encrypt_key(key, keylen, &((AesContext *)context)->u.enc);
50   else
51     aes_decrypt_key(key, keylen, &((AesContext *)context)->u.dec);
52   return TRUE;
53 }
54
55 /* Returns the size of the cipher context. */
56
57 SILC_CIPHER_API_CONTEXT_LEN(aes)
58 {
59   return sizeof(AesContext);
60 }
61
62 /* Encrypts with the cipher in CBC mode. Source and destination buffers
63    maybe one and same. */
64
65 SILC_CIPHER_API_ENCRYPT_CBC(aes)
66 {
67   int nb = len >> 4;
68
69   while(nb--) {
70     lp32(iv)[0] ^= lp32(src)[0];
71     lp32(iv)[1] ^= lp32(src)[1];
72     lp32(iv)[2] ^= lp32(src)[2];
73     lp32(iv)[3] ^= lp32(src)[3];
74     aes_encrypt(iv, iv, &((AesContext *)context)->u.enc);
75     memcpy(dst, iv, 16);
76     src += 16;
77     dst += 16;
78   }
79
80   return TRUE;
81 }
82
83 /* Decrypts with the cipher in CBC mode. Source and destination buffers
84    maybe one and same. */
85
86 SILC_CIPHER_API_DECRYPT_CBC(aes)
87 {
88   unsigned char tmp[16];
89   int nb = len >> 4;
90
91   while(nb--) {
92     memcpy(tmp, src, 16);
93     aes_decrypt(src, dst, &((AesContext *)context)->u.dec);
94     lp32(dst)[0] ^= lp32(iv)[0];
95     lp32(dst)[1] ^= lp32(iv)[1];
96     lp32(dst)[2] ^= lp32(iv)[2];
97     lp32(dst)[3] ^= lp32(iv)[3];
98     memcpy(iv, tmp, 16);
99     src += 16;
100     dst += 16;
101   }
102
103   return TRUE;
104 }
105
106 /****************************************************************************/
107
108 #if defined(__cplusplus)
109 extern "C"
110 {
111 #endif
112
113 #if defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 )
114 #  define XP_DIR __cdecl
115 #else
116 #  define XP_DIR
117 #endif
118
119 #define d_1(t,n,b,e)       ALIGN const XP_DIR t n[256]    =   b(e)
120 #define d_4(t,n,b,e,f,g,h) ALIGN const XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) }
121 ALIGN const uint_32t t_dec(r,c)[RC_LENGTH] = rc_data(w0);
122
123 #ifdef SILC_ASM_AES
124 d_1(uint_8t, t_dec(i,box), isb_data, h0);
125 #endif /* SILC_ASM_AES */
126 d_4(uint_32t, t_dec(f,n), sb_data, u0, u1, u2, u3);
127 d_4(uint_32t, t_dec(f,l), sb_data, w0, w1, w2, w3);
128 d_4(uint_32t, t_dec(i,n), isb_data, v0, v1, v2, v3);
129 d_4(uint_32t, t_dec(i,l), isb_data, w0, w1, w2, w3);
130 d_4(uint_32t, t_dec(i,m), mm_data, v0, v1, v2, v3);
131
132 #define ke4(k,i) \
133 {   k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \
134     k[4*(i)+5] = ss[1] ^= ss[0]; \
135     k[4*(i)+6] = ss[2] ^= ss[1]; \
136     k[4*(i)+7] = ss[3] ^= ss[2]; \
137 }
138
139 AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1])
140 {   uint_32t    ss[4];
141
142     cx->ks[0] = ss[0] = word_in(key, 0);
143     cx->ks[1] = ss[1] = word_in(key, 1);
144     cx->ks[2] = ss[2] = word_in(key, 2);
145     cx->ks[3] = ss[3] = word_in(key, 3);
146
147     ke4(cx->ks, 0);  ke4(cx->ks, 1);
148     ke4(cx->ks, 2);  ke4(cx->ks, 3);
149     ke4(cx->ks, 4);  ke4(cx->ks, 5);
150     ke4(cx->ks, 6);  ke4(cx->ks, 7);
151     ke4(cx->ks, 8);
152     ke4(cx->ks, 9);
153     cx->inf.l = 0;
154     cx->inf.b[0] = 10 * 16;
155 }
156
157 #define kef6(k,i) \
158 {   k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \
159     k[6*(i)+ 7] = ss[1] ^= ss[0]; \
160     k[6*(i)+ 8] = ss[2] ^= ss[1]; \
161     k[6*(i)+ 9] = ss[3] ^= ss[2]; \
162 }
163
164 #define ke6(k,i) \
165 {   kef6(k,i); \
166     k[6*(i)+10] = ss[4] ^= ss[3]; \
167     k[6*(i)+11] = ss[5] ^= ss[4]; \
168 }
169
170 AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1])
171 {   uint_32t    ss[6];
172
173     cx->ks[0] = ss[0] = word_in(key, 0);
174     cx->ks[1] = ss[1] = word_in(key, 1);
175     cx->ks[2] = ss[2] = word_in(key, 2);
176     cx->ks[3] = ss[3] = word_in(key, 3);
177     cx->ks[4] = ss[4] = word_in(key, 4);
178     cx->ks[5] = ss[5] = word_in(key, 5);
179
180     ke6(cx->ks, 0);  ke6(cx->ks, 1);
181     ke6(cx->ks, 2);  ke6(cx->ks, 3);
182     ke6(cx->ks, 4);  ke6(cx->ks, 5);
183     ke6(cx->ks, 6);
184     kef6(cx->ks, 7);
185     cx->inf.l = 0;
186     cx->inf.b[0] = 12 * 16;
187 }
188
189 #define kef8(k,i) \
190 {   k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \
191     k[8*(i)+ 9] = ss[1] ^= ss[0]; \
192     k[8*(i)+10] = ss[2] ^= ss[1]; \
193     k[8*(i)+11] = ss[3] ^= ss[2]; \
194 }
195
196 #define ke8(k,i) \
197 {   kef8(k,i); \
198     k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); \
199     k[8*(i)+13] = ss[5] ^= ss[4]; \
200     k[8*(i)+14] = ss[6] ^= ss[5]; \
201     k[8*(i)+15] = ss[7] ^= ss[6]; \
202 }
203
204 AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1])
205 {   uint_32t    ss[8];
206
207     cx->ks[0] = ss[0] = word_in(key, 0);
208     cx->ks[1] = ss[1] = word_in(key, 1);
209     cx->ks[2] = ss[2] = word_in(key, 2);
210     cx->ks[3] = ss[3] = word_in(key, 3);
211     cx->ks[4] = ss[4] = word_in(key, 4);
212     cx->ks[5] = ss[5] = word_in(key, 5);
213     cx->ks[6] = ss[6] = word_in(key, 6);
214     cx->ks[7] = ss[7] = word_in(key, 7);
215
216     ke8(cx->ks, 0); ke8(cx->ks, 1);
217     ke8(cx->ks, 2); ke8(cx->ks, 3);
218     ke8(cx->ks, 4); ke8(cx->ks, 5);
219     kef8(cx->ks, 6);
220     cx->inf.l = 0;
221     cx->inf.b[0] = 14 * 16;
222 }
223
224 AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1])
225 {
226     switch(key_len)
227     {
228     case 16: case 128: aes_encrypt_key128(key, cx); return;
229     case 24: case 192: aes_encrypt_key192(key, cx); return;
230     case 32: case 256: aes_encrypt_key256(key, cx); return;
231     }
232 }
233
234 #define v(n,i)  ((n) - (i) + 2 * ((i) & 3))
235 #define k4e(k,i) \
236 {   k[v(40,(4*(i))+4)] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \
237     k[v(40,(4*(i))+5)] = ss[1] ^= ss[0]; \
238     k[v(40,(4*(i))+6)] = ss[2] ^= ss[1]; \
239     k[v(40,(4*(i))+7)] = ss[3] ^= ss[2]; \
240 }
241
242 #define kdf4(k,i) \
243 {   ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \
244     ss[1] = ss[1] ^ ss[3]; \
245     ss[2] = ss[2] ^ ss[3]; \
246     ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \
247     ss[i % 4] ^= ss[4]; \
248     ss[4] ^= k[v(40,(4*(i)))];   k[v(40,(4*(i))+4)] = ff(ss[4]); \
249     ss[4] ^= k[v(40,(4*(i))+1)]; k[v(40,(4*(i))+5)] = ff(ss[4]); \
250     ss[4] ^= k[v(40,(4*(i))+2)]; k[v(40,(4*(i))+6)] = ff(ss[4]); \
251     ss[4] ^= k[v(40,(4*(i))+3)]; k[v(40,(4*(i))+7)] = ff(ss[4]); \
252 }
253
254 #define kd4(k,i) \
255 {   ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \
256     ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \
257     k[v(40,(4*(i))+4)] = ss[4] ^= k[v(40,(4*(i)))]; \
258     k[v(40,(4*(i))+5)] = ss[4] ^= k[v(40,(4*(i))+1)]; \
259     k[v(40,(4*(i))+6)] = ss[4] ^= k[v(40,(4*(i))+2)]; \
260     k[v(40,(4*(i))+7)] = ss[4] ^= k[v(40,(4*(i))+3)]; \
261 }
262
263 #define kdl4(k,i) \
264 {   ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \
265     k[v(40,(4*(i))+4)] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \
266     k[v(40,(4*(i))+5)] = ss[1] ^ ss[3]; \
267     k[v(40,(4*(i))+6)] = ss[0]; \
268     k[v(40,(4*(i))+7)] = ss[1]; \
269 }
270
271 AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1])
272 {   uint_32t    ss[5];
273 #if defined( d_vars )
274         d_vars;
275 #endif
276     cx->ks[v(40,(0))] = ss[0] = word_in(key, 0);
277     cx->ks[v(40,(1))] = ss[1] = word_in(key, 1);
278     cx->ks[v(40,(2))] = ss[2] = word_in(key, 2);
279     cx->ks[v(40,(3))] = ss[3] = word_in(key, 3);
280
281     kdf4(cx->ks, 0);  kd4(cx->ks, 1);
282      kd4(cx->ks, 2);  kd4(cx->ks, 3);
283      kd4(cx->ks, 4);  kd4(cx->ks, 5);
284      kd4(cx->ks, 6);  kd4(cx->ks, 7);
285      kd4(cx->ks, 8); kdl4(cx->ks, 9);
286     cx->inf.l = 0;
287     cx->inf.b[0] = 10 * 16;
288 }
289
290 #define k6ef(k,i) \
291 {   k[v(48,(6*(i))+ 6)] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \
292     k[v(48,(6*(i))+ 7)] = ss[1] ^= ss[0]; \
293     k[v(48,(6*(i))+ 8)] = ss[2] ^= ss[1]; \
294     k[v(48,(6*(i))+ 9)] = ss[3] ^= ss[2]; \
295 }
296
297 #define k6e(k,i) \
298 {   k6ef(k,i); \
299     k[v(48,(6*(i))+10)] = ss[4] ^= ss[3]; \
300     k[v(48,(6*(i))+11)] = ss[5] ^= ss[4]; \
301 }
302
303 #define kdf6(k,i) \
304 {   ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ff(ss[0]); \
305     ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ff(ss[1]); \
306     ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ff(ss[2]); \
307     ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ff(ss[3]); \
308     ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ff(ss[4]); \
309     ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ff(ss[5]); \
310 }
311
312 #define kd6(k,i) \
313 {   ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \
314     ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[v(48,(6*(i))+ 6)] = ss[6] ^= k[v(48,(6*(i)))]; \
315     ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[6] ^= k[v(48,(6*(i))+ 1)]; \
316     ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[6] ^= k[v(48,(6*(i))+ 2)]; \
317     ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[6] ^= k[v(48,(6*(i))+ 3)]; \
318     ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ss[6] ^= k[v(48,(6*(i))+ 4)]; \
319     ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ss[6] ^= k[v(48,(6*(i))+ 5)]; \
320 }
321
322 #define kdl6(k,i) \
323 {   ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ss[0]; \
324     ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[1]; \
325     ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[2]; \
326     ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[3]; \
327 }
328
329 AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1])
330 {   uint_32t    ss[7];
331 #if defined( d_vars )
332         d_vars;
333 #endif
334     cx->ks[v(48,(0))] = ss[0] = word_in(key, 0);
335     cx->ks[v(48,(1))] = ss[1] = word_in(key, 1);
336     cx->ks[v(48,(2))] = ss[2] = word_in(key, 2);
337     cx->ks[v(48,(3))] = ss[3] = word_in(key, 3);
338
339     cx->ks[v(48,(4))] = ff(ss[4] = word_in(key, 4));
340     cx->ks[v(48,(5))] = ff(ss[5] = word_in(key, 5));
341     kdf6(cx->ks, 0); kd6(cx->ks, 1);
342     kd6(cx->ks, 2);  kd6(cx->ks, 3);
343     kd6(cx->ks, 4);  kd6(cx->ks, 5);
344     kd6(cx->ks, 6); kdl6(cx->ks, 7);
345     cx->inf.l = 0;
346     cx->inf.b[0] = 12 * 16;
347 }
348
349 #define k8ef(k,i) \
350 {   k[v(56,(8*(i))+ 8)] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \
351     k[v(56,(8*(i))+ 9)] = ss[1] ^= ss[0]; \
352     k[v(56,(8*(i))+10)] = ss[2] ^= ss[1]; \
353     k[v(56,(8*(i))+11)] = ss[3] ^= ss[2]; \
354 }
355
356 #define k8e(k,i) \
357 {   k8ef(k,i); \
358     k[v(56,(8*(i))+12)] = ss[4] ^= ls_box(ss[3],0); \
359     k[v(56,(8*(i))+13)] = ss[5] ^= ss[4]; \
360     k[v(56,(8*(i))+14)] = ss[6] ^= ss[5]; \
361     k[v(56,(8*(i))+15)] = ss[7] ^= ss[6]; \
362 }
363
364 #define kdf8(k,i) \
365 {   ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ff(ss[0]); \
366     ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ff(ss[1]); \
367     ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ff(ss[2]); \
368     ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ff(ss[3]); \
369     ss[4] ^= ls_box(ss[3],0); k[v(56,(8*(i))+12)] = ff(ss[4]); \
370     ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ff(ss[5]); \
371     ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ff(ss[6]); \
372     ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ff(ss[7]); \
373 }
374
375 #define kd8(k,i) \
376 {   ss[8] = ls_box(ss[7],3) ^ t_use(r,c)[i]; \
377     ss[0] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+ 8)] = ss[8] ^= k[v(56,(8*(i)))]; \
378     ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[8] ^= k[v(56,(8*(i))+ 1)]; \
379     ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[8] ^= k[v(56,(8*(i))+ 2)]; \
380     ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[8] ^= k[v(56,(8*(i))+ 3)]; \
381     ss[8] = ls_box(ss[3],0); \
382     ss[4] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+12)] = ss[8] ^= k[v(56,(8*(i))+ 4)]; \
383     ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ss[8] ^= k[v(56,(8*(i))+ 5)]; \
384     ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ss[8] ^= k[v(56,(8*(i))+ 6)]; \
385     ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ss[8] ^= k[v(56,(8*(i))+ 7)]; \
386 }
387
388 #define kdl8(k,i) \
389 {   ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ss[0]; \
390     ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[1]; \
391     ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[2]; \
392     ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[3]; \
393 }
394
395 AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1])
396 {   uint_32t    ss[9];
397 #if defined( d_vars )
398         d_vars;
399 #endif
400     cx->ks[v(56,(0))] = ss[0] = word_in(key, 0);
401     cx->ks[v(56,(1))] = ss[1] = word_in(key, 1);
402     cx->ks[v(56,(2))] = ss[2] = word_in(key, 2);
403     cx->ks[v(56,(3))] = ss[3] = word_in(key, 3);
404
405     cx->ks[v(56,(4))] = ff(ss[4] = word_in(key, 4));
406     cx->ks[v(56,(5))] = ff(ss[5] = word_in(key, 5));
407     cx->ks[v(56,(6))] = ff(ss[6] = word_in(key, 6));
408     cx->ks[v(56,(7))] = ff(ss[7] = word_in(key, 7));
409     kdf8(cx->ks, 0); kd8(cx->ks, 1);
410     kd8(cx->ks, 2);  kd8(cx->ks, 3);
411     kd8(cx->ks, 4);  kd8(cx->ks, 5);
412     kdl8(cx->ks, 6);
413     cx->inf.l = 0;
414     cx->inf.b[0] = 14 * 16;
415 }
416
417 AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1])
418 {
419     switch(key_len)
420     {
421     case 16: case 128: aes_decrypt_key128(key, cx); return;
422     case 24: case 192: aes_decrypt_key192(key, cx); return;
423     case 32: case 256: aes_decrypt_key256(key, cx); return;
424     }
425 }
426
427 #ifndef SILC_ASM_AES
428 /* C version of AES */
429
430 #define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])
431 #define so(y,x,c)   word_out(y, c, s(x,c))
432 #define locals(y,x)     x[4],y[4]
433 #define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
434                         s(y,2) = s(x,2); s(y,3) = s(x,3);
435 #define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)
436 #define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
437 #define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
438
439 /* Visual C++ .Net v7.1 provides the fastest encryption code when using
440    Pentium optimiation with small code but this is poor for decryption
441    so we need to control this with the following VC++ pragmas
442 */
443
444 #if defined( _MSC_VER ) && !defined( _WIN64 )
445 #pragma optimize( "s", on )
446 #endif
447
448 #define fwd_var(x,r,c)\
449  ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
450  : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\
451  : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
452  :          ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))
453 #define fwd_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))
454 #define fwd_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c))
455
456 AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1])
457 {   uint_32t         locals(b0, b1);
458     const uint_32t   *kp;
459
460     kp = cx->ks;
461     state_in(b0, in, kp);
462
463     switch(cx->inf.b[0])
464     {
465     case 14 * 16:
466         round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);
467         round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);
468         kp += 2 * N_COLS;
469     case 12 * 16:
470         round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);
471         round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);
472         kp += 2 * N_COLS;
473     case 10 * 16:
474         round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);
475         round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);
476         round(fwd_rnd,  b1, b0, kp + 3 * N_COLS);
477         round(fwd_rnd,  b0, b1, kp + 4 * N_COLS);
478         round(fwd_rnd,  b1, b0, kp + 5 * N_COLS);
479         round(fwd_rnd,  b0, b1, kp + 6 * N_COLS);
480         round(fwd_rnd,  b1, b0, kp + 7 * N_COLS);
481         round(fwd_rnd,  b0, b1, kp + 8 * N_COLS);
482         round(fwd_rnd,  b1, b0, kp + 9 * N_COLS);
483         round(fwd_lrnd, b0, b1, kp +10 * N_COLS);
484     }
485
486     state_out(out, b0);
487 }
488
489 #define inv_var(x,r,c)\
490  ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
491  : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\
492  : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
493  :          ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0)))
494
495 #define inv_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c))
496 #define inv_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c))
497 #define key_ofs     0
498 #define rnd_key(n)  (kp + n * N_COLS)
499
500 AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1])
501 {   uint_32t        locals(b0, b1);
502     const uint_32t *kp;
503
504     kp = cx->ks + (key_ofs ? (cx->inf.b[0] >> 2) : 0);
505     state_in(b0, in, kp);
506
507     kp = cx->ks + (key_ofs ? 0 : (cx->inf.b[0] >> 2));
508     switch(cx->inf.b[0])
509     {
510     case 14 * 16:
511         round(inv_rnd,  b1, b0, rnd_key(-13));
512         round(inv_rnd,  b0, b1, rnd_key(-12));
513     case 12 * 16:
514         round(inv_rnd,  b1, b0, rnd_key(-11));
515         round(inv_rnd,  b0, b1, rnd_key(-10));
516     case 10 * 16:
517         round(inv_rnd,  b1, b0, rnd_key(-9));
518         round(inv_rnd,  b0, b1, rnd_key(-8));
519         round(inv_rnd,  b1, b0, rnd_key(-7));
520         round(inv_rnd,  b0, b1, rnd_key(-6));
521         round(inv_rnd,  b1, b0, rnd_key(-5));
522         round(inv_rnd,  b0, b1, rnd_key(-4));
523         round(inv_rnd,  b1, b0, rnd_key(-3));
524         round(inv_rnd,  b0, b1, rnd_key(-2));
525         round(inv_rnd,  b1, b0, rnd_key(-1));
526         round(inv_lrnd, b0, b1, rnd_key( 0));
527     }
528
529     state_out(out, b0);
530 }
531
532 #if defined(__cplusplus)
533 }
534 #endif
535
536 #endif /* SILC_ASM_AES */