Imported Upstream version 1.1.11
[platform/upstream/libmtp.git] / src / mtpz.c
1 /**
2  * \file mtpz.c
3  *
4  * Copyright (C) 2011-2012 Sajid Anwar <sajidanwar94@gmail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  * This file provides mtp zune cryptographic setup interfaces.
22  * It is also used with Windows Phone 7, but Microsoft/Nokiad seem
23  * to have discontinued MTPZ on Windows Phone 8.
24  *
25  * DISCLAIMER:
26  *
27  * The intention of this implementation is for users to be able
28  * to interoperate with their devices, i.e. copy music to them in
29  * operating systems other than Microsoft Windows, so it can be
30  * played back on the device. We do not provide encryption keys
31  * and constants in libmtp, we never will. You have to have these
32  * on file in your home directory in $HOME/.mtpz-data, and we suggest
33  * that you talk to Microsoft about providing the proper numbers if
34  * you want to use this facility.
35  */
36 #include "config.h"
37 #include "libmtp.h"
38 #include "unicode.h"
39 #include "ptp.h"
40 #include "libusb-glue.h"
41 #include "device-flags.h"
42 #include "playlist-spl.h"
43 #include "util.h"
44 #include "mtpz.h"
45
46 #include <gcrypt.h>
47
48 #include <stdlib.h>
49 #include <unistd.h>
50 #include <string.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 #include <time.h>
54 #include <errno.h>
55
56
57 /* Microsoft MTPZ extensions */
58
59 /*
60  * The ~/.mtpz-data file contains all four necessary pieces of data:
61  *
62  *   encryption key
63  *   public exponent
64  *   modulus
65  *   private key
66  *   certificate data
67  *
68  * These four pieces of data are each stored in hex representation,
69  * separated by newline characters.
70  *
71  * If you know of a published, public reference for one of these
72  * arrays of data, please inform us, so we can include it here and
73  * drop it from the external file. Even better is if you convince
74  * Microsoft to officially provide keys to this project.
75  */
76
77 static unsigned char *MTPZ_ENCRYPTION_KEY;
78 static unsigned char *MTPZ_PUBLIC_EXPONENT;
79 static unsigned char *MTPZ_MODULUS;
80 static unsigned char *MTPZ_PRIVATE_KEY;
81 static char *MTPZ_CERTIFICATES;
82
83 // Strip the trailing newline from fgets().
84 static char *fgets_strip(char * str, int num, FILE * stream)
85 {
86         char *result = str;
87
88         if ((result = fgets(str, num, stream)))
89         {
90                 size_t newlen = strlen(result);
91
92                 if (result[newlen - 1] == '\n')
93                         result[newlen - 1] = '\0';
94         }
95
96         return result;
97 }
98
99 static char *hex_to_bytes(char *hex, size_t len)
100 {
101         if (len % 2)
102                 return NULL;
103
104         char *bytes = malloc(len / 2);
105         unsigned int u;
106         int i = 0;
107
108         while (i < len && sscanf(hex + i, "%2x", &u) == 1)
109         {
110                 bytes[i / 2] = u;
111                 i += 2;
112         }
113
114         return bytes;
115 }
116
117 int mtpz_loaddata()
118 {
119         char *home = getenv("HOME");
120         int ret = -1;
121         if (!home)
122         {
123                 LIBMTP_ERROR("Unable to determine user's home directory, MTPZ disabled.\n");
124                 return -1;
125         }
126
127         int plen = strlen(home) + strlen("/.mtpz-data") + 1;
128         char path[plen];
129         sprintf(path, "%s/.mtpz-data", home);
130
131         FILE *fdata = fopen(path, "r");
132         if (!fdata)
133                 return ret;
134
135         // Should only be six characters in length, but fgets will encounter a newline and stop.
136         MTPZ_PUBLIC_EXPONENT = (unsigned char *)fgets_strip((char *)malloc(8), 8, fdata);
137         if (!MTPZ_PUBLIC_EXPONENT)
138         {
139                 LIBMTP_ERROR("Unable to read MTPZ public exponent from ~/.mtpz-data, MTPZ disabled.\n");
140                 goto cleanup;
141         }
142
143         // Should only be 33 characters in length, but fgets will encounter a newline and stop.
144         char *hexenckey = fgets_strip((char *)malloc(35), 35, fdata);
145         if (!hexenckey)
146         {
147                 LIBMTP_ERROR("Unable to read MTPZ encryption key from ~/.mtpz-data, MTPZ disabled.\n");
148                 goto cleanup;
149         }
150
151         MTPZ_ENCRYPTION_KEY = hex_to_bytes(hexenckey, strlen(hexenckey));
152         if (!MTPZ_ENCRYPTION_KEY)
153         {
154                 LIBMTP_ERROR("Unable to read MTPZ encryption key from ~/.mtpz-data, MTPZ disabled.\n");
155                 goto cleanup;
156         }
157
158         // Should only be 256 characters in length, but fgets will encounter a newline and stop.
159         MTPZ_MODULUS = (unsigned char *)fgets_strip((char *)malloc(260), 260, fdata);
160         if (!MTPZ_MODULUS)
161         {
162                 LIBMTP_ERROR("Unable to read MTPZ modulus from ~/.mtpz-data, MTPZ disabled.\n");
163                 goto cleanup;
164         }
165
166         // Should only be 256 characters in length, but fgets will encounter a newline and stop.
167         MTPZ_PRIVATE_KEY = (unsigned char *)fgets_strip((char *)malloc(260), 260, fdata);
168         if (!MTPZ_PRIVATE_KEY)
169         {
170                 LIBMTP_ERROR("Unable to read MTPZ private key from ~/.mtpz-data, MTPZ disabled.\n");
171                 goto cleanup;
172         }
173
174         // Should only be 1258 characters in length, but fgets will encounter the end of the file and stop.
175         char *hexcerts = fgets_strip((char *)malloc(1260), 1260, fdata);
176         if (!hexcerts)
177         {
178                 LIBMTP_ERROR("Unable to read MTPZ certificates from ~/.mtpz-data, MTPZ disabled.\n");
179                 goto cleanup;
180         }
181
182         MTPZ_CERTIFICATES = hex_to_bytes(hexcerts, strlen(hexcerts));
183         if (!MTPZ_CERTIFICATES)
184         {
185                 LIBMTP_ERROR("Unable to parse MTPZ certificates from ~/.mtpz-data, MTPZ disabled.\n");
186                 goto cleanup;
187         }
188         // If all done without errors, drop the fail
189         ret = 0;
190 cleanup:
191         fclose(fdata);
192         return ret;
193 }
194 /* MTPZ RSA */
195
196 typedef struct mtpz_rsa_struct
197 {
198         gcry_sexp_t privkey;
199         gcry_sexp_t pubkey;
200 } mtpz_rsa_t;
201
202 mtpz_rsa_t *mtpz_rsa_init(const unsigned char *modulus, const unsigned char *priv_key, const unsigned char *pub_exp);
203 void mtpz_rsa_free(mtpz_rsa_t *);
204 int mtpz_rsa_decrypt(int flen, unsigned char *from, int tlen, unsigned char *to, mtpz_rsa_t *rsa);
205 int mtpz_rsa_sign(int flen, unsigned char *from, int tlen, unsigned char *to, mtpz_rsa_t *rsa);
206
207 /* MTPZ hashing */
208
209 #define MTPZ_HASHSTATE_84 5
210 #define MTPZ_HASHSTATE_88 6
211
212 static char *mtpz_hash_init_state();
213 static void mtpz_hash_reset_state(char *);
214 static void mtpz_hash_transform_hash(char *, char *, int);
215 static void mtpz_hash_finalize_hash(char *, char *);
216 static char *mtpz_hash_custom6A5DC(char *, char *, int, int);
217
218 static void mtpz_hash_compute_hash(char *, char *, int);
219 static unsigned int mtpz_hash_f(int s, unsigned int x, unsigned int y, unsigned int z);
220 static unsigned int mtpz_hash_rotate_left(unsigned int x, int n);
221
222 /* MTPZ encryption */
223
224 unsigned char mtpz_aes_rcon[];
225 unsigned char mtpz_aes_sbox[];
226 unsigned char mtpz_aes_invsbox[];
227 unsigned int mtpz_aes_ft1[];
228 unsigned int mtpz_aes_ft2[];
229 unsigned int mtpz_aes_ft3[];
230 unsigned int mtpz_aes_ft4[];
231 unsigned int mtpz_aes_rt1[];
232 unsigned int mtpz_aes_rt2[];
233 unsigned int mtpz_aes_rt3[];
234 unsigned int mtpz_aes_rt4[];
235 unsigned int mtpz_aes_gb11[];
236 unsigned int mtpz_aes_gb14[];
237 unsigned int mtpz_aes_gb13[];
238 unsigned int mtpz_aes_gb9[];
239
240 #define MTPZ_ENCRYPTIONLOBYTE(val) (((val) >> 24) & 0xFF)
241 #define MTPZ_ENCRYPTIONBYTE1(val) (((val) >> 16) & 0xFF)
242 #define MTPZ_ENCRYPTIONBYTE2(val) (((val) >>  8) & 0xFF)
243 #define MTPZ_ENCRYPTIONBYTE3(val) (((val) >>  0) & 0xFF)
244
245 #define MTPZ_SWAP(x) mtpz_bswap32(x)
246
247 void mtpz_encryption_cipher(unsigned char *data, unsigned int len, char encrypt);
248 void mtpz_encryption_cipher_advanced(unsigned char *key, unsigned int key_len, unsigned char *data, unsigned int data_len, char encrypt);
249 unsigned char *mtpz_encryption_expand_key(unsigned char *constant, int key_len, int count, int *out_len);
250 void mtpz_encryption_expand_key_inner(unsigned char *constant, int key_len, unsigned char **out, int *out_len);
251 void mtpz_encryption_inv_mix_columns(unsigned char *expanded, int offset, int rounds);
252 void mtpz_encryption_decrypt_custom(unsigned char *data, unsigned char *seed, unsigned char *expanded);
253 void mtpz_encryption_encrypt_custom(unsigned char *data, unsigned char *seed, unsigned char *expanded);
254 void mtpz_encryption_encrypt_mac(unsigned char *hash, unsigned int hash_length, unsigned char *seed, unsigned int seed_len, unsigned char *out);
255
256
257 static inline uint32_t mtpz_bswap32(uint32_t x)
258 {
259 #if defined __GNUC__ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) || defined(__clang__)
260         return __builtin_bswap32(x);
261 #else
262         return (x >> 24) |
263                ((x >> 8) & 0x0000ff00) |
264                ((x << 8) & 0x00ff0000) |
265                (x << 24);
266 #endif
267 }
268
269
270 /* MTPZ RSA implementation */
271 mtpz_rsa_t *mtpz_rsa_init(const unsigned char *str_modulus, const unsigned char *str_privkey, const unsigned char *str_pubexp)
272 {
273         mtpz_rsa_t *rsa = calloc(1, sizeof(mtpz_rsa_t));
274         if (rsa == NULL)
275                 return NULL;
276
277         gcry_mpi_t mpi_modulus, mpi_privkey, mpi_pubexp;
278
279         gcry_mpi_scan(&mpi_modulus, GCRYMPI_FMT_HEX, str_modulus, 0, NULL);
280         gcry_mpi_scan(&mpi_privkey, GCRYMPI_FMT_HEX, str_privkey, 0, NULL);
281         gcry_mpi_scan(&mpi_pubexp, GCRYMPI_FMT_HEX, str_pubexp, 0, NULL);
282
283         gcry_sexp_build(&rsa->privkey, NULL, "(private-key (rsa (n %m) (e %m) (d %m)))", mpi_modulus, mpi_pubexp, mpi_privkey);
284         gcry_sexp_build(&rsa->pubkey, NULL, "(public-key (rsa (n %m) (e %m)))", mpi_modulus, mpi_pubexp);
285
286         gcry_mpi_release(mpi_modulus);
287         gcry_mpi_release(mpi_privkey);
288         gcry_mpi_release(mpi_pubexp);
289
290         return rsa;
291 }
292
293 void mtpz_rsa_free(mtpz_rsa_t *rsa)
294 {
295         gcry_sexp_release(rsa->privkey);
296         gcry_sexp_release(rsa->pubkey);
297 }
298
299 int mtpz_rsa_decrypt(int flen, unsigned char *from, int tlen, unsigned char *to, mtpz_rsa_t *rsa)
300 {
301         gcry_mpi_t mpi_from;
302         gcry_mpi_scan(&mpi_from, GCRYMPI_FMT_USG, from, flen, NULL);
303
304         gcry_sexp_t sexp_data;
305         gcry_sexp_build(&sexp_data, NULL, "(enc-val (flags raw) (rsa (a %m)))", mpi_from);
306
307         gcry_sexp_t sexp_plain;
308         gcry_pk_decrypt(&sexp_plain, sexp_data, rsa->privkey);
309
310         gcry_mpi_t mpi_value = gcry_sexp_nth_mpi(sexp_plain, 1, GCRYMPI_FMT_USG);
311
312         // Lame workaround. GCRYMPI_FMT_USG gets rid of any leading zeroes which we do need,
313         // so we'll count how many bits are being used, and subtract that from how many bits actually
314         // should be there, and then write into our output array shifted over however many bits/8.
315         int bitshift = (tlen * 8) - gcry_mpi_get_nbits(mpi_value);
316         size_t written;
317
318         if (bitshift / 8)
319         {
320                 memset(to, 0, bitshift / 8);
321                 to += bitshift / 8;
322                 tlen -= bitshift / 8;
323         }
324
325         gcry_mpi_print(GCRYMPI_FMT_USG, to, tlen, &written, mpi_value);
326
327         gcry_mpi_release(mpi_from);
328         gcry_mpi_release(mpi_value);
329         gcry_sexp_release(sexp_data);
330         gcry_sexp_release(sexp_plain);
331
332         return (int)written;
333 }
334
335 int mtpz_rsa_sign(int flen, unsigned char *from, int tlen, unsigned char *to, mtpz_rsa_t *rsa)
336 {
337         return mtpz_rsa_decrypt(flen, from, tlen, to, rsa);
338 }
339
340 /* MTPZ hashing implementation */
341
342 static char *mtpz_hash_init_state()
343 {
344         char *s = (char *)malloc(92);
345
346         if (s != NULL)
347                 memset(s, 0, 92);
348
349         return s;
350 }
351
352 void mtpz_hash_reset_state(char *state)
353 {
354         int *state_box = (int *)(state + 64);
355
356         /*
357          * Constants from
358          * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
359          * Page 13, section 5.3.1
360          */
361         state_box[0] = 0x67452301;
362         state_box[1] = 0xefcdab89;
363         state_box[2] = 0x98badcfe;
364         state_box[3] = 0x10325476;
365         state_box[4] = 0xc3d2e1f0;
366         state_box[MTPZ_HASHSTATE_84] = 0;
367         state_box[MTPZ_HASHSTATE_88] = 0;
368 }
369
370 void mtpz_hash_transform_hash(char *state, char *msg, int len)
371 {
372         int *state_box = (int *)(state + 64);
373
374         int x = state_box[MTPZ_HASHSTATE_88] & 0x3F;
375         int v5 = len + state_box[MTPZ_HASHSTATE_88];
376         state_box[MTPZ_HASHSTATE_88] = v5;
377
378         int i = len, j = 0;
379         int a1 = 0;
380         int c = 0;
381
382         if (len > v5)
383                 state_box[MTPZ_HASHSTATE_84] += 1;
384
385         if (x)
386         {
387                 if (len + x > 0x3F)
388                 {
389                         for (a1 = 0; a1 < 64 - x; a1++)
390                         {
391                                 state[x + a1] = msg[a1];
392                         }
393
394                         i = len + x - 64;
395                         j = 64 - x;
396
397                         mtpz_hash_compute_hash(state, state, 64);
398                 }
399         }
400
401         while (i > 63)
402         {
403                 mtpz_hash_compute_hash(state, msg + j, 64);
404                 j += 64;
405                 i -= 64;
406         }
407
408         if (i != 0)
409         {
410                 for (c = 0; c < i; c++)
411                 {
412                         state[x + c] = msg[j + c];
413                 }
414         }
415 }
416
417 // out has at least 20 bytes of space
418 void mtpz_hash_finalize_hash(char *state, char *out)
419 {
420         int *state_box = (int *)(state + 64);
421
422         int v2 = 64 - (state_box[MTPZ_HASHSTATE_88] & 0x3F);
423         int v6, v7;
424
425         if (v2 <= 8)
426                 v2 += 64;
427
428         char *v5 = (char *)malloc(72);
429         memset(v5, 0, 72);
430
431         v5[0] = '\x80';
432         v6 = 8 * state_box[MTPZ_HASHSTATE_84] | (state_box[MTPZ_HASHSTATE_88] >> 29);
433         v7 = 8 * state_box[MTPZ_HASHSTATE_88];
434
435         v6 = MTPZ_SWAP(v6);
436         v7 = MTPZ_SWAP(v7);
437
438         *(int *)(v5 + v2 - 8) = v6;
439         *(int *)(v5 + v2 - 4) = v7;
440
441         mtpz_hash_transform_hash(state, v5, v2);
442
443         int *out_int = (int *)out;
444         out_int[0] = MTPZ_SWAP(state_box[0]);
445         out_int[1] = MTPZ_SWAP(state_box[1]);
446         out_int[2] = MTPZ_SWAP(state_box[2]);
447         out_int[3] = MTPZ_SWAP(state_box[3]);
448         out_int[4] = MTPZ_SWAP(state_box[4]);
449
450         memset(state, 0, 64);
451         mtpz_hash_reset_state(state);
452 }
453
454 char *mtpz_hash_custom6A5DC(char *state, char *msg, int len, int a4)
455 {
456         int v11 = (a4 / 20) + 1;
457         char *v13 = (char *)malloc(v11 * 20);
458         char *v5 = (char *)malloc(len + 4);
459         int i;
460         int k;
461
462         memset(v13, 0, v11 * 20);
463         memset(v5, 0, len + 4);
464         memcpy(v5, msg, len);
465
466         for (i = 0; i < v11; i++)
467         {
468                 k = MTPZ_SWAP(i);
469                 *(int *)(v5 + len) = k;
470
471                 mtpz_hash_reset_state(state);
472                 mtpz_hash_transform_hash(state, v5, len + 4);
473                 mtpz_hash_finalize_hash(state, v13 + i * 20);
474         }
475
476         free(v5); v5 = NULL;
477
478         return v13;
479 }
480
481 void mtpz_hash_compute_hash(char *state, char *msg, int len)
482 {
483         int *state_box = (int *)(state + 64);
484
485         const unsigned int K[] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 };
486
487         if (len != 64)
488                 return;
489
490         int *M = (int *)msg;
491
492         // HASH COMPUTATION
493         unsigned int W[80];
494         unsigned int a, b, c, d, e;
495         int i, s;
496         unsigned int T;
497
498         // 1 - prepare message schedule 'W'.
499         for (i = 0; i < 16; i++) W[i] = MTPZ_SWAP(M[i]);
500         for (i = 16; i < 80; i++) W[i] = mtpz_hash_rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
501
502         // 2 - initialize five working variables a, b, c, d, e with previous hash value
503         a = state_box[0];
504         b = state_box[1];
505         c = state_box[2];
506         d = state_box[3];
507         e = state_box[4];
508
509         // 3 - main loop
510         for (i = 0; i < 80; i++)
511         {
512                 s = i / 20;
513                 T = (mtpz_hash_rotate_left(a, 5) + mtpz_hash_f(s, b, c, d) + e + K[s] + W[i]) & 0xFFFFFFFF;
514                 e = d;
515                 d = c;
516                 c = mtpz_hash_rotate_left(b, 30);
517                 b = a;
518                 a = T;
519         }
520
521         state_box[0] = (state_box[0] + a) & 0xFFFFFFFF;
522         state_box[1] = (state_box[1] + b) & 0xFFFFFFFF;
523         state_box[2] = (state_box[2] + c) & 0xFFFFFFFF;
524         state_box[3] = (state_box[3] + d) & 0xFFFFFFFF;
525         state_box[4] = (state_box[4] + e) & 0xFFFFFFFF;
526 }
527
528 unsigned int mtpz_hash_f(int s, unsigned int x, unsigned int y, unsigned int z)
529 {
530         switch (s)
531         {
532         case 0:
533                 return (x & y) ^ (~x & z); // Ch()
534         case 1:
535                 return x ^ y ^ z; // Parity()
536         case 2:
537                 return (x & y) ^ (x & z) ^ (y & z); // Maj()
538         case 3:
539                 return x ^ y ^ z; // Parity()
540         }
541
542         return 0;
543 }
544
545 unsigned int mtpz_hash_rotate_left(unsigned int x, int n)
546 {
547         return (x << n) | (x >> (32 - n));
548 }
549
550 /* MTPZ encryption implementation */
551
552 void mtpz_encryption_cipher(unsigned char *data, unsigned int len, char encrypt)
553 {
554         unsigned char *expanded = NULL;
555
556         int offset = 0, count = len;
557
558         if ((count & 0x0F) == 0)
559         {
560                 int exp_len = 0;
561                 expanded = mtpz_encryption_expand_key((unsigned char *)MTPZ_ENCRYPTION_KEY, 16, 10, &exp_len);
562
563                 if (count != 0)
564                 {
565                         do
566                         {
567                                 if (encrypt)
568                                         mtpz_encryption_encrypt_custom(data + offset, NULL, expanded);
569                                 else
570                                         mtpz_encryption_decrypt_custom(data + offset, NULL, expanded);
571
572                                 count -= 16;
573                                 offset += 16;
574                         }
575                         while (count != 0);
576                 }
577         }
578 }
579
580 void mtpz_encryption_cipher_advanced(unsigned char *key, unsigned int key_len, unsigned char *data, unsigned int data_len, char encrypt)
581 {
582         int len = (key_len == 16) ? 10 :
583                           (key_len == 24) ? 12 : 32;
584         int exp_len;
585         unsigned char *expanded = mtpz_encryption_expand_key(key, key_len, len, &exp_len);
586
587         int offset = 0, count = data_len;
588         unsigned char *out = (unsigned char *)malloc(16);
589         unsigned int *out_int = (unsigned int *)out;
590         unsigned int *data_int = (unsigned int *)data;
591         unsigned int *dtf = (unsigned int *)malloc(16);
592         memset((unsigned char *)dtf, 0, 16);
593
594         while (count != 0)
595         {
596                 int chunk = 16;
597
598                 if (count < 16)
599                 {
600                         memset(out, 0, 16);
601                         chunk = count;
602                 }
603
604                 memcpy(out, data + offset, chunk);
605
606                 if (encrypt)
607                 {
608                         out_int[0] ^= MTPZ_SWAP(dtf[0]);
609                         out_int[1] ^= MTPZ_SWAP(dtf[1]);
610                         out_int[2] ^= MTPZ_SWAP(dtf[2]);
611                         out_int[3] ^= MTPZ_SWAP(dtf[3]);
612
613                         mtpz_encryption_encrypt_custom(data + offset, out, expanded);
614
615                         dtf[0] = MTPZ_SWAP(data_int[(offset / 4) + 0]);
616             dtf[1] = MTPZ_SWAP(data_int[(offset / 4) + 1]);
617             dtf[2] = MTPZ_SWAP(data_int[(offset / 4) + 2]);
618             dtf[3] = MTPZ_SWAP(data_int[(offset / 4) + 3]);
619                 }
620                 else
621                 {
622                         mtpz_encryption_decrypt_custom(data + offset, out, expanded);
623
624                         data_int[(offset / 4) + 0] ^= MTPZ_SWAP(dtf[0]);
625                         data_int[(offset / 4) + 1] ^= MTPZ_SWAP(dtf[1]);
626                         data_int[(offset / 4) + 2] ^= MTPZ_SWAP(dtf[2]);
627                         data_int[(offset / 4) + 3] ^= MTPZ_SWAP(dtf[3]);
628
629                         dtf[0] = MTPZ_SWAP(out_int[0]);
630                         dtf[1] = MTPZ_SWAP(out_int[1]);
631                         dtf[2] = MTPZ_SWAP(out_int[2]);
632                         dtf[3] = MTPZ_SWAP(out_int[3]);
633                 }
634
635                 offset += chunk;
636                 count -= chunk;
637         }
638
639         free(out);
640         free(dtf);
641         free(expanded);
642 }
643
644 unsigned char *mtpz_encryption_expand_key(unsigned char *constant, int key_len, int count, int *out_len)
645 {
646         int i = 0;
647         int seek = 0;
648         unsigned char *back = (unsigned char *)malloc(484);
649         memset(back, 0, 484);
650         *out_len = 484;
651
652         unsigned char *inner;
653         int inner_len;
654         mtpz_encryption_expand_key_inner(constant, key_len, &inner, &inner_len);
655
656         back[i] = (unsigned char)(count % 0xFF);
657         i += 4;
658
659         memcpy(back + i, inner, inner_len);
660         i += inner_len;
661         memcpy(back + i, inner, inner_len);
662         i += inner_len;
663
664         switch (count)
665         {
666         case 10:
667                 seek = 0xB4;
668                 break;
669
670         case 12:
671                 seek = 0xD4;
672                 break;
673
674         case 14:
675         default:
676                 seek = 0xF4;
677                 break;
678         }
679
680         mtpz_encryption_inv_mix_columns(back, seek, count);
681
682         return back;
683 }
684
685 void mtpz_encryption_expand_key_inner(unsigned char *constant, int key_len, unsigned char **out, int *out_len)
686 {
687         int ks = -1;
688         int rcon_i = 0;
689         int i = 0, j = 0;
690
691         switch (key_len)
692         {
693                 case 16:
694                         ks = 16 * (10 + 1);
695                         break;
696
697                 case 24:
698                         ks = 16 * (12 + 1);
699                         break;
700
701                 case 32:
702                         ks = 16 * (14 + 1);
703                         break;
704
705                 default:
706                         *out = NULL;
707                         *out_len = 0;
708         }
709
710         unsigned char *key = (unsigned char *)malloc(ks);
711         unsigned char *temp = (unsigned char *)malloc(4);
712         memcpy(key, constant, key_len);
713         unsigned char t0, t1, t2, t3;
714
715         for (i = key_len; i < ks; i += 4)
716         {
717                 temp[0] = t0 = key[i - 4];
718                 temp[1] = t1 = key[i - 3];
719                 temp[2] = t2 = key[i - 2];
720                 temp[3] = t3 = key[i - 1];
721
722                 if (i % key_len == 0)
723                 {
724                         temp[0] = (mtpz_aes_sbox[t1] ^ mtpz_aes_rcon[rcon_i]) & 0xFF;
725                         temp[1] = mtpz_aes_sbox[t2];
726                         temp[2] = mtpz_aes_sbox[t3];
727                         temp[3] = mtpz_aes_sbox[t0];
728                         rcon_i++;
729                 }
730                 else if ((key_len > 24) && (i % key_len == 16))
731                 {
732                         temp[0] = mtpz_aes_sbox[t0];
733                         temp[1] = mtpz_aes_sbox[t1];
734                         temp[2] = mtpz_aes_sbox[t2];
735                         temp[3] = mtpz_aes_sbox[t3];
736                 }
737
738                 for (j = 0; j < 4; j++)
739                 {
740                         key[i + j] = (unsigned char)((key[i + j - key_len] ^ temp[j]) & 0xFF);
741                 }
742         }
743
744         free(temp);
745
746         *out = key;
747         *out_len = ks;
748 }
749
750 void mtpz_encryption_inv_mix_columns(unsigned char *expanded, int offset, int rounds)
751 {
752         int v8 = 1, o = offset;
753         unsigned int *exp_int = NULL;
754
755         for (v8 = 1; v8 < rounds; v8++)
756         {
757                 exp_int = (unsigned int *)(expanded + o + 16);
758
759                 exp_int[0] = MTPZ_SWAP(mtpz_aes_gb9[expanded[o + 19]] ^ mtpz_aes_gb13[expanded[o + 18]] ^ mtpz_aes_gb11[expanded[o + 17]] ^ mtpz_aes_gb14[expanded[o + 16]]);
760                 exp_int[1] = MTPZ_SWAP(mtpz_aes_gb9[expanded[o + 23]] ^ mtpz_aes_gb13[expanded[o + 22]] ^ mtpz_aes_gb11[expanded[o + 21]] ^ mtpz_aes_gb14[expanded[o + 20]]);
761                 exp_int[2] = MTPZ_SWAP(mtpz_aes_gb9[expanded[o + 27]] ^ mtpz_aes_gb13[expanded[o + 26]] ^ mtpz_aes_gb11[expanded[o + 25]] ^ mtpz_aes_gb14[expanded[o + 24]]);
762                 exp_int[3] = MTPZ_SWAP(mtpz_aes_gb9[expanded[o + 31]] ^ mtpz_aes_gb13[expanded[o + 30]] ^ mtpz_aes_gb11[expanded[o + 29]] ^ mtpz_aes_gb14[expanded[o + 28]]);
763                 o += 16;
764         }
765 }
766
767 void mtpz_encryption_decrypt_custom(unsigned char *data, unsigned char *seed, unsigned char *expanded)
768 {
769         unsigned int *u_data = (unsigned int *)data;
770         unsigned int *u_expanded = (unsigned int *)expanded;
771         int keyOffset = 0xB4 + 0xA0;
772
773         unsigned int *u_seed;
774
775         if (seed == NULL)
776                 u_seed = u_data;
777         else
778                 u_seed = (unsigned int *)seed;
779
780         unsigned int v14 = MTPZ_SWAP(u_seed[0]) ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]);
781         unsigned int v15 = MTPZ_SWAP(u_seed[1]) ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]);
782         unsigned int v16 = MTPZ_SWAP(u_seed[2]) ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]);
783         unsigned int v17 = MTPZ_SWAP(u_seed[3]) ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]);
784
785         unsigned int v18 = mtpz_aes_rt1[MTPZ_ENCRYPTIONBYTE3(v15)] ^ mtpz_aes_rt2[MTPZ_ENCRYPTIONBYTE2(v16)] ^ mtpz_aes_rt3[MTPZ_ENCRYPTIONLOBYTE(v14)] ^ mtpz_aes_rt4[MTPZ_ENCRYPTIONBYTE1(v17)];
786         unsigned int v19 = mtpz_aes_rt1[MTPZ_ENCRYPTIONBYTE3(v16)] ^ mtpz_aes_rt2[MTPZ_ENCRYPTIONBYTE2(v17)] ^ mtpz_aes_rt3[MTPZ_ENCRYPTIONLOBYTE(v15)] ^ mtpz_aes_rt4[MTPZ_ENCRYPTIONBYTE1(v14)];
787         unsigned int v20 = mtpz_aes_rt1[MTPZ_ENCRYPTIONBYTE3(v17)] ^ mtpz_aes_rt2[MTPZ_ENCRYPTIONBYTE2(v14)] ^ mtpz_aes_rt3[MTPZ_ENCRYPTIONLOBYTE(v16)] ^ mtpz_aes_rt4[MTPZ_ENCRYPTIONBYTE1(v15)];
788         unsigned int v21 = mtpz_aes_rt1[MTPZ_ENCRYPTIONBYTE3(v14)] ^ mtpz_aes_rt2[MTPZ_ENCRYPTIONBYTE2(v15)] ^ mtpz_aes_rt3[MTPZ_ENCRYPTIONLOBYTE(v17)] ^ mtpz_aes_rt4[MTPZ_ENCRYPTIONBYTE1(v16)];
789
790         keyOffset -= 16;
791         int rounds = 9;
792
793         do
794         {
795                 v14 = v18 ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]);
796                 v15 = v19 ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]);
797                 v16 = v20 ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]);
798                 v17 = v21 ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]);
799
800                 v18 = mtpz_aes_rt1[MTPZ_ENCRYPTIONBYTE3(v15)] ^ mtpz_aes_rt2[MTPZ_ENCRYPTIONBYTE2(v16)] ^ mtpz_aes_rt3[MTPZ_ENCRYPTIONLOBYTE(v14)] ^ mtpz_aes_rt4[MTPZ_ENCRYPTIONBYTE1(v17)];
801                 v19 = mtpz_aes_rt1[MTPZ_ENCRYPTIONBYTE3(v16)] ^ mtpz_aes_rt2[MTPZ_ENCRYPTIONBYTE2(v17)] ^ mtpz_aes_rt3[MTPZ_ENCRYPTIONLOBYTE(v15)] ^ mtpz_aes_rt4[MTPZ_ENCRYPTIONBYTE1(v14)];
802                 v20 = mtpz_aes_rt1[MTPZ_ENCRYPTIONBYTE3(v17)] ^ mtpz_aes_rt2[MTPZ_ENCRYPTIONBYTE2(v14)] ^ mtpz_aes_rt3[MTPZ_ENCRYPTIONLOBYTE(v16)] ^ mtpz_aes_rt4[MTPZ_ENCRYPTIONBYTE1(v15)];
803                 v21 = mtpz_aes_rt1[MTPZ_ENCRYPTIONBYTE3(v14)] ^ mtpz_aes_rt2[MTPZ_ENCRYPTIONBYTE2(v15)] ^ mtpz_aes_rt3[MTPZ_ENCRYPTIONLOBYTE(v17)] ^ mtpz_aes_rt4[MTPZ_ENCRYPTIONBYTE1(v16)];
804
805                 rounds--;
806                 keyOffset -= 16;
807         }
808         while (rounds != 1);
809
810         v14 = v18 ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]);
811         v15 = v19 ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]);
812         v16 = v20 ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]);
813         v17 = v21 ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]);
814         keyOffset -= 16;
815
816         v18 = ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONLOBYTE(v14)]) << 24) |
817                   ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE1 (v17)]) << 16) |
818                   ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE2 (v16)]) <<  8) |
819                   ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE3 (v15)]) <<  0);
820
821         v19 = ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONLOBYTE(v15)]) << 24) |
822                   ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE1 (v14)]) << 16) |
823                   ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE2 (v17)]) <<  8) |
824                   ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE3 (v16)]) <<  0);
825
826         v20 = ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONLOBYTE(v16)]) << 24) |
827                   ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE1 (v15)]) << 16) |
828                   ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE2 (v14)]) <<  8) |
829                   ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE3 (v17)]) <<  0);
830
831         v21 = ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONLOBYTE(v17)]) << 24) |
832                   ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE1 (v16)]) << 16) |
833                   ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE2 (v15)]) <<  8) |
834                   ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE3 (v14)]) <<  0);
835
836         u_data[0] = MTPZ_SWAP(v18 ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]));
837         u_data[1] = MTPZ_SWAP(v19 ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]));
838         u_data[2] = MTPZ_SWAP(v20 ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]));
839         u_data[3] = MTPZ_SWAP(v21 ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]));
840 };
841
842 void mtpz_encryption_encrypt_custom(unsigned char *data, unsigned char *seed, unsigned char *expanded)
843 {
844         unsigned int *u_data = (unsigned int *)data;
845         unsigned int *u_expanded = (unsigned int *)expanded;
846         int keyOffset = 0x04;
847
848         unsigned int *u_seed;
849
850         if (seed == NULL)
851                 u_seed = u_data;
852         else
853                 u_seed = (unsigned int *)seed;
854
855         unsigned int v14 = MTPZ_SWAP(u_seed[0]) ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]);
856         unsigned int v15 = MTPZ_SWAP(u_seed[1]) ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]);
857         unsigned int v16 = MTPZ_SWAP(u_seed[2]) ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]);
858         unsigned int v17 = MTPZ_SWAP(u_seed[3]) ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]);
859
860         unsigned int v18 = mtpz_aes_ft1[MTPZ_ENCRYPTIONBYTE3(v17)] ^ mtpz_aes_ft2[MTPZ_ENCRYPTIONBYTE2(v16)] ^ mtpz_aes_ft3[MTPZ_ENCRYPTIONLOBYTE(v14)] ^ mtpz_aes_ft4[MTPZ_ENCRYPTIONBYTE1(v15)];
861         unsigned int v19 = mtpz_aes_ft1[MTPZ_ENCRYPTIONBYTE3(v14)] ^ mtpz_aes_ft2[MTPZ_ENCRYPTIONBYTE2(v17)] ^ mtpz_aes_ft3[MTPZ_ENCRYPTIONLOBYTE(v15)] ^ mtpz_aes_ft4[MTPZ_ENCRYPTIONBYTE1(v16)];
862         unsigned int v20 = mtpz_aes_ft1[MTPZ_ENCRYPTIONBYTE3(v15)] ^ mtpz_aes_ft2[MTPZ_ENCRYPTIONBYTE2(v14)] ^ mtpz_aes_ft3[MTPZ_ENCRYPTIONLOBYTE(v16)] ^ mtpz_aes_ft4[MTPZ_ENCRYPTIONBYTE1(v17)];
863         unsigned int v21 = mtpz_aes_ft1[MTPZ_ENCRYPTIONBYTE3(v16)] ^ mtpz_aes_ft2[MTPZ_ENCRYPTIONBYTE2(v15)] ^ mtpz_aes_ft3[MTPZ_ENCRYPTIONLOBYTE(v17)] ^ mtpz_aes_ft4[MTPZ_ENCRYPTIONBYTE1(v14)];
864
865         keyOffset += 16;
866         int rounds = 1;
867
868         do
869         {
870
871                 v14 = v18 ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]);
872                 v15 = v19 ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]);
873                 v16 = v20 ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]);
874                 v17 = v21 ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]);
875
876                 v18 = mtpz_aes_ft1[MTPZ_ENCRYPTIONBYTE3(v17)] ^ mtpz_aes_ft2[MTPZ_ENCRYPTIONBYTE2(v16)] ^ mtpz_aes_ft3[MTPZ_ENCRYPTIONLOBYTE(v14)] ^ mtpz_aes_ft4[MTPZ_ENCRYPTIONBYTE1(v15)];
877                 v19 = mtpz_aes_ft1[MTPZ_ENCRYPTIONBYTE3(v14)] ^ mtpz_aes_ft2[MTPZ_ENCRYPTIONBYTE2(v17)] ^ mtpz_aes_ft3[MTPZ_ENCRYPTIONLOBYTE(v15)] ^ mtpz_aes_ft4[MTPZ_ENCRYPTIONBYTE1(v16)];
878                 v20 = mtpz_aes_ft1[MTPZ_ENCRYPTIONBYTE3(v15)] ^ mtpz_aes_ft2[MTPZ_ENCRYPTIONBYTE2(v14)] ^ mtpz_aes_ft3[MTPZ_ENCRYPTIONLOBYTE(v16)] ^ mtpz_aes_ft4[MTPZ_ENCRYPTIONBYTE1(v17)];
879                 v21 = mtpz_aes_ft1[MTPZ_ENCRYPTIONBYTE3(v16)] ^ mtpz_aes_ft2[MTPZ_ENCRYPTIONBYTE2(v15)] ^ mtpz_aes_ft3[MTPZ_ENCRYPTIONLOBYTE(v17)] ^ mtpz_aes_ft4[MTPZ_ENCRYPTIONBYTE1(v14)];
880
881                 rounds++;
882                 keyOffset += 16;
883         }
884         while (rounds != 9);
885
886         v14 = v18 ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]);
887         v15 = v19 ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]);
888         v16 = v20 ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]);
889         v17 = v21 ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]);
890         keyOffset += 16;
891
892         unsigned char *FT3_Bytes = (unsigned char *)mtpz_aes_ft3;
893
894         v18 = ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONLOBYTE(v14)]) << 24) |
895                   ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE1 (v15)]) << 16) |
896                   ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE2 (v16)]) <<  8) |
897                   ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE3 (v17)]) <<  0);
898
899         v19 = ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONLOBYTE(v15)]) << 24) |
900                   ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE1 (v16)]) << 16) |
901                   ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE2 (v17)]) <<  8) |
902                   ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE3 (v14)]) <<  0);
903
904         v20 = ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONLOBYTE(v16)]) << 24) |
905                   ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE1 (v17)]) << 16) |
906                   ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE2 (v14)]) <<  8) |
907                   ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE3 (v15)]) <<  0);
908
909         v21 = ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONLOBYTE(v17)]) << 24) |
910                   ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE1 (v14)]) << 16) |
911                   ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE2 (v15)]) <<  8) |
912                   ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE3 (v16)]) <<  0);
913
914         u_data[0] = MTPZ_SWAP(v18 ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]));
915         u_data[1] = MTPZ_SWAP(v19 ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]));
916         u_data[2] = MTPZ_SWAP(v20 ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]));
917         u_data[3] = MTPZ_SWAP(v21 ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]));
918 }
919
920 void mtpz_encryption_encrypt_mac(unsigned char *hash, unsigned int hash_length, unsigned char *seed, unsigned int seed_len, unsigned char *out)
921 {
922         if (hash == NULL || hash_length != 16)
923                 return;
924
925         unsigned char *loop1 = (unsigned char *)malloc(17);
926         memset(loop1, 0, 17);
927         unsigned char *loop2 = (unsigned char *)malloc(17);
928         memset(loop2, 0, 17);
929         int i = 0;
930
931         {
932                 unsigned char *enc_hash = (unsigned char *)malloc(17);
933                 memset(enc_hash, 0, 17);
934                 mtpz_encryption_cipher_advanced(hash, hash_length, enc_hash, 16, 1);
935
936                 for (i = 0; i < 16; i++)
937                         loop1[i] = (unsigned char)((2 * enc_hash[i]) | (enc_hash[i + 1] >> 7));
938
939                 if (enc_hash[0] >= (unsigned char)128)
940                         loop1[15] ^= (unsigned char)0x87;
941
942                 for (i = 0; i < 16; i++)
943                         loop2[i] = (unsigned char)((2 * loop1[i]) | (loop1[i + 1] >> 7));
944
945                 if (loop1[0] >= (unsigned char)128)
946                         loop2[15] ^= (unsigned char)0x87;
947
948                 free(enc_hash);
949         }
950
951         {
952                 int len =       (hash_length == 16) ? 10 :
953                                         (hash_length == 24) ? 12 : 32;
954                 int exp_len;
955                 unsigned char *expanded = mtpz_encryption_expand_key(hash, hash_length, len, &exp_len);
956
957                 unsigned char *actual_seed = (unsigned char *)malloc(16);
958                 memset(actual_seed, 0, 16);
959
960                 int i = 0;
961
962                 if (seed_len == 16)
963                 {
964                         for (i = 0; i < 16; i++)
965                                 actual_seed[i] ^= seed[i];
966
967                         for (i = 0; i < 16; i++)
968                                 actual_seed[i] ^= loop1[i];
969                 }
970                 else
971                 {
972                         for (i = 0; i < seed_len; i++)
973                                 actual_seed[i] ^= seed[i];
974
975                         actual_seed[seed_len] = (unsigned char)128;
976
977                         for (i = 0; i < 16; i++)
978                                 actual_seed[i] ^= loop2[i];
979                 }
980
981                 mtpz_encryption_encrypt_custom(out, actual_seed, expanded);
982
983                 free(expanded);
984                 free(actual_seed);
985         }
986
987         free(loop1);
988         free(loop2);
989 }
990
991
992 /* ENCRYPTION CONSTANTS */
993 /*
994  * These tables can also be found in Mozilla's Network Security Services:
995  *     http://www.mozilla.org/projects/security/pki/nss/
996  *
997  * <rijndael32.tab>:
998  *     https://hg.mozilla.org/mozilla-central/raw-file/90828ac18dcf/security/nss/lib/freebl/rijndael32.tab
999  *
1000  * Each of the following constant tables will also identify the corresponding
1001  * table in the <rijndael32.tab> link.
1002  */
1003
1004 /* Corresponds to Rcon[30] (seems to be truncated to include only the used constants) */
1005 unsigned char mtpz_aes_rcon[] =
1006 {
1007         0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a
1008 };
1009
1010 /* Corresponds to _S[256] (in hex) */
1011 unsigned char mtpz_aes_sbox[] =
1012 {
1013         0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01,
1014         0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d,
1015         0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4,
1016         0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
1017         0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7,
1018         0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
1019         0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e,
1020         0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
1021         0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb,
1022         0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb,
1023         0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c,
1024         0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
1025         0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c,
1026         0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d,
1027         0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a,
1028         0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
1029         0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3,
1030         0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
1031         0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a,
1032         0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
1033         0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e,
1034         0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9,
1035         0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9,
1036         0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
1037         0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99,
1038         0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
1039 };
1040
1041 /* Corresponds to _SInv[256] (in hex) */
1042 unsigned char mtpz_aes_invsbox[] =
1043 {
1044         0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,  0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
1045         0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,  0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
1046         0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,  0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
1047         0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,  0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
1048         0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,  0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
1049         0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,  0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
1050         0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,  0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
1051         0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,  0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
1052         0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,  0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
1053         0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,  0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
1054         0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,  0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
1055         0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,  0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
1056         0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,  0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
1057         0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,  0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
1058         0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,  0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
1059         0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,  0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
1060 };
1061
1062 /* Corresponds to _T3[256] */
1063 unsigned int mtpz_aes_ft1[] =
1064 {
1065         0x6363A5C6, 0x7C7C84F8,  0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6,  0x6F6FB1DE, 0xC5C55491,
1066         0x30305060, 0x01010302,  0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5,  0xABABE64D, 0x76769AEC,
1067         0xCACA458F, 0x82829D1F,  0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2,  0x4747C98E, 0xF0F00BFB,
1068         0xADADEC41, 0xD4D467B3,  0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753,  0x727296E4, 0xC0C05B9B,
1069         0xB7B7C275, 0xFDFD1CE1,  0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E,  0xF7F702F5, 0xCCCC4F83,
1070         0x34345C68, 0xA5A5F451,  0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB,  0x31315362, 0x15153F2A,
1071         0x04040C08, 0xC7C75295,  0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137,  0x05050F0A, 0x9A9AB52F,
1072         0x0707090E, 0x12123624,  0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E,  0xB2B2CD7F, 0x75759FEA,
1073         0x09091B12, 0x83839E1D,  0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC,  0x5A5AEEB4, 0xA0A0FB5B,
1074         0x5252F6A4, 0x3B3B4D76,  0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD,  0x2F2F715E, 0x84849713,
1075         0x5353F5A6, 0xD1D168B9,  0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3,  0xB1B1C879, 0x5B5BEDB6,
1076         0x6A6ABED4, 0xCBCB468D,  0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498,  0x5858E8B0, 0xCFCF4A85,
1077         0xD0D06BBB, 0xEFEF2AC5,  0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A,  0x33335566, 0x85859411,
1078         0x4545CF8A, 0xF9F910E9,  0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478,  0x9F9FBA25, 0xA8A8E34B,
1079         0x5151F3A2, 0xA3A3FE5D,  0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21,  0x38384870, 0xF5F504F1,
1080         0xBCBCDF63, 0xB6B6C177,  0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5,  0xF3F30EFD, 0xD2D26DBF,
1081         0xCDCD4C81, 0x0C0C1418,  0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235,  0x4444CC88, 0x1717392E,
1082         0xC4C45793, 0xA7A7F255,  0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA,  0x19192B32, 0x737395E6,
1083         0x6060A0C0, 0x81819819,  0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54,  0x9090AB3B, 0x8888830B,
1084         0x4646CA8C, 0xEEEE29C7,  0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC,  0x0B0B1D16, 0xDBDB76AD,
1085         0xE0E03BDB, 0x32325664,  0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C,  0x24246C48, 0x5C5CE4B8,
1086         0xC2C25D9F, 0xD3D36EBD,  0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431,  0xE4E437D3, 0x79798BF2,
1087         0xE7E732D5, 0xC8C8438B,  0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1,  0x4E4ED29C, 0xA9A9E049,
1088         0x6C6CB4D8, 0x5656FAAC,  0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4,  0xAEAEE947, 0x08081810,
1089         0xBABAD56F, 0x787888F0,  0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157,  0xB4B4C773, 0xC6C65197,
1090         0xE8E823CB, 0xDDDD7CA1,  0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61,  0x8B8B860D, 0x8A8A850F,
1091         0x707090E0, 0x3E3E427C,  0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506,  0xF6F601F7, 0x0E0E121C,
1092         0x6161A3C2, 0x35355F6A,  0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899,  0x1D1D273A, 0x9E9EB927,
1093         0xE1E138D9, 0xF8F813EB,  0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9,  0x8E8E8907, 0x9494A733,
1094         0x9B9BB62D, 0x1E1E223C,  0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA,  0x28287850, 0xDFDF7AA5,
1095         0x8C8C8F03, 0xA1A1F859,  0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7,  0x4242C684, 0x6868B8D0,
1096         0x4141C382, 0x9999B029,  0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8,  0xBBBBD66D, 0x16163A2C,
1097 };
1098
1099 /* Corresponds to _T2[256] */
1100 unsigned int mtpz_aes_ft2[] =
1101 {
1102         0x63A5C663, 0x7C84F87C,  0x7799EE77, 0x7B8DF67B, 0xF20DFFF2, 0x6BBDD66B,  0x6FB1DE6F, 0xC55491C5,
1103         0x30506030, 0x01030201,  0x67A9CE67, 0x2B7D562B, 0xFE19E7FE, 0xD762B5D7,  0xABE64DAB, 0x769AEC76,
1104         0xCA458FCA, 0x829D1F82,  0xC94089C9, 0x7D87FA7D, 0xFA15EFFA, 0x59EBB259,  0x47C98E47, 0xF00BFBF0,
1105         0xADEC41AD, 0xD467B3D4,  0xA2FD5FA2, 0xAFEA45AF, 0x9CBF239C, 0xA4F753A4,  0x7296E472, 0xC05B9BC0,
1106         0xB7C275B7, 0xFD1CE1FD,  0x93AE3D93, 0x266A4C26, 0x365A6C36, 0x3F417E3F,  0xF702F5F7, 0xCC4F83CC,
1107         0x345C6834, 0xA5F451A5,  0xE534D1E5, 0xF108F9F1, 0x7193E271, 0xD873ABD8,  0x31536231, 0x153F2A15,
1108         0x040C0804, 0xC75295C7,  0x23654623, 0xC35E9DC3, 0x18283018, 0x96A13796,  0x050F0A05, 0x9AB52F9A,
1109         0x07090E07, 0x12362412,  0x809B1B80, 0xE23DDFE2, 0xEB26CDEB, 0x27694E27,  0xB2CD7FB2, 0x759FEA75,
1110         0x091B1209, 0x839E1D83,  0x2C74582C, 0x1A2E341A, 0x1B2D361B, 0x6EB2DC6E,  0x5AEEB45A, 0xA0FB5BA0,
1111         0x52F6A452, 0x3B4D763B,  0xD661B7D6, 0xB3CE7DB3, 0x297B5229, 0xE33EDDE3,  0x2F715E2F, 0x84971384,
1112         0x53F5A653, 0xD168B9D1,  0x00000000, 0xED2CC1ED, 0x20604020, 0xFC1FE3FC,  0xB1C879B1, 0x5BEDB65B,
1113         0x6ABED46A, 0xCB468DCB,  0xBED967BE, 0x394B7239, 0x4ADE944A, 0x4CD4984C,  0x58E8B058, 0xCF4A85CF,
1114         0xD06BBBD0, 0xEF2AC5EF,  0xAAE54FAA, 0xFB16EDFB, 0x43C58643, 0x4DD79A4D,  0x33556633, 0x85941185,
1115         0x45CF8A45, 0xF910E9F9,  0x02060402, 0x7F81FE7F, 0x50F0A050, 0x3C44783C,  0x9FBA259F, 0xA8E34BA8,
1116         0x51F3A251, 0xA3FE5DA3,  0x40C08040, 0x8F8A058F, 0x92AD3F92, 0x9DBC219D,  0x38487038, 0xF504F1F5,
1117         0xBCDF63BC, 0xB6C177B6,  0xDA75AFDA, 0x21634221, 0x10302010, 0xFF1AE5FF,  0xF30EFDF3, 0xD26DBFD2,
1118         0xCD4C81CD, 0x0C14180C,  0x13352613, 0xEC2FC3EC, 0x5FE1BE5F, 0x97A23597,  0x44CC8844, 0x17392E17,
1119         0xC45793C4, 0xA7F255A7,  0x7E82FC7E, 0x3D477A3D, 0x64ACC864, 0x5DE7BA5D,  0x192B3219, 0x7395E673,
1120         0x60A0C060, 0x81981981,  0x4FD19E4F, 0xDC7FA3DC, 0x22664422, 0x2A7E542A,  0x90AB3B90, 0x88830B88,
1121         0x46CA8C46, 0xEE29C7EE,  0xB8D36BB8, 0x143C2814, 0xDE79A7DE, 0x5EE2BC5E,  0x0B1D160B, 0xDB76ADDB,
1122         0xE03BDBE0, 0x32566432,  0x3A4E743A, 0x0A1E140A, 0x49DB9249, 0x060A0C06,  0x246C4824, 0x5CE4B85C,
1123         0xC25D9FC2, 0xD36EBDD3,  0xACEF43AC, 0x62A6C462, 0x91A83991, 0x95A43195,  0xE437D3E4, 0x798BF279,
1124         0xE732D5E7, 0xC8438BC8,  0x37596E37, 0x6DB7DA6D, 0x8D8C018D, 0xD564B1D5,  0x4ED29C4E, 0xA9E049A9,
1125         0x6CB4D86C, 0x56FAAC56,  0xF407F3F4, 0xEA25CFEA, 0x65AFCA65, 0x7A8EF47A,  0xAEE947AE, 0x08181008,
1126         0xBAD56FBA, 0x7888F078,  0x256F4A25, 0x2E725C2E, 0x1C24381C, 0xA6F157A6,  0xB4C773B4, 0xC65197C6,
1127         0xE823CBE8, 0xDD7CA1DD,  0x749CE874, 0x1F213E1F, 0x4BDD964B, 0xBDDC61BD,  0x8B860D8B, 0x8A850F8A,
1128         0x7090E070, 0x3E427C3E,  0xB5C471B5, 0x66AACC66, 0x48D89048, 0x03050603,  0xF601F7F6, 0x0E121C0E,
1129         0x61A3C261, 0x355F6A35,  0x57F9AE57, 0xB9D069B9, 0x86911786, 0xC15899C1,  0x1D273A1D, 0x9EB9279E,
1130         0xE138D9E1, 0xF813EBF8,  0x98B32B98, 0x11332211, 0x69BBD269, 0xD970A9D9,  0x8E89078E, 0x94A73394,
1131         0x9BB62D9B, 0x1E223C1E,  0x87921587, 0xE920C9E9, 0xCE4987CE, 0x55FFAA55,  0x28785028, 0xDF7AA5DF,
1132         0x8C8F038C, 0xA1F859A1,  0x89800989, 0x0D171A0D, 0xBFDA65BF, 0xE631D7E6,  0x42C68442, 0x68B8D068,
1133         0x41C38241, 0x99B02999,  0x2D775A2D, 0x0F111E0F, 0xB0CB7BB0, 0x54FCA854,  0xBBD66DBB, 0x163A2C16,
1134 };
1135
1136 /* Corresponds to _T0[256] */
1137 unsigned int mtpz_aes_ft3[] =
1138 {
1139         0xC66363A5, 0xF87C7C84,  0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD,  0xDE6F6FB1, 0x91C5C554,
1140         0x60303050, 0x02010103,  0xCE6767A9, 0x562B2B7D, 0xE7FEFE19, 0xB5D7D762,  0x4DABABE6, 0xEC76769A,
1141         0x8FCACA45, 0x1F82829D,  0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB,  0x8E4747C9, 0xFBF0F00B,
1142         0x41ADADEC, 0xB3D4D467,  0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7,  0xE4727296, 0x9BC0C05B,
1143         0x75B7B7C2, 0xE1FDFD1C,  0x3D9393AE, 0x4C26266A, 0x6C36365A, 0x7E3F3F41,  0xF5F7F702, 0x83CCCC4F,
1144         0x6834345C, 0x51A5A5F4,  0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873,  0x62313153, 0x2A15153F,
1145         0x0804040C, 0x95C7C752,  0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1,  0x0A05050F, 0x2F9A9AB5,
1146         0x0E070709, 0x24121236,  0x1B80809B, 0xDFE2E23D, 0xCDEBEB26, 0x4E272769,  0x7FB2B2CD, 0xEA75759F,
1147         0x1209091B, 0x1D83839E,  0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2,  0xB45A5AEE, 0x5BA0A0FB,
1148         0xA45252F6, 0x763B3B4D,  0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E,  0x5E2F2F71, 0x13848497,
1149         0xA65353F5, 0xB9D1D168,  0x00000000, 0xC1EDED2C, 0x40202060, 0xE3FCFC1F,  0x79B1B1C8, 0xB65B5BED,
1150         0xD46A6ABE, 0x8DCBCB46,  0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4,  0xB05858E8, 0x85CFCF4A,
1151         0xBBD0D06B, 0xC5EFEF2A,  0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7,  0x66333355, 0x11858594,
1152         0x8A4545CF, 0xE9F9F910,  0x04020206, 0xFE7F7F81, 0xA05050F0, 0x783C3C44,  0x259F9FBA, 0x4BA8A8E3,
1153         0xA25151F3, 0x5DA3A3FE,  0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC,  0x70383848, 0xF1F5F504,
1154         0x63BCBCDF, 0x77B6B6C1,  0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A,  0xFDF3F30E, 0xBFD2D26D,
1155         0x81CDCD4C, 0x180C0C14,  0x26131335, 0xC3ECEC2F, 0xBE5F5FE1, 0x359797A2,  0x884444CC, 0x2E171739,
1156         0x93C4C457, 0x55A7A7F2,  0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7,  0x3219192B, 0xE6737395,
1157         0xC06060A0, 0x19818198,  0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E,  0x3B9090AB, 0x0B888883,
1158         0x8C4646CA, 0xC7EEEE29,  0x6BB8B8D3, 0x2814143C, 0xA7DEDE79, 0xBC5E5EE2,  0x160B0B1D, 0xADDBDB76,
1159         0xDBE0E03B, 0x64323256,  0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A,  0x4824246C, 0xB85C5CE4,
1160         0x9FC2C25D, 0xBDD3D36E,  0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4,  0xD3E4E437, 0xF279798B,
1161         0xD5E7E732, 0x8BC8C843,  0x6E373759, 0xDA6D6DB7, 0x018D8D8C, 0xB1D5D564,  0x9C4E4ED2, 0x49A9A9E0,
1162         0xD86C6CB4, 0xAC5656FA,  0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E,  0x47AEAEE9, 0x10080818,
1163         0x6FBABAD5, 0xF0787888,  0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1,  0x73B4B4C7, 0x97C6C651,
1164         0xCBE8E823, 0xA1DDDD7C,  0xE874749C, 0x3E1F1F21, 0x964B4BDD, 0x61BDBDDC,  0x0D8B8B86, 0x0F8A8A85,
1165         0xE0707090, 0x7C3E3E42,  0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305,  0xF7F6F601, 0x1C0E0E12,
1166         0xC26161A3, 0x6A35355F,  0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158,  0x3A1D1D27, 0x279E9EB9,
1167         0xD9E1E138, 0xEBF8F813,  0x2B9898B3, 0x22111133, 0xD26969BB, 0xA9D9D970,  0x078E8E89, 0x339494A7,
1168         0x2D9B9BB6, 0x3C1E1E22,  0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF,  0x50282878, 0xA5DFDF7A,
1169         0x038C8C8F, 0x59A1A1F8,  0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631,  0x844242C6, 0xD06868B8,
1170         0x824141C3, 0x299999B0,  0x5A2D2D77, 0x1E0F0F11, 0x7BB0B0CB, 0xA85454FC,  0x6DBBBBD6, 0x2C16163A,
1171 };
1172
1173 /* Corresponds to _T1[256] */
1174 unsigned int mtpz_aes_ft4[] =
1175 {
1176         0xA5C66363, 0x84F87C7C,  0x99EE7777, 0x8DF67B7B, 0x0DFFF2F2, 0xBDD66B6B,  0xB1DE6F6F, 0x5491C5C5,
1177         0x50603030, 0x03020101,  0xA9CE6767, 0x7D562B2B, 0x19E7FEFE, 0x62B5D7D7,  0xE64DABAB, 0x9AEC7676,
1178         0x458FCACA, 0x9D1F8282,  0x4089C9C9, 0x87FA7D7D, 0x15EFFAFA, 0xEBB25959,  0xC98E4747, 0x0BFBF0F0,
1179         0xEC41ADAD, 0x67B3D4D4,  0xFD5FA2A2, 0xEA45AFAF, 0xBF239C9C, 0xF753A4A4,  0x96E47272, 0x5B9BC0C0,
1180         0xC275B7B7, 0x1CE1FDFD,  0xAE3D9393, 0x6A4C2626, 0x5A6C3636, 0x417E3F3F,  0x02F5F7F7, 0x4F83CCCC,
1181         0x5C683434, 0xF451A5A5,  0x34D1E5E5, 0x08F9F1F1, 0x93E27171, 0x73ABD8D8,  0x53623131, 0x3F2A1515,
1182         0x0C080404, 0x5295C7C7,  0x65462323, 0x5E9DC3C3, 0x28301818, 0xA1379696,  0x0F0A0505, 0xB52F9A9A,
1183         0x090E0707, 0x36241212,  0x9B1B8080, 0x3DDFE2E2, 0x26CDEBEB, 0x694E2727,  0xCD7FB2B2, 0x9FEA7575,
1184         0x1B120909, 0x9E1D8383,  0x74582C2C, 0x2E341A1A, 0x2D361B1B, 0xB2DC6E6E,  0xEEB45A5A, 0xFB5BA0A0,
1185         0xF6A45252, 0x4D763B3B,  0x61B7D6D6, 0xCE7DB3B3, 0x7B522929, 0x3EDDE3E3,  0x715E2F2F, 0x97138484,
1186         0xF5A65353, 0x68B9D1D1,  0x00000000, 0x2CC1EDED, 0x60402020, 0x1FE3FCFC,  0xC879B1B1, 0xEDB65B5B,
1187         0xBED46A6A, 0x468DCBCB,  0xD967BEBE, 0x4B723939, 0xDE944A4A, 0xD4984C4C,  0xE8B05858, 0x4A85CFCF,
1188         0x6BBBD0D0, 0x2AC5EFEF,  0xE54FAAAA, 0x16EDFBFB, 0xC5864343, 0xD79A4D4D,  0x55663333, 0x94118585,
1189         0xCF8A4545, 0x10E9F9F9,  0x06040202, 0x81FE7F7F, 0xF0A05050, 0x44783C3C,  0xBA259F9F, 0xE34BA8A8,
1190         0xF3A25151, 0xFE5DA3A3,  0xC0804040, 0x8A058F8F, 0xAD3F9292, 0xBC219D9D,  0x48703838, 0x04F1F5F5,
1191         0xDF63BCBC, 0xC177B6B6,  0x75AFDADA, 0x63422121, 0x30201010, 0x1AE5FFFF,  0x0EFDF3F3, 0x6DBFD2D2,
1192         0x4C81CDCD, 0x14180C0C,  0x35261313, 0x2FC3ECEC, 0xE1BE5F5F, 0xA2359797,  0xCC884444, 0x392E1717,
1193         0x5793C4C4, 0xF255A7A7,  0x82FC7E7E, 0x477A3D3D, 0xACC86464, 0xE7BA5D5D,  0x2B321919, 0x95E67373,
1194         0xA0C06060, 0x98198181,  0xD19E4F4F, 0x7FA3DCDC, 0x66442222, 0x7E542A2A,  0xAB3B9090, 0x830B8888,
1195         0xCA8C4646, 0x29C7EEEE,  0xD36BB8B8, 0x3C281414, 0x79A7DEDE, 0xE2BC5E5E,  0x1D160B0B, 0x76ADDBDB,
1196         0x3BDBE0E0, 0x56643232,  0x4E743A3A, 0x1E140A0A, 0xDB924949, 0x0A0C0606,  0x6C482424, 0xE4B85C5C,
1197         0x5D9FC2C2, 0x6EBDD3D3,  0xEF43ACAC, 0xA6C46262, 0xA8399191, 0xA4319595,  0x37D3E4E4, 0x8BF27979,
1198         0x32D5E7E7, 0x438BC8C8,  0x596E3737, 0xB7DA6D6D, 0x8C018D8D, 0x64B1D5D5,  0xD29C4E4E, 0xE049A9A9,
1199         0xB4D86C6C, 0xFAAC5656,  0x07F3F4F4, 0x25CFEAEA, 0xAFCA6565, 0x8EF47A7A,  0xE947AEAE, 0x18100808,
1200         0xD56FBABA, 0x88F07878,  0x6F4A2525, 0x725C2E2E, 0x24381C1C, 0xF157A6A6,  0xC773B4B4, 0x5197C6C6,
1201         0x23CBE8E8, 0x7CA1DDDD,  0x9CE87474, 0x213E1F1F, 0xDD964B4B, 0xDC61BDBD,  0x860D8B8B, 0x850F8A8A,
1202         0x90E07070, 0x427C3E3E,  0xC471B5B5, 0xAACC6666, 0xD8904848, 0x05060303,  0x01F7F6F6, 0x121C0E0E,
1203         0xA3C26161, 0x5F6A3535,  0xF9AE5757, 0xD069B9B9, 0x91178686, 0x5899C1C1,  0x273A1D1D, 0xB9279E9E,
1204         0x38D9E1E1, 0x13EBF8F8,  0xB32B9898, 0x33221111, 0xBBD26969, 0x70A9D9D9,  0x89078E8E, 0xA7339494,
1205         0xB62D9B9B, 0x223C1E1E,  0x92158787, 0x20C9E9E9, 0x4987CECE, 0xFFAA5555,  0x78502828, 0x7AA5DFDF,
1206         0x8F038C8C, 0xF859A1A1,  0x80098989, 0x171A0D0D, 0xDA65BFBF, 0x31D7E6E6,  0xC6844242, 0xB8D06868,
1207         0xC3824141, 0xB0299999,  0x775A2D2D, 0x111E0F0F, 0xCB7BB0B0, 0xFCA85454,  0xD66DBBBB, 0x3A2C1616,
1208 };
1209
1210 /* Corresponds to _TInv3[256] */
1211 unsigned int mtpz_aes_rt1[] =
1212 {
1213         0xF4A75051, 0x4165537E,  0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F,  0xFA58ABAC, 0xE303934B,
1214         0x30FA5520, 0x766DF6AD,  0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5,  0x35448026, 0x62A38FB5,
1215         0xB15A49DE, 0xBA1B6725,  0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281,  0x4697A38D, 0xD3F9C66B,
1216         0x8F5FE703, 0x929C9515,  0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358,  0xE0692949, 0xC9C8448E,
1217         0xC2896A75, 0x8E7978F4,  0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0,  0x20AC66C9, 0xCE3AB47D,
1218         0xDF4A1863, 0x1A3182E5,  0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB,  0x81A01CFE, 0x082B94F9,
1219         0x48685870, 0x45FD198F,  0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272,  0x1F8F57E3, 0x55AB2A66,
1220         0xEB2807B2, 0xB5C2032F,  0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223,  0x036ABA02, 0x16825CED,
1221         0xCF1C2B8A, 0x79B492A7,  0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506,  0x34621FD1, 0xA6FE8AC4,
1222         0x2E539D34, 0xF355A0A2,  0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40,  0x719F065E, 0x6E1051BD,
1223         0x218AF93E, 0xDD063D96,  0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571,  0x06D46F04, 0x5015FF60,
1224         0x98FB2419, 0xBDE997D6,  0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807,  0x195B38E7, 0xC8EEDB79,
1225         0x7C0A47A1, 0x420FE97C,  0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832,  0x1170AC1E, 0x5A724E6C,
1226         0x0EFFFBFD, 0x8538560F,  0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168,  0x5B54D19B, 0x362E3A24,
1227         0x0A67B10C, 0x57E70F93,  0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261,  0x774B695A, 0x121A161C,
1228         0x93BA0AE2, 0xA02AE5C0,  0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2,  0xB6A8B92D, 0x1EA9C814,
1229         0xF1198557, 0x75074CAF,  0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C,  0x663BC544, 0xFB7E345B,
1230         0x4329768B, 0x23C6DCCB,  0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042,  0x97224013, 0xC6112084,
1231         0x4A247D85, 0xBB3DF8D2,  0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC,  0x8652EC0D, 0xC1E3D077,
1232         0xB3166C2B, 0x70B999A9,  0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0,  0x7D2CD856, 0x3390EF22,
1233         0x494EC787, 0x38D1C1D9,  0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5,  0xB78E26DA, 0xADBFA43F,
1234         0x3A9DE42C, 0x78920D50,  0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890,  0x39F75E2E, 0xC3AFF582,
1235         0x5D80BE9F, 0xD0937C69,  0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710,  0x9C636EE8, 0x3BBB7BDB,
1236         0x267809CD, 0x5918F46E,  0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA,  0xBCCF0821, 0x15E8E6EF,
1237         0xE79BD9BA, 0x6F36CE4A,  0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A,  0xA59430C6, 0xA266C035,
1238         0x4EBC3774, 0x82CAA6FC,  0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741,  0xCD500E7F, 0x91F62F17,
1239         0x4DD68D76, 0xEFB04D43,  0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C,  0x2C1FB8C1, 0x65517F46,
1240         0x5EEA049D, 0x8C355D01,  0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292,  0x105633E9, 0xD647136D,
1241         0xD7618C9A, 0xA10C7A37,  0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7,  0x1CE5EDE1, 0x47B13C7A,
1242         0xD2DF599C, 0xF2733F55,  0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F,  0x3D6F14DF, 0x44DB8678,
1243         0xAFF381CA, 0x68C43EB9,  0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC,  0x3C498B28, 0x0D9541FF,
1244         0xA8017139, 0x0CB3DE08,  0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5,  0x6C5C7448, 0xB85742D0
1245 };
1246
1247 /* Corresponds to _TInv2[256] */
1248 unsigned int mtpz_aes_rt2[] =
1249 {
1250         0xA75051F4, 0x65537E41,  0xA4C31A17, 0x5E963A27, 0x6BCB3BAB, 0x45F11F9D,  0x58ABACFA, 0x03934BE3,
1251         0xFA552030, 0x6DF6AD76,  0x769188CC, 0x4C25F502, 0xD7FC4FE5, 0xCBD7C52A,  0x44802635, 0xA38FB562,
1252         0x5A49DEB1, 0x1B6725BA,  0x0E9845EA, 0xC0E15DFE, 0x7502C32F, 0xF012814C,  0x97A38D46, 0xF9C66BD3,
1253         0x5FE7038F, 0x9C951592,  0x7AEBBF6D, 0x59DA9552, 0x832DD4BE, 0x21D35874,  0x692949E0, 0xC8448EC9,
1254         0x896A75C2, 0x7978F48E,  0x3E6B9958, 0x71DD27B9, 0x4FB6BEE1, 0xAD17F088,  0xAC66C920, 0x3AB47DCE,
1255         0x4A1863DF, 0x3182E51A,  0x33609751, 0x7F456253, 0x77E0B164, 0xAE84BB6B,  0xA01CFE81, 0x2B94F908,
1256         0x68587048, 0xFD198F45,  0x6C8794DE, 0xF8B7527B, 0xD323AB73, 0x02E2724B,  0x8F57E31F, 0xAB2A6655,
1257         0x2807B2EB, 0xC2032FB5,  0x7B9A86C5, 0x08A5D337, 0x87F23028, 0xA5B223BF,  0x6ABA0203, 0x825CED16,
1258         0x1C2B8ACF, 0xB492A779,  0xF2F0F307, 0xE2A14E69, 0xF4CD65DA, 0xBED50605,  0x621FD134, 0xFE8AC4A6,
1259         0x539D342E, 0x55A0A2F3,  0xE132058A, 0xEB75A4F6, 0xEC390B83, 0xEFAA4060,  0x9F065E71, 0x1051BD6E,
1260         0x8AF93E21, 0x063D96DD,  0x05AEDD3E, 0xBD464DE6, 0x8DB59154, 0x5D0571C4,  0xD46F0406, 0x15FF6050,
1261         0xFB241998, 0xE997D6BD,  0x43CC8940, 0x9E7767D9, 0x42BDB0E8, 0x8B880789,  0x5B38E719, 0xEEDB79C8,
1262         0x0A47A17C, 0x0FE97C42,  0x1EC9F884, 0x00000000, 0x86830980, 0xED48322B,  0x70AC1E11, 0x724E6C5A,
1263         0xFFFBFD0E, 0x38560F85,  0xD51E3DAE, 0x3927362D, 0xD9640A0F, 0xA621685C,  0x54D19B5B, 0x2E3A2436,
1264         0x67B10C0A, 0xE70F9357,  0x96D2B4EE, 0x919E1B9B, 0xC54F80C0, 0x20A261DC,  0x4B695A77, 0x1A161C12,
1265         0xBA0AE293, 0x2AE5C0A0,  0xE0433C22, 0x171D121B, 0x0D0B0E09, 0xC7ADF28B,  0xA8B92DB6, 0xA9C8141E,
1266         0x198557F1, 0x074CAF75,  0xDDBBEE99, 0x60FDA37F, 0x269FF701, 0xF5BC5C72,  0x3BC54466, 0x7E345BFB,
1267         0x29768B43, 0xC6DCCB23,  0xFC68B6ED, 0xF163B8E4, 0xDCCAD731, 0x85104263,  0x22401397, 0x112084C6,
1268         0x247D854A, 0x3DF8D2BB,  0x3211AEF9, 0xA16DC729, 0x2F4B1D9E, 0x30F3DCB2,  0x52EC0D86, 0xE3D077C1,
1269         0x166C2BB3, 0xB999A970,  0x48FA1194, 0x642247E9, 0x8CC4A8FC, 0x3F1AA0F0,  0x2CD8567D, 0x90EF2233,
1270         0x4EC78749, 0xD1C1D938,  0xA2FE8CCA, 0x0B3698D4, 0x81CFA6F5, 0xDE28A57A,  0x8E26DAB7, 0xBFA43FAD,
1271         0x9DE42C3A, 0x920D5078,  0xCC9B6A5F, 0x4662547E, 0x13C2F68D, 0xB8E890D8,  0xF75E2E39, 0xAFF582C3,
1272         0x80BE9F5D, 0x937C69D0,  0x2DA96FD5, 0x12B3CF25, 0x993BC8AC, 0x7DA71018,  0x636EE89C, 0xBB7BDB3B,
1273         0x7809CD26, 0x18F46E59,  0xB701EC9A, 0x9AA8834F, 0x6E65E695, 0xE67EAAFF,  0xCF0821BC, 0xE8E6EF15,
1274         0x9BD9BAE7, 0x36CE4A6F,  0x09D4EA9F, 0x7CD629B0, 0xB2AF31A4, 0x23312A3F,  0x9430C6A5, 0x66C035A2,
1275         0xBC37744E, 0xCAA6FC82,  0xD0B0E090, 0xD81533A7, 0x984AF104, 0xDAF741EC,  0x500E7FCD, 0xF62F1791,
1276         0xD68D764D, 0xB04D43EF,  0x4D54CCAA, 0x04DFE496, 0xB5E39ED1, 0x881B4C6A,  0x1FB8C12C, 0x517F4665,
1277         0xEA049D5E, 0x355D018C,  0x7473FA87, 0x412EFB0B, 0x1D5AB367, 0xD25292DB,  0x5633E910, 0x47136DD6,
1278         0x618C9AD7, 0x0C7A37A1,  0x148E59F8, 0x3C89EB13, 0x27EECEA9, 0xC935B761,  0xE5EDE11C, 0xB13C7A47,
1279         0xDF599CD2, 0x733F55F2,  0xCE791814, 0x37BF73C7, 0xCDEA53F7, 0xAA5B5FFD,  0x6F14DF3D, 0xDB867844,
1280         0xF381CAAF, 0xC43EB968,  0x342C3824, 0x405FC2A3, 0xC372161D, 0x250CBCE2,  0x498B283C, 0x9541FF0D,
1281         0x017139A8, 0xB3DE080C,  0xE49CD8B4, 0xC1906456, 0x84617BCB, 0xB670D532,  0x5C74486C, 0x5742D0B8
1282 };
1283
1284 /* Corresponds to _TInv0[256] */
1285 unsigned int mtpz_aes_rt3[] =
1286 {
1287         0x51F4A750, 0x7E416553,  0x1A17A4C3, 0x3A275E96, 0x3BAB6BCB, 0x1F9D45F1,  0xACFA58AB, 0x4BE30393,
1288         0x2030FA55, 0xAD766DF6,  0x88CC7691, 0xF5024C25, 0x4FE5D7FC, 0xC52ACBD7,  0x26354480, 0xB562A38F,
1289         0xDEB15A49, 0x25BA1B67,  0x45EA0E98, 0x5DFEC0E1, 0xC32F7502, 0x814CF012,  0x8D4697A3, 0x6BD3F9C6,
1290         0x038F5FE7, 0x15929C95,  0xBF6D7AEB, 0x955259DA, 0xD4BE832D, 0x587421D3,  0x49E06929, 0x8EC9C844,
1291         0x75C2896A, 0xF48E7978,  0x99583E6B, 0x27B971DD, 0xBEE14FB6, 0xF088AD17,  0xC920AC66, 0x7DCE3AB4,
1292         0x63DF4A18, 0xE51A3182,  0x97513360, 0x62537F45, 0xB16477E0, 0xBB6BAE84,  0xFE81A01C, 0xF9082B94,
1293         0x70486858, 0x8F45FD19,  0x94DE6C87, 0x527BF8B7, 0xAB73D323, 0x724B02E2,  0xE31F8F57, 0x6655AB2A,
1294         0xB2EB2807, 0x2FB5C203,  0x86C57B9A, 0xD33708A5, 0x302887F2, 0x23BFA5B2,  0x02036ABA, 0xED16825C,
1295         0x8ACF1C2B, 0xA779B492,  0xF307F2F0, 0x4E69E2A1, 0x65DAF4CD, 0x0605BED5,  0xD134621F, 0xC4A6FE8A,
1296         0x342E539D, 0xA2F355A0,  0x058AE132, 0xA4F6EB75, 0x0B83EC39, 0x4060EFAA,  0x5E719F06, 0xBD6E1051,
1297         0x3E218AF9, 0x96DD063D,  0xDD3E05AE, 0x4DE6BD46, 0x91548DB5, 0x71C45D05,  0x0406D46F, 0x605015FF,
1298         0x1998FB24, 0xD6BDE997,  0x894043CC, 0x67D99E77, 0xB0E842BD, 0x07898B88,  0xE7195B38, 0x79C8EEDB,
1299         0xA17C0A47, 0x7C420FE9,  0xF8841EC9, 0x00000000, 0x09808683, 0x322BED48,  0x1E1170AC, 0x6C5A724E,
1300         0xFD0EFFFB, 0x0F853856,  0x3DAED51E, 0x362D3927, 0x0A0FD964, 0x685CA621,  0x9B5B54D1, 0x24362E3A,
1301         0x0C0A67B1, 0x9357E70F,  0xB4EE96D2, 0x1B9B919E, 0x80C0C54F, 0x61DC20A2,  0x5A774B69, 0x1C121A16,
1302         0xE293BA0A, 0xC0A02AE5,  0x3C22E043, 0x121B171D, 0x0E090D0B, 0xF28BC7AD,  0x2DB6A8B9, 0x141EA9C8,
1303         0x57F11985, 0xAF75074C,  0xEE99DDBB, 0xA37F60FD, 0xF701269F, 0x5C72F5BC,  0x44663BC5, 0x5BFB7E34,
1304         0x8B432976, 0xCB23C6DC,  0xB6EDFC68, 0xB8E4F163, 0xD731DCCA, 0x42638510,  0x13972240, 0x84C61120,
1305         0x854A247D, 0xD2BB3DF8,  0xAEF93211, 0xC729A16D, 0x1D9E2F4B, 0xDCB230F3,  0x0D8652EC, 0x77C1E3D0,
1306         0x2BB3166C, 0xA970B999,  0x119448FA, 0x47E96422, 0xA8FC8CC4, 0xA0F03F1A,  0x567D2CD8, 0x223390EF,
1307         0x87494EC7, 0xD938D1C1,  0x8CCAA2FE, 0x98D40B36, 0xA6F581CF, 0xA57ADE28,  0xDAB78E26, 0x3FADBFA4,
1308         0x2C3A9DE4, 0x5078920D,  0x6A5FCC9B, 0x547E4662, 0xF68D13C2, 0x90D8B8E8,  0x2E39F75E, 0x82C3AFF5,
1309         0x9F5D80BE, 0x69D0937C,  0x6FD52DA9, 0xCF2512B3, 0xC8AC993B, 0x10187DA7,  0xE89C636E, 0xDB3BBB7B,
1310         0xCD267809, 0x6E5918F4,  0xEC9AB701, 0x834F9AA8, 0xE6956E65, 0xAAFFE67E,  0x21BCCF08, 0xEF15E8E6,
1311         0xBAE79BD9, 0x4A6F36CE,  0xEA9F09D4, 0x29B07CD6, 0x31A4B2AF, 0x2A3F2331,  0xC6A59430, 0x35A266C0,
1312         0x744EBC37, 0xFC82CAA6,  0xE090D0B0, 0x33A7D815, 0xF104984A, 0x41ECDAF7,  0x7FCD500E, 0x1791F62F,
1313         0x764DD68D, 0x43EFB04D,  0xCCAA4D54, 0xE49604DF, 0x9ED1B5E3, 0x4C6A881B,  0xC12C1FB8, 0x4665517F,
1314         0x9D5EEA04, 0x018C355D,  0xFA877473, 0xFB0B412E, 0xB3671D5A, 0x92DBD252,  0xE9105633, 0x6DD64713,
1315         0x9AD7618C, 0x37A10C7A,  0x59F8148E, 0xEB133C89, 0xCEA927EE, 0xB761C935,  0xE11CE5ED, 0x7A47B13C,
1316         0x9CD2DF59, 0x55F2733F,  0x1814CE79, 0x73C737BF, 0x53F7CDEA, 0x5FFDAA5B,  0xDF3D6F14, 0x7844DB86,
1317         0xCAAFF381, 0xB968C43E,  0x3824342C, 0xC2A3405F, 0x161DC372, 0xBCE2250C,  0x283C498B, 0xFF0D9541,
1318         0x39A80171, 0x080CB3DE,  0xD8B4E49C, 0x6456C190, 0x7BCB8461, 0xD532B670,  0x486C5C74, 0xD0B85742
1319 };
1320
1321 /* Corresponds to _TInv1[256] */
1322 unsigned int mtpz_aes_rt4[] =
1323 {
1324         0x5051F4A7, 0x537E4165,  0xC31A17A4, 0x963A275E, 0xCB3BAB6B, 0xF11F9D45,  0xABACFA58, 0x934BE303,
1325         0x552030FA, 0xF6AD766D,  0x9188CC76, 0x25F5024C, 0xFC4FE5D7, 0xD7C52ACB,  0x80263544, 0x8FB562A3,
1326         0x49DEB15A, 0x6725BA1B,  0x9845EA0E, 0xE15DFEC0, 0x02C32F75, 0x12814CF0,  0xA38D4697, 0xC66BD3F9,
1327         0xE7038F5F, 0x9515929C,  0xEBBF6D7A, 0xDA955259, 0x2DD4BE83, 0xD3587421,  0x2949E069, 0x448EC9C8,
1328         0x6A75C289, 0x78F48E79,  0x6B99583E, 0xDD27B971, 0xB6BEE14F, 0x17F088AD,  0x66C920AC, 0xB47DCE3A,
1329         0x1863DF4A, 0x82E51A31,  0x60975133, 0x4562537F, 0xE0B16477, 0x84BB6BAE,  0x1CFE81A0, 0x94F9082B,
1330         0x58704868, 0x198F45FD,  0x8794DE6C, 0xB7527BF8, 0x23AB73D3, 0xE2724B02,  0x57E31F8F, 0x2A6655AB,
1331         0x07B2EB28, 0x032FB5C2,  0x9A86C57B, 0xA5D33708, 0xF2302887, 0xB223BFA5,  0xBA02036A, 0x5CED1682,
1332         0x2B8ACF1C, 0x92A779B4,  0xF0F307F2, 0xA14E69E2, 0xCD65DAF4, 0xD50605BE,  0x1FD13462, 0x8AC4A6FE,
1333         0x9D342E53, 0xA0A2F355,  0x32058AE1, 0x75A4F6EB, 0x390B83EC, 0xAA4060EF,  0x065E719F, 0x51BD6E10,
1334         0xF93E218A, 0x3D96DD06,  0xAEDD3E05, 0x464DE6BD, 0xB591548D, 0x0571C45D,  0x6F0406D4, 0xFF605015,
1335         0x241998FB, 0x97D6BDE9,  0xCC894043, 0x7767D99E, 0xBDB0E842, 0x8807898B,  0x38E7195B, 0xDB79C8EE,
1336         0x47A17C0A, 0xE97C420F,  0xC9F8841E, 0x00000000, 0x83098086, 0x48322BED,  0xAC1E1170, 0x4E6C5A72,
1337         0xFBFD0EFF, 0x560F8538,  0x1E3DAED5, 0x27362D39, 0x640A0FD9, 0x21685CA6,  0xD19B5B54, 0x3A24362E,
1338         0xB10C0A67, 0x0F9357E7,  0xD2B4EE96, 0x9E1B9B91, 0x4F80C0C5, 0xA261DC20,  0x695A774B, 0x161C121A,
1339         0x0AE293BA, 0xE5C0A02A,  0x433C22E0, 0x1D121B17, 0x0B0E090D, 0xADF28BC7,  0xB92DB6A8, 0xC8141EA9,
1340         0x8557F119, 0x4CAF7507,  0xBBEE99DD, 0xFDA37F60, 0x9FF70126, 0xBC5C72F5,  0xC544663B, 0x345BFB7E,
1341         0x768B4329, 0xDCCB23C6,  0x68B6EDFC, 0x63B8E4F1, 0xCAD731DC, 0x10426385,  0x40139722, 0x2084C611,
1342         0x7D854A24, 0xF8D2BB3D,  0x11AEF932, 0x6DC729A1, 0x4B1D9E2F, 0xF3DCB230,  0xEC0D8652, 0xD077C1E3,
1343         0x6C2BB316, 0x99A970B9,  0xFA119448, 0x2247E964, 0xC4A8FC8C, 0x1AA0F03F,  0xD8567D2C, 0xEF223390,
1344         0xC787494E, 0xC1D938D1,  0xFE8CCAA2, 0x3698D40B, 0xCFA6F581, 0x28A57ADE,  0x26DAB78E, 0xA43FADBF,
1345         0xE42C3A9D, 0x0D507892,  0x9B6A5FCC, 0x62547E46, 0xC2F68D13, 0xE890D8B8,  0x5E2E39F7, 0xF582C3AF,
1346         0xBE9F5D80, 0x7C69D093,  0xA96FD52D, 0xB3CF2512, 0x3BC8AC99, 0xA710187D,  0x6EE89C63, 0x7BDB3BBB,
1347         0x09CD2678, 0xF46E5918,  0x01EC9AB7, 0xA8834F9A, 0x65E6956E, 0x7EAAFFE6,  0x0821BCCF, 0xE6EF15E8,
1348         0xD9BAE79B, 0xCE4A6F36,  0xD4EA9F09, 0xD629B07C, 0xAF31A4B2, 0x312A3F23,  0x30C6A594, 0xC035A266,
1349         0x37744EBC, 0xA6FC82CA,  0xB0E090D0, 0x1533A7D8, 0x4AF10498, 0xF741ECDA,  0x0E7FCD50, 0x2F1791F6,
1350         0x8D764DD6, 0x4D43EFB0,  0x54CCAA4D, 0xDFE49604, 0xE39ED1B5, 0x1B4C6A88,  0xB8C12C1F, 0x7F466551,
1351         0x049D5EEA, 0x5D018C35,  0x73FA8774, 0x2EFB0B41, 0x5AB3671D, 0x5292DBD2,  0x33E91056, 0x136DD647,
1352         0x8C9AD761, 0x7A37A10C,  0x8E59F814, 0x89EB133C, 0xEECEA927, 0x35B761C9,  0xEDE11CE5, 0x3C7A47B1,
1353         0x599CD2DF, 0x3F55F273,  0x791814CE, 0xBF73C737, 0xEA53F7CD, 0x5B5FFDAA,  0x14DF3D6F, 0x867844DB,
1354         0x81CAAFF3, 0x3EB968C4,  0x2C382434, 0x5FC2A340, 0x72161DC3, 0x0CBCE225,  0x8B283C49, 0x41FF0D95,
1355         0x7139A801, 0xDE080CB3,  0x9CD8B4E4, 0x906456C1, 0x617BCB84, 0x70D532B6,  0x74486C5C, 0x42D0B857
1356 };
1357
1358 /* Corresponds to _IMXC1[256] */
1359 unsigned int mtpz_aes_gb11[] =
1360 {
1361         0x00000000, 0x0B0E090D,  0x161C121A, 0x1D121B17, 0x2C382434, 0x27362D39,  0x3A24362E, 0x312A3F23,
1362         0x58704868, 0x537E4165,  0x4E6C5A72, 0x4562537F, 0x74486C5C, 0x7F466551,  0x62547E46, 0x695A774B,
1363         0xB0E090D0, 0xBBEE99DD,  0xA6FC82CA, 0xADF28BC7, 0x9CD8B4E4, 0x97D6BDE9,  0x8AC4A6FE, 0x81CAAFF3,
1364         0xE890D8B8, 0xE39ED1B5,  0xFE8CCAA2, 0xF582C3AF, 0xC4A8FC8C, 0xCFA6F581,  0xD2B4EE96, 0xD9BAE79B,
1365         0x7BDB3BBB, 0x70D532B6,  0x6DC729A1, 0x66C920AC, 0x57E31F8F, 0x5CED1682,  0x41FF0D95, 0x4AF10498,
1366         0x23AB73D3, 0x28A57ADE,  0x35B761C9, 0x3EB968C4, 0x0F9357E7, 0x049D5EEA,  0x198F45FD, 0x12814CF0,
1367         0xCB3BAB6B, 0xC035A266,  0xDD27B971, 0xD629B07C, 0xE7038F5F, 0xEC0D8652,  0xF11F9D45, 0xFA119448,
1368         0x934BE303, 0x9845EA0E,  0x8557F119, 0x8E59F814, 0xBF73C737, 0xB47DCE3A,  0xA96FD52D, 0xA261DC20,
1369         0xF6AD766D, 0xFDA37F60,  0xE0B16477, 0xEBBF6D7A, 0xDA955259, 0xD19B5B54,  0xCC894043, 0xC787494E,
1370         0xAEDD3E05, 0xA5D33708,  0xB8C12C1F, 0xB3CF2512, 0x82E51A31, 0x89EB133C,  0x94F9082B, 0x9FF70126,
1371         0x464DE6BD, 0x4D43EFB0,  0x5051F4A7, 0x5B5FFDAA, 0x6A75C289, 0x617BCB84,  0x7C69D093, 0x7767D99E,
1372         0x1E3DAED5, 0x1533A7D8,  0x0821BCCF, 0x032FB5C2, 0x32058AE1, 0x390B83EC,  0x241998FB, 0x2F1791F6,
1373         0x8D764DD6, 0x867844DB,  0x9B6A5FCC, 0x906456C1, 0xA14E69E2, 0xAA4060EF,  0xB7527BF8, 0xBC5C72F5,
1374         0xD50605BE, 0xDE080CB3,  0xC31A17A4, 0xC8141EA9, 0xF93E218A, 0xF2302887,  0xEF223390, 0xE42C3A9D,
1375         0x3D96DD06, 0x3698D40B,  0x2B8ACF1C, 0x2084C611, 0x11AEF932, 0x1AA0F03F,  0x07B2EB28, 0x0CBCE225,
1376         0x65E6956E, 0x6EE89C63,  0x73FA8774, 0x78F48E79, 0x49DEB15A, 0x42D0B857,  0x5FC2A340, 0x54CCAA4D,
1377         0xF741ECDA, 0xFC4FE5D7,  0xE15DFEC0, 0xEA53F7CD, 0xDB79C8EE, 0xD077C1E3,  0xCD65DAF4, 0xC66BD3F9,
1378         0xAF31A4B2, 0xA43FADBF,  0xB92DB6A8, 0xB223BFA5, 0x83098086, 0x8807898B,  0x9515929C, 0x9E1B9B91,
1379         0x47A17C0A, 0x4CAF7507,  0x51BD6E10, 0x5AB3671D, 0x6B99583E, 0x60975133,  0x7D854A24, 0x768B4329,
1380         0x1FD13462, 0x14DF3D6F,  0x09CD2678, 0x02C32F75, 0x33E91056, 0x38E7195B,  0x25F5024C, 0x2EFB0B41,
1381         0x8C9AD761, 0x8794DE6C,  0x9A86C57B, 0x9188CC76, 0xA0A2F355, 0xABACFA58,  0xB6BEE14F, 0xBDB0E842,
1382         0xD4EA9F09, 0xDFE49604,  0xC2F68D13, 0xC9F8841E, 0xF8D2BB3D, 0xF3DCB230,  0xEECEA927, 0xE5C0A02A,
1383         0x3C7A47B1, 0x37744EBC,  0x2A6655AB, 0x21685CA6, 0x10426385, 0x1B4C6A88,  0x065E719F, 0x0D507892,
1384         0x640A0FD9, 0x6F0406D4,  0x72161DC3, 0x791814CE, 0x48322BED, 0x433C22E0,  0x5E2E39F7, 0x552030FA,
1385         0x01EC9AB7, 0x0AE293BA,  0x17F088AD, 0x1CFE81A0, 0x2DD4BE83, 0x26DAB78E,  0x3BC8AC99, 0x30C6A594,
1386         0x599CD2DF, 0x5292DBD2,  0x4F80C0C5, 0x448EC9C8, 0x75A4F6EB, 0x7EAAFFE6,  0x63B8E4F1, 0x68B6EDFC,
1387         0xB10C0A67, 0xBA02036A,  0xA710187D, 0xAC1E1170, 0x9D342E53, 0x963A275E,  0x8B283C49, 0x80263544,
1388         0xE97C420F, 0xE2724B02,  0xFF605015, 0xF46E5918, 0xC544663B, 0xCE4A6F36,  0xD3587421, 0xD8567D2C,
1389         0x7A37A10C, 0x7139A801,  0x6C2BB316, 0x6725BA1B, 0x560F8538, 0x5D018C35,  0x40139722, 0x4B1D9E2F,
1390         0x2247E964, 0x2949E069,  0x345BFB7E, 0x3F55F273, 0x0E7FCD50, 0x0571C45D,  0x1863DF4A, 0x136DD647,
1391         0xCAD731DC, 0xC1D938D1,  0xDCCB23C6, 0xD7C52ACB, 0xE6EF15E8, 0xEDE11CE5,  0xF0F307F2, 0xFBFD0EFF,
1392         0x92A779B4, 0x99A970B9,  0x84BB6BAE, 0x8FB562A3, 0xBE9F5D80, 0xB591548D,  0xA8834F9A, 0xA38D4697,
1393 };
1394
1395 /* Corresponds to _IMXC0[256] */
1396 unsigned int mtpz_aes_gb14[] =
1397 {
1398         0x00000000,  0x0E090D0B,   0x1C121A16,  0x121B171D,  0x3824342C,  0x362D3927,   0x24362E3A,  0x2A3F2331,
1399         0x70486858,  0x7E416553,   0x6C5A724E,  0x62537F45,  0x486C5C74,  0x4665517F,   0x547E4662,  0x5A774B69,
1400         0xE090D0B0,  0xEE99DDBB,   0xFC82CAA6,  0xF28BC7AD,  0xD8B4E49C,  0xD6BDE997,   0xC4A6FE8A,  0xCAAFF381,
1401         0x90D8B8E8,  0x9ED1B5E3,   0x8CCAA2FE,  0x82C3AFF5,  0xA8FC8CC4,  0xA6F581CF,   0xB4EE96D2,  0xBAE79BD9,
1402         0xDB3BBB7B,  0xD532B670,   0xC729A16D,  0xC920AC66,  0xE31F8F57,  0xED16825C,   0xFF0D9541,  0xF104984A,
1403         0xAB73D323,  0xA57ADE28,   0xB761C935,  0xB968C43E,  0x9357E70F,  0x9D5EEA04,   0x8F45FD19,  0x814CF012,
1404         0x3BAB6BCB,  0x35A266C0,   0x27B971DD,  0x29B07CD6,  0x038F5FE7,  0x0D8652EC,   0x1F9D45F1,  0x119448FA,
1405         0x4BE30393,  0x45EA0E98,   0x57F11985,  0x59F8148E,  0x73C737BF,  0x7DCE3AB4,   0x6FD52DA9,  0x61DC20A2,
1406         0xAD766DF6,  0xA37F60FD,   0xB16477E0,  0xBF6D7AEB,  0x955259DA,  0x9B5B54D1,   0x894043CC,  0x87494EC7,
1407         0xDD3E05AE,  0xD33708A5,   0xC12C1FB8,  0xCF2512B3,  0xE51A3182,  0xEB133C89,   0xF9082B94,  0xF701269F,
1408         0x4DE6BD46,  0x43EFB04D,   0x51F4A750,  0x5FFDAA5B,  0x75C2896A,  0x7BCB8461,   0x69D0937C,  0x67D99E77,
1409         0x3DAED51E,  0x33A7D815,   0x21BCCF08,  0x2FB5C203,  0x058AE132,  0x0B83EC39,   0x1998FB24,  0x1791F62F,
1410         0x764DD68D,  0x7844DB86,   0x6A5FCC9B,  0x6456C190,  0x4E69E2A1,  0x4060EFAA,   0x527BF8B7,  0x5C72F5BC,
1411         0x0605BED5,  0x080CB3DE,   0x1A17A4C3,  0x141EA9C8,  0x3E218AF9,  0x302887F2,   0x223390EF,  0x2C3A9DE4,
1412         0x96DD063D,  0x98D40B36,   0x8ACF1C2B,  0x84C61120,  0xAEF93211,  0xA0F03F1A,   0xB2EB2807,  0xBCE2250C,
1413         0xE6956E65,  0xE89C636E,   0xFA877473,  0xF48E7978,  0xDEB15A49,  0xD0B85742,   0xC2A3405F,  0xCCAA4D54,
1414         0x41ECDAF7,  0x4FE5D7FC,   0x5DFEC0E1,  0x53F7CDEA,  0x79C8EEDB,  0x77C1E3D0,   0x65DAF4CD,  0x6BD3F9C6,
1415         0x31A4B2AF,  0x3FADBFA4,   0x2DB6A8B9,  0x23BFA5B2,  0x09808683,  0x07898B88,   0x15929C95,  0x1B9B919E,
1416         0xA17C0A47,  0xAF75074C,   0xBD6E1051,  0xB3671D5A,  0x99583E6B,  0x97513360,   0x854A247D,  0x8B432976,
1417         0xD134621F,  0xDF3D6F14,   0xCD267809,  0xC32F7502,  0xE9105633,  0xE7195B38,   0xF5024C25,  0xFB0B412E,
1418         0x9AD7618C,  0x94DE6C87,   0x86C57B9A,  0x88CC7691,  0xA2F355A0,  0xACFA58AB,   0xBEE14FB6,  0xB0E842BD,
1419         0xEA9F09D4,  0xE49604DF,   0xF68D13C2,  0xF8841EC9,  0xD2BB3DF8,  0xDCB230F3,   0xCEA927EE,  0xC0A02AE5,
1420         0x7A47B13C,  0x744EBC37,   0x6655AB2A,  0x685CA621,  0x42638510,  0x4C6A881B,   0x5E719F06,  0x5078920D,
1421         0x0A0FD964,  0x0406D46F,   0x161DC372,  0x1814CE79,  0x322BED48,  0x3C22E043,   0x2E39F75E,  0x2030FA55,
1422         0xEC9AB701,  0xE293BA0A,   0xF088AD17,  0xFE81A01C,  0xD4BE832D,  0xDAB78E26,   0xC8AC993B,  0xC6A59430,
1423         0x9CD2DF59,  0x92DBD252,   0x80C0C54F,  0x8EC9C844,  0xA4F6EB75,  0xAAFFE67E,   0xB8E4F163,  0xB6EDFC68,
1424         0x0C0A67B1,  0x02036ABA,   0x10187DA7,  0x1E1170AC,  0x342E539D,  0x3A275E96,   0x283C498B,  0x26354480,
1425         0x7C420FE9,  0x724B02E2,   0x605015FF,  0x6E5918F4,  0x44663BC5,  0x4A6F36CE,   0x587421D3,  0x567D2CD8,
1426         0x37A10C7A,  0x39A80171,   0x2BB3166C,  0x25BA1B67,  0x0F853856,  0x018C355D,   0x13972240,  0x1D9E2F4B,
1427         0x47E96422,  0x49E06929,   0x5BFB7E34,  0x55F2733F,  0x7FCD500E,  0x71C45D05,   0x63DF4A18,  0x6DD64713,
1428         0xD731DCCA,  0xD938D1C1,   0xCB23C6DC,  0xC52ACBD7,  0xEF15E8E6,  0xE11CE5ED,   0xF307F2F0,  0xFD0EFFFB,
1429         0xA779B492,  0xA970B999,   0xBB6BAE84,  0xB562A38F,  0x9F5D80BE,  0x91548DB5,   0x834F9AA8,  0x8D4697A3,
1430 } ;
1431
1432 /* Corresponds to _IMXC2[256] */
1433 unsigned int mtpz_aes_gb13[] =
1434 {
1435         0x00000000,  0x0D0B0E09,   0x1A161C12,  0x171D121B,  0x342C3824,  0x3927362D,   0x2E3A2436,  0x23312A3F,
1436         0x68587048,  0x65537E41,   0x724E6C5A,  0x7F456253,  0x5C74486C,  0x517F4665,   0x4662547E,  0x4B695A77,
1437         0xD0B0E090,  0xDDBBEE99,   0xCAA6FC82,  0xC7ADF28B,  0xE49CD8B4,  0xE997D6BD,   0xFE8AC4A6,  0xF381CAAF,
1438         0xB8E890D8,  0xB5E39ED1,   0xA2FE8CCA,  0xAFF582C3,  0x8CC4A8FC,  0x81CFA6F5,   0x96D2B4EE,  0x9BD9BAE7,
1439         0xBB7BDB3B,  0xB670D532,   0xA16DC729,  0xAC66C920,  0x8F57E31F,  0x825CED16,   0x9541FF0D,  0x984AF104,
1440         0xD323AB73,  0xDE28A57A,   0xC935B761,  0xC43EB968,  0xE70F9357,  0xEA049D5E,   0xFD198F45,  0xF012814C,
1441         0x6BCB3BAB,  0x66C035A2,   0x71DD27B9,  0x7CD629B0,  0x5FE7038F,  0x52EC0D86,   0x45F11F9D,  0x48FA1194,
1442         0x03934BE3,  0x0E9845EA,   0x198557F1,  0x148E59F8,  0x37BF73C7,  0x3AB47DCE,   0x2DA96FD5,  0x20A261DC,
1443         0x6DF6AD76,  0x60FDA37F,   0x77E0B164,  0x7AEBBF6D,  0x59DA9552,  0x54D19B5B,   0x43CC8940,  0x4EC78749,
1444         0x05AEDD3E,  0x08A5D337,   0x1FB8C12C,  0x12B3CF25,  0x3182E51A,  0x3C89EB13,   0x2B94F908,  0x269FF701,
1445         0xBD464DE6,  0xB04D43EF,   0xA75051F4,  0xAA5B5FFD,  0x896A75C2,  0x84617BCB,   0x937C69D0,  0x9E7767D9,
1446         0xD51E3DAE,  0xD81533A7,   0xCF0821BC,  0xC2032FB5,  0xE132058A,  0xEC390B83,   0xFB241998,  0xF62F1791,
1447         0xD68D764D,  0xDB867844,   0xCC9B6A5F,  0xC1906456,  0xE2A14E69,  0xEFAA4060,   0xF8B7527B,  0xF5BC5C72,
1448         0xBED50605,  0xB3DE080C,   0xA4C31A17,  0xA9C8141E,  0x8AF93E21,  0x87F23028,   0x90EF2233,  0x9DE42C3A,
1449         0x063D96DD,  0x0B3698D4,   0x1C2B8ACF,  0x112084C6,  0x3211AEF9,  0x3F1AA0F0,   0x2807B2EB,  0x250CBCE2,
1450         0x6E65E695,  0x636EE89C,   0x7473FA87,  0x7978F48E,  0x5A49DEB1,  0x5742D0B8,   0x405FC2A3,  0x4D54CCAA,
1451         0xDAF741EC,  0xD7FC4FE5,   0xC0E15DFE,  0xCDEA53F7,  0xEEDB79C8,  0xE3D077C1,   0xF4CD65DA,  0xF9C66BD3,
1452         0xB2AF31A4,  0xBFA43FAD,   0xA8B92DB6,  0xA5B223BF,  0x86830980,  0x8B880789,   0x9C951592,  0x919E1B9B,
1453         0x0A47A17C,  0x074CAF75,   0x1051BD6E,  0x1D5AB367,  0x3E6B9958,  0x33609751,   0x247D854A,  0x29768B43,
1454         0x621FD134,  0x6F14DF3D,   0x7809CD26,  0x7502C32F,  0x5633E910,  0x5B38E719,   0x4C25F502,  0x412EFB0B,
1455         0x618C9AD7,  0x6C8794DE,   0x7B9A86C5,  0x769188CC,  0x55A0A2F3,  0x58ABACFA,   0x4FB6BEE1,  0x42BDB0E8,
1456         0x09D4EA9F,  0x04DFE496,   0x13C2F68D,  0x1EC9F884,  0x3DF8D2BB,  0x30F3DCB2,   0x27EECEA9,  0x2AE5C0A0,
1457         0xB13C7A47,  0xBC37744E,   0xAB2A6655,  0xA621685C,  0x85104263,  0x881B4C6A,   0x9F065E71,  0x920D5078,
1458         0xD9640A0F,  0xD46F0406,   0xC372161D,  0xCE791814,  0xED48322B,  0xE0433C22,   0xF75E2E39,  0xFA552030,
1459         0xB701EC9A,  0xBA0AE293,   0xAD17F088,  0xA01CFE81,  0x832DD4BE,  0x8E26DAB7,   0x993BC8AC,  0x9430C6A5,
1460         0xDF599CD2,  0xD25292DB,   0xC54F80C0,  0xC8448EC9,  0xEB75A4F6,  0xE67EAAFF,   0xF163B8E4,  0xFC68B6ED,
1461         0x67B10C0A,  0x6ABA0203,   0x7DA71018,  0x70AC1E11,  0x539D342E,  0x5E963A27,   0x498B283C,  0x44802635,
1462         0x0FE97C42,  0x02E2724B,   0x15FF6050,  0x18F46E59,  0x3BC54466,  0x36CE4A6F,   0x21D35874,  0x2CD8567D,
1463         0x0C7A37A1,  0x017139A8,   0x166C2BB3,  0x1B6725BA,  0x38560F85,  0x355D018C,   0x22401397,  0x2F4B1D9E,
1464         0x642247E9,  0x692949E0,   0x7E345BFB,  0x733F55F2,  0x500E7FCD,  0x5D0571C4,   0x4A1863DF,  0x47136DD6,
1465         0xDCCAD731,  0xD1C1D938,   0xC6DCCB23,  0xCBD7C52A,  0xE8E6EF15,  0xE5EDE11C,   0xF2F0F307,  0xFFFBFD0E,
1466         0xB492A779,  0xB999A970,   0xAE84BB6B,  0xA38FB562,  0x80BE9F5D,  0x8DB59154,   0x9AA8834F,  0x97A38D46,
1467 };
1468
1469 /* Corresponds to _IMXC3[256] */
1470 unsigned int mtpz_aes_gb9[] =
1471 {
1472         0x00000000,  0x090D0B0E,   0x121A161C,  0x1B171D12,  0x24342C38,  0x2D392736,   0x362E3A24,  0x3F23312A,
1473         0x48685870,  0x4165537E,   0x5A724E6C,  0x537F4562,  0x6C5C7448,  0x65517F46,   0x7E466254,  0x774B695A,
1474         0x90D0B0E0,  0x99DDBBEE,   0x82CAA6FC,  0x8BC7ADF2,  0xB4E49CD8,  0xBDE997D6,   0xA6FE8AC4,  0xAFF381CA,
1475         0xD8B8E890,  0xD1B5E39E,   0xCAA2FE8C,  0xC3AFF582,  0xFC8CC4A8,  0xF581CFA6,   0xEE96D2B4,  0xE79BD9BA,
1476         0x3BBB7BDB,  0x32B670D5,   0x29A16DC7,  0x20AC66C9,  0x1F8F57E3,  0x16825CED,   0x0D9541FF,  0x04984AF1,
1477         0x73D323AB,  0x7ADE28A5,   0x61C935B7,  0x68C43EB9,  0x57E70F93,  0x5EEA049D,   0x45FD198F,  0x4CF01281,
1478         0xAB6BCB3B,  0xA266C035,   0xB971DD27,  0xB07CD629,  0x8F5FE703,  0x8652EC0D,   0x9D45F11F,  0x9448FA11,
1479         0xE303934B,  0xEA0E9845,   0xF1198557,  0xF8148E59,  0xC737BF73,  0xCE3AB47D,   0xD52DA96F,  0xDC20A261,
1480         0x766DF6AD,  0x7F60FDA3,   0x6477E0B1,  0x6D7AEBBF,  0x5259DA95,  0x5B54D19B,   0x4043CC89,  0x494EC787,
1481         0x3E05AEDD,  0x3708A5D3,   0x2C1FB8C1,  0x2512B3CF,  0x1A3182E5,  0x133C89EB,   0x082B94F9,  0x01269FF7,
1482         0xE6BD464D,  0xEFB04D43,   0xF4A75051,  0xFDAA5B5F,  0xC2896A75,  0xCB84617B,   0xD0937C69,  0xD99E7767,
1483         0xAED51E3D,  0xA7D81533,   0xBCCF0821,  0xB5C2032F,  0x8AE13205,  0x83EC390B,   0x98FB2419,  0x91F62F17,
1484         0x4DD68D76,  0x44DB8678,   0x5FCC9B6A,  0x56C19064,  0x69E2A14E,  0x60EFAA40,   0x7BF8B752,  0x72F5BC5C,
1485         0x05BED506,  0x0CB3DE08,   0x17A4C31A,  0x1EA9C814,  0x218AF93E,  0x2887F230,   0x3390EF22,  0x3A9DE42C,
1486         0xDD063D96,  0xD40B3698,   0xCF1C2B8A,  0xC6112084,  0xF93211AE,  0xF03F1AA0,   0xEB2807B2,  0xE2250CBC,
1487         0x956E65E6,  0x9C636EE8,   0x877473FA,  0x8E7978F4,  0xB15A49DE,  0xB85742D0,   0xA3405FC2,  0xAA4D54CC,
1488         0xECDAF741,  0xE5D7FC4F,   0xFEC0E15D,  0xF7CDEA53,  0xC8EEDB79,  0xC1E3D077,   0xDAF4CD65,  0xD3F9C66B,
1489         0xA4B2AF31,  0xADBFA43F,   0xB6A8B92D,  0xBFA5B223,  0x80868309,  0x898B8807,   0x929C9515,  0x9B919E1B,
1490         0x7C0A47A1,  0x75074CAF,   0x6E1051BD,  0x671D5AB3,  0x583E6B99,  0x51336097,   0x4A247D85,  0x4329768B,
1491         0x34621FD1,  0x3D6F14DF,   0x267809CD,  0x2F7502C3,  0x105633E9,  0x195B38E7,   0x024C25F5,  0x0B412EFB,
1492         0xD7618C9A,  0xDE6C8794,   0xC57B9A86,  0xCC769188,  0xF355A0A2,  0xFA58ABAC,   0xE14FB6BE,  0xE842BDB0,
1493         0x9F09D4EA,  0x9604DFE4,   0x8D13C2F6,  0x841EC9F8,  0xBB3DF8D2,  0xB230F3DC,   0xA927EECE,  0xA02AE5C0,
1494         0x47B13C7A,  0x4EBC3774,   0x55AB2A66,  0x5CA62168,  0x63851042,  0x6A881B4C,   0x719F065E,  0x78920D50,
1495         0x0FD9640A,  0x06D46F04,   0x1DC37216,  0x14CE7918,  0x2BED4832,  0x22E0433C,   0x39F75E2E,  0x30FA5520,
1496         0x9AB701EC,  0x93BA0AE2,   0x88AD17F0,  0x81A01CFE,  0xBE832DD4,  0xB78E26DA,   0xAC993BC8,  0xA59430C6,
1497         0xD2DF599C,  0xDBD25292,   0xC0C54F80,  0xC9C8448E,  0xF6EB75A4,  0xFFE67EAA,   0xE4F163B8,  0xEDFC68B6,
1498         0x0A67B10C,  0x036ABA02,   0x187DA710,  0x1170AC1E,  0x2E539D34,  0x275E963A,   0x3C498B28,  0x35448026,
1499         0x420FE97C,  0x4B02E272,   0x5015FF60,  0x5918F46E,  0x663BC544,  0x6F36CE4A,   0x7421D358,  0x7D2CD856,
1500         0xA10C7A37,  0xA8017139,   0xB3166C2B,  0xBA1B6725,  0x8538560F,  0x8C355D01,   0x97224013,  0x9E2F4B1D,
1501         0xE9642247,  0xE0692949,   0xFB7E345B,  0xF2733F55,  0xCD500E7F,  0xC45D0571,   0xDF4A1863,  0xD647136D,
1502         0x31DCCAD7,  0x38D1C1D9,   0x23C6DCCB,  0x2ACBD7C5,  0x15E8E6EF,  0x1CE5EDE1,   0x07F2F0F3,  0x0EFFFBFD,
1503         0x79B492A7,  0x70B999A9,   0x6BAE84BB,  0x62A38FB5,  0x5D80BE9F,  0x548DB591,   0x4F9AA883,  0x4697A38D,
1504 };
1505
1506 static uint16_t
1507 ptp_mtpz_validatehandshakeresponse (PTPParams* params, unsigned char *random, unsigned char **calculatedHash)
1508 {
1509         uint16_t ret;
1510         unsigned int len;
1511         unsigned char* response = NULL;
1512
1513         ret = ptp_mtpz_getwmdrmpdappresponse (params, &response, &len);
1514         if (ret != PTP_RC_OK)
1515         {
1516                 LIBMTP_INFO ("(MTPZ) Failure - did not receive device's response.\n");
1517                 return ret;
1518         }
1519
1520         char *reader = (char *)response;
1521         int i;
1522
1523         if (*(reader++) != '\x02')
1524         {
1525                 return -1;
1526         }
1527
1528         if (*(reader++) != '\x02')
1529         {
1530                 return -1;
1531         }
1532
1533         // Message is always 128 bytes.
1534         reader++;
1535         if (*(reader++) != '\x80')
1536         {
1537                 return -1;
1538         }
1539
1540         char *message = (char *)malloc(128);
1541         memcpy(message, reader, 128);
1542         reader += 128;
1543
1544         // Decrypt the hash-key-message..
1545         char *msg_dec = (char *)malloc(128);
1546         memset(msg_dec, 0, 128);
1547
1548         mtpz_rsa_t *rsa = mtpz_rsa_init(MTPZ_MODULUS, MTPZ_PRIVATE_KEY, MTPZ_PUBLIC_EXPONENT);
1549         if (!rsa)
1550         {
1551                 LIBMTP_INFO ("(MTPZ) Failure - could not instantiate RSA object.\n");
1552                 free(message);
1553                 free(msg_dec);
1554                 return -1;
1555         }
1556
1557         if (mtpz_rsa_decrypt(128, (unsigned char *)message, 128, (unsigned char *)msg_dec, rsa) == 0)
1558         {
1559                 LIBMTP_INFO ("(MTPZ) Failure - could not perform RSA decryption.\n");
1560
1561                 free(message);
1562                 free(msg_dec);
1563                 mtpz_rsa_free(rsa);
1564                 return -1;
1565         }
1566
1567         mtpz_rsa_free(rsa);
1568         rsa = NULL;
1569
1570         char *state = mtpz_hash_init_state();
1571         char *hash_key = (char *)malloc(16);
1572         char *v10 = mtpz_hash_custom6A5DC(state, msg_dec + 21, 107, 20);
1573
1574         for (i = 0; i < 20; i++)
1575                 msg_dec[i + 1] ^= v10[i];
1576
1577         char *v11 = mtpz_hash_custom6A5DC(state, msg_dec + 1, 20, 107);
1578
1579         for (i = 0; i < 107; i++)
1580                 msg_dec[i + 21] ^= v11[i];
1581
1582         memcpy(hash_key, msg_dec + 112, 16);
1583
1584         // Encrypted message is 0x340 bytes.
1585         reader += 2;
1586         if (*(reader++) != '\x03' || *(reader++) != '\x40')
1587         {
1588                 return -1;
1589         }
1590
1591         unsigned char *act_msg = (unsigned char *)malloc(832);
1592         unsigned char *act_reader = act_msg;
1593         memcpy(act_msg, reader, 832);
1594         reader = NULL;
1595
1596         mtpz_encryption_cipher_advanced((unsigned char *)hash_key, 16, act_msg, 832, 0);
1597
1598         act_reader++;
1599         unsigned int certs_length = MTPZ_SWAP(*(unsigned int *)(act_reader));
1600         act_reader += 4;
1601         act_reader += certs_length;
1602
1603         unsigned int rand_length = MTPZ_SWAP(*(unsigned short *)(act_reader) << 16);
1604         act_reader += 2;
1605         unsigned char *rand_data = (unsigned char *)malloc(rand_length);
1606         memcpy(rand_data, act_reader, rand_length);
1607         if (memcmp(rand_data, random, 16) != 0)
1608         {
1609                 free(rand_data);
1610                 return -1;
1611         }
1612         free(rand_data);
1613         act_reader += rand_length;
1614
1615         unsigned int dev_rand_length = MTPZ_SWAP(*(unsigned short *)(act_reader) << 16);
1616         act_reader += 2;
1617         act_reader += dev_rand_length;
1618
1619         act_reader++;
1620
1621         unsigned int sig_length = MTPZ_SWAP(*(unsigned short *)(act_reader) << 16);
1622         act_reader += 2;
1623         act_reader += sig_length;
1624
1625         act_reader++;
1626
1627         unsigned int machash_length = MTPZ_SWAP(*(unsigned short *)(act_reader) << 16);
1628         act_reader += 2;
1629         unsigned char *machash_data = (unsigned char *)malloc(machash_length);
1630         memcpy(machash_data, act_reader, machash_length);
1631         act_reader += machash_length;
1632
1633         *calculatedHash = machash_data;
1634
1635         free(message);
1636         free(msg_dec);
1637         free(state);
1638         free(v10);
1639         free(v11);
1640         free(act_msg);
1641
1642         return ret;
1643 }
1644
1645 static uint16_t
1646 ptp_mtpz_opensecuresyncsession (PTPParams* params, unsigned char *hash)
1647 {
1648         unsigned char   mch[16];
1649         uint32_t        *hashparams = (unsigned int *)mch;
1650         unsigned int    macCount = *(unsigned int *)(hash + 16);
1651         uint16_t        ret;
1652
1653         mtpz_encryption_encrypt_mac(hash, 16, (unsigned char *)(&macCount), 4, mch);
1654
1655         ret = ptp_mtpz_wmdrmpd_enabletrustedfilesoperations(params,
1656                 MTPZ_SWAP(hashparams[0]), MTPZ_SWAP(hashparams[1]),
1657                 MTPZ_SWAP(hashparams[2]), MTPZ_SWAP(hashparams[3]));
1658         return ret;
1659 };
1660
1661 static unsigned char *
1662 ptp_mtpz_makeapplicationcertificatemessage (unsigned int *out_len, unsigned char **out_random)
1663 {
1664         *out_len = 785;
1665
1666         unsigned char *acm = (unsigned char *)malloc(785);
1667         unsigned char *target = acm;
1668         memset(acm, 0, 785);
1669
1670         unsigned char *random = (unsigned char *)malloc(16);
1671
1672         int i = 0;
1673         int certsLength = 0x275;
1674
1675         // Write the marker bytes, length of certificates, and certificates themselves.
1676         *(target++) = '\x02';
1677         *(target++) = '\x01';
1678         *(target++) = '\x01';
1679         *(target++) = '\x00';
1680         *(target++) = '\x00';
1681         *(target++) = '\x02';
1682         *(target++) = '\x75';
1683         memcpy(target, MTPZ_CERTIFICATES, certsLength);
1684         target += certsLength;
1685
1686         // Write the random bytes.
1687         *(target++) = '\x00';   *(target++) = '\x10';
1688         srand(time(NULL));
1689
1690         for (i = 0; i < 16; i++)
1691                 *(random + i) = (unsigned char)(rand() % 256);
1692
1693         *out_random = random;
1694         memcpy(target, random, 16);
1695         target += 16;
1696
1697         char *state = mtpz_hash_init_state();
1698         char *v16 = (char *)malloc(28); memset(v16, 0, 28);
1699         char *hash = (char *)malloc(20); memset(hash, 0, 20);
1700         char *odata = (char *)malloc(128); memset(odata, 0, 128);
1701
1702         mtpz_hash_reset_state(state);
1703         mtpz_hash_transform_hash(state, (char *)acm + 2, (target - acm - 2));
1704         mtpz_hash_finalize_hash(state, v16 + 8);
1705
1706         mtpz_hash_reset_state(state);
1707         mtpz_hash_transform_hash(state, v16, 28);
1708         mtpz_hash_finalize_hash(state, hash);
1709
1710         char *v17 = mtpz_hash_custom6A5DC(state, hash, 20, 107);
1711
1712         for (i = 0; i < 20; i++)
1713                 odata[107 + i] = hash[i];
1714
1715         odata[106] = '\x01';
1716
1717         if (v17 != NULL)
1718         {
1719                 for (i = 0; i < 107; i++)
1720                         odata[i] ^= v17[i];
1721
1722                 odata[0] &= 127;
1723                 odata[127] = 188;
1724         }
1725
1726         // Free up some jazz.
1727         free(state); state = NULL;
1728         free(v16); v16 = NULL;
1729         free(v17); v17 = NULL;
1730         free(hash); hash = NULL;
1731
1732         // Take care of some RSA jazz.
1733         mtpz_rsa_t *rsa = mtpz_rsa_init(MTPZ_MODULUS, MTPZ_PRIVATE_KEY, MTPZ_PUBLIC_EXPONENT);
1734         if (!rsa)
1735         {
1736                 LIBMTP_INFO("(MTPZ) Failure - could not instantiate RSA object.\n");
1737                 *out_len = 0;
1738                 return NULL;
1739         }
1740
1741         char *signature = (char *)malloc(128);
1742         memset(signature, 0, 128);
1743         mtpz_rsa_sign(128, (unsigned char *)odata, 128, (unsigned char *)signature, rsa);
1744
1745         // Free some more things.
1746         mtpz_rsa_free(rsa); rsa = NULL;
1747         free(odata); odata = NULL;
1748
1749         // Write the signature + bytes.
1750         *(target++) = '\x01'; *(target++) = '\x00'; *(target++) = '\x80';
1751         memcpy(target, signature, 128);
1752
1753         // Kill target.
1754         target = NULL;
1755
1756         return acm;
1757 };
1758
1759 static unsigned char *
1760 ptp_mtpz_makeconfirmationmessage (unsigned char *hash, unsigned int *out_len)
1761 {
1762         *out_len = 20;
1763         unsigned char *message = (unsigned char *)malloc(20);
1764         message[0] = (unsigned char)0x02;
1765         message[1] = (unsigned char)0x03;
1766         message[2] = (unsigned char)0x00;
1767         message[3] = (unsigned char)0x10;
1768
1769         unsigned char *seed = (unsigned char *)malloc(16);
1770         memset(seed, 0, 16);
1771         seed[15] = (unsigned char)(0x01);
1772
1773         mtpz_encryption_encrypt_mac(hash, 16u, seed, 16u, message + 4);
1774
1775         free(seed);
1776
1777         return message;
1778 }
1779
1780 uint16_t ptp_mtpz_handshake (PTPParams* params)
1781 {
1782         uint16_t ret = PTP_RC_OK;
1783         uint32_t size;
1784         unsigned char *hash=NULL;
1785         unsigned char *random=NULL;
1786         PTPPropertyValue propval;
1787         unsigned char*  applicationCertificateMessage;
1788         unsigned char*  message;
1789
1790         /* FIXME: do other places of libmtp set it? should we set it? */
1791         LIBMTP_INFO ("(MTPZ) Setting session initiator info.\n");
1792         propval.str = "libmtp/Sajid Anwar - MTPZClassDriver";
1793         ret = ptp_setdevicepropvalue(params,
1794                    PTP_DPC_MTP_SessionInitiatorInfo,
1795                    &propval,
1796                    PTP_DTC_STR);
1797         if (ret != PTP_RC_OK)
1798                 return ret;
1799
1800         LIBMTP_INFO ("(MTPZ) Resetting handshake.\n");
1801         ret = ptp_mtpz_resethandshake(params);
1802         if (ret != PTP_RC_OK)
1803                 return ret;
1804
1805         LIBMTP_INFO ("(MTPZ) Sending application certificate message.\n");
1806         applicationCertificateMessage = ptp_mtpz_makeapplicationcertificatemessage(&size, &random);
1807         ret = ptp_mtpz_sendwmdrmpdapprequest (params, applicationCertificateMessage, size);
1808         free (applicationCertificateMessage);
1809         if (ret != PTP_RC_OK)
1810                 return ret;
1811
1812         LIBMTP_INFO ("(MTPZ) Getting and validating handshake response.\n");
1813         ret = ptp_mtpz_validatehandshakeresponse(params, random, &hash);
1814         if (ret != PTP_RC_OK)
1815                 goto free_random;
1816
1817         LIBMTP_INFO ("(MTPZ) Sending confirmation message.\n");
1818         message = ptp_mtpz_makeconfirmationmessage(hash, &size);
1819         ret = ptp_mtpz_sendwmdrmpdapprequest (params, message, size);
1820         if (ret != PTP_RC_OK)
1821                 goto free_hash;
1822         free (message);
1823
1824         LIBMTP_INFO ("(MTPZ) Opening secure sync session.\n");
1825         ret = ptp_mtpz_opensecuresyncsession(params, hash);
1826 free_hash:
1827         free(hash);
1828 free_random:
1829         free(random);
1830         return ret;
1831 }