Home | History | Annotate | Download | only in src
      1 /**
      2  * \file mtpz.c
      3  *
      4  * Copyright (C) 2011-2012 Sajid Anwar <sajidanwar94 (at) 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 		return;
    709 	}
    710 
    711 	unsigned char *key = (unsigned char *)malloc(ks);
    712 	unsigned char *temp = (unsigned char *)malloc(4);
    713 	memcpy(key, constant, key_len);
    714 	unsigned char t0, t1, t2, t3;
    715 
    716 	for (i = key_len; i < ks; i += 4)
    717 	{
    718 		temp[0] = t0 = key[i - 4];
    719 		temp[1] = t1 = key[i - 3];
    720 		temp[2] = t2 = key[i - 2];
    721 		temp[3] = t3 = key[i - 1];
    722 
    723 		if (i % key_len == 0)
    724 		{
    725 			temp[0] = (mtpz_aes_sbox[t1] ^ mtpz_aes_rcon[rcon_i]) & 0xFF;
    726 			temp[1] = mtpz_aes_sbox[t2];
    727 			temp[2] = mtpz_aes_sbox[t3];
    728 			temp[3] = mtpz_aes_sbox[t0];
    729 			rcon_i++;
    730 		}
    731 		else if ((key_len > 24) && (i % key_len == 16))
    732 		{
    733 			temp[0] = mtpz_aes_sbox[t0];
    734 			temp[1] = mtpz_aes_sbox[t1];
    735 			temp[2] = mtpz_aes_sbox[t2];
    736 			temp[3] = mtpz_aes_sbox[t3];
    737 		}
    738 
    739 		for (j = 0; j < 4; j++)
    740 		{
    741 			key[i + j] = (unsigned char)((key[i + j - key_len] ^ temp[j]) & 0xFF);
    742 		}
    743 	}
    744 
    745 	free(temp);
    746 
    747 	*out = key;
    748 	*out_len = ks;
    749 }
    750 
    751 void mtpz_encryption_inv_mix_columns(unsigned char *expanded, int offset, int rounds)
    752 {
    753 	int v8 = 1, o = offset;
    754 	unsigned int *exp_int = NULL;
    755 
    756 	for (v8 = 1; v8 < rounds; v8++)
    757 	{
    758 		exp_int = (unsigned int *)(expanded + o + 16);
    759 
    760 		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]]);
    761 		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]]);
    762 		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]]);
    763 		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]]);
    764 		o += 16;
    765 	}
    766 }
    767 
    768 void mtpz_encryption_decrypt_custom(unsigned char *data, unsigned char *seed, unsigned char *expanded)
    769 {
    770 	unsigned int *u_data = (unsigned int *)data;
    771 	unsigned int *u_expanded = (unsigned int *)expanded;
    772 	int keyOffset = 0xB4 + 0xA0;
    773 
    774 	unsigned int *u_seed;
    775 
    776 	if (seed == NULL)
    777 		u_seed = u_data;
    778 	else
    779 		u_seed = (unsigned int *)seed;
    780 
    781 	unsigned int v14 = MTPZ_SWAP(u_seed[0]) ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]);
    782 	unsigned int v15 = MTPZ_SWAP(u_seed[1]) ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]);
    783 	unsigned int v16 = MTPZ_SWAP(u_seed[2]) ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]);
    784 	unsigned int v17 = MTPZ_SWAP(u_seed[3]) ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]);
    785 
    786 	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)];
    787 	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)];
    788 	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)];
    789 	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)];
    790 
    791 	keyOffset -= 16;
    792 	int rounds = 9;
    793 
    794 	do
    795 	{
    796 		v14 = v18 ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]);
    797 		v15 = v19 ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]);
    798 		v16 = v20 ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]);
    799 		v17 = v21 ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]);
    800 
    801 		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)];
    802 		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)];
    803 		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)];
    804 		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)];
    805 
    806 		rounds--;
    807 		keyOffset -= 16;
    808 	}
    809 	while (rounds != 1);
    810 
    811 	v14 = v18 ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]);
    812 	v15 = v19 ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]);
    813 	v16 = v20 ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]);
    814 	v17 = v21 ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]);
    815 	keyOffset -= 16;
    816 
    817 	v18 = ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONLOBYTE(v14)]) << 24) |
    818 		  ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE1 (v17)]) << 16) |
    819 		  ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE2 (v16)]) <<  8) |
    820 		  ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE3 (v15)]) <<  0);
    821 
    822 	v19 = ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONLOBYTE(v15)]) << 24) |
    823 		  ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE1 (v14)]) << 16) |
    824 		  ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE2 (v17)]) <<  8) |
    825 		  ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE3 (v16)]) <<  0);
    826 
    827 	v20 = ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONLOBYTE(v16)]) << 24) |
    828 		  ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE1 (v15)]) << 16) |
    829 		  ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE2 (v14)]) <<  8) |
    830 		  ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE3 (v17)]) <<  0);
    831 
    832 	v21 = ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONLOBYTE(v17)]) << 24) |
    833 		  ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE1 (v16)]) << 16) |
    834 		  ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE2 (v15)]) <<  8) |
    835 		  ((mtpz_aes_invsbox[MTPZ_ENCRYPTIONBYTE3 (v14)]) <<  0);
    836 
    837 	u_data[0] = MTPZ_SWAP(v18 ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]));
    838 	u_data[1] = MTPZ_SWAP(v19 ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]));
    839 	u_data[2] = MTPZ_SWAP(v20 ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]));
    840 	u_data[3] = MTPZ_SWAP(v21 ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]));
    841 };
    842 
    843 void mtpz_encryption_encrypt_custom(unsigned char *data, unsigned char *seed, unsigned char *expanded)
    844 {
    845 	unsigned int *u_data = (unsigned int *)data;
    846 	unsigned int *u_expanded = (unsigned int *)expanded;
    847 	int keyOffset = 0x04;
    848 
    849 	unsigned int *u_seed;
    850 
    851 	if (seed == NULL)
    852 		u_seed = u_data;
    853 	else
    854 		u_seed = (unsigned int *)seed;
    855 
    856 	unsigned int v14 = MTPZ_SWAP(u_seed[0]) ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]);
    857 	unsigned int v15 = MTPZ_SWAP(u_seed[1]) ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]);
    858 	unsigned int v16 = MTPZ_SWAP(u_seed[2]) ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]);
    859 	unsigned int v17 = MTPZ_SWAP(u_seed[3]) ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]);
    860 
    861 	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)];
    862 	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)];
    863 	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)];
    864 	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)];
    865 
    866 	keyOffset += 16;
    867 	int rounds = 1;
    868 
    869 	do
    870 	{
    871 
    872 		v14 = v18 ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]);
    873 		v15 = v19 ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]);
    874 		v16 = v20 ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]);
    875 		v17 = v21 ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]);
    876 
    877 		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)];
    878 		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)];
    879 		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)];
    880 		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)];
    881 
    882 		rounds++;
    883 		keyOffset += 16;
    884 	}
    885 	while (rounds != 9);
    886 
    887 	v14 = v18 ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]);
    888 	v15 = v19 ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]);
    889 	v16 = v20 ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]);
    890 	v17 = v21 ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]);
    891 	keyOffset += 16;
    892 
    893 	unsigned char *FT3_Bytes = (unsigned char *)mtpz_aes_ft3;
    894 
    895 	v18 = ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONLOBYTE(v14)]) << 24) |
    896 		  ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE1 (v15)]) << 16) |
    897 		  ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE2 (v16)]) <<  8) |
    898 		  ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE3 (v17)]) <<  0);
    899 
    900 	v19 = ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONLOBYTE(v15)]) << 24) |
    901 		  ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE1 (v16)]) << 16) |
    902 		  ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE2 (v17)]) <<  8) |
    903 		  ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE3 (v14)]) <<  0);
    904 
    905 	v20 = ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONLOBYTE(v16)]) << 24) |
    906 		  ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE1 (v17)]) << 16) |
    907 		  ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE2 (v14)]) <<  8) |
    908 		  ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE3 (v15)]) <<  0);
    909 
    910 	v21 = ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONLOBYTE(v17)]) << 24) |
    911 		  ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE1 (v14)]) << 16) |
    912 		  ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE2 (v15)]) <<  8) |
    913 		  ((FT3_Bytes[1 + 4 * MTPZ_ENCRYPTIONBYTE3 (v16)]) <<  0);
    914 
    915 	u_data[0] = MTPZ_SWAP(v18 ^ MTPZ_SWAP(u_expanded[(keyOffset     ) / 4]));
    916 	u_data[1] = MTPZ_SWAP(v19 ^ MTPZ_SWAP(u_expanded[(keyOffset +  4) / 4]));
    917 	u_data[2] = MTPZ_SWAP(v20 ^ MTPZ_SWAP(u_expanded[(keyOffset +  8) / 4]));
    918 	u_data[3] = MTPZ_SWAP(v21 ^ MTPZ_SWAP(u_expanded[(keyOffset + 12) / 4]));
    919 }
    920 
    921 void mtpz_encryption_encrypt_mac(unsigned char *hash, unsigned int hash_length, unsigned char *seed, unsigned int seed_len, unsigned char *out)
    922 {
    923 	if (hash == NULL || hash_length != 16)
    924 		return;
    925 
    926 	unsigned char *loop1 = (unsigned char *)malloc(17);
    927 	memset(loop1, 0, 17);
    928 	unsigned char *loop2 = (unsigned char *)malloc(17);
    929 	memset(loop2, 0, 17);
    930 	int i = 0;
    931 
    932 	{
    933 		unsigned char *enc_hash = (unsigned char *)malloc(17);
    934 		memset(enc_hash, 0, 17);
    935 		mtpz_encryption_cipher_advanced(hash, hash_length, enc_hash, 16, 1);
    936 
    937 		for (i = 0; i < 16; i++)
    938 			loop1[i] = (unsigned char)((2 * enc_hash[i]) | (enc_hash[i + 1] >> 7));
    939 
    940 		if (enc_hash[0] >= (unsigned char)128)
    941 			loop1[15] ^= (unsigned char)0x87;
    942 
    943 		for (i = 0; i < 16; i++)
    944 			loop2[i] = (unsigned char)((2 * loop1[i]) | (loop1[i + 1] >> 7));
    945 
    946 		if (loop1[0] >= (unsigned char)128)
    947 			loop2[15] ^= (unsigned char)0x87;
    948 
    949 		free(enc_hash);
    950 	}
    951 
    952 	{
    953 		int len = 	(hash_length == 16) ? 10 :
    954 					(hash_length == 24) ? 12 : 32;
    955 		int exp_len;
    956 		unsigned char *expanded = mtpz_encryption_expand_key(hash, hash_length, len, &exp_len);
    957 
    958 		unsigned char *actual_seed = (unsigned char *)malloc(16);
    959 		memset(actual_seed, 0, 16);
    960 
    961 		int i = 0;
    962 
    963 		if (seed_len == 16)
    964 		{
    965 			for (i = 0; i < 16; i++)
    966 				actual_seed[i] ^= seed[i];
    967 
    968 			for (i = 0; i < 16; i++)
    969 				actual_seed[i] ^= loop1[i];
    970 		}
    971 		else
    972 		{
    973 			for (i = 0; i < seed_len; i++)
    974 				actual_seed[i] ^= seed[i];
    975 
    976 			actual_seed[seed_len] = (unsigned char)128;
    977 
    978 			for (i = 0; i < 16; i++)
    979 				actual_seed[i] ^= loop2[i];
    980 		}
    981 
    982 		mtpz_encryption_encrypt_custom(out, actual_seed, expanded);
    983 
    984 		free(expanded);
    985 		free(actual_seed);
    986 	}
    987 
    988 	free(loop1);
    989 	free(loop2);
    990 }
    991 
    992 
    993 /* ENCRYPTION CONSTANTS */
    994 /*
    995  * These tables can also be found in Mozilla's Network Security Services:
    996  *     http://www.mozilla.org/projects/security/pki/nss/
    997  *
    998  * <rijndael32.tab>:
    999  *     https://hg.mozilla.org/mozilla-central/raw-file/90828ac18dcf/security/nss/lib/freebl/rijndael32.tab
   1000  *
   1001  * Each of the following constant tables will also identify the corresponding
   1002  * table in the <rijndael32.tab> link.
   1003  */
   1004 
   1005 /* Corresponds to Rcon[30] (seems to be truncated to include only the used constants) */
   1006 unsigned char mtpz_aes_rcon[] =
   1007 {
   1008 	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a
   1009 };
   1010 
   1011 /* Corresponds to _S[256] (in hex) */
   1012 unsigned char mtpz_aes_sbox[] =
   1013 {
   1014 	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01,
   1015 	0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d,
   1016 	0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4,
   1017 	0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
   1018 	0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7,
   1019 	0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
   1020 	0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e,
   1021 	0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
   1022 	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb,
   1023 	0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb,
   1024 	0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c,
   1025 	0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
   1026 	0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c,
   1027 	0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d,
   1028 	0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a,
   1029 	0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
   1030 	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3,
   1031 	0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
   1032 	0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a,
   1033 	0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
   1034 	0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e,
   1035 	0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9,
   1036 	0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9,
   1037 	0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
   1038 	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99,
   1039 	0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
   1040 };
   1041 
   1042 /* Corresponds to _SInv[256] (in hex) */
   1043 unsigned char mtpz_aes_invsbox[] =
   1044 {
   1045 	0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,  0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
   1046 	0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,  0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
   1047 	0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,  0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
   1048 	0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,  0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
   1049 	0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,  0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
   1050 	0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,  0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
   1051 	0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,  0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
   1052 	0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,  0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
   1053 	0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,  0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
   1054 	0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,  0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
   1055 	0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,  0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
   1056 	0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,  0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
   1057 	0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,  0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
   1058 	0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,  0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
   1059 	0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,  0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
   1060 	0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,  0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
   1061 };
   1062 
   1063 /* Corresponds to _T3[256] */
   1064 unsigned int mtpz_aes_ft1[] =
   1065 {
   1066 	0x6363A5C6, 0x7C7C84F8,  0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6,  0x6F6FB1DE, 0xC5C55491,
   1067 	0x30305060, 0x01010302,  0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5,  0xABABE64D, 0x76769AEC,
   1068 	0xCACA458F, 0x82829D1F,  0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2,  0x4747C98E, 0xF0F00BFB,
   1069 	0xADADEC41, 0xD4D467B3,  0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753,  0x727296E4, 0xC0C05B9B,
   1070 	0xB7B7C275, 0xFDFD1CE1,  0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E,  0xF7F702F5, 0xCCCC4F83,
   1071 	0x34345C68, 0xA5A5F451,  0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB,  0x31315362, 0x15153F2A,
   1072 	0x04040C08, 0xC7C75295,  0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137,  0x05050F0A, 0x9A9AB52F,
   1073 	0x0707090E, 0x12123624,  0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E,  0xB2B2CD7F, 0x75759FEA,
   1074 	0x09091B12, 0x83839E1D,  0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC,  0x5A5AEEB4, 0xA0A0FB5B,
   1075 	0x5252F6A4, 0x3B3B4D76,  0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD,  0x2F2F715E, 0x84849713,
   1076 	0x5353F5A6, 0xD1D168B9,  0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3,  0xB1B1C879, 0x5B5BEDB6,
   1077 	0x6A6ABED4, 0xCBCB468D,  0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498,  0x5858E8B0, 0xCFCF4A85,
   1078 	0xD0D06BBB, 0xEFEF2AC5,  0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A,  0x33335566, 0x85859411,
   1079 	0x4545CF8A, 0xF9F910E9,  0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478,  0x9F9FBA25, 0xA8A8E34B,
   1080 	0x5151F3A2, 0xA3A3FE5D,  0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21,  0x38384870, 0xF5F504F1,
   1081 	0xBCBCDF63, 0xB6B6C177,  0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5,  0xF3F30EFD, 0xD2D26DBF,
   1082 	0xCDCD4C81, 0x0C0C1418,  0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235,  0x4444CC88, 0x1717392E,
   1083 	0xC4C45793, 0xA7A7F255,  0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA,  0x19192B32, 0x737395E6,
   1084 	0x6060A0C0, 0x81819819,  0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54,  0x9090AB3B, 0x8888830B,
   1085 	0x4646CA8C, 0xEEEE29C7,  0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC,  0x0B0B1D16, 0xDBDB76AD,
   1086 	0xE0E03BDB, 0x32325664,  0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C,  0x24246C48, 0x5C5CE4B8,
   1087 	0xC2C25D9F, 0xD3D36EBD,  0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431,  0xE4E437D3, 0x79798BF2,
   1088 	0xE7E732D5, 0xC8C8438B,  0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1,  0x4E4ED29C, 0xA9A9E049,
   1089 	0x6C6CB4D8, 0x5656FAAC,  0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4,  0xAEAEE947, 0x08081810,
   1090 	0xBABAD56F, 0x787888F0,  0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157,  0xB4B4C773, 0xC6C65197,
   1091 	0xE8E823CB, 0xDDDD7CA1,  0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61,  0x8B8B860D, 0x8A8A850F,
   1092 	0x707090E0, 0x3E3E427C,  0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506,  0xF6F601F7, 0x0E0E121C,
   1093 	0x6161A3C2, 0x35355F6A,  0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899,  0x1D1D273A, 0x9E9EB927,
   1094 	0xE1E138D9, 0xF8F813EB,  0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9,  0x8E8E8907, 0x9494A733,
   1095 	0x9B9BB62D, 0x1E1E223C,  0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA,  0x28287850, 0xDFDF7AA5,
   1096 	0x8C8C8F03, 0xA1A1F859,  0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7,  0x4242C684, 0x6868B8D0,
   1097 	0x4141C382, 0x9999B029,  0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8,  0xBBBBD66D, 0x16163A2C,
   1098 };
   1099 
   1100 /* Corresponds to _T2[256] */
   1101 unsigned int mtpz_aes_ft2[] =
   1102 {
   1103 	0x63A5C663, 0x7C84F87C,  0x7799EE77, 0x7B8DF67B, 0xF20DFFF2, 0x6BBDD66B,  0x6FB1DE6F, 0xC55491C5,
   1104 	0x30506030, 0x01030201,  0x67A9CE67, 0x2B7D562B, 0xFE19E7FE, 0xD762B5D7,  0xABE64DAB, 0x769AEC76,
   1105 	0xCA458FCA, 0x829D1F82,  0xC94089C9, 0x7D87FA7D, 0xFA15EFFA, 0x59EBB259,  0x47C98E47, 0xF00BFBF0,
   1106 	0xADEC41AD, 0xD467B3D4,  0xA2FD5FA2, 0xAFEA45AF, 0x9CBF239C, 0xA4F753A4,  0x7296E472, 0xC05B9BC0,
   1107 	0xB7C275B7, 0xFD1CE1FD,  0x93AE3D93, 0x266A4C26, 0x365A6C36, 0x3F417E3F,  0xF702F5F7, 0xCC4F83CC,
   1108 	0x345C6834, 0xA5F451A5,  0xE534D1E5, 0xF108F9F1, 0x7193E271, 0xD873ABD8,  0x31536231, 0x153F2A15,
   1109 	0x040C0804, 0xC75295C7,  0x23654623, 0xC35E9DC3, 0x18283018, 0x96A13796,  0x050F0A05, 0x9AB52F9A,
   1110 	0x07090E07, 0x12362412,  0x809B1B80, 0xE23DDFE2, 0xEB26CDEB, 0x27694E27,  0xB2CD7FB2, 0x759FEA75,
   1111 	0x091B1209, 0x839E1D83,  0x2C74582C, 0x1A2E341A, 0x1B2D361B, 0x6EB2DC6E,  0x5AEEB45A, 0xA0FB5BA0,
   1112 	0x52F6A452, 0x3B4D763B,  0xD661B7D6, 0xB3CE7DB3, 0x297B5229, 0xE33EDDE3,  0x2F715E2F, 0x84971384,
   1113 	0x53F5A653, 0xD168B9D1,  0x00000000, 0xED2CC1ED, 0x20604020, 0xFC1FE3FC,  0xB1C879B1, 0x5BEDB65B,
   1114 	0x6ABED46A, 0xCB468DCB,  0xBED967BE, 0x394B7239, 0x4ADE944A, 0x4CD4984C,  0x58E8B058, 0xCF4A85CF,
   1115 	0xD06BBBD0, 0xEF2AC5EF,  0xAAE54FAA, 0xFB16EDFB, 0x43C58643, 0x4DD79A4D,  0x33556633, 0x85941185,
   1116 	0x45CF8A45, 0xF910E9F9,  0x02060402, 0x7F81FE7F, 0x50F0A050, 0x3C44783C,  0x9FBA259F, 0xA8E34BA8,
   1117 	0x51F3A251, 0xA3FE5DA3,  0x40C08040, 0x8F8A058F, 0x92AD3F92, 0x9DBC219D,  0x38487038, 0xF504F1F5,
   1118 	0xBCDF63BC, 0xB6C177B6,  0xDA75AFDA, 0x21634221, 0x10302010, 0xFF1AE5FF,  0xF30EFDF3, 0xD26DBFD2,
   1119 	0xCD4C81CD, 0x0C14180C,  0x13352613, 0xEC2FC3EC, 0x5FE1BE5F, 0x97A23597,  0x44CC8844, 0x17392E17,
   1120 	0xC45793C4, 0xA7F255A7,  0x7E82FC7E, 0x3D477A3D, 0x64ACC864, 0x5DE7BA5D,  0x192B3219, 0x7395E673,
   1121 	0x60A0C060, 0x81981981,  0x4FD19E4F, 0xDC7FA3DC, 0x22664422, 0x2A7E542A,  0x90AB3B90, 0x88830B88,
   1122 	0x46CA8C46, 0xEE29C7EE,  0xB8D36BB8, 0x143C2814, 0xDE79A7DE, 0x5EE2BC5E,  0x0B1D160B, 0xDB76ADDB,
   1123 	0xE03BDBE0, 0x32566432,  0x3A4E743A, 0x0A1E140A, 0x49DB9249, 0x060A0C06,  0x246C4824, 0x5CE4B85C,
   1124 	0xC25D9FC2, 0xD36EBDD3,  0xACEF43AC, 0x62A6C462, 0x91A83991, 0x95A43195,  0xE437D3E4, 0x798BF279,
   1125 	0xE732D5E7, 0xC8438BC8,  0x37596E37, 0x6DB7DA6D, 0x8D8C018D, 0xD564B1D5,  0x4ED29C4E, 0xA9E049A9,
   1126 	0x6CB4D86C, 0x56FAAC56,  0xF407F3F4, 0xEA25CFEA, 0x65AFCA65, 0x7A8EF47A,  0xAEE947AE, 0x08181008,
   1127 	0xBAD56FBA, 0x7888F078,  0x256F4A25, 0x2E725C2E, 0x1C24381C, 0xA6F157A6,  0xB4C773B4, 0xC65197C6,
   1128 	0xE823CBE8, 0xDD7CA1DD,  0x749CE874, 0x1F213E1F, 0x4BDD964B, 0xBDDC61BD,  0x8B860D8B, 0x8A850F8A,
   1129 	0x7090E070, 0x3E427C3E,  0xB5C471B5, 0x66AACC66, 0x48D89048, 0x03050603,  0xF601F7F6, 0x0E121C0E,
   1130 	0x61A3C261, 0x355F6A35,  0x57F9AE57, 0xB9D069B9, 0x86911786, 0xC15899C1,  0x1D273A1D, 0x9EB9279E,
   1131 	0xE138D9E1, 0xF813EBF8,  0x98B32B98, 0x11332211, 0x69BBD269, 0xD970A9D9,  0x8E89078E, 0x94A73394,
   1132 	0x9BB62D9B, 0x1E223C1E,  0x87921587, 0xE920C9E9, 0xCE4987CE, 0x55FFAA55,  0x28785028, 0xDF7AA5DF,
   1133 	0x8C8F038C, 0xA1F859A1,  0x89800989, 0x0D171A0D, 0xBFDA65BF, 0xE631D7E6,  0x42C68442, 0x68B8D068,
   1134 	0x41C38241, 0x99B02999,  0x2D775A2D, 0x0F111E0F, 0xB0CB7BB0, 0x54FCA854,  0xBBD66DBB, 0x163A2C16,
   1135 };
   1136 
   1137 /* Corresponds to _T0[256] */
   1138 unsigned int mtpz_aes_ft3[] =
   1139 {
   1140 	0xC66363A5, 0xF87C7C84,  0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD,  0xDE6F6FB1, 0x91C5C554,
   1141 	0x60303050, 0x02010103,  0xCE6767A9, 0x562B2B7D, 0xE7FEFE19, 0xB5D7D762,  0x4DABABE6, 0xEC76769A,
   1142 	0x8FCACA45, 0x1F82829D,  0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB,  0x8E4747C9, 0xFBF0F00B,
   1143 	0x41ADADEC, 0xB3D4D467,  0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7,  0xE4727296, 0x9BC0C05B,
   1144 	0x75B7B7C2, 0xE1FDFD1C,  0x3D9393AE, 0x4C26266A, 0x6C36365A, 0x7E3F3F41,  0xF5F7F702, 0x83CCCC4F,
   1145 	0x6834345C, 0x51A5A5F4,  0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873,  0x62313153, 0x2A15153F,
   1146 	0x0804040C, 0x95C7C752,  0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1,  0x0A05050F, 0x2F9A9AB5,
   1147 	0x0E070709, 0x24121236,  0x1B80809B, 0xDFE2E23D, 0xCDEBEB26, 0x4E272769,  0x7FB2B2CD, 0xEA75759F,
   1148 	0x1209091B, 0x1D83839E,  0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2,  0xB45A5AEE, 0x5BA0A0FB,
   1149 	0xA45252F6, 0x763B3B4D,  0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E,  0x5E2F2F71, 0x13848497,
   1150 	0xA65353F5, 0xB9D1D168,  0x00000000, 0xC1EDED2C, 0x40202060, 0xE3FCFC1F,  0x79B1B1C8, 0xB65B5BED,
   1151 	0xD46A6ABE, 0x8DCBCB46,  0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4,  0xB05858E8, 0x85CFCF4A,
   1152 	0xBBD0D06B, 0xC5EFEF2A,  0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7,  0x66333355, 0x11858594,
   1153 	0x8A4545CF, 0xE9F9F910,  0x04020206, 0xFE7F7F81, 0xA05050F0, 0x783C3C44,  0x259F9FBA, 0x4BA8A8E3,
   1154 	0xA25151F3, 0x5DA3A3FE,  0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC,  0x70383848, 0xF1F5F504,
   1155 	0x63BCBCDF, 0x77B6B6C1,  0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A,  0xFDF3F30E, 0xBFD2D26D,
   1156 	0x81CDCD4C, 0x180C0C14,  0x26131335, 0xC3ECEC2F, 0xBE5F5FE1, 0x359797A2,  0x884444CC, 0x2E171739,
   1157 	0x93C4C457, 0x55A7A7F2,  0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7,  0x3219192B, 0xE6737395,
   1158 	0xC06060A0, 0x19818198,  0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E,  0x3B9090AB, 0x0B888883,
   1159 	0x8C4646CA, 0xC7EEEE29,  0x6BB8B8D3, 0x2814143C, 0xA7DEDE79, 0xBC5E5EE2,  0x160B0B1D, 0xADDBDB76,
   1160 	0xDBE0E03B, 0x64323256,  0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A,  0x4824246C, 0xB85C5CE4,
   1161 	0x9FC2C25D, 0xBDD3D36E,  0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4,  0xD3E4E437, 0xF279798B,
   1162 	0xD5E7E732, 0x8BC8C843,  0x6E373759, 0xDA6D6DB7, 0x018D8D8C, 0xB1D5D564,  0x9C4E4ED2, 0x49A9A9E0,
   1163 	0xD86C6CB4, 0xAC5656FA,  0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E,  0x47AEAEE9, 0x10080818,
   1164 	0x6FBABAD5, 0xF0787888,  0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1,  0x73B4B4C7, 0x97C6C651,
   1165 	0xCBE8E823, 0xA1DDDD7C,  0xE874749C, 0x3E1F1F21, 0x964B4BDD, 0x61BDBDDC,  0x0D8B8B86, 0x0F8A8A85,
   1166 	0xE0707090, 0x7C3E3E42,  0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305,  0xF7F6F601, 0x1C0E0E12,
   1167 	0xC26161A3, 0x6A35355F,  0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158,  0x3A1D1D27, 0x279E9EB9,
   1168 	0xD9E1E138, 0xEBF8F813,  0x2B9898B3, 0x22111133, 0xD26969BB, 0xA9D9D970,  0x078E8E89, 0x339494A7,
   1169 	0x2D9B9BB6, 0x3C1E1E22,  0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF,  0x50282878, 0xA5DFDF7A,
   1170 	0x038C8C8F, 0x59A1A1F8,  0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631,  0x844242C6, 0xD06868B8,
   1171 	0x824141C3, 0x299999B0,  0x5A2D2D77, 0x1E0F0F11, 0x7BB0B0CB, 0xA85454FC,  0x6DBBBBD6, 0x2C16163A,
   1172 };
   1173 
   1174 /* Corresponds to _T1[256] */
   1175 unsigned int mtpz_aes_ft4[] =
   1176 {
   1177 	0xA5C66363, 0x84F87C7C,  0x99EE7777, 0x8DF67B7B, 0x0DFFF2F2, 0xBDD66B6B,  0xB1DE6F6F, 0x5491C5C5,
   1178 	0x50603030, 0x03020101,  0xA9CE6767, 0x7D562B2B, 0x19E7FEFE, 0x62B5D7D7,  0xE64DABAB, 0x9AEC7676,
   1179 	0x458FCACA, 0x9D1F8282,  0x4089C9C9, 0x87FA7D7D, 0x15EFFAFA, 0xEBB25959,  0xC98E4747, 0x0BFBF0F0,
   1180 	0xEC41ADAD, 0x67B3D4D4,  0xFD5FA2A2, 0xEA45AFAF, 0xBF239C9C, 0xF753A4A4,  0x96E47272, 0x5B9BC0C0,
   1181 	0xC275B7B7, 0x1CE1FDFD,  0xAE3D9393, 0x6A4C2626, 0x5A6C3636, 0x417E3F3F,  0x02F5F7F7, 0x4F83CCCC,
   1182 	0x5C683434, 0xF451A5A5,  0x34D1E5E5, 0x08F9F1F1, 0x93E27171, 0x73ABD8D8,  0x53623131, 0x3F2A1515,
   1183 	0x0C080404, 0x5295C7C7,  0x65462323, 0x5E9DC3C3, 0x28301818, 0xA1379696,  0x0F0A0505, 0xB52F9A9A,
   1184 	0x090E0707, 0x36241212,  0x9B1B8080, 0x3DDFE2E2, 0x26CDEBEB, 0x694E2727,  0xCD7FB2B2, 0x9FEA7575,
   1185 	0x1B120909, 0x9E1D8383,  0x74582C2C, 0x2E341A1A, 0x2D361B1B, 0xB2DC6E6E,  0xEEB45A5A, 0xFB5BA0A0,
   1186 	0xF6A45252, 0x4D763B3B,  0x61B7D6D6, 0xCE7DB3B3, 0x7B522929, 0x3EDDE3E3,  0x715E2F2F, 0x97138484,
   1187 	0xF5A65353, 0x68B9D1D1,  0x00000000, 0x2CC1EDED, 0x60402020, 0x1FE3FCFC,  0xC879B1B1, 0xEDB65B5B,
   1188 	0xBED46A6A, 0x468DCBCB,  0xD967BEBE, 0x4B723939, 0xDE944A4A, 0xD4984C4C,  0xE8B05858, 0x4A85CFCF,
   1189 	0x6BBBD0D0, 0x2AC5EFEF,  0xE54FAAAA, 0x16EDFBFB, 0xC5864343, 0xD79A4D4D,  0x55663333, 0x94118585,
   1190 	0xCF8A4545, 0x10E9F9F9,  0x06040202, 0x81FE7F7F, 0xF0A05050, 0x44783C3C,  0xBA259F9F, 0xE34BA8A8,
   1191 	0xF3A25151, 0xFE5DA3A3,  0xC0804040, 0x8A058F8F, 0xAD3F9292, 0xBC219D9D,  0x48703838, 0x04F1F5F5,
   1192 	0xDF63BCBC, 0xC177B6B6,  0x75AFDADA, 0x63422121, 0x30201010, 0x1AE5FFFF,  0x0EFDF3F3, 0x6DBFD2D2,
   1193 	0x4C81CDCD, 0x14180C0C,  0x35261313, 0x2FC3ECEC, 0xE1BE5F5F, 0xA2359797,  0xCC884444, 0x392E1717,
   1194 	0x5793C4C4, 0xF255A7A7,  0x82FC7E7E, 0x477A3D3D, 0xACC86464, 0xE7BA5D5D,  0x2B321919, 0x95E67373,
   1195 	0xA0C06060, 0x98198181,  0xD19E4F4F, 0x7FA3DCDC, 0x66442222, 0x7E542A2A,  0xAB3B9090, 0x830B8888,
   1196 	0xCA8C4646, 0x29C7EEEE,  0xD36BB8B8, 0x3C281414, 0x79A7DEDE, 0xE2BC5E5E,  0x1D160B0B, 0x76ADDBDB,
   1197 	0x3BDBE0E0, 0x56643232,  0x4E743A3A, 0x1E140A0A, 0xDB924949, 0x0A0C0606,  0x6C482424, 0xE4B85C5C,
   1198 	0x5D9FC2C2, 0x6EBDD3D3,  0xEF43ACAC, 0xA6C46262, 0xA8399191, 0xA4319595,  0x37D3E4E4, 0x8BF27979,
   1199 	0x32D5E7E7, 0x438BC8C8,  0x596E3737, 0xB7DA6D6D, 0x8C018D8D, 0x64B1D5D5,  0xD29C4E4E, 0xE049A9A9,
   1200 	0xB4D86C6C, 0xFAAC5656,  0x07F3F4F4, 0x25CFEAEA, 0xAFCA6565, 0x8EF47A7A,  0xE947AEAE, 0x18100808,
   1201 	0xD56FBABA, 0x88F07878,  0x6F4A2525, 0x725C2E2E, 0x24381C1C, 0xF157A6A6,  0xC773B4B4, 0x5197C6C6,
   1202 	0x23CBE8E8, 0x7CA1DDDD,  0x9CE87474, 0x213E1F1F, 0xDD964B4B, 0xDC61BDBD,  0x860D8B8B, 0x850F8A8A,
   1203 	0x90E07070, 0x427C3E3E,  0xC471B5B5, 0xAACC6666, 0xD8904848, 0x05060303,  0x01F7F6F6, 0x121C0E0E,
   1204 	0xA3C26161, 0x5F6A3535,  0xF9AE5757, 0xD069B9B9, 0x91178686, 0x5899C1C1,  0x273A1D1D, 0xB9279E9E,
   1205 	0x38D9E1E1, 0x13EBF8F8,  0xB32B9898, 0x33221111, 0xBBD26969, 0x70A9D9D9,  0x89078E8E, 0xA7339494,
   1206 	0xB62D9B9B, 0x223C1E1E,  0x92158787, 0x20C9E9E9, 0x4987CECE, 0xFFAA5555,  0x78502828, 0x7AA5DFDF,
   1207 	0x8F038C8C, 0xF859A1A1,  0x80098989, 0x171A0D0D, 0xDA65BFBF, 0x31D7E6E6,  0xC6844242, 0xB8D06868,
   1208 	0xC3824141, 0xB0299999,  0x775A2D2D, 0x111E0F0F, 0xCB7BB0B0, 0xFCA85454,  0xD66DBBBB, 0x3A2C1616,
   1209 };
   1210 
   1211 /* Corresponds to _TInv3[256] */
   1212 unsigned int mtpz_aes_rt1[] =
   1213 {
   1214 	0xF4A75051, 0x4165537E,  0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F,  0xFA58ABAC, 0xE303934B,
   1215 	0x30FA5520, 0x766DF6AD,  0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5,  0x35448026, 0x62A38FB5,
   1216 	0xB15A49DE, 0xBA1B6725,  0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281,  0x4697A38D, 0xD3F9C66B,
   1217 	0x8F5FE703, 0x929C9515,  0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358,  0xE0692949, 0xC9C8448E,
   1218 	0xC2896A75, 0x8E7978F4,  0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0,  0x20AC66C9, 0xCE3AB47D,
   1219 	0xDF4A1863, 0x1A3182E5,  0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB,  0x81A01CFE, 0x082B94F9,
   1220 	0x48685870, 0x45FD198F,  0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272,  0x1F8F57E3, 0x55AB2A66,
   1221 	0xEB2807B2, 0xB5C2032F,  0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223,  0x036ABA02, 0x16825CED,
   1222 	0xCF1C2B8A, 0x79B492A7,  0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506,  0x34621FD1, 0xA6FE8AC4,
   1223 	0x2E539D34, 0xF355A0A2,  0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40,  0x719F065E, 0x6E1051BD,
   1224 	0x218AF93E, 0xDD063D96,  0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571,  0x06D46F04, 0x5015FF60,
   1225 	0x98FB2419, 0xBDE997D6,  0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807,  0x195B38E7, 0xC8EEDB79,
   1226 	0x7C0A47A1, 0x420FE97C,  0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832,  0x1170AC1E, 0x5A724E6C,
   1227 	0x0EFFFBFD, 0x8538560F,  0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168,  0x5B54D19B, 0x362E3A24,
   1228 	0x0A67B10C, 0x57E70F93,  0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261,  0x774B695A, 0x121A161C,
   1229 	0x93BA0AE2, 0xA02AE5C0,  0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2,  0xB6A8B92D, 0x1EA9C814,
   1230 	0xF1198557, 0x75074CAF,  0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C,  0x663BC544, 0xFB7E345B,
   1231 	0x4329768B, 0x23C6DCCB,  0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042,  0x97224013, 0xC6112084,
   1232 	0x4A247D85, 0xBB3DF8D2,  0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC,  0x8652EC0D, 0xC1E3D077,
   1233 	0xB3166C2B, 0x70B999A9,  0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0,  0x7D2CD856, 0x3390EF22,
   1234 	0x494EC787, 0x38D1C1D9,  0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5,  0xB78E26DA, 0xADBFA43F,
   1235 	0x3A9DE42C, 0x78920D50,  0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890,  0x39F75E2E, 0xC3AFF582,
   1236 	0x5D80BE9F, 0xD0937C69,  0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710,  0x9C636EE8, 0x3BBB7BDB,
   1237 	0x267809CD, 0x5918F46E,  0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA,  0xBCCF0821, 0x15E8E6EF,
   1238 	0xE79BD9BA, 0x6F36CE4A,  0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A,  0xA59430C6, 0xA266C035,
   1239 	0x4EBC3774, 0x82CAA6FC,  0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741,  0xCD500E7F, 0x91F62F17,
   1240 	0x4DD68D76, 0xEFB04D43,  0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C,  0x2C1FB8C1, 0x65517F46,
   1241 	0x5EEA049D, 0x8C355D01,  0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292,  0x105633E9, 0xD647136D,
   1242 	0xD7618C9A, 0xA10C7A37,  0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7,  0x1CE5EDE1, 0x47B13C7A,
   1243 	0xD2DF599C, 0xF2733F55,  0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F,  0x3D6F14DF, 0x44DB8678,
   1244 	0xAFF381CA, 0x68C43EB9,  0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC,  0x3C498B28, 0x0D9541FF,
   1245 	0xA8017139, 0x0CB3DE08,  0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5,  0x6C5C7448, 0xB85742D0
   1246 };
   1247 
   1248 /* Corresponds to _TInv2[256] */
   1249 unsigned int mtpz_aes_rt2[] =
   1250 {
   1251 	0xA75051F4, 0x65537E41,  0xA4C31A17, 0x5E963A27, 0x6BCB3BAB, 0x45F11F9D,  0x58ABACFA, 0x03934BE3,
   1252 	0xFA552030, 0x6DF6AD76,  0x769188CC, 0x4C25F502, 0xD7FC4FE5, 0xCBD7C52A,  0x44802635, 0xA38FB562,
   1253 	0x5A49DEB1, 0x1B6725BA,  0x0E9845EA, 0xC0E15DFE, 0x7502C32F, 0xF012814C,  0x97A38D46, 0xF9C66BD3,
   1254 	0x5FE7038F, 0x9C951592,  0x7AEBBF6D, 0x59DA9552, 0x832DD4BE, 0x21D35874,  0x692949E0, 0xC8448EC9,
   1255 	0x896A75C2, 0x7978F48E,  0x3E6B9958, 0x71DD27B9, 0x4FB6BEE1, 0xAD17F088,  0xAC66C920, 0x3AB47DCE,
   1256 	0x4A1863DF, 0x3182E51A,  0x33609751, 0x7F456253, 0x77E0B164, 0xAE84BB6B,  0xA01CFE81, 0x2B94F908,
   1257 	0x68587048, 0xFD198F45,  0x6C8794DE, 0xF8B7527B, 0xD323AB73, 0x02E2724B,  0x8F57E31F, 0xAB2A6655,
   1258 	0x2807B2EB, 0xC2032FB5,  0x7B9A86C5, 0x08A5D337, 0x87F23028, 0xA5B223BF,  0x6ABA0203, 0x825CED16,
   1259 	0x1C2B8ACF, 0xB492A779,  0xF2F0F307, 0xE2A14E69, 0xF4CD65DA, 0xBED50605,  0x621FD134, 0xFE8AC4A6,
   1260 	0x539D342E, 0x55A0A2F3,  0xE132058A, 0xEB75A4F6, 0xEC390B83, 0xEFAA4060,  0x9F065E71, 0x1051BD6E,
   1261 	0x8AF93E21, 0x063D96DD,  0x05AEDD3E, 0xBD464DE6, 0x8DB59154, 0x5D0571C4,  0xD46F0406, 0x15FF6050,
   1262 	0xFB241998, 0xE997D6BD,  0x43CC8940, 0x9E7767D9, 0x42BDB0E8, 0x8B880789,  0x5B38E719, 0xEEDB79C8,
   1263 	0x0A47A17C, 0x0FE97C42,  0x1EC9F884, 0x00000000, 0x86830980, 0xED48322B,  0x70AC1E11, 0x724E6C5A,
   1264 	0xFFFBFD0E, 0x38560F85,  0xD51E3DAE, 0x3927362D, 0xD9640A0F, 0xA621685C,  0x54D19B5B, 0x2E3A2436,
   1265 	0x67B10C0A, 0xE70F9357,  0x96D2B4EE, 0x919E1B9B, 0xC54F80C0, 0x20A261DC,  0x4B695A77, 0x1A161C12,
   1266 	0xBA0AE293, 0x2AE5C0A0,  0xE0433C22, 0x171D121B, 0x0D0B0E09, 0xC7ADF28B,  0xA8B92DB6, 0xA9C8141E,
   1267 	0x198557F1, 0x074CAF75,  0xDDBBEE99, 0x60FDA37F, 0x269FF701, 0xF5BC5C72,  0x3BC54466, 0x7E345BFB,
   1268 	0x29768B43, 0xC6DCCB23,  0xFC68B6ED, 0xF163B8E4, 0xDCCAD731, 0x85104263,  0x22401397, 0x112084C6,
   1269 	0x247D854A, 0x3DF8D2BB,  0x3211AEF9, 0xA16DC729, 0x2F4B1D9E, 0x30F3DCB2,  0x52EC0D86, 0xE3D077C1,
   1270 	0x166C2BB3, 0xB999A970,  0x48FA1194, 0x642247E9, 0x8CC4A8FC, 0x3F1AA0F0,  0x2CD8567D, 0x90EF2233,
   1271 	0x4EC78749, 0xD1C1D938,  0xA2FE8CCA, 0x0B3698D4, 0x81CFA6F5, 0xDE28A57A,  0x8E26DAB7, 0xBFA43FAD,
   1272 	0x9DE42C3A, 0x920D5078,  0xCC9B6A5F, 0x4662547E, 0x13C2F68D, 0xB8E890D8,  0xF75E2E39, 0xAFF582C3,
   1273 	0x80BE9F5D, 0x937C69D0,  0x2DA96FD5, 0x12B3CF25, 0x993BC8AC, 0x7DA71018,  0x636EE89C, 0xBB7BDB3B,
   1274 	0x7809CD26, 0x18F46E59,  0xB701EC9A, 0x9AA8834F, 0x6E65E695, 0xE67EAAFF,  0xCF0821BC, 0xE8E6EF15,
   1275 	0x9BD9BAE7, 0x36CE4A6F,  0x09D4EA9F, 0x7CD629B0, 0xB2AF31A4, 0x23312A3F,  0x9430C6A5, 0x66C035A2,
   1276 	0xBC37744E, 0xCAA6FC82,  0xD0B0E090, 0xD81533A7, 0x984AF104, 0xDAF741EC,  0x500E7FCD, 0xF62F1791,
   1277 	0xD68D764D, 0xB04D43EF,  0x4D54CCAA, 0x04DFE496, 0xB5E39ED1, 0x881B4C6A,  0x1FB8C12C, 0x517F4665,
   1278 	0xEA049D5E, 0x355D018C,  0x7473FA87, 0x412EFB0B, 0x1D5AB367, 0xD25292DB,  0x5633E910, 0x47136DD6,
   1279 	0x618C9AD7, 0x0C7A37A1,  0x148E59F8, 0x3C89EB13, 0x27EECEA9, 0xC935B761,  0xE5EDE11C, 0xB13C7A47,
   1280 	0xDF599CD2, 0x733F55F2,  0xCE791814, 0x37BF73C7, 0xCDEA53F7, 0xAA5B5FFD,  0x6F14DF3D, 0xDB867844,
   1281 	0xF381CAAF, 0xC43EB968,  0x342C3824, 0x405FC2A3, 0xC372161D, 0x250CBCE2,  0x498B283C, 0x9541FF0D,
   1282 	0x017139A8, 0xB3DE080C,  0xE49CD8B4, 0xC1906456, 0x84617BCB, 0xB670D532,  0x5C74486C, 0x5742D0B8
   1283 };
   1284 
   1285 /* Corresponds to _TInv0[256] */
   1286 unsigned int mtpz_aes_rt3[] =
   1287 {
   1288 	0x51F4A750, 0x7E416553,  0x1A17A4C3, 0x3A275E96, 0x3BAB6BCB, 0x1F9D45F1,  0xACFA58AB, 0x4BE30393,
   1289 	0x2030FA55, 0xAD766DF6,  0x88CC7691, 0xF5024C25, 0x4FE5D7FC, 0xC52ACBD7,  0x26354480, 0xB562A38F,
   1290 	0xDEB15A49, 0x25BA1B67,  0x45EA0E98, 0x5DFEC0E1, 0xC32F7502, 0x814CF012,  0x8D4697A3, 0x6BD3F9C6,
   1291 	0x038F5FE7, 0x15929C95,  0xBF6D7AEB, 0x955259DA, 0xD4BE832D, 0x587421D3,  0x49E06929, 0x8EC9C844,
   1292 	0x75C2896A, 0xF48E7978,  0x99583E6B, 0x27B971DD, 0xBEE14FB6, 0xF088AD17,  0xC920AC66, 0x7DCE3AB4,
   1293 	0x63DF4A18, 0xE51A3182,  0x97513360, 0x62537F45, 0xB16477E0, 0xBB6BAE84,  0xFE81A01C, 0xF9082B94,
   1294 	0x70486858, 0x8F45FD19,  0x94DE6C87, 0x527BF8B7, 0xAB73D323, 0x724B02E2,  0xE31F8F57, 0x6655AB2A,
   1295 	0xB2EB2807, 0x2FB5C203,  0x86C57B9A, 0xD33708A5, 0x302887F2, 0x23BFA5B2,  0x02036ABA, 0xED16825C,
   1296 	0x8ACF1C2B, 0xA779B492,  0xF307F2F0, 0x4E69E2A1, 0x65DAF4CD, 0x0605BED5,  0xD134621F, 0xC4A6FE8A,
   1297 	0x342E539D, 0xA2F355A0,  0x058AE132, 0xA4F6EB75, 0x0B83EC39, 0x4060EFAA,  0x5E719F06, 0xBD6E1051,
   1298 	0x3E218AF9, 0x96DD063D,  0xDD3E05AE, 0x4DE6BD46, 0x91548DB5, 0x71C45D05,  0x0406D46F, 0x605015FF,
   1299 	0x1998FB24, 0xD6BDE997,  0x894043CC, 0x67D99E77, 0xB0E842BD, 0x07898B88,  0xE7195B38, 0x79C8EEDB,
   1300 	0xA17C0A47, 0x7C420FE9,  0xF8841EC9, 0x00000000, 0x09808683, 0x322BED48,  0x1E1170AC, 0x6C5A724E,
   1301 	0xFD0EFFFB, 0x0F853856,  0x3DAED51E, 0x362D3927, 0x0A0FD964, 0x685CA621,  0x9B5B54D1, 0x24362E3A,
   1302 	0x0C0A67B1, 0x9357E70F,  0xB4EE96D2, 0x1B9B919E, 0x80C0C54F, 0x61DC20A2,  0x5A774B69, 0x1C121A16,
   1303 	0xE293BA0A, 0xC0A02AE5,  0x3C22E043, 0x121B171D, 0x0E090D0B, 0xF28BC7AD,  0x2DB6A8B9, 0x141EA9C8,
   1304 	0x57F11985, 0xAF75074C,  0xEE99DDBB, 0xA37F60FD, 0xF701269F, 0x5C72F5BC,  0x44663BC5, 0x5BFB7E34,
   1305 	0x8B432976, 0xCB23C6DC,  0xB6EDFC68, 0xB8E4F163, 0xD731DCCA, 0x42638510,  0x13972240, 0x84C61120,
   1306 	0x854A247D, 0xD2BB3DF8,  0xAEF93211, 0xC729A16D, 0x1D9E2F4B, 0xDCB230F3,  0x0D8652EC, 0x77C1E3D0,
   1307 	0x2BB3166C, 0xA970B999,  0x119448FA, 0x47E96422, 0xA8FC8CC4, 0xA0F03F1A,  0x567D2CD8, 0x223390EF,
   1308 	0x87494EC7, 0xD938D1C1,  0x8CCAA2FE, 0x98D40B36, 0xA6F581CF, 0xA57ADE28,  0xDAB78E26, 0x3FADBFA4,
   1309 	0x2C3A9DE4, 0x5078920D,  0x6A5FCC9B, 0x547E4662, 0xF68D13C2, 0x90D8B8E8,  0x2E39F75E, 0x82C3AFF5,
   1310 	0x9F5D80BE, 0x69D0937C,  0x6FD52DA9, 0xCF2512B3, 0xC8AC993B, 0x10187DA7,  0xE89C636E, 0xDB3BBB7B,
   1311 	0xCD267809, 0x6E5918F4,  0xEC9AB701, 0x834F9AA8, 0xE6956E65, 0xAAFFE67E,  0x21BCCF08, 0xEF15E8E6,
   1312 	0xBAE79BD9, 0x4A6F36CE,  0xEA9F09D4, 0x29B07CD6, 0x31A4B2AF, 0x2A3F2331,  0xC6A59430, 0x35A266C0,
   1313 	0x744EBC37, 0xFC82CAA6,  0xE090D0B0, 0x33A7D815, 0xF104984A, 0x41ECDAF7,  0x7FCD500E, 0x1791F62F,
   1314 	0x764DD68D, 0x43EFB04D,  0xCCAA4D54, 0xE49604DF, 0x9ED1B5E3, 0x4C6A881B,  0xC12C1FB8, 0x4665517F,
   1315 	0x9D5EEA04, 0x018C355D,  0xFA877473, 0xFB0B412E, 0xB3671D5A, 0x92DBD252,  0xE9105633, 0x6DD64713,
   1316 	0x9AD7618C, 0x37A10C7A,  0x59F8148E, 0xEB133C89, 0xCEA927EE, 0xB761C935,  0xE11CE5ED, 0x7A47B13C,
   1317 	0x9CD2DF59, 0x55F2733F,  0x1814CE79, 0x73C737BF, 0x53F7CDEA, 0x5FFDAA5B,  0xDF3D6F14, 0x7844DB86,
   1318 	0xCAAFF381, 0xB968C43E,  0x3824342C, 0xC2A3405F, 0x161DC372, 0xBCE2250C,  0x283C498B, 0xFF0D9541,
   1319 	0x39A80171, 0x080CB3DE,  0xD8B4E49C, 0x6456C190, 0x7BCB8461, 0xD532B670,  0x486C5C74, 0xD0B85742
   1320 };
   1321 
   1322 /* Corresponds to _TInv1[256] */
   1323 unsigned int mtpz_aes_rt4[] =
   1324 {
   1325 	0x5051F4A7, 0x537E4165,  0xC31A17A4, 0x963A275E, 0xCB3BAB6B, 0xF11F9D45,  0xABACFA58, 0x934BE303,
   1326 	0x552030FA, 0xF6AD766D,  0x9188CC76, 0x25F5024C, 0xFC4FE5D7, 0xD7C52ACB,  0x80263544, 0x8FB562A3,
   1327 	0x49DEB15A, 0x6725BA1B,  0x9845EA0E, 0xE15DFEC0, 0x02C32F75, 0x12814CF0,  0xA38D4697, 0xC66BD3F9,
   1328 	0xE7038F5F, 0x9515929C,  0xEBBF6D7A, 0xDA955259, 0x2DD4BE83, 0xD3587421,  0x2949E069, 0x448EC9C8,
   1329 	0x6A75C289, 0x78F48E79,  0x6B99583E, 0xDD27B971, 0xB6BEE14F, 0x17F088AD,  0x66C920AC, 0xB47DCE3A,
   1330 	0x1863DF4A, 0x82E51A31,  0x60975133, 0x4562537F, 0xE0B16477, 0x84BB6BAE,  0x1CFE81A0, 0x94F9082B,
   1331 	0x58704868, 0x198F45FD,  0x8794DE6C, 0xB7527BF8, 0x23AB73D3, 0xE2724B02,  0x57E31F8F, 0x2A6655AB,
   1332 	0x07B2EB28, 0x032FB5C2,  0x9A86C57B, 0xA5D33708, 0xF2302887, 0xB223BFA5,  0xBA02036A, 0x5CED1682,
   1333 	0x2B8ACF1C, 0x92A779B4,  0xF0F307F2, 0xA14E69E2, 0xCD65DAF4, 0xD50605BE,  0x1FD13462, 0x8AC4A6FE,
   1334 	0x9D342E53, 0xA0A2F355,  0x32058AE1, 0x75A4F6EB, 0x390B83EC, 0xAA4060EF,  0x065E719F, 0x51BD6E10,
   1335 	0xF93E218A, 0x3D96DD06,  0xAEDD3E05, 0x464DE6BD, 0xB591548D, 0x0571C45D,  0x6F0406D4, 0xFF605015,
   1336 	0x241998FB, 0x97D6BDE9,  0xCC894043, 0x7767D99E, 0xBDB0E842, 0x8807898B,  0x38E7195B, 0xDB79C8EE,
   1337 	0x47A17C0A, 0xE97C420F,  0xC9F8841E, 0x00000000, 0x83098086, 0x48322BED,  0xAC1E1170, 0x4E6C5A72,
   1338 	0xFBFD0EFF, 0x560F8538,  0x1E3DAED5, 0x27362D39, 0x640A0FD9, 0x21685CA6,  0xD19B5B54, 0x3A24362E,
   1339 	0xB10C0A67, 0x0F9357E7,  0xD2B4EE96, 0x9E1B9B91, 0x4F80C0C5, 0xA261DC20,  0x695A774B, 0x161C121A,
   1340 	0x0AE293BA, 0xE5C0A02A,  0x433C22E0, 0x1D121B17, 0x0B0E090D, 0xADF28BC7,  0xB92DB6A8, 0xC8141EA9,
   1341 	0x8557F119, 0x4CAF7507,  0xBBEE99DD, 0xFDA37F60, 0x9FF70126, 0xBC5C72F5,  0xC544663B, 0x345BFB7E,
   1342 	0x768B4329, 0xDCCB23C6,  0x68B6EDFC, 0x63B8E4F1, 0xCAD731DC, 0x10426385,  0x40139722, 0x2084C611,
   1343 	0x7D854A24, 0xF8D2BB3D,  0x11AEF932, 0x6DC729A1, 0x4B1D9E2F, 0xF3DCB230,  0xEC0D8652, 0xD077C1E3,
   1344 	0x6C2BB316, 0x99A970B9,  0xFA119448, 0x2247E964, 0xC4A8FC8C, 0x1AA0F03F,  0xD8567D2C, 0xEF223390,
   1345 	0xC787494E, 0xC1D938D1,  0xFE8CCAA2, 0x3698D40B, 0xCFA6F581, 0x28A57ADE,  0x26DAB78E, 0xA43FADBF,
   1346 	0xE42C3A9D, 0x0D507892,  0x9B6A5FCC, 0x62547E46, 0xC2F68D13, 0xE890D8B8,  0x5E2E39F7, 0xF582C3AF,
   1347 	0xBE9F5D80, 0x7C69D093,  0xA96FD52D, 0xB3CF2512, 0x3BC8AC99, 0xA710187D,  0x6EE89C63, 0x7BDB3BBB,
   1348 	0x09CD2678, 0xF46E5918,  0x01EC9AB7, 0xA8834F9A, 0x65E6956E, 0x7EAAFFE6,  0x0821BCCF, 0xE6EF15E8,
   1349 	0xD9BAE79B, 0xCE4A6F36,  0xD4EA9F09, 0xD629B07C, 0xAF31A4B2, 0x312A3F23,  0x30C6A594, 0xC035A266,
   1350 	0x37744EBC, 0xA6FC82CA,  0xB0E090D0, 0x1533A7D8, 0x4AF10498, 0xF741ECDA,  0x0E7FCD50, 0x2F1791F6,
   1351 	0x8D764DD6, 0x4D43EFB0,  0x54CCAA4D, 0xDFE49604, 0xE39ED1B5, 0x1B4C6A88,  0xB8C12C1F, 0x7F466551,
   1352 	0x049D5EEA, 0x5D018C35,  0x73FA8774, 0x2EFB0B41, 0x5AB3671D, 0x5292DBD2,  0x33E91056, 0x136DD647,
   1353 	0x8C9AD761, 0x7A37A10C,  0x8E59F814, 0x89EB133C, 0xEECEA927, 0x35B761C9,  0xEDE11CE5, 0x3C7A47B1,
   1354 	0x599CD2DF, 0x3F55F273,  0x791814CE, 0xBF73C737, 0xEA53F7CD, 0x5B5FFDAA,  0x14DF3D6F, 0x867844DB,
   1355 	0x81CAAFF3, 0x3EB968C4,  0x2C382434, 0x5FC2A340, 0x72161DC3, 0x0CBCE225,  0x8B283C49, 0x41FF0D95,
   1356 	0x7139A801, 0xDE080CB3,  0x9CD8B4E4, 0x906456C1, 0x617BCB84, 0x70D532B6,  0x74486C5C, 0x42D0B857
   1357 };
   1358 
   1359 /* Corresponds to _IMXC1[256] */
   1360 unsigned int mtpz_aes_gb11[] =
   1361 {
   1362 	0x00000000, 0x0B0E090D,  0x161C121A, 0x1D121B17, 0x2C382434, 0x27362D39,  0x3A24362E, 0x312A3F23,
   1363 	0x58704868, 0x537E4165,  0x4E6C5A72, 0x4562537F, 0x74486C5C, 0x7F466551,  0x62547E46, 0x695A774B,
   1364 	0xB0E090D0, 0xBBEE99DD,  0xA6FC82CA, 0xADF28BC7, 0x9CD8B4E4, 0x97D6BDE9,  0x8AC4A6FE, 0x81CAAFF3,
   1365 	0xE890D8B8, 0xE39ED1B5,  0xFE8CCAA2, 0xF582C3AF, 0xC4A8FC8C, 0xCFA6F581,  0xD2B4EE96, 0xD9BAE79B,
   1366 	0x7BDB3BBB, 0x70D532B6,  0x6DC729A1, 0x66C920AC, 0x57E31F8F, 0x5CED1682,  0x41FF0D95, 0x4AF10498,
   1367 	0x23AB73D3, 0x28A57ADE,  0x35B761C9, 0x3EB968C4, 0x0F9357E7, 0x049D5EEA,  0x198F45FD, 0x12814CF0,
   1368 	0xCB3BAB6B, 0xC035A266,  0xDD27B971, 0xD629B07C, 0xE7038F5F, 0xEC0D8652,  0xF11F9D45, 0xFA119448,
   1369 	0x934BE303, 0x9845EA0E,  0x8557F119, 0x8E59F814, 0xBF73C737, 0xB47DCE3A,  0xA96FD52D, 0xA261DC20,
   1370 	0xF6AD766D, 0xFDA37F60,  0xE0B16477, 0xEBBF6D7A, 0xDA955259, 0xD19B5B54,  0xCC894043, 0xC787494E,
   1371 	0xAEDD3E05, 0xA5D33708,  0xB8C12C1F, 0xB3CF2512, 0x82E51A31, 0x89EB133C,  0x94F9082B, 0x9FF70126,
   1372 	0x464DE6BD, 0x4D43EFB0,  0x5051F4A7, 0x5B5FFDAA, 0x6A75C289, 0x617BCB84,  0x7C69D093, 0x7767D99E,
   1373 	0x1E3DAED5, 0x1533A7D8,  0x0821BCCF, 0x032FB5C2, 0x32058AE1, 0x390B83EC,  0x241998FB, 0x2F1791F6,
   1374 	0x8D764DD6, 0x867844DB,  0x9B6A5FCC, 0x906456C1, 0xA14E69E2, 0xAA4060EF,  0xB7527BF8, 0xBC5C72F5,
   1375 	0xD50605BE, 0xDE080CB3,  0xC31A17A4, 0xC8141EA9, 0xF93E218A, 0xF2302887,  0xEF223390, 0xE42C3A9D,
   1376 	0x3D96DD06, 0x3698D40B,  0x2B8ACF1C, 0x2084C611, 0x11AEF932, 0x1AA0F03F,  0x07B2EB28, 0x0CBCE225,
   1377 	0x65E6956E, 0x6EE89C63,  0x73FA8774, 0x78F48E79, 0x49DEB15A, 0x42D0B857,  0x5FC2A340, 0x54CCAA4D,
   1378 	0xF741ECDA, 0xFC4FE5D7,  0xE15DFEC0, 0xEA53F7CD, 0xDB79C8EE, 0xD077C1E3,  0xCD65DAF4, 0xC66BD3F9,
   1379 	0xAF31A4B2, 0xA43FADBF,  0xB92DB6A8, 0xB223BFA5, 0x83098086, 0x8807898B,  0x9515929C, 0x9E1B9B91,
   1380 	0x47A17C0A, 0x4CAF7507,  0x51BD6E10, 0x5AB3671D, 0x6B99583E, 0x60975133,  0x7D854A24, 0x768B4329,
   1381 	0x1FD13462, 0x14DF3D6F,  0x09CD2678, 0x02C32F75, 0x33E91056, 0x38E7195B,  0x25F5024C, 0x2EFB0B41,
   1382 	0x8C9AD761, 0x8794DE6C,  0x9A86C57B, 0x9188CC76, 0xA0A2F355, 0xABACFA58,  0xB6BEE14F, 0xBDB0E842,
   1383 	0xD4EA9F09, 0xDFE49604,  0xC2F68D13, 0xC9F8841E, 0xF8D2BB3D, 0xF3DCB230,  0xEECEA927, 0xE5C0A02A,
   1384 	0x3C7A47B1, 0x37744EBC,  0x2A6655AB, 0x21685CA6, 0x10426385, 0x1B4C6A88,  0x065E719F, 0x0D507892,
   1385 	0x640A0FD9, 0x6F0406D4,  0x72161DC3, 0x791814CE, 0x48322BED, 0x433C22E0,  0x5E2E39F7, 0x552030FA,
   1386 	0x01EC9AB7, 0x0AE293BA,  0x17F088AD, 0x1CFE81A0, 0x2DD4BE83, 0x26DAB78E,  0x3BC8AC99, 0x30C6A594,
   1387 	0x599CD2DF, 0x5292DBD2,  0x4F80C0C5, 0x448EC9C8, 0x75A4F6EB, 0x7EAAFFE6,  0x63B8E4F1, 0x68B6EDFC,
   1388 	0xB10C0A67, 0xBA02036A,  0xA710187D, 0xAC1E1170, 0x9D342E53, 0x963A275E,  0x8B283C49, 0x80263544,
   1389 	0xE97C420F, 0xE2724B02,  0xFF605015, 0xF46E5918, 0xC544663B, 0xCE4A6F36,  0xD3587421, 0xD8567D2C,
   1390 	0x7A37A10C, 0x7139A801,  0x6C2BB316, 0x6725BA1B, 0x560F8538, 0x5D018C35,  0x40139722, 0x4B1D9E2F,
   1391 	0x2247E964, 0x2949E069,  0x345BFB7E, 0x3F55F273, 0x0E7FCD50, 0x0571C45D,  0x1863DF4A, 0x136DD647,
   1392 	0xCAD731DC, 0xC1D938D1,  0xDCCB23C6, 0xD7C52ACB, 0xE6EF15E8, 0xEDE11CE5,  0xF0F307F2, 0xFBFD0EFF,
   1393 	0x92A779B4, 0x99A970B9,  0x84BB6BAE, 0x8FB562A3, 0xBE9F5D80, 0xB591548D,  0xA8834F9A, 0xA38D4697,
   1394 };
   1395 
   1396 /* Corresponds to _IMXC0[256] */
   1397 unsigned int mtpz_aes_gb14[] =
   1398 {
   1399 	0x00000000,  0x0E090D0B,   0x1C121A16,  0x121B171D,  0x3824342C,  0x362D3927,   0x24362E3A,  0x2A3F2331,
   1400 	0x70486858,  0x7E416553,   0x6C5A724E,  0x62537F45,  0x486C5C74,  0x4665517F,   0x547E4662,  0x5A774B69,
   1401 	0xE090D0B0,  0xEE99DDBB,   0xFC82CAA6,  0xF28BC7AD,  0xD8B4E49C,  0xD6BDE997,   0xC4A6FE8A,  0xCAAFF381,
   1402 	0x90D8B8E8,  0x9ED1B5E3,   0x8CCAA2FE,  0x82C3AFF5,  0xA8FC8CC4,  0xA6F581CF,   0xB4EE96D2,  0xBAE79BD9,
   1403 	0xDB3BBB7B,  0xD532B670,   0xC729A16D,  0xC920AC66,  0xE31F8F57,  0xED16825C,   0xFF0D9541,  0xF104984A,
   1404 	0xAB73D323,  0xA57ADE28,   0xB761C935,  0xB968C43E,  0x9357E70F,  0x9D5EEA04,   0x8F45FD19,  0x814CF012,
   1405 	0x3BAB6BCB,  0x35A266C0,   0x27B971DD,  0x29B07CD6,  0x038F5FE7,  0x0D8652EC,   0x1F9D45F1,  0x119448FA,
   1406 	0x4BE30393,  0x45EA0E98,   0x57F11985,  0x59F8148E,  0x73C737BF,  0x7DCE3AB4,   0x6FD52DA9,  0x61DC20A2,
   1407 	0xAD766DF6,  0xA37F60FD,   0xB16477E0,  0xBF6D7AEB,  0x955259DA,  0x9B5B54D1,   0x894043CC,  0x87494EC7,
   1408 	0xDD3E05AE,  0xD33708A5,   0xC12C1FB8,  0xCF2512B3,  0xE51A3182,  0xEB133C89,   0xF9082B94,  0xF701269F,
   1409 	0x4DE6BD46,  0x43EFB04D,   0x51F4A750,  0x5FFDAA5B,  0x75C2896A,  0x7BCB8461,   0x69D0937C,  0x67D99E77,
   1410 	0x3DAED51E,  0x33A7D815,   0x21BCCF08,  0x2FB5C203,  0x058AE132,  0x0B83EC39,   0x1998FB24,  0x1791F62F,
   1411 	0x764DD68D,  0x7844DB86,   0x6A5FCC9B,  0x6456C190,  0x4E69E2A1,  0x4060EFAA,   0x527BF8B7,  0x5C72F5BC,
   1412 	0x0605BED5,  0x080CB3DE,   0x1A17A4C3,  0x141EA9C8,  0x3E218AF9,  0x302887F2,   0x223390EF,  0x2C3A9DE4,
   1413 	0x96DD063D,  0x98D40B36,   0x8ACF1C2B,  0x84C61120,  0xAEF93211,  0xA0F03F1A,   0xB2EB2807,  0xBCE2250C,
   1414 	0xE6956E65,  0xE89C636E,   0xFA877473,  0xF48E7978,  0xDEB15A49,  0xD0B85742,   0xC2A3405F,  0xCCAA4D54,
   1415 	0x41ECDAF7,  0x4FE5D7FC,   0x5DFEC0E1,  0x53F7CDEA,  0x79C8EEDB,  0x77C1E3D0,   0x65DAF4CD,  0x6BD3F9C6,
   1416 	0x31A4B2AF,  0x3FADBFA4,   0x2DB6A8B9,  0x23BFA5B2,  0x09808683,  0x07898B88,   0x15929C95,  0x1B9B919E,
   1417 	0xA17C0A47,  0xAF75074C,   0xBD6E1051,  0xB3671D5A,  0x99583E6B,  0x97513360,   0x854A247D,  0x8B432976,
   1418 	0xD134621F,  0xDF3D6F14,   0xCD267809,  0xC32F7502,  0xE9105633,  0xE7195B38,   0xF5024C25,  0xFB0B412E,
   1419 	0x9AD7618C,  0x94DE6C87,   0x86C57B9A,  0x88CC7691,  0xA2F355A0,  0xACFA58AB,   0xBEE14FB6,  0xB0E842BD,
   1420 	0xEA9F09D4,  0xE49604DF,   0xF68D13C2,  0xF8841EC9,  0xD2BB3DF8,  0xDCB230F3,   0xCEA927EE,  0xC0A02AE5,
   1421 	0x7A47B13C,  0x744EBC37,   0x6655AB2A,  0x685CA621,  0x42638510,  0x4C6A881B,   0x5E719F06,  0x5078920D,
   1422 	0x0A0FD964,  0x0406D46F,   0x161DC372,  0x1814CE79,  0x322BED48,  0x3C22E043,   0x2E39F75E,  0x2030FA55,
   1423 	0xEC9AB701,  0xE293BA0A,   0xF088AD17,  0xFE81A01C,  0xD4BE832D,  0xDAB78E26,   0xC8AC993B,  0xC6A59430,
   1424 	0x9CD2DF59,  0x92DBD252,   0x80C0C54F,  0x8EC9C844,  0xA4F6EB75,  0xAAFFE67E,   0xB8E4F163,  0xB6EDFC68,
   1425 	0x0C0A67B1,  0x02036ABA,   0x10187DA7,  0x1E1170AC,  0x342E539D,  0x3A275E96,   0x283C498B,  0x26354480,
   1426 	0x7C420FE9,  0x724B02E2,   0x605015FF,  0x6E5918F4,  0x44663BC5,  0x4A6F36CE,   0x587421D3,  0x567D2CD8,
   1427 	0x37A10C7A,  0x39A80171,   0x2BB3166C,  0x25BA1B67,  0x0F853856,  0x018C355D,   0x13972240,  0x1D9E2F4B,
   1428 	0x47E96422,  0x49E06929,   0x5BFB7E34,  0x55F2733F,  0x7FCD500E,  0x71C45D05,   0x63DF4A18,  0x6DD64713,
   1429 	0xD731DCCA,  0xD938D1C1,   0xCB23C6DC,  0xC52ACBD7,  0xEF15E8E6,  0xE11CE5ED,   0xF307F2F0,  0xFD0EFFFB,
   1430 	0xA779B492,  0xA970B999,   0xBB6BAE84,  0xB562A38F,  0x9F5D80BE,  0x91548DB5,   0x834F9AA8,  0x8D4697A3,
   1431 } ;
   1432 
   1433 /* Corresponds to _IMXC2[256] */
   1434 unsigned int mtpz_aes_gb13[] =
   1435 {
   1436 	0x00000000,  0x0D0B0E09,   0x1A161C12,  0x171D121B,  0x342C3824,  0x3927362D,   0x2E3A2436,  0x23312A3F,
   1437 	0x68587048,  0x65537E41,   0x724E6C5A,  0x7F456253,  0x5C74486C,  0x517F4665,   0x4662547E,  0x4B695A77,
   1438 	0xD0B0E090,  0xDDBBEE99,   0xCAA6FC82,  0xC7ADF28B,  0xE49CD8B4,  0xE997D6BD,   0xFE8AC4A6,  0xF381CAAF,
   1439 	0xB8E890D8,  0xB5E39ED1,   0xA2FE8CCA,  0xAFF582C3,  0x8CC4A8FC,  0x81CFA6F5,   0x96D2B4EE,  0x9BD9BAE7,
   1440 	0xBB7BDB3B,  0xB670D532,   0xA16DC729,  0xAC66C920,  0x8F57E31F,  0x825CED16,   0x9541FF0D,  0x984AF104,
   1441 	0xD323AB73,  0xDE28A57A,   0xC935B761,  0xC43EB968,  0xE70F9357,  0xEA049D5E,   0xFD198F45,  0xF012814C,
   1442 	0x6BCB3BAB,  0x66C035A2,   0x71DD27B9,  0x7CD629B0,  0x5FE7038F,  0x52EC0D86,   0x45F11F9D,  0x48FA1194,
   1443 	0x03934BE3,  0x0E9845EA,   0x198557F1,  0x148E59F8,  0x37BF73C7,  0x3AB47DCE,   0x2DA96FD5,  0x20A261DC,
   1444 	0x6DF6AD76,  0x60FDA37F,   0x77E0B164,  0x7AEBBF6D,  0x59DA9552,  0x54D19B5B,   0x43CC8940,  0x4EC78749,
   1445 	0x05AEDD3E,  0x08A5D337,   0x1FB8C12C,  0x12B3CF25,  0x3182E51A,  0x3C89EB13,   0x2B94F908,  0x269FF701,
   1446 	0xBD464DE6,  0xB04D43EF,   0xA75051F4,  0xAA5B5FFD,  0x896A75C2,  0x84617BCB,   0x937C69D0,  0x9E7767D9,
   1447 	0xD51E3DAE,  0xD81533A7,   0xCF0821BC,  0xC2032FB5,  0xE132058A,  0xEC390B83,   0xFB241998,  0xF62F1791,
   1448 	0xD68D764D,  0xDB867844,   0xCC9B6A5F,  0xC1906456,  0xE2A14E69,  0xEFAA4060,   0xF8B7527B,  0xF5BC5C72,
   1449 	0xBED50605,  0xB3DE080C,   0xA4C31A17,  0xA9C8141E,  0x8AF93E21,  0x87F23028,   0x90EF2233,  0x9DE42C3A,
   1450 	0x063D96DD,  0x0B3698D4,   0x1C2B8ACF,  0x112084C6,  0x3211AEF9,  0x3F1AA0F0,   0x2807B2EB,  0x250CBCE2,
   1451 	0x6E65E695,  0x636EE89C,   0x7473FA87,  0x7978F48E,  0x5A49DEB1,  0x5742D0B8,   0x405FC2A3,  0x4D54CCAA,
   1452 	0xDAF741EC,  0xD7FC4FE5,   0xC0E15DFE,  0xCDEA53F7,  0xEEDB79C8,  0xE3D077C1,   0xF4CD65DA,  0xF9C66BD3,
   1453 	0xB2AF31A4,  0xBFA43FAD,   0xA8B92DB6,  0xA5B223BF,  0x86830980,  0x8B880789,   0x9C951592,  0x919E1B9B,
   1454 	0x0A47A17C,  0x074CAF75,   0x1051BD6E,  0x1D5AB367,  0x3E6B9958,  0x33609751,   0x247D854A,  0x29768B43,
   1455 	0x621FD134,  0x6F14DF3D,   0x7809CD26,  0x7502C32F,  0x5633E910,  0x5B38E719,   0x4C25F502,  0x412EFB0B,
   1456 	0x618C9AD7,  0x6C8794DE,   0x7B9A86C5,  0x769188CC,  0x55A0A2F3,  0x58ABACFA,   0x4FB6BEE1,  0x42BDB0E8,
   1457 	0x09D4EA9F,  0x04DFE496,   0x13C2F68D,  0x1EC9F884,  0x3DF8D2BB,  0x30F3DCB2,   0x27EECEA9,  0x2AE5C0A0,
   1458 	0xB13C7A47,  0xBC37744E,   0xAB2A6655,  0xA621685C,  0x85104263,  0x881B4C6A,   0x9F065E71,  0x920D5078,
   1459 	0xD9640A0F,  0xD46F0406,   0xC372161D,  0xCE791814,  0xED48322B,  0xE0433C22,   0xF75E2E39,  0xFA552030,
   1460 	0xB701EC9A,  0xBA0AE293,   0xAD17F088,  0xA01CFE81,  0x832DD4BE,  0x8E26DAB7,   0x993BC8AC,  0x9430C6A5,
   1461 	0xDF599CD2,  0xD25292DB,   0xC54F80C0,  0xC8448EC9,  0xEB75A4F6,  0xE67EAAFF,   0xF163B8E4,  0xFC68B6ED,
   1462 	0x67B10C0A,  0x6ABA0203,   0x7DA71018,  0x70AC1E11,  0x539D342E,  0x5E963A27,   0x498B283C,  0x44802635,
   1463 	0x0FE97C42,  0x02E2724B,   0x15FF6050,  0x18F46E59,  0x3BC54466,  0x36CE4A6F,   0x21D35874,  0x2CD8567D,
   1464 	0x0C7A37A1,  0x017139A8,   0x166C2BB3,  0x1B6725BA,  0x38560F85,  0x355D018C,   0x22401397,  0x2F4B1D9E,
   1465 	0x642247E9,  0x692949E0,   0x7E345BFB,  0x733F55F2,  0x500E7FCD,  0x5D0571C4,   0x4A1863DF,  0x47136DD6,
   1466 	0xDCCAD731,  0xD1C1D938,   0xC6DCCB23,  0xCBD7C52A,  0xE8E6EF15,  0xE5EDE11C,   0xF2F0F307,  0xFFFBFD0E,
   1467 	0xB492A779,  0xB999A970,   0xAE84BB6B,  0xA38FB562,  0x80BE9F5D,  0x8DB59154,   0x9AA8834F,  0x97A38D46,
   1468 };
   1469 
   1470 /* Corresponds to _IMXC3[256] */
   1471 unsigned int mtpz_aes_gb9[] =
   1472 {
   1473 	0x00000000,  0x090D0B0E,   0x121A161C,  0x1B171D12,  0x24342C38,  0x2D392736,   0x362E3A24,  0x3F23312A,
   1474 	0x48685870,  0x4165537E,   0x5A724E6C,  0x537F4562,  0x6C5C7448,  0x65517F46,   0x7E466254,  0x774B695A,
   1475 	0x90D0B0E0,  0x99DDBBEE,   0x82CAA6FC,  0x8BC7ADF2,  0xB4E49CD8,  0xBDE997D6,   0xA6FE8AC4,  0xAFF381CA,
   1476 	0xD8B8E890,  0xD1B5E39E,   0xCAA2FE8C,  0xC3AFF582,  0xFC8CC4A8,  0xF581CFA6,   0xEE96D2B4,  0xE79BD9BA,
   1477 	0x3BBB7BDB,  0x32B670D5,   0x29A16DC7,  0x20AC66C9,  0x1F8F57E3,  0x16825CED,   0x0D9541FF,  0x04984AF1,
   1478 	0x73D323AB,  0x7ADE28A5,   0x61C935B7,  0x68C43EB9,  0x57E70F93,  0x5EEA049D,   0x45FD198F,  0x4CF01281,
   1479 	0xAB6BCB3B,  0xA266C035,   0xB971DD27,  0xB07CD629,  0x8F5FE703,  0x8652EC0D,   0x9D45F11F,  0x9448FA11,
   1480 	0xE303934B,  0xEA0E9845,   0xF1198557,  0xF8148E59,  0xC737BF73,  0xCE3AB47D,   0xD52DA96F,  0xDC20A261,
   1481 	0x766DF6AD,  0x7F60FDA3,   0x6477E0B1,  0x6D7AEBBF,  0x5259DA95,  0x5B54D19B,   0x4043CC89,  0x494EC787,
   1482 	0x3E05AEDD,  0x3708A5D3,   0x2C1FB8C1,  0x2512B3CF,  0x1A3182E5,  0x133C89EB,   0x082B94F9,  0x01269FF7,
   1483 	0xE6BD464D,  0xEFB04D43,   0xF4A75051,  0xFDAA5B5F,  0xC2896A75,  0xCB84617B,   0xD0937C69,  0xD99E7767,
   1484 	0xAED51E3D,  0xA7D81533,   0xBCCF0821,  0xB5C2032F,  0x8AE13205,  0x83EC390B,   0x98FB2419,  0x91F62F17,
   1485 	0x4DD68D76,  0x44DB8678,   0x5FCC9B6A,  0x56C19064,  0x69E2A14E,  0x60EFAA40,   0x7BF8B752,  0x72F5BC5C,
   1486 	0x05BED506,  0x0CB3DE08,   0x17A4C31A,  0x1EA9C814,  0x218AF93E,  0x2887F230,   0x3390EF22,  0x3A9DE42C,
   1487 	0xDD063D96,  0xD40B3698,   0xCF1C2B8A,  0xC6112084,  0xF93211AE,  0xF03F1AA0,   0xEB2807B2,  0xE2250CBC,
   1488 	0x956E65E6,  0x9C636EE8,   0x877473FA,  0x8E7978F4,  0xB15A49DE,  0xB85742D0,   0xA3405FC2,  0xAA4D54CC,
   1489 	0xECDAF741,  0xE5D7FC4F,   0xFEC0E15D,  0xF7CDEA53,  0xC8EEDB79,  0xC1E3D077,   0xDAF4CD65,  0xD3F9C66B,
   1490 	0xA4B2AF31,  0xADBFA43F,   0xB6A8B92D,  0xBFA5B223,  0x80868309,  0x898B8807,   0x929C9515,  0x9B919E1B,
   1491 	0x7C0A47A1,  0x75074CAF,   0x6E1051BD,  0x671D5AB3,  0x583E6B99,  0x51336097,   0x4A247D85,  0x4329768B,
   1492 	0x34621FD1,  0x3D6F14DF,   0x267809CD,  0x2F7502C3,  0x105633E9,  0x195B38E7,   0x024C25F5,  0x0B412EFB,
   1493 	0xD7618C9A,  0xDE6C8794,   0xC57B9A86,  0xCC769188,  0xF355A0A2,  0xFA58ABAC,   0xE14FB6BE,  0xE842BDB0,
   1494 	0x9F09D4EA,  0x9604DFE4,   0x8D13C2F6,  0x841EC9F8,  0xBB3DF8D2,  0xB230F3DC,   0xA927EECE,  0xA02AE5C0,
   1495 	0x47B13C7A,  0x4EBC3774,   0x55AB2A66,  0x5CA62168,  0x63851042,  0x6A881B4C,   0x719F065E,  0x78920D50,
   1496 	0x0FD9640A,  0x06D46F04,   0x1DC37216,  0x14CE7918,  0x2BED4832,  0x22E0433C,   0x39F75E2E,  0x30FA5520,
   1497 	0x9AB701EC,  0x93BA0AE2,   0x88AD17F0,  0x81A01CFE,  0xBE832DD4,  0xB78E26DA,   0xAC993BC8,  0xA59430C6,
   1498 	0xD2DF599C,  0xDBD25292,   0xC0C54F80,  0xC9C8448E,  0xF6EB75A4,  0xFFE67EAA,   0xE4F163B8,  0xEDFC68B6,
   1499 	0x0A67B10C,  0x036ABA02,   0x187DA710,  0x1170AC1E,  0x2E539D34,  0x275E963A,   0x3C498B28,  0x35448026,
   1500 	0x420FE97C,  0x4B02E272,   0x5015FF60,  0x5918F46E,  0x663BC544,  0x6F36CE4A,   0x7421D358,  0x7D2CD856,
   1501 	0xA10C7A37,  0xA8017139,   0xB3166C2B,  0xBA1B6725,  0x8538560F,  0x8C355D01,   0x97224013,  0x9E2F4B1D,
   1502 	0xE9642247,  0xE0692949,   0xFB7E345B,  0xF2733F55,  0xCD500E7F,  0xC45D0571,   0xDF4A1863,  0xD647136D,
   1503 	0x31DCCAD7,  0x38D1C1D9,   0x23C6DCCB,  0x2ACBD7C5,  0x15E8E6EF,  0x1CE5EDE1,   0x07F2F0F3,  0x0EFFFBFD,
   1504 	0x79B492A7,  0x70B999A9,   0x6BAE84BB,  0x62A38FB5,  0x5D80BE9F,  0x548DB591,   0x4F9AA883,  0x4697A38D,
   1505 };
   1506 
   1507 static uint16_t
   1508 ptp_mtpz_validatehandshakeresponse (PTPParams* params, unsigned char *random, unsigned char **calculatedHash)
   1509 {
   1510 	uint16_t ret;
   1511 	unsigned int len;
   1512 	unsigned char* response = NULL;
   1513 
   1514 	ret = ptp_mtpz_getwmdrmpdappresponse (params, &response, &len);
   1515 	if (ret != PTP_RC_OK)
   1516 	{
   1517 		LIBMTP_INFO ("(MTPZ) Failure - did not receive device's response.\n");
   1518 		return ret;
   1519 	}
   1520 
   1521 	char *reader = (char *)response;
   1522 	int i;
   1523 
   1524 	if (*(reader++) != '\x02')
   1525 	{
   1526 		return -1;
   1527 	}
   1528 
   1529 	if (*(reader++) != '\x02')
   1530 	{
   1531 		return -1;
   1532 	}
   1533 
   1534 	// Message is always 128 bytes.
   1535 	reader++;
   1536 	if (*(reader++) != '\x80')
   1537 	{
   1538 		return -1;
   1539 	}
   1540 
   1541 	char *message = (char *)malloc(128);
   1542 	memcpy(message, reader, 128);
   1543 	reader += 128;
   1544 
   1545 	// Decrypt the hash-key-message..
   1546 	char *msg_dec = (char *)malloc(128);
   1547 	memset(msg_dec, 0, 128);
   1548 
   1549 	mtpz_rsa_t *rsa = mtpz_rsa_init(MTPZ_MODULUS, MTPZ_PRIVATE_KEY, MTPZ_PUBLIC_EXPONENT);
   1550 	if (!rsa)
   1551 	{
   1552 		LIBMTP_INFO ("(MTPZ) Failure - could not instantiate RSA object.\n");
   1553 		free(message);
   1554 		free(msg_dec);
   1555 		return -1;
   1556 	}
   1557 
   1558 	if (mtpz_rsa_decrypt(128, (unsigned char *)message, 128, (unsigned char *)msg_dec, rsa) == 0)
   1559 	{
   1560 		LIBMTP_INFO ("(MTPZ) Failure - could not perform RSA decryption.\n");
   1561 
   1562 		free(message);
   1563 		free(msg_dec);
   1564 		mtpz_rsa_free(rsa);
   1565 		return -1;
   1566 	}
   1567 
   1568 	mtpz_rsa_free(rsa);
   1569 	rsa = NULL;
   1570 
   1571 	char *state = mtpz_hash_init_state();
   1572 	char *hash_key = (char *)malloc(16);
   1573 	char *v10 = mtpz_hash_custom6A5DC(state, msg_dec + 21, 107, 20);
   1574 
   1575 	for (i = 0; i < 20; i++)
   1576 		msg_dec[i + 1] ^= v10[i];
   1577 
   1578 	char *v11 = mtpz_hash_custom6A5DC(state, msg_dec + 1, 20, 107);
   1579 
   1580 	for (i = 0; i < 107; i++)
   1581 		msg_dec[i + 21] ^= v11[i];
   1582 
   1583 	memcpy(hash_key, msg_dec + 112, 16);
   1584 
   1585 	// Encrypted message is 0x340 bytes.
   1586 	reader += 2;
   1587 	if (*(reader++) != '\x03' || *(reader++) != '\x40')
   1588 	{
   1589 		return -1;
   1590 	}
   1591 
   1592 	unsigned char *act_msg = (unsigned char *)malloc(832);
   1593 	unsigned char *act_reader = act_msg;
   1594 	memcpy(act_msg, reader, 832);
   1595 	reader = NULL;
   1596 
   1597 	mtpz_encryption_cipher_advanced((unsigned char *)hash_key, 16, act_msg, 832, 0);
   1598 
   1599 	act_reader++;
   1600 	unsigned int certs_length = MTPZ_SWAP(*(unsigned int *)(act_reader));
   1601 	act_reader += 4;
   1602 	act_reader += certs_length;
   1603 
   1604 	unsigned int rand_length = MTPZ_SWAP(*(unsigned short *)(act_reader) << 16);
   1605 	act_reader += 2;
   1606 	unsigned char *rand_data = (unsigned char *)malloc(rand_length);
   1607 	memcpy(rand_data, act_reader, rand_length);
   1608 	if (memcmp(rand_data, random, 16) != 0)
   1609 	{
   1610 		free(rand_data);
   1611 		return -1;
   1612 	}
   1613 	free(rand_data);
   1614 	act_reader += rand_length;
   1615 
   1616 	unsigned int dev_rand_length = MTPZ_SWAP(*(unsigned short *)(act_reader) << 16);
   1617 	act_reader += 2;
   1618 	act_reader += dev_rand_length;
   1619 
   1620 	act_reader++;
   1621 
   1622 	unsigned int sig_length = MTPZ_SWAP(*(unsigned short *)(act_reader) << 16);
   1623 	act_reader += 2;
   1624 	act_reader += sig_length;
   1625 
   1626 	act_reader++;
   1627 
   1628 	unsigned int machash_length = MTPZ_SWAP(*(unsigned short *)(act_reader) << 16);
   1629 	act_reader += 2;
   1630 	unsigned char *machash_data = (unsigned char *)malloc(machash_length);
   1631 	memcpy(machash_data, act_reader, machash_length);
   1632 	act_reader += machash_length;
   1633 
   1634 	*calculatedHash = machash_data;
   1635 
   1636 	free(message);
   1637 	free(msg_dec);
   1638 	free(state);
   1639 	free(v10);
   1640 	free(v11);
   1641 	free(act_msg);
   1642 
   1643 	return ret;
   1644 }
   1645 
   1646 static uint16_t
   1647 ptp_mtpz_opensecuresyncsession (PTPParams* params, unsigned char *hash)
   1648 {
   1649 	unsigned char	mch[16];
   1650 	uint32_t	*hashparams = (unsigned int *)mch;
   1651 	unsigned int	macCount = *(unsigned int *)(hash + 16);
   1652 	uint16_t	ret;
   1653 
   1654 	mtpz_encryption_encrypt_mac(hash, 16, (unsigned char *)(&macCount), 4, mch);
   1655 
   1656 	ret = ptp_mtpz_wmdrmpd_enabletrustedfilesoperations(params,
   1657 		MTPZ_SWAP(hashparams[0]), MTPZ_SWAP(hashparams[1]),
   1658 		MTPZ_SWAP(hashparams[2]), MTPZ_SWAP(hashparams[3]));
   1659 	return ret;
   1660 };
   1661 
   1662 static unsigned char *
   1663 ptp_mtpz_makeapplicationcertificatemessage (unsigned int *out_len, unsigned char **out_random)
   1664 {
   1665 	*out_len = 785;
   1666 
   1667 	unsigned char *acm = (unsigned char *)malloc(785);
   1668 	unsigned char *target = acm;
   1669 	memset(acm, 0, 785);
   1670 
   1671 	unsigned char *random = (unsigned char *)malloc(16);
   1672 
   1673 	int i = 0;
   1674 	int certsLength = 0x275;
   1675 
   1676 	// Write the marker bytes, length of certificates, and certificates themselves.
   1677 	*(target++) = '\x02';
   1678 	*(target++) = '\x01';
   1679 	*(target++) = '\x01';
   1680 	*(target++) = '\x00';
   1681 	*(target++) = '\x00';
   1682 	*(target++) = '\x02';
   1683 	*(target++) = '\x75';
   1684 	memcpy(target, MTPZ_CERTIFICATES, certsLength);
   1685 	target += certsLength;
   1686 
   1687 	// Write the random bytes.
   1688 	*(target++) = '\x00';	*(target++) = '\x10';
   1689 	srand(time(NULL));
   1690 
   1691 	for (i = 0; i < 16; i++)
   1692 		*(random + i) = (unsigned char)(rand() % 256);
   1693 
   1694 	*out_random = random;
   1695 	memcpy(target, random, 16);
   1696 	target += 16;
   1697 
   1698 	char *state = mtpz_hash_init_state();
   1699 	char *v16 = (char *)malloc(28); memset(v16, 0, 28);
   1700 	char *hash = (char *)malloc(20); memset(hash, 0, 20);
   1701 	char *odata = (char *)malloc(128); memset(odata, 0, 128);
   1702 
   1703 	mtpz_hash_reset_state(state);
   1704 	mtpz_hash_transform_hash(state, (char *)acm + 2, (target - acm - 2));
   1705 	mtpz_hash_finalize_hash(state, v16 + 8);
   1706 
   1707 	mtpz_hash_reset_state(state);
   1708 	mtpz_hash_transform_hash(state, v16, 28);
   1709 	mtpz_hash_finalize_hash(state, hash);
   1710 
   1711 	char *v17 = mtpz_hash_custom6A5DC(state, hash, 20, 107);
   1712 
   1713 	for (i = 0; i < 20; i++)
   1714 		odata[107 + i] = hash[i];
   1715 
   1716 	odata[106] = '\x01';
   1717 
   1718 	if (v17 != NULL)
   1719 	{
   1720 		for (i = 0; i < 107; i++)
   1721 			odata[i] ^= v17[i];
   1722 
   1723 		odata[0] &= 127;
   1724 		odata[127] = 188;
   1725 	}
   1726 
   1727 	// Free up some jazz.
   1728 	free(state); state = NULL;
   1729 	free(v16); v16 = NULL;
   1730 	free(v17); v17 = NULL;
   1731 	free(hash); hash = NULL;
   1732 
   1733 	// Take care of some RSA jazz.
   1734 	mtpz_rsa_t *rsa = mtpz_rsa_init(MTPZ_MODULUS, MTPZ_PRIVATE_KEY, MTPZ_PUBLIC_EXPONENT);
   1735 	if (!rsa)
   1736 	{
   1737 		LIBMTP_INFO("(MTPZ) Failure - could not instantiate RSA object.\n");
   1738 		*out_len = 0;
   1739 		return NULL;
   1740 	}
   1741 
   1742 	char *signature = (char *)malloc(128);
   1743 	memset(signature, 0, 128);
   1744 	mtpz_rsa_sign(128, (unsigned char *)odata, 128, (unsigned char *)signature, rsa);
   1745 
   1746 	// Free some more things.
   1747 	mtpz_rsa_free(rsa); rsa = NULL;
   1748 	free(odata); odata = NULL;
   1749 
   1750 	// Write the signature + bytes.
   1751 	*(target++) = '\x01'; *(target++) = '\x00'; *(target++) = '\x80';
   1752 	memcpy(target, signature, 128);
   1753 
   1754 	// Kill target.
   1755 	target = NULL;
   1756 
   1757 	return acm;
   1758 };
   1759 
   1760 static unsigned char *
   1761 ptp_mtpz_makeconfirmationmessage (unsigned char *hash, unsigned int *out_len)
   1762 {
   1763 	*out_len = 20;
   1764 	unsigned char *message = (unsigned char *)malloc(20);
   1765 	message[0] = (unsigned char)0x02;
   1766 	message[1] = (unsigned char)0x03;
   1767 	message[2] = (unsigned char)0x00;
   1768 	message[3] = (unsigned char)0x10;
   1769 
   1770 	unsigned char *seed = (unsigned char *)malloc(16);
   1771 	memset(seed, 0, 16);
   1772 	seed[15] = (unsigned char)(0x01);
   1773 
   1774 	mtpz_encryption_encrypt_mac(hash, 16u, seed, 16u, message + 4);
   1775 
   1776 	free(seed);
   1777 
   1778 	return message;
   1779 }
   1780 
   1781 uint16_t ptp_mtpz_handshake (PTPParams* params)
   1782 {
   1783 	uint16_t ret = PTP_RC_OK;
   1784 	uint32_t size;
   1785 	unsigned char *hash=NULL;
   1786 	unsigned char *random=NULL;
   1787 	PTPPropertyValue propval;
   1788 	unsigned char*	applicationCertificateMessage;
   1789 	unsigned char*	message;
   1790 
   1791 	/* FIXME: do other places of libmtp set it? should we set it? */
   1792 	LIBMTP_INFO ("(MTPZ) Setting session initiator info.\n");
   1793 	propval.str = "libmtp/Sajid Anwar - MTPZClassDriver";
   1794 	ret = ptp_setdevicepropvalue(params,
   1795 		   PTP_DPC_MTP_SessionInitiatorInfo,
   1796 		   &propval,
   1797 		   PTP_DTC_STR);
   1798 	if (ret != PTP_RC_OK)
   1799 		return ret;
   1800 
   1801 	LIBMTP_INFO ("(MTPZ) Resetting handshake.\n");
   1802 	ret = ptp_mtpz_resethandshake(params);
   1803 	if (ret != PTP_RC_OK)
   1804 		return ret;
   1805 
   1806 	LIBMTP_INFO ("(MTPZ) Sending application certificate message.\n");
   1807 	applicationCertificateMessage = ptp_mtpz_makeapplicationcertificatemessage(&size, &random);
   1808 	ret = ptp_mtpz_sendwmdrmpdapprequest (params, applicationCertificateMessage, size);
   1809 	free (applicationCertificateMessage);
   1810 	if (ret != PTP_RC_OK)
   1811 		return ret;
   1812 
   1813 	LIBMTP_INFO ("(MTPZ) Getting and validating handshake response.\n");
   1814 	ret = ptp_mtpz_validatehandshakeresponse(params, random, &hash);
   1815 	if (ret != PTP_RC_OK)
   1816 		goto free_random;
   1817 
   1818 	LIBMTP_INFO ("(MTPZ) Sending confirmation message.\n");
   1819 	message = ptp_mtpz_makeconfirmationmessage(hash, &size);
   1820         ret = ptp_mtpz_sendwmdrmpdapprequest (params, message, size);
   1821 	if (ret != PTP_RC_OK)
   1822 		goto free_hash;
   1823 	free (message);
   1824 
   1825 	LIBMTP_INFO ("(MTPZ) Opening secure sync session.\n");
   1826 	ret = ptp_mtpz_opensecuresyncsession(params, hash);
   1827 free_hash:
   1828 	free(hash);
   1829 free_random:
   1830 	free(random);
   1831 	return ret;
   1832 }
   1833