From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail.kernel.org ([198.145.29.99]:44286 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2404290AbfEXWEo (ORCPT ); Fri, 24 May 2019 18:04:44 -0400 From: Eric Biggers Subject: [PATCH v2 2/7] fscrypt-crypt-util: add utility for reproducing fscrypt encrypted data Date: Fri, 24 May 2019 15:04:20 -0700 Message-Id: <20190524220425.201170-3-ebiggers@kernel.org> In-Reply-To: <20190524220425.201170-1-ebiggers@kernel.org> References: <20190524220425.201170-1-ebiggers@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: fstests-owner@vger.kernel.org Content-Transfer-Encoding: quoted-printable To: fstests@vger.kernel.org Cc: linux-fscrypt@vger.kernel.org, linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net List-ID: From: Eric Biggers Add a utility program that can reproduce encrypted contents and filenames. It implements all encryption algorithms currently supported by fscrypt (a.k.a. ext4, f2fs, and ubifs encryption), and it generates IVs in the same way. The program takes the algorithm and master key on the command line, and encrypts stdin to stdout. A file nonce may also be passed on the command line, and the program will "tweak" the encryption using this nonce in the same way the kernel does -- either by deriving a subkey, or by including the nonce in the IVs. The block size and padding amount may also be specified. No dependencies are added, as all algorithms implemented from scratch. Signed-off-by: Eric Biggers --- .gitignore | 1 + src/Makefile | 3 +- src/fscrypt-crypt-util.c | 1633 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 1636 insertions(+), 1 deletion(-) create mode 100644 src/fscrypt-crypt-util.c diff --git a/.gitignore b/.gitignore index c13fb713..11232be7 100644 --- a/.gitignore +++ b/.gitignore @@ -73,6 +73,7 @@ /src/fill /src/fill2 /src/fs_perms +/src/fscrypt-crypt-util /src/fssum /src/fstest /src/fsync-err diff --git a/src/Makefile b/src/Makefile index 4057d7b3..9d3d2529 100644 --- a/src/Makefile +++ b/src/Makefile @@ -27,7 +27,8 @@ LINUX_TARGETS =3D xfsctl bstat t_mtab getdevicesize pre= allo_rw_pattern_reader \ renameat2 t_getcwd e4compact test-nextquota punch-alternating \ attr-list-by-handle-cursor-test listxattr dio-interleaved t_dir_type \ dio-invalidate-cache stat_test t_encrypted_d_revalidate \ - attr_replace_test swapon mkswap t_attr_corruption t_open_tmpfiles + attr_replace_test swapon mkswap t_attr_corruption t_open_tmpfiles \ + fscrypt-crypt-util =20 SUBDIRS =3D log-writes perf =20 diff --git a/src/fscrypt-crypt-util.c b/src/fscrypt-crypt-util.c new file mode 100644 index 00000000..81574a55 --- /dev/null +++ b/src/fscrypt-crypt-util.c @@ -0,0 +1,1633 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * fscrypt-crypt-util.c - utility for verifying fscrypt-encrypted data + * + * Copyright 2019 Google LLC + */ + +/* + * This program implements all crypto algorithms supported by fscrypt (a= .k.a. + * ext4, f2fs, and ubifs encryption), for the purpose of verifying the + * correctness of the ciphertext stored on-disk. See usage() below. + * + * All algorithms are implemented in portable C code to avoid depending = on + * libcrypto (OpenSSL), and because some fscrypt-supported algorithms ar= en't + * available in libcrypto anyway (e.g. Adiantum). For simplicity, all c= rypto + * code here tries to follow the mathematical definitions directly, with= out + * optimizing for performance or worrying about following security best + * practices such as mitigating side-channel attacks. So, only use this= program + * for testing! + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PROGRAM_NAME "fscrypt-crypt-util" + +/* + * Define to enable the tests of the crypto code in this file. If enabl= ed, you + * must link this program with OpenSSL (-lcrypto) v1.1.0 or later, and y= our + * kernel needs CONFIG_CRYPTO_USER_API_SKCIPHER=3Dy and CONFIG_CRYPTO_AD= IANTUM=3Dy. + */ +#undef ENABLE_ALG_TESTS + +#define NUM_ALG_TEST_ITERATIONS 10000 + +static void usage(FILE *fp) +{ + fputs( +"Usage: " PROGRAM_NAME " [OPTION]... CIPHER MASTER_KEY\n" +"\n" +"Utility for verifying fscrypt-encrypted data. This program encrypts\n" +"(or decrypts) the data on stdin using the given CIPHER with the given\n= " +"MASTER_KEY (or a key derived from it, if a KDF is specified), and write= s the\n" +"resulting ciphertext (or plaintext) to stdout.\n" +"\n" +"CIPHER can be AES-256-XTS, AES-256-CTS-CBC, AES-128-CBC-ESSIV, AES-128-= CTS-CBC,\n" +"or Adiantum. MASTER_KEY must be a hex string long enough for the ciphe= r.\n" +"\n" +"WARNING: this program is only meant for testing, not for \"real\" use!\= n" +"\n" +"Options:\n" +" --block-size=3DBLOCK_SIZE Encrypt each BLOCK_SIZE bytes independe= ntly.\n" +" Default: 4096 bytes\n" +" --decrypt Decrypt instead of encrypt\n" +" --file-nonce=3DNONCE File's nonce as a 32-character hex stri= ng\n" +" --help Show this help\n" +" --kdf=3DKDF Key derivation function to use: AES-128= -ECB\n" +" or none. Default: none\n" +" --padding=3DPADDING If last block is partial, zero-pad it t= o next\n" +" PADDING-byte boundary. Default: BLOCK_= SIZE\n" + , fp); +} + +/*----------------------------------------------------------------------= ------* + * Utilities = * + *----------------------------------------------------------------------= ------*/ + +#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0])) +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#define ROUND_DOWN(x, y) ((x) & ~((y) - 1)) +#define ROUND_UP(x, y) (((x) + (y) - 1) & ~((y) - 1)) +#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) +#define STATIC_ASSERT(e) ((void)sizeof(char[1 - 2*!(e)])) + +typedef __u8 u8; +typedef __u16 u16; +typedef __u32 u32; +typedef __u64 u64; + +#define cpu_to_le32 __cpu_to_le32 +#define cpu_to_be32 __cpu_to_be32 +#define cpu_to_le64 __cpu_to_le64 +#define cpu_to_be64 __cpu_to_be64 +#define le32_to_cpu __le32_to_cpu +#define be32_to_cpu __be32_to_cpu +#define le64_to_cpu __le64_to_cpu +#define be64_to_cpu __be64_to_cpu + +#define DEFINE_UNALIGNED_ACCESS_HELPERS(type, native_type) \ +static inline native_type __attribute__((unused)) \ +get_unaligned_##type(const void *p) \ +{ \ + __##type x; \ + \ + memcpy(&x, p, sizeof(x)); \ + return type##_to_cpu(x); \ +} \ + \ +static inline void __attribute__((unused)) \ +put_unaligned_##type(native_type v, void *p) \ +{ \ + __##type x =3D cpu_to_##type(v); \ + \ + memcpy(p, &x, sizeof(x)); \ +} + +DEFINE_UNALIGNED_ACCESS_HELPERS(le32, u32) +DEFINE_UNALIGNED_ACCESS_HELPERS(be32, u32) +DEFINE_UNALIGNED_ACCESS_HELPERS(le64, u64) +DEFINE_UNALIGNED_ACCESS_HELPERS(be64, u64) + +static inline bool is_power_of_2(unsigned long v) +{ + return v !=3D 0 && (v & (v - 1)) =3D=3D 0; +} + +static inline u32 rol32(u32 v, int n) +{ + return (v << n) | (v >> (32 - n)); +} + +static inline u32 ror32(u32 v, int n) +{ + return (v >> n) | (v << (32 - n)); +} + +static inline void xor(u8 *res, const u8 *a, const u8 *b, size_t count) +{ + while (count--) + *res++ =3D *a++ ^ *b++; +} + +static void __attribute__((noreturn, format(printf, 2, 3))) +do_die(int err, const char *format, ...) +{ + va_list va; + + va_start(va, format); + fputs("[" PROGRAM_NAME "] ERROR: ", stderr); + vfprintf(stderr, format, va); + if (err) + fprintf(stderr, ": %s", strerror(errno)); + putc('\n', stderr); + va_end(va); + exit(1); +} + +#define die(format, ...) do_die(0, (format), ##__VA_ARGS__) +#define die_errno(format, ...) do_die(errno, (format), ##__VA_ARGS__) + +static __attribute__((noreturn)) void +assertion_failed(const char *expr, const char *file, int line) +{ + die("Assertion failed: %s at %s:%d", expr, file, line); +} + +#define ASSERT(e) ({ if (!(e)) assertion_failed(#e, __FILE__, __LINE__);= }) + +static void *xmalloc(size_t size) +{ + void *p =3D malloc(size); + + ASSERT(p !=3D NULL); + return p; +} + +static int hexchar2bin(char c) +{ + if (c >=3D 'a' && c <=3D 'f') + return 10 + c - 'a'; + if (c >=3D 'A' && c <=3D 'F') + return 10 + c - 'A'; + if (c >=3D '0' && c <=3D '9') + return c - '0'; + return -1; +} + +static int hex2bin(const char *hex, u8 *bin, int max_bin_size) +{ + size_t len =3D strlen(hex); + size_t i; + + if (len & 1) + return -1; + len /=3D 2; + if (len > max_bin_size) + return -1; + + for (i =3D 0; i < len; i++) { + int high =3D hexchar2bin(hex[2 * i]); + int low =3D hexchar2bin(hex[2 * i + 1]); + + if (high < 0 || low < 0) + return -1; + bin[i] =3D (high << 4) | low; + } + return len; +} + +static size_t xread(int fd, void *buf, size_t count) +{ + const size_t orig_count =3D count; + + while (count) { + ssize_t res =3D read(fd, buf, count); + + if (res < 0) + die_errno("read error"); + if (res =3D=3D 0) + break; + buf +=3D res; + count -=3D res; + } + return orig_count - count; +} + +static void full_write(int fd, const void *buf, size_t count) +{ + while (count) { + ssize_t res =3D write(fd, buf, count); + + if (res < 0) + die_errno("write error"); + buf +=3D res; + count -=3D res; + } +} + +#ifdef ENABLE_ALG_TESTS +static void rand_bytes(u8 *buf, size_t count) +{ + while (count--) + *buf++ =3D rand(); +} +#endif + +/*----------------------------------------------------------------------= ------* + * Finite field arithmetic = * + *----------------------------------------------------------------------= ------*/ + +/* Multiply a GF(2^8) element by the polynomial 'x' */ +static inline u8 gf2_8_mul_x(u8 b) +{ + return (b << 1) ^ ((b & 0x80) ? 0x1B : 0); +} + +/* Multiply four packed GF(2^8) elements by the polynomial 'x' */ +static inline u32 gf2_8_mul_x_4way(u32 w) +{ + return ((w & 0x7F7F7F7F) << 1) ^ (((w & 0x80808080) >> 7) * 0x1B); +} + +/* Element of GF(2^128) */ +typedef struct { + __le64 lo; + __le64 hi; +} ble128; + +/* Multiply a GF(2^128) element by the polynomial 'x' */ +static inline void gf2_128_mul_x(ble128 *t) +{ + u64 lo =3D le64_to_cpu(t->lo); + u64 hi =3D le64_to_cpu(t->hi); + + t->hi =3D cpu_to_le64((hi << 1) | (lo >> 63)); + t->lo =3D cpu_to_le64((lo << 1) ^ ((hi & (1ULL << 63)) ? 0x87 : 0)); +} + +/*----------------------------------------------------------------------= ------* + * Group arithmetic = * + *----------------------------------------------------------------------= ------*/ + +/* Element of Z/(2^{128}Z) (a.k.a. the integers modulo 2^128) */ +typedef struct { + __le64 lo; + __le64 hi; +} le128; + +static inline void le128_add(le128 *res, const le128 *a, const le128 *b) +{ + u64 a_lo =3D le64_to_cpu(a->lo); + u64 b_lo =3D le64_to_cpu(b->lo); + + res->lo =3D cpu_to_le64(a_lo + b_lo); + res->hi =3D cpu_to_le64(le64_to_cpu(a->hi) + le64_to_cpu(b->hi) + + (a_lo + b_lo < a_lo)); +} + +static inline void le128_sub(le128 *res, const le128 *a, const le128 *b) +{ + u64 a_lo =3D le64_to_cpu(a->lo); + u64 b_lo =3D le64_to_cpu(b->lo); + + res->lo =3D cpu_to_le64(a_lo - b_lo); + res->hi =3D cpu_to_le64(le64_to_cpu(a->hi) - le64_to_cpu(b->hi) - + (a_lo - b_lo > a_lo)); +} + +/*----------------------------------------------------------------------= ------* + * AES block cipher = * + *----------------------------------------------------------------------= ------*/ + +/* + * Reference: "FIPS 197, Advanced Encryption Standard" + * https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.197.pdf + */ + +#define AES_BLOCK_SIZE 16 +#define AES_128_KEY_SIZE 16 +#define AES_192_KEY_SIZE 24 +#define AES_256_KEY_SIZE 32 + +static inline void AddRoundKey(u32 state[4], const u32 *rk) +{ + int i; + + for (i =3D 0; i < 4; i++) + state[i] ^=3D rk[i]; +} + +static const u8 aes_sbox[256] =3D { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, + 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, + 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, + 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, + 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, + 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, + 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, + 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, + 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, + 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, + 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, + 0xb0, 0x54, 0xbb, 0x16, +}; + +static u8 aes_inverse_sbox[256]; + +static void aes_init(void) +{ + int i; + + for (i =3D 0; i < 256; i++) + aes_inverse_sbox[aes_sbox[i]] =3D i; +} + +static inline u32 DoSubWord(u32 w, const u8 sbox[256]) +{ + return ((u32)sbox[(u8)(w >> 24)] << 24) | + ((u32)sbox[(u8)(w >> 16)] << 16) | + ((u32)sbox[(u8)(w >> 8)] << 8) | + ((u32)sbox[(u8)(w >> 0)] << 0); +} + +static inline u32 SubWord(u32 w) +{ + return DoSubWord(w, aes_sbox); +} + +static inline u32 InvSubWord(u32 w) +{ + return DoSubWord(w, aes_inverse_sbox); +} + +static inline void SubBytes(u32 state[4]) +{ + int i; + + for (i =3D 0; i < 4; i++) + state[i] =3D SubWord(state[i]); +} + +static inline void InvSubBytes(u32 state[4]) +{ + int i; + + for (i =3D 0; i < 4; i++) + state[i] =3D InvSubWord(state[i]); +} + +static inline void DoShiftRows(u32 state[4], int direction) +{ + u32 newstate[4]; + int i; + + for (i =3D 0; i < 4; i++) + newstate[i] =3D (state[(i + direction*0) & 3] & 0xff) | + (state[(i + direction*1) & 3] & 0xff00) | + (state[(i + direction*2) & 3] & 0xff0000) | + (state[(i + direction*3) & 3] & 0xff000000); + memcpy(state, newstate, 16); +} + +static inline void ShiftRows(u32 state[4]) +{ + DoShiftRows(state, 1); +} + +static inline void InvShiftRows(u32 state[4]) +{ + DoShiftRows(state, -1); +} + +/* + * Mix one column by doing the following matrix multiplication in GF(2^8= ): + * + * | 2 3 1 1 | | w[0] | + * | 1 2 3 1 | | w[1] | + * | 1 1 2 3 | x | w[2] | + * | 3 1 1 2 | | w[3] | + * + * a.k.a. w[i] =3D 2*w[i] + 3*w[(i+1)%4] + w[(i+2)%4] + w[(i+3)%4] + */ +static inline u32 MixColumn(u32 w) +{ + u32 _2w0_w2 =3D gf2_8_mul_x_4way(w) ^ ror32(w, 16); + u32 _3w1_w3 =3D ror32(_2w0_w2 ^ w, 8); + + return _2w0_w2 ^ _3w1_w3; +} + +/* + * ( | 5 0 4 0 | | w[0] | ) + * ( | 0 5 0 4 | | w[1] | ) + * MixColumn( | 4 0 5 0 | x | w[2] | ) + * ( | 0 4 0 5 | | w[3] | ) + */ +static inline u32 InvMixColumn(u32 w) +{ + u32 _4w =3D gf2_8_mul_x_4way(gf2_8_mul_x_4way(w)); + + return MixColumn(_4w ^ w ^ ror32(_4w, 16)); +} + +static inline void MixColumns(u32 state[4]) +{ + int i; + + for (i =3D 0; i < 4; i++) + state[i] =3D MixColumn(state[i]); +} + +static inline void InvMixColumns(u32 state[4]) +{ + int i; + + for (i =3D 0; i < 4; i++) + state[i] =3D InvMixColumn(state[i]); +} + +struct aes_key { + u32 round_keys[15 * 4]; + int nrounds; +}; + +/* Expand an AES key */ +static void aes_setkey(struct aes_key *k, const u8 *key, int keysize) +{ + const int N =3D keysize / 4; + u32 * const rk =3D k->round_keys; + u8 rcon =3D 1; + int i; + + ASSERT(keysize =3D=3D 16 || keysize =3D=3D 24 || keysize =3D=3D 32); + k->nrounds =3D 6 + N; + for (i =3D 0; i < 4 * (k->nrounds + 1); i++) { + if (i < N) { + rk[i] =3D get_unaligned_le32(&key[i * sizeof(__le32)]); + } else if (i % N =3D=3D 0) { + rk[i] =3D rk[i - N] ^ SubWord(ror32(rk[i - 1], 8)) ^ rcon; + rcon =3D gf2_8_mul_x(rcon); + } else if (N > 6 && i % N =3D=3D 4) { + rk[i] =3D rk[i - N] ^ SubWord(rk[i - 1]); + } else { + rk[i] =3D rk[i - N] ^ rk[i - 1]; + } + } +} + +/* Encrypt one 16-byte block with AES */ +static void aes_encrypt(const struct aes_key *k, const u8 src[AES_BLOCK_= SIZE], + u8 dst[AES_BLOCK_SIZE]) +{ + u32 state[4]; + int i; + + for (i =3D 0; i < 4; i++) + state[i] =3D get_unaligned_le32(&src[i * sizeof(__le32)]); + + AddRoundKey(state, k->round_keys); + for (i =3D 1; i < k->nrounds; i++) { + SubBytes(state); + ShiftRows(state); + MixColumns(state); + AddRoundKey(state, &k->round_keys[4 * i]); + } + SubBytes(state); + ShiftRows(state); + AddRoundKey(state, &k->round_keys[4 * i]); + + for (i =3D 0; i < 4; i++) + put_unaligned_le32(state[i], &dst[i * sizeof(__le32)]); +} + +/* Decrypt one 16-byte block with AES */ +static void aes_decrypt(const struct aes_key *k, const u8 src[AES_BLOCK_= SIZE], + u8 dst[AES_BLOCK_SIZE]) +{ + u32 state[4]; + int i; + + for (i =3D 0; i < 4; i++) + state[i] =3D get_unaligned_le32(&src[i * sizeof(__le32)]); + + AddRoundKey(state, &k->round_keys[4 * k->nrounds]); + InvShiftRows(state); + InvSubBytes(state); + for (i =3D k->nrounds - 1; i >=3D 1; i--) { + AddRoundKey(state, &k->round_keys[4 * i]); + InvMixColumns(state); + InvShiftRows(state); + InvSubBytes(state); + } + AddRoundKey(state, k->round_keys); + + for (i =3D 0; i < 4; i++) + put_unaligned_le32(state[i], &dst[i * sizeof(__le32)]); +} + +#ifdef ENABLE_ALG_TESTS +#include +static void test_aes_keysize(int keysize) +{ + unsigned long num_tests =3D NUM_ALG_TEST_ITERATIONS; + + while (num_tests--) { + struct aes_key k; + AES_KEY ref_k; + u8 key[AES_256_KEY_SIZE]; + u8 ptext[AES_BLOCK_SIZE]; + u8 ctext[AES_BLOCK_SIZE]; + u8 ref_ctext[AES_BLOCK_SIZE]; + u8 decrypted[AES_BLOCK_SIZE]; + + rand_bytes(key, keysize); + rand_bytes(ptext, AES_BLOCK_SIZE); + + aes_setkey(&k, key, keysize); + aes_encrypt(&k, ptext, ctext); + + ASSERT(AES_set_encrypt_key(key, keysize*8, &ref_k) =3D=3D 0); + AES_encrypt(ptext, ref_ctext, &ref_k); + + ASSERT(memcmp(ctext, ref_ctext, AES_BLOCK_SIZE) =3D=3D 0); + + aes_decrypt(&k, ctext, decrypted); + ASSERT(memcmp(ptext, decrypted, AES_BLOCK_SIZE) =3D=3D 0); + } +} + +static void test_aes(void) +{ + test_aes_keysize(AES_128_KEY_SIZE); + test_aes_keysize(AES_192_KEY_SIZE); + test_aes_keysize(AES_256_KEY_SIZE); +} +#endif /* ENABLE_ALG_TESTS */ + +/*----------------------------------------------------------------------= ------* + * SHA-256 = * + *----------------------------------------------------------------------= ------*/ + +/* + * Reference: "FIPS 180-2, Secure Hash Standard" + * https://csrc.nist.gov/csrc/media/publications/fips/180/2/archive/2002= -08-01/documents/fips180-2withchangenotice.pdf + */ + +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 + +#define Ch(x, y, z) (((x) & (y)) ^ (~(x) & (z))) +#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +#define Sigma256_0(x) (ror32((x), 2) ^ ror32((x), 13) ^ ror32((x), 22)) +#define Sigma256_1(x) (ror32((x), 6) ^ ror32((x), 11) ^ ror32((x), 25)) +#define sigma256_0(x) (ror32((x), 7) ^ ror32((x), 18) ^ ((x) >> 3)) +#define sigma256_1(x) (ror32((x), 17) ^ ror32((x), 19) ^ ((x) >> 10)) + +static const u32 sha256_iv[8] =3D { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, + 0x1f83d9ab, 0x5be0cd19, +}; + +static const u32 sha256_round_constants[64] =3D { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, + 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, + 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, + 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +}; + +/* Compute the SHA-256 digest of the given buffer */ +static void sha256(const u8 *in, size_t inlen, u8 out[SHA256_DIGEST_SIZE= ]) +{ + const size_t msglen =3D ROUND_UP(inlen + 9, SHA256_BLOCK_SIZE); + u8 * const msg =3D xmalloc(msglen); + u32 H[8]; + int i; + + /* super naive way of handling the padding */ + memcpy(msg, in, inlen); + memset(&msg[inlen], 0, msglen - inlen); + msg[inlen] =3D 0x80; + put_unaligned_be64((u64)inlen * 8, &msg[msglen - sizeof(__be64)]); + in =3D msg; + + memcpy(H, sha256_iv, sizeof(H)); + do { + u32 a =3D H[0], b =3D H[1], c =3D H[2], d =3D H[3], + e =3D H[4], f =3D H[5], g =3D H[6], h =3D H[7]; + u32 W[64]; + + for (i =3D 0; i < 16; i++) + W[i] =3D get_unaligned_be32(&in[i * sizeof(__be32)]); + for (; i < ARRAY_SIZE(W); i++) + W[i] =3D sigma256_1(W[i - 2]) + W[i - 7] + + sigma256_0(W[i - 15]) + W[i - 16]; + for (i =3D 0; i < ARRAY_SIZE(W); i++) { + u32 T1 =3D h + Sigma256_1(e) + Ch(e, f, g) + + sha256_round_constants[i] + W[i]; + u32 T2 =3D Sigma256_0(a) + Maj(a, b, c); + + h =3D g; g =3D f; f =3D e; e =3D d + T1; + d =3D c; c =3D b; b =3D a; a =3D T1 + T2; + } + H[0] +=3D a; H[1] +=3D b; H[2] +=3D c; H[3] +=3D d; + H[4] +=3D e; H[5] +=3D f; H[6] +=3D g; H[7] +=3D h; + } while ((in +=3D SHA256_BLOCK_SIZE) !=3D &msg[msglen]); + + for (i =3D 0; i < ARRAY_SIZE(H); i++) + put_unaligned_be32(H[i], &out[i * sizeof(__be32)]); + free(msg); +} + +#ifdef ENABLE_ALG_TESTS +#include +static void test_sha2(void) +{ + unsigned long num_tests =3D NUM_ALG_TEST_ITERATIONS; + + while (num_tests--) { + u8 in[4096]; + u8 digest[SHA256_DIGEST_SIZE]; + u8 ref_digest[SHA256_DIGEST_SIZE]; + const size_t inlen =3D rand() % (1 + sizeof(in)); + + rand_bytes(in, inlen); + + sha256(in, inlen, digest); + SHA256(in, inlen, ref_digest); + ASSERT(memcmp(digest, ref_digest, SHA256_DIGEST_SIZE) =3D=3D 0); + } +} +#endif /* ENABLE_ALG_TESTS */ + +/*----------------------------------------------------------------------= ------* + * AES encryption modes = * + *----------------------------------------------------------------------= ------*/ + +static void aes_256_xts_crypt(const u8 key[2 * AES_256_KEY_SIZE], + const u8 iv[AES_BLOCK_SIZE], const u8 *src, + u8 *dst, size_t nbytes, bool decrypting) +{ + struct aes_key tweak_key, cipher_key; + ble128 t; + size_t i; + + ASSERT(nbytes % AES_BLOCK_SIZE =3D=3D 0); + aes_setkey(&cipher_key, key, AES_256_KEY_SIZE); + aes_setkey(&tweak_key, &key[AES_256_KEY_SIZE], AES_256_KEY_SIZE); + aes_encrypt(&tweak_key, iv, (u8 *)&t); + for (i =3D 0; i < nbytes; i +=3D AES_BLOCK_SIZE) { + xor(&dst[i], &src[i], (const u8 *)&t, AES_BLOCK_SIZE); + if (decrypting) + aes_decrypt(&cipher_key, &dst[i], &dst[i]); + else + aes_encrypt(&cipher_key, &dst[i], &dst[i]); + xor(&dst[i], &dst[i], (const u8 *)&t, AES_BLOCK_SIZE); + gf2_128_mul_x(&t); + } +} + +static void aes_256_xts_encrypt(const u8 key[2 * AES_256_KEY_SIZE], + const u8 iv[AES_BLOCK_SIZE], const u8 *src, + u8 *dst, size_t nbytes) +{ + aes_256_xts_crypt(key, iv, src, dst, nbytes, false); +} + +static void aes_256_xts_decrypt(const u8 key[2 * AES_256_KEY_SIZE], + const u8 iv[AES_BLOCK_SIZE], const u8 *src, + u8 *dst, size_t nbytes) +{ + aes_256_xts_crypt(key, iv, src, dst, nbytes, true); +} + +#ifdef ENABLE_ALG_TESTS +#include +static void test_aes_256_xts(void) +{ + unsigned long num_tests =3D NUM_ALG_TEST_ITERATIONS; + EVP_CIPHER_CTX *ctx =3D EVP_CIPHER_CTX_new(); + + ASSERT(ctx !=3D NULL); + while (num_tests--) { + u8 key[2 * AES_256_KEY_SIZE]; + u8 iv[AES_BLOCK_SIZE]; + u8 ptext[512]; + u8 ctext[sizeof(ptext)]; + u8 ref_ctext[sizeof(ptext)]; + u8 decrypted[sizeof(ptext)]; + const size_t datalen =3D ROUND_DOWN(rand() % (1 + sizeof(ptext)), + AES_BLOCK_SIZE); + int outl, res; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + rand_bytes(ptext, datalen); + + aes_256_xts_encrypt(key, iv, ptext, ctext, datalen); + res =3D EVP_EncryptInit_ex(ctx, EVP_aes_256_xts(), NULL, key, iv); + ASSERT(res > 0); + res =3D EVP_EncryptUpdate(ctx, ref_ctext, &outl, ptext, datalen); + ASSERT(res > 0); + ASSERT(outl =3D=3D datalen); + ASSERT(memcmp(ctext, ref_ctext, datalen) =3D=3D 0); + + aes_256_xts_decrypt(key, iv, ctext, decrypted, datalen); + ASSERT(memcmp(ptext, decrypted, datalen) =3D=3D 0); + } + EVP_CIPHER_CTX_free(ctx); +} +#endif /* ENABLE_ALG_TESTS */ + +static void aes_cbc_encrypt(const struct aes_key *k, + const u8 iv[AES_BLOCK_SIZE], + const u8 *src, u8 *dst, size_t nbytes) +{ + size_t i; + + ASSERT(nbytes % AES_BLOCK_SIZE =3D=3D 0); + for (i =3D 0; i < nbytes; i +=3D AES_BLOCK_SIZE) { + xor(&dst[i], &src[i], (i =3D=3D 0 ? iv : &dst[i - AES_BLOCK_SIZE]), + AES_BLOCK_SIZE); + aes_encrypt(k, &dst[i], &dst[i]); + } +} + +static void aes_cbc_decrypt(const struct aes_key *k, + const u8 iv[AES_BLOCK_SIZE], + const u8 *src, u8 *dst, size_t nbytes) +{ + size_t i =3D nbytes; + + ASSERT(i % AES_BLOCK_SIZE =3D=3D 0); + while (i) { + i -=3D AES_BLOCK_SIZE; + aes_decrypt(k, &src[i], &dst[i]); + xor(&dst[i], &dst[i], (i =3D=3D 0 ? iv : &src[i - AES_BLOCK_SIZE]), + AES_BLOCK_SIZE); + } +} + +static void aes_cts_cbc_encrypt(const u8 *key, int keysize, + const u8 iv[AES_BLOCK_SIZE], + const u8 *src, u8 *dst, size_t nbytes) +{ + const size_t offset =3D ROUND_DOWN(nbytes - 1, AES_BLOCK_SIZE); + const size_t final_bsize =3D nbytes - offset; + struct aes_key k; + u8 *pad; + u8 buf[AES_BLOCK_SIZE]; + + ASSERT(nbytes >=3D AES_BLOCK_SIZE); + + aes_setkey(&k, key, keysize); + + if (nbytes =3D=3D AES_BLOCK_SIZE) + return aes_cbc_encrypt(&k, iv, src, dst, nbytes); + + aes_cbc_encrypt(&k, iv, src, dst, offset); + pad =3D &dst[offset - AES_BLOCK_SIZE]; + + memcpy(buf, pad, AES_BLOCK_SIZE); + xor(buf, buf, &src[offset], final_bsize); + memcpy(&dst[offset], pad, final_bsize); + aes_encrypt(&k, buf, pad); +} + +static void aes_cts_cbc_decrypt(const u8 *key, int keysize, + const u8 iv[AES_BLOCK_SIZE], + const u8 *src, u8 *dst, size_t nbytes) +{ + const size_t offset =3D ROUND_DOWN(nbytes - 1, AES_BLOCK_SIZE); + const size_t final_bsize =3D nbytes - offset; + struct aes_key k; + u8 *pad; + + ASSERT(nbytes >=3D AES_BLOCK_SIZE); + + aes_setkey(&k, key, keysize); + + if (nbytes =3D=3D AES_BLOCK_SIZE) + return aes_cbc_decrypt(&k, iv, src, dst, nbytes); + + pad =3D &dst[offset - AES_BLOCK_SIZE]; + aes_decrypt(&k, &src[offset - AES_BLOCK_SIZE], pad); + xor(&dst[offset], &src[offset], pad, final_bsize); + xor(pad, pad, &dst[offset], final_bsize); + + aes_cbc_decrypt(&k, (offset =3D=3D AES_BLOCK_SIZE ? + iv : &src[offset - 2 * AES_BLOCK_SIZE]), + pad, pad, AES_BLOCK_SIZE); + aes_cbc_decrypt(&k, iv, src, dst, offset - AES_BLOCK_SIZE); +} + +static void aes_256_cts_cbc_encrypt(const u8 key[AES_256_KEY_SIZE], + const u8 iv[AES_BLOCK_SIZE], + const u8 *src, u8 *dst, size_t nbytes) +{ + aes_cts_cbc_encrypt(key, AES_256_KEY_SIZE, iv, src, dst, nbytes); +} + +static void aes_256_cts_cbc_decrypt(const u8 key[AES_256_KEY_SIZE], + const u8 iv[AES_BLOCK_SIZE], + const u8 *src, u8 *dst, size_t nbytes) +{ + aes_cts_cbc_decrypt(key, AES_256_KEY_SIZE, iv, src, dst, nbytes); +} + +#ifdef ENABLE_ALG_TESTS +#include +static void aes_block128_f(const unsigned char in[16], + unsigned char out[16], const void *key) +{ + aes_encrypt(key, in, out); +} + +static void test_aes_256_cts_cbc(void) +{ + unsigned long num_tests =3D NUM_ALG_TEST_ITERATIONS; + + while (num_tests--) { + u8 key[AES_256_KEY_SIZE]; + u8 iv[AES_BLOCK_SIZE]; + u8 iv_copy[AES_BLOCK_SIZE]; + u8 ptext[512]; + u8 ctext[sizeof(ptext)]; + u8 ref_ctext[sizeof(ptext)]; + u8 decrypted[sizeof(ptext)]; + const size_t datalen =3D 16 + (rand() % (sizeof(ptext) - 15)); + struct aes_key k; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + rand_bytes(ptext, datalen); + + aes_256_cts_cbc_encrypt(key, iv, ptext, ctext, datalen); + + /* OpenSSL doesn't allow datalen=3DAES_BLOCK_SIZE; Linux does */ + if (datalen !=3D AES_BLOCK_SIZE) { + aes_setkey(&k, key, sizeof(key)); + memcpy(iv_copy, iv, sizeof(iv)); + ASSERT(CRYPTO_cts128_encrypt_block(ptext, ref_ctext, + datalen, &k, iv_copy, + aes_block128_f) + =3D=3D datalen); + ASSERT(memcmp(ctext, ref_ctext, datalen) =3D=3D 0); + } + aes_256_cts_cbc_decrypt(key, iv, ctext, decrypted, datalen); + ASSERT(memcmp(ptext, decrypted, datalen) =3D=3D 0); + } +} +#endif /* ENABLE_ALG_TESTS */ + +static void essiv_generate_iv(const u8 orig_key[AES_128_KEY_SIZE], + const u8 orig_iv[AES_BLOCK_SIZE], + u8 real_iv[AES_BLOCK_SIZE]) +{ + u8 essiv_key[SHA256_DIGEST_SIZE]; + struct aes_key essiv; + + /* AES encrypt the original IV using a hash of the original key */ + STATIC_ASSERT(SHA256_DIGEST_SIZE =3D=3D AES_256_KEY_SIZE); + sha256(orig_key, AES_128_KEY_SIZE, essiv_key); + aes_setkey(&essiv, essiv_key, AES_256_KEY_SIZE); + aes_encrypt(&essiv, orig_iv, real_iv); +} + +static void aes_128_cbc_essiv_encrypt(const u8 key[AES_128_KEY_SIZE], + const u8 iv[AES_BLOCK_SIZE], + const u8 *src, u8 *dst, size_t nbytes) +{ + struct aes_key k; + u8 real_iv[AES_BLOCK_SIZE]; + + aes_setkey(&k, key, AES_128_KEY_SIZE); + essiv_generate_iv(key, iv, real_iv); + aes_cbc_encrypt(&k, real_iv, src, dst, nbytes); +} + +static void aes_128_cbc_essiv_decrypt(const u8 key[AES_128_KEY_SIZE], + const u8 iv[AES_BLOCK_SIZE], + const u8 *src, u8 *dst, size_t nbytes) +{ + struct aes_key k; + u8 real_iv[AES_BLOCK_SIZE]; + + aes_setkey(&k, key, AES_128_KEY_SIZE); + essiv_generate_iv(key, iv, real_iv); + aes_cbc_decrypt(&k, real_iv, src, dst, nbytes); +} + +static void aes_128_cts_cbc_encrypt(const u8 key[AES_128_KEY_SIZE], + const u8 iv[AES_BLOCK_SIZE], + const u8 *src, u8 *dst, size_t nbytes) +{ + aes_cts_cbc_encrypt(key, AES_128_KEY_SIZE, iv, src, dst, nbytes); +} + +static void aes_128_cts_cbc_decrypt(const u8 key[AES_128_KEY_SIZE], + const u8 iv[AES_BLOCK_SIZE], + const u8 *src, u8 *dst, size_t nbytes) +{ + aes_cts_cbc_decrypt(key, AES_128_KEY_SIZE, iv, src, dst, nbytes); +} + +/*----------------------------------------------------------------------= ------* + * XChaCha12 stream cipher = * + *----------------------------------------------------------------------= ------*/ + +/* + * References: + * - "XChaCha: eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305" + * https://tools.ietf.org/html/draft-arciszewski-xchacha-03 + * + * - "ChaCha, a variant of Salsa20" + * https://cr.yp.to/chacha/chacha-20080128.pdf + * + * - "Extending the Salsa20 nonce" + * https://cr.yp.to/snuffle/xsalsa-20081128.pdf + */ + +#define CHACHA_KEY_SIZE 32 +#define XCHACHA_KEY_SIZE CHACHA_KEY_SIZE +#define XCHACHA_NONCE_SIZE 24 + +static void chacha_init_state(u32 state[16], const u8 key[CHACHA_KEY_SIZ= E], + const u8 iv[16]) +{ + static const u8 consts[16] =3D "expand 32-byte k"; + int i; + + for (i =3D 0; i < 4; i++) + state[i] =3D get_unaligned_le32(&consts[i * sizeof(__le32)]); + for (i =3D 0; i < 8; i++) + state[4 + i] =3D get_unaligned_le32(&key[i * sizeof(__le32)]); + for (i =3D 0; i < 4; i++) + state[12 + i] =3D get_unaligned_le32(&iv[i * sizeof(__le32)]); +} + +#define CHACHA_QUARTERROUND(a, b, c, d) \ + do { \ + a +=3D b; d =3D rol32(d ^ a, 16); \ + c +=3D d; b =3D rol32(b ^ c, 12); \ + a +=3D b; d =3D rol32(d ^ a, 8); \ + c +=3D d; b =3D rol32(b ^ c, 7); \ + } while (0) + +static void chacha_permute(u32 x[16], int nrounds) +{ + do { + /* column round */ + CHACHA_QUARTERROUND(x[0], x[4], x[8], x[12]); + CHACHA_QUARTERROUND(x[1], x[5], x[9], x[13]); + CHACHA_QUARTERROUND(x[2], x[6], x[10], x[14]); + CHACHA_QUARTERROUND(x[3], x[7], x[11], x[15]); + + /* diagonal round */ + CHACHA_QUARTERROUND(x[0], x[5], x[10], x[15]); + CHACHA_QUARTERROUND(x[1], x[6], x[11], x[12]); + CHACHA_QUARTERROUND(x[2], x[7], x[8], x[13]); + CHACHA_QUARTERROUND(x[3], x[4], x[9], x[14]); + } while ((nrounds -=3D 2) !=3D 0); +} + +static void xchacha(const u8 key[XCHACHA_KEY_SIZE], + const u8 nonce[XCHACHA_NONCE_SIZE], + const u8 *src, u8 *dst, size_t nbytes, int nrounds) +{ + u32 state[16]; + u8 real_key[CHACHA_KEY_SIZE]; + u8 real_iv[16] =3D { 0 }; + size_t i, j; + + /* Compute real key using original key and first 128 nonce bits */ + chacha_init_state(state, key, nonce); + chacha_permute(state, nrounds); + for (i =3D 0; i < 8; i++) /* state words 0..3, 12..15 */ + put_unaligned_le32(state[(i < 4 ? 0 : 8) + i], + &real_key[i * sizeof(__le32)]); + + /* Now do regular ChaCha, using real key and remaining nonce bits */ + memcpy(&real_iv[8], nonce + 16, 8); + chacha_init_state(state, real_key, real_iv); + for (i =3D 0; i < nbytes; i +=3D 64) { + u32 x[16]; + __le32 keystream[16]; + + memcpy(x, state, 64); + chacha_permute(x, nrounds); + for (j =3D 0; j < 16; j++) + keystream[j] =3D cpu_to_le32(x[j] + state[j]); + xor(&dst[i], &src[i], (u8 *)keystream, MIN(nbytes - i, 64)); + if (++state[12] =3D=3D 0) + state[13]++; + } +} + +static void xchacha12(const u8 key[XCHACHA_KEY_SIZE], + const u8 nonce[XCHACHA_NONCE_SIZE], + const u8 *src, u8 *dst, size_t nbytes) +{ + xchacha(key, nonce, src, dst, nbytes, 12); +} + +/*----------------------------------------------------------------------= ------* + * Poly1305 = * + *----------------------------------------------------------------------= ------*/ + +/* + * Note: this is only the Poly1305 =CE=B5-almost-=E2=88=86-universal has= h function, not the + * full Poly1305 MAC. I.e., it doesn't add anything at the end. + */ + +#define POLY1305_KEY_SIZE 16 +#define POLY1305_BLOCK_SIZE 16 + +static void poly1305(const u8 key[POLY1305_KEY_SIZE], + const u8 *msg, size_t msglen, le128 *out) +{ + const u32 limb_mask =3D 0x3ffffff; /* limbs are base 2^26 */ + const u64 r0 =3D (get_unaligned_le32(key + 0) >> 0) & 0x3ffffff; + const u64 r1 =3D (get_unaligned_le32(key + 3) >> 2) & 0x3ffff03; + const u64 r2 =3D (get_unaligned_le32(key + 6) >> 4) & 0x3ffc0ff; + const u64 r3 =3D (get_unaligned_le32(key + 9) >> 6) & 0x3f03fff; + const u64 r4 =3D (get_unaligned_le32(key + 12) >> 8) & 0x00fffff; + u32 h0 =3D 0, h1 =3D 0, h2 =3D 0, h3 =3D 0, h4 =3D 0; + u32 g0, g1, g2, g3, g4, ge_p_mask; + + /* Partial block support is not necessary for Adiantum */ + ASSERT(msglen % POLY1305_BLOCK_SIZE =3D=3D 0); + + while (msglen) { + u64 d0, d1, d2, d3, d4; + + /* h +=3D *msg */ + h0 +=3D (get_unaligned_le32(msg + 0) >> 0) & limb_mask; + h1 +=3D (get_unaligned_le32(msg + 3) >> 2) & limb_mask; + h2 +=3D (get_unaligned_le32(msg + 6) >> 4) & limb_mask; + h3 +=3D (get_unaligned_le32(msg + 9) >> 6) & limb_mask; + h4 +=3D (get_unaligned_le32(msg + 12) >> 8) | (1 << 24); + + /* h *=3D r */ + d0 =3D h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1; + d1 =3D h0*r1 + h1*r0 + h2*5*r4 + h3*5*r3 + h4*5*r2; + d2 =3D h0*r2 + h1*r1 + h2*r0 + h3*5*r4 + h4*5*r3; + d3 =3D h0*r3 + h1*r2 + h2*r1 + h3*r0 + h4*5*r4; + d4 =3D h0*r4 + h1*r3 + h2*r2 + h3*r1 + h4*r0; + + /* (partial) h %=3D 2^130 - 5 */ + d1 +=3D d0 >> 26; h0 =3D d0 & limb_mask; + d2 +=3D d1 >> 26; h1 =3D d1 & limb_mask; + d3 +=3D d2 >> 26; h2 =3D d2 & limb_mask; + d4 +=3D d3 >> 26; h3 =3D d3 & limb_mask; + h0 +=3D (d4 >> 26) * 5; h4 =3D d4 & limb_mask; + h1 +=3D h0 >> 26; h0 &=3D limb_mask; + + msg +=3D POLY1305_BLOCK_SIZE; + msglen -=3D POLY1305_BLOCK_SIZE; + } + + /* fully carry h */ + h2 +=3D (h1 >> 26); h1 &=3D limb_mask; + h3 +=3D (h2 >> 26); h2 &=3D limb_mask; + h4 +=3D (h3 >> 26); h3 &=3D limb_mask; + h0 +=3D (h4 >> 26) * 5; h4 &=3D limb_mask; + h1 +=3D (h0 >> 26); h0 &=3D limb_mask; + + /* if (h >=3D 2^130 - 5) h -=3D 2^130 - 5; */ + g0 =3D h0 + 5; + g1 =3D h1 + (g0 >> 26); g0 &=3D limb_mask; + g2 =3D h2 + (g1 >> 26); g1 &=3D limb_mask; + g3 =3D h3 + (g2 >> 26); g2 &=3D limb_mask; + g4 =3D h4 + (g3 >> 26); g3 &=3D limb_mask; + ge_p_mask =3D ~((g4 >> 26) - 1); /* all 1's if h >=3D 2^130 - 5, else 0= */ + h0 =3D (h0 & ~ge_p_mask) | (g0 & ge_p_mask); + h1 =3D (h1 & ~ge_p_mask) | (g1 & ge_p_mask); + h2 =3D (h2 & ~ge_p_mask) | (g2 & ge_p_mask); + h3 =3D (h3 & ~ge_p_mask) | (g3 & ge_p_mask); + h4 =3D (h4 & ~ge_p_mask) | (g4 & ge_p_mask & limb_mask); + + /* h %=3D 2^128 */ + out->lo =3D cpu_to_le64(((u64)h2 << 52) | ((u64)h1 << 26) | h0); + out->hi =3D cpu_to_le64(((u64)h4 << 40) | ((u64)h3 << 14) | (h2 >> 12))= ; +} + +/*----------------------------------------------------------------------= ------* + * Adiantum encryption mode = * + *----------------------------------------------------------------------= ------*/ + +/* + * Reference: "Adiantum: length-preserving encryption for entry-level pr= ocessors" + * https://tosc.iacr.org/index.php/ToSC/article/view/7360 + */ + +#define ADIANTUM_KEY_SIZE 32 +#define ADIANTUM_IV_SIZE 32 +#define ADIANTUM_HASH_KEY_SIZE ((2 * POLY1305_KEY_SIZE) + NH_KEY_SIZE) + +#define NH_KEY_SIZE 1072 +#define NH_KEY_WORDS (NH_KEY_SIZE / sizeof(u32)) +#define NH_BLOCK_SIZE 1024 +#define NH_HASH_SIZE 32 +#define NH_MESSAGE_UNIT 16 + +static u64 nh_pass(const u32 *key, const u8 *msg, size_t msglen) +{ + u64 sum =3D 0; + + ASSERT(msglen % NH_MESSAGE_UNIT =3D=3D 0); + while (msglen) { + sum +=3D (u64)(u32)(get_unaligned_le32(msg + 0) + key[0]) * + (u32)(get_unaligned_le32(msg + 8) + key[2]); + sum +=3D (u64)(u32)(get_unaligned_le32(msg + 4) + key[1]) * + (u32)(get_unaligned_le32(msg + 12) + key[3]); + key +=3D NH_MESSAGE_UNIT / sizeof(key[0]); + msg +=3D NH_MESSAGE_UNIT; + msglen -=3D NH_MESSAGE_UNIT; + } + return sum; +} + +/* NH =CE=B5-almost-universal hash function */ +static void nh(const u32 *key, const u8 *msg, size_t msglen, + u8 result[NH_HASH_SIZE]) +{ + size_t i; + + for (i =3D 0; i < NH_HASH_SIZE; i +=3D sizeof(__le64)) { + put_unaligned_le64(nh_pass(key, msg, msglen), &result[i]); + key +=3D NH_MESSAGE_UNIT / sizeof(key[0]); + } +} + +/* Adiantum's =CE=B5-almost-=E2=88=86-universal hash function */ +static void adiantum_hash(const u8 key[ADIANTUM_HASH_KEY_SIZE], + const u8 iv[ADIANTUM_IV_SIZE], + const u8 *msg, size_t msglen, le128 *result) +{ + const u8 *header_poly_key =3D key; + const u8 *msg_poly_key =3D header_poly_key + POLY1305_KEY_SIZE; + const u8 *nh_key =3D msg_poly_key + POLY1305_KEY_SIZE; + u32 nh_key_words[NH_KEY_WORDS]; + u8 header[POLY1305_BLOCK_SIZE + ADIANTUM_IV_SIZE]; + const size_t num_nh_blocks =3D DIV_ROUND_UP(msglen, NH_BLOCK_SIZE); + u8 *nh_hashes =3D xmalloc(num_nh_blocks * NH_HASH_SIZE); + const size_t padded_msglen =3D ROUND_UP(msglen, NH_MESSAGE_UNIT); + u8 *padded_msg =3D xmalloc(padded_msglen); + le128 hash1, hash2; + size_t i; + + for (i =3D 0; i < NH_KEY_WORDS; i++) + nh_key_words[i] =3D get_unaligned_le32(&nh_key[i * sizeof(u32)]); + + /* Hash tweak and message length with first Poly1305 key */ + put_unaligned_le64((u64)msglen * 8, header); + put_unaligned_le64(0, &header[sizeof(__le64)]); + memcpy(&header[POLY1305_BLOCK_SIZE], iv, ADIANTUM_IV_SIZE); + poly1305(header_poly_key, header, sizeof(header), &hash1); + + /* Hash NH hashes of message blocks using second Poly1305 key */ + /* (using a super naive way of handling the padding) */ + memcpy(padded_msg, msg, msglen); + memset(&padded_msg[msglen], 0, padded_msglen - msglen); + for (i =3D 0; i < num_nh_blocks; i++) { + nh(nh_key_words, &padded_msg[i * NH_BLOCK_SIZE], + MIN(NH_BLOCK_SIZE, padded_msglen - (i * NH_BLOCK_SIZE)), + &nh_hashes[i * NH_HASH_SIZE]); + } + poly1305(msg_poly_key, nh_hashes, num_nh_blocks * NH_HASH_SIZE, &hash2)= ; + + /* Add the two hashes together to get the final hash */ + le128_add(result, &hash1, &hash2); + + free(nh_hashes); + free(padded_msg); +} + +static void adiantum_crypt(const u8 key[ADIANTUM_KEY_SIZE], + const u8 iv[ADIANTUM_IV_SIZE], const u8 *src, + u8 *dst, size_t nbytes, bool decrypting) +{ + u8 subkeys[AES_256_KEY_SIZE + ADIANTUM_HASH_KEY_SIZE] =3D { 0 }; + struct aes_key aes_key; + union { + u8 nonce[XCHACHA_NONCE_SIZE]; + le128 block; + } u =3D { .nonce =3D { 1 } }; + const size_t bulk_len =3D nbytes - sizeof(u.block); + le128 hash; + + ASSERT(nbytes >=3D sizeof(u.block)); + + /* Derive subkeys */ + xchacha12(key, u.nonce, subkeys, subkeys, sizeof(subkeys)); + aes_setkey(&aes_key, subkeys, AES_256_KEY_SIZE); + + /* Hash left part and add to right part */ + adiantum_hash(&subkeys[AES_256_KEY_SIZE], iv, src, bulk_len, &hash); + memcpy(&u.block, &src[bulk_len], sizeof(u.block)); + le128_add(&u.block, &u.block, &hash); + + if (!decrypting) /* Encrypt right part with block cipher */ + aes_encrypt(&aes_key, u.nonce, u.nonce); + + /* Encrypt left part with stream cipher, using the computed nonce */ + u.nonce[sizeof(u.block)] =3D 1; + xchacha12(key, u.nonce, src, dst, bulk_len); + + if (decrypting) /* Decrypt right part with block cipher */ + aes_decrypt(&aes_key, u.nonce, u.nonce); + + /* Finalize right part by subtracting hash of left part */ + adiantum_hash(&subkeys[AES_256_KEY_SIZE], iv, dst, bulk_len, &hash); + le128_sub(&u.block, &u.block, &hash); + memcpy(&dst[bulk_len], &u.block, sizeof(u.block)); +} + +static void adiantum_encrypt(const u8 key[ADIANTUM_KEY_SIZE], + const u8 iv[ADIANTUM_IV_SIZE], + const u8 *src, u8 *dst, size_t nbytes) +{ + adiantum_crypt(key, iv, src, dst, nbytes, false); +} + +static void adiantum_decrypt(const u8 key[ADIANTUM_KEY_SIZE], + const u8 iv[ADIANTUM_IV_SIZE], + const u8 *src, u8 *dst, size_t nbytes) +{ + adiantum_crypt(key, iv, src, dst, nbytes, true); +} + +#ifdef ENABLE_ALG_TESTS +#include +#include +#define SOL_ALG 279 +static void af_alg_crypt(int algfd, int op, const u8 *key, size_t keylen= , + const u8 *iv, size_t ivlen, + const u8 *src, u8 *dst, size_t datalen) +{ + size_t controllen =3D CMSG_SPACE(sizeof(int)) + + CMSG_SPACE(sizeof(struct af_alg_iv) + ivlen); + u8 *control =3D xmalloc(controllen); + struct iovec iov =3D { .iov_base =3D (u8 *)src, .iov_len =3D datalen }; + struct msghdr msg =3D { + .msg_iov =3D &iov, + .msg_iovlen =3D 1, + .msg_control =3D control, + .msg_controllen =3D controllen, + }; + struct cmsghdr *cmsg; + struct af_alg_iv *algiv; + int reqfd; + + memset(control, 0, controllen); + + cmsg =3D CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len =3D CMSG_LEN(sizeof(int)); + cmsg->cmsg_level =3D SOL_ALG; + cmsg->cmsg_type =3D ALG_SET_OP; + *(int *)CMSG_DATA(cmsg) =3D op; + + cmsg =3D CMSG_NXTHDR(&msg, cmsg); + cmsg->cmsg_len =3D CMSG_LEN(sizeof(struct af_alg_iv) + ivlen); + cmsg->cmsg_level =3D SOL_ALG; + cmsg->cmsg_type =3D ALG_SET_IV; + algiv =3D (struct af_alg_iv *)CMSG_DATA(cmsg); + algiv->ivlen =3D ivlen; + memcpy(algiv->iv, iv, ivlen); + + if (setsockopt(algfd, SOL_ALG, ALG_SET_KEY, key, keylen) !=3D 0) + die_errno("can't set key on AF_ALG socket"); + + reqfd =3D accept(algfd, NULL, NULL); + if (reqfd < 0) + die_errno("can't accept() AF_ALG socket"); + if (sendmsg(reqfd, &msg, 0) !=3D datalen) + die_errno("can't sendmsg() AF_ALG request socket"); + if (xread(reqfd, dst, datalen) !=3D datalen) + die("short read from AF_ALG request socket"); + close(reqfd); + + free(control); +} + +static void test_adiantum(void) +{ + int algfd =3D socket(AF_ALG, SOCK_SEQPACKET, 0); + struct sockaddr_alg addr =3D { + .salg_type =3D "skcipher", + .salg_name =3D "adiantum(xchacha12,aes)", + }; + unsigned long num_tests =3D NUM_ALG_TEST_ITERATIONS; + + if (algfd < 0) + die_errno("can't create AF_ALG socket"); + if (bind(algfd, (struct sockaddr *)&addr, sizeof(addr)) !=3D 0) + die_errno("can't bind AF_ALG socket to Adiantum algorithm"); + + while (num_tests--) { + u8 key[ADIANTUM_KEY_SIZE]; + u8 iv[ADIANTUM_IV_SIZE]; + u8 ptext[4096]; + u8 ctext[sizeof(ptext)]; + u8 ref_ctext[sizeof(ptext)]; + u8 decrypted[sizeof(ptext)]; + const size_t datalen =3D 16 + (rand() % (sizeof(ptext) - 15)); + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + rand_bytes(ptext, datalen); + + adiantum_encrypt(key, iv, ptext, ctext, datalen); + af_alg_crypt(algfd, ALG_OP_ENCRYPT, key, sizeof(key), + iv, sizeof(iv), ptext, ref_ctext, datalen); + ASSERT(memcmp(ctext, ref_ctext, datalen) =3D=3D 0); + + adiantum_decrypt(key, iv, ctext, decrypted, datalen); + ASSERT(memcmp(ptext, decrypted, datalen) =3D=3D 0); + } + close(algfd); +} +#endif /* ENABLE_ALG_TESTS */ + +/*----------------------------------------------------------------------= ------* + * Main program = * + *----------------------------------------------------------------------= ------*/ + +#define FILE_NONCE_SIZE 16 +#define MAX_KEY_SIZE 64 + +static const struct fscrypt_cipher { + const char *name; + void (*encrypt)(const u8 *key, const u8 *iv, const u8 *src, + u8 *dst, size_t nbytes); + void (*decrypt)(const u8 *key, const u8 *iv, const u8 *src, + u8 *dst, size_t nbytes); + int keysize; + int min_input_size; +} fscrypt_ciphers[] =3D { + { + .name =3D "AES-256-XTS", + .encrypt =3D aes_256_xts_encrypt, + .decrypt =3D aes_256_xts_decrypt, + .keysize =3D 2 * AES_256_KEY_SIZE, + }, { + .name =3D "AES-256-CTS-CBC", + .encrypt =3D aes_256_cts_cbc_encrypt, + .decrypt =3D aes_256_cts_cbc_decrypt, + .keysize =3D AES_256_KEY_SIZE, + .min_input_size =3D AES_BLOCK_SIZE, + }, { + .name =3D "AES-128-CBC-ESSIV", + .encrypt =3D aes_128_cbc_essiv_encrypt, + .decrypt =3D aes_128_cbc_essiv_decrypt, + .keysize =3D AES_128_KEY_SIZE, + }, { + .name =3D "AES-128-CTS-CBC", + .encrypt =3D aes_128_cts_cbc_encrypt, + .decrypt =3D aes_128_cts_cbc_decrypt, + .keysize =3D AES_128_KEY_SIZE, + .min_input_size =3D AES_BLOCK_SIZE, + }, { + .name =3D "Adiantum", + .encrypt =3D adiantum_encrypt, + .decrypt =3D adiantum_decrypt, + .keysize =3D ADIANTUM_KEY_SIZE, + .min_input_size =3D AES_BLOCK_SIZE, + } +}; + +static const struct fscrypt_cipher *find_fscrypt_cipher(const char *name= ) +{ + size_t i; + + for (i =3D 0; i < ARRAY_SIZE(fscrypt_ciphers); i++) { + if (strcmp(fscrypt_ciphers[i].name, name) =3D=3D 0) + return &fscrypt_ciphers[i]; + } + return NULL; +} + +struct fscrypt_iv { + union { + __le64 block_num; + u8 bytes[32]; + }; +}; + +static void crypt_loop(const struct fscrypt_cipher *cipher, const u8 *ke= y, + struct fscrypt_iv *iv, bool decrypting, + size_t block_size, size_t padding) +{ + u8 *buf =3D xmalloc(block_size); + size_t res; + + while ((res =3D xread(STDIN_FILENO, buf, block_size)) > 0) { + size_t crypt_len =3D block_size; + + if (padding > 0) { + crypt_len =3D MAX(res, cipher->min_input_size); + crypt_len =3D ROUND_UP(crypt_len, padding); + crypt_len =3D MIN(crypt_len, block_size); + } + ASSERT(crypt_len >=3D res); + memset(&buf[res], 0, crypt_len - res); + + if (decrypting) + cipher->decrypt(key, iv->bytes, buf, buf, crypt_len); + else + cipher->encrypt(key, iv->bytes, buf, buf, crypt_len); + + full_write(STDOUT_FILENO, buf, crypt_len); + + iv->block_num =3D cpu_to_le64(le64_to_cpu(iv->block_num) + 1); + } + free(buf); +} + +/* The supported key derivation functions */ +enum kdf_algorithm { + KDF_NONE, + KDF_AES_128_ECB, +}; + +static enum kdf_algorithm parse_kdf_algorithm(const char *arg) +{ + if (strcmp(arg, "none") =3D=3D 0) + return KDF_NONE; + if (strcmp(arg, "AES-128-ECB") =3D=3D 0) + return KDF_AES_128_ECB; + die("Unknown KDF: %s", arg); +} + +/* + * Get the key and starting IV with which the encryption will actually b= e done. + * If a KDF was specified, a subkey is derived from the master key and f= ile + * nonce. Otherwise, the master key is used directly. + */ +static void get_key_and_iv(const u8 *master_key, size_t master_key_size, + enum kdf_algorithm kdf, + const u8 nonce[FILE_NONCE_SIZE], + u8 *real_key, size_t real_key_size, + struct fscrypt_iv *iv) +{ + struct aes_key aes_key; + size_t i; + + ASSERT(real_key_size <=3D master_key_size); + + memset(iv, 0, sizeof(*iv)); + + switch (kdf) { + case KDF_NONE: + memcpy(real_key, master_key, real_key_size); + if (nonce !=3D NULL) + memcpy(&iv->bytes[8], nonce, FILE_NONCE_SIZE); + break; + case KDF_AES_128_ECB: + if (nonce =3D=3D NULL) + die("--file-nonce is required with --kdf=3DAES-128-ECB"); + STATIC_ASSERT(FILE_NONCE_SIZE =3D=3D AES_128_KEY_SIZE); + ASSERT(real_key_size % AES_BLOCK_SIZE =3D=3D 0); + aes_setkey(&aes_key, nonce, AES_128_KEY_SIZE); + for (i =3D 0; i < real_key_size; i +=3D AES_BLOCK_SIZE) + aes_encrypt(&aes_key, &master_key[i], &real_key[i]); + break; + default: + ASSERT(0); + } +} + +enum { + OPT_BLOCK_SIZE, + OPT_DECRYPT, + OPT_FILE_NONCE, + OPT_HELP, + OPT_KDF, + OPT_PADDING, +}; + +static const struct option longopts[] =3D { + { "block-size", required_argument, NULL, OPT_BLOCK_SIZE }, + { "decrypt", no_argument, NULL, OPT_DECRYPT }, + { "file-nonce", required_argument, NULL, OPT_FILE_NONCE }, + { "help", no_argument, NULL, OPT_HELP }, + { "kdf", required_argument, NULL, OPT_KDF }, + { "padding", required_argument, NULL, OPT_PADDING }, + { NULL, 0, NULL, 0 }, +}; + +int main(int argc, char *argv[]) +{ + size_t block_size =3D 4096; + bool decrypting =3D false; + u8 _file_nonce[FILE_NONCE_SIZE]; + u8 *file_nonce =3D NULL; + enum kdf_algorithm kdf =3D KDF_NONE; + size_t padding =3D 0; + const struct fscrypt_cipher *cipher; + u8 master_key[MAX_KEY_SIZE]; + int master_key_size; + u8 real_key[MAX_KEY_SIZE]; + struct fscrypt_iv iv; + char *tmp; + int c; + + aes_init(); + +#ifdef ENABLE_ALG_TESTS + test_aes(); + test_sha2(); + test_aes_256_xts(); + test_aes_256_cts_cbc(); + test_adiantum(); +#endif + + while ((c =3D getopt_long(argc, argv, "", longopts, NULL)) !=3D -1) { + switch (c) { + case OPT_BLOCK_SIZE: + block_size =3D strtoul(optarg, &tmp, 10); + if (block_size <=3D 0 || *tmp) + die("Invalid block size: %s", optarg); + break; + case OPT_DECRYPT: + decrypting =3D true; + break; + case OPT_FILE_NONCE: + if (hex2bin(optarg, _file_nonce, FILE_NONCE_SIZE) !=3D + FILE_NONCE_SIZE) + die("Invalid file nonce: %s", optarg); + file_nonce =3D _file_nonce; + break; + case OPT_HELP: + usage(stdout); + return 0; + case OPT_KDF: + kdf =3D parse_kdf_algorithm(optarg); + break; + case OPT_PADDING: + padding =3D strtoul(optarg, &tmp, 10); + if (padding <=3D 0 || *tmp || !is_power_of_2(padding) || + padding > INT_MAX) + die("Invalid padding amount: %s", optarg); + break; + default: + usage(stderr); + return 2; + } + } + argc -=3D optind; + argv +=3D optind; + + if (argc !=3D 2) { + usage(stderr); + return 2; + } + + cipher =3D find_fscrypt_cipher(argv[0]); + if (cipher =3D=3D NULL) + die("Unknown cipher: %s", argv[0]); + + if (block_size < cipher->min_input_size) + die("Block size of %zu bytes is too small for cipher %s", + block_size, cipher->name); + + master_key_size =3D hex2bin(argv[1], master_key, MAX_KEY_SIZE); + if (master_key_size < 0) + die("Invalid master_key: %s", argv[1]); + if (master_key_size < cipher->keysize) + die("Master key is too short for cipher %s", cipher->name); + + get_key_and_iv(master_key, master_key_size, kdf, file_nonce, + real_key, cipher->keysize, &iv); + + crypt_loop(cipher, real_key, &iv, decrypting, block_size, padding); + return 0; +} --=20 2.22.0.rc1.257.g3120a18244-goog From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eric Biggers Subject: [PATCH v2 2/7] fscrypt-crypt-util: add utility for reproducing fscrypt encrypted data Date: Fri, 24 May 2019 15:04:20 -0700 Message-ID: <20190524220425.201170-3-ebiggers@kernel.org> References: <20190524220425.201170-1-ebiggers@kernel.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1hUIJ2-0002PH-7w for linux-f2fs-devel@lists.sourceforge.net; Fri, 24 May 2019 22:04:52 +0000 Received: from mail.kernel.org ([198.145.29.99]) by sfi-mx-4.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1hUIIx-007hL0-RW for linux-f2fs-devel@lists.sourceforge.net; Fri, 24 May 2019 22:04:51 +0000 In-Reply-To: <20190524220425.201170-1-ebiggers@kernel.org> List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linux-f2fs-devel-bounces@lists.sourceforge.net To: fstests@vger.kernel.org Cc: linux-fscrypt@vger.kernel.org, linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net RnJvbTogRXJpYyBCaWdnZXJzIDxlYmlnZ2Vyc0Bnb29nbGUuY29tPgoKQWRkIGEgdXRpbGl0eSBw cm9ncmFtIHRoYXQgY2FuIHJlcHJvZHVjZSBlbmNyeXB0ZWQgY29udGVudHMgYW5kCmZpbGVuYW1l cy4gIEl0IGltcGxlbWVudHMgYWxsIGVuY3J5cHRpb24gYWxnb3JpdGhtcyBjdXJyZW50bHkgc3Vw cG9ydGVkCmJ5IGZzY3J5cHQgKGEuay5hLiBleHQ0LCBmMmZzLCBhbmQgdWJpZnMgZW5jcnlwdGlv biksIGFuZCBpdCBnZW5lcmF0ZXMKSVZzIGluIHRoZSBzYW1lIHdheS4gIFRoZSBwcm9ncmFtIHRh a2VzIHRoZSBhbGdvcml0aG0gYW5kIG1hc3RlciBrZXkgb24KdGhlIGNvbW1hbmQgbGluZSwgYW5k IGVuY3J5cHRzIHN0ZGluIHRvIHN0ZG91dC4KCkEgZmlsZSBub25jZSBtYXkgYWxzbyBiZSBwYXNz ZWQgb24gdGhlIGNvbW1hbmQgbGluZSwgYW5kIHRoZSBwcm9ncmFtCndpbGwgInR3ZWFrIiB0aGUg ZW5jcnlwdGlvbiB1c2luZyB0aGlzIG5vbmNlIGluIHRoZSBzYW1lIHdheSB0aGUga2VybmVsCmRv ZXMgLS0gZWl0aGVyIGJ5IGRlcml2aW5nIGEgc3Via2V5LCBvciBieSBpbmNsdWRpbmcgdGhlIG5v bmNlIGluIHRoZQpJVnMuICBUaGUgYmxvY2sgc2l6ZSBhbmQgcGFkZGluZyBhbW91bnQgbWF5IGFs c28gYmUgc3BlY2lmaWVkLgoKTm8gZGVwZW5kZW5jaWVzIGFyZSBhZGRlZCwgYXMgYWxsIGFsZ29y aXRobXMgaW1wbGVtZW50ZWQgZnJvbSBzY3JhdGNoLgoKU2lnbmVkLW9mZi1ieTogRXJpYyBCaWdn ZXJzIDxlYmlnZ2Vyc0Bnb29nbGUuY29tPgotLS0KIC5naXRpZ25vcmUgICAgICAgICAgICAgICB8 ICAgIDEgKwogc3JjL01ha2VmaWxlICAgICAgICAgICAgIHwgICAgMyArLQogc3JjL2ZzY3J5cHQt Y3J5cHQtdXRpbC5jIHwgMTYzMyArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KwogMyBmaWxlcyBjaGFuZ2VkLCAxNjM2IGluc2VydGlvbnMoKyksIDEgZGVsZXRpb24oLSkKIGNy ZWF0ZSBtb2RlIDEwMDY0NCBzcmMvZnNjcnlwdC1jcnlwdC11dGlsLmMKCmRpZmYgLS1naXQgYS8u Z2l0aWdub3JlIGIvLmdpdGlnbm9yZQppbmRleCBjMTNmYjcxMy4uMTEyMzJiZTcgMTAwNjQ0Ci0t LSBhLy5naXRpZ25vcmUKKysrIGIvLmdpdGlnbm9yZQpAQCAtNzMsNiArNzMsNyBAQAogL3NyYy9m aWxsCiAvc3JjL2ZpbGwyCiAvc3JjL2ZzX3Blcm1zCisvc3JjL2ZzY3J5cHQtY3J5cHQtdXRpbAog L3NyYy9mc3N1bQogL3NyYy9mc3Rlc3QKIC9zcmMvZnN5bmMtZXJyCmRpZmYgLS1naXQgYS9zcmMv TWFrZWZpbGUgYi9zcmMvTWFrZWZpbGUKaW5kZXggNDA1N2Q3YjMuLjlkM2QyNTI5IDEwMDY0NAot LS0gYS9zcmMvTWFrZWZpbGUKKysrIGIvc3JjL01ha2VmaWxlCkBAIC0yNyw3ICsyNyw4IEBAIExJ TlVYX1RBUkdFVFMgPSB4ZnNjdGwgYnN0YXQgdF9tdGFiIGdldGRldmljZXNpemUgcHJlYWxsb19y d19wYXR0ZXJuX3JlYWRlciBcCiAJcmVuYW1lYXQyIHRfZ2V0Y3dkIGU0Y29tcGFjdCB0ZXN0LW5l eHRxdW90YSBwdW5jaC1hbHRlcm5hdGluZyBcCiAJYXR0ci1saXN0LWJ5LWhhbmRsZS1jdXJzb3It dGVzdCBsaXN0eGF0dHIgZGlvLWludGVybGVhdmVkIHRfZGlyX3R5cGUgXAogCWRpby1pbnZhbGlk YXRlLWNhY2hlIHN0YXRfdGVzdCB0X2VuY3J5cHRlZF9kX3JldmFsaWRhdGUgXAotCWF0dHJfcmVw bGFjZV90ZXN0IHN3YXBvbiBta3N3YXAgdF9hdHRyX2NvcnJ1cHRpb24gdF9vcGVuX3RtcGZpbGVz CisJYXR0cl9yZXBsYWNlX3Rlc3Qgc3dhcG9uIG1rc3dhcCB0X2F0dHJfY29ycnVwdGlvbiB0X29w ZW5fdG1wZmlsZXMgXAorCWZzY3J5cHQtY3J5cHQtdXRpbAogCiBTVUJESVJTID0gbG9nLXdyaXRl cyBwZXJmCiAKZGlmZiAtLWdpdCBhL3NyYy9mc2NyeXB0LWNyeXB0LXV0aWwuYyBiL3NyYy9mc2Ny eXB0LWNyeXB0LXV0aWwuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMC4uODE1 NzRhNTUKLS0tIC9kZXYvbnVsbAorKysgYi9zcmMvZnNjcnlwdC1jcnlwdC11dGlsLmMKQEAgLTAs MCArMSwxNjMzIEBACisvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMCsKKy8qCisg KiBmc2NyeXB0LWNyeXB0LXV0aWwuYyAtIHV0aWxpdHkgZm9yIHZlcmlmeWluZyBmc2NyeXB0LWVu Y3J5cHRlZCBkYXRhCisgKgorICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQworICovCisKKy8q CisgKiBUaGlzIHByb2dyYW0gaW1wbGVtZW50cyBhbGwgY3J5cHRvIGFsZ29yaXRobXMgc3VwcG9y dGVkIGJ5IGZzY3J5cHQgKGEuay5hLgorICogZXh0NCwgZjJmcywgYW5kIHViaWZzIGVuY3J5cHRp b24pLCBmb3IgdGhlIHB1cnBvc2Ugb2YgdmVyaWZ5aW5nIHRoZQorICogY29ycmVjdG5lc3Mgb2Yg dGhlIGNpcGhlcnRleHQgc3RvcmVkIG9uLWRpc2suICBTZWUgdXNhZ2UoKSBiZWxvdy4KKyAqCisg KiBBbGwgYWxnb3JpdGhtcyBhcmUgaW1wbGVtZW50ZWQgaW4gcG9ydGFibGUgQyBjb2RlIHRvIGF2 b2lkIGRlcGVuZGluZyBvbgorICogbGliY3J5cHRvIChPcGVuU1NMKSwgYW5kIGJlY2F1c2Ugc29t ZSBmc2NyeXB0LXN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZW4ndAorICogYXZhaWxhYmxlIGluIGxp YmNyeXB0byBhbnl3YXkgKGUuZy4gQWRpYW50dW0pLiAgRm9yIHNpbXBsaWNpdHksIGFsbCBjcnlw dG8KKyAqIGNvZGUgaGVyZSB0cmllcyB0byBmb2xsb3cgdGhlIG1hdGhlbWF0aWNhbCBkZWZpbml0 aW9ucyBkaXJlY3RseSwgd2l0aG91dAorICogb3B0aW1pemluZyBmb3IgcGVyZm9ybWFuY2Ugb3Ig d29ycnlpbmcgYWJvdXQgZm9sbG93aW5nIHNlY3VyaXR5IGJlc3QKKyAqIHByYWN0aWNlcyBzdWNo IGFzIG1pdGlnYXRpbmcgc2lkZS1jaGFubmVsIGF0dGFja3MuICBTbywgb25seSB1c2UgdGhpcyBw cm9ncmFtCisgKiBmb3IgdGVzdGluZyEKKyAqLworCisjaW5jbHVkZSA8YXNtL2J5dGVvcmRlci5o PgorI2luY2x1ZGUgPGVycm5vLmg+CisjaW5jbHVkZSA8Z2V0b3B0Lmg+CisjaW5jbHVkZSA8bGlt aXRzLmg+CisjaW5jbHVkZSA8bGludXgvdHlwZXMuaD4KKyNpbmNsdWRlIDxzdGRhcmcuaD4KKyNp bmNsdWRlIDxzdGRib29sLmg+CisjaW5jbHVkZSA8c3RkaW8uaD4KKyNpbmNsdWRlIDxzdGRsaWIu aD4KKyNpbmNsdWRlIDxzdHJpbmcuaD4KKyNpbmNsdWRlIDx1bmlzdGQuaD4KKworI2RlZmluZSBQ Uk9HUkFNX05BTUUgImZzY3J5cHQtY3J5cHQtdXRpbCIKKworLyoKKyAqIERlZmluZSB0byBlbmFi bGUgdGhlIHRlc3RzIG9mIHRoZSBjcnlwdG8gY29kZSBpbiB0aGlzIGZpbGUuICBJZiBlbmFibGVk LCB5b3UKKyAqIG11c3QgbGluayB0aGlzIHByb2dyYW0gd2l0aCBPcGVuU1NMICgtbGNyeXB0bykg djEuMS4wIG9yIGxhdGVyLCBhbmQgeW91cgorICoga2VybmVsIG5lZWRzIENPTkZJR19DUllQVE9f VVNFUl9BUElfU0tDSVBIRVI9eSBhbmQgQ09ORklHX0NSWVBUT19BRElBTlRVTT15LgorICovCisj dW5kZWYgRU5BQkxFX0FMR19URVNUUworCisjZGVmaW5lIE5VTV9BTEdfVEVTVF9JVEVSQVRJT05T CTEwMDAwCisKK3N0YXRpYyB2b2lkIHVzYWdlKEZJTEUgKmZwKQoreworCWZwdXRzKAorIlVzYWdl OiAiIFBST0dSQU1fTkFNRSAiIFtPUFRJT05dLi4uIENJUEhFUiBNQVNURVJfS0VZXG4iCisiXG4i CisiVXRpbGl0eSBmb3IgdmVyaWZ5aW5nIGZzY3J5cHQtZW5jcnlwdGVkIGRhdGEuICBUaGlzIHBy b2dyYW0gZW5jcnlwdHNcbiIKKyIob3IgZGVjcnlwdHMpIHRoZSBkYXRhIG9uIHN0ZGluIHVzaW5n IHRoZSBnaXZlbiBDSVBIRVIgd2l0aCB0aGUgZ2l2ZW5cbiIKKyJNQVNURVJfS0VZIChvciBhIGtl eSBkZXJpdmVkIGZyb20gaXQsIGlmIGEgS0RGIGlzIHNwZWNpZmllZCksIGFuZCB3cml0ZXMgdGhl XG4iCisicmVzdWx0aW5nIGNpcGhlcnRleHQgKG9yIHBsYWludGV4dCkgdG8gc3Rkb3V0LlxuIgor IlxuIgorIkNJUEhFUiBjYW4gYmUgQUVTLTI1Ni1YVFMsIEFFUy0yNTYtQ1RTLUNCQywgQUVTLTEy OC1DQkMtRVNTSVYsIEFFUy0xMjgtQ1RTLUNCQyxcbiIKKyJvciBBZGlhbnR1bS4gIE1BU1RFUl9L RVkgbXVzdCBiZSBhIGhleCBzdHJpbmcgbG9uZyBlbm91Z2ggZm9yIHRoZSBjaXBoZXIuXG4iCisi XG4iCisiV0FSTklORzogdGhpcyBwcm9ncmFtIGlzIG9ubHkgbWVhbnQgZm9yIHRlc3RpbmcsIG5v dCBmb3IgXCJyZWFsXCIgdXNlIVxuIgorIlxuIgorIk9wdGlvbnM6XG4iCisiICAtLWJsb2NrLXNp emU9QkxPQ0tfU0laRSAgICAgRW5jcnlwdCBlYWNoIEJMT0NLX1NJWkUgYnl0ZXMgaW5kZXBlbmRl bnRseS5cbiIKKyIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlZmF1bHQ6IDQwOTYg Ynl0ZXNcbiIKKyIgIC0tZGVjcnlwdCAgICAgICAgICAgICAgICAgICBEZWNyeXB0IGluc3RlYWQg b2YgZW5jcnlwdFxuIgorIiAgLS1maWxlLW5vbmNlPU5PTkNFICAgICAgICAgIEZpbGUncyBub25j ZSBhcyBhIDMyLWNoYXJhY3RlciBoZXggc3RyaW5nXG4iCisiICAtLWhlbHAgICAgICAgICAgICAg ICAgICAgICAgU2hvdyB0aGlzIGhlbHBcbiIKKyIgIC0ta2RmPUtERiAgICAgICAgICAgICAgICAg ICBLZXkgZGVyaXZhdGlvbiBmdW5jdGlvbiB0byB1c2U6IEFFUy0xMjgtRUNCXG4iCisiICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICBvciBub25lLiAgRGVmYXVsdDogbm9uZVxuIgorIiAg LS1wYWRkaW5nPVBBRERJTkcgICAgICAgICAgIElmIGxhc3QgYmxvY2sgaXMgcGFydGlhbCwgemVy by1wYWQgaXQgdG8gbmV4dFxuIgorIiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUEFE RElORy1ieXRlIGJvdW5kYXJ5LiAgRGVmYXVsdDogQkxPQ0tfU0laRVxuIgorCSwgZnApOworfQor CisvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qCisgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIFV0aWxpdGllcyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqCisgKi0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0qLworCisjZGVmaW5lIEFSUkFZX1NJWkUoQSkJCShzaXplb2YoQSkgLyBz aXplb2YoKEEpWzBdKSkKKyNkZWZpbmUgTUlOKHgsIHkpCQkoKHgpIDwgKHkpID8gKHgpIDogKHkp KQorI2RlZmluZSBNQVgoeCwgeSkJCSgoeCkgPiAoeSkgPyAoeCkgOiAoeSkpCisjZGVmaW5lIFJP VU5EX0RPV04oeCwgeSkJKCh4KSAmIH4oKHkpIC0gMSkpCisjZGVmaW5lIFJPVU5EX1VQKHgsIHkp CQkoKCh4KSArICh5KSAtIDEpICYgfigoeSkgLSAxKSkKKyNkZWZpbmUgRElWX1JPVU5EX1VQKG4s IGQpCSgoKG4pICsgKGQpIC0gMSkgLyAoZCkpCisjZGVmaW5lIFNUQVRJQ19BU1NFUlQoZSkJKCh2 b2lkKXNpemVvZihjaGFyWzEgLSAyKiEoZSldKSkKKwordHlwZWRlZiBfX3U4CQkJdTg7Cit0eXBl ZGVmIF9fdTE2CQkJdTE2OwordHlwZWRlZiBfX3UzMgkJCXUzMjsKK3R5cGVkZWYgX191NjQJCQl1 NjQ7CisKKyNkZWZpbmUgY3B1X3RvX2xlMzIJCV9fY3B1X3RvX2xlMzIKKyNkZWZpbmUgY3B1X3Rv X2JlMzIJCV9fY3B1X3RvX2JlMzIKKyNkZWZpbmUgY3B1X3RvX2xlNjQJCV9fY3B1X3RvX2xlNjQK KyNkZWZpbmUgY3B1X3RvX2JlNjQJCV9fY3B1X3RvX2JlNjQKKyNkZWZpbmUgbGUzMl90b19jcHUJ CV9fbGUzMl90b19jcHUKKyNkZWZpbmUgYmUzMl90b19jcHUJCV9fYmUzMl90b19jcHUKKyNkZWZp bmUgbGU2NF90b19jcHUJCV9fbGU2NF90b19jcHUKKyNkZWZpbmUgYmU2NF90b19jcHUJCV9fYmU2 NF90b19jcHUKKworI2RlZmluZSBERUZJTkVfVU5BTElHTkVEX0FDQ0VTU19IRUxQRVJTKHR5cGUs IG5hdGl2ZV90eXBlKQlcCitzdGF0aWMgaW5saW5lIG5hdGl2ZV90eXBlIF9fYXR0cmlidXRlX18o KHVudXNlZCkpCQlcCitnZXRfdW5hbGlnbmVkXyMjdHlwZShjb25zdCB2b2lkICpwKQkJCQlcCit7 CQkJCQkJCQlcCisJX18jI3R5cGUgeDsJCQkJCQlcCisJCQkJCQkJCVwKKwltZW1jcHkoJngsIHAs IHNpemVvZih4KSk7CQkJCVwKKwlyZXR1cm4gdHlwZSMjX3RvX2NwdSh4KTsJCQkJXAorfQkJCQkJ CQkJXAorCQkJCQkJCQlcCitzdGF0aWMgaW5saW5lIHZvaWQgX19hdHRyaWJ1dGVfXygodW51c2Vk KSkJCQlcCitwdXRfdW5hbGlnbmVkXyMjdHlwZShuYXRpdmVfdHlwZSB2LCB2b2lkICpwKQkJCVwK K3sJCQkJCQkJCVwKKwlfXyMjdHlwZSB4ID0gY3B1X3RvXyMjdHlwZSh2KTsJCQkJXAorCQkJCQkJ CQlcCisJbWVtY3B5KHAsICZ4LCBzaXplb2YoeCkpOwkJCQlcCit9CisKK0RFRklORV9VTkFMSUdO RURfQUNDRVNTX0hFTFBFUlMobGUzMiwgdTMyKQorREVGSU5FX1VOQUxJR05FRF9BQ0NFU1NfSEVM UEVSUyhiZTMyLCB1MzIpCitERUZJTkVfVU5BTElHTkVEX0FDQ0VTU19IRUxQRVJTKGxlNjQsIHU2 NCkKK0RFRklORV9VTkFMSUdORURfQUNDRVNTX0hFTFBFUlMoYmU2NCwgdTY0KQorCitzdGF0aWMg aW5saW5lIGJvb2wgaXNfcG93ZXJfb2ZfMih1bnNpZ25lZCBsb25nIHYpCit7CisJcmV0dXJuIHYg IT0gMCAmJiAodiAmICh2IC0gMSkpID09IDA7Cit9CisKK3N0YXRpYyBpbmxpbmUgdTMyIHJvbDMy KHUzMiB2LCBpbnQgbikKK3sKKwlyZXR1cm4gKHYgPDwgbikgfCAodiA+PiAoMzIgLSBuKSk7Cit9 CisKK3N0YXRpYyBpbmxpbmUgdTMyIHJvcjMyKHUzMiB2LCBpbnQgbikKK3sKKwlyZXR1cm4gKHYg Pj4gbikgfCAodiA8PCAoMzIgLSBuKSk7Cit9CisKK3N0YXRpYyBpbmxpbmUgdm9pZCB4b3IodTgg KnJlcywgY29uc3QgdTggKmEsIGNvbnN0IHU4ICpiLCBzaXplX3QgY291bnQpCit7CisJd2hpbGUg KGNvdW50LS0pCisJCSpyZXMrKyA9ICphKysgXiAqYisrOworfQorCitzdGF0aWMgdm9pZCBfX2F0 dHJpYnV0ZV9fKChub3JldHVybiwgZm9ybWF0KHByaW50ZiwgMiwgMykpKQorZG9fZGllKGludCBl cnIsIGNvbnN0IGNoYXIgKmZvcm1hdCwgLi4uKQoreworCXZhX2xpc3QgdmE7CisKKwl2YV9zdGFy dCh2YSwgZm9ybWF0KTsKKwlmcHV0cygiWyIgUFJPR1JBTV9OQU1FICJdIEVSUk9SOiAiLCBzdGRl cnIpOworCXZmcHJpbnRmKHN0ZGVyciwgZm9ybWF0LCB2YSk7CisJaWYgKGVycikKKwkJZnByaW50 ZihzdGRlcnIsICI6ICVzIiwgc3RyZXJyb3IoZXJybm8pKTsKKwlwdXRjKCdcbicsIHN0ZGVycik7 CisJdmFfZW5kKHZhKTsKKwlleGl0KDEpOworfQorCisjZGVmaW5lIGRpZShmb3JtYXQsIC4uLikJ ZG9fZGllKDAsICAgICAoZm9ybWF0KSwgIyNfX1ZBX0FSR1NfXykKKyNkZWZpbmUgZGllX2Vycm5v KGZvcm1hdCwgLi4uKQlkb19kaWUoZXJybm8sIChmb3JtYXQpLCAjI19fVkFfQVJHU19fKQorCitz dGF0aWMgX19hdHRyaWJ1dGVfXygobm9yZXR1cm4pKSB2b2lkCithc3NlcnRpb25fZmFpbGVkKGNv bnN0IGNoYXIgKmV4cHIsIGNvbnN0IGNoYXIgKmZpbGUsIGludCBsaW5lKQoreworCWRpZSgiQXNz ZXJ0aW9uIGZhaWxlZDogJXMgYXQgJXM6JWQiLCBleHByLCBmaWxlLCBsaW5lKTsKK30KKworI2Rl ZmluZSBBU1NFUlQoZSkgKHsgaWYgKCEoZSkpIGFzc2VydGlvbl9mYWlsZWQoI2UsIF9fRklMRV9f LCBfX0xJTkVfXyk7IH0pCisKK3N0YXRpYyB2b2lkICp4bWFsbG9jKHNpemVfdCBzaXplKQorewor CXZvaWQgKnAgPSBtYWxsb2Moc2l6ZSk7CisKKwlBU1NFUlQocCAhPSBOVUxMKTsKKwlyZXR1cm4g cDsKK30KKworc3RhdGljIGludCBoZXhjaGFyMmJpbihjaGFyIGMpCit7CisJaWYgKGMgPj0gJ2En ICYmIGMgPD0gJ2YnKQorCQlyZXR1cm4gMTAgKyBjIC0gJ2EnOworCWlmIChjID49ICdBJyAmJiBj IDw9ICdGJykKKwkJcmV0dXJuIDEwICsgYyAtICdBJzsKKwlpZiAoYyA+PSAnMCcgJiYgYyA8PSAn OScpCisJCXJldHVybiBjIC0gJzAnOworCXJldHVybiAtMTsKK30KKworc3RhdGljIGludCBoZXgy YmluKGNvbnN0IGNoYXIgKmhleCwgdTggKmJpbiwgaW50IG1heF9iaW5fc2l6ZSkKK3sKKwlzaXpl X3QgbGVuID0gc3RybGVuKGhleCk7CisJc2l6ZV90IGk7CisKKwlpZiAobGVuICYgMSkKKwkJcmV0 dXJuIC0xOworCWxlbiAvPSAyOworCWlmIChsZW4gPiBtYXhfYmluX3NpemUpCisJCXJldHVybiAt MTsKKworCWZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykgeworCQlpbnQgaGlnaCA9IGhleGNoYXIy YmluKGhleFsyICogaV0pOworCQlpbnQgbG93ID0gaGV4Y2hhcjJiaW4oaGV4WzIgKiBpICsgMV0p OworCisJCWlmIChoaWdoIDwgMCB8fCBsb3cgPCAwKQorCQkJcmV0dXJuIC0xOworCQliaW5baV0g PSAoaGlnaCA8PCA0KSB8IGxvdzsKKwl9CisJcmV0dXJuIGxlbjsKK30KKworc3RhdGljIHNpemVf dCB4cmVhZChpbnQgZmQsIHZvaWQgKmJ1Ziwgc2l6ZV90IGNvdW50KQoreworCWNvbnN0IHNpemVf dCBvcmlnX2NvdW50ID0gY291bnQ7CisKKwl3aGlsZSAoY291bnQpIHsKKwkJc3NpemVfdCByZXMg PSByZWFkKGZkLCBidWYsIGNvdW50KTsKKworCQlpZiAocmVzIDwgMCkKKwkJCWRpZV9lcnJubygi cmVhZCBlcnJvciIpOworCQlpZiAocmVzID09IDApCisJCQlicmVhazsKKwkJYnVmICs9IHJlczsK KwkJY291bnQgLT0gcmVzOworCX0KKwlyZXR1cm4gb3JpZ19jb3VudCAtIGNvdW50OworfQorCitz dGF0aWMgdm9pZCBmdWxsX3dyaXRlKGludCBmZCwgY29uc3Qgdm9pZCAqYnVmLCBzaXplX3QgY291 bnQpCit7CisJd2hpbGUgKGNvdW50KSB7CisJCXNzaXplX3QgcmVzID0gd3JpdGUoZmQsIGJ1Ziwg Y291bnQpOworCisJCWlmIChyZXMgPCAwKQorCQkJZGllX2Vycm5vKCJ3cml0ZSBlcnJvciIpOwor CQlidWYgKz0gcmVzOworCQljb3VudCAtPSByZXM7CisJfQorfQorCisjaWZkZWYgRU5BQkxFX0FM R19URVNUUworc3RhdGljIHZvaWQgcmFuZF9ieXRlcyh1OCAqYnVmLCBzaXplX3QgY291bnQpCit7 CisJd2hpbGUgKGNvdW50LS0pCisJCSpidWYrKyA9IHJhbmQoKTsKK30KKyNlbmRpZgorCisvKi0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0qCisgKiAgICAgICAgICAgICAgICAgICAgICAgICAgRmluaXRlIGZp ZWxkIGFyaXRobWV0aWMgICAgICAgICAgICAgICAgICAgICAgICAgICAqCisgKi0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0qLworCisvKiBNdWx0aXBseSBhIEdGKDJeOCkgZWxlbWVudCBieSB0aGUgcG9seW5v bWlhbCAneCcgKi8KK3N0YXRpYyBpbmxpbmUgdTggZ2YyXzhfbXVsX3godTggYikKK3sKKwlyZXR1 cm4gKGIgPDwgMSkgXiAoKGIgJiAweDgwKSA/IDB4MUIgOiAwKTsKK30KKworLyogTXVsdGlwbHkg Zm91ciBwYWNrZWQgR0YoMl44KSBlbGVtZW50cyBieSB0aGUgcG9seW5vbWlhbCAneCcgKi8KK3N0 YXRpYyBpbmxpbmUgdTMyIGdmMl84X211bF94XzR3YXkodTMyIHcpCit7CisJcmV0dXJuICgodyAm IDB4N0Y3RjdGN0YpIDw8IDEpIF4gKCgodyAmIDB4ODA4MDgwODApID4+IDcpICogMHgxQik7Cit9 CisKKy8qIEVsZW1lbnQgb2YgR0YoMl4xMjgpICovCit0eXBlZGVmIHN0cnVjdCB7CisJX19sZTY0 IGxvOworCV9fbGU2NCBoaTsKK30gYmxlMTI4OworCisvKiBNdWx0aXBseSBhIEdGKDJeMTI4KSBl bGVtZW50IGJ5IHRoZSBwb2x5bm9taWFsICd4JyAqLworc3RhdGljIGlubGluZSB2b2lkIGdmMl8x MjhfbXVsX3goYmxlMTI4ICp0KQoreworCXU2NCBsbyA9IGxlNjRfdG9fY3B1KHQtPmxvKTsKKwl1 NjQgaGkgPSBsZTY0X3RvX2NwdSh0LT5oaSk7CisKKwl0LT5oaSA9IGNwdV90b19sZTY0KChoaSA8 PCAxKSB8IChsbyA+PiA2MykpOworCXQtPmxvID0gY3B1X3RvX2xlNjQoKGxvIDw8IDEpIF4gKCho aSAmICgxVUxMIDw8IDYzKSkgPyAweDg3IDogMCkpOworfQorCisvKi0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0qCisgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR3JvdXAgYXJpdGhtZXRpYyAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAqCisgKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLworCisv KiBFbGVtZW50IG9mIFovKDJeezEyOH1aKSAgKGEuay5hLiB0aGUgaW50ZWdlcnMgbW9kdWxvIDJe MTI4KSAqLwordHlwZWRlZiBzdHJ1Y3QgeworCV9fbGU2NCBsbzsKKwlfX2xlNjQgaGk7Cit9IGxl MTI4OworCitzdGF0aWMgaW5saW5lIHZvaWQgbGUxMjhfYWRkKGxlMTI4ICpyZXMsIGNvbnN0IGxl MTI4ICphLCBjb25zdCBsZTEyOCAqYikKK3sKKwl1NjQgYV9sbyA9IGxlNjRfdG9fY3B1KGEtPmxv KTsKKwl1NjQgYl9sbyA9IGxlNjRfdG9fY3B1KGItPmxvKTsKKworCXJlcy0+bG8gPSBjcHVfdG9f bGU2NChhX2xvICsgYl9sbyk7CisJcmVzLT5oaSA9IGNwdV90b19sZTY0KGxlNjRfdG9fY3B1KGEt PmhpKSArIGxlNjRfdG9fY3B1KGItPmhpKSArCisJCQkgICAgICAoYV9sbyArIGJfbG8gPCBhX2xv KSk7Cit9CisKK3N0YXRpYyBpbmxpbmUgdm9pZCBsZTEyOF9zdWIobGUxMjggKnJlcywgY29uc3Qg bGUxMjggKmEsIGNvbnN0IGxlMTI4ICpiKQoreworCXU2NCBhX2xvID0gbGU2NF90b19jcHUoYS0+ bG8pOworCXU2NCBiX2xvID0gbGU2NF90b19jcHUoYi0+bG8pOworCisJcmVzLT5sbyA9IGNwdV90 b19sZTY0KGFfbG8gLSBiX2xvKTsKKwlyZXMtPmhpID0gY3B1X3RvX2xlNjQobGU2NF90b19jcHUo YS0+aGkpIC0gbGU2NF90b19jcHUoYi0+aGkpIC0KKwkJCSAgICAgIChhX2xvIC0gYl9sbyA+IGFf bG8pKTsKK30KKworLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKgorICogICAgICAgICAgICAgICAgICAg ICAgICAgICAgICBBRVMgYmxvY2sgY2lwaGVyICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg KgorICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KKworLyoKKyAqIFJlZmVyZW5jZTogIkZJUFMgMTk3 LCBBZHZhbmNlZCBFbmNyeXB0aW9uIFN0YW5kYXJkIgorICoJaHR0cHM6Ly9udmxwdWJzLm5pc3Qu Z292L25pc3RwdWJzL2ZpcHMvbmlzdC5maXBzLjE5Ny5wZGYKKyAqLworCisjZGVmaW5lIEFFU19C TE9DS19TSVpFCQkxNgorI2RlZmluZSBBRVNfMTI4X0tFWV9TSVpFCTE2CisjZGVmaW5lIEFFU18x OTJfS0VZX1NJWkUJMjQKKyNkZWZpbmUgQUVTXzI1Nl9LRVlfU0laRQkzMgorCitzdGF0aWMgaW5s aW5lIHZvaWQgQWRkUm91bmRLZXkodTMyIHN0YXRlWzRdLCBjb25zdCB1MzIgKnJrKQoreworCWlu dCBpOworCisJZm9yIChpID0gMDsgaSA8IDQ7IGkrKykKKwkJc3RhdGVbaV0gXj0gcmtbaV07Cit9 CisKK3N0YXRpYyBjb25zdCB1OCBhZXNfc2JveFsyNTZdID0geworCTB4NjMsIDB4N2MsIDB4Nzcs IDB4N2IsIDB4ZjIsIDB4NmIsIDB4NmYsIDB4YzUsIDB4MzAsIDB4MDEsIDB4NjcsIDB4MmIsCisJ MHhmZSwgMHhkNywgMHhhYiwgMHg3NiwgMHhjYSwgMHg4MiwgMHhjOSwgMHg3ZCwgMHhmYSwgMHg1 OSwgMHg0NywgMHhmMCwKKwkweGFkLCAweGQ0LCAweGEyLCAweGFmLCAweDljLCAweGE0LCAweDcy LCAweGMwLCAweGI3LCAweGZkLCAweDkzLCAweDI2LAorCTB4MzYsIDB4M2YsIDB4ZjcsIDB4Y2Ms IDB4MzQsIDB4YTUsIDB4ZTUsIDB4ZjEsIDB4NzEsIDB4ZDgsIDB4MzEsIDB4MTUsCisJMHgwNCwg MHhjNywgMHgyMywgMHhjMywgMHgxOCwgMHg5NiwgMHgwNSwgMHg5YSwgMHgwNywgMHgxMiwgMHg4 MCwgMHhlMiwKKwkweGViLCAweDI3LCAweGIyLCAweDc1LCAweDA5LCAweDgzLCAweDJjLCAweDFh LCAweDFiLCAweDZlLCAweDVhLCAweGEwLAorCTB4NTIsIDB4M2IsIDB4ZDYsIDB4YjMsIDB4Mjks IDB4ZTMsIDB4MmYsIDB4ODQsIDB4NTMsIDB4ZDEsIDB4MDAsIDB4ZWQsCisJMHgyMCwgMHhmYywg MHhiMSwgMHg1YiwgMHg2YSwgMHhjYiwgMHhiZSwgMHgzOSwgMHg0YSwgMHg0YywgMHg1OCwgMHhj ZiwKKwkweGQwLCAweGVmLCAweGFhLCAweGZiLCAweDQzLCAweDRkLCAweDMzLCAweDg1LCAweDQ1 LCAweGY5LCAweDAyLCAweDdmLAorCTB4NTAsIDB4M2MsIDB4OWYsIDB4YTgsIDB4NTEsIDB4YTMs IDB4NDAsIDB4OGYsIDB4OTIsIDB4OWQsIDB4MzgsIDB4ZjUsCisJMHhiYywgMHhiNiwgMHhkYSwg MHgyMSwgMHgxMCwgMHhmZiwgMHhmMywgMHhkMiwgMHhjZCwgMHgwYywgMHgxMywgMHhlYywKKwkw eDVmLCAweDk3LCAweDQ0LCAweDE3LCAweGM0LCAweGE3LCAweDdlLCAweDNkLCAweDY0LCAweDVk LCAweDE5LCAweDczLAorCTB4NjAsIDB4ODEsIDB4NGYsIDB4ZGMsIDB4MjIsIDB4MmEsIDB4OTAs IDB4ODgsIDB4NDYsIDB4ZWUsIDB4YjgsIDB4MTQsCisJMHhkZSwgMHg1ZSwgMHgwYiwgMHhkYiwg MHhlMCwgMHgzMiwgMHgzYSwgMHgwYSwgMHg0OSwgMHgwNiwgMHgyNCwgMHg1YywKKwkweGMyLCAw eGQzLCAweGFjLCAweDYyLCAweDkxLCAweDk1LCAweGU0LCAweDc5LCAweGU3LCAweGM4LCAweDM3 LCAweDZkLAorCTB4OGQsIDB4ZDUsIDB4NGUsIDB4YTksIDB4NmMsIDB4NTYsIDB4ZjQsIDB4ZWEs IDB4NjUsIDB4N2EsIDB4YWUsIDB4MDgsCisJMHhiYSwgMHg3OCwgMHgyNSwgMHgyZSwgMHgxYywg MHhhNiwgMHhiNCwgMHhjNiwgMHhlOCwgMHhkZCwgMHg3NCwgMHgxZiwKKwkweDRiLCAweGJkLCAw eDhiLCAweDhhLCAweDcwLCAweDNlLCAweGI1LCAweDY2LCAweDQ4LCAweDAzLCAweGY2LCAweDBl LAorCTB4NjEsIDB4MzUsIDB4NTcsIDB4YjksIDB4ODYsIDB4YzEsIDB4MWQsIDB4OWUsIDB4ZTEs IDB4ZjgsIDB4OTgsIDB4MTEsCisJMHg2OSwgMHhkOSwgMHg4ZSwgMHg5NCwgMHg5YiwgMHgxZSwg MHg4NywgMHhlOSwgMHhjZSwgMHg1NSwgMHgyOCwgMHhkZiwKKwkweDhjLCAweGExLCAweDg5LCAw eDBkLCAweGJmLCAweGU2LCAweDQyLCAweDY4LCAweDQxLCAweDk5LCAweDJkLCAweDBmLAorCTB4 YjAsIDB4NTQsIDB4YmIsIDB4MTYsCit9OworCitzdGF0aWMgdTggYWVzX2ludmVyc2Vfc2JveFsy NTZdOworCitzdGF0aWMgdm9pZCBhZXNfaW5pdCh2b2lkKQoreworCWludCBpOworCisJZm9yIChp ID0gMDsgaSA8IDI1NjsgaSsrKQorCQlhZXNfaW52ZXJzZV9zYm94W2Flc19zYm94W2ldXSA9IGk7 Cit9CisKK3N0YXRpYyBpbmxpbmUgdTMyIERvU3ViV29yZCh1MzIgdywgY29uc3QgdTggc2JveFsy NTZdKQoreworCXJldHVybiAoKHUzMilzYm94Wyh1OCkodyA+PiAyNCldIDw8IDI0KSB8CisJICAg ICAgICgodTMyKXNib3hbKHU4KSh3ID4+IDE2KV0gPDwgMTYpIHwKKwkgICAgICAgKCh1MzIpc2Jv eFsodTgpKHcgPj4gIDgpXSA8PCAgOCkgfAorCSAgICAgICAoKHUzMilzYm94Wyh1OCkodyA+PiAg MCldIDw8ICAwKTsKK30KKworc3RhdGljIGlubGluZSB1MzIgU3ViV29yZCh1MzIgdykKK3sKKwly ZXR1cm4gRG9TdWJXb3JkKHcsIGFlc19zYm94KTsKK30KKworc3RhdGljIGlubGluZSB1MzIgSW52 U3ViV29yZCh1MzIgdykKK3sKKwlyZXR1cm4gRG9TdWJXb3JkKHcsIGFlc19pbnZlcnNlX3Nib3gp OworfQorCitzdGF0aWMgaW5saW5lIHZvaWQgU3ViQnl0ZXModTMyIHN0YXRlWzRdKQoreworCWlu dCBpOworCisJZm9yIChpID0gMDsgaSA8IDQ7IGkrKykKKwkJc3RhdGVbaV0gPSBTdWJXb3JkKHN0 YXRlW2ldKTsKK30KKworc3RhdGljIGlubGluZSB2b2lkIEludlN1YkJ5dGVzKHUzMiBzdGF0ZVs0 XSkKK3sKKwlpbnQgaTsKKworCWZvciAoaSA9IDA7IGkgPCA0OyBpKyspCisJCXN0YXRlW2ldID0g SW52U3ViV29yZChzdGF0ZVtpXSk7Cit9CisKK3N0YXRpYyBpbmxpbmUgdm9pZCBEb1NoaWZ0Um93 cyh1MzIgc3RhdGVbNF0sIGludCBkaXJlY3Rpb24pCit7CisJdTMyIG5ld3N0YXRlWzRdOworCWlu dCBpOworCisJZm9yIChpID0gMDsgaSA8IDQ7IGkrKykKKwkJbmV3c3RhdGVbaV0gPSAoc3RhdGVb KGkgKyBkaXJlY3Rpb24qMCkgJiAzXSAmIDB4ZmYpIHwKKwkJCSAgICAgIChzdGF0ZVsoaSArIGRp cmVjdGlvbioxKSAmIDNdICYgMHhmZjAwKSB8CisJCQkgICAgICAoc3RhdGVbKGkgKyBkaXJlY3Rp b24qMikgJiAzXSAmIDB4ZmYwMDAwKSB8CisJCQkgICAgICAoc3RhdGVbKGkgKyBkaXJlY3Rpb24q MykgJiAzXSAmIDB4ZmYwMDAwMDApOworCW1lbWNweShzdGF0ZSwgbmV3c3RhdGUsIDE2KTsKK30K Kworc3RhdGljIGlubGluZSB2b2lkIFNoaWZ0Um93cyh1MzIgc3RhdGVbNF0pCit7CisJRG9TaGlm dFJvd3Moc3RhdGUsIDEpOworfQorCitzdGF0aWMgaW5saW5lIHZvaWQgSW52U2hpZnRSb3dzKHUz MiBzdGF0ZVs0XSkKK3sKKwlEb1NoaWZ0Um93cyhzdGF0ZSwgLTEpOworfQorCisvKgorICogTWl4 IG9uZSBjb2x1bW4gYnkgZG9pbmcgdGhlIGZvbGxvd2luZyBtYXRyaXggbXVsdGlwbGljYXRpb24g aW4gR0YoMl44KToKKyAqCisgKiAgICAgfCAyIDMgMSAxIHwgICB8IHdbMF0gfAorICogICAgIHwg MSAyIDMgMSB8ICAgfCB3WzFdIHwKKyAqICAgICB8IDEgMSAyIDMgfCB4IHwgd1syXSB8CisgKiAg ICAgfCAzIDEgMSAyIHwgICB8IHdbM10gfAorICoKKyAqIGEuay5hLiB3W2ldID0gMip3W2ldICsg Myp3WyhpKzEpJTRdICsgd1soaSsyKSU0XSArIHdbKGkrMyklNF0KKyAqLworc3RhdGljIGlubGlu ZSB1MzIgTWl4Q29sdW1uKHUzMiB3KQoreworCXUzMiBfMncwX3cyID0gZ2YyXzhfbXVsX3hfNHdh eSh3KSBeIHJvcjMyKHcsIDE2KTsKKwl1MzIgXzN3MV93MyA9IHJvcjMyKF8ydzBfdzIgXiB3LCA4 KTsKKworCXJldHVybiBfMncwX3cyIF4gXzN3MV93MzsKK30KKworLyoKKyAqICAgICAgICAgICAo IHwgNSAwIDQgMCB8ICAgfCB3WzBdIHwgKQorICogICAgICAgICAgKCAgfCAwIDUgMCA0IHwgICB8 IHdbMV0gfCAgKQorICogTWl4Q29sdW1uKCAgfCA0IDAgNSAwIHwgeCB8IHdbMl0gfCAgKQorICog ICAgICAgICAgICggfCAwIDQgMCA1IHwgICB8IHdbM10gfCApCisgKi8KK3N0YXRpYyBpbmxpbmUg dTMyIEludk1peENvbHVtbih1MzIgdykKK3sKKwl1MzIgXzR3ID0gZ2YyXzhfbXVsX3hfNHdheShn ZjJfOF9tdWxfeF80d2F5KHcpKTsKKworCXJldHVybiBNaXhDb2x1bW4oXzR3IF4gdyBeIHJvcjMy KF80dywgMTYpKTsKK30KKworc3RhdGljIGlubGluZSB2b2lkIE1peENvbHVtbnModTMyIHN0YXRl WzRdKQoreworCWludCBpOworCisJZm9yIChpID0gMDsgaSA8IDQ7IGkrKykKKwkJc3RhdGVbaV0g PSBNaXhDb2x1bW4oc3RhdGVbaV0pOworfQorCitzdGF0aWMgaW5saW5lIHZvaWQgSW52TWl4Q29s dW1ucyh1MzIgc3RhdGVbNF0pCit7CisJaW50IGk7CisKKwlmb3IgKGkgPSAwOyBpIDwgNDsgaSsr KQorCQlzdGF0ZVtpXSA9IEludk1peENvbHVtbihzdGF0ZVtpXSk7Cit9CisKK3N0cnVjdCBhZXNf a2V5IHsKKwl1MzIgcm91bmRfa2V5c1sxNSAqIDRdOworCWludCBucm91bmRzOworfTsKKworLyog RXhwYW5kIGFuIEFFUyBrZXkgKi8KK3N0YXRpYyB2b2lkIGFlc19zZXRrZXkoc3RydWN0IGFlc19r ZXkgKmssIGNvbnN0IHU4ICprZXksIGludCBrZXlzaXplKQoreworCWNvbnN0IGludCBOID0ga2V5 c2l6ZSAvIDQ7CisJdTMyICogY29uc3QgcmsgPSBrLT5yb3VuZF9rZXlzOworCXU4IHJjb24gPSAx OworCWludCBpOworCisJQVNTRVJUKGtleXNpemUgPT0gMTYgfHwga2V5c2l6ZSA9PSAyNCB8fCBr ZXlzaXplID09IDMyKTsKKwlrLT5ucm91bmRzID0gNiArIE47CisJZm9yIChpID0gMDsgaSA8IDQg KiAoay0+bnJvdW5kcyArIDEpOyBpKyspIHsKKwkJaWYgKGkgPCBOKSB7CisJCQlya1tpXSA9IGdl dF91bmFsaWduZWRfbGUzMigma2V5W2kgKiBzaXplb2YoX19sZTMyKV0pOworCQl9IGVsc2UgaWYg KGkgJSBOID09IDApIHsKKwkJCXJrW2ldID0gcmtbaSAtIE5dIF4gU3ViV29yZChyb3IzMihya1tp IC0gMV0sIDgpKSBeIHJjb247CisJCQlyY29uID0gZ2YyXzhfbXVsX3gocmNvbik7CisJCX0gZWxz ZSBpZiAoTiA+IDYgJiYgaSAlIE4gPT0gNCkgeworCQkJcmtbaV0gPSBya1tpIC0gTl0gXiBTdWJX b3JkKHJrW2kgLSAxXSk7CisJCX0gZWxzZSB7CisJCQlya1tpXSA9IHJrW2kgLSBOXSBeIHJrW2kg LSAxXTsKKwkJfQorCX0KK30KKworLyogRW5jcnlwdCBvbmUgMTYtYnl0ZSBibG9jayB3aXRoIEFF UyAqLworc3RhdGljIHZvaWQgYWVzX2VuY3J5cHQoY29uc3Qgc3RydWN0IGFlc19rZXkgKmssIGNv bnN0IHU4IHNyY1tBRVNfQkxPQ0tfU0laRV0sCisJCQl1OCBkc3RbQUVTX0JMT0NLX1NJWkVdKQor eworCXUzMiBzdGF0ZVs0XTsKKwlpbnQgaTsKKworCWZvciAoaSA9IDA7IGkgPCA0OyBpKyspCisJ CXN0YXRlW2ldID0gZ2V0X3VuYWxpZ25lZF9sZTMyKCZzcmNbaSAqIHNpemVvZihfX2xlMzIpXSk7 CisKKwlBZGRSb3VuZEtleShzdGF0ZSwgay0+cm91bmRfa2V5cyk7CisJZm9yIChpID0gMTsgaSA8 IGstPm5yb3VuZHM7IGkrKykgeworCQlTdWJCeXRlcyhzdGF0ZSk7CisJCVNoaWZ0Um93cyhzdGF0 ZSk7CisJCU1peENvbHVtbnMoc3RhdGUpOworCQlBZGRSb3VuZEtleShzdGF0ZSwgJmstPnJvdW5k X2tleXNbNCAqIGldKTsKKwl9CisJU3ViQnl0ZXMoc3RhdGUpOworCVNoaWZ0Um93cyhzdGF0ZSk7 CisJQWRkUm91bmRLZXkoc3RhdGUsICZrLT5yb3VuZF9rZXlzWzQgKiBpXSk7CisKKwlmb3IgKGkg PSAwOyBpIDwgNDsgaSsrKQorCQlwdXRfdW5hbGlnbmVkX2xlMzIoc3RhdGVbaV0sICZkc3RbaSAq IHNpemVvZihfX2xlMzIpXSk7Cit9CisKKy8qIERlY3J5cHQgb25lIDE2LWJ5dGUgYmxvY2sgd2l0 aCBBRVMgKi8KK3N0YXRpYyB2b2lkIGFlc19kZWNyeXB0KGNvbnN0IHN0cnVjdCBhZXNfa2V5ICpr LCBjb25zdCB1OCBzcmNbQUVTX0JMT0NLX1NJWkVdLAorCQkJdTggZHN0W0FFU19CTE9DS19TSVpF XSkKK3sKKwl1MzIgc3RhdGVbNF07CisJaW50IGk7CisKKwlmb3IgKGkgPSAwOyBpIDwgNDsgaSsr KQorCQlzdGF0ZVtpXSA9IGdldF91bmFsaWduZWRfbGUzMigmc3JjW2kgKiBzaXplb2YoX19sZTMy KV0pOworCisJQWRkUm91bmRLZXkoc3RhdGUsICZrLT5yb3VuZF9rZXlzWzQgKiBrLT5ucm91bmRz XSk7CisJSW52U2hpZnRSb3dzKHN0YXRlKTsKKwlJbnZTdWJCeXRlcyhzdGF0ZSk7CisJZm9yIChp ID0gay0+bnJvdW5kcyAtIDE7IGkgPj0gMTsgaS0tKSB7CisJCUFkZFJvdW5kS2V5KHN0YXRlLCAm ay0+cm91bmRfa2V5c1s0ICogaV0pOworCQlJbnZNaXhDb2x1bW5zKHN0YXRlKTsKKwkJSW52U2hp ZnRSb3dzKHN0YXRlKTsKKwkJSW52U3ViQnl0ZXMoc3RhdGUpOworCX0KKwlBZGRSb3VuZEtleShz dGF0ZSwgay0+cm91bmRfa2V5cyk7CisKKwlmb3IgKGkgPSAwOyBpIDwgNDsgaSsrKQorCQlwdXRf dW5hbGlnbmVkX2xlMzIoc3RhdGVbaV0sICZkc3RbaSAqIHNpemVvZihfX2xlMzIpXSk7Cit9CisK KyNpZmRlZiBFTkFCTEVfQUxHX1RFU1RTCisjaW5jbHVkZSA8b3BlbnNzbC9hZXMuaD4KK3N0YXRp YyB2b2lkIHRlc3RfYWVzX2tleXNpemUoaW50IGtleXNpemUpCit7CisJdW5zaWduZWQgbG9uZyBu dW1fdGVzdHMgPSBOVU1fQUxHX1RFU1RfSVRFUkFUSU9OUzsKKworCXdoaWxlIChudW1fdGVzdHMt LSkgeworCQlzdHJ1Y3QgYWVzX2tleSBrOworCQlBRVNfS0VZIHJlZl9rOworCQl1OCBrZXlbQUVT XzI1Nl9LRVlfU0laRV07CisJCXU4IHB0ZXh0W0FFU19CTE9DS19TSVpFXTsKKwkJdTggY3RleHRb QUVTX0JMT0NLX1NJWkVdOworCQl1OCByZWZfY3RleHRbQUVTX0JMT0NLX1NJWkVdOworCQl1OCBk ZWNyeXB0ZWRbQUVTX0JMT0NLX1NJWkVdOworCisJCXJhbmRfYnl0ZXMoa2V5LCBrZXlzaXplKTsK KwkJcmFuZF9ieXRlcyhwdGV4dCwgQUVTX0JMT0NLX1NJWkUpOworCisJCWFlc19zZXRrZXkoJmss IGtleSwga2V5c2l6ZSk7CisJCWFlc19lbmNyeXB0KCZrLCBwdGV4dCwgY3RleHQpOworCisJCUFT U0VSVChBRVNfc2V0X2VuY3J5cHRfa2V5KGtleSwga2V5c2l6ZSo4LCAmcmVmX2spID09IDApOwor CQlBRVNfZW5jcnlwdChwdGV4dCwgcmVmX2N0ZXh0LCAmcmVmX2spOworCisJCUFTU0VSVChtZW1j bXAoY3RleHQsIHJlZl9jdGV4dCwgQUVTX0JMT0NLX1NJWkUpID09IDApOworCisJCWFlc19kZWNy eXB0KCZrLCBjdGV4dCwgZGVjcnlwdGVkKTsKKwkJQVNTRVJUKG1lbWNtcChwdGV4dCwgZGVjcnlw dGVkLCBBRVNfQkxPQ0tfU0laRSkgPT0gMCk7CisJfQorfQorCitzdGF0aWMgdm9pZCB0ZXN0X2Fl cyh2b2lkKQoreworCXRlc3RfYWVzX2tleXNpemUoQUVTXzEyOF9LRVlfU0laRSk7CisJdGVzdF9h ZXNfa2V5c2l6ZShBRVNfMTkyX0tFWV9TSVpFKTsKKwl0ZXN0X2Flc19rZXlzaXplKEFFU18yNTZf S0VZX1NJWkUpOworfQorI2VuZGlmIC8qIEVOQUJMRV9BTEdfVEVTVFMgKi8KKworLyotLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tKgorICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU0hBLTI1 NiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKgorICotLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tKi8KKworLyoKKyAqIFJlZmVyZW5jZTogIkZJUFMgMTgwLTIsIFNlY3VyZSBIYXNoIFN0YW5k YXJkIgorICoJaHR0cHM6Ly9jc3JjLm5pc3QuZ292L2NzcmMvbWVkaWEvcHVibGljYXRpb25zL2Zp cHMvMTgwLzIvYXJjaGl2ZS8yMDAyLTA4LTAxL2RvY3VtZW50cy9maXBzMTgwLTJ3aXRoY2hhbmdl bm90aWNlLnBkZgorICovCisKKyNkZWZpbmUgU0hBMjU2X0RJR0VTVF9TSVpFCTMyCisjZGVmaW5l IFNIQTI1Nl9CTE9DS19TSVpFCTY0CisKKyNkZWZpbmUgQ2goeCwgeSwgeikJKCgoeCkgJiAoeSkp IF4gKH4oeCkgJiAoeikpKQorI2RlZmluZSBNYWooeCwgeSwgeikJKCgoeCkgJiAoeSkpIF4gKCh4 KSAmICh6KSkgXiAoKHkpICYgKHopKSkKKyNkZWZpbmUgU2lnbWEyNTZfMCh4KQkocm9yMzIoKHgp LCAgMikgXiByb3IzMigoeCksIDEzKSBeIHJvcjMyKCh4KSwgMjIpKQorI2RlZmluZSBTaWdtYTI1 Nl8xKHgpCShyb3IzMigoeCksICA2KSBeIHJvcjMyKCh4KSwgMTEpIF4gcm9yMzIoKHgpLCAyNSkp CisjZGVmaW5lIHNpZ21hMjU2XzAoeCkJKHJvcjMyKCh4KSwgIDcpIF4gcm9yMzIoKHgpLCAxOCkg XiAoKHgpID4+ICAzKSkKKyNkZWZpbmUgc2lnbWEyNTZfMSh4KQkocm9yMzIoKHgpLCAxNykgXiBy b3IzMigoeCksIDE5KSBeICgoeCkgPj4gMTApKQorCitzdGF0aWMgY29uc3QgdTMyIHNoYTI1Nl9p dls4XSA9IHsKKwkweDZhMDllNjY3LCAweGJiNjdhZTg1LCAweDNjNmVmMzcyLCAweGE1NGZmNTNh LCAweDUxMGU1MjdmLCAweDliMDU2ODhjLAorCTB4MWY4M2Q5YWIsIDB4NWJlMGNkMTksCit9Owor CitzdGF0aWMgY29uc3QgdTMyIHNoYTI1Nl9yb3VuZF9jb25zdGFudHNbNjRdID0geworCTB4NDI4 YTJmOTgsIDB4NzEzNzQ0OTEsIDB4YjVjMGZiY2YsIDB4ZTliNWRiYTUsIDB4Mzk1NmMyNWIsIDB4 NTlmMTExZjEsCisJMHg5MjNmODJhNCwgMHhhYjFjNWVkNSwgMHhkODA3YWE5OCwgMHgxMjgzNWIw MSwgMHgyNDMxODViZSwgMHg1NTBjN2RjMywKKwkweDcyYmU1ZDc0LCAweDgwZGViMWZlLCAweDli ZGMwNmE3LCAweGMxOWJmMTc0LCAweGU0OWI2OWMxLCAweGVmYmU0Nzg2LAorCTB4MGZjMTlkYzYs IDB4MjQwY2ExY2MsIDB4MmRlOTJjNmYsIDB4NGE3NDg0YWEsIDB4NWNiMGE5ZGMsIDB4NzZmOTg4 ZGEsCisJMHg5ODNlNTE1MiwgMHhhODMxYzY2ZCwgMHhiMDAzMjdjOCwgMHhiZjU5N2ZjNywgMHhj NmUwMGJmMywgMHhkNWE3OTE0NywKKwkweDA2Y2E2MzUxLCAweDE0MjkyOTY3LCAweDI3YjcwYTg1 LCAweDJlMWIyMTM4LCAweDRkMmM2ZGZjLCAweDUzMzgwZDEzLAorCTB4NjUwYTczNTQsIDB4NzY2 YTBhYmIsIDB4ODFjMmM5MmUsIDB4OTI3MjJjODUsIDB4YTJiZmU4YTEsIDB4YTgxYTY2NGIsCisJ MHhjMjRiOGI3MCwgMHhjNzZjNTFhMywgMHhkMTkyZTgxOSwgMHhkNjk5MDYyNCwgMHhmNDBlMzU4 NSwgMHgxMDZhYTA3MCwKKwkweDE5YTRjMTE2LCAweDFlMzc2YzA4LCAweDI3NDg3NzRjLCAweDM0 YjBiY2I1LCAweDM5MWMwY2IzLCAweDRlZDhhYTRhLAorCTB4NWI5Y2NhNGYsIDB4NjgyZTZmZjMs IDB4NzQ4ZjgyZWUsIDB4NzhhNTYzNmYsIDB4ODRjODc4MTQsIDB4OGNjNzAyMDgsCisJMHg5MGJl ZmZmYSwgMHhhNDUwNmNlYiwgMHhiZWY5YTNmNywgMHhjNjcxNzhmMiwKK307CisKKy8qIENvbXB1 dGUgdGhlIFNIQS0yNTYgZGlnZXN0IG9mIHRoZSBnaXZlbiBidWZmZXIgKi8KK3N0YXRpYyB2b2lk IHNoYTI1Nihjb25zdCB1OCAqaW4sIHNpemVfdCBpbmxlbiwgdTggb3V0W1NIQTI1Nl9ESUdFU1Rf U0laRV0pCit7CisJY29uc3Qgc2l6ZV90IG1zZ2xlbiA9IFJPVU5EX1VQKGlubGVuICsgOSwgU0hB MjU2X0JMT0NLX1NJWkUpOworCXU4ICogY29uc3QgbXNnID0geG1hbGxvYyhtc2dsZW4pOworCXUz MiBIWzhdOworCWludCBpOworCisJLyogc3VwZXIgbmFpdmUgd2F5IG9mIGhhbmRsaW5nIHRoZSBw YWRkaW5nICovCisJbWVtY3B5KG1zZywgaW4sIGlubGVuKTsKKwltZW1zZXQoJm1zZ1tpbmxlbl0s IDAsIG1zZ2xlbiAtIGlubGVuKTsKKwltc2dbaW5sZW5dID0gMHg4MDsKKwlwdXRfdW5hbGlnbmVk X2JlNjQoKHU2NClpbmxlbiAqIDgsICZtc2dbbXNnbGVuIC0gc2l6ZW9mKF9fYmU2NCldKTsKKwlp biA9IG1zZzsKKworCW1lbWNweShILCBzaGEyNTZfaXYsIHNpemVvZihIKSk7CisJZG8geworCQl1 MzIgYSA9IEhbMF0sIGIgPSBIWzFdLCBjID0gSFsyXSwgZCA9IEhbM10sCisJCSAgICBlID0gSFs0 XSwgZiA9IEhbNV0sIGcgPSBIWzZdLCBoID0gSFs3XTsKKwkJdTMyIFdbNjRdOworCisJCWZvciAo aSA9IDA7IGkgPCAxNjsgaSsrKQorCQkJV1tpXSA9IGdldF91bmFsaWduZWRfYmUzMigmaW5baSAq IHNpemVvZihfX2JlMzIpXSk7CisJCWZvciAoOyBpIDwgQVJSQVlfU0laRShXKTsgaSsrKQorCQkJ V1tpXSA9IHNpZ21hMjU2XzEoV1tpIC0gMl0pICsgV1tpIC0gN10gKworCQkJICAgICAgIHNpZ21h MjU2XzAoV1tpIC0gMTVdKSArIFdbaSAtIDE2XTsKKwkJZm9yIChpID0gMDsgaSA8IEFSUkFZX1NJ WkUoVyk7IGkrKykgeworCQkJdTMyIFQxID0gaCArIFNpZ21hMjU2XzEoZSkgKyBDaChlLCBmLCBn KSArCisJCQkJIHNoYTI1Nl9yb3VuZF9jb25zdGFudHNbaV0gKyBXW2ldOworCQkJdTMyIFQyID0g U2lnbWEyNTZfMChhKSArIE1haihhLCBiLCBjKTsKKworCQkJaCA9IGc7IGcgPSBmOyBmID0gZTsg ZSA9IGQgKyBUMTsKKwkJCWQgPSBjOyBjID0gYjsgYiA9IGE7IGEgPSBUMSArIFQyOworCQl9CisJ CUhbMF0gKz0gYTsgSFsxXSArPSBiOyBIWzJdICs9IGM7IEhbM10gKz0gZDsKKwkJSFs0XSArPSBl OyBIWzVdICs9IGY7IEhbNl0gKz0gZzsgSFs3XSArPSBoOworCX0gd2hpbGUgKChpbiArPSBTSEEy NTZfQkxPQ0tfU0laRSkgIT0gJm1zZ1ttc2dsZW5dKTsKKworCWZvciAoaSA9IDA7IGkgPCBBUlJB WV9TSVpFKEgpOyBpKyspCisJCXB1dF91bmFsaWduZWRfYmUzMihIW2ldLCAmb3V0W2kgKiBzaXpl b2YoX19iZTMyKV0pOworCWZyZWUobXNnKTsKK30KKworI2lmZGVmIEVOQUJMRV9BTEdfVEVTVFMK KyNpbmNsdWRlIDxvcGVuc3NsL3NoYS5oPgorc3RhdGljIHZvaWQgdGVzdF9zaGEyKHZvaWQpCit7 CisJdW5zaWduZWQgbG9uZyBudW1fdGVzdHMgPSBOVU1fQUxHX1RFU1RfSVRFUkFUSU9OUzsKKwor CXdoaWxlIChudW1fdGVzdHMtLSkgeworCQl1OCBpbls0MDk2XTsKKwkJdTggZGlnZXN0W1NIQTI1 Nl9ESUdFU1RfU0laRV07CisJCXU4IHJlZl9kaWdlc3RbU0hBMjU2X0RJR0VTVF9TSVpFXTsKKwkJ Y29uc3Qgc2l6ZV90IGlubGVuID0gcmFuZCgpICUgKDEgKyBzaXplb2YoaW4pKTsKKworCQlyYW5k X2J5dGVzKGluLCBpbmxlbik7CisKKwkJc2hhMjU2KGluLCBpbmxlbiwgZGlnZXN0KTsKKwkJU0hB MjU2KGluLCBpbmxlbiwgcmVmX2RpZ2VzdCk7CisJCUFTU0VSVChtZW1jbXAoZGlnZXN0LCByZWZf ZGlnZXN0LCBTSEEyNTZfRElHRVNUX1NJWkUpID09IDApOworCX0KK30KKyNlbmRpZiAvKiBFTkFC TEVfQUxHX1RFU1RTICovCisKKy8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSoKKyAqICAgICAgICAgICAg ICAgICAgICAgICAgICAgIEFFUyBlbmNyeXB0aW9uIG1vZGVzICAgICAgICAgICAgICAgICAgICAg ICAgICAgICoKKyAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCisKK3N0YXRpYyB2b2lkIGFlc18yNTZf eHRzX2NyeXB0KGNvbnN0IHU4IGtleVsyICogQUVTXzI1Nl9LRVlfU0laRV0sCisJCQkgICAgICBj b25zdCB1OCBpdltBRVNfQkxPQ0tfU0laRV0sIGNvbnN0IHU4ICpzcmMsCisJCQkgICAgICB1OCAq ZHN0LCBzaXplX3QgbmJ5dGVzLCBib29sIGRlY3J5cHRpbmcpCit7CisJc3RydWN0IGFlc19rZXkg dHdlYWtfa2V5LCBjaXBoZXJfa2V5OworCWJsZTEyOCB0OworCXNpemVfdCBpOworCisJQVNTRVJU KG5ieXRlcyAlIEFFU19CTE9DS19TSVpFID09IDApOworCWFlc19zZXRrZXkoJmNpcGhlcl9rZXks IGtleSwgQUVTXzI1Nl9LRVlfU0laRSk7CisJYWVzX3NldGtleSgmdHdlYWtfa2V5LCAma2V5W0FF U18yNTZfS0VZX1NJWkVdLCBBRVNfMjU2X0tFWV9TSVpFKTsKKwlhZXNfZW5jcnlwdCgmdHdlYWtf a2V5LCBpdiwgKHU4ICopJnQpOworCWZvciAoaSA9IDA7IGkgPCBuYnl0ZXM7IGkgKz0gQUVTX0JM T0NLX1NJWkUpIHsKKwkJeG9yKCZkc3RbaV0sICZzcmNbaV0sIChjb25zdCB1OCAqKSZ0LCBBRVNf QkxPQ0tfU0laRSk7CisJCWlmIChkZWNyeXB0aW5nKQorCQkJYWVzX2RlY3J5cHQoJmNpcGhlcl9r ZXksICZkc3RbaV0sICZkc3RbaV0pOworCQllbHNlCisJCQlhZXNfZW5jcnlwdCgmY2lwaGVyX2tl eSwgJmRzdFtpXSwgJmRzdFtpXSk7CisJCXhvcigmZHN0W2ldLCAmZHN0W2ldLCAoY29uc3QgdTgg KikmdCwgQUVTX0JMT0NLX1NJWkUpOworCQlnZjJfMTI4X211bF94KCZ0KTsKKwl9Cit9CisKK3N0 YXRpYyB2b2lkIGFlc18yNTZfeHRzX2VuY3J5cHQoY29uc3QgdTgga2V5WzIgKiBBRVNfMjU2X0tF WV9TSVpFXSwKKwkJCQljb25zdCB1OCBpdltBRVNfQkxPQ0tfU0laRV0sIGNvbnN0IHU4ICpzcmMs CisJCQkJdTggKmRzdCwgc2l6ZV90IG5ieXRlcykKK3sKKwlhZXNfMjU2X3h0c19jcnlwdChrZXks IGl2LCBzcmMsIGRzdCwgbmJ5dGVzLCBmYWxzZSk7Cit9CisKK3N0YXRpYyB2b2lkIGFlc18yNTZf eHRzX2RlY3J5cHQoY29uc3QgdTgga2V5WzIgKiBBRVNfMjU2X0tFWV9TSVpFXSwKKwkJCQljb25z dCB1OCBpdltBRVNfQkxPQ0tfU0laRV0sIGNvbnN0IHU4ICpzcmMsCisJCQkJdTggKmRzdCwgc2l6 ZV90IG5ieXRlcykKK3sKKwlhZXNfMjU2X3h0c19jcnlwdChrZXksIGl2LCBzcmMsIGRzdCwgbmJ5 dGVzLCB0cnVlKTsKK30KKworI2lmZGVmIEVOQUJMRV9BTEdfVEVTVFMKKyNpbmNsdWRlIDxvcGVu c3NsL2V2cC5oPgorc3RhdGljIHZvaWQgdGVzdF9hZXNfMjU2X3h0cyh2b2lkKQoreworCXVuc2ln bmVkIGxvbmcgbnVtX3Rlc3RzID0gTlVNX0FMR19URVNUX0lURVJBVElPTlM7CisJRVZQX0NJUEhF Ul9DVFggKmN0eCA9IEVWUF9DSVBIRVJfQ1RYX25ldygpOworCisJQVNTRVJUKGN0eCAhPSBOVUxM KTsKKwl3aGlsZSAobnVtX3Rlc3RzLS0pIHsKKwkJdTgga2V5WzIgKiBBRVNfMjU2X0tFWV9TSVpF XTsKKwkJdTggaXZbQUVTX0JMT0NLX1NJWkVdOworCQl1OCBwdGV4dFs1MTJdOworCQl1OCBjdGV4 dFtzaXplb2YocHRleHQpXTsKKwkJdTggcmVmX2N0ZXh0W3NpemVvZihwdGV4dCldOworCQl1OCBk ZWNyeXB0ZWRbc2l6ZW9mKHB0ZXh0KV07CisJCWNvbnN0IHNpemVfdCBkYXRhbGVuID0gUk9VTkRf RE9XTihyYW5kKCkgJSAoMSArIHNpemVvZihwdGV4dCkpLAorCQkJCQkJICBBRVNfQkxPQ0tfU0la RSk7CisJCWludCBvdXRsLCByZXM7CisKKwkJcmFuZF9ieXRlcyhrZXksIHNpemVvZihrZXkpKTsK KwkJcmFuZF9ieXRlcyhpdiwgc2l6ZW9mKGl2KSk7CisJCXJhbmRfYnl0ZXMocHRleHQsIGRhdGFs ZW4pOworCisJCWFlc18yNTZfeHRzX2VuY3J5cHQoa2V5LCBpdiwgcHRleHQsIGN0ZXh0LCBkYXRh bGVuKTsKKwkJcmVzID0gRVZQX0VuY3J5cHRJbml0X2V4KGN0eCwgRVZQX2Flc18yNTZfeHRzKCks IE5VTEwsIGtleSwgaXYpOworCQlBU1NFUlQocmVzID4gMCk7CisJCXJlcyA9IEVWUF9FbmNyeXB0 VXBkYXRlKGN0eCwgcmVmX2N0ZXh0LCAmb3V0bCwgcHRleHQsIGRhdGFsZW4pOworCQlBU1NFUlQo cmVzID4gMCk7CisJCUFTU0VSVChvdXRsID09IGRhdGFsZW4pOworCQlBU1NFUlQobWVtY21wKGN0 ZXh0LCByZWZfY3RleHQsIGRhdGFsZW4pID09IDApOworCisJCWFlc18yNTZfeHRzX2RlY3J5cHQo a2V5LCBpdiwgY3RleHQsIGRlY3J5cHRlZCwgZGF0YWxlbik7CisJCUFTU0VSVChtZW1jbXAocHRl eHQsIGRlY3J5cHRlZCwgZGF0YWxlbikgPT0gMCk7CisJfQorCUVWUF9DSVBIRVJfQ1RYX2ZyZWUo Y3R4KTsKK30KKyNlbmRpZiAvKiBFTkFCTEVfQUxHX1RFU1RTICovCisKK3N0YXRpYyB2b2lkIGFl c19jYmNfZW5jcnlwdChjb25zdCBzdHJ1Y3QgYWVzX2tleSAqaywKKwkJCSAgICBjb25zdCB1OCBp dltBRVNfQkxPQ0tfU0laRV0sCisJCQkgICAgY29uc3QgdTggKnNyYywgdTggKmRzdCwgc2l6ZV90 IG5ieXRlcykKK3sKKwlzaXplX3QgaTsKKworCUFTU0VSVChuYnl0ZXMgJSBBRVNfQkxPQ0tfU0la RSA9PSAwKTsKKwlmb3IgKGkgPSAwOyBpIDwgbmJ5dGVzOyBpICs9IEFFU19CTE9DS19TSVpFKSB7 CisJCXhvcigmZHN0W2ldLCAmc3JjW2ldLCAoaSA9PSAwID8gaXYgOiAmZHN0W2kgLSBBRVNfQkxP Q0tfU0laRV0pLAorCQkgICAgQUVTX0JMT0NLX1NJWkUpOworCQlhZXNfZW5jcnlwdChrLCAmZHN0 W2ldLCAmZHN0W2ldKTsKKwl9Cit9CisKK3N0YXRpYyB2b2lkIGFlc19jYmNfZGVjcnlwdChjb25z dCBzdHJ1Y3QgYWVzX2tleSAqaywKKwkJCSAgICBjb25zdCB1OCBpdltBRVNfQkxPQ0tfU0laRV0s CisJCQkgICAgY29uc3QgdTggKnNyYywgdTggKmRzdCwgc2l6ZV90IG5ieXRlcykKK3sKKwlzaXpl X3QgaSA9IG5ieXRlczsKKworCUFTU0VSVChpICUgQUVTX0JMT0NLX1NJWkUgPT0gMCk7CisJd2hp bGUgKGkpIHsKKwkJaSAtPSBBRVNfQkxPQ0tfU0laRTsKKwkJYWVzX2RlY3J5cHQoaywgJnNyY1tp XSwgJmRzdFtpXSk7CisJCXhvcigmZHN0W2ldLCAmZHN0W2ldLCAoaSA9PSAwID8gaXYgOiAmc3Jj W2kgLSBBRVNfQkxPQ0tfU0laRV0pLAorCQkgICAgQUVTX0JMT0NLX1NJWkUpOworCX0KK30KKwor c3RhdGljIHZvaWQgYWVzX2N0c19jYmNfZW5jcnlwdChjb25zdCB1OCAqa2V5LCBpbnQga2V5c2l6 ZSwKKwkJCQljb25zdCB1OCBpdltBRVNfQkxPQ0tfU0laRV0sCisJCQkJY29uc3QgdTggKnNyYywg dTggKmRzdCwgc2l6ZV90IG5ieXRlcykKK3sKKwljb25zdCBzaXplX3Qgb2Zmc2V0ID0gUk9VTkRf RE9XTihuYnl0ZXMgLSAxLCBBRVNfQkxPQ0tfU0laRSk7CisJY29uc3Qgc2l6ZV90IGZpbmFsX2Jz aXplID0gbmJ5dGVzIC0gb2Zmc2V0OworCXN0cnVjdCBhZXNfa2V5IGs7CisJdTggKnBhZDsKKwl1 OCBidWZbQUVTX0JMT0NLX1NJWkVdOworCisJQVNTRVJUKG5ieXRlcyA+PSBBRVNfQkxPQ0tfU0la RSk7CisKKwlhZXNfc2V0a2V5KCZrLCBrZXksIGtleXNpemUpOworCisJaWYgKG5ieXRlcyA9PSBB RVNfQkxPQ0tfU0laRSkKKwkJcmV0dXJuIGFlc19jYmNfZW5jcnlwdCgmaywgaXYsIHNyYywgZHN0 LCBuYnl0ZXMpOworCisJYWVzX2NiY19lbmNyeXB0KCZrLCBpdiwgc3JjLCBkc3QsIG9mZnNldCk7 CisJcGFkID0gJmRzdFtvZmZzZXQgLSBBRVNfQkxPQ0tfU0laRV07CisKKwltZW1jcHkoYnVmLCBw YWQsIEFFU19CTE9DS19TSVpFKTsKKwl4b3IoYnVmLCBidWYsICZzcmNbb2Zmc2V0XSwgZmluYWxf YnNpemUpOworCW1lbWNweSgmZHN0W29mZnNldF0sIHBhZCwgZmluYWxfYnNpemUpOworCWFlc19l bmNyeXB0KCZrLCBidWYsIHBhZCk7Cit9CisKK3N0YXRpYyB2b2lkIGFlc19jdHNfY2JjX2RlY3J5 cHQoY29uc3QgdTggKmtleSwgaW50IGtleXNpemUsCisJCQkJY29uc3QgdTggaXZbQUVTX0JMT0NL X1NJWkVdLAorCQkJCWNvbnN0IHU4ICpzcmMsIHU4ICpkc3QsIHNpemVfdCBuYnl0ZXMpCit7CisJ Y29uc3Qgc2l6ZV90IG9mZnNldCA9IFJPVU5EX0RPV04obmJ5dGVzIC0gMSwgQUVTX0JMT0NLX1NJ WkUpOworCWNvbnN0IHNpemVfdCBmaW5hbF9ic2l6ZSA9IG5ieXRlcyAtIG9mZnNldDsKKwlzdHJ1 Y3QgYWVzX2tleSBrOworCXU4ICpwYWQ7CisKKwlBU1NFUlQobmJ5dGVzID49IEFFU19CTE9DS19T SVpFKTsKKworCWFlc19zZXRrZXkoJmssIGtleSwga2V5c2l6ZSk7CisKKwlpZiAobmJ5dGVzID09 IEFFU19CTE9DS19TSVpFKQorCQlyZXR1cm4gYWVzX2NiY19kZWNyeXB0KCZrLCBpdiwgc3JjLCBk c3QsIG5ieXRlcyk7CisKKwlwYWQgPSAmZHN0W29mZnNldCAtIEFFU19CTE9DS19TSVpFXTsKKwlh ZXNfZGVjcnlwdCgmaywgJnNyY1tvZmZzZXQgLSBBRVNfQkxPQ0tfU0laRV0sIHBhZCk7CisJeG9y KCZkc3Rbb2Zmc2V0XSwgJnNyY1tvZmZzZXRdLCBwYWQsIGZpbmFsX2JzaXplKTsKKwl4b3IocGFk LCBwYWQsICZkc3Rbb2Zmc2V0XSwgZmluYWxfYnNpemUpOworCisJYWVzX2NiY19kZWNyeXB0KCZr LCAob2Zmc2V0ID09IEFFU19CTE9DS19TSVpFID8KKwkJCSAgICAgaXYgOiAmc3JjW29mZnNldCAt IDIgKiBBRVNfQkxPQ0tfU0laRV0pLAorCQkJcGFkLCBwYWQsIEFFU19CTE9DS19TSVpFKTsKKwlh ZXNfY2JjX2RlY3J5cHQoJmssIGl2LCBzcmMsIGRzdCwgb2Zmc2V0IC0gQUVTX0JMT0NLX1NJWkUp OworfQorCitzdGF0aWMgdm9pZCBhZXNfMjU2X2N0c19jYmNfZW5jcnlwdChjb25zdCB1OCBrZXlb QUVTXzI1Nl9LRVlfU0laRV0sCisJCQkJICAgIGNvbnN0IHU4IGl2W0FFU19CTE9DS19TSVpFXSwK KwkJCQkgICAgY29uc3QgdTggKnNyYywgdTggKmRzdCwgc2l6ZV90IG5ieXRlcykKK3sKKwlhZXNf Y3RzX2NiY19lbmNyeXB0KGtleSwgQUVTXzI1Nl9LRVlfU0laRSwgaXYsIHNyYywgZHN0LCBuYnl0 ZXMpOworfQorCitzdGF0aWMgdm9pZCBhZXNfMjU2X2N0c19jYmNfZGVjcnlwdChjb25zdCB1OCBr ZXlbQUVTXzI1Nl9LRVlfU0laRV0sCisJCQkJICAgIGNvbnN0IHU4IGl2W0FFU19CTE9DS19TSVpF XSwKKwkJCQkgICAgY29uc3QgdTggKnNyYywgdTggKmRzdCwgc2l6ZV90IG5ieXRlcykKK3sKKwlh ZXNfY3RzX2NiY19kZWNyeXB0KGtleSwgQUVTXzI1Nl9LRVlfU0laRSwgaXYsIHNyYywgZHN0LCBu Ynl0ZXMpOworfQorCisjaWZkZWYgRU5BQkxFX0FMR19URVNUUworI2luY2x1ZGUgPG9wZW5zc2wv bW9kZXMuaD4KK3N0YXRpYyB2b2lkIGFlc19ibG9jazEyOF9mKGNvbnN0IHVuc2lnbmVkIGNoYXIg aW5bMTZdLAorCQkJICAgdW5zaWduZWQgY2hhciBvdXRbMTZdLCBjb25zdCB2b2lkICprZXkpCit7 CisJYWVzX2VuY3J5cHQoa2V5LCBpbiwgb3V0KTsKK30KKworc3RhdGljIHZvaWQgdGVzdF9hZXNf MjU2X2N0c19jYmModm9pZCkKK3sKKwl1bnNpZ25lZCBsb25nIG51bV90ZXN0cyA9IE5VTV9BTEdf VEVTVF9JVEVSQVRJT05TOworCisJd2hpbGUgKG51bV90ZXN0cy0tKSB7CisJCXU4IGtleVtBRVNf MjU2X0tFWV9TSVpFXTsKKwkJdTggaXZbQUVTX0JMT0NLX1NJWkVdOworCQl1OCBpdl9jb3B5W0FF U19CTE9DS19TSVpFXTsKKwkJdTggcHRleHRbNTEyXTsKKwkJdTggY3RleHRbc2l6ZW9mKHB0ZXh0 KV07CisJCXU4IHJlZl9jdGV4dFtzaXplb2YocHRleHQpXTsKKwkJdTggZGVjcnlwdGVkW3NpemVv ZihwdGV4dCldOworCQljb25zdCBzaXplX3QgZGF0YWxlbiA9IDE2ICsgKHJhbmQoKSAlIChzaXpl b2YocHRleHQpIC0gMTUpKTsKKwkJc3RydWN0IGFlc19rZXkgazsKKworCQlyYW5kX2J5dGVzKGtl eSwgc2l6ZW9mKGtleSkpOworCQlyYW5kX2J5dGVzKGl2LCBzaXplb2YoaXYpKTsKKwkJcmFuZF9i eXRlcyhwdGV4dCwgZGF0YWxlbik7CisKKwkJYWVzXzI1Nl9jdHNfY2JjX2VuY3J5cHQoa2V5LCBp diwgcHRleHQsIGN0ZXh0LCBkYXRhbGVuKTsKKworCQkvKiBPcGVuU1NMIGRvZXNuJ3QgYWxsb3cg ZGF0YWxlbj1BRVNfQkxPQ0tfU0laRTsgTGludXggZG9lcyAqLworCQlpZiAoZGF0YWxlbiAhPSBB RVNfQkxPQ0tfU0laRSkgeworCQkJYWVzX3NldGtleSgmaywga2V5LCBzaXplb2Yoa2V5KSk7CisJ CQltZW1jcHkoaXZfY29weSwgaXYsIHNpemVvZihpdikpOworCQkJQVNTRVJUKENSWVBUT19jdHMx MjhfZW5jcnlwdF9ibG9jayhwdGV4dCwgcmVmX2N0ZXh0LAorCQkJCQkJCSAgIGRhdGFsZW4sICZr LCBpdl9jb3B5LAorCQkJCQkJCSAgIGFlc19ibG9jazEyOF9mKQorCQkJICAgICAgID09IGRhdGFs ZW4pOworCQkJQVNTRVJUKG1lbWNtcChjdGV4dCwgcmVmX2N0ZXh0LCBkYXRhbGVuKSA9PSAwKTsK KwkJfQorCQlhZXNfMjU2X2N0c19jYmNfZGVjcnlwdChrZXksIGl2LCBjdGV4dCwgZGVjcnlwdGVk LCBkYXRhbGVuKTsKKwkJQVNTRVJUKG1lbWNtcChwdGV4dCwgZGVjcnlwdGVkLCBkYXRhbGVuKSA9 PSAwKTsKKwl9Cit9CisjZW5kaWYgLyogRU5BQkxFX0FMR19URVNUUyAqLworCitzdGF0aWMgdm9p ZCBlc3Npdl9nZW5lcmF0ZV9pdihjb25zdCB1OCBvcmlnX2tleVtBRVNfMTI4X0tFWV9TSVpFXSwK KwkJCSAgICAgIGNvbnN0IHU4IG9yaWdfaXZbQUVTX0JMT0NLX1NJWkVdLAorCQkJICAgICAgdTgg cmVhbF9pdltBRVNfQkxPQ0tfU0laRV0pCit7CisJdTggZXNzaXZfa2V5W1NIQTI1Nl9ESUdFU1Rf U0laRV07CisJc3RydWN0IGFlc19rZXkgZXNzaXY7CisKKwkvKiBBRVMgZW5jcnlwdCB0aGUgb3Jp Z2luYWwgSVYgdXNpbmcgYSBoYXNoIG9mIHRoZSBvcmlnaW5hbCBrZXkgKi8KKwlTVEFUSUNfQVNT RVJUKFNIQTI1Nl9ESUdFU1RfU0laRSA9PSBBRVNfMjU2X0tFWV9TSVpFKTsKKwlzaGEyNTYob3Jp Z19rZXksIEFFU18xMjhfS0VZX1NJWkUsIGVzc2l2X2tleSk7CisJYWVzX3NldGtleSgmZXNzaXYs IGVzc2l2X2tleSwgQUVTXzI1Nl9LRVlfU0laRSk7CisJYWVzX2VuY3J5cHQoJmVzc2l2LCBvcmln X2l2LCByZWFsX2l2KTsKK30KKworc3RhdGljIHZvaWQgYWVzXzEyOF9jYmNfZXNzaXZfZW5jcnlw dChjb25zdCB1OCBrZXlbQUVTXzEyOF9LRVlfU0laRV0sCisJCQkJICAgICAgY29uc3QgdTggaXZb QUVTX0JMT0NLX1NJWkVdLAorCQkJCSAgICAgIGNvbnN0IHU4ICpzcmMsIHU4ICpkc3QsIHNpemVf dCBuYnl0ZXMpCit7CisJc3RydWN0IGFlc19rZXkgazsKKwl1OCByZWFsX2l2W0FFU19CTE9DS19T SVpFXTsKKworCWFlc19zZXRrZXkoJmssIGtleSwgQUVTXzEyOF9LRVlfU0laRSk7CisJZXNzaXZf Z2VuZXJhdGVfaXYoa2V5LCBpdiwgcmVhbF9pdik7CisJYWVzX2NiY19lbmNyeXB0KCZrLCByZWFs X2l2LCBzcmMsIGRzdCwgbmJ5dGVzKTsKK30KKworc3RhdGljIHZvaWQgYWVzXzEyOF9jYmNfZXNz aXZfZGVjcnlwdChjb25zdCB1OCBrZXlbQUVTXzEyOF9LRVlfU0laRV0sCisJCQkJICAgICAgY29u c3QgdTggaXZbQUVTX0JMT0NLX1NJWkVdLAorCQkJCSAgICAgIGNvbnN0IHU4ICpzcmMsIHU4ICpk c3QsIHNpemVfdCBuYnl0ZXMpCit7CisJc3RydWN0IGFlc19rZXkgazsKKwl1OCByZWFsX2l2W0FF U19CTE9DS19TSVpFXTsKKworCWFlc19zZXRrZXkoJmssIGtleSwgQUVTXzEyOF9LRVlfU0laRSk7 CisJZXNzaXZfZ2VuZXJhdGVfaXYoa2V5LCBpdiwgcmVhbF9pdik7CisJYWVzX2NiY19kZWNyeXB0 KCZrLCByZWFsX2l2LCBzcmMsIGRzdCwgbmJ5dGVzKTsKK30KKworc3RhdGljIHZvaWQgYWVzXzEy OF9jdHNfY2JjX2VuY3J5cHQoY29uc3QgdTgga2V5W0FFU18xMjhfS0VZX1NJWkVdLAorCQkJCSAg ICBjb25zdCB1OCBpdltBRVNfQkxPQ0tfU0laRV0sCisJCQkJICAgIGNvbnN0IHU4ICpzcmMsIHU4 ICpkc3QsIHNpemVfdCBuYnl0ZXMpCit7CisJYWVzX2N0c19jYmNfZW5jcnlwdChrZXksIEFFU18x MjhfS0VZX1NJWkUsIGl2LCBzcmMsIGRzdCwgbmJ5dGVzKTsKK30KKworc3RhdGljIHZvaWQgYWVz XzEyOF9jdHNfY2JjX2RlY3J5cHQoY29uc3QgdTgga2V5W0FFU18xMjhfS0VZX1NJWkVdLAorCQkJ CSAgICBjb25zdCB1OCBpdltBRVNfQkxPQ0tfU0laRV0sCisJCQkJICAgIGNvbnN0IHU4ICpzcmMs IHU4ICpkc3QsIHNpemVfdCBuYnl0ZXMpCit7CisJYWVzX2N0c19jYmNfZGVjcnlwdChrZXksIEFF U18xMjhfS0VZX1NJWkUsIGl2LCBzcmMsIGRzdCwgbmJ5dGVzKTsKK30KKworLyotLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tKgorICogICAgICAgICAgICAgICAgICAgICAgICAgICBYQ2hhQ2hhMTIgc3RyZWFt IGNpcGhlciAgICAgICAgICAgICAgICAgICAgICAgICAgKgorICotLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t Ki8KKworLyoKKyAqIFJlZmVyZW5jZXM6CisgKiAgIC0gIlhDaGFDaGE6IGVYdGVuZGVkLW5vbmNl IENoYUNoYSBhbmQgQUVBRF9YQ2hhQ2hhMjBfUG9seTEzMDUiCisgKglodHRwczovL3Rvb2xzLmll dGYub3JnL2h0bWwvZHJhZnQtYXJjaXN6ZXdza2kteGNoYWNoYS0wMworICoKKyAqICAgLSAiQ2hh Q2hhLCBhIHZhcmlhbnQgb2YgU2Fsc2EyMCIKKyAqCWh0dHBzOi8vY3IueXAudG8vY2hhY2hhL2No YWNoYS0yMDA4MDEyOC5wZGYKKyAqCisgKiAgIC0gIkV4dGVuZGluZyB0aGUgU2Fsc2EyMCBub25j ZSIKKyAqCWh0dHBzOi8vY3IueXAudG8vc251ZmZsZS94c2Fsc2EtMjAwODExMjgucGRmCisgKi8K KworI2RlZmluZSBDSEFDSEFfS0VZX1NJWkUJCTMyCisjZGVmaW5lIFhDSEFDSEFfS0VZX1NJWkUJ Q0hBQ0hBX0tFWV9TSVpFCisjZGVmaW5lIFhDSEFDSEFfTk9OQ0VfU0laRQkyNAorCitzdGF0aWMg dm9pZCBjaGFjaGFfaW5pdF9zdGF0ZSh1MzIgc3RhdGVbMTZdLCBjb25zdCB1OCBrZXlbQ0hBQ0hB X0tFWV9TSVpFXSwKKwkJCSAgICAgIGNvbnN0IHU4IGl2WzE2XSkKK3sKKwlzdGF0aWMgY29uc3Qg dTggY29uc3RzWzE2XSA9ICJleHBhbmQgMzItYnl0ZSBrIjsKKwlpbnQgaTsKKworCWZvciAoaSA9 IDA7IGkgPCA0OyBpKyspCisJCXN0YXRlW2ldID0gZ2V0X3VuYWxpZ25lZF9sZTMyKCZjb25zdHNb aSAqIHNpemVvZihfX2xlMzIpXSk7CisJZm9yIChpID0gMDsgaSA8IDg7IGkrKykKKwkJc3RhdGVb NCArIGldID0gZ2V0X3VuYWxpZ25lZF9sZTMyKCZrZXlbaSAqIHNpemVvZihfX2xlMzIpXSk7CisJ Zm9yIChpID0gMDsgaSA8IDQ7IGkrKykKKwkJc3RhdGVbMTIgKyBpXSA9IGdldF91bmFsaWduZWRf bGUzMigmaXZbaSAqIHNpemVvZihfX2xlMzIpXSk7Cit9CisKKyNkZWZpbmUgQ0hBQ0hBX1FVQVJU RVJST1VORChhLCBiLCBjLCBkKQkJXAorCWRvIHsJCQkJCVwKKwkJYSArPSBiOyBkID0gcm9sMzIo ZCBeIGEsIDE2KTsJXAorCQljICs9IGQ7IGIgPSByb2wzMihiIF4gYywgMTIpOwlcCisJCWEgKz0g YjsgZCA9IHJvbDMyKGQgXiBhLCA4KTsJXAorCQljICs9IGQ7IGIgPSByb2wzMihiIF4gYywgNyk7 CVwKKwl9IHdoaWxlICgwKQorCitzdGF0aWMgdm9pZCBjaGFjaGFfcGVybXV0ZSh1MzIgeFsxNl0s IGludCBucm91bmRzKQoreworCWRvIHsKKwkJLyogY29sdW1uIHJvdW5kICovCisJCUNIQUNIQV9R VUFSVEVSUk9VTkQoeFswXSwgeFs0XSwgeFs4XSwgeFsxMl0pOworCQlDSEFDSEFfUVVBUlRFUlJP VU5EKHhbMV0sIHhbNV0sIHhbOV0sIHhbMTNdKTsKKwkJQ0hBQ0hBX1FVQVJURVJST1VORCh4WzJd LCB4WzZdLCB4WzEwXSwgeFsxNF0pOworCQlDSEFDSEFfUVVBUlRFUlJPVU5EKHhbM10sIHhbN10s IHhbMTFdLCB4WzE1XSk7CisKKwkJLyogZGlhZ29uYWwgcm91bmQgKi8KKwkJQ0hBQ0hBX1FVQVJU RVJST1VORCh4WzBdLCB4WzVdLCB4WzEwXSwgeFsxNV0pOworCQlDSEFDSEFfUVVBUlRFUlJPVU5E KHhbMV0sIHhbNl0sIHhbMTFdLCB4WzEyXSk7CisJCUNIQUNIQV9RVUFSVEVSUk9VTkQoeFsyXSwg eFs3XSwgeFs4XSwgeFsxM10pOworCQlDSEFDSEFfUVVBUlRFUlJPVU5EKHhbM10sIHhbNF0sIHhb OV0sIHhbMTRdKTsKKwl9IHdoaWxlICgobnJvdW5kcyAtPSAyKSAhPSAwKTsKK30KKworc3RhdGlj IHZvaWQgeGNoYWNoYShjb25zdCB1OCBrZXlbWENIQUNIQV9LRVlfU0laRV0sCisJCSAgICBjb25z dCB1OCBub25jZVtYQ0hBQ0hBX05PTkNFX1NJWkVdLAorCQkgICAgY29uc3QgdTggKnNyYywgdTgg KmRzdCwgc2l6ZV90IG5ieXRlcywgaW50IG5yb3VuZHMpCit7CisJdTMyIHN0YXRlWzE2XTsKKwl1 OCByZWFsX2tleVtDSEFDSEFfS0VZX1NJWkVdOworCXU4IHJlYWxfaXZbMTZdID0geyAwIH07CisJ c2l6ZV90IGksIGo7CisKKwkvKiBDb21wdXRlIHJlYWwga2V5IHVzaW5nIG9yaWdpbmFsIGtleSBh bmQgZmlyc3QgMTI4IG5vbmNlIGJpdHMgKi8KKwljaGFjaGFfaW5pdF9zdGF0ZShzdGF0ZSwga2V5 LCBub25jZSk7CisJY2hhY2hhX3Blcm11dGUoc3RhdGUsIG5yb3VuZHMpOworCWZvciAoaSA9IDA7 IGkgPCA4OyBpKyspIC8qIHN0YXRlIHdvcmRzIDAuLjMsIDEyLi4xNSAqLworCQlwdXRfdW5hbGln bmVkX2xlMzIoc3RhdGVbKGkgPCA0ID8gMCA6IDgpICsgaV0sCisJCQkJICAgJnJlYWxfa2V5W2kg KiBzaXplb2YoX19sZTMyKV0pOworCisJLyogTm93IGRvIHJlZ3VsYXIgQ2hhQ2hhLCB1c2luZyBy ZWFsIGtleSBhbmQgcmVtYWluaW5nIG5vbmNlIGJpdHMgKi8KKwltZW1jcHkoJnJlYWxfaXZbOF0s IG5vbmNlICsgMTYsIDgpOworCWNoYWNoYV9pbml0X3N0YXRlKHN0YXRlLCByZWFsX2tleSwgcmVh bF9pdik7CisJZm9yIChpID0gMDsgaSA8IG5ieXRlczsgaSArPSA2NCkgeworCQl1MzIgeFsxNl07 CisJCV9fbGUzMiBrZXlzdHJlYW1bMTZdOworCisJCW1lbWNweSh4LCBzdGF0ZSwgNjQpOworCQlj aGFjaGFfcGVybXV0ZSh4LCBucm91bmRzKTsKKwkJZm9yIChqID0gMDsgaiA8IDE2OyBqKyspCisJ CQlrZXlzdHJlYW1bal0gPSBjcHVfdG9fbGUzMih4W2pdICsgc3RhdGVbal0pOworCQl4b3IoJmRz dFtpXSwgJnNyY1tpXSwgKHU4ICopa2V5c3RyZWFtLCBNSU4obmJ5dGVzIC0gaSwgNjQpKTsKKwkJ aWYgKCsrc3RhdGVbMTJdID09IDApCisJCQlzdGF0ZVsxM10rKzsKKwl9Cit9CisKK3N0YXRpYyB2 b2lkIHhjaGFjaGExMihjb25zdCB1OCBrZXlbWENIQUNIQV9LRVlfU0laRV0sCisJCSAgICAgIGNv bnN0IHU4IG5vbmNlW1hDSEFDSEFfTk9OQ0VfU0laRV0sCisJCSAgICAgIGNvbnN0IHU4ICpzcmMs IHU4ICpkc3QsIHNpemVfdCBuYnl0ZXMpCit7CisJeGNoYWNoYShrZXksIG5vbmNlLCBzcmMsIGRz dCwgbmJ5dGVzLCAxMik7Cit9CisKKy8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSoKKyAqICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgUG9seTEzMDUgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICoKKyAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCisKKy8qCisgKiBOb3RlOiB0aGlz IGlzIG9ubHkgdGhlIFBvbHkxMzA1IM61LWFsbW9zdC3iiIYtdW5pdmVyc2FsIGhhc2ggZnVuY3Rp b24sIG5vdCB0aGUKKyAqIGZ1bGwgUG9seTEzMDUgTUFDLiAgSS5lLiwgaXQgZG9lc24ndCBhZGQg YW55dGhpbmcgYXQgdGhlIGVuZC4KKyAqLworCisjZGVmaW5lIFBPTFkxMzA1X0tFWV9TSVpFCTE2 CisjZGVmaW5lIFBPTFkxMzA1X0JMT0NLX1NJWkUJMTYKKworc3RhdGljIHZvaWQgcG9seTEzMDUo Y29uc3QgdTgga2V5W1BPTFkxMzA1X0tFWV9TSVpFXSwKKwkJICAgICBjb25zdCB1OCAqbXNnLCBz aXplX3QgbXNnbGVuLCBsZTEyOCAqb3V0KQoreworCWNvbnN0IHUzMiBsaW1iX21hc2sgPSAweDNm ZmZmZmY7CS8qIGxpbWJzIGFyZSBiYXNlIDJeMjYgKi8KKwljb25zdCB1NjQgcjAgPSAoZ2V0X3Vu YWxpZ25lZF9sZTMyKGtleSArICAwKSA+PiAwKSAmIDB4M2ZmZmZmZjsKKwljb25zdCB1NjQgcjEg PSAoZ2V0X3VuYWxpZ25lZF9sZTMyKGtleSArICAzKSA+PiAyKSAmIDB4M2ZmZmYwMzsKKwljb25z dCB1NjQgcjIgPSAoZ2V0X3VuYWxpZ25lZF9sZTMyKGtleSArICA2KSA+PiA0KSAmIDB4M2ZmYzBm ZjsKKwljb25zdCB1NjQgcjMgPSAoZ2V0X3VuYWxpZ25lZF9sZTMyKGtleSArICA5KSA+PiA2KSAm IDB4M2YwM2ZmZjsKKwljb25zdCB1NjQgcjQgPSAoZ2V0X3VuYWxpZ25lZF9sZTMyKGtleSArIDEy KSA+PiA4KSAmIDB4MDBmZmZmZjsKKwl1MzIgaDAgPSAwLCBoMSA9IDAsIGgyID0gMCwgaDMgPSAw LCBoNCA9IDA7CisJdTMyIGcwLCBnMSwgZzIsIGczLCBnNCwgZ2VfcF9tYXNrOworCisJLyogUGFy dGlhbCBibG9jayBzdXBwb3J0IGlzIG5vdCBuZWNlc3NhcnkgZm9yIEFkaWFudHVtICovCisJQVNT RVJUKG1zZ2xlbiAlIFBPTFkxMzA1X0JMT0NLX1NJWkUgPT0gMCk7CisKKwl3aGlsZSAobXNnbGVu KSB7CisJCXU2NCBkMCwgZDEsIGQyLCBkMywgZDQ7CisKKwkJLyogaCArPSAqbXNnICovCisJCWgw ICs9IChnZXRfdW5hbGlnbmVkX2xlMzIobXNnICsgIDApID4+IDApICYgbGltYl9tYXNrOworCQlo MSArPSAoZ2V0X3VuYWxpZ25lZF9sZTMyKG1zZyArICAzKSA+PiAyKSAmIGxpbWJfbWFzazsKKwkJ aDIgKz0gKGdldF91bmFsaWduZWRfbGUzMihtc2cgKyAgNikgPj4gNCkgJiBsaW1iX21hc2s7CisJ CWgzICs9IChnZXRfdW5hbGlnbmVkX2xlMzIobXNnICsgIDkpID4+IDYpICYgbGltYl9tYXNrOwor CQloNCArPSAoZ2V0X3VuYWxpZ25lZF9sZTMyKG1zZyArIDEyKSA+PiA4KSB8ICgxIDw8IDI0KTsK KworCQkvKiBoICo9IHIgKi8KKwkJZDAgPSBoMCpyMCArIGgxKjUqcjQgKyBoMio1KnIzICsgaDMq NSpyMiArIGg0KjUqcjE7CisJCWQxID0gaDAqcjEgKyBoMSpyMCAgICsgaDIqNSpyNCArIGgzKjUq cjMgKyBoNCo1KnIyOworCQlkMiA9IGgwKnIyICsgaDEqcjEgICArIGgyKnIwICAgKyBoMyo1KnI0 ICsgaDQqNSpyMzsKKwkJZDMgPSBoMCpyMyArIGgxKnIyICAgKyBoMipyMSAgICsgaDMqcjAgICAr IGg0KjUqcjQ7CisJCWQ0ID0gaDAqcjQgKyBoMSpyMyAgICsgaDIqcjIgICArIGgzKnIxICAgKyBo NCpyMDsKKworCQkvKiAocGFydGlhbCkgaCAlPSAyXjEzMCAtIDUgKi8KKwkJZDEgKz0gZDAgPj4g MjY7CQloMCA9IGQwICYgbGltYl9tYXNrOworCQlkMiArPSBkMSA+PiAyNjsJCWgxID0gZDEgJiBs aW1iX21hc2s7CisJCWQzICs9IGQyID4+IDI2OwkJaDIgPSBkMiAmIGxpbWJfbWFzazsKKwkJZDQg Kz0gZDMgPj4gMjY7CQloMyA9IGQzICYgbGltYl9tYXNrOworCQloMCArPSAoZDQgPj4gMjYpICog NTsJaDQgPSBkNCAmIGxpbWJfbWFzazsKKwkJaDEgKz0gaDAgPj4gMjY7CQloMCAmPSBsaW1iX21h c2s7CisKKwkJbXNnICs9IFBPTFkxMzA1X0JMT0NLX1NJWkU7CisJCW1zZ2xlbiAtPSBQT0xZMTMw NV9CTE9DS19TSVpFOworCX0KKworCS8qIGZ1bGx5IGNhcnJ5IGggKi8KKwloMiArPSAoaDEgPj4g MjYpOwloMSAmPSBsaW1iX21hc2s7CisJaDMgKz0gKGgyID4+IDI2KTsJaDIgJj0gbGltYl9tYXNr OworCWg0ICs9IChoMyA+PiAyNik7CWgzICY9IGxpbWJfbWFzazsKKwloMCArPSAoaDQgPj4gMjYp ICogNTsJaDQgJj0gbGltYl9tYXNrOworCWgxICs9IChoMCA+PiAyNik7CWgwICY9IGxpbWJfbWFz azsKKworCS8qIGlmIChoID49IDJeMTMwIC0gNSkgaCAtPSAyXjEzMCAtIDU7ICovCisJZzAgPSBo MCArIDU7CisJZzEgPSBoMSArIChnMCA+PiAyNik7CWcwICY9IGxpbWJfbWFzazsKKwlnMiA9IGgy ICsgKGcxID4+IDI2KTsJZzEgJj0gbGltYl9tYXNrOworCWczID0gaDMgKyAoZzIgPj4gMjYpOwln MiAmPSBsaW1iX21hc2s7CisJZzQgPSBoNCArIChnMyA+PiAyNik7CWczICY9IGxpbWJfbWFzazsK KwlnZV9wX21hc2sgPSB+KChnNCA+PiAyNikgLSAxKTsgLyogYWxsIDEncyBpZiBoID49IDJeMTMw IC0gNSwgZWxzZSAwICovCisJaDAgPSAoaDAgJiB+Z2VfcF9tYXNrKSB8IChnMCAmIGdlX3BfbWFz ayk7CisJaDEgPSAoaDEgJiB+Z2VfcF9tYXNrKSB8IChnMSAmIGdlX3BfbWFzayk7CisJaDIgPSAo aDIgJiB+Z2VfcF9tYXNrKSB8IChnMiAmIGdlX3BfbWFzayk7CisJaDMgPSAoaDMgJiB+Z2VfcF9t YXNrKSB8IChnMyAmIGdlX3BfbWFzayk7CisJaDQgPSAoaDQgJiB+Z2VfcF9tYXNrKSB8IChnNCAm IGdlX3BfbWFzayAmIGxpbWJfbWFzayk7CisKKwkvKiBoICU9IDJeMTI4ICovCisJb3V0LT5sbyA9 IGNwdV90b19sZTY0KCgodTY0KWgyIDw8IDUyKSB8ICgodTY0KWgxIDw8IDI2KSB8IGgwKTsKKwlv dXQtPmhpID0gY3B1X3RvX2xlNjQoKCh1NjQpaDQgPDwgNDApIHwgKCh1NjQpaDMgPDwgMTQpIHwg KGgyID4+IDEyKSk7Cit9CisKKy8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSoKKyAqICAgICAgICAgICAg ICAgICAgICAgICAgICBBZGlhbnR1bSBlbmNyeXB0aW9uIG1vZGUgICAgICAgICAgICAgICAgICAg ICAgICAgICoKKyAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCisKKy8qCisgKiBSZWZlcmVuY2U6ICJB ZGlhbnR1bTogbGVuZ3RoLXByZXNlcnZpbmcgZW5jcnlwdGlvbiBmb3IgZW50cnktbGV2ZWwgcHJv Y2Vzc29ycyIKKyAqCWh0dHBzOi8vdG9zYy5pYWNyLm9yZy9pbmRleC5waHAvVG9TQy9hcnRpY2xl L3ZpZXcvNzM2MAorICovCisKKyNkZWZpbmUgQURJQU5UVU1fS0VZX1NJWkUJMzIKKyNkZWZpbmUg QURJQU5UVU1fSVZfU0laRQkzMgorI2RlZmluZSBBRElBTlRVTV9IQVNIX0tFWV9TSVpFCSgoMiAq IFBPTFkxMzA1X0tFWV9TSVpFKSArIE5IX0tFWV9TSVpFKQorCisjZGVmaW5lIE5IX0tFWV9TSVpF CQkxMDcyCisjZGVmaW5lIE5IX0tFWV9XT1JEUwkJKE5IX0tFWV9TSVpFIC8gc2l6ZW9mKHUzMikp CisjZGVmaW5lIE5IX0JMT0NLX1NJWkUJCTEwMjQKKyNkZWZpbmUgTkhfSEFTSF9TSVpFCQkzMgor I2RlZmluZSBOSF9NRVNTQUdFX1VOSVQJCTE2CisKK3N0YXRpYyB1NjQgbmhfcGFzcyhjb25zdCB1 MzIgKmtleSwgY29uc3QgdTggKm1zZywgc2l6ZV90IG1zZ2xlbikKK3sKKwl1NjQgc3VtID0gMDsK KworCUFTU0VSVChtc2dsZW4gJSBOSF9NRVNTQUdFX1VOSVQgPT0gMCk7CisJd2hpbGUgKG1zZ2xl bikgeworCQlzdW0gKz0gKHU2NCkodTMyKShnZXRfdW5hbGlnbmVkX2xlMzIobXNnICsgIDApICsg a2V5WzBdKSAqCisJCQkgICAgKHUzMikoZ2V0X3VuYWxpZ25lZF9sZTMyKG1zZyArICA4KSArIGtl eVsyXSk7CisJCXN1bSArPSAodTY0KSh1MzIpKGdldF91bmFsaWduZWRfbGUzMihtc2cgKyAgNCkg KyBrZXlbMV0pICoKKwkJCSAgICAodTMyKShnZXRfdW5hbGlnbmVkX2xlMzIobXNnICsgMTIpICsg a2V5WzNdKTsKKwkJa2V5ICs9IE5IX01FU1NBR0VfVU5JVCAvIHNpemVvZihrZXlbMF0pOworCQlt c2cgKz0gTkhfTUVTU0FHRV9VTklUOworCQltc2dsZW4gLT0gTkhfTUVTU0FHRV9VTklUOworCX0K KwlyZXR1cm4gc3VtOworfQorCisvKiBOSCDOtS1hbG1vc3QtdW5pdmVyc2FsIGhhc2ggZnVuY3Rp b24gKi8KK3N0YXRpYyB2b2lkIG5oKGNvbnN0IHUzMiAqa2V5LCBjb25zdCB1OCAqbXNnLCBzaXpl X3QgbXNnbGVuLAorCSAgICAgICB1OCByZXN1bHRbTkhfSEFTSF9TSVpFXSkKK3sKKwlzaXplX3Qg aTsKKworCWZvciAoaSA9IDA7IGkgPCBOSF9IQVNIX1NJWkU7IGkgKz0gc2l6ZW9mKF9fbGU2NCkp IHsKKwkJcHV0X3VuYWxpZ25lZF9sZTY0KG5oX3Bhc3Moa2V5LCBtc2csIG1zZ2xlbiksICZyZXN1 bHRbaV0pOworCQlrZXkgKz0gTkhfTUVTU0FHRV9VTklUIC8gc2l6ZW9mKGtleVswXSk7CisJfQor fQorCisvKiBBZGlhbnR1bSdzIM61LWFsbW9zdC3iiIYtdW5pdmVyc2FsIGhhc2ggZnVuY3Rpb24g Ki8KK3N0YXRpYyB2b2lkIGFkaWFudHVtX2hhc2goY29uc3QgdTgga2V5W0FESUFOVFVNX0hBU0hf S0VZX1NJWkVdLAorCQkJICBjb25zdCB1OCBpdltBRElBTlRVTV9JVl9TSVpFXSwKKwkJCSAgY29u c3QgdTggKm1zZywgc2l6ZV90IG1zZ2xlbiwgbGUxMjggKnJlc3VsdCkKK3sKKwljb25zdCB1OCAq aGVhZGVyX3BvbHlfa2V5ID0ga2V5OworCWNvbnN0IHU4ICptc2dfcG9seV9rZXkgPSBoZWFkZXJf cG9seV9rZXkgKyBQT0xZMTMwNV9LRVlfU0laRTsKKwljb25zdCB1OCAqbmhfa2V5ID0gbXNnX3Bv bHlfa2V5ICsgUE9MWTEzMDVfS0VZX1NJWkU7CisJdTMyIG5oX2tleV93b3Jkc1tOSF9LRVlfV09S RFNdOworCXU4IGhlYWRlcltQT0xZMTMwNV9CTE9DS19TSVpFICsgQURJQU5UVU1fSVZfU0laRV07 CisJY29uc3Qgc2l6ZV90IG51bV9uaF9ibG9ja3MgPSBESVZfUk9VTkRfVVAobXNnbGVuLCBOSF9C TE9DS19TSVpFKTsKKwl1OCAqbmhfaGFzaGVzID0geG1hbGxvYyhudW1fbmhfYmxvY2tzICogTkhf SEFTSF9TSVpFKTsKKwljb25zdCBzaXplX3QgcGFkZGVkX21zZ2xlbiA9IFJPVU5EX1VQKG1zZ2xl biwgTkhfTUVTU0FHRV9VTklUKTsKKwl1OCAqcGFkZGVkX21zZyA9IHhtYWxsb2MocGFkZGVkX21z Z2xlbik7CisJbGUxMjggaGFzaDEsIGhhc2gyOworCXNpemVfdCBpOworCisJZm9yIChpID0gMDsg aSA8IE5IX0tFWV9XT1JEUzsgaSsrKQorCQluaF9rZXlfd29yZHNbaV0gPSBnZXRfdW5hbGlnbmVk X2xlMzIoJm5oX2tleVtpICogc2l6ZW9mKHUzMildKTsKKworCS8qIEhhc2ggdHdlYWsgYW5kIG1l c3NhZ2UgbGVuZ3RoIHdpdGggZmlyc3QgUG9seTEzMDUga2V5ICovCisJcHV0X3VuYWxpZ25lZF9s ZTY0KCh1NjQpbXNnbGVuICogOCwgaGVhZGVyKTsKKwlwdXRfdW5hbGlnbmVkX2xlNjQoMCwgJmhl YWRlcltzaXplb2YoX19sZTY0KV0pOworCW1lbWNweSgmaGVhZGVyW1BPTFkxMzA1X0JMT0NLX1NJ WkVdLCBpdiwgQURJQU5UVU1fSVZfU0laRSk7CisJcG9seTEzMDUoaGVhZGVyX3BvbHlfa2V5LCBo ZWFkZXIsIHNpemVvZihoZWFkZXIpLCAmaGFzaDEpOworCisJLyogSGFzaCBOSCBoYXNoZXMgb2Yg bWVzc2FnZSBibG9ja3MgdXNpbmcgc2Vjb25kIFBvbHkxMzA1IGtleSAqLworCS8qICh1c2luZyBh IHN1cGVyIG5haXZlIHdheSBvZiBoYW5kbGluZyB0aGUgcGFkZGluZykgKi8KKwltZW1jcHkocGFk ZGVkX21zZywgbXNnLCBtc2dsZW4pOworCW1lbXNldCgmcGFkZGVkX21zZ1ttc2dsZW5dLCAwLCBw YWRkZWRfbXNnbGVuIC0gbXNnbGVuKTsKKwlmb3IgKGkgPSAwOyBpIDwgbnVtX25oX2Jsb2Nrczsg aSsrKSB7CisJCW5oKG5oX2tleV93b3JkcywgJnBhZGRlZF9tc2dbaSAqIE5IX0JMT0NLX1NJWkVd LAorCQkgICBNSU4oTkhfQkxPQ0tfU0laRSwgcGFkZGVkX21zZ2xlbiAtIChpICogTkhfQkxPQ0tf U0laRSkpLAorCQkgICAmbmhfaGFzaGVzW2kgKiBOSF9IQVNIX1NJWkVdKTsKKwl9CisJcG9seTEz MDUobXNnX3BvbHlfa2V5LCBuaF9oYXNoZXMsIG51bV9uaF9ibG9ja3MgKiBOSF9IQVNIX1NJWkUs ICZoYXNoMik7CisKKwkvKiBBZGQgdGhlIHR3byBoYXNoZXMgdG9nZXRoZXIgdG8gZ2V0IHRoZSBm aW5hbCBoYXNoICovCisJbGUxMjhfYWRkKHJlc3VsdCwgJmhhc2gxLCAmaGFzaDIpOworCisJZnJl ZShuaF9oYXNoZXMpOworCWZyZWUocGFkZGVkX21zZyk7Cit9CisKK3N0YXRpYyB2b2lkIGFkaWFu dHVtX2NyeXB0KGNvbnN0IHU4IGtleVtBRElBTlRVTV9LRVlfU0laRV0sCisJCQkgICBjb25zdCB1 OCBpdltBRElBTlRVTV9JVl9TSVpFXSwgY29uc3QgdTggKnNyYywKKwkJCSAgIHU4ICpkc3QsIHNp emVfdCBuYnl0ZXMsIGJvb2wgZGVjcnlwdGluZykKK3sKKwl1OCBzdWJrZXlzW0FFU18yNTZfS0VZ X1NJWkUgKyBBRElBTlRVTV9IQVNIX0tFWV9TSVpFXSA9IHsgMCB9OworCXN0cnVjdCBhZXNfa2V5 IGFlc19rZXk7CisJdW5pb24geworCQl1OCBub25jZVtYQ0hBQ0hBX05PTkNFX1NJWkVdOworCQls ZTEyOCBibG9jazsKKwl9IHUgPSB7IC5ub25jZSA9IHsgMSB9IH07CisJY29uc3Qgc2l6ZV90IGJ1 bGtfbGVuID0gbmJ5dGVzIC0gc2l6ZW9mKHUuYmxvY2spOworCWxlMTI4IGhhc2g7CisKKwlBU1NF UlQobmJ5dGVzID49IHNpemVvZih1LmJsb2NrKSk7CisKKwkvKiBEZXJpdmUgc3Via2V5cyAqLwor CXhjaGFjaGExMihrZXksIHUubm9uY2UsIHN1YmtleXMsIHN1YmtleXMsIHNpemVvZihzdWJrZXlz KSk7CisJYWVzX3NldGtleSgmYWVzX2tleSwgc3Via2V5cywgQUVTXzI1Nl9LRVlfU0laRSk7CisK KwkvKiBIYXNoIGxlZnQgcGFydCBhbmQgYWRkIHRvIHJpZ2h0IHBhcnQgKi8KKwlhZGlhbnR1bV9o YXNoKCZzdWJrZXlzW0FFU18yNTZfS0VZX1NJWkVdLCBpdiwgc3JjLCBidWxrX2xlbiwgJmhhc2gp OworCW1lbWNweSgmdS5ibG9jaywgJnNyY1tidWxrX2xlbl0sIHNpemVvZih1LmJsb2NrKSk7CisJ bGUxMjhfYWRkKCZ1LmJsb2NrLCAmdS5ibG9jaywgJmhhc2gpOworCisJaWYgKCFkZWNyeXB0aW5n KSAvKiBFbmNyeXB0IHJpZ2h0IHBhcnQgd2l0aCBibG9jayBjaXBoZXIgKi8KKwkJYWVzX2VuY3J5 cHQoJmFlc19rZXksIHUubm9uY2UsIHUubm9uY2UpOworCisJLyogRW5jcnlwdCBsZWZ0IHBhcnQg d2l0aCBzdHJlYW0gY2lwaGVyLCB1c2luZyB0aGUgY29tcHV0ZWQgbm9uY2UgKi8KKwl1Lm5vbmNl W3NpemVvZih1LmJsb2NrKV0gPSAxOworCXhjaGFjaGExMihrZXksIHUubm9uY2UsIHNyYywgZHN0 LCBidWxrX2xlbik7CisKKwlpZiAoZGVjcnlwdGluZykgLyogRGVjcnlwdCByaWdodCBwYXJ0IHdp dGggYmxvY2sgY2lwaGVyICovCisJCWFlc19kZWNyeXB0KCZhZXNfa2V5LCB1Lm5vbmNlLCB1Lm5v bmNlKTsKKworCS8qIEZpbmFsaXplIHJpZ2h0IHBhcnQgYnkgc3VidHJhY3RpbmcgaGFzaCBvZiBs ZWZ0IHBhcnQgKi8KKwlhZGlhbnR1bV9oYXNoKCZzdWJrZXlzW0FFU18yNTZfS0VZX1NJWkVdLCBp diwgZHN0LCBidWxrX2xlbiwgJmhhc2gpOworCWxlMTI4X3N1YigmdS5ibG9jaywgJnUuYmxvY2ss ICZoYXNoKTsKKwltZW1jcHkoJmRzdFtidWxrX2xlbl0sICZ1LmJsb2NrLCBzaXplb2YodS5ibG9j aykpOworfQorCitzdGF0aWMgdm9pZCBhZGlhbnR1bV9lbmNyeXB0KGNvbnN0IHU4IGtleVtBRElB TlRVTV9LRVlfU0laRV0sCisJCQkgICAgIGNvbnN0IHU4IGl2W0FESUFOVFVNX0lWX1NJWkVdLAor CQkJICAgICBjb25zdCB1OCAqc3JjLCB1OCAqZHN0LCBzaXplX3QgbmJ5dGVzKQoreworCWFkaWFu dHVtX2NyeXB0KGtleSwgaXYsIHNyYywgZHN0LCBuYnl0ZXMsIGZhbHNlKTsKK30KKworc3RhdGlj IHZvaWQgYWRpYW50dW1fZGVjcnlwdChjb25zdCB1OCBrZXlbQURJQU5UVU1fS0VZX1NJWkVdLAor CQkJICAgICBjb25zdCB1OCBpdltBRElBTlRVTV9JVl9TSVpFXSwKKwkJCSAgICAgY29uc3QgdTgg KnNyYywgdTggKmRzdCwgc2l6ZV90IG5ieXRlcykKK3sKKwlhZGlhbnR1bV9jcnlwdChrZXksIGl2 LCBzcmMsIGRzdCwgbmJ5dGVzLCB0cnVlKTsKK30KKworI2lmZGVmIEVOQUJMRV9BTEdfVEVTVFMK KyNpbmNsdWRlIDxsaW51eC9pZl9hbGcuaD4KKyNpbmNsdWRlIDxzeXMvc29ja2V0Lmg+CisjZGVm aW5lIFNPTF9BTEcgMjc5CitzdGF0aWMgdm9pZCBhZl9hbGdfY3J5cHQoaW50IGFsZ2ZkLCBpbnQg b3AsIGNvbnN0IHU4ICprZXksIHNpemVfdCBrZXlsZW4sCisJCQkgY29uc3QgdTggKml2LCBzaXpl X3QgaXZsZW4sCisJCQkgY29uc3QgdTggKnNyYywgdTggKmRzdCwgc2l6ZV90IGRhdGFsZW4pCit7 CisJc2l6ZV90IGNvbnRyb2xsZW4gPSBDTVNHX1NQQUNFKHNpemVvZihpbnQpKSArCisJCQkgICAg Q01TR19TUEFDRShzaXplb2Yoc3RydWN0IGFmX2FsZ19pdikgKyBpdmxlbik7CisJdTggKmNvbnRy b2wgPSB4bWFsbG9jKGNvbnRyb2xsZW4pOworCXN0cnVjdCBpb3ZlYyBpb3YgPSB7IC5pb3ZfYmFz ZSA9ICh1OCAqKXNyYywgLmlvdl9sZW4gPSBkYXRhbGVuIH07CisJc3RydWN0IG1zZ2hkciBtc2cg PSB7CisJCS5tc2dfaW92ID0gJmlvdiwKKwkJLm1zZ19pb3ZsZW4gPSAxLAorCQkubXNnX2NvbnRy b2wgPSBjb250cm9sLAorCQkubXNnX2NvbnRyb2xsZW4gPSBjb250cm9sbGVuLAorCX07CisJc3Ry dWN0IGNtc2doZHIgKmNtc2c7CisJc3RydWN0IGFmX2FsZ19pdiAqYWxnaXY7CisJaW50IHJlcWZk OworCisJbWVtc2V0KGNvbnRyb2wsIDAsIGNvbnRyb2xsZW4pOworCisJY21zZyA9IENNU0dfRklS U1RIRFIoJm1zZyk7CisJY21zZy0+Y21zZ19sZW4gPSBDTVNHX0xFTihzaXplb2YoaW50KSk7CisJ Y21zZy0+Y21zZ19sZXZlbCA9IFNPTF9BTEc7CisJY21zZy0+Y21zZ190eXBlID0gQUxHX1NFVF9P UDsKKwkqKGludCAqKUNNU0dfREFUQShjbXNnKSA9IG9wOworCisJY21zZyA9IENNU0dfTlhUSERS KCZtc2csIGNtc2cpOworCWNtc2ctPmNtc2dfbGVuID0gQ01TR19MRU4oc2l6ZW9mKHN0cnVjdCBh Zl9hbGdfaXYpICsgaXZsZW4pOworCWNtc2ctPmNtc2dfbGV2ZWwgPSBTT0xfQUxHOworCWNtc2ct PmNtc2dfdHlwZSA9IEFMR19TRVRfSVY7CisJYWxnaXYgPSAoc3RydWN0IGFmX2FsZ19pdiAqKUNN U0dfREFUQShjbXNnKTsKKwlhbGdpdi0+aXZsZW4gPSBpdmxlbjsKKwltZW1jcHkoYWxnaXYtPml2 LCBpdiwgaXZsZW4pOworCisJaWYgKHNldHNvY2tvcHQoYWxnZmQsIFNPTF9BTEcsIEFMR19TRVRf S0VZLCBrZXksIGtleWxlbikgIT0gMCkKKwkJZGllX2Vycm5vKCJjYW4ndCBzZXQga2V5IG9uIEFG X0FMRyBzb2NrZXQiKTsKKworCXJlcWZkID0gYWNjZXB0KGFsZ2ZkLCBOVUxMLCBOVUxMKTsKKwlp ZiAocmVxZmQgPCAwKQorCQlkaWVfZXJybm8oImNhbid0IGFjY2VwdCgpIEFGX0FMRyBzb2NrZXQi KTsKKwlpZiAoc2VuZG1zZyhyZXFmZCwgJm1zZywgMCkgIT0gZGF0YWxlbikKKwkJZGllX2Vycm5v KCJjYW4ndCBzZW5kbXNnKCkgQUZfQUxHIHJlcXVlc3Qgc29ja2V0Iik7CisJaWYgKHhyZWFkKHJl cWZkLCBkc3QsIGRhdGFsZW4pICE9IGRhdGFsZW4pCisJCWRpZSgic2hvcnQgcmVhZCBmcm9tIEFG X0FMRyByZXF1ZXN0IHNvY2tldCIpOworCWNsb3NlKHJlcWZkKTsKKworCWZyZWUoY29udHJvbCk7 Cit9CisKK3N0YXRpYyB2b2lkIHRlc3RfYWRpYW50dW0odm9pZCkKK3sKKwlpbnQgYWxnZmQgPSBz b2NrZXQoQUZfQUxHLCBTT0NLX1NFUVBBQ0tFVCwgMCk7CisJc3RydWN0IHNvY2thZGRyX2FsZyBh ZGRyID0geworCQkuc2FsZ190eXBlID0gInNrY2lwaGVyIiwKKwkJLnNhbGdfbmFtZSA9ICJhZGlh bnR1bSh4Y2hhY2hhMTIsYWVzKSIsCisJfTsKKwl1bnNpZ25lZCBsb25nIG51bV90ZXN0cyA9IE5V TV9BTEdfVEVTVF9JVEVSQVRJT05TOworCisJaWYgKGFsZ2ZkIDwgMCkKKwkJZGllX2Vycm5vKCJj YW4ndCBjcmVhdGUgQUZfQUxHIHNvY2tldCIpOworCWlmIChiaW5kKGFsZ2ZkLCAoc3RydWN0IHNv Y2thZGRyICopJmFkZHIsIHNpemVvZihhZGRyKSkgIT0gMCkKKwkJZGllX2Vycm5vKCJjYW4ndCBi aW5kIEFGX0FMRyBzb2NrZXQgdG8gQWRpYW50dW0gYWxnb3JpdGhtIik7CisKKwl3aGlsZSAobnVt X3Rlc3RzLS0pIHsKKwkJdTgga2V5W0FESUFOVFVNX0tFWV9TSVpFXTsKKwkJdTggaXZbQURJQU5U VU1fSVZfU0laRV07CisJCXU4IHB0ZXh0WzQwOTZdOworCQl1OCBjdGV4dFtzaXplb2YocHRleHQp XTsKKwkJdTggcmVmX2N0ZXh0W3NpemVvZihwdGV4dCldOworCQl1OCBkZWNyeXB0ZWRbc2l6ZW9m KHB0ZXh0KV07CisJCWNvbnN0IHNpemVfdCBkYXRhbGVuID0gMTYgKyAocmFuZCgpICUgKHNpemVv ZihwdGV4dCkgLSAxNSkpOworCisJCXJhbmRfYnl0ZXMoa2V5LCBzaXplb2Yoa2V5KSk7CisJCXJh bmRfYnl0ZXMoaXYsIHNpemVvZihpdikpOworCQlyYW5kX2J5dGVzKHB0ZXh0LCBkYXRhbGVuKTsK KworCQlhZGlhbnR1bV9lbmNyeXB0KGtleSwgaXYsIHB0ZXh0LCBjdGV4dCwgZGF0YWxlbik7CisJ CWFmX2FsZ19jcnlwdChhbGdmZCwgQUxHX09QX0VOQ1JZUFQsIGtleSwgc2l6ZW9mKGtleSksCisJ CQkgICAgIGl2LCBzaXplb2YoaXYpLCBwdGV4dCwgcmVmX2N0ZXh0LCBkYXRhbGVuKTsKKwkJQVNT RVJUKG1lbWNtcChjdGV4dCwgcmVmX2N0ZXh0LCBkYXRhbGVuKSA9PSAwKTsKKworCQlhZGlhbnR1 bV9kZWNyeXB0KGtleSwgaXYsIGN0ZXh0LCBkZWNyeXB0ZWQsIGRhdGFsZW4pOworCQlBU1NFUlQo bWVtY21wKHB0ZXh0LCBkZWNyeXB0ZWQsIGRhdGFsZW4pID09IDApOworCX0KKwljbG9zZShhbGdm ZCk7Cit9CisjZW5kaWYgLyogRU5BQkxFX0FMR19URVNUUyAqLworCisvKi0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0qCisgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNYWluIHByb2dyYW0gICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqCisgKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwor CisjZGVmaW5lIEZJTEVfTk9OQ0VfU0laRQkJMTYKKyNkZWZpbmUgTUFYX0tFWV9TSVpFCQk2NAor CitzdGF0aWMgY29uc3Qgc3RydWN0IGZzY3J5cHRfY2lwaGVyIHsKKwljb25zdCBjaGFyICpuYW1l OworCXZvaWQgKCplbmNyeXB0KShjb25zdCB1OCAqa2V5LCBjb25zdCB1OCAqaXYsIGNvbnN0IHU4 ICpzcmMsCisJCQl1OCAqZHN0LCBzaXplX3QgbmJ5dGVzKTsKKwl2b2lkICgqZGVjcnlwdCkoY29u c3QgdTggKmtleSwgY29uc3QgdTggKml2LCBjb25zdCB1OCAqc3JjLAorCQkJdTggKmRzdCwgc2l6 ZV90IG5ieXRlcyk7CisJaW50IGtleXNpemU7CisJaW50IG1pbl9pbnB1dF9zaXplOworfSBmc2Ny eXB0X2NpcGhlcnNbXSA9IHsKKwl7CisJCS5uYW1lID0gIkFFUy0yNTYtWFRTIiwKKwkJLmVuY3J5 cHQgPSBhZXNfMjU2X3h0c19lbmNyeXB0LAorCQkuZGVjcnlwdCA9IGFlc18yNTZfeHRzX2RlY3J5 cHQsCisJCS5rZXlzaXplID0gMiAqIEFFU18yNTZfS0VZX1NJWkUsCisJfSwgeworCQkubmFtZSA9 ICJBRVMtMjU2LUNUUy1DQkMiLAorCQkuZW5jcnlwdCA9IGFlc18yNTZfY3RzX2NiY19lbmNyeXB0 LAorCQkuZGVjcnlwdCA9IGFlc18yNTZfY3RzX2NiY19kZWNyeXB0LAorCQkua2V5c2l6ZSA9IEFF U18yNTZfS0VZX1NJWkUsCisJCS5taW5faW5wdXRfc2l6ZSA9IEFFU19CTE9DS19TSVpFLAorCX0s IHsKKwkJLm5hbWUgPSAiQUVTLTEyOC1DQkMtRVNTSVYiLAorCQkuZW5jcnlwdCA9IGFlc18xMjhf Y2JjX2Vzc2l2X2VuY3J5cHQsCisJCS5kZWNyeXB0ID0gYWVzXzEyOF9jYmNfZXNzaXZfZGVjcnlw dCwKKwkJLmtleXNpemUgPSBBRVNfMTI4X0tFWV9TSVpFLAorCX0sIHsKKwkJLm5hbWUgPSAiQUVT LTEyOC1DVFMtQ0JDIiwKKwkJLmVuY3J5cHQgPSBhZXNfMTI4X2N0c19jYmNfZW5jcnlwdCwKKwkJ LmRlY3J5cHQgPSBhZXNfMTI4X2N0c19jYmNfZGVjcnlwdCwKKwkJLmtleXNpemUgPSBBRVNfMTI4 X0tFWV9TSVpFLAorCQkubWluX2lucHV0X3NpemUgPSBBRVNfQkxPQ0tfU0laRSwKKwl9LCB7CisJ CS5uYW1lID0gIkFkaWFudHVtIiwKKwkJLmVuY3J5cHQgPSBhZGlhbnR1bV9lbmNyeXB0LAorCQku ZGVjcnlwdCA9IGFkaWFudHVtX2RlY3J5cHQsCisJCS5rZXlzaXplID0gQURJQU5UVU1fS0VZX1NJ WkUsCisJCS5taW5faW5wdXRfc2l6ZSA9IEFFU19CTE9DS19TSVpFLAorCX0KK307CisKK3N0YXRp YyBjb25zdCBzdHJ1Y3QgZnNjcnlwdF9jaXBoZXIgKmZpbmRfZnNjcnlwdF9jaXBoZXIoY29uc3Qg Y2hhciAqbmFtZSkKK3sKKwlzaXplX3QgaTsKKworCWZvciAoaSA9IDA7IGkgPCBBUlJBWV9TSVpF KGZzY3J5cHRfY2lwaGVycyk7IGkrKykgeworCQlpZiAoc3RyY21wKGZzY3J5cHRfY2lwaGVyc1tp XS5uYW1lLCBuYW1lKSA9PSAwKQorCQkJcmV0dXJuICZmc2NyeXB0X2NpcGhlcnNbaV07CisJfQor CXJldHVybiBOVUxMOworfQorCitzdHJ1Y3QgZnNjcnlwdF9pdiB7CisJdW5pb24geworCQlfX2xl NjQgYmxvY2tfbnVtOworCQl1OCBieXRlc1szMl07CisJfTsKK307CisKK3N0YXRpYyB2b2lkIGNy eXB0X2xvb3AoY29uc3Qgc3RydWN0IGZzY3J5cHRfY2lwaGVyICpjaXBoZXIsIGNvbnN0IHU4ICpr ZXksCisJCSAgICAgICBzdHJ1Y3QgZnNjcnlwdF9pdiAqaXYsIGJvb2wgZGVjcnlwdGluZywKKwkJ ICAgICAgIHNpemVfdCBibG9ja19zaXplLCBzaXplX3QgcGFkZGluZykKK3sKKwl1OCAqYnVmID0g eG1hbGxvYyhibG9ja19zaXplKTsKKwlzaXplX3QgcmVzOworCisJd2hpbGUgKChyZXMgPSB4cmVh ZChTVERJTl9GSUxFTk8sIGJ1ZiwgYmxvY2tfc2l6ZSkpID4gMCkgeworCQlzaXplX3QgY3J5cHRf bGVuID0gYmxvY2tfc2l6ZTsKKworCQlpZiAocGFkZGluZyA+IDApIHsKKwkJCWNyeXB0X2xlbiA9 IE1BWChyZXMsIGNpcGhlci0+bWluX2lucHV0X3NpemUpOworCQkJY3J5cHRfbGVuID0gUk9VTkRf VVAoY3J5cHRfbGVuLCBwYWRkaW5nKTsKKwkJCWNyeXB0X2xlbiA9IE1JTihjcnlwdF9sZW4sIGJs b2NrX3NpemUpOworCQl9CisJCUFTU0VSVChjcnlwdF9sZW4gPj0gcmVzKTsKKwkJbWVtc2V0KCZi dWZbcmVzXSwgMCwgY3J5cHRfbGVuIC0gcmVzKTsKKworCQlpZiAoZGVjcnlwdGluZykKKwkJCWNp cGhlci0+ZGVjcnlwdChrZXksIGl2LT5ieXRlcywgYnVmLCBidWYsIGNyeXB0X2xlbik7CisJCWVs c2UKKwkJCWNpcGhlci0+ZW5jcnlwdChrZXksIGl2LT5ieXRlcywgYnVmLCBidWYsIGNyeXB0X2xl bik7CisKKwkJZnVsbF93cml0ZShTVERPVVRfRklMRU5PLCBidWYsIGNyeXB0X2xlbik7CisKKwkJ aXYtPmJsb2NrX251bSA9IGNwdV90b19sZTY0KGxlNjRfdG9fY3B1KGl2LT5ibG9ja19udW0pICsg MSk7CisJfQorCWZyZWUoYnVmKTsKK30KKworLyogVGhlIHN1cHBvcnRlZCBrZXkgZGVyaXZhdGlv biBmdW5jdGlvbnMgKi8KK2VudW0ga2RmX2FsZ29yaXRobSB7CisJS0RGX05PTkUsCisJS0RGX0FF U18xMjhfRUNCLAorfTsKKworc3RhdGljIGVudW0ga2RmX2FsZ29yaXRobSBwYXJzZV9rZGZfYWxn b3JpdGhtKGNvbnN0IGNoYXIgKmFyZykKK3sKKwlpZiAoc3RyY21wKGFyZywgIm5vbmUiKSA9PSAw KQorCQlyZXR1cm4gS0RGX05PTkU7CisJaWYgKHN0cmNtcChhcmcsICJBRVMtMTI4LUVDQiIpID09 IDApCisJCXJldHVybiBLREZfQUVTXzEyOF9FQ0I7CisJZGllKCJVbmtub3duIEtERjogJXMiLCBh cmcpOworfQorCisvKgorICogR2V0IHRoZSBrZXkgYW5kIHN0YXJ0aW5nIElWIHdpdGggd2hpY2gg dGhlIGVuY3J5cHRpb24gd2lsbCBhY3R1YWxseSBiZSBkb25lLgorICogSWYgYSBLREYgd2FzIHNw ZWNpZmllZCwgYSBzdWJrZXkgaXMgZGVyaXZlZCBmcm9tIHRoZSBtYXN0ZXIga2V5IGFuZCBmaWxl CisgKiBub25jZS4gIE90aGVyd2lzZSwgdGhlIG1hc3RlciBrZXkgaXMgdXNlZCBkaXJlY3RseS4K KyAqLworc3RhdGljIHZvaWQgZ2V0X2tleV9hbmRfaXYoY29uc3QgdTggKm1hc3Rlcl9rZXksIHNp emVfdCBtYXN0ZXJfa2V5X3NpemUsCisJCQkgICBlbnVtIGtkZl9hbGdvcml0aG0ga2RmLAorCQkJ ICAgY29uc3QgdTggbm9uY2VbRklMRV9OT05DRV9TSVpFXSwKKwkJCSAgIHU4ICpyZWFsX2tleSwg c2l6ZV90IHJlYWxfa2V5X3NpemUsCisJCQkgICBzdHJ1Y3QgZnNjcnlwdF9pdiAqaXYpCit7CisJ c3RydWN0IGFlc19rZXkgYWVzX2tleTsKKwlzaXplX3QgaTsKKworCUFTU0VSVChyZWFsX2tleV9z aXplIDw9IG1hc3Rlcl9rZXlfc2l6ZSk7CisKKwltZW1zZXQoaXYsIDAsIHNpemVvZigqaXYpKTsK KworCXN3aXRjaCAoa2RmKSB7CisJY2FzZSBLREZfTk9ORToKKwkJbWVtY3B5KHJlYWxfa2V5LCBt YXN0ZXJfa2V5LCByZWFsX2tleV9zaXplKTsKKwkJaWYgKG5vbmNlICE9IE5VTEwpCisJCQltZW1j cHkoJml2LT5ieXRlc1s4XSwgbm9uY2UsIEZJTEVfTk9OQ0VfU0laRSk7CisJCWJyZWFrOworCWNh c2UgS0RGX0FFU18xMjhfRUNCOgorCQlpZiAobm9uY2UgPT0gTlVMTCkKKwkJCWRpZSgiLS1maWxl LW5vbmNlIGlzIHJlcXVpcmVkIHdpdGggLS1rZGY9QUVTLTEyOC1FQ0IiKTsKKwkJU1RBVElDX0FT U0VSVChGSUxFX05PTkNFX1NJWkUgPT0gQUVTXzEyOF9LRVlfU0laRSk7CisJCUFTU0VSVChyZWFs X2tleV9zaXplICUgQUVTX0JMT0NLX1NJWkUgPT0gMCk7CisJCWFlc19zZXRrZXkoJmFlc19rZXks IG5vbmNlLCBBRVNfMTI4X0tFWV9TSVpFKTsKKwkJZm9yIChpID0gMDsgaSA8IHJlYWxfa2V5X3Np emU7IGkgKz0gQUVTX0JMT0NLX1NJWkUpCisJCQlhZXNfZW5jcnlwdCgmYWVzX2tleSwgJm1hc3Rl cl9rZXlbaV0sICZyZWFsX2tleVtpXSk7CisJCWJyZWFrOworCWRlZmF1bHQ6CisJCUFTU0VSVCgw KTsKKwl9Cit9CisKK2VudW0geworCU9QVF9CTE9DS19TSVpFLAorCU9QVF9ERUNSWVBULAorCU9Q VF9GSUxFX05PTkNFLAorCU9QVF9IRUxQLAorCU9QVF9LREYsCisJT1BUX1BBRERJTkcsCit9Owor CitzdGF0aWMgY29uc3Qgc3RydWN0IG9wdGlvbiBsb25nb3B0c1tdID0geworCXsgImJsb2NrLXNp emUiLCAgICAgIHJlcXVpcmVkX2FyZ3VtZW50LCBOVUxMLCBPUFRfQkxPQ0tfU0laRSB9LAorCXsg ImRlY3J5cHQiLCAgICAgICAgIG5vX2FyZ3VtZW50LCAgICAgICBOVUxMLCBPUFRfREVDUllQVCB9 LAorCXsgImZpbGUtbm9uY2UiLCAgICAgIHJlcXVpcmVkX2FyZ3VtZW50LCBOVUxMLCBPUFRfRklM RV9OT05DRSB9LAorCXsgImhlbHAiLCAgICAgICAgICAgIG5vX2FyZ3VtZW50LCAgICAgICBOVUxM LCBPUFRfSEVMUCB9LAorCXsgImtkZiIsICAgICAgICAgICAgIHJlcXVpcmVkX2FyZ3VtZW50LCBO VUxMLCBPUFRfS0RGIH0sCisJeyAicGFkZGluZyIsICAgICAgICAgcmVxdWlyZWRfYXJndW1lbnQs IE5VTEwsIE9QVF9QQURESU5HIH0sCisJeyBOVUxMLCAwLCBOVUxMLCAwIH0sCit9OworCitpbnQg bWFpbihpbnQgYXJnYywgY2hhciAqYXJndltdKQoreworCXNpemVfdCBibG9ja19zaXplID0gNDA5 NjsKKwlib29sIGRlY3J5cHRpbmcgPSBmYWxzZTsKKwl1OCBfZmlsZV9ub25jZVtGSUxFX05PTkNF X1NJWkVdOworCXU4ICpmaWxlX25vbmNlID0gTlVMTDsKKwllbnVtIGtkZl9hbGdvcml0aG0ga2Rm ID0gS0RGX05PTkU7CisJc2l6ZV90IHBhZGRpbmcgPSAwOworCWNvbnN0IHN0cnVjdCBmc2NyeXB0 X2NpcGhlciAqY2lwaGVyOworCXU4IG1hc3Rlcl9rZXlbTUFYX0tFWV9TSVpFXTsKKwlpbnQgbWFz dGVyX2tleV9zaXplOworCXU4IHJlYWxfa2V5W01BWF9LRVlfU0laRV07CisJc3RydWN0IGZzY3J5 cHRfaXYgaXY7CisJY2hhciAqdG1wOworCWludCBjOworCisJYWVzX2luaXQoKTsKKworI2lmZGVm IEVOQUJMRV9BTEdfVEVTVFMKKwl0ZXN0X2FlcygpOworCXRlc3Rfc2hhMigpOworCXRlc3RfYWVz XzI1Nl94dHMoKTsKKwl0ZXN0X2Flc18yNTZfY3RzX2NiYygpOworCXRlc3RfYWRpYW50dW0oKTsK KyNlbmRpZgorCisJd2hpbGUgKChjID0gZ2V0b3B0X2xvbmcoYXJnYywgYXJndiwgIiIsIGxvbmdv cHRzLCBOVUxMKSkgIT0gLTEpIHsKKwkJc3dpdGNoIChjKSB7CisJCWNhc2UgT1BUX0JMT0NLX1NJ WkU6CisJCQlibG9ja19zaXplID0gc3RydG91bChvcHRhcmcsICZ0bXAsIDEwKTsKKwkJCWlmIChi bG9ja19zaXplIDw9IDAgfHwgKnRtcCkKKwkJCQlkaWUoIkludmFsaWQgYmxvY2sgc2l6ZTogJXMi LCBvcHRhcmcpOworCQkJYnJlYWs7CisJCWNhc2UgT1BUX0RFQ1JZUFQ6CisJCQlkZWNyeXB0aW5n ID0gdHJ1ZTsKKwkJCWJyZWFrOworCQljYXNlIE9QVF9GSUxFX05PTkNFOgorCQkJaWYgKGhleDJi aW4ob3B0YXJnLCBfZmlsZV9ub25jZSwgRklMRV9OT05DRV9TSVpFKSAhPQorCQkJICAgIEZJTEVf Tk9OQ0VfU0laRSkKKwkJCQlkaWUoIkludmFsaWQgZmlsZSBub25jZTogJXMiLCBvcHRhcmcpOwor CQkJZmlsZV9ub25jZSA9IF9maWxlX25vbmNlOworCQkJYnJlYWs7CisJCWNhc2UgT1BUX0hFTFA6 CisJCQl1c2FnZShzdGRvdXQpOworCQkJcmV0dXJuIDA7CisJCWNhc2UgT1BUX0tERjoKKwkJCWtk ZiA9IHBhcnNlX2tkZl9hbGdvcml0aG0ob3B0YXJnKTsKKwkJCWJyZWFrOworCQljYXNlIE9QVF9Q QURESU5HOgorCQkJcGFkZGluZyA9IHN0cnRvdWwob3B0YXJnLCAmdG1wLCAxMCk7CisJCQlpZiAo cGFkZGluZyA8PSAwIHx8ICp0bXAgfHwgIWlzX3Bvd2VyX29mXzIocGFkZGluZykgfHwKKwkJCSAg ICBwYWRkaW5nID4gSU5UX01BWCkKKwkJCQlkaWUoIkludmFsaWQgcGFkZGluZyBhbW91bnQ6ICVz Iiwgb3B0YXJnKTsKKwkJCWJyZWFrOworCQlkZWZhdWx0OgorCQkJdXNhZ2Uoc3RkZXJyKTsKKwkJ CXJldHVybiAyOworCQl9CisJfQorCWFyZ2MgLT0gb3B0aW5kOworCWFyZ3YgKz0gb3B0aW5kOwor CisJaWYgKGFyZ2MgIT0gMikgeworCQl1c2FnZShzdGRlcnIpOworCQlyZXR1cm4gMjsKKwl9CisK KwljaXBoZXIgPSBmaW5kX2ZzY3J5cHRfY2lwaGVyKGFyZ3ZbMF0pOworCWlmIChjaXBoZXIgPT0g TlVMTCkKKwkJZGllKCJVbmtub3duIGNpcGhlcjogJXMiLCBhcmd2WzBdKTsKKworCWlmIChibG9j a19zaXplIDwgY2lwaGVyLT5taW5faW5wdXRfc2l6ZSkKKwkJZGllKCJCbG9jayBzaXplIG9mICV6 dSBieXRlcyBpcyB0b28gc21hbGwgZm9yIGNpcGhlciAlcyIsCisJCSAgICBibG9ja19zaXplLCBj aXBoZXItPm5hbWUpOworCisJbWFzdGVyX2tleV9zaXplID0gaGV4MmJpbihhcmd2WzFdLCBtYXN0 ZXJfa2V5LCBNQVhfS0VZX1NJWkUpOworCWlmIChtYXN0ZXJfa2V5X3NpemUgPCAwKQorCQlkaWUo IkludmFsaWQgbWFzdGVyX2tleTogJXMiLCBhcmd2WzFdKTsKKwlpZiAobWFzdGVyX2tleV9zaXpl IDwgY2lwaGVyLT5rZXlzaXplKQorCQlkaWUoIk1hc3RlciBrZXkgaXMgdG9vIHNob3J0IGZvciBj aXBoZXIgJXMiLCBjaXBoZXItPm5hbWUpOworCisJZ2V0X2tleV9hbmRfaXYobWFzdGVyX2tleSwg bWFzdGVyX2tleV9zaXplLCBrZGYsIGZpbGVfbm9uY2UsCisJCSAgICAgICByZWFsX2tleSwgY2lw aGVyLT5rZXlzaXplLCAmaXYpOworCisJY3J5cHRfbG9vcChjaXBoZXIsIHJlYWxfa2V5LCAmaXYs IGRlY3J5cHRpbmcsIGJsb2NrX3NpemUsIHBhZGRpbmcpOworCXJldHVybiAwOworfQotLSAKMi4y Mi4wLnJjMS4yNTcuZzMxMjBhMTgyNDQtZ29vZwoKCgpfX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fXwpMaW51eC1mMmZzLWRldmVsIG1haWxpbmcgbGlzdApMaW51 eC1mMmZzLWRldmVsQGxpc3RzLnNvdXJjZWZvcmdlLm5ldApodHRwczovL2xpc3RzLnNvdXJjZWZv cmdlLm5ldC9saXN0cy9saXN0aW5mby9saW51eC1mMmZzLWRldmVsCg==