]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - sshaes.c
aes_setup() is unused outside this file. Make it static.
[PuTTY.git] / sshaes.c
1 /*
2  * aes.c - implementation of AES / Rijndael
3  * 
4  * AES is a flexible algorithm as regards endianness: it has no
5  * inherent preference as to which way round you should form words
6  * from the input byte stream. It talks endlessly of four-byte
7  * _vectors_, but never of 32-bit _words_ - there's no 32-bit
8  * addition at all, which would force an endianness by means of
9  * which way the carries went. So it would be possible to write a
10  * working AES that read words big-endian, and another working one
11  * that read them little-endian, just by computing a different set
12  * of tables - with no speed drop.
13  * 
14  * It's therefore tempting to do just that, and remove the overhead
15  * of GET_32BIT_MSB_FIRST() et al, allowing every system to use its
16  * own endianness-native code; but I decided not to, partly for
17  * ease of testing, and mostly because I like the flexibility that
18  * allows you to encrypt a non-word-aligned block of memory (which
19  * many systems would stop being able to do if I went the
20  * endianness-dependent route).
21  * 
22  * This implementation reads and stores words big-endian, but
23  * that's a minor implementation detail. By flipping the endianness
24  * of everything in the E0..E3, D0..D3 tables, and substituting
25  * GET_32BIT_LSB_FIRST for GET_32BIT_MSB_FIRST, I could create an
26  * implementation that worked internally little-endian and gave the
27  * same answers at the same speed.
28  */
29
30 #include <assert.h>
31 #include <stdlib.h>
32
33 #include "ssh.h"
34
35 #define MAX_NR 14                      /* max no of rounds */
36 #define MAX_NK 8                       /* max no of words in input key */
37 #define MAX_NB 8                       /* max no of words in cipher blk */
38
39 #define mulby2(x) ( ((x&0x7F) << 1) ^ (x & 0x80 ? 0x1B : 0) )
40
41 #define GET_32BIT_MSB_FIRST(cp) \
42   (((unsigned long)(unsigned char)(cp)[3]) | \
43   ((unsigned long)(unsigned char)(cp)[2] << 8) | \
44   ((unsigned long)(unsigned char)(cp)[1] << 16) | \
45   ((unsigned long)(unsigned char)(cp)[0] << 24))
46
47 #define PUT_32BIT_MSB_FIRST(cp, value) do { \
48   (cp)[3] = (value); \
49   (cp)[2] = (value) >> 8; \
50   (cp)[1] = (value) >> 16; \
51   (cp)[0] = (value) >> 24; } while (0)
52
53 typedef struct AESContext AESContext;
54
55 struct AESContext {
56     word32 keysched[(MAX_NR + 1) * MAX_NB];
57     word32 invkeysched[(MAX_NR + 1) * MAX_NB];
58     void (*encrypt) (AESContext * ctx, word32 * block);
59     void (*decrypt) (AESContext * ctx, word32 * block);
60     word32 iv[MAX_NB];
61     int Nb, Nr;
62 };
63
64 static const unsigned char Sbox[], Sboxinv[];
65 static const word32 E0[], E1[], E2[], E3[];
66 static const word32 D0[], D1[], D2[], D3[];
67
68 /*
69  * Common macros in both the encryption and decryption routines.
70  */
71 #define ADD_ROUND_KEY_4 (block[0]^=*keysched++, block[1]^=*keysched++, \
72                          block[2]^=*keysched++, block[3]^=*keysched++)
73 #define ADD_ROUND_KEY_6 (block[0]^=*keysched++, block[1]^=*keysched++, \
74                          block[2]^=*keysched++, block[3]^=*keysched++, \
75                          block[4]^=*keysched++, block[5]^=*keysched++)
76 #define ADD_ROUND_KEY_8 (block[0]^=*keysched++, block[1]^=*keysched++, \
77                          block[2]^=*keysched++, block[3]^=*keysched++, \
78                          block[4]^=*keysched++, block[5]^=*keysched++, \
79                          block[6]^=*keysched++, block[7]^=*keysched++)
80 #define MOVEWORD(i) ( block[i] = newstate[i] )
81
82 /*
83  * Macros for the encryption routine. There are three encryption
84  * cores, for Nb=4,6,8.
85  */
86 #define MAKEWORD(i) ( newstate[i] = (E0[(block[i] >> 24) & 0xFF] ^ \
87                                      E1[(block[(i+C1)%Nb] >> 16) & 0xFF] ^ \
88                                      E2[(block[(i+C2)%Nb] >> 8) & 0xFF] ^ \
89                                      E3[block[(i+C3)%Nb] & 0xFF]) )
90 #define LASTWORD(i) ( newstate[i] = (Sbox[(block[i] >> 24) & 0xFF] << 24) | \
91                             (Sbox[(block[(i+C1)%Nb] >> 16) & 0xFF] << 16) | \
92                             (Sbox[(block[(i+C2)%Nb] >>  8) & 0xFF] <<  8) | \
93                             (Sbox[(block[(i+C3)%Nb]      ) & 0xFF]      ) )
94
95 /*
96  * Core encrypt routines, expecting word32 inputs read big-endian
97  * from the byte-oriented input stream.
98  */
99 static void aes_encrypt_nb_4(AESContext * ctx, word32 * block)
100 {
101     int i;
102     static const int C1 = 1, C2 = 2, C3 = 3, Nb = 4;
103     word32 *keysched = ctx->keysched;
104     word32 newstate[4];
105     for (i = 0; i < ctx->Nr - 1; i++) {
106         ADD_ROUND_KEY_4;
107         MAKEWORD(0);
108         MAKEWORD(1);
109         MAKEWORD(2);
110         MAKEWORD(3);
111         MOVEWORD(0);
112         MOVEWORD(1);
113         MOVEWORD(2);
114         MOVEWORD(3);
115     }
116     ADD_ROUND_KEY_4;
117     LASTWORD(0);
118     LASTWORD(1);
119     LASTWORD(2);
120     LASTWORD(3);
121     MOVEWORD(0);
122     MOVEWORD(1);
123     MOVEWORD(2);
124     MOVEWORD(3);
125     ADD_ROUND_KEY_4;
126 }
127 static void aes_encrypt_nb_6(AESContext * ctx, word32 * block)
128 {
129     int i;
130     static const int C1 = 1, C2 = 2, C3 = 3, Nb = 6;
131     word32 *keysched = ctx->keysched;
132     word32 newstate[6];
133     for (i = 0; i < ctx->Nr - 1; i++) {
134         ADD_ROUND_KEY_6;
135         MAKEWORD(0);
136         MAKEWORD(1);
137         MAKEWORD(2);
138         MAKEWORD(3);
139         MAKEWORD(4);
140         MAKEWORD(5);
141         MOVEWORD(0);
142         MOVEWORD(1);
143         MOVEWORD(2);
144         MOVEWORD(3);
145         MOVEWORD(4);
146         MOVEWORD(5);
147     }
148     ADD_ROUND_KEY_6;
149     LASTWORD(0);
150     LASTWORD(1);
151     LASTWORD(2);
152     LASTWORD(3);
153     LASTWORD(4);
154     LASTWORD(5);
155     MOVEWORD(0);
156     MOVEWORD(1);
157     MOVEWORD(2);
158     MOVEWORD(3);
159     MOVEWORD(4);
160     MOVEWORD(5);
161     ADD_ROUND_KEY_6;
162 }
163 static void aes_encrypt_nb_8(AESContext * ctx, word32 * block)
164 {
165     int i;
166     static const int C1 = 1, C2 = 3, C3 = 4, Nb = 8;
167     word32 *keysched = ctx->keysched;
168     word32 newstate[8];
169     for (i = 0; i < ctx->Nr - 1; i++) {
170         ADD_ROUND_KEY_8;
171         MAKEWORD(0);
172         MAKEWORD(1);
173         MAKEWORD(2);
174         MAKEWORD(3);
175         MAKEWORD(4);
176         MAKEWORD(5);
177         MAKEWORD(6);
178         MAKEWORD(7);
179         MOVEWORD(0);
180         MOVEWORD(1);
181         MOVEWORD(2);
182         MOVEWORD(3);
183         MOVEWORD(4);
184         MOVEWORD(5);
185         MOVEWORD(6);
186         MOVEWORD(7);
187     }
188     ADD_ROUND_KEY_8;
189     LASTWORD(0);
190     LASTWORD(1);
191     LASTWORD(2);
192     LASTWORD(3);
193     LASTWORD(4);
194     LASTWORD(5);
195     LASTWORD(6);
196     LASTWORD(7);
197     MOVEWORD(0);
198     MOVEWORD(1);
199     MOVEWORD(2);
200     MOVEWORD(3);
201     MOVEWORD(4);
202     MOVEWORD(5);
203     MOVEWORD(6);
204     MOVEWORD(7);
205     ADD_ROUND_KEY_8;
206 }
207
208 #undef MAKEWORD
209 #undef LASTWORD
210
211 /*
212  * Macros for the decryption routine. There are three decryption
213  * cores, for Nb=4,6,8.
214  */
215 #define MAKEWORD(i) ( newstate[i] = (D0[(block[i] >> 24) & 0xFF] ^ \
216                                      D1[(block[(i+C1)%Nb] >> 16) & 0xFF] ^ \
217                                      D2[(block[(i+C2)%Nb] >> 8) & 0xFF] ^ \
218                                      D3[block[(i+C3)%Nb] & 0xFF]) )
219 #define LASTWORD(i) (newstate[i] = (Sboxinv[(block[i] >> 24) & 0xFF] << 24) | \
220                            (Sboxinv[(block[(i+C1)%Nb] >> 16) & 0xFF] << 16) | \
221                            (Sboxinv[(block[(i+C2)%Nb] >>  8) & 0xFF] <<  8) | \
222                            (Sboxinv[(block[(i+C3)%Nb]      ) & 0xFF]      ) )
223
224 /*
225  * Core decrypt routines, expecting word32 inputs read big-endian
226  * from the byte-oriented input stream.
227  */
228 static void aes_decrypt_nb_4(AESContext * ctx, word32 * block)
229 {
230     int i;
231     static const int C1 = 4 - 1, C2 = 4 - 2, C3 = 4 - 3, Nb = 4;
232     word32 *keysched = ctx->invkeysched;
233     word32 newstate[4];
234     for (i = 0; i < ctx->Nr - 1; i++) {
235         ADD_ROUND_KEY_4;
236         MAKEWORD(0);
237         MAKEWORD(1);
238         MAKEWORD(2);
239         MAKEWORD(3);
240         MOVEWORD(0);
241         MOVEWORD(1);
242         MOVEWORD(2);
243         MOVEWORD(3);
244     }
245     ADD_ROUND_KEY_4;
246     LASTWORD(0);
247     LASTWORD(1);
248     LASTWORD(2);
249     LASTWORD(3);
250     MOVEWORD(0);
251     MOVEWORD(1);
252     MOVEWORD(2);
253     MOVEWORD(3);
254     ADD_ROUND_KEY_4;
255 }
256 static void aes_decrypt_nb_6(AESContext * ctx, word32 * block)
257 {
258     int i;
259     static const int C1 = 6 - 1, C2 = 6 - 2, C3 = 6 - 3, Nb = 6;
260     word32 *keysched = ctx->invkeysched;
261     word32 newstate[6];
262     for (i = 0; i < ctx->Nr - 1; i++) {
263         ADD_ROUND_KEY_6;
264         MAKEWORD(0);
265         MAKEWORD(1);
266         MAKEWORD(2);
267         MAKEWORD(3);
268         MAKEWORD(4);
269         MAKEWORD(5);
270         MOVEWORD(0);
271         MOVEWORD(1);
272         MOVEWORD(2);
273         MOVEWORD(3);
274         MOVEWORD(4);
275         MOVEWORD(5);
276     }
277     ADD_ROUND_KEY_6;
278     LASTWORD(0);
279     LASTWORD(1);
280     LASTWORD(2);
281     LASTWORD(3);
282     LASTWORD(4);
283     LASTWORD(5);
284     MOVEWORD(0);
285     MOVEWORD(1);
286     MOVEWORD(2);
287     MOVEWORD(3);
288     MOVEWORD(4);
289     MOVEWORD(5);
290     ADD_ROUND_KEY_6;
291 }
292 static void aes_decrypt_nb_8(AESContext * ctx, word32 * block)
293 {
294     int i;
295     static const int C1 = 8 - 1, C2 = 8 - 3, C3 = 8 - 4, Nb = 8;
296     word32 *keysched = ctx->invkeysched;
297     word32 newstate[8];
298     for (i = 0; i < ctx->Nr - 1; i++) {
299         ADD_ROUND_KEY_8;
300         MAKEWORD(0);
301         MAKEWORD(1);
302         MAKEWORD(2);
303         MAKEWORD(3);
304         MAKEWORD(4);
305         MAKEWORD(5);
306         MAKEWORD(6);
307         MAKEWORD(7);
308         MOVEWORD(0);
309         MOVEWORD(1);
310         MOVEWORD(2);
311         MOVEWORD(3);
312         MOVEWORD(4);
313         MOVEWORD(5);
314         MOVEWORD(6);
315         MOVEWORD(7);
316     }
317     ADD_ROUND_KEY_8;
318     LASTWORD(0);
319     LASTWORD(1);
320     LASTWORD(2);
321     LASTWORD(3);
322     LASTWORD(4);
323     LASTWORD(5);
324     LASTWORD(6);
325     LASTWORD(7);
326     MOVEWORD(0);
327     MOVEWORD(1);
328     MOVEWORD(2);
329     MOVEWORD(3);
330     MOVEWORD(4);
331     MOVEWORD(5);
332     MOVEWORD(6);
333     MOVEWORD(7);
334     ADD_ROUND_KEY_8;
335 }
336
337 #undef MAKEWORD
338 #undef LASTWORD
339
340 static const unsigned char Sbox[256] = {
341     0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
342     0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
343     0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
344     0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
345     0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
346     0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
347     0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
348     0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
349     0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
350     0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
351     0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
352     0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
353     0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
354     0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
355     0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
356     0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
357     0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
358     0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
359     0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
360     0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
361     0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
362     0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
363     0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
364     0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
365     0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
366     0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
367     0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
368     0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
369     0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
370     0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
371     0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
372     0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
373 };
374
375 static const unsigned char Sboxinv[256] = {
376     0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
377     0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
378     0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
379     0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
380     0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
381     0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
382     0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
383     0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
384     0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
385     0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
386     0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
387     0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
388     0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
389     0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
390     0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
391     0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
392     0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
393     0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
394     0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
395     0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
396     0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
397     0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
398     0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
399     0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
400     0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
401     0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
402     0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
403     0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
404     0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
405     0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
406     0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
407     0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
408 };
409
410 static const word32 E0[256] = {
411     0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d,
412     0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554,
413     0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d,
414     0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a,
415     0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87,
416     0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b,
417     0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea,
418     0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b,
419     0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a,
420     0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f,
421     0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108,
422     0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f,
423     0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e,
424     0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5,
425     0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d,
426     0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f,
427     0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e,
428     0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb,
429     0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce,
430     0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497,
431     0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c,
432     0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed,
433     0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b,
434     0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a,
435     0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16,
436     0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594,
437     0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81,
438     0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3,
439     0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a,
440     0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504,
441     0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163,
442     0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d,
443     0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f,
444     0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739,
445     0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47,
446     0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395,
447     0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f,
448     0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883,
449     0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c,
450     0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76,
451     0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e,
452     0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4,
453     0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6,
454     0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b,
455     0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7,
456     0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0,
457     0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25,
458     0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,
459     0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72,
460     0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651,
461     0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21,
462     0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85,
463     0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa,
464     0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12,
465     0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0,
466     0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9,
467     0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133,
468     0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7,
469     0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920,
470     0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a,
471     0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17,
472     0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8,
473     0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11,
474     0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a,
475 };
476 static const word32 E1[256] = {
477     0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b,
478     0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5,
479     0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b,
480     0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676,
481     0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d,
482     0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0,
483     0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf,
484     0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0,
485     0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626,
486     0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc,
487     0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1,
488     0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515,
489     0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3,
490     0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a,
491     0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2,
492     0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575,
493     0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a,
494     0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0,
495     0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3,
496     0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484,
497     0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded,
498     0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b,
499     0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939,
500     0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf,
501     0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb,
502     0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585,
503     0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f,
504     0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8,
505     0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f,
506     0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5,
507     0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121,
508     0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2,
509     0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec,
510     0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717,
511     0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d,
512     0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373,
513     0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc,
514     0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888,
515     0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414,
516     0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb,
517     0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a,
518     0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c,
519     0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262,
520     0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979,
521     0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d,
522     0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9,
523     0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea,
524     0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808,
525     0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e,
526     0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6,
527     0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f,
528     0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a,
529     0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666,
530     0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e,
531     0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9,
532     0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e,
533     0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111,
534     0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494,
535     0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9,
536     0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf,
537     0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d,
538     0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868,
539     0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f,
540     0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616,
541 };
542 static const word32 E2[256] = {
543     0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b,
544     0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5,
545     0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b,
546     0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76,
547     0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d,
548     0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0,
549     0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af,
550     0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0,
551     0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26,
552     0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc,
553     0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1,
554     0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15,
555     0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3,
556     0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a,
557     0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2,
558     0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75,
559     0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a,
560     0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0,
561     0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3,
562     0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384,
563     0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed,
564     0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b,
565     0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239,
566     0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf,
567     0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb,
568     0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185,
569     0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f,
570     0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8,
571     0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f,
572     0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5,
573     0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221,
574     0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2,
575     0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec,
576     0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17,
577     0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d,
578     0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673,
579     0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc,
580     0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88,
581     0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814,
582     0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb,
583     0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a,
584     0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c,
585     0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462,
586     0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279,
587     0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d,
588     0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9,
589     0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea,
590     0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008,
591     0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e,
592     0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6,
593     0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f,
594     0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a,
595     0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66,
596     0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e,
597     0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9,
598     0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e,
599     0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211,
600     0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394,
601     0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9,
602     0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df,
603     0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d,
604     0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068,
605     0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f,
606     0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16,
607 };
608 static const word32 E3[256] = {
609     0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6,
610     0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491,
611     0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56,
612     0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec,
613     0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa,
614     0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb,
615     0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45,
616     0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b,
617     0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c,
618     0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83,
619     0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9,
620     0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a,
621     0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d,
622     0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f,
623     0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf,
624     0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea,
625     0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34,
626     0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b,
627     0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d,
628     0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713,
629     0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1,
630     0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6,
631     0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72,
632     0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85,
633     0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed,
634     0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411,
635     0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe,
636     0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b,
637     0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05,
638     0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1,
639     0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342,
640     0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf,
641     0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3,
642     0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e,
643     0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a,
644     0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6,
645     0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3,
646     0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b,
647     0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28,
648     0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad,
649     0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14,
650     0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8,
651     0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4,
652     0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2,
653     0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da,
654     0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049,
655     0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf,
656     0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810,
657     0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c,
658     0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197,
659     0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e,
660     0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f,
661     0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc,
662     0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c,
663     0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069,
664     0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927,
665     0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322,
666     0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733,
667     0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9,
668     0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5,
669     0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a,
670     0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0,
671     0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e,
672     0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c,
673 };
674 static const word32 D0[256] = {
675     0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96,
676     0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393,
677     0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25,
678     0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f,
679     0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1,
680     0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6,
681     0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da,
682     0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844,
683     0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd,
684     0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4,
685     0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45,
686     0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94,
687     0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7,
688     0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a,
689     0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5,
690     0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c,
691     0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1,
692     0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a,
693     0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75,
694     0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051,
695     0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46,
696     0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff,
697     0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77,
698     0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb,
699     0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000,
700     0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e,
701     0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927,
702     0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a,
703     0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e,
704     0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16,
705     0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d,
706     0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8,
707     0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd,
708     0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34,
709     0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163,
710     0xd731dcca, 0x42638510, 0x13972240, 0x84c61120,
711     0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d,
712     0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0,
713     0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422,
714     0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef,
715     0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36,
716     0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4,
717     0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662,
718     0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5,
719     0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3,
720     0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b,
721     0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8,
722     0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6,
723     0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6,
724     0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0,
725     0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815,
726     0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f,
727     0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df,
728     0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f,
729     0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e,
730     0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713,
731     0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89,
732     0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c,
733     0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf,
734     0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86,
735     0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f,
736     0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541,
737     0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190,
738     0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742,
739 };
740 static const word32 D1[256] = {
741     0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e,
742     0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303,
743     0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c,
744     0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3,
745     0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0,
746     0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9,
747     0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259,
748     0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8,
749     0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971,
750     0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a,
751     0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f,
752     0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b,
753     0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8,
754     0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab,
755     0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708,
756     0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682,
757     0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2,
758     0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe,
759     0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb,
760     0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10,
761     0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd,
762     0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015,
763     0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e,
764     0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee,
765     0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000,
766     0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72,
767     0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39,
768     0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e,
769     0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91,
770     0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a,
771     0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17,
772     0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9,
773     0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60,
774     0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e,
775     0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1,
776     0xcad731dc, 0x10426385, 0x40139722, 0x2084c611,
777     0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1,
778     0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3,
779     0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964,
780     0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390,
781     0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b,
782     0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf,
783     0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46,
784     0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af,
785     0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512,
786     0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb,
787     0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a,
788     0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8,
789     0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c,
790     0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266,
791     0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8,
792     0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6,
793     0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604,
794     0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551,
795     0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41,
796     0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647,
797     0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c,
798     0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1,
799     0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737,
800     0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db,
801     0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340,
802     0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95,
803     0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1,
804     0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857,
805 };
806 static const word32 D2[256] = {
807     0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27,
808     0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3,
809     0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502,
810     0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562,
811     0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe,
812     0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3,
813     0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552,
814     0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9,
815     0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9,
816     0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce,
817     0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253,
818     0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908,
819     0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b,
820     0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655,
821     0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337,
822     0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16,
823     0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69,
824     0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6,
825     0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6,
826     0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e,
827     0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6,
828     0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050,
829     0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9,
830     0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8,
831     0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000,
832     0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a,
833     0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d,
834     0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436,
835     0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b,
836     0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12,
837     0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b,
838     0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e,
839     0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f,
840     0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb,
841     0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4,
842     0xdccad731, 0x85104263, 0x22401397, 0x112084c6,
843     0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729,
844     0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1,
845     0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9,
846     0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233,
847     0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4,
848     0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad,
849     0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e,
850     0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3,
851     0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25,
852     0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b,
853     0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f,
854     0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15,
855     0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0,
856     0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2,
857     0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7,
858     0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791,
859     0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496,
860     0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665,
861     0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b,
862     0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6,
863     0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13,
864     0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47,
865     0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7,
866     0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844,
867     0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3,
868     0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d,
869     0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456,
870     0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8,
871 };
872 static const word32 D3[256] = {
873     0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a,
874     0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b,
875     0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5,
876     0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5,
877     0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d,
878     0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b,
879     0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95,
880     0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e,
881     0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27,
882     0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d,
883     0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562,
884     0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9,
885     0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752,
886     0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66,
887     0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3,
888     0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced,
889     0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e,
890     0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4,
891     0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4,
892     0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd,
893     0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d,
894     0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60,
895     0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767,
896     0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79,
897     0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000,
898     0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c,
899     0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736,
900     0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24,
901     0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b,
902     0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c,
903     0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12,
904     0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814,
905     0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3,
906     0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b,
907     0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8,
908     0x31dccad7, 0x63851042, 0x97224013, 0xc6112084,
909     0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7,
910     0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077,
911     0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247,
912     0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22,
913     0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698,
914     0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f,
915     0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254,
916     0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582,
917     0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf,
918     0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb,
919     0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883,
920     0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef,
921     0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629,
922     0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035,
923     0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533,
924     0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17,
925     0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4,
926     0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46,
927     0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb,
928     0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d,
929     0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb,
930     0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a,
931     0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73,
932     0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678,
933     0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2,
934     0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff,
935     0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064,
936     0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0,
937 };
938
939 /*
940  * Set up an AESContext. `keylen' and `blocklen' are measured in
941  * bytes; each can be either 16 (128-bit), 24 (192-bit), or 32
942  * (256-bit).
943  */
944 static void aes_setup(AESContext * ctx, int blocklen,
945                unsigned char *key, int keylen)
946 {
947     int i, j, Nk, rconst;
948
949     assert(blocklen == 16 || blocklen == 24 || blocklen == 32);
950     assert(keylen == 16 || keylen == 24 || keylen == 32);
951
952     /*
953      * Basic parameters. Words per block, words in key, rounds.
954      */
955     Nk = keylen / 4;
956     ctx->Nb = blocklen / 4;
957     ctx->Nr = 6 + (ctx->Nb > Nk ? ctx->Nb : Nk);
958
959     /*
960      * Assign core-function pointers.
961      */
962     if (ctx->Nb == 8)
963         ctx->encrypt = aes_encrypt_nb_8, ctx->decrypt = aes_decrypt_nb_8;
964     else if (ctx->Nb == 6)
965         ctx->encrypt = aes_encrypt_nb_6, ctx->decrypt = aes_decrypt_nb_6;
966     else if (ctx->Nb == 4)
967         ctx->encrypt = aes_encrypt_nb_4, ctx->decrypt = aes_decrypt_nb_4;
968
969     /*
970      * Now do the key setup itself.
971      */
972     rconst = 1;
973     for (i = 0; i < (ctx->Nr + 1) * ctx->Nb; i++) {
974         if (i < Nk)
975             ctx->keysched[i] = GET_32BIT_MSB_FIRST(key + 4 * i);
976         else {
977             word32 temp = ctx->keysched[i - 1];
978             if (i % Nk == 0) {
979                 int a, b, c, d;
980                 a = (temp >> 16) & 0xFF;
981                 b = (temp >> 8) & 0xFF;
982                 c = (temp >> 0) & 0xFF;
983                 d = (temp >> 24) & 0xFF;
984                 temp = Sbox[a] ^ rconst;
985                 temp = (temp << 8) | Sbox[b];
986                 temp = (temp << 8) | Sbox[c];
987                 temp = (temp << 8) | Sbox[d];
988                 rconst = mulby2(rconst);
989             } else if (i % Nk == 4 && Nk > 6) {
990                 int a, b, c, d;
991                 a = (temp >> 24) & 0xFF;
992                 b = (temp >> 16) & 0xFF;
993                 c = (temp >> 8) & 0xFF;
994                 d = (temp >> 0) & 0xFF;
995                 temp = Sbox[a];
996                 temp = (temp << 8) | Sbox[b];
997                 temp = (temp << 8) | Sbox[c];
998                 temp = (temp << 8) | Sbox[d];
999             }
1000             ctx->keysched[i] = ctx->keysched[i - Nk] ^ temp;
1001         }
1002     }
1003
1004     /*
1005      * Now prepare the modified keys for the inverse cipher.
1006      */
1007     for (i = 0; i <= ctx->Nr; i++) {
1008         for (j = 0; j < ctx->Nb; j++) {
1009             word32 temp;
1010             temp = ctx->keysched[(ctx->Nr - i) * ctx->Nb + j];
1011             if (i != 0 && i != ctx->Nr) {
1012                 /*
1013                  * Perform the InvMixColumn operation on i. The D
1014                  * tables give the result of InvMixColumn applied
1015                  * to Sboxinv on individual bytes, so we should
1016                  * compose Sbox with the D tables for this.
1017                  */
1018                 int a, b, c, d;
1019                 a = (temp >> 24) & 0xFF;
1020                 b = (temp >> 16) & 0xFF;
1021                 c = (temp >> 8) & 0xFF;
1022                 d = (temp >> 0) & 0xFF;
1023                 temp = D0[Sbox[a]];
1024                 temp ^= D1[Sbox[b]];
1025                 temp ^= D2[Sbox[c]];
1026                 temp ^= D3[Sbox[d]];
1027             }
1028             ctx->invkeysched[i * ctx->Nb + j] = temp;
1029         }
1030     }
1031 }
1032
1033 static void aes_encrypt(AESContext * ctx, word32 * block)
1034 {
1035     ctx->encrypt(ctx, block);
1036 }
1037
1038 static void aes_decrypt(AESContext * ctx, word32 * block)
1039 {
1040     ctx->decrypt(ctx, block);
1041 }
1042
1043 static void aes_encrypt_cbc(unsigned char *blk, int len, AESContext * ctx)
1044 {
1045     word32 iv[4];
1046     int i;
1047
1048     assert((len & 15) == 0);
1049
1050     memcpy(iv, ctx->iv, sizeof(iv));
1051
1052     while (len > 0) {
1053         for (i = 0; i < 4; i++)
1054             iv[i] ^= GET_32BIT_MSB_FIRST(blk + 4 * i);
1055         aes_encrypt(ctx, iv);
1056         for (i = 0; i < 4; i++)
1057             PUT_32BIT_MSB_FIRST(blk + 4 * i, iv[i]);
1058         blk += 16;
1059         len -= 16;
1060     }
1061
1062     memcpy(ctx->iv, iv, sizeof(iv));
1063 }
1064
1065 static void aes_decrypt_cbc(unsigned char *blk, int len, AESContext * ctx)
1066 {
1067     word32 iv[4], x[4], ct[4];
1068     int i;
1069
1070     assert((len & 15) == 0);
1071
1072     memcpy(iv, ctx->iv, sizeof(iv));
1073
1074     while (len > 0) {
1075         for (i = 0; i < 4; i++)
1076             x[i] = ct[i] = GET_32BIT_MSB_FIRST(blk + 4 * i);
1077         aes_decrypt(ctx, x);
1078         for (i = 0; i < 4; i++) {
1079             PUT_32BIT_MSB_FIRST(blk + 4 * i, iv[i] ^ x[i]);
1080             iv[i] = ct[i];
1081         }
1082         blk += 16;
1083         len -= 16;
1084     }
1085
1086     memcpy(ctx->iv, iv, sizeof(iv));
1087 }
1088
1089 static void *aes_make_context(void)
1090 {
1091     return smalloc(sizeof(AESContext));
1092 }
1093
1094 static void aes_free_context(void *handle)
1095 {
1096     sfree(handle);
1097 }
1098
1099 static void aes128_key(void *handle, unsigned char *key)
1100 {
1101     AESContext *ctx = (AESContext *)handle;
1102     aes_setup(ctx, 16, key, 16);
1103 }
1104
1105 static void aes192_key(void *handle, unsigned char *key)
1106 {
1107     AESContext *ctx = (AESContext *)handle;
1108     aes_setup(ctx, 16, key, 24);
1109 }
1110
1111 static void aes256_key(void *handle, unsigned char *key)
1112 {
1113     AESContext *ctx = (AESContext *)handle;
1114     aes_setup(ctx, 16, key, 32);
1115 }
1116
1117 static void aes_iv(void *handle, unsigned char *iv)
1118 {
1119     AESContext *ctx = (AESContext *)handle;
1120     int i;
1121     for (i = 0; i < 4; i++)
1122         ctx->iv[i] = GET_32BIT_MSB_FIRST(iv + 4 * i);
1123 }
1124
1125 static void aes_ssh2_encrypt_blk(void *handle, unsigned char *blk, int len)
1126 {
1127     AESContext *ctx = (AESContext *)handle;
1128     aes_encrypt_cbc(blk, len, ctx);
1129 }
1130
1131 static void aes_ssh2_decrypt_blk(void *handle, unsigned char *blk, int len)
1132 {
1133     AESContext *ctx = (AESContext *)handle;
1134     aes_decrypt_cbc(blk, len, ctx);
1135 }
1136
1137 void aes256_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
1138 {
1139     AESContext ctx;
1140     aes_setup(&ctx, 16, key, 32);
1141     memset(ctx.iv, 0, sizeof(ctx.iv));
1142     aes_encrypt_cbc(blk, len, &ctx);
1143     memset(&ctx, 0, sizeof(ctx));
1144 }
1145
1146 void aes256_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
1147 {
1148     AESContext ctx;
1149     aes_setup(&ctx, 16, key, 32);
1150     memset(ctx.iv, 0, sizeof(ctx.iv));
1151     aes_decrypt_cbc(blk, len, &ctx);
1152     memset(&ctx, 0, sizeof(ctx));
1153 }
1154
1155 static const struct ssh2_cipher ssh_aes128 = {
1156     aes_make_context, aes_free_context, aes_iv, aes128_key,
1157     aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk,
1158     "aes128-cbc",
1159     16, 128, "AES-128"
1160 };
1161
1162 static const struct ssh2_cipher ssh_aes192 = {
1163     aes_make_context, aes_free_context, aes_iv, aes192_key,
1164     aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk,
1165     "aes192-cbc",
1166     16, 192, "AES-192"
1167 };
1168
1169 static const struct ssh2_cipher ssh_aes256 = {
1170     aes_make_context, aes_free_context, aes_iv, aes256_key,
1171     aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk,
1172     "aes256-cbc",
1173     16, 256, "AES-256"
1174 };
1175
1176 static const struct ssh2_cipher ssh_rijndael128 = {
1177     aes_make_context, aes_free_context, aes_iv, aes128_key,
1178     aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk,
1179     "rijndael128-cbc",
1180     16, 128, "AES-128"
1181 };
1182
1183 static const struct ssh2_cipher ssh_rijndael192 = {
1184     aes_make_context, aes_free_context, aes_iv, aes192_key,
1185     aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk,
1186     "rijndael192-cbc",
1187     16, 192, "AES-192"
1188 };
1189
1190 static const struct ssh2_cipher ssh_rijndael256 = {
1191     aes_make_context, aes_free_context, aes_iv, aes256_key,
1192     aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk,
1193     "rijndael256-cbc",
1194     16, 256, "AES-256"
1195 };
1196
1197 static const struct ssh2_cipher ssh_rijndael_lysator = {
1198     aes_make_context, aes_free_context, aes_iv, aes256_key,
1199     aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk,
1200     "rijndael-cbc@lysator.liu.se",
1201     16, 256, "AES-256"
1202 };
1203
1204 static const struct ssh2_cipher *const aes_list[] = {
1205     &ssh_aes256,
1206     &ssh_rijndael256,
1207     &ssh_rijndael_lysator,
1208     &ssh_aes192,
1209     &ssh_rijndael192,
1210     &ssh_aes128,
1211     &ssh_rijndael128,
1212 };
1213
1214 const struct ssh2_ciphers ssh2_aes = {
1215     sizeof(aes_list) / sizeof(*aes_list),
1216     aes_list
1217 };