1 /* AES implementation by Tom St Denis
3 * Derived from the Public Domain source code by
8 * @version 3.0 (December 2000)
10 * Optimised ANSI C code for the Rijndael cipher (now AES)
12 * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
13 * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
14 * @author Paulo Barreto <paulo.barreto@terra.com.br>
22 const struct _cipher_descriptor rijndael_desc =
28 &rijndael_ecb_encrypt,
29 &rijndael_ecb_decrypt,
34 const struct _cipher_descriptor aes_desc =
40 &rijndael_ecb_encrypt,
41 &rijndael_ecb_decrypt,
48 int rijndael_setup(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
51 unsigned long temp, *rk;
54 _ARGCHK(skey != NULL);
56 if (keylen != 16 && keylen != 24 && keylen != 32) {
57 return CRYPT_INVALID_KEYSIZE;
60 if (rounds != 0 && rounds != (10 + ((keylen/8)-2)*2)) {
61 return CRYPT_INVALID_ROUNDS;
64 skey->rijndael.Nr = 10 + ((keylen/8)-2)*2;
66 /* setup the forward key */
67 rk = skey->rijndael.eK;
69 LOAD32H(rk[1], key + 4);
70 LOAD32H(rk[2], key + 8);
71 LOAD32H(rk[3], key + 12);
76 (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
77 (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
78 (Te4[(temp ) & 0xff] & 0x0000ff00) ^
79 (Te4[(temp >> 24) ] & 0x000000ff) ^
81 rk[5] = rk[1] ^ rk[4];
82 rk[6] = rk[2] ^ rk[5];
83 rk[7] = rk[3] ^ rk[6];
89 } else if (keylen == 24) {
90 LOAD32H(rk[4], key + 16);
91 LOAD32H(rk[5], key + 20);
94 temp = skey->rijndael.eK[rk - skey->rijndael.eK + 5];
99 (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
100 (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
101 (Te4[(temp ) & 0xff] & 0x0000ff00) ^
102 (Te4[(temp >> 24) ] & 0x000000ff) ^
104 rk[ 7] = rk[ 1] ^ rk[ 6];
105 rk[ 8] = rk[ 2] ^ rk[ 7];
106 rk[ 9] = rk[ 3] ^ rk[ 8];
110 rk[10] = rk[ 4] ^ rk[ 9];
111 rk[11] = rk[ 5] ^ rk[10];
114 } else if (keylen == 32) {
115 LOAD32H(rk[4], key + 16);
116 LOAD32H(rk[5], key + 20);
117 LOAD32H(rk[6], key + 24);
118 LOAD32H(rk[7], key + 28);
121 temp = skey->rijndael.eK[rk - skey->rijndael.eK + 7];
126 (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
127 (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
128 (Te4[(temp ) & 0xff] & 0x0000ff00) ^
129 (Te4[(temp >> 24) ] & 0x000000ff) ^
131 rk[ 9] = rk[ 1] ^ rk[ 8];
132 rk[10] = rk[ 2] ^ rk[ 9];
133 rk[11] = rk[ 3] ^ rk[10];
139 (Te4[(temp >> 24) ] & 0xff000000) ^
140 (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
141 (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^
142 (Te4[(temp ) & 0xff] & 0x000000ff);
143 rk[13] = rk[ 5] ^ rk[12];
144 rk[14] = rk[ 6] ^ rk[13];
145 rk[15] = rk[ 7] ^ rk[14];
150 /* setup the inverse key now */
151 memcpy(skey->rijndael.dK, skey->rijndael.eK, sizeof(skey->rijndael.eK));
152 rk = skey->rijndael.dK;
154 for (i = 0, j = 4*skey->rijndael.Nr; i < j; i += 4, j -= 4) {
155 temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
156 temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
157 temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
158 temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
160 /* apply the inverse MixColumn transform to all round keys but the first and the last: */
161 for (i = 1; i < skey->rijndael.Nr; i++) {
164 Td0[Te4[(rk[0] >> 24) ] & 0xff] ^
165 Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
166 Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^
167 Td3[Te4[(rk[0] ) & 0xff] & 0xff];
169 Td0[Te4[(rk[1] >> 24) ] & 0xff] ^
170 Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
171 Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^
172 Td3[Te4[(rk[1] ) & 0xff] & 0xff];
174 Td0[Te4[(rk[2] >> 24) ] & 0xff] ^
175 Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
176 Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^
177 Td3[Te4[(rk[2] ) & 0xff] & 0xff];
179 Td0[Te4[(rk[3] >> 24) ] & 0xff] ^
180 Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
181 Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^
182 Td3[Te4[(rk[3] ) & 0xff] & 0xff];
188 void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
190 unsigned long s0, s1, s2, s3, t0, t1, t2, t3, *rk;
199 _ARGCHK(skey != NULL);
201 Nr = skey->rijndael.Nr;
202 rk = skey->rijndael.eK;
205 * map byte array block to cipher state
206 * and add initial round key:
208 LOAD32H(s0, pt ); s0 ^= rk[0];
209 LOAD32H(s1, pt + 4); s1 ^= rk[1];
210 LOAD32H(s2, pt + 8); s2 ^= rk[2];
211 LOAD32H(s3, pt + 12); s3 ^= rk[3];
214 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
215 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
216 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
217 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
219 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
220 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
221 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
222 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
224 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
225 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
226 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
227 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
229 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
230 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
231 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
232 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
234 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
235 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
236 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
237 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
239 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
240 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
241 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
242 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
244 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
245 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
246 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
247 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
249 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
250 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
251 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
252 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
254 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
255 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
256 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
257 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
260 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
261 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
262 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
263 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
265 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
266 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
267 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
268 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
271 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
272 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
273 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
274 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
276 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
277 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
278 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
279 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
283 #else /* SMALL_CODE */
285 * Nr - 1 full rounds:
290 /* Both of these blocks are equivalent except the top is more friendlier for x86 processors */
292 t0 = rk[4]; t1 = rk[5]; t2 = rk[6]; t3 = rk[7];
293 t1 ^= Te3[(s0 ) & 0xFF]; t2 ^= Te2[(s0 >> 8) & 0xFF]; t3 ^= Te1[(s0 >> 16) & 0xFF]; t0 ^= Te0[(s0 >> 24)];
294 t2 ^= Te3[(s1 ) & 0xFF]; t3 ^= Te2[(s1 >> 8) & 0xFF]; t0 ^= Te1[(s1 >> 16) & 0xFF]; t1 ^= Te0[(s1 >> 24)];
295 t3 ^= Te3[(s2 ) & 0xFF]; t0 ^= Te2[(s2 >> 8) & 0xFF]; t1 ^= Te1[(s2 >> 16) & 0xFF]; t2 ^= Te0[(s2 >> 24)];
296 t0 ^= Te3[(s3 ) & 0xFF]; t1 ^= Te2[(s3 >> 8) & 0xFF]; t2 ^= Te1[(s3 >> 16) & 0xFF]; t3 ^= Te0[(s3 >> 24)];
300 Te1[(s1 >> 16) & 0xff] ^
301 Te2[(s2 >> 8) & 0xff] ^
306 Te1[(s2 >> 16) & 0xff] ^
307 Te2[(s3 >> 8) & 0xff] ^
312 Te1[(s3 >> 16) & 0xff] ^
313 Te2[(s0 >> 8) & 0xff] ^
318 Te1[(s0 >> 16) & 0xff] ^
319 Te2[(s1 >> 8) & 0xff] ^
329 /* this second half optimization actually makes it slower on the Athlon, use with caution. */
331 s1 = rk[1]; s2 = rk[2]; s3 = rk[3]; s0 = rk[0];
332 s1 ^= Te3[(t0 ) & 0xFF]; s2 ^= Te2[(t0 >> 8) & 0xFF]; s3 ^= Te1[(t0 >> 16) & 0xFF]; s0 ^= Te0[(t0 >> 24)];
333 s2 ^= Te3[(t1 ) & 0xFF]; s3 ^= Te2[(t1 >> 8) & 0xFF]; s0 ^= Te1[(t1 >> 16) & 0xFF]; s1 ^= Te0[(t1 >> 24)];
334 s3 ^= Te3[(t2 ) & 0xFF]; s0 ^= Te2[(t2 >> 8) & 0xFF]; s1 ^= Te1[(t2 >> 16) & 0xFF]; s2 ^= Te0[(t2 >> 24)];
335 s0 ^= Te3[(t3 ) & 0xFF]; s1 ^= Te2[(t3 >> 8) & 0xFF]; s2 ^= Te1[(t3 >> 16) & 0xFF]; s3 ^= Te0[(t3 >> 24)];
339 Te1[(t1 >> 16) & 0xff] ^
340 Te2[(t2 >> 8) & 0xff] ^
345 Te1[(t2 >> 16) & 0xff] ^
346 Te2[(t3 >> 8) & 0xff] ^
351 Te1[(t3 >> 16) & 0xff] ^
352 Te2[(t0 >> 8) & 0xff] ^
357 Te1[(t0 >> 16) & 0xff] ^
358 Te2[(t1 >> 8) & 0xff] ^
363 #endif /* SMALL_CODE */
365 * apply last round and
366 * map cipher state to byte array block:
369 (Te4[(t0 >> 24) ] & 0xff000000) ^
370 (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
371 (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
372 (Te4[(t3 ) & 0xff] & 0x000000ff) ^
376 (Te4[(t1 >> 24) ] & 0xff000000) ^
377 (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
378 (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
379 (Te4[(t0 ) & 0xff] & 0x000000ff) ^
383 (Te4[(t2 >> 24) ] & 0xff000000) ^
384 (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
385 (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
386 (Te4[(t1 ) & 0xff] & 0x000000ff) ^
390 (Te4[(t3 >> 24) ] & 0xff000000) ^
391 (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
392 (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
393 (Te4[(t2 ) & 0xff] & 0x000000ff) ^
398 void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) {
399 unsigned long s0, s1, s2, s3, t0, t1, t2, t3, *rk;
403 #endif /* SMALL_CODE */
407 _ARGCHK(skey != NULL);
409 Nr = skey->rijndael.Nr;
410 rk = skey->rijndael.dK;
413 * map byte array block to cipher state
414 * and add initial round key:
416 LOAD32H(s0, ct ); s0 ^= rk[0];
417 LOAD32H(s1, ct + 4); s1 ^= rk[1];
418 LOAD32H(s2, ct + 8); s2 ^= rk[2];
419 LOAD32H(s3, ct + 12); s3 ^= rk[3];
422 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
423 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
424 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
425 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
427 s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
428 s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
429 s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
430 s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
432 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
433 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
434 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
435 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
437 s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
438 s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
439 s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
440 s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
442 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
443 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
444 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
445 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
447 s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
448 s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
449 s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
450 s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
452 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
453 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
454 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
455 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
457 s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
458 s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
459 s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
460 s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
462 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
463 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
464 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
465 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
468 s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
469 s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
470 s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
471 s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
473 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
474 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
475 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
476 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
479 s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
480 s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
481 s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
482 s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
484 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
485 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
486 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
487 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
491 #else /* SMALL_CODE */
493 * Nr - 1 full rounds:
499 Td1[(s3 >> 16) & 0xff] ^
500 Td2[(s2 >> 8) & 0xff] ^
505 Td1[(s0 >> 16) & 0xff] ^
506 Td2[(s3 >> 8) & 0xff] ^
511 Td1[(s1 >> 16) & 0xff] ^
512 Td2[(s0 >> 8) & 0xff] ^
517 Td1[(s2 >> 16) & 0xff] ^
518 Td2[(s1 >> 8) & 0xff] ^
529 Td1[(t3 >> 16) & 0xff] ^
530 Td2[(t2 >> 8) & 0xff] ^
535 Td1[(t0 >> 16) & 0xff] ^
536 Td2[(t3 >> 8) & 0xff] ^
541 Td1[(t1 >> 16) & 0xff] ^
542 Td2[(t0 >> 8) & 0xff] ^
547 Td1[(t2 >> 16) & 0xff] ^
548 Td2[(t1 >> 8) & 0xff] ^
552 #endif /* SMALL_CODE */
554 * apply last round and
555 * map cipher state to byte array block:
558 (Td4[(t0 >> 24) ] & 0xff000000) ^
559 (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
560 (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
561 (Td4[(t1 ) & 0xff] & 0x000000ff) ^
565 (Td4[(t1 >> 24) ] & 0xff000000) ^
566 (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
567 (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
568 (Td4[(t2 ) & 0xff] & 0x000000ff) ^
572 (Td4[(t2 >> 24) ] & 0xff000000) ^
573 (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
574 (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
575 (Td4[(t3 ) & 0xff] & 0x000000ff) ^
579 (Td4[(t3 >> 24) ] & 0xff000000) ^
580 (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
581 (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
582 (Td4[(t0 ) & 0xff] & 0x000000ff) ^
587 int rijndael_test(void)
593 static const struct {
595 unsigned char key[32], pt[16], ct[16];
598 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
599 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
600 { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
601 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
602 { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
603 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }
606 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
607 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
608 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
609 { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
610 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
611 { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
612 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }
615 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
616 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
617 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
618 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
619 { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
620 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
621 { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
622 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }
627 unsigned char tmp[2][16];
630 for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
631 zeromem(&key, sizeof(key));
632 if ((err = rijndael_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
636 rijndael_ecb_encrypt(tests[i].pt, tmp[0], &key);
637 rijndael_ecb_decrypt(tmp[0], tmp[1], &key);
638 if (memcmp(tmp[0], tests[i].ct, 16) || memcmp(tmp[1], tests[i].pt, 16)) {
640 printf("\n\nTest %d failed\n", i);
641 if (memcmp(tmp[0], tests[i].ct, 16)) {
643 for (i = 0; i < 16; i++) {
644 printf("%02x ", tmp[0][i]);
649 for (i = 0; i < 16; i++) {
650 printf("%02x ", tmp[1][i]);
655 return CRYPT_FAIL_TESTVECTOR;
662 int rijndael_keysize(int *desired_keysize)
664 _ARGCHK(desired_keysize != NULL);
666 if (*desired_keysize < 16)
667 return CRYPT_INVALID_KEYSIZE;
668 if (*desired_keysize < 24) {
669 *desired_keysize = 16;
671 } else if (*desired_keysize < 32) {
672 *desired_keysize = 24;
675 *desired_keysize = 32;