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