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