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