4 * The Advanced Encryption Standard (AES, aka AES) block cipher,
\r
5 * designed by J. Daemen and V. Rijmen.
\r
7 * @author Paulo S. L. M. Barreto
\r
9 * This software is hereby placed in the public domain.
\r
11 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
\r
12 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
\r
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
\r
14 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
\r
15 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
\r
16 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
\r
17 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
\r
18 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
\r
19 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
\r
20 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
21 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
24 #include <freeradius-devel/ident.h>
\r
36 #define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
\r
39 #define GETWORD(p) SWAP(*((uint *)(p)))
\r
40 #define PUTWORD(ct, st) { *((uint *)(ct)) = SWAP((st)); }
\r
42 #define GETWORD(pt) (((uint)(pt)[0] << 24) ^ ((uint)(pt)[1] << 16) ^ ((uint)(pt)[2] << 8) ^ ((uint)(pt)[3]))
\r
43 #define PUTWORD(ct, st) { (ct)[0] = (byte)((st) >> 24); (ct)[1] = (byte)((st) >> 16); (ct)[2] = (byte)((st) >> 8); (ct)[3] = (byte)(st); }
\r
46 //////////////////////////////////////////////////////////////////////
\r
47 // Construction/Destruction
\r
48 //////////////////////////////////////////////////////////////////////
\r
55 memset(e_sched, 0, sizeof(e_sched));
\r
56 memset(d_sched, 0, sizeof(d_sched));
\r
59 //////////////////////////////////////////////////////////////////////
\r
61 //////////////////////////////////////////////////////////////////////
\r
63 void AES::ExpandKey(const byte *cipherKey, uint keyBits) {
\r
64 uint *rek = e_sched;
\r
68 rek[0] = GETWORD(cipherKey );
\r
69 rek[1] = GETWORD(cipherKey + 4);
\r
70 rek[2] = GETWORD(cipherKey + 8);
\r
71 rek[3] = GETWORD(cipherKey + 12);
\r
72 if (keyBits == 128) {
\r
76 (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
\r
77 (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
\r
78 (Te4[(temp ) & 0xff] & 0x0000ff00) ^
\r
79 (Te4[(temp >> 24) ] & 0x000000ff) ^
\r
81 rek[5] = rek[1] ^ rek[4];
\r
82 rek[6] = rek[2] ^ rek[5];
\r
83 rek[7] = rek[3] ^ rek[6];
\r
91 rek[4] = GETWORD(cipherKey + 16);
\r
92 rek[5] = GETWORD(cipherKey + 20);
\r
93 if (keyBits == 192) {
\r
97 (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
\r
98 (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
\r
99 (Te4[(temp ) & 0xff] & 0x0000ff00) ^
\r
100 (Te4[(temp >> 24) ] & 0x000000ff) ^
\r
102 rek[ 7] = rek[ 1] ^ rek[ 6];
\r
103 rek[ 8] = rek[ 2] ^ rek[ 7];
\r
104 rek[ 9] = rek[ 3] ^ rek[ 8];
\r
109 rek[10] = rek[ 4] ^ rek[ 9];
\r
110 rek[11] = rek[ 5] ^ rek[10];
\r
114 rek[6] = GETWORD(cipherKey + 24);
\r
115 rek[7] = GETWORD(cipherKey + 28);
\r
116 if (keyBits == 256) {
\r
119 rek[ 8] = rek[ 0] ^
\r
120 (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
\r
121 (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
\r
122 (Te4[(temp ) & 0xff] & 0x0000ff00) ^
\r
123 (Te4[(temp >> 24) ] & 0x000000ff) ^
\r
125 rek[ 9] = rek[ 1] ^ rek[ 8];
\r
126 rek[10] = rek[ 2] ^ rek[ 9];
\r
127 rek[11] = rek[ 3] ^ rek[10];
\r
133 rek[12] = rek[ 4] ^
\r
134 (Te4[(temp >> 24) ] & 0xff000000) ^
\r
135 (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
\r
136 (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^
\r
137 (Te4[(temp ) & 0xff] & 0x000000ff);
\r
138 rek[13] = rek[ 5] ^ rek[12];
\r
139 rek[14] = rek[ 6] ^ rek[13];
\r
140 rek[15] = rek[ 7] ^ rek[14];
\r
148 void AES::InvertKey() {
\r
149 uint *rek = e_sched;
\r
150 uint *rdk = d_sched;
\r
153 assert(Nr == 10 || Nr == 12 || Nr == 14);
\r
155 /* apply the inverse MixColumn transform to all round keys but the first and the last: */
\r
156 memcpy(rdk, rek, 16);
\r
159 for (r = 1; r < Nr; r++) {
\r
161 Td0[Te4[(rek[0] >> 24) ] & 0xff] ^
\r
162 Td1[Te4[(rek[0] >> 16) & 0xff] & 0xff] ^
\r
163 Td2[Te4[(rek[0] >> 8) & 0xff] & 0xff] ^
\r
164 Td3[Te4[(rek[0] ) & 0xff] & 0xff];
\r
166 Td0[Te4[(rek[1] >> 24) ] & 0xff] ^
\r
167 Td1[Te4[(rek[1] >> 16) & 0xff] & 0xff] ^
\r
168 Td2[Te4[(rek[1] >> 8) & 0xff] & 0xff] ^
\r
169 Td3[Te4[(rek[1] ) & 0xff] & 0xff];
\r
171 Td0[Te4[(rek[2] >> 24) ] & 0xff] ^
\r
172 Td1[Te4[(rek[2] >> 16) & 0xff] & 0xff] ^
\r
173 Td2[Te4[(rek[2] >> 8) & 0xff] & 0xff] ^
\r
174 Td3[Te4[(rek[2] ) & 0xff] & 0xff];
\r
176 Td0[Te4[(rek[3] >> 24) ] & 0xff] ^
\r
177 Td1[Te4[(rek[3] >> 16) & 0xff] & 0xff] ^
\r
178 Td2[Te4[(rek[3] >> 8) & 0xff] & 0xff] ^
\r
179 Td3[Te4[(rek[3] ) & 0xff] & 0xff];
\r
183 memcpy(rdk, rek, 16);
\r
186 //////////////////////////////////////////////////////////////////////
\r
187 // Public Interface
\r
188 //////////////////////////////////////////////////////////////////////
\r
190 void AES::makeKey(const byte *cipherKey, uint keySize, uint dir) {
\r
192 case 16: case 24: case 32:
\r
193 keySize <<= 3; // key size is now in bits
\r
195 case 128: case 192: case 256:
\r
198 assert(keySize == 16 || keySize == 24 || keySize == 32 || keySize == 128 || keySize == 192 || keySize == 256);
\r
200 assert(dir >= DIR_NONE && dir <= DIR_BOTH);
\r
201 if (dir != DIR_NONE) {
\r
202 ExpandKey(cipherKey, keySize);
\r
203 if (dir & DIR_DECRYPT) {
\r
209 void AES::encrypt(const byte *pt, byte *ct) {
\r
210 uint *rek = e_sched;
\r
211 uint s0, s1, s2, s3, t0, t1, t2, t3;
\r
212 #ifndef FULL_UNROLL
\r
214 #endif /* ?FULL_UNROLL */
\r
217 * map byte array block to cipher state
\r
218 * and add initial round key:
\r
220 s0 = GETWORD(pt ) ^ rek[0];
\r
221 s1 = GETWORD(pt + 4) ^ rek[1];
\r
222 s2 = GETWORD(pt + 8) ^ rek[2];
\r
223 s3 = GETWORD(pt + 12) ^ rek[3];
\r
226 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[ 4];
\r
227 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[ 5];
\r
228 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[ 6];
\r
229 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[ 7];
\r
231 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rek[ 8];
\r
232 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rek[ 9];
\r
233 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rek[10];
\r
234 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rek[11];
\r
236 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[12];
\r
237 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[13];
\r
238 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[14];
\r
239 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[15];
\r
241 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rek[16];
\r
242 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rek[17];
\r
243 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rek[18];
\r
244 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rek[19];
\r
246 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[20];
\r
247 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[21];
\r
248 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[22];
\r
249 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[23];
\r
251 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rek[24];
\r
252 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rek[25];
\r
253 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rek[26];
\r
254 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rek[27];
\r
256 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[28];
\r
257 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[29];
\r
258 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[30];
\r
259 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[31];
\r
261 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rek[32];
\r
262 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rek[33];
\r
263 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rek[34];
\r
264 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rek[35];
\r
266 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[36];
\r
267 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[37];
\r
268 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[38];
\r
269 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[39];
\r
272 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rek[40];
\r
273 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rek[41];
\r
274 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rek[42];
\r
275 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rek[43];
\r
277 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[44];
\r
278 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[45];
\r
279 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[46];
\r
280 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[47];
\r
283 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rek[48];
\r
284 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rek[49];
\r
285 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rek[50];
\r
286 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rek[51];
\r
288 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[52];
\r
289 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[53];
\r
290 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[54];
\r
291 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[55];
\r
295 #else /* !FULL_UNROLL */
\r
297 * Nr - 1 full rounds:
\r
303 Te1[(s1 >> 16) & 0xff] ^
\r
304 Te2[(s2 >> 8) & 0xff] ^
\r
305 Te3[(s3 ) & 0xff] ^
\r
309 Te1[(s2 >> 16) & 0xff] ^
\r
310 Te2[(s3 >> 8) & 0xff] ^
\r
311 Te3[(s0 ) & 0xff] ^
\r
315 Te1[(s3 >> 16) & 0xff] ^
\r
316 Te2[(s0 >> 8) & 0xff] ^
\r
317 Te3[(s1 ) & 0xff] ^
\r
321 Te1[(s0 >> 16) & 0xff] ^
\r
322 Te2[(s1 >> 8) & 0xff] ^
\r
323 Te3[(s2 ) & 0xff] ^
\r
333 Te1[(t1 >> 16) & 0xff] ^
\r
334 Te2[(t2 >> 8) & 0xff] ^
\r
335 Te3[(t3 ) & 0xff] ^
\r
339 Te1[(t2 >> 16) & 0xff] ^
\r
340 Te2[(t3 >> 8) & 0xff] ^
\r
341 Te3[(t0 ) & 0xff] ^
\r
345 Te1[(t3 >> 16) & 0xff] ^
\r
346 Te2[(t0 >> 8) & 0xff] ^
\r
347 Te3[(t1 ) & 0xff] ^
\r
351 Te1[(t0 >> 16) & 0xff] ^
\r
352 Te2[(t1 >> 8) & 0xff] ^
\r
353 Te3[(t2 ) & 0xff] ^
\r
356 #endif /* ?FULL_UNROLL */
\r
358 * apply last round and
\r
359 * map cipher state to byte array block:
\r
362 (Te4[(t0 >> 24) ] & 0xff000000) ^
\r
363 (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
\r
364 (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
\r
365 (Te4[(t3 ) & 0xff] & 0x000000ff) ^
\r
369 (Te4[(t1 >> 24) ] & 0xff000000) ^
\r
370 (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
\r
371 (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
\r
372 (Te4[(t0 ) & 0xff] & 0x000000ff) ^
\r
374 PUTWORD(ct + 4, s1);
\r
376 (Te4[(t2 >> 24) ] & 0xff000000) ^
\r
377 (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
\r
378 (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
\r
379 (Te4[(t1 ) & 0xff] & 0x000000ff) ^
\r
381 PUTWORD(ct + 8, s2);
\r
383 (Te4[(t3 >> 24) ] & 0xff000000) ^
\r
384 (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
\r
385 (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
\r
386 (Te4[(t2 ) & 0xff] & 0x000000ff) ^
\r
388 PUTWORD(ct + 12, s3);
\r
391 void AES::decrypt(const byte *ct, byte *pt) {
\r
392 uint *rdk = d_sched;
\r
393 uint s0, s1, s2, s3, t0, t1, t2, t3;
\r
394 #ifndef FULL_UNROLL
\r
396 #endif /* ?FULL_UNROLL */
\r
399 * map byte array block to cipher state
\r
400 * and add initial round key:
\r
402 s0 = GETWORD(ct ) ^ rdk[0];
\r
403 s1 = GETWORD(ct + 4) ^ rdk[1];
\r
404 s2 = GETWORD(ct + 8) ^ rdk[2];
\r
405 s3 = GETWORD(ct + 12) ^ rdk[3];
\r
408 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[ 4];
\r
409 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[ 5];
\r
410 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[ 6];
\r
411 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[ 7];
\r
413 s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rdk[ 8];
\r
414 s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rdk[ 9];
\r
415 s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rdk[10];
\r
416 s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rdk[11];
\r
418 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[12];
\r
419 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[13];
\r
420 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[14];
\r
421 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[15];
\r
423 s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rdk[16];
\r
424 s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rdk[17];
\r
425 s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rdk[18];
\r
426 s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rdk[19];
\r
428 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[20];
\r
429 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[21];
\r
430 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[22];
\r
431 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[23];
\r
433 s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rdk[24];
\r
434 s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rdk[25];
\r
435 s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rdk[26];
\r
436 s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rdk[27];
\r
438 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[28];
\r
439 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[29];
\r
440 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[30];
\r
441 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[31];
\r
443 s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rdk[32];
\r
444 s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rdk[33];
\r
445 s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rdk[34];
\r
446 s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rdk[35];
\r
448 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[36];
\r
449 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[37];
\r
450 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[38];
\r
451 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[39];
\r
454 s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rdk[40];
\r
455 s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rdk[41];
\r
456 s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rdk[42];
\r
457 s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rdk[43];
\r
459 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[44];
\r
460 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[45];
\r
461 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[46];
\r
462 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[47];
\r
465 s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rdk[48];
\r
466 s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rdk[49];
\r
467 s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rdk[50];
\r
468 s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rdk[51];
\r
470 t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[52];
\r
471 t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[53];
\r
472 t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[54];
\r
473 t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[55];
\r
477 #else /* !FULL_UNROLL */
\r
479 * Nr - 1 full rounds:
\r
485 Td1[(s3 >> 16) & 0xff] ^
\r
486 Td2[(s2 >> 8) & 0xff] ^
\r
487 Td3[(s1 ) & 0xff] ^
\r
491 Td1[(s0 >> 16) & 0xff] ^
\r
492 Td2[(s3 >> 8) & 0xff] ^
\r
493 Td3[(s2 ) & 0xff] ^
\r
497 Td1[(s1 >> 16) & 0xff] ^
\r
498 Td2[(s0 >> 8) & 0xff] ^
\r
499 Td3[(s3 ) & 0xff] ^
\r
503 Td1[(s2 >> 16) & 0xff] ^
\r
504 Td2[(s1 >> 8) & 0xff] ^
\r
505 Td3[(s0 ) & 0xff] ^
\r
515 Td1[(t3 >> 16) & 0xff] ^
\r
516 Td2[(t2 >> 8) & 0xff] ^
\r
517 Td3[(t1 ) & 0xff] ^
\r
521 Td1[(t0 >> 16) & 0xff] ^
\r
522 Td2[(t3 >> 8) & 0xff] ^
\r
523 Td3[(t2 ) & 0xff] ^
\r
527 Td1[(t1 >> 16) & 0xff] ^
\r
528 Td2[(t0 >> 8) & 0xff] ^
\r
529 Td3[(t3 ) & 0xff] ^
\r
533 Td1[(t2 >> 16) & 0xff] ^
\r
534 Td2[(t1 >> 8) & 0xff] ^
\r
535 Td3[(t0 ) & 0xff] ^
\r
538 #endif /* ?FULL_UNROLL */
\r
540 * apply last round and
\r
541 * map cipher state to byte array block:
\r
544 (Td4[(t0 >> 24) ] & 0xff000000) ^
\r
545 (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
\r
546 (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
\r
547 (Td4[(t1 ) & 0xff] & 0x000000ff) ^
\r
551 (Td4[(t1 >> 24) ] & 0xff000000) ^
\r
552 (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
\r
553 (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
\r
554 (Td4[(t2 ) & 0xff] & 0x000000ff) ^
\r
556 PUTWORD(pt + 4, s1);
\r
558 (Td4[(t2 >> 24) ] & 0xff000000) ^
\r
559 (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
\r
560 (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
\r
561 (Td4[(t3 ) & 0xff] & 0x000000ff) ^
\r
563 PUTWORD(pt + 8, s2);
\r
565 (Td4[(t3 >> 24) ] & 0xff000000) ^
\r
566 (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
\r
567 (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
\r
568 (Td4[(t0 ) & 0xff] & 0x000000ff) ^
\r
570 PUTWORD(pt + 12, s3);
\r