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