From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail.kernel.org ([198.145.29.99]:45062 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726378AbfDZUpn (ORCPT ); Fri, 26 Apr 2019 16:45:43 -0400 From: Eric Biggers Subject: [RFC PATCH 2/7] fscrypt-crypt-util: add utility for reproducing fscrypt encrypted data Date: Fri, 26 Apr 2019 13:41:48 -0700 Message-Id: <20190426204153.101861-3-ebiggers@kernel.org> In-Reply-To: <20190426204153.101861-1-ebiggers@kernel.org> References: <20190426204153.101861-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 | 1645 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 1648 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..715e2bf2 --- /dev/null +++ b/src/fscrypt-crypt-util.c @@ -0,0 +1,1645 @@ +// 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" +" --kdf=3DKDF Key derivation function to use: AES-128= -ECB\n" +" or none. Default: none\n" +" --help Show this help\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 u64 ror64(u64 v, int n) +{ + return (v >> n) | (v << (64 - 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 actual_ctext[sizeof(ptext)]; + u8 expected_ctext[sizeof(ptext)]; + u8 decrypted[sizeof(ptext)]; + const size_t datalen =3D ROUND_DOWN(rand() % (1 + sizeof(ptext)), + AES_BLOCK_SIZE); + int outl; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + rand_bytes(ptext, datalen); + + aes_256_xts_encrypt(key, iv, ptext, actual_ctext, datalen); + ASSERT(EVP_EncryptInit_ex(ctx, EVP_aes_256_xts(), + NULL, key, iv) > 0); + ASSERT(EVP_EncryptUpdate(ctx, expected_ctext, &outl, + ptext, datalen) > 0); + ASSERT(outl =3D=3D datalen); + ASSERT(memcmp(actual_ctext, expected_ctext, datalen) =3D=3D 0); + + aes_256_xts_decrypt(key, iv, actual_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 actual_ctext[sizeof(ptext)]; + u8 expected_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, actual_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, + expected_ctext, + datalen, &k, iv_copy, + aes_block128_f) + =3D=3D datalen); + ASSERT(memcmp(actual_ctext, expected_ctext, + datalen) =3D=3D 0); + } + aes_256_cts_cbc_decrypt(key, iv, actual_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[ADIANTUM_IV_SIZE + POLY1305_BLOCK_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 actual_ctext[sizeof(ptext)]; + u8 expected_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, actual_ctext, datalen); + af_alg_crypt(algfd, ALG_OP_ENCRYPT, key, sizeof(key), + iv, sizeof(iv), ptext, expected_ctext, datalen); + ASSERT(memcmp(actual_ctext, expected_ctext, datalen) =3D=3D 0); + + adiantum_decrypt(key, iv, actual_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, + .min_input_size =3D AES_BLOCK_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, + .min_input_size =3D AES_BLOCK_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 MIN(ROUND_UP(res, padding), crypt_len); + + crypt_len =3D MAX(crypt_len, cipher->min_input_size); + + 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) +{ + bool nonce_in_iv =3D false; + 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); + nonce_in_iv =3D true; + 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); + } + + if (nonce_in_iv && nonce !=3D NULL) + memcpy(&iv->bytes[8], nonce, FILE_NONCE_SIZE); +} + +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.21.0.593.g511ec345e18-goog From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eric Biggers Subject: [RFC PATCH 2/7] fscrypt-crypt-util: add utility for reproducing fscrypt encrypted data Date: Fri, 26 Apr 2019 13:41:48 -0700 Message-ID: <20190426204153.101861-3-ebiggers@kernel.org> References: <20190426204153.101861-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-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1hK7jE-000420-6s for linux-f2fs-devel@lists.sourceforge.net; Fri, 26 Apr 2019 20:45:52 +0000 Received: from mail.kernel.org ([198.145.29.99]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1hK7jA-00Fdwz-OB for linux-f2fs-devel@lists.sourceforge.net; Fri, 26 Apr 2019 20:45:52 +0000 In-Reply-To: <20190426204153.101861-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 Y3J5cHQtdXRpbC5jIHwgMTY0NSArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KwogMyBmaWxlcyBjaGFuZ2VkLCAxNjQ4IGluc2VydGlvbnMoKyksIDEgZGVsZXRpb24oLSkKIGNy ZWF0ZSBtb2RlIDEwMDY0NCBzcmMvZnNjcnlwdC1jcnlwdC11dGlsLmMKCmRpZmYgLS1naXQgYS8u Z2l0aWdub3JlIGIvLmdpdGlnbm9yZQppbmRleCBjMTNmYjcxMy4uMTEyMzJiZTcgMTAwNjQ0Ci0t LSBhLy5naXRpZ25vcmUKKysrIGIvLmdpdGlnbm9yZQpAQCAtNzMsNiArNzMsNyBAQAogL3NyYy9m aWxsCiAvc3JjL2ZpbGwyCiAvc3JjL2ZzX3Blcm1zCisvc3JjL2ZzY3J5cHQtY3J5cHQtdXRpbAog L3NyYy9mc3N1bQogL3NyYy9mc3Rlc3QKIC9zcmMvZnN5bmMtZXJyCmRpZmYgLS1naXQgYS9zcmMv TWFrZWZpbGUgYi9zcmMvTWFrZWZpbGUKaW5kZXggNDA1N2Q3YjMuLjlkM2QyNTI5IDEwMDY0NAot LS0gYS9zcmMvTWFrZWZpbGUKKysrIGIvc3JjL01ha2VmaWxlCkBAIC0yNyw3ICsyNyw4IEBAIExJ TlVYX1RBUkdFVFMgPSB4ZnNjdGwgYnN0YXQgdF9tdGFiIGdldGRldmljZXNpemUgcHJlYWxsb19y d19wYXR0ZXJuX3JlYWRlciBcCiAJcmVuYW1lYXQyIHRfZ2V0Y3dkIGU0Y29tcGFjdCB0ZXN0LW5l eHRxdW90YSBwdW5jaC1hbHRlcm5hdGluZyBcCiAJYXR0ci1saXN0LWJ5LWhhbmRsZS1jdXJzb3It dGVzdCBsaXN0eGF0dHIgZGlvLWludGVybGVhdmVkIHRfZGlyX3R5cGUgXAogCWRpby1pbnZhbGlk YXRlLWNhY2hlIHN0YXRfdGVzdCB0X2VuY3J5cHRlZF9kX3JldmFsaWRhdGUgXAotCWF0dHJfcmVw bGFjZV90ZXN0IHN3YXBvbiBta3N3YXAgdF9hdHRyX2NvcnJ1cHRpb24gdF9vcGVuX3RtcGZpbGVz CisJYXR0cl9yZXBsYWNlX3Rlc3Qgc3dhcG9uIG1rc3dhcCB0X2F0dHJfY29ycnVwdGlvbiB0X29w ZW5fdG1wZmlsZXMgXAorCWZzY3J5cHQtY3J5cHQtdXRpbAogCiBTVUJESVJTID0gbG9nLXdyaXRl cyBwZXJmCiAKZGlmZiAtLWdpdCBhL3NyYy9mc2NyeXB0LWNyeXB0LXV0aWwuYyBiL3NyYy9mc2Ny eXB0LWNyeXB0LXV0aWwuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMC4uNzE1 ZTJiZjIKLS0tIC9kZXYvbnVsbAorKysgYi9zcmMvZnNjcnlwdC1jcnlwdC11dGlsLmMKQEAgLTAs MCArMSwxNjQ1IEBACisvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMCsKKy8qCisg 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 ZSBhcyBhIDMyLWNoYXJhY3RlciBoZXggc3RyaW5nXG4iCisiICAtLWtkZj1LREYgICAgICAgICAg ICAgICAgICAgS2V5IGRlcml2YXRpb24gZnVuY3Rpb24gdG8gdXNlOiBBRVMtMTI4LUVDQlxuIgor IiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3Igbm9uZS4gIERlZmF1bHQ6IG5vbmVc biIKKyIgIC0taGVscCAgICAgICAgICAgICAgICAgICAgICBTaG93IHRoaXMgaGVscFxuIgorIiAg 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 Pj4gbikgfCAodiA8PCAoMzIgLSBuKSk7Cit9CisKK3N0YXRpYyBpbmxpbmUgdTY0IHJvcjY0KHU2 NCB2LCBpbnQgbikKK3sKKwlyZXR1cm4gKHYgPj4gbikgfCAodiA8PCAoNjQgLSBuKSk7Cit9CisK K3N0YXRpYyBpbmxpbmUgdm9pZCB4b3IodTggKnJlcywgY29uc3QgdTggKmEsIGNvbnN0IHU4ICpi LCBzaXplX3QgY291bnQpCit7CisJd2hpbGUgKGNvdW50LS0pCisJCSpyZXMrKyA9ICphKysgXiAq YisrOworfQorCitzdGF0aWMgdm9pZCBfX2F0dHJpYnV0ZV9fKChub3JldHVybiwgZm9ybWF0KHBy aW50ZiwgMiwgMykpKQorZG9fZGllKGludCBlcnIsIGNvbnN0IGNoYXIgKmZvcm1hdCwgLi4uKQor eworCXZhX2xpc3QgdmE7CisKKwl2YV9zdGFydCh2YSwgZm9ybWF0KTsKKwlmcHV0cygiWyIgUFJP R1JBTV9OQU1FICJdIEVSUk9SOiAiLCBzdGRlcnIpOworCXZmcHJpbnRmKHN0ZGVyciwgZm9ybWF0 LCB2YSk7CisJaWYgKGVycikKKwkJZnByaW50ZihzdGRlcnIsICI6ICVzIiwgc3RyZXJyb3IoZXJy bm8pKTsKKwlwdXRjKCdcbicsIHN0ZGVycik7CisJdmFfZW5kKHZhKTsKKwlleGl0KDEpOworfQor CisjZGVmaW5lIGRpZShmb3JtYXQsIC4uLikJZG9fZGllKDAsICAgICAoZm9ybWF0KSwgIyNfX1ZB X0FSR1NfXykKKyNkZWZpbmUgZGllX2Vycm5vKGZvcm1hdCwgLi4uKQlkb19kaWUoZXJybm8sIChm b3JtYXQpLCAjI19fVkFfQVJHU19fKQorCitzdGF0aWMgX19hdHRyaWJ1dGVfXygobm9yZXR1cm4p KSB2b2lkCithc3NlcnRpb25fZmFpbGVkKGNvbnN0IGNoYXIgKmV4cHIsIGNvbnN0IGNoYXIgKmZp bGUsIGludCBsaW5lKQoreworCWRpZSgiQXNzZXJ0aW9uIGZhaWxlZDogJXMgYXQgJXM6JWQiLCBl eHByLCBmaWxlLCBsaW5lKTsKK30KKworI2RlZmluZSBBU1NFUlQoZSkgKHsgaWYgKCEoZSkpIGFz c2VydGlvbl9mYWlsZWQoI2UsIF9fRklMRV9fLCBfX0xJTkVfXyk7IH0pCisKK3N0YXRpYyB2b2lk ICp4bWFsbG9jKHNpemVfdCBzaXplKQoreworCXZvaWQgKnAgPSBtYWxsb2Moc2l6ZSk7CisKKwlB U1NFUlQocCAhPSBOVUxMKTsKKwlyZXR1cm4gcDsKK30KKworc3RhdGljIGludCBoZXhjaGFyMmJp bihjaGFyIGMpCit7CisJaWYgKGMgPj0gJ2EnICYmIGMgPD0gJ2YnKQorCQlyZXR1cm4gMTAgKyBj IC0gJ2EnOworCWlmIChjID49ICdBJyAmJiBjIDw9ICdGJykKKwkJcmV0dXJuIDEwICsgYyAtICdB JzsKKwlpZiAoYyA+PSAnMCcgJiYgYyA8PSAnOScpCisJCXJldHVybiBjIC0gJzAnOworCXJldHVy biAtMTsKK30KKworc3RhdGljIGludCBoZXgyYmluKGNvbnN0IGNoYXIgKmhleCwgdTggKmJpbiwg aW50IG1heF9iaW5fc2l6ZSkKK3sKKwlzaXplX3QgbGVuID0gc3RybGVuKGhleCk7CisJc2l6ZV90 IGk7CisKKwlpZiAobGVuICYgMSkKKwkJcmV0dXJuIC0xOworCWxlbiAvPSAyOworCWlmIChsZW4g PiBtYXhfYmluX3NpemUpCisJCXJldHVybiAtMTsKKworCWZvciAoaSA9IDA7IGkgPCBsZW47IGkr KykgeworCQlpbnQgaGlnaCA9IGhleGNoYXIyYmluKGhleFsyICogaV0pOworCQlpbnQgbG93ID0g aGV4Y2hhcjJiaW4oaGV4WzIgKiBpICsgMV0pOworCisJCWlmIChoaWdoIDwgMCB8fCBsb3cgPCAw KQorCQkJcmV0dXJuIC0xOworCQliaW5baV0gPSAoaGlnaCA8PCA0KSB8IGxvdzsKKwl9CisJcmV0 dXJuIGxlbjsKK30KKworc3RhdGljIHNpemVfdCB4cmVhZChpbnQgZmQsIHZvaWQgKmJ1Ziwgc2l6 ZV90IGNvdW50KQoreworCWNvbnN0IHNpemVfdCBvcmlnX2NvdW50ID0gY291bnQ7CisKKwl3aGls ZSAoY291bnQpIHsKKwkJc3NpemVfdCByZXMgPSByZWFkKGZkLCBidWYsIGNvdW50KTsKKworCQlp ZiAocmVzIDwgMCkKKwkJCWRpZV9lcnJubygicmVhZCBlcnJvciIpOworCQlpZiAocmVzID09IDAp CisJCQlicmVhazsKKwkJYnVmICs9IHJlczsKKwkJY291bnQgLT0gcmVzOworCX0KKwlyZXR1cm4g b3JpZ19jb3VudCAtIGNvdW50OworfQorCitzdGF0aWMgdm9pZCBmdWxsX3dyaXRlKGludCBmZCwg Y29uc3Qgdm9pZCAqYnVmLCBzaXplX3QgY291bnQpCit7CisJd2hpbGUgKGNvdW50KSB7CisJCXNz aXplX3QgcmVzID0gd3JpdGUoZmQsIGJ1ZiwgY291bnQpOworCisJCWlmIChyZXMgPCAwKQorCQkJ ZGllX2Vycm5vKCJ3cml0ZSBlcnJvciIpOworCQlidWYgKz0gcmVzOworCQljb3VudCAtPSByZXM7 CisJfQorfQorCisjaWZkZWYgRU5BQkxFX0FMR19URVNUUworc3RhdGljIHZvaWQgcmFuZF9ieXRl cyh1OCAqYnVmLCBzaXplX3QgY291bnQpCit7CisJd2hpbGUgKGNvdW50LS0pCisJCSpidWYrKyA9 IHJhbmQoKTsKK30KKyNlbmRpZgorCisvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qCisgKiAgICAgICAg ICAgICAgICAgICAgICAgICAgRmluaXRlIGZpZWxkIGFyaXRobWV0aWMgICAgICAgICAgICAgICAg ICAgICAgICAgICAqCisgKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLworCisvKiBNdWx0aXBseSBhIEdG KDJeOCkgZWxlbWVudCBieSB0aGUgcG9seW5vbWlhbCAneCcgKi8KK3N0YXRpYyBpbmxpbmUgdTgg Z2YyXzhfbXVsX3godTggYikKK3sKKwlyZXR1cm4gKGIgPDwgMSkgXiAoKGIgJiAweDgwKSA/IDB4 MUIgOiAwKTsKK30KKworLyogTXVsdGlwbHkgZm91ciBwYWNrZWQgR0YoMl44KSBlbGVtZW50cyBi eSB0aGUgcG9seW5vbWlhbCAneCcgKi8KK3N0YXRpYyBpbmxpbmUgdTMyIGdmMl84X211bF94XzR3 YXkodTMyIHcpCit7CisJcmV0dXJuICgodyAmIDB4N0Y3RjdGN0YpIDw8IDEpIF4gKCgodyAmIDB4 ODA4MDgwODApID4+IDcpICogMHgxQik7Cit9CisKKy8qIEVsZW1lbnQgb2YgR0YoMl4xMjgpICov Cit0eXBlZGVmIHN0cnVjdCB7CisJX19sZTY0IGxvOworCV9fbGU2NCBoaTsKK30gYmxlMTI4Owor CisvKiBNdWx0aXBseSBhIEdGKDJeMTI4KSBlbGVtZW50IGJ5IHRoZSBwb2x5bm9taWFsICd4JyAq Lworc3RhdGljIGlubGluZSB2b2lkIGdmMl8xMjhfbXVsX3goYmxlMTI4ICp0KQoreworCXU2NCBs byA9IGxlNjRfdG9fY3B1KHQtPmxvKTsKKwl1NjQgaGkgPSBsZTY0X3RvX2NwdSh0LT5oaSk7CisK Kwl0LT5oaSA9IGNwdV90b19sZTY0KChoaSA8PCAxKSB8IChsbyA+PiA2MykpOworCXQtPmxvID0g Y3B1X3RvX2xlNjQoKGxvIDw8IDEpIF4gKChoaSAmICgxVUxMIDw8IDYzKSkgPyAweDg3IDogMCkp OworfQorCisvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qCisgKiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgR3JvdXAgYXJpdGhtZXRpYyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqCisg Ki0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0qLworCisvKiBFbGVtZW50IG9mIFovKDJeezEyOH1aKSAgKGEu ay5hLiB0aGUgaW50ZWdlcnMgbW9kdWxvIDJeMTI4KSAqLwordHlwZWRlZiBzdHJ1Y3QgeworCV9f bGU2NCBsbzsKKwlfX2xlNjQgaGk7Cit9IGxlMTI4OworCitzdGF0aWMgaW5saW5lIHZvaWQgbGUx MjhfYWRkKGxlMTI4ICpyZXMsIGNvbnN0IGxlMTI4ICphLCBjb25zdCBsZTEyOCAqYikKK3sKKwl1 NjQgYV9sbyA9IGxlNjRfdG9fY3B1KGEtPmxvKTsKKwl1NjQgYl9sbyA9IGxlNjRfdG9fY3B1KGIt PmxvKTsKKworCXJlcy0+bG8gPSBjcHVfdG9fbGU2NChhX2xvICsgYl9sbyk7CisJcmVzLT5oaSA9 IGNwdV90b19sZTY0KGxlNjRfdG9fY3B1KGEtPmhpKSArIGxlNjRfdG9fY3B1KGItPmhpKSArCisJ CQkgICAgICAoYV9sbyArIGJfbG8gPCBhX2xvKSk7Cit9CisKK3N0YXRpYyBpbmxpbmUgdm9pZCBs ZTEyOF9zdWIobGUxMjggKnJlcywgY29uc3QgbGUxMjggKmEsIGNvbnN0IGxlMTI4ICpiKQorewor CXU2NCBhX2xvID0gbGU2NF90b19jcHUoYS0+bG8pOworCXU2NCBiX2xvID0gbGU2NF90b19jcHUo Yi0+bG8pOworCisJcmVzLT5sbyA9IGNwdV90b19sZTY0KGFfbG8gLSBiX2xvKTsKKwlyZXMtPmhp ID0gY3B1X3RvX2xlNjQobGU2NF90b19jcHUoYS0+aGkpIC0gbGU2NF90b19jcHUoYi0+aGkpIC0K KwkJCSAgICAgIChhX2xvIC0gYl9sbyA+IGFfbG8pKTsKK30KKworLyotLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tKgorICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBRVMgYmxvY2sgY2lwaGVyICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgKgorICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KKwor LyoKKyAqIFJlZmVyZW5jZTogIkZJUFMgMTk3LCBBZHZhbmNlZCBFbmNyeXB0aW9uIFN0YW5kYXJk IgorICoJaHR0cHM6Ly9udmxwdWJzLm5pc3QuZ292L25pc3RwdWJzL2ZpcHMvbmlzdC5maXBzLjE5 Ny5wZGYKKyAqLworCisjZGVmaW5lIEFFU19CTE9DS19TSVpFCQkxNgorI2RlZmluZSBBRVNfMTI4 X0tFWV9TSVpFCTE2CisjZGVmaW5lIEFFU18xOTJfS0VZX1NJWkUJMjQKKyNkZWZpbmUgQUVTXzI1 Nl9LRVlfU0laRQkzMgorCitzdGF0aWMgaW5saW5lIHZvaWQgQWRkUm91bmRLZXkodTMyIHN0YXRl WzRdLCBjb25zdCB1MzIgKnJrKQoreworCWludCBpOworCisJZm9yIChpID0gMDsgaSA8IDQ7IGkr KykKKwkJc3RhdGVbaV0gXj0gcmtbaV07Cit9CisKK3N0YXRpYyBjb25zdCB1OCBhZXNfc2JveFsy NTZdID0geworCTB4NjMsIDB4N2MsIDB4NzcsIDB4N2IsIDB4ZjIsIDB4NmIsIDB4NmYsIDB4YzUs IDB4MzAsIDB4MDEsIDB4NjcsIDB4MmIsCisJMHhmZSwgMHhkNywgMHhhYiwgMHg3NiwgMHhjYSwg MHg4MiwgMHhjOSwgMHg3ZCwgMHhmYSwgMHg1OSwgMHg0NywgMHhmMCwKKwkweGFkLCAweGQ0LCAw eGEyLCAweGFmLCAweDljLCAweGE0LCAweDcyLCAweGMwLCAweGI3LCAweGZkLCAweDkzLCAweDI2 LAorCTB4MzYsIDB4M2YsIDB4ZjcsIDB4Y2MsIDB4MzQsIDB4YTUsIDB4ZTUsIDB4ZjEsIDB4NzEs IDB4ZDgsIDB4MzEsIDB4MTUsCisJMHgwNCwgMHhjNywgMHgyMywgMHhjMywgMHgxOCwgMHg5Niwg MHgwNSwgMHg5YSwgMHgwNywgMHgxMiwgMHg4MCwgMHhlMiwKKwkweGViLCAweDI3LCAweGIyLCAw eDc1LCAweDA5LCAweDgzLCAweDJjLCAweDFhLCAweDFiLCAweDZlLCAweDVhLCAweGEwLAorCTB4 NTIsIDB4M2IsIDB4ZDYsIDB4YjMsIDB4MjksIDB4ZTMsIDB4MmYsIDB4ODQsIDB4NTMsIDB4ZDEs IDB4MDAsIDB4ZWQsCisJMHgyMCwgMHhmYywgMHhiMSwgMHg1YiwgMHg2YSwgMHhjYiwgMHhiZSwg MHgzOSwgMHg0YSwgMHg0YywgMHg1OCwgMHhjZiwKKwkweGQwLCAweGVmLCAweGFhLCAweGZiLCAw eDQzLCAweDRkLCAweDMzLCAweDg1LCAweDQ1LCAweGY5LCAweDAyLCAweDdmLAorCTB4NTAsIDB4 M2MsIDB4OWYsIDB4YTgsIDB4NTEsIDB4YTMsIDB4NDAsIDB4OGYsIDB4OTIsIDB4OWQsIDB4Mzgs IDB4ZjUsCisJMHhiYywgMHhiNiwgMHhkYSwgMHgyMSwgMHgxMCwgMHhmZiwgMHhmMywgMHhkMiwg MHhjZCwgMHgwYywgMHgxMywgMHhlYywKKwkweDVmLCAweDk3LCAweDQ0LCAweDE3LCAweGM0LCAw eGE3LCAweDdlLCAweDNkLCAweDY0LCAweDVkLCAweDE5LCAweDczLAorCTB4NjAsIDB4ODEsIDB4 NGYsIDB4ZGMsIDB4MjIsIDB4MmEsIDB4OTAsIDB4ODgsIDB4NDYsIDB4ZWUsIDB4YjgsIDB4MTQs CisJMHhkZSwgMHg1ZSwgMHgwYiwgMHhkYiwgMHhlMCwgMHgzMiwgMHgzYSwgMHgwYSwgMHg0OSwg MHgwNiwgMHgyNCwgMHg1YywKKwkweGMyLCAweGQzLCAweGFjLCAweDYyLCAweDkxLCAweDk1LCAw eGU0LCAweDc5LCAweGU3LCAweGM4LCAweDM3LCAweDZkLAorCTB4OGQsIDB4ZDUsIDB4NGUsIDB4 YTksIDB4NmMsIDB4NTYsIDB4ZjQsIDB4ZWEsIDB4NjUsIDB4N2EsIDB4YWUsIDB4MDgsCisJMHhi YSwgMHg3OCwgMHgyNSwgMHgyZSwgMHgxYywgMHhhNiwgMHhiNCwgMHhjNiwgMHhlOCwgMHhkZCwg MHg3NCwgMHgxZiwKKwkweDRiLCAweGJkLCAweDhiLCAweDhhLCAweDcwLCAweDNlLCAweGI1LCAw eDY2LCAweDQ4LCAweDAzLCAweGY2LCAweDBlLAorCTB4NjEsIDB4MzUsIDB4NTcsIDB4YjksIDB4 ODYsIDB4YzEsIDB4MWQsIDB4OWUsIDB4ZTEsIDB4ZjgsIDB4OTgsIDB4MTEsCisJMHg2OSwgMHhk OSwgMHg4ZSwgMHg5NCwgMHg5YiwgMHgxZSwgMHg4NywgMHhlOSwgMHhjZSwgMHg1NSwgMHgyOCwg MHhkZiwKKwkweDhjLCAweGExLCAweDg5LCAweDBkLCAweGJmLCAweGU2LCAweDQyLCAweDY4LCAw eDQxLCAweDk5LCAweDJkLCAweDBmLAorCTB4YjAsIDB4NTQsIDB4YmIsIDB4MTYsCit9OworCitz dGF0aWMgdTggYWVzX2ludmVyc2Vfc2JveFsyNTZdOworCitzdGF0aWMgdm9pZCBhZXNfaW5pdCh2 b2lkKQoreworCWludCBpOworCisJZm9yIChpID0gMDsgaSA8IDI1NjsgaSsrKQorCQlhZXNfaW52 ZXJzZV9zYm94W2Flc19zYm94W2ldXSA9IGk7Cit9CisKK3N0YXRpYyBpbmxpbmUgdTMyIERvU3Vi V29yZCh1MzIgdywgY29uc3QgdTggc2JveFsyNTZdKQoreworCXJldHVybiAoKHUzMilzYm94Wyh1 OCkodyA+PiAyNCldIDw8IDI0KSB8CisJICAgICAgICgodTMyKXNib3hbKHU4KSh3ID4+IDE2KV0g PDwgMTYpIHwKKwkgICAgICAgKCh1MzIpc2JveFsodTgpKHcgPj4gIDgpXSA8PCAgOCkgfAorCSAg ICAgICAoKHUzMilzYm94Wyh1OCkodyA+PiAgMCldIDw8ICAwKTsKK30KKworc3RhdGljIGlubGlu ZSB1MzIgU3ViV29yZCh1MzIgdykKK3sKKwlyZXR1cm4gRG9TdWJXb3JkKHcsIGFlc19zYm94KTsK K30KKworc3RhdGljIGlubGluZSB1MzIgSW52U3ViV29yZCh1MzIgdykKK3sKKwlyZXR1cm4gRG9T dWJXb3JkKHcsIGFlc19pbnZlcnNlX3Nib3gpOworfQorCitzdGF0aWMgaW5saW5lIHZvaWQgU3Vi Qnl0ZXModTMyIHN0YXRlWzRdKQoreworCWludCBpOworCisJZm9yIChpID0gMDsgaSA8IDQ7IGkr KykKKwkJc3RhdGVbaV0gPSBTdWJXb3JkKHN0YXRlW2ldKTsKK30KKworc3RhdGljIGlubGluZSB2 b2lkIEludlN1YkJ5dGVzKHUzMiBzdGF0ZVs0XSkKK3sKKwlpbnQgaTsKKworCWZvciAoaSA9IDA7 IGkgPCA0OyBpKyspCisJCXN0YXRlW2ldID0gSW52U3ViV29yZChzdGF0ZVtpXSk7Cit9CisKK3N0 YXRpYyBpbmxpbmUgdm9pZCBEb1NoaWZ0Um93cyh1MzIgc3RhdGVbNF0sIGludCBkaXJlY3Rpb24p Cit7CisJdTMyIG5ld3N0YXRlWzRdOworCWludCBpOworCisJZm9yIChpID0gMDsgaSA8IDQ7IGkr KykKKwkJbmV3c3RhdGVbaV0gPSAoc3RhdGVbKGkgKyBkaXJlY3Rpb24qMCkgJiAzXSAmIDB4ZmYp IHwKKwkJCSAgICAgIChzdGF0ZVsoaSArIGRpcmVjdGlvbioxKSAmIDNdICYgMHhmZjAwKSB8CisJ CQkgICAgICAoc3RhdGVbKGkgKyBkaXJlY3Rpb24qMikgJiAzXSAmIDB4ZmYwMDAwKSB8CisJCQkg ICAgICAoc3RhdGVbKGkgKyBkaXJlY3Rpb24qMykgJiAzXSAmIDB4ZmYwMDAwMDApOworCW1lbWNw eShzdGF0ZSwgbmV3c3RhdGUsIDE2KTsKK30KKworc3RhdGljIGlubGluZSB2b2lkIFNoaWZ0Um93 cyh1MzIgc3RhdGVbNF0pCit7CisJRG9TaGlmdFJvd3Moc3RhdGUsIDEpOworfQorCitzdGF0aWMg aW5saW5lIHZvaWQgSW52U2hpZnRSb3dzKHUzMiBzdGF0ZVs0XSkKK3sKKwlEb1NoaWZ0Um93cyhz dGF0ZSwgLTEpOworfQorCisvKgorICogTWl4IG9uZSBjb2x1bW4gYnkgZG9pbmcgdGhlIGZvbGxv d2luZyBtYXRyaXggbXVsdGlwbGljYXRpb24gaW4gR0YoMl44KToKKyAqCisgKiAgICAgfCAyIDMg MSAxIHwgICB8IHdbMF0gfAorICogICAgIHwgMSAyIDMgMSB8ICAgfCB3WzFdIHwKKyAqICAgICB8 IDEgMSAyIDMgfCB4IHwgd1syXSB8CisgKiAgICAgfCAzIDEgMSAyIHwgICB8IHdbM10gfAorICoK KyAqIGEuay5hLiB3W2ldID0gMip3W2ldICsgMyp3WyhpKzEpJTRdICsgd1soaSsyKSU0XSArIHdb KGkrMyklNF0KKyAqLworc3RhdGljIGlubGluZSB1MzIgTWl4Q29sdW1uKHUzMiB3KQoreworCXUz MiBfMncwX3cyID0gZ2YyXzhfbXVsX3hfNHdheSh3KSBeIHJvcjMyKHcsIDE2KTsKKwl1MzIgXzN3 MV93MyA9IHJvcjMyKF8ydzBfdzIgXiB3LCA4KTsKKworCXJldHVybiBfMncwX3cyIF4gXzN3MV93 MzsKK30KKworLyoKKyAqICAgICAgICAgICAoIHwgNSAwIDQgMCB8ICAgfCB3WzBdIHwgKQorICog ICAgICAgICAgKCAgfCAwIDUgMCA0IHwgICB8IHdbMV0gfCAgKQorICogTWl4Q29sdW1uKCAgfCA0 IDAgNSAwIHwgeCB8IHdbMl0gfCAgKQorICogICAgICAgICAgICggfCAwIDQgMCA1IHwgICB8IHdb M10gfCApCisgKi8KK3N0YXRpYyBpbmxpbmUgdTMyIEludk1peENvbHVtbih1MzIgdykKK3sKKwl1 MzIgXzR3ID0gZ2YyXzhfbXVsX3hfNHdheShnZjJfOF9tdWxfeF80d2F5KHcpKTsKKworCXJldHVy biBNaXhDb2x1bW4oXzR3IF4gdyBeIHJvcjMyKF80dywgMTYpKTsKK30KKworc3RhdGljIGlubGlu ZSB2b2lkIE1peENvbHVtbnModTMyIHN0YXRlWzRdKQoreworCWludCBpOworCisJZm9yIChpID0g MDsgaSA8IDQ7IGkrKykKKwkJc3RhdGVbaV0gPSBNaXhDb2x1bW4oc3RhdGVbaV0pOworfQorCitz dGF0aWMgaW5saW5lIHZvaWQgSW52TWl4Q29sdW1ucyh1MzIgc3RhdGVbNF0pCit7CisJaW50IGk7 CisKKwlmb3IgKGkgPSAwOyBpIDwgNDsgaSsrKQorCQlzdGF0ZVtpXSA9IEludk1peENvbHVtbihz dGF0ZVtpXSk7Cit9CisKK3N0cnVjdCBhZXNfa2V5IHsKKwl1MzIgcm91bmRfa2V5c1sxNSAqIDRd OworCWludCBucm91bmRzOworfTsKKworLyogRXhwYW5kIGFuIEFFUyBrZXkgKi8KK3N0YXRpYyB2 b2lkIGFlc19zZXRrZXkoc3RydWN0IGFlc19rZXkgKmssIGNvbnN0IHU4ICprZXksIGludCBrZXlz aXplKQoreworCWNvbnN0IGludCBOID0ga2V5c2l6ZSAvIDQ7CisJdTMyICogY29uc3QgcmsgPSBr LT5yb3VuZF9rZXlzOworCXU4IHJjb24gPSAxOworCWludCBpOworCisJQVNTRVJUKGtleXNpemUg PT0gMTYgfHwga2V5c2l6ZSA9PSAyNCB8fCBrZXlzaXplID09IDMyKTsKKwlrLT5ucm91bmRzID0g NiArIE47CisJZm9yIChpID0gMDsgaSA8IDQgKiAoay0+bnJvdW5kcyArIDEpOyBpKyspIHsKKwkJ aWYgKGkgPCBOKSB7CisJCQlya1tpXSA9IGdldF91bmFsaWduZWRfbGUzMigma2V5W2kgKiBzaXpl b2YoX19sZTMyKV0pOworCQl9IGVsc2UgaWYgKGkgJSBOID09IDApIHsKKwkJCXJrW2ldID0gcmtb aSAtIE5dIF4gU3ViV29yZChyb3IzMihya1tpIC0gMV0sIDgpKSBeIHJjb247CisJCQlyY29uID0g Z2YyXzhfbXVsX3gocmNvbik7CisJCX0gZWxzZSBpZiAoTiA+IDYgJiYgaSAlIE4gPT0gNCkgewor CQkJcmtbaV0gPSBya1tpIC0gTl0gXiBTdWJXb3JkKHJrW2kgLSAxXSk7CisJCX0gZWxzZSB7CisJ CQlya1tpXSA9IHJrW2kgLSBOXSBeIHJrW2kgLSAxXTsKKwkJfQorCX0KK30KKworLyogRW5jcnlw dCBvbmUgMTYtYnl0ZSBibG9jayB3aXRoIEFFUyAqLworc3RhdGljIHZvaWQgYWVzX2VuY3J5cHQo Y29uc3Qgc3RydWN0IGFlc19rZXkgKmssIGNvbnN0IHU4IHNyY1tBRVNfQkxPQ0tfU0laRV0sCisJ CQl1OCBkc3RbQUVTX0JMT0NLX1NJWkVdKQoreworCXUzMiBzdGF0ZVs0XTsKKwlpbnQgaTsKKwor CWZvciAoaSA9IDA7IGkgPCA0OyBpKyspCisJCXN0YXRlW2ldID0gZ2V0X3VuYWxpZ25lZF9sZTMy KCZzcmNbaSAqIHNpemVvZihfX2xlMzIpXSk7CisKKwlBZGRSb3VuZEtleShzdGF0ZSwgay0+cm91 bmRfa2V5cyk7CisJZm9yIChpID0gMTsgaSA8IGstPm5yb3VuZHM7IGkrKykgeworCQlTdWJCeXRl cyhzdGF0ZSk7CisJCVNoaWZ0Um93cyhzdGF0ZSk7CisJCU1peENvbHVtbnMoc3RhdGUpOworCQlB ZGRSb3VuZEtleShzdGF0ZSwgJmstPnJvdW5kX2tleXNbNCAqIGldKTsKKwl9CisJU3ViQnl0ZXMo c3RhdGUpOworCVNoaWZ0Um93cyhzdGF0ZSk7CisJQWRkUm91bmRLZXkoc3RhdGUsICZrLT5yb3Vu ZF9rZXlzWzQgKiBpXSk7CisKKwlmb3IgKGkgPSAwOyBpIDwgNDsgaSsrKQorCQlwdXRfdW5hbGln bmVkX2xlMzIoc3RhdGVbaV0sICZkc3RbaSAqIHNpemVvZihfX2xlMzIpXSk7Cit9CisKKy8qIERl Y3J5cHQgb25lIDE2LWJ5dGUgYmxvY2sgd2l0aCBBRVMgKi8KK3N0YXRpYyB2b2lkIGFlc19kZWNy eXB0KGNvbnN0IHN0cnVjdCBhZXNfa2V5ICprLCBjb25zdCB1OCBzcmNbQUVTX0JMT0NLX1NJWkVd LAorCQkJdTggZHN0W0FFU19CTE9DS19TSVpFXSkKK3sKKwl1MzIgc3RhdGVbNF07CisJaW50IGk7 CisKKwlmb3IgKGkgPSAwOyBpIDwgNDsgaSsrKQorCQlzdGF0ZVtpXSA9IGdldF91bmFsaWduZWRf bGUzMigmc3JjW2kgKiBzaXplb2YoX19sZTMyKV0pOworCisJQWRkUm91bmRLZXkoc3RhdGUsICZr LT5yb3VuZF9rZXlzWzQgKiBrLT5ucm91bmRzXSk7CisJSW52U2hpZnRSb3dzKHN0YXRlKTsKKwlJ bnZTdWJCeXRlcyhzdGF0ZSk7CisJZm9yIChpID0gay0+bnJvdW5kcyAtIDE7IGkgPj0gMTsgaS0t KSB7CisJCUFkZFJvdW5kS2V5KHN0YXRlLCAmay0+cm91bmRfa2V5c1s0ICogaV0pOworCQlJbnZN aXhDb2x1bW5zKHN0YXRlKTsKKwkJSW52U2hpZnRSb3dzKHN0YXRlKTsKKwkJSW52U3ViQnl0ZXMo c3RhdGUpOworCX0KKwlBZGRSb3VuZEtleShzdGF0ZSwgay0+cm91bmRfa2V5cyk7CisKKwlmb3Ig KGkgPSAwOyBpIDwgNDsgaSsrKQorCQlwdXRfdW5hbGlnbmVkX2xlMzIoc3RhdGVbaV0sICZkc3Rb aSAqIHNpemVvZihfX2xlMzIpXSk7Cit9CisKKyNpZmRlZiBFTkFCTEVfQUxHX1RFU1RTCisjaW5j bHVkZSA8b3BlbnNzbC9hZXMuaD4KK3N0YXRpYyB2b2lkIHRlc3RfYWVzX2tleXNpemUoaW50IGtl eXNpemUpCit7CisJdW5zaWduZWQgbG9uZyBudW1fdGVzdHMgPSBOVU1fQUxHX1RFU1RfSVRFUkFU SU9OUzsKKworCXdoaWxlIChudW1fdGVzdHMtLSkgeworCQlzdHJ1Y3QgYWVzX2tleSBrOworCQlB RVNfS0VZIHJlZl9rOworCQl1OCBrZXlbQUVTXzI1Nl9LRVlfU0laRV07CisJCXU4IHB0ZXh0W0FF U19CTE9DS19TSVpFXTsKKwkJdTggY3RleHRbQUVTX0JMT0NLX1NJWkVdOworCQl1OCByZWZfY3Rl eHRbQUVTX0JMT0NLX1NJWkVdOworCQl1OCBkZWNyeXB0ZWRbQUVTX0JMT0NLX1NJWkVdOworCisJ CXJhbmRfYnl0ZXMoa2V5LCBrZXlzaXplKTsKKwkJcmFuZF9ieXRlcyhwdGV4dCwgQUVTX0JMT0NL X1NJWkUpOworCisJCWFlc19zZXRrZXkoJmssIGtleSwga2V5c2l6ZSk7CisJCWFlc19lbmNyeXB0 KCZrLCBwdGV4dCwgY3RleHQpOworCisJCUFTU0VSVChBRVNfc2V0X2VuY3J5cHRfa2V5KGtleSwg a2V5c2l6ZSo4LCAmcmVmX2spID09IDApOworCQlBRVNfZW5jcnlwdChwdGV4dCwgcmVmX2N0ZXh0 LCAmcmVmX2spOworCisJCUFTU0VSVChtZW1jbXAoY3RleHQsIHJlZl9jdGV4dCwgQUVTX0JMT0NL X1NJWkUpID09IDApOworCisJCWFlc19kZWNyeXB0KCZrLCBjdGV4dCwgZGVjcnlwdGVkKTsKKwkJ QVNTRVJUKG1lbWNtcChwdGV4dCwgZGVjcnlwdGVkLCBBRVNfQkxPQ0tfU0laRSkgPT0gMCk7CisJ fQorfQorCitzdGF0aWMgdm9pZCB0ZXN0X2Flcyh2b2lkKQoreworCXRlc3RfYWVzX2tleXNpemUo QUVTXzEyOF9LRVlfU0laRSk7CisJdGVzdF9hZXNfa2V5c2l6ZShBRVNfMTkyX0tFWV9TSVpFKTsK Kwl0ZXN0X2Flc19rZXlzaXplKEFFU18yNTZfS0VZX1NJWkUpOworfQorI2VuZGlmIC8qIEVOQUJM RV9BTEdfVEVTVFMgKi8KKworLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKgorICogICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgU0hBLTI1NiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgKgorICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KKworLyoKKyAqIFJlZmVyZW5jZTogIkZJ UFMgMTgwLTIsIFNlY3VyZSBIYXNoIFN0YW5kYXJkIgorICoJaHR0cHM6Ly9jc3JjLm5pc3QuZ292 L2NzcmMvbWVkaWEvcHVibGljYXRpb25zL2ZpcHMvMTgwLzIvYXJjaGl2ZS8yMDAyLTA4LTAxL2Rv Y3VtZW50cy9maXBzMTgwLTJ3aXRoY2hhbmdlbm90aWNlLnBkZgorICovCisKKyNkZWZpbmUgU0hB MjU2X0RJR0VTVF9TSVpFCTMyCisjZGVmaW5lIFNIQTI1Nl9CTE9DS19TSVpFCTY0CisKKyNkZWZp bmUgQ2goeCwgeSwgeikJKCgoeCkgJiAoeSkpIF4gKH4oeCkgJiAoeikpKQorI2RlZmluZSBNYWoo eCwgeSwgeikJKCgoeCkgJiAoeSkpIF4gKCh4KSAmICh6KSkgXiAoKHkpICYgKHopKSkKKyNkZWZp bmUgU2lnbWEyNTZfMCh4KQkocm9yMzIoKHgpLCAgMikgXiByb3IzMigoeCksIDEzKSBeIHJvcjMy KCh4KSwgMjIpKQorI2RlZmluZSBTaWdtYTI1Nl8xKHgpCShyb3IzMigoeCksICA2KSBeIHJvcjMy KCh4KSwgMTEpIF4gcm9yMzIoKHgpLCAyNSkpCisjZGVmaW5lIHNpZ21hMjU2XzAoeCkJKHJvcjMy KCh4KSwgIDcpIF4gcm9yMzIoKHgpLCAxOCkgXiAoKHgpID4+ICAzKSkKKyNkZWZpbmUgc2lnbWEy NTZfMSh4KQkocm9yMzIoKHgpLCAxNykgXiByb3IzMigoeCksIDE5KSBeICgoeCkgPj4gMTApKQor CitzdGF0aWMgY29uc3QgdTMyIHNoYTI1Nl9pdls4XSA9IHsKKwkweDZhMDllNjY3LCAweGJiNjdh ZTg1LCAweDNjNmVmMzcyLCAweGE1NGZmNTNhLCAweDUxMGU1MjdmLCAweDliMDU2ODhjLAorCTB4 MWY4M2Q5YWIsIDB4NWJlMGNkMTksCit9OworCitzdGF0aWMgY29uc3QgdTMyIHNoYTI1Nl9yb3Vu ZF9jb25zdGFudHNbNjRdID0geworCTB4NDI4YTJmOTgsIDB4NzEzNzQ0OTEsIDB4YjVjMGZiY2Ys IDB4ZTliNWRiYTUsIDB4Mzk1NmMyNWIsIDB4NTlmMTExZjEsCisJMHg5MjNmODJhNCwgMHhhYjFj NWVkNSwgMHhkODA3YWE5OCwgMHgxMjgzNWIwMSwgMHgyNDMxODViZSwgMHg1NTBjN2RjMywKKwkw eDcyYmU1ZDc0LCAweDgwZGViMWZlLCAweDliZGMwNmE3LCAweGMxOWJmMTc0LCAweGU0OWI2OWMx LCAweGVmYmU0Nzg2LAorCTB4MGZjMTlkYzYsIDB4MjQwY2ExY2MsIDB4MmRlOTJjNmYsIDB4NGE3 NDg0YWEsIDB4NWNiMGE5ZGMsIDB4NzZmOTg4ZGEsCisJMHg5ODNlNTE1MiwgMHhhODMxYzY2ZCwg MHhiMDAzMjdjOCwgMHhiZjU5N2ZjNywgMHhjNmUwMGJmMywgMHhkNWE3OTE0NywKKwkweDA2Y2E2 MzUxLCAweDE0MjkyOTY3LCAweDI3YjcwYTg1LCAweDJlMWIyMTM4LCAweDRkMmM2ZGZjLCAweDUz MzgwZDEzLAorCTB4NjUwYTczNTQsIDB4NzY2YTBhYmIsIDB4ODFjMmM5MmUsIDB4OTI3MjJjODUs IDB4YTJiZmU4YTEsIDB4YTgxYTY2NGIsCisJMHhjMjRiOGI3MCwgMHhjNzZjNTFhMywgMHhkMTky ZTgxOSwgMHhkNjk5MDYyNCwgMHhmNDBlMzU4NSwgMHgxMDZhYTA3MCwKKwkweDE5YTRjMTE2LCAw eDFlMzc2YzA4LCAweDI3NDg3NzRjLCAweDM0YjBiY2I1LCAweDM5MWMwY2IzLCAweDRlZDhhYTRh LAorCTB4NWI5Y2NhNGYsIDB4NjgyZTZmZjMsIDB4NzQ4ZjgyZWUsIDB4NzhhNTYzNmYsIDB4ODRj ODc4MTQsIDB4OGNjNzAyMDgsCisJMHg5MGJlZmZmYSwgMHhhNDUwNmNlYiwgMHhiZWY5YTNmNywg MHhjNjcxNzhmMiwKK307CisKKy8qIENvbXB1dGUgdGhlIFNIQS0yNTYgZGlnZXN0IG9mIHRoZSBn aXZlbiBidWZmZXIgKi8KK3N0YXRpYyB2b2lkIHNoYTI1Nihjb25zdCB1OCAqaW4sIHNpemVfdCBp bmxlbiwgdTggb3V0W1NIQTI1Nl9ESUdFU1RfU0laRV0pCit7CisJY29uc3Qgc2l6ZV90IG1zZ2xl biA9IFJPVU5EX1VQKGlubGVuICsgOSwgU0hBMjU2X0JMT0NLX1NJWkUpOworCXU4ICogY29uc3Qg bXNnID0geG1hbGxvYyhtc2dsZW4pOworCXUzMiBIWzhdOworCWludCBpOworCisJLyogc3VwZXIg bmFpdmUgd2F5IG9mIGhhbmRsaW5nIHRoZSBwYWRkaW5nICovCisJbWVtY3B5KG1zZywgaW4sIGlu bGVuKTsKKwltZW1zZXQoJm1zZ1tpbmxlbl0sIDAsIG1zZ2xlbiAtIGlubGVuKTsKKwltc2dbaW5s ZW5dID0gMHg4MDsKKwlwdXRfdW5hbGlnbmVkX2JlNjQoKHU2NClpbmxlbiAqIDgsICZtc2dbbXNn bGVuIC0gc2l6ZW9mKF9fYmU2NCldKTsKKwlpbiA9IG1zZzsKKworCW1lbWNweShILCBzaGEyNTZf aXYsIHNpemVvZihIKSk7CisJZG8geworCQl1MzIgYSA9IEhbMF0sIGIgPSBIWzFdLCBjID0gSFsy XSwgZCA9IEhbM10sCisJCSAgICBlID0gSFs0XSwgZiA9IEhbNV0sIGcgPSBIWzZdLCBoID0gSFs3 XTsKKwkJdTMyIFdbNjRdOworCisJCWZvciAoaSA9IDA7IGkgPCAxNjsgaSsrKQorCQkJV1tpXSA9 IGdldF91bmFsaWduZWRfYmUzMigmaW5baSAqIHNpemVvZihfX2JlMzIpXSk7CisJCWZvciAoOyBp IDwgQVJSQVlfU0laRShXKTsgaSsrKQorCQkJV1tpXSA9IHNpZ21hMjU2XzEoV1tpIC0gMl0pICsg V1tpIC0gN10gKworCQkJICAgICAgIHNpZ21hMjU2XzAoV1tpIC0gMTVdKSArIFdbaSAtIDE2XTsK KwkJZm9yIChpID0gMDsgaSA8IEFSUkFZX1NJWkUoVyk7IGkrKykgeworCQkJdTMyIFQxID0gaCAr IFNpZ21hMjU2XzEoZSkgKyBDaChlLCBmLCBnKSArCisJCQkJIHNoYTI1Nl9yb3VuZF9jb25zdGFu dHNbaV0gKyBXW2ldOworCQkJdTMyIFQyID0gU2lnbWEyNTZfMChhKSArIE1haihhLCBiLCBjKTsK KworCQkJaCA9IGc7IGcgPSBmOyBmID0gZTsgZSA9IGQgKyBUMTsKKwkJCWQgPSBjOyBjID0gYjsg YiA9IGE7IGEgPSBUMSArIFQyOworCQl9CisJCUhbMF0gKz0gYTsgSFsxXSArPSBiOyBIWzJdICs9 IGM7IEhbM10gKz0gZDsKKwkJSFs0XSArPSBlOyBIWzVdICs9IGY7IEhbNl0gKz0gZzsgSFs3XSAr PSBoOworCX0gd2hpbGUgKChpbiArPSBTSEEyNTZfQkxPQ0tfU0laRSkgIT0gJm1zZ1ttc2dsZW5d KTsKKworCWZvciAoaSA9IDA7IGkgPCBBUlJBWV9TSVpFKEgpOyBpKyspCisJCXB1dF91bmFsaWdu ZWRfYmUzMihIW2ldLCAmb3V0W2kgKiBzaXplb2YoX19iZTMyKV0pOworCWZyZWUobXNnKTsKK30K KworI2lmZGVmIEVOQUJMRV9BTEdfVEVTVFMKKyNpbmNsdWRlIDxvcGVuc3NsL3NoYS5oPgorc3Rh dGljIHZvaWQgdGVzdF9zaGEyKHZvaWQpCit7CisJdW5zaWduZWQgbG9uZyBudW1fdGVzdHMgPSBO VU1fQUxHX1RFU1RfSVRFUkFUSU9OUzsKKworCXdoaWxlIChudW1fdGVzdHMtLSkgeworCQl1OCBp bls0MDk2XTsKKwkJdTggZGlnZXN0W1NIQTI1Nl9ESUdFU1RfU0laRV07CisJCXU4IHJlZl9kaWdl c3RbU0hBMjU2X0RJR0VTVF9TSVpFXTsKKwkJY29uc3Qgc2l6ZV90IGlubGVuID0gcmFuZCgpICUg KDEgKyBzaXplb2YoaW4pKTsKKworCQlyYW5kX2J5dGVzKGluLCBpbmxlbik7CisKKwkJc2hhMjU2 KGluLCBpbmxlbiwgZGlnZXN0KTsKKwkJU0hBMjU2KGluLCBpbmxlbiwgcmVmX2RpZ2VzdCk7CisJ CUFTU0VSVChtZW1jbXAoZGlnZXN0LCByZWZfZGlnZXN0LCBTSEEyNTZfRElHRVNUX1NJWkUpID09 IDApOworCX0KK30KKyNlbmRpZiAvKiBFTkFCTEVfQUxHX1RFU1RTICovCisKKy8qLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLSoKKyAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFFUyBlbmNyeXB0aW9u IG1vZGVzICAgICAgICAgICAgICAgICAgICAgICAgICAgICoKKyAqLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LSovCisKK3N0YXRpYyB2b2lkIGFlc18yNTZfeHRzX2NyeXB0KGNvbnN0IHU4IGtleVsyICogQUVT XzI1Nl9LRVlfU0laRV0sCisJCQkgICAgICBjb25zdCB1OCBpdltBRVNfQkxPQ0tfU0laRV0sIGNv bnN0IHU4ICpzcmMsCisJCQkgICAgICB1OCAqZHN0LCBzaXplX3QgbmJ5dGVzLCBib29sIGRlY3J5 cHRpbmcpCit7CisJc3RydWN0IGFlc19rZXkgdHdlYWtfa2V5LCBjaXBoZXJfa2V5OworCWJsZTEy OCB0OworCXNpemVfdCBpOworCisJQVNTRVJUKG5ieXRlcyAlIEFFU19CTE9DS19TSVpFID09IDAp OworCWFlc19zZXRrZXkoJmNpcGhlcl9rZXksIGtleSwgQUVTXzI1Nl9LRVlfU0laRSk7CisJYWVz X3NldGtleSgmdHdlYWtfa2V5LCAma2V5W0FFU18yNTZfS0VZX1NJWkVdLCBBRVNfMjU2X0tFWV9T SVpFKTsKKwlhZXNfZW5jcnlwdCgmdHdlYWtfa2V5LCBpdiwgKHU4ICopJnQpOworCWZvciAoaSA9 IDA7IGkgPCBuYnl0ZXM7IGkgKz0gQUVTX0JMT0NLX1NJWkUpIHsKKwkJeG9yKCZkc3RbaV0sICZz cmNbaV0sIChjb25zdCB1OCAqKSZ0LCBBRVNfQkxPQ0tfU0laRSk7CisJCWlmIChkZWNyeXB0aW5n KQorCQkJYWVzX2RlY3J5cHQoJmNpcGhlcl9rZXksICZkc3RbaV0sICZkc3RbaV0pOworCQllbHNl CisJCQlhZXNfZW5jcnlwdCgmY2lwaGVyX2tleSwgJmRzdFtpXSwgJmRzdFtpXSk7CisJCXhvcigm ZHN0W2ldLCAmZHN0W2ldLCAoY29uc3QgdTggKikmdCwgQUVTX0JMT0NLX1NJWkUpOworCQlnZjJf MTI4X211bF94KCZ0KTsKKwl9Cit9CisKK3N0YXRpYyB2b2lkIGFlc18yNTZfeHRzX2VuY3J5cHQo Y29uc3QgdTgga2V5WzIgKiBBRVNfMjU2X0tFWV9TSVpFXSwKKwkJCQljb25zdCB1OCBpdltBRVNf QkxPQ0tfU0laRV0sIGNvbnN0IHU4ICpzcmMsCisJCQkJdTggKmRzdCwgc2l6ZV90IG5ieXRlcykK K3sKKwlhZXNfMjU2X3h0c19jcnlwdChrZXksIGl2LCBzcmMsIGRzdCwgbmJ5dGVzLCBmYWxzZSk7 Cit9CisKK3N0YXRpYyB2b2lkIGFlc18yNTZfeHRzX2RlY3J5cHQoY29uc3QgdTgga2V5WzIgKiBB RVNfMjU2X0tFWV9TSVpFXSwKKwkJCQljb25zdCB1OCBpdltBRVNfQkxPQ0tfU0laRV0sIGNvbnN0 IHU4ICpzcmMsCisJCQkJdTggKmRzdCwgc2l6ZV90IG5ieXRlcykKK3sKKwlhZXNfMjU2X3h0c19j cnlwdChrZXksIGl2LCBzcmMsIGRzdCwgbmJ5dGVzLCB0cnVlKTsKK30KKworI2lmZGVmIEVOQUJM RV9BTEdfVEVTVFMKKyNpbmNsdWRlIDxvcGVuc3NsL2V2cC5oPgorc3RhdGljIHZvaWQgdGVzdF9h ZXNfMjU2X3h0cyh2b2lkKQoreworCXVuc2lnbmVkIGxvbmcgbnVtX3Rlc3RzID0gTlVNX0FMR19U RVNUX0lURVJBVElPTlM7CisJRVZQX0NJUEhFUl9DVFggKmN0eCA9IEVWUF9DSVBIRVJfQ1RYX25l dygpOworCisJQVNTRVJUKGN0eCAhPSBOVUxMKTsKKwl3aGlsZSAobnVtX3Rlc3RzLS0pIHsKKwkJ dTgga2V5WzIgKiBBRVNfMjU2X0tFWV9TSVpFXTsKKwkJdTggaXZbQUVTX0JMT0NLX1NJWkVdOwor CQl1OCBwdGV4dFs1MTJdOworCQl1OCBhY3R1YWxfY3RleHRbc2l6ZW9mKHB0ZXh0KV07CisJCXU4 IGV4cGVjdGVkX2N0ZXh0W3NpemVvZihwdGV4dCldOworCQl1OCBkZWNyeXB0ZWRbc2l6ZW9mKHB0 ZXh0KV07CisJCWNvbnN0IHNpemVfdCBkYXRhbGVuID0gUk9VTkRfRE9XTihyYW5kKCkgJSAoMSAr IHNpemVvZihwdGV4dCkpLAorCQkJCQkJICBBRVNfQkxPQ0tfU0laRSk7CisJCWludCBvdXRsOwor CisJCXJhbmRfYnl0ZXMoa2V5LCBzaXplb2Yoa2V5KSk7CisJCXJhbmRfYnl0ZXMoaXYsIHNpemVv ZihpdikpOworCQlyYW5kX2J5dGVzKHB0ZXh0LCBkYXRhbGVuKTsKKworCQlhZXNfMjU2X3h0c19l bmNyeXB0KGtleSwgaXYsIHB0ZXh0LCBhY3R1YWxfY3RleHQsIGRhdGFsZW4pOworCQlBU1NFUlQo RVZQX0VuY3J5cHRJbml0X2V4KGN0eCwgRVZQX2Flc18yNTZfeHRzKCksCisJCQkJCSAgTlVMTCwg a2V5LCBpdikgPiAwKTsKKwkJQVNTRVJUKEVWUF9FbmNyeXB0VXBkYXRlKGN0eCwgZXhwZWN0ZWRf Y3RleHQsICZvdXRsLAorCQkJCQkgcHRleHQsIGRhdGFsZW4pID4gMCk7CisJCUFTU0VSVChvdXRs ID09IGRhdGFsZW4pOworCQlBU1NFUlQobWVtY21wKGFjdHVhbF9jdGV4dCwgZXhwZWN0ZWRfY3Rl eHQsIGRhdGFsZW4pID09IDApOworCisJCWFlc18yNTZfeHRzX2RlY3J5cHQoa2V5LCBpdiwgYWN0 dWFsX2N0ZXh0LCBkZWNyeXB0ZWQsIGRhdGFsZW4pOworCQlBU1NFUlQobWVtY21wKHB0ZXh0LCBk ZWNyeXB0ZWQsIGRhdGFsZW4pID09IDApOworCX0KKwlFVlBfQ0lQSEVSX0NUWF9mcmVlKGN0eCk7 Cit9CisjZW5kaWYgLyogRU5BQkxFX0FMR19URVNUUyAqLworCitzdGF0aWMgdm9pZCBhZXNfY2Jj X2VuY3J5cHQoY29uc3Qgc3RydWN0IGFlc19rZXkgKmssCisJCQkgICAgY29uc3QgdTggaXZbQUVT X0JMT0NLX1NJWkVdLAorCQkJICAgIGNvbnN0IHU4ICpzcmMsIHU4ICpkc3QsIHNpemVfdCBuYnl0 ZXMpCit7CisJc2l6ZV90IGk7CisKKwlBU1NFUlQobmJ5dGVzICUgQUVTX0JMT0NLX1NJWkUgPT0g MCk7CisJZm9yIChpID0gMDsgaSA8IG5ieXRlczsgaSArPSBBRVNfQkxPQ0tfU0laRSkgeworCQl4 b3IoJmRzdFtpXSwgJnNyY1tpXSwgKGkgPT0gMCA/IGl2IDogJmRzdFtpIC0gQUVTX0JMT0NLX1NJ WkVdKSwKKwkJICAgIEFFU19CTE9DS19TSVpFKTsKKwkJYWVzX2VuY3J5cHQoaywgJmRzdFtpXSwg JmRzdFtpXSk7CisJfQorfQorCitzdGF0aWMgdm9pZCBhZXNfY2JjX2RlY3J5cHQoY29uc3Qgc3Ry dWN0IGFlc19rZXkgKmssCisJCQkgICAgY29uc3QgdTggaXZbQUVTX0JMT0NLX1NJWkVdLAorCQkJ ICAgIGNvbnN0IHU4ICpzcmMsIHU4ICpkc3QsIHNpemVfdCBuYnl0ZXMpCit7CisJc2l6ZV90IGkg PSBuYnl0ZXM7CisKKwlBU1NFUlQoaSAlIEFFU19CTE9DS19TSVpFID09IDApOworCXdoaWxlIChp KSB7CisJCWkgLT0gQUVTX0JMT0NLX1NJWkU7CisJCWFlc19kZWNyeXB0KGssICZzcmNbaV0sICZk c3RbaV0pOworCQl4b3IoJmRzdFtpXSwgJmRzdFtpXSwgKGkgPT0gMCA/IGl2IDogJnNyY1tpIC0g QUVTX0JMT0NLX1NJWkVdKSwKKwkJICAgIEFFU19CTE9DS19TSVpFKTsKKwl9Cit9CisKK3N0YXRp YyB2b2lkIGFlc19jdHNfY2JjX2VuY3J5cHQoY29uc3QgdTggKmtleSwgaW50IGtleXNpemUsCisJ CQkJY29uc3QgdTggaXZbQUVTX0JMT0NLX1NJWkVdLAorCQkJCWNvbnN0IHU4ICpzcmMsIHU4ICpk c3QsIHNpemVfdCBuYnl0ZXMpCit7CisJY29uc3Qgc2l6ZV90IG9mZnNldCA9IFJPVU5EX0RPV04o bmJ5dGVzIC0gMSwgQUVTX0JMT0NLX1NJWkUpOworCWNvbnN0IHNpemVfdCBmaW5hbF9ic2l6ZSA9 IG5ieXRlcyAtIG9mZnNldDsKKwlzdHJ1Y3QgYWVzX2tleSBrOworCXU4ICpwYWQ7CisJdTggYnVm W0FFU19CTE9DS19TSVpFXTsKKworCUFTU0VSVChuYnl0ZXMgPj0gQUVTX0JMT0NLX1NJWkUpOwor CisJYWVzX3NldGtleSgmaywga2V5LCBrZXlzaXplKTsKKworCWlmIChuYnl0ZXMgPT0gQUVTX0JM T0NLX1NJWkUpCisJCXJldHVybiBhZXNfY2JjX2VuY3J5cHQoJmssIGl2LCBzcmMsIGRzdCwgbmJ5 dGVzKTsKKworCWFlc19jYmNfZW5jcnlwdCgmaywgaXYsIHNyYywgZHN0LCBvZmZzZXQpOworCXBh ZCA9ICZkc3Rbb2Zmc2V0IC0gQUVTX0JMT0NLX1NJWkVdOworCisJbWVtY3B5KGJ1ZiwgcGFkLCBB RVNfQkxPQ0tfU0laRSk7CisJeG9yKGJ1ZiwgYnVmLCAmc3JjW29mZnNldF0sIGZpbmFsX2JzaXpl KTsKKwltZW1jcHkoJmRzdFtvZmZzZXRdLCBwYWQsIGZpbmFsX2JzaXplKTsKKwlhZXNfZW5jcnlw dCgmaywgYnVmLCBwYWQpOworfQorCitzdGF0aWMgdm9pZCBhZXNfY3RzX2NiY19kZWNyeXB0KGNv bnN0IHU4ICprZXksIGludCBrZXlzaXplLAorCQkJCWNvbnN0IHU4IGl2W0FFU19CTE9DS19TSVpF XSwKKwkJCQljb25zdCB1OCAqc3JjLCB1OCAqZHN0LCBzaXplX3QgbmJ5dGVzKQoreworCWNvbnN0 IHNpemVfdCBvZmZzZXQgPSBST1VORF9ET1dOKG5ieXRlcyAtIDEsIEFFU19CTE9DS19TSVpFKTsK Kwljb25zdCBzaXplX3QgZmluYWxfYnNpemUgPSBuYnl0ZXMgLSBvZmZzZXQ7CisJc3RydWN0IGFl c19rZXkgazsKKwl1OCAqcGFkOworCisJQVNTRVJUKG5ieXRlcyA+PSBBRVNfQkxPQ0tfU0laRSk7 CisKKwlhZXNfc2V0a2V5KCZrLCBrZXksIGtleXNpemUpOworCisJaWYgKG5ieXRlcyA9PSBBRVNf QkxPQ0tfU0laRSkKKwkJcmV0dXJuIGFlc19jYmNfZGVjcnlwdCgmaywgaXYsIHNyYywgZHN0LCBu Ynl0ZXMpOworCisJcGFkID0gJmRzdFtvZmZzZXQgLSBBRVNfQkxPQ0tfU0laRV07CisJYWVzX2Rl Y3J5cHQoJmssICZzcmNbb2Zmc2V0IC0gQUVTX0JMT0NLX1NJWkVdLCBwYWQpOworCXhvcigmZHN0 W29mZnNldF0sICZzcmNbb2Zmc2V0XSwgcGFkLCBmaW5hbF9ic2l6ZSk7CisJeG9yKHBhZCwgcGFk LCAmZHN0W29mZnNldF0sIGZpbmFsX2JzaXplKTsKKworCWFlc19jYmNfZGVjcnlwdCgmaywgKG9m ZnNldCA9PSBBRVNfQkxPQ0tfU0laRSA/CisJCQkgICAgIGl2IDogJnNyY1tvZmZzZXQgLSAyICog QUVTX0JMT0NLX1NJWkVdKSwKKwkJCXBhZCwgcGFkLCBBRVNfQkxPQ0tfU0laRSk7CisJYWVzX2Ni Y19kZWNyeXB0KCZrLCBpdiwgc3JjLCBkc3QsIG9mZnNldCAtIEFFU19CTE9DS19TSVpFKTsKK30K Kworc3RhdGljIHZvaWQgYWVzXzI1Nl9jdHNfY2JjX2VuY3J5cHQoY29uc3QgdTgga2V5W0FFU18y NTZfS0VZX1NJWkVdLAorCQkJCSAgICBjb25zdCB1OCBpdltBRVNfQkxPQ0tfU0laRV0sCisJCQkJ ICAgIGNvbnN0IHU4ICpzcmMsIHU4ICpkc3QsIHNpemVfdCBuYnl0ZXMpCit7CisJYWVzX2N0c19j YmNfZW5jcnlwdChrZXksIEFFU18yNTZfS0VZX1NJWkUsIGl2LCBzcmMsIGRzdCwgbmJ5dGVzKTsK K30KKworc3RhdGljIHZvaWQgYWVzXzI1Nl9jdHNfY2JjX2RlY3J5cHQoY29uc3QgdTgga2V5W0FF U18yNTZfS0VZX1NJWkVdLAorCQkJCSAgICBjb25zdCB1OCBpdltBRVNfQkxPQ0tfU0laRV0sCisJ CQkJICAgIGNvbnN0IHU4ICpzcmMsIHU4ICpkc3QsIHNpemVfdCBuYnl0ZXMpCit7CisJYWVzX2N0 c19jYmNfZGVjcnlwdChrZXksIEFFU18yNTZfS0VZX1NJWkUsIGl2LCBzcmMsIGRzdCwgbmJ5dGVz KTsKK30KKworI2lmZGVmIEVOQUJMRV9BTEdfVEVTVFMKKyNpbmNsdWRlIDxvcGVuc3NsL21vZGVz Lmg+CitzdGF0aWMgdm9pZCBhZXNfYmxvY2sxMjhfZihjb25zdCB1bnNpZ25lZCBjaGFyIGluWzE2 XSwKKwkJCSAgIHVuc2lnbmVkIGNoYXIgb3V0WzE2XSwgY29uc3Qgdm9pZCAqa2V5KQoreworCWFl c19lbmNyeXB0KGtleSwgaW4sIG91dCk7Cit9CisKK3N0YXRpYyB2b2lkIHRlc3RfYWVzXzI1Nl9j dHNfY2JjKHZvaWQpCit7CisJdW5zaWduZWQgbG9uZyBudW1fdGVzdHMgPSBOVU1fQUxHX1RFU1Rf SVRFUkFUSU9OUzsKKworCXdoaWxlIChudW1fdGVzdHMtLSkgeworCQl1OCBrZXlbQUVTXzI1Nl9L RVlfU0laRV07CisJCXU4IGl2W0FFU19CTE9DS19TSVpFXTsKKwkJdTggaXZfY29weVtBRVNfQkxP Q0tfU0laRV07CisJCXU4IHB0ZXh0WzUxMl07CisJCXU4IGFjdHVhbF9jdGV4dFtzaXplb2YocHRl eHQpXTsKKwkJdTggZXhwZWN0ZWRfY3RleHRbc2l6ZW9mKHB0ZXh0KV07CisJCXU4IGRlY3J5cHRl ZFtzaXplb2YocHRleHQpXTsKKwkJY29uc3Qgc2l6ZV90IGRhdGFsZW4gPSAxNiArIChyYW5kKCkg JSAoc2l6ZW9mKHB0ZXh0KSAtIDE1KSk7CisJCXN0cnVjdCBhZXNfa2V5IGs7CisKKwkJcmFuZF9i eXRlcyhrZXksIHNpemVvZihrZXkpKTsKKwkJcmFuZF9ieXRlcyhpdiwgc2l6ZW9mKGl2KSk7CisJ CXJhbmRfYnl0ZXMocHRleHQsIGRhdGFsZW4pOworCisJCWFlc18yNTZfY3RzX2NiY19lbmNyeXB0 KGtleSwgaXYsIHB0ZXh0LCBhY3R1YWxfY3RleHQsIGRhdGFsZW4pOworCisJCS8qIE9wZW5TU0wg ZG9lc24ndCBhbGxvdyBkYXRhbGVuPUFFU19CTE9DS19TSVpFOyBMaW51eCBkb2VzICovCisJCWlm IChkYXRhbGVuICE9IEFFU19CTE9DS19TSVpFKSB7CisJCQlhZXNfc2V0a2V5KCZrLCBrZXksIHNp emVvZihrZXkpKTsKKwkJCW1lbWNweShpdl9jb3B5LCBpdiwgc2l6ZW9mKGl2KSk7CisJCQlBU1NF UlQoQ1JZUFRPX2N0czEyOF9lbmNyeXB0X2Jsb2NrKHB0ZXh0LAorCQkJCQkJCSAgIGV4cGVjdGVk X2N0ZXh0LAorCQkJCQkJCSAgIGRhdGFsZW4sICZrLCBpdl9jb3B5LAorCQkJCQkJCSAgIGFlc19i bG9jazEyOF9mKQorCQkJICAgICAgID09IGRhdGFsZW4pOworCQkJQVNTRVJUKG1lbWNtcChhY3R1 YWxfY3RleHQsIGV4cGVjdGVkX2N0ZXh0LAorCQkJCSAgICAgIGRhdGFsZW4pID09IDApOworCQl9 CisJCWFlc18yNTZfY3RzX2NiY19kZWNyeXB0KGtleSwgaXYsIGFjdHVhbF9jdGV4dCwgZGVjcnlw dGVkLAorCQkJCQlkYXRhbGVuKTsKKwkJQVNTRVJUKG1lbWNtcChwdGV4dCwgZGVjcnlwdGVkLCBk YXRhbGVuKSA9PSAwKTsKKwl9Cit9CisjZW5kaWYgLyogRU5BQkxFX0FMR19URVNUUyAqLworCitz dGF0aWMgdm9pZCBlc3Npdl9nZW5lcmF0ZV9pdihjb25zdCB1OCBvcmlnX2tleVtBRVNfMTI4X0tF WV9TSVpFXSwKKwkJCSAgICAgIGNvbnN0IHU4IG9yaWdfaXZbQUVTX0JMT0NLX1NJWkVdLAorCQkJ ICAgICAgdTggcmVhbF9pdltBRVNfQkxPQ0tfU0laRV0pCit7CisJdTggZXNzaXZfa2V5W1NIQTI1 Nl9ESUdFU1RfU0laRV07CisJc3RydWN0IGFlc19rZXkgZXNzaXY7CisKKwkvKiBBRVMgZW5jcnlw dCB0aGUgb3JpZ2luYWwgSVYgdXNpbmcgYSBoYXNoIG9mIHRoZSBvcmlnaW5hbCBrZXkgKi8KKwlT VEFUSUNfQVNTRVJUKFNIQTI1Nl9ESUdFU1RfU0laRSA9PSBBRVNfMjU2X0tFWV9TSVpFKTsKKwlz aGEyNTYob3JpZ19rZXksIEFFU18xMjhfS0VZX1NJWkUsIGVzc2l2X2tleSk7CisJYWVzX3NldGtl eSgmZXNzaXYsIGVzc2l2X2tleSwgQUVTXzI1Nl9LRVlfU0laRSk7CisJYWVzX2VuY3J5cHQoJmVz c2l2LCBvcmlnX2l2LCByZWFsX2l2KTsKK30KKworc3RhdGljIHZvaWQgYWVzXzEyOF9jYmNfZXNz aXZfZW5jcnlwdChjb25zdCB1OCBrZXlbQUVTXzEyOF9LRVlfU0laRV0sCisJCQkJICAgICAgY29u c3QgdTggaXZbQUVTX0JMT0NLX1NJWkVdLAorCQkJCSAgICAgIGNvbnN0IHU4ICpzcmMsIHU4ICpk c3QsIHNpemVfdCBuYnl0ZXMpCit7CisJc3RydWN0IGFlc19rZXkgazsKKwl1OCByZWFsX2l2W0FF U19CTE9DS19TSVpFXTsKKworCWFlc19zZXRrZXkoJmssIGtleSwgQUVTXzEyOF9LRVlfU0laRSk7 CisJZXNzaXZfZ2VuZXJhdGVfaXYoa2V5LCBpdiwgcmVhbF9pdik7CisJYWVzX2NiY19lbmNyeXB0 KCZrLCByZWFsX2l2LCBzcmMsIGRzdCwgbmJ5dGVzKTsKK30KKworc3RhdGljIHZvaWQgYWVzXzEy OF9jYmNfZXNzaXZfZGVjcnlwdChjb25zdCB1OCBrZXlbQUVTXzEyOF9LRVlfU0laRV0sCisJCQkJ ICAgICAgY29uc3QgdTggaXZbQUVTX0JMT0NLX1NJWkVdLAorCQkJCSAgICAgIGNvbnN0IHU4ICpz cmMsIHU4ICpkc3QsIHNpemVfdCBuYnl0ZXMpCit7CisJc3RydWN0IGFlc19rZXkgazsKKwl1OCBy ZWFsX2l2W0FFU19CTE9DS19TSVpFXTsKKworCWFlc19zZXRrZXkoJmssIGtleSwgQUVTXzEyOF9L RVlfU0laRSk7CisJZXNzaXZfZ2VuZXJhdGVfaXYoa2V5LCBpdiwgcmVhbF9pdik7CisJYWVzX2Ni Y19kZWNyeXB0KCZrLCByZWFsX2l2LCBzcmMsIGRzdCwgbmJ5dGVzKTsKK30KKworc3RhdGljIHZv aWQgYWVzXzEyOF9jdHNfY2JjX2VuY3J5cHQoY29uc3QgdTgga2V5W0FFU18xMjhfS0VZX1NJWkVd LAorCQkJCSAgICBjb25zdCB1OCBpdltBRVNfQkxPQ0tfU0laRV0sCisJCQkJICAgIGNvbnN0IHU4 ICpzcmMsIHU4ICpkc3QsIHNpemVfdCBuYnl0ZXMpCit7CisJYWVzX2N0c19jYmNfZW5jcnlwdChr ZXksIEFFU18xMjhfS0VZX1NJWkUsIGl2LCBzcmMsIGRzdCwgbmJ5dGVzKTsKK30KKworc3RhdGlj IHZvaWQgYWVzXzEyOF9jdHNfY2JjX2RlY3J5cHQoY29uc3QgdTgga2V5W0FFU18xMjhfS0VZX1NJ WkVdLAorCQkJCSAgICBjb25zdCB1OCBpdltBRVNfQkxPQ0tfU0laRV0sCisJCQkJICAgIGNvbnN0 IHU4ICpzcmMsIHU4ICpkc3QsIHNpemVfdCBuYnl0ZXMpCit7CisJYWVzX2N0c19jYmNfZGVjcnlw dChrZXksIEFFU18xMjhfS0VZX1NJWkUsIGl2LCBzcmMsIGRzdCwgbmJ5dGVzKTsKK30KKworLyot LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tKgorICogICAgICAgICAgICAgICAgICAgICAgICAgICBYQ2hhQ2hh MTIgc3RyZWFtIGNpcGhlciAgICAgICAgICAgICAgICAgICAgICAgICAgKgorICotLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tKi8KKworLyoKKyAqIFJlZmVyZW5jZXM6CisgKiAgIC0gIlhDaGFDaGE6IGVYdGVu ZGVkLW5vbmNlIENoYUNoYSBhbmQgQUVBRF9YQ2hhQ2hhMjBfUG9seTEzMDUiCisgKglodHRwczov L3Rvb2xzLmlldGYub3JnL2h0bWwvZHJhZnQtYXJjaXN6ZXdza2kteGNoYWNoYS0wMworICoKKyAq ICAgLSAiQ2hhQ2hhLCBhIHZhcmlhbnQgb2YgU2Fsc2EyMCIKKyAqCWh0dHBzOi8vY3IueXAudG8v Y2hhY2hhL2NoYWNoYS0yMDA4MDEyOC5wZGYKKyAqCisgKiAgIC0gIkV4dGVuZGluZyB0aGUgU2Fs c2EyMCBub25jZSIKKyAqCWh0dHBzOi8vY3IueXAudG8vc251ZmZsZS94c2Fsc2EtMjAwODExMjgu cGRmCisgKi8KKworI2RlZmluZSBDSEFDSEFfS0VZX1NJWkUJCTMyCisjZGVmaW5lIFhDSEFDSEFf S0VZX1NJWkUJQ0hBQ0hBX0tFWV9TSVpFCisjZGVmaW5lIFhDSEFDSEFfTk9OQ0VfU0laRQkyNAor CitzdGF0aWMgdm9pZCBjaGFjaGFfaW5pdF9zdGF0ZSh1MzIgc3RhdGVbMTZdLCBjb25zdCB1OCBr ZXlbQ0hBQ0hBX0tFWV9TSVpFXSwKKwkJCSAgICAgIGNvbnN0IHU4IGl2WzE2XSkKK3sKKwlzdGF0 aWMgY29uc3QgdTggY29uc3RzWzE2XSA9ICJleHBhbmQgMzItYnl0ZSBrIjsKKwlpbnQgaTsKKwor CWZvciAoaSA9IDA7IGkgPCA0OyBpKyspCisJCXN0YXRlW2ldID0gZ2V0X3VuYWxpZ25lZF9sZTMy KCZjb25zdHNbaSAqIHNpemVvZihfX2xlMzIpXSk7CisJZm9yIChpID0gMDsgaSA8IDg7IGkrKykK KwkJc3RhdGVbNCArIGldID0gZ2V0X3VuYWxpZ25lZF9sZTMyKCZrZXlbaSAqIHNpemVvZihfX2xl MzIpXSk7CisJZm9yIChpID0gMDsgaSA8IDQ7IGkrKykKKwkJc3RhdGVbMTIgKyBpXSA9IGdldF91 bmFsaWduZWRfbGUzMigmaXZbaSAqIHNpemVvZihfX2xlMzIpXSk7Cit9CisKKyNkZWZpbmUgQ0hB Q0hBX1FVQVJURVJST1VORChhLCBiLCBjLCBkKQkJXAorCWRvIHsJCQkJCVwKKwkJYSArPSBiOyBk ID0gcm9sMzIoZCBeIGEsIDE2KTsJXAorCQljICs9IGQ7IGIgPSByb2wzMihiIF4gYywgMTIpOwlc CisJCWEgKz0gYjsgZCA9IHJvbDMyKGQgXiBhLCA4KTsJXAorCQljICs9IGQ7IGIgPSByb2wzMihi IF4gYywgNyk7CVwKKwl9IHdoaWxlICgwKQorCitzdGF0aWMgdm9pZCBjaGFjaGFfcGVybXV0ZSh1 MzIgeFsxNl0sIGludCBucm91bmRzKQoreworCWRvIHsKKwkJLyogY29sdW1uIHJvdW5kICovCisJ CUNIQUNIQV9RVUFSVEVSUk9VTkQoeFswXSwgeFs0XSwgeFs4XSwgeFsxMl0pOworCQlDSEFDSEFf UVVBUlRFUlJPVU5EKHhbMV0sIHhbNV0sIHhbOV0sIHhbMTNdKTsKKwkJQ0hBQ0hBX1FVQVJURVJS T1VORCh4WzJdLCB4WzZdLCB4WzEwXSwgeFsxNF0pOworCQlDSEFDSEFfUVVBUlRFUlJPVU5EKHhb M10sIHhbN10sIHhbMTFdLCB4WzE1XSk7CisKKwkJLyogZGlhZ29uYWwgcm91bmQgKi8KKwkJQ0hB Q0hBX1FVQVJURVJST1VORCh4WzBdLCB4WzVdLCB4WzEwXSwgeFsxNV0pOworCQlDSEFDSEFfUVVB UlRFUlJPVU5EKHhbMV0sIHhbNl0sIHhbMTFdLCB4WzEyXSk7CisJCUNIQUNIQV9RVUFSVEVSUk9V TkQoeFsyXSwgeFs3XSwgeFs4XSwgeFsxM10pOworCQlDSEFDSEFfUVVBUlRFUlJPVU5EKHhbM10s IHhbNF0sIHhbOV0sIHhbMTRdKTsKKwl9IHdoaWxlICgobnJvdW5kcyAtPSAyKSAhPSAwKTsKK30K Kworc3RhdGljIHZvaWQgeGNoYWNoYShjb25zdCB1OCBrZXlbWENIQUNIQV9LRVlfU0laRV0sCisJ CSAgICBjb25zdCB1OCBub25jZVtYQ0hBQ0hBX05PTkNFX1NJWkVdLAorCQkgICAgY29uc3QgdTgg KnNyYywgdTggKmRzdCwgc2l6ZV90IG5ieXRlcywgaW50IG5yb3VuZHMpCit7CisJdTMyIHN0YXRl WzE2XTsKKwl1OCByZWFsX2tleVtDSEFDSEFfS0VZX1NJWkVdOworCXU4IHJlYWxfaXZbMTZdID0g eyAwIH07CisJc2l6ZV90IGksIGo7CisKKwkvKiBDb21wdXRlIHJlYWwga2V5IHVzaW5nIG9yaWdp bmFsIGtleSBhbmQgZmlyc3QgMTI4IG5vbmNlIGJpdHMgKi8KKwljaGFjaGFfaW5pdF9zdGF0ZShz dGF0ZSwga2V5LCBub25jZSk7CisJY2hhY2hhX3Blcm11dGUoc3RhdGUsIG5yb3VuZHMpOworCWZv ciAoaSA9IDA7IGkgPCA4OyBpKyspIC8qIHN0YXRlIHdvcmRzIDAuLjMsIDEyLi4xNSAqLworCQlw dXRfdW5hbGlnbmVkX2xlMzIoc3RhdGVbKGkgPCA0ID8gMCA6IDgpICsgaV0sCisJCQkJICAgJnJl YWxfa2V5W2kgKiBzaXplb2YoX19sZTMyKV0pOworCisJLyogTm93IGRvIHJlZ3VsYXIgQ2hhQ2hh LCB1c2luZyByZWFsIGtleSBhbmQgcmVtYWluaW5nIG5vbmNlIGJpdHMgKi8KKwltZW1jcHkoJnJl YWxfaXZbOF0sIG5vbmNlICsgMTYsIDgpOworCWNoYWNoYV9pbml0X3N0YXRlKHN0YXRlLCByZWFs X2tleSwgcmVhbF9pdik7CisJZm9yIChpID0gMDsgaSA8IG5ieXRlczsgaSArPSA2NCkgeworCQl1 MzIgeFsxNl07CisJCV9fbGUzMiBrZXlzdHJlYW1bMTZdOworCisJCW1lbWNweSh4LCBzdGF0ZSwg NjQpOworCQljaGFjaGFfcGVybXV0ZSh4LCBucm91bmRzKTsKKwkJZm9yIChqID0gMDsgaiA8IDE2 OyBqKyspCisJCQlrZXlzdHJlYW1bal0gPSBjcHVfdG9fbGUzMih4W2pdICsgc3RhdGVbal0pOwor CQl4b3IoJmRzdFtpXSwgJnNyY1tpXSwgKHU4ICopa2V5c3RyZWFtLCBNSU4obmJ5dGVzIC0gaSwg NjQpKTsKKwkJaWYgKCsrc3RhdGVbMTJdID09IDApCisJCQlzdGF0ZVsxM10rKzsKKwl9Cit9CisK K3N0YXRpYyB2b2lkIHhjaGFjaGExMihjb25zdCB1OCBrZXlbWENIQUNIQV9LRVlfU0laRV0sCisJ CSAgICAgIGNvbnN0IHU4IG5vbmNlW1hDSEFDSEFfTk9OQ0VfU0laRV0sCisJCSAgICAgIGNvbnN0 IHU4ICpzcmMsIHU4ICpkc3QsIHNpemVfdCBuYnl0ZXMpCit7CisJeGNoYWNoYShrZXksIG5vbmNl LCBzcmMsIGRzdCwgbmJ5dGVzLCAxMik7Cit9CisKKy8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSoKKyAq ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUG9seTEzMDUgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICoKKyAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCisKKy8qCisgKiBO b3RlOiB0aGlzIGlzIG9ubHkgdGhlIFBvbHkxMzA1IM61LWFsbW9zdC3iiIYtdW5pdmVyc2FsIGhh c2ggZnVuY3Rpb24sIG5vdCB0aGUKKyAqIGZ1bGwgUG9seTEzMDUgTUFDLiAgSS5lLiwgaXQgZG9l c24ndCBhZGQgYW55dGhpbmcgYXQgdGhlIGVuZC4KKyAqLworCisjZGVmaW5lIFBPTFkxMzA1X0tF WV9TSVpFCTE2CisjZGVmaW5lIFBPTFkxMzA1X0JMT0NLX1NJWkUJMTYKKworc3RhdGljIHZvaWQg cG9seTEzMDUoY29uc3QgdTgga2V5W1BPTFkxMzA1X0tFWV9TSVpFXSwKKwkJICAgICBjb25zdCB1 OCAqbXNnLCBzaXplX3QgbXNnbGVuLCBsZTEyOCAqb3V0KQoreworCWNvbnN0IHUzMiBsaW1iX21h c2sgPSAweDNmZmZmZmY7CS8qIGxpbWJzIGFyZSBiYXNlIDJeMjYgKi8KKwljb25zdCB1NjQgcjAg PSAoZ2V0X3VuYWxpZ25lZF9sZTMyKGtleSArICAwKSA+PiAwKSAmIDB4M2ZmZmZmZjsKKwljb25z dCB1NjQgcjEgPSAoZ2V0X3VuYWxpZ25lZF9sZTMyKGtleSArICAzKSA+PiAyKSAmIDB4M2ZmZmYw MzsKKwljb25zdCB1NjQgcjIgPSAoZ2V0X3VuYWxpZ25lZF9sZTMyKGtleSArICA2KSA+PiA0KSAm IDB4M2ZmYzBmZjsKKwljb25zdCB1NjQgcjMgPSAoZ2V0X3VuYWxpZ25lZF9sZTMyKGtleSArICA5 KSA+PiA2KSAmIDB4M2YwM2ZmZjsKKwljb25zdCB1NjQgcjQgPSAoZ2V0X3VuYWxpZ25lZF9sZTMy KGtleSArIDEyKSA+PiA4KSAmIDB4MDBmZmZmZjsKKwl1MzIgaDAgPSAwLCBoMSA9IDAsIGgyID0g MCwgaDMgPSAwLCBoNCA9IDA7CisJdTMyIGcwLCBnMSwgZzIsIGczLCBnNCwgZ2VfcF9tYXNrOwor CisJLyogUGFydGlhbCBibG9jayBzdXBwb3J0IGlzIG5vdCBuZWNlc3NhcnkgZm9yIEFkaWFudHVt ICovCisJQVNTRVJUKG1zZ2xlbiAlIFBPTFkxMzA1X0JMT0NLX1NJWkUgPT0gMCk7CisKKwl3aGls ZSAobXNnbGVuKSB7CisJCXU2NCBkMCwgZDEsIGQyLCBkMywgZDQ7CisKKwkJLyogaCArPSAqbXNn ICovCisJCWgwICs9IChnZXRfdW5hbGlnbmVkX2xlMzIobXNnICsgIDApID4+IDApICYgbGltYl9t YXNrOworCQloMSArPSAoZ2V0X3VuYWxpZ25lZF9sZTMyKG1zZyArICAzKSA+PiAyKSAmIGxpbWJf bWFzazsKKwkJaDIgKz0gKGdldF91bmFsaWduZWRfbGUzMihtc2cgKyAgNikgPj4gNCkgJiBsaW1i X21hc2s7CisJCWgzICs9IChnZXRfdW5hbGlnbmVkX2xlMzIobXNnICsgIDkpID4+IDYpICYgbGlt Yl9tYXNrOworCQloNCArPSAoZ2V0X3VuYWxpZ25lZF9sZTMyKG1zZyArIDEyKSA+PiA4KSB8ICgx IDw8IDI0KTsKKworCQkvKiBoICo9IHIgKi8KKwkJZDAgPSBoMCpyMCArIGgxKjUqcjQgKyBoMio1 KnIzICsgaDMqNSpyMiArIGg0KjUqcjE7CisJCWQxID0gaDAqcjEgKyBoMSpyMCAgICsgaDIqNSpy NCArIGgzKjUqcjMgKyBoNCo1KnIyOworCQlkMiA9IGgwKnIyICsgaDEqcjEgICArIGgyKnIwICAg KyBoMyo1KnI0ICsgaDQqNSpyMzsKKwkJZDMgPSBoMCpyMyArIGgxKnIyICAgKyBoMipyMSAgICsg aDMqcjAgICArIGg0KjUqcjQ7CisJCWQ0ID0gaDAqcjQgKyBoMSpyMyAgICsgaDIqcjIgICArIGgz KnIxICAgKyBoNCpyMDsKKworCQkvKiAocGFydGlhbCkgaCAlPSAyXjEzMCAtIDUgKi8KKwkJZDEg Kz0gZDAgPj4gMjY7CQloMCA9IGQwICYgbGltYl9tYXNrOworCQlkMiArPSBkMSA+PiAyNjsJCWgx ID0gZDEgJiBsaW1iX21hc2s7CisJCWQzICs9IGQyID4+IDI2OwkJaDIgPSBkMiAmIGxpbWJfbWFz azsKKwkJZDQgKz0gZDMgPj4gMjY7CQloMyA9IGQzICYgbGltYl9tYXNrOworCQloMCArPSAoZDQg Pj4gMjYpICogNTsJaDQgPSBkNCAmIGxpbWJfbWFzazsKKwkJaDEgKz0gaDAgPj4gMjY7CQloMCAm PSBsaW1iX21hc2s7CisKKwkJbXNnICs9IFBPTFkxMzA1X0JMT0NLX1NJWkU7CisJCW1zZ2xlbiAt PSBQT0xZMTMwNV9CTE9DS19TSVpFOworCX0KKworCS8qIGZ1bGx5IGNhcnJ5IGggKi8KKwloMiAr PSAoaDEgPj4gMjYpOwloMSAmPSBsaW1iX21hc2s7CisJaDMgKz0gKGgyID4+IDI2KTsJaDIgJj0g bGltYl9tYXNrOworCWg0ICs9IChoMyA+PiAyNik7CWgzICY9IGxpbWJfbWFzazsKKwloMCArPSAo aDQgPj4gMjYpICogNTsJaDQgJj0gbGltYl9tYXNrOworCWgxICs9IChoMCA+PiAyNik7CWgwICY9 IGxpbWJfbWFzazsKKworCS8qIGlmIChoID49IDJeMTMwIC0gNSkgaCAtPSAyXjEzMCAtIDU7ICov CisJZzAgPSBoMCArIDU7CisJZzEgPSBoMSArIChnMCA+PiAyNik7CWcwICY9IGxpbWJfbWFzazsK KwlnMiA9IGgyICsgKGcxID4+IDI2KTsJZzEgJj0gbGltYl9tYXNrOworCWczID0gaDMgKyAoZzIg Pj4gMjYpOwlnMiAmPSBsaW1iX21hc2s7CisJZzQgPSBoNCArIChnMyA+PiAyNik7CWczICY9IGxp bWJfbWFzazsKKwlnZV9wX21hc2sgPSB+KChnNCA+PiAyNikgLSAxKTsgLyogYWxsIDEncyBpZiBo ID49IDJeMTMwIC0gNSwgZWxzZSAwICovCisJaDAgPSAoaDAgJiB+Z2VfcF9tYXNrKSB8IChnMCAm IGdlX3BfbWFzayk7CisJaDEgPSAoaDEgJiB+Z2VfcF9tYXNrKSB8IChnMSAmIGdlX3BfbWFzayk7 CisJaDIgPSAoaDIgJiB+Z2VfcF9tYXNrKSB8IChnMiAmIGdlX3BfbWFzayk7CisJaDMgPSAoaDMg JiB+Z2VfcF9tYXNrKSB8IChnMyAmIGdlX3BfbWFzayk7CisJaDQgPSAoaDQgJiB+Z2VfcF9tYXNr KSB8IChnNCAmIGdlX3BfbWFzayAmIGxpbWJfbWFzayk7CisKKwkvKiBoICU9IDJeMTI4ICovCisJ b3V0LT5sbyA9IGNwdV90b19sZTY0KCgodTY0KWgyIDw8IDUyKSB8ICgodTY0KWgxIDw8IDI2KSB8 IGgwKTsKKwlvdXQtPmhpID0gY3B1X3RvX2xlNjQoKCh1NjQpaDQgPDwgNDApIHwgKCh1NjQpaDMg PDwgMTQpIHwgKGgyID4+IDEyKSk7Cit9CisKKy8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSoKKyAqICAg ICAgICAgICAgICAgICAgICAgICAgICBBZGlhbnR1bSBlbmNyeXB0aW9uIG1vZGUgICAgICAgICAg ICAgICAgICAgICAgICAgICoKKyAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCisKKy8qCisgKiBSZWZl cmVuY2U6ICJBZGlhbnR1bTogbGVuZ3RoLXByZXNlcnZpbmcgZW5jcnlwdGlvbiBmb3IgZW50cnkt bGV2ZWwgcHJvY2Vzc29ycyIKKyAqCWh0dHBzOi8vdG9zYy5pYWNyLm9yZy9pbmRleC5waHAvVG9T Qy9hcnRpY2xlL3ZpZXcvNzM2MAorICovCisKKyNkZWZpbmUgQURJQU5UVU1fS0VZX1NJWkUJMzIK KyNkZWZpbmUgQURJQU5UVU1fSVZfU0laRQkzMgorI2RlZmluZSBBRElBTlRVTV9IQVNIX0tFWV9T SVpFCSgoMiAqIFBPTFkxMzA1X0tFWV9TSVpFKSArIE5IX0tFWV9TSVpFKQorCisjZGVmaW5lIE5I X0tFWV9TSVpFCQkxMDcyCisjZGVmaW5lIE5IX0tFWV9XT1JEUwkJKE5IX0tFWV9TSVpFIC8gc2l6 ZW9mKHUzMikpCisjZGVmaW5lIE5IX0JMT0NLX1NJWkUJCTEwMjQKKyNkZWZpbmUgTkhfSEFTSF9T SVpFCQkzMgorI2RlZmluZSBOSF9NRVNTQUdFX1VOSVQJCTE2CisKK3N0YXRpYyB1NjQgbmhfcGFz cyhjb25zdCB1MzIgKmtleSwgY29uc3QgdTggKm1zZywgc2l6ZV90IG1zZ2xlbikKK3sKKwl1NjQg c3VtID0gMDsKKworCUFTU0VSVChtc2dsZW4gJSBOSF9NRVNTQUdFX1VOSVQgPT0gMCk7CisJd2hp bGUgKG1zZ2xlbikgeworCQlzdW0gKz0gKHU2NCkodTMyKShnZXRfdW5hbGlnbmVkX2xlMzIobXNn ICsgIDApICsga2V5WzBdKSAqCisJCQkgICAgKHUzMikoZ2V0X3VuYWxpZ25lZF9sZTMyKG1zZyAr ICA4KSArIGtleVsyXSk7CisJCXN1bSArPSAodTY0KSh1MzIpKGdldF91bmFsaWduZWRfbGUzMiht c2cgKyAgNCkgKyBrZXlbMV0pICoKKwkJCSAgICAodTMyKShnZXRfdW5hbGlnbmVkX2xlMzIobXNn ICsgMTIpICsga2V5WzNdKTsKKwkJa2V5ICs9IE5IX01FU1NBR0VfVU5JVCAvIHNpemVvZihrZXlb MF0pOworCQltc2cgKz0gTkhfTUVTU0FHRV9VTklUOworCQltc2dsZW4gLT0gTkhfTUVTU0FHRV9V TklUOworCX0KKwlyZXR1cm4gc3VtOworfQorCisvKiBOSCDOtS1hbG1vc3QtdW5pdmVyc2FsIGhh c2ggZnVuY3Rpb24gKi8KK3N0YXRpYyB2b2lkIG5oKGNvbnN0IHUzMiAqa2V5LCBjb25zdCB1OCAq bXNnLCBzaXplX3QgbXNnbGVuLAorCSAgICAgICB1OCByZXN1bHRbTkhfSEFTSF9TSVpFXSkKK3sK KwlzaXplX3QgaTsKKworCWZvciAoaSA9IDA7IGkgPCBOSF9IQVNIX1NJWkU7IGkgKz0gc2l6ZW9m KF9fbGU2NCkpIHsKKwkJcHV0X3VuYWxpZ25lZF9sZTY0KG5oX3Bhc3Moa2V5LCBtc2csIG1zZ2xl biksICZyZXN1bHRbaV0pOworCQlrZXkgKz0gTkhfTUVTU0FHRV9VTklUIC8gc2l6ZW9mKGtleVsw XSk7CisJfQorfQorCisvKiBBZGlhbnR1bSdzIM61LWFsbW9zdC3iiIYtdW5pdmVyc2FsIGhhc2gg ZnVuY3Rpb24gKi8KK3N0YXRpYyB2b2lkIGFkaWFudHVtX2hhc2goY29uc3QgdTgga2V5W0FESUFO VFVNX0hBU0hfS0VZX1NJWkVdLAorCQkJICBjb25zdCB1OCBpdltBRElBTlRVTV9JVl9TSVpFXSwK KwkJCSAgY29uc3QgdTggKm1zZywgc2l6ZV90IG1zZ2xlbiwgbGUxMjggKnJlc3VsdCkKK3sKKwlj b25zdCB1OCAqaGVhZGVyX3BvbHlfa2V5ID0ga2V5OworCWNvbnN0IHU4ICptc2dfcG9seV9rZXkg PSBoZWFkZXJfcG9seV9rZXkgKyBQT0xZMTMwNV9LRVlfU0laRTsKKwljb25zdCB1OCAqbmhfa2V5 ID0gbXNnX3BvbHlfa2V5ICsgUE9MWTEzMDVfS0VZX1NJWkU7CisJdTMyIG5oX2tleV93b3Jkc1tO SF9LRVlfV09SRFNdOworCXU4IGhlYWRlcltBRElBTlRVTV9JVl9TSVpFICsgUE9MWTEzMDVfQkxP Q0tfU0laRV07CisJY29uc3Qgc2l6ZV90IG51bV9uaF9ibG9ja3MgPSBESVZfUk9VTkRfVVAobXNn bGVuLCBOSF9CTE9DS19TSVpFKTsKKwl1OCAqbmhfaGFzaGVzID0geG1hbGxvYyhudW1fbmhfYmxv Y2tzICogTkhfSEFTSF9TSVpFKTsKKwljb25zdCBzaXplX3QgcGFkZGVkX21zZ2xlbiA9IFJPVU5E X1VQKG1zZ2xlbiwgTkhfTUVTU0FHRV9VTklUKTsKKwl1OCAqcGFkZGVkX21zZyA9IHhtYWxsb2Mo cGFkZGVkX21zZ2xlbik7CisJbGUxMjggaGFzaDEsIGhhc2gyOworCXNpemVfdCBpOworCisJZm9y IChpID0gMDsgaSA8IE5IX0tFWV9XT1JEUzsgaSsrKQorCQluaF9rZXlfd29yZHNbaV0gPSBnZXRf dW5hbGlnbmVkX2xlMzIoJm5oX2tleVtpICogc2l6ZW9mKHUzMildKTsKKworCS8qIEhhc2ggdHdl YWsgYW5kIG1lc3NhZ2UgbGVuZ3RoIHdpdGggZmlyc3QgUG9seTEzMDUga2V5ICovCisJcHV0X3Vu YWxpZ25lZF9sZTY0KCh1NjQpbXNnbGVuICogOCwgaGVhZGVyKTsKKwlwdXRfdW5hbGlnbmVkX2xl NjQoMCwgJmhlYWRlcltzaXplb2YoX19sZTY0KV0pOworCW1lbWNweSgmaGVhZGVyW1BPTFkxMzA1 X0JMT0NLX1NJWkVdLCBpdiwgQURJQU5UVU1fSVZfU0laRSk7CisJcG9seTEzMDUoaGVhZGVyX3Bv bHlfa2V5LCBoZWFkZXIsIHNpemVvZihoZWFkZXIpLCAmaGFzaDEpOworCisJLyogSGFzaCBOSCBo YXNoZXMgb2YgbWVzc2FnZSBibG9ja3MgdXNpbmcgc2Vjb25kIFBvbHkxMzA1IGtleSAqLworCS8q ICh1c2luZyBhIHN1cGVyIG5haXZlIHdheSBvZiBoYW5kbGluZyB0aGUgcGFkZGluZykgKi8KKwlt ZW1jcHkocGFkZGVkX21zZywgbXNnLCBtc2dsZW4pOworCW1lbXNldCgmcGFkZGVkX21zZ1ttc2ds ZW5dLCAwLCBwYWRkZWRfbXNnbGVuIC0gbXNnbGVuKTsKKwlmb3IgKGkgPSAwOyBpIDwgbnVtX25o X2Jsb2NrczsgaSsrKSB7CisJCW5oKG5oX2tleV93b3JkcywgJnBhZGRlZF9tc2dbaSAqIE5IX0JM T0NLX1NJWkVdLAorCQkgICBNSU4oTkhfQkxPQ0tfU0laRSwgcGFkZGVkX21zZ2xlbiAtIChpICog TkhfQkxPQ0tfU0laRSkpLAorCQkgICAmbmhfaGFzaGVzW2kgKiBOSF9IQVNIX1NJWkVdKTsKKwl9 CisJcG9seTEzMDUobXNnX3BvbHlfa2V5LCBuaF9oYXNoZXMsIG51bV9uaF9ibG9ja3MgKiBOSF9I QVNIX1NJWkUsICZoYXNoMik7CisKKwkvKiBBZGQgdGhlIHR3byBoYXNoZXMgdG9nZXRoZXIgdG8g Z2V0IHRoZSBmaW5hbCBoYXNoICovCisJbGUxMjhfYWRkKHJlc3VsdCwgJmhhc2gxLCAmaGFzaDIp OworCisJZnJlZShuaF9oYXNoZXMpOworCWZyZWUocGFkZGVkX21zZyk7Cit9CisKK3N0YXRpYyB2 b2lkIGFkaWFudHVtX2NyeXB0KGNvbnN0IHU4IGtleVtBRElBTlRVTV9LRVlfU0laRV0sCisJCQkg ICBjb25zdCB1OCBpdltBRElBTlRVTV9JVl9TSVpFXSwgY29uc3QgdTggKnNyYywKKwkJCSAgIHU4 ICpkc3QsIHNpemVfdCBuYnl0ZXMsIGJvb2wgZGVjcnlwdGluZykKK3sKKwl1OCBzdWJrZXlzW0FF U18yNTZfS0VZX1NJWkUgKyBBRElBTlRVTV9IQVNIX0tFWV9TSVpFXSA9IHsgMCB9OworCXN0cnVj dCBhZXNfa2V5IGFlc19rZXk7CisJdW5pb24geworCQl1OCBub25jZVtYQ0hBQ0hBX05PTkNFX1NJ WkVdOworCQlsZTEyOCBibG9jazsKKwl9IHUgPSB7IC5ub25jZSA9IHsgMSB9IH07CisJY29uc3Qg c2l6ZV90IGJ1bGtfbGVuID0gbmJ5dGVzIC0gc2l6ZW9mKHUuYmxvY2spOworCWxlMTI4IGhhc2g7 CisKKwlBU1NFUlQobmJ5dGVzID49IHNpemVvZih1LmJsb2NrKSk7CisKKwkvKiBEZXJpdmUgc3Vi a2V5cyAqLworCXhjaGFjaGExMihrZXksIHUubm9uY2UsIHN1YmtleXMsIHN1YmtleXMsIHNpemVv ZihzdWJrZXlzKSk7CisJYWVzX3NldGtleSgmYWVzX2tleSwgc3Via2V5cywgQUVTXzI1Nl9LRVlf U0laRSk7CisKKwkvKiBIYXNoIGxlZnQgcGFydCBhbmQgYWRkIHRvIHJpZ2h0IHBhcnQgKi8KKwlh ZGlhbnR1bV9oYXNoKCZzdWJrZXlzW0FFU18yNTZfS0VZX1NJWkVdLCBpdiwgc3JjLCBidWxrX2xl biwgJmhhc2gpOworCW1lbWNweSgmdS5ibG9jaywgJnNyY1tidWxrX2xlbl0sIHNpemVvZih1LmJs b2NrKSk7CisJbGUxMjhfYWRkKCZ1LmJsb2NrLCAmdS5ibG9jaywgJmhhc2gpOworCisJaWYgKCFk ZWNyeXB0aW5nKSAvKiBFbmNyeXB0IHJpZ2h0IHBhcnQgd2l0aCBibG9jayBjaXBoZXIgKi8KKwkJ YWVzX2VuY3J5cHQoJmFlc19rZXksIHUubm9uY2UsIHUubm9uY2UpOworCisJLyogRW5jcnlwdCBs ZWZ0IHBhcnQgd2l0aCBzdHJlYW0gY2lwaGVyLCB1c2luZyB0aGUgY29tcHV0ZWQgbm9uY2UgKi8K Kwl1Lm5vbmNlW3NpemVvZih1LmJsb2NrKV0gPSAxOworCXhjaGFjaGExMihrZXksIHUubm9uY2Us IHNyYywgZHN0LCBidWxrX2xlbik7CisKKwlpZiAoZGVjcnlwdGluZykgLyogRGVjcnlwdCByaWdo dCBwYXJ0IHdpdGggYmxvY2sgY2lwaGVyICovCisJCWFlc19kZWNyeXB0KCZhZXNfa2V5LCB1Lm5v bmNlLCB1Lm5vbmNlKTsKKworCS8qIEZpbmFsaXplIHJpZ2h0IHBhcnQgYnkgc3VidHJhY3Rpbmcg aGFzaCBvZiBsZWZ0IHBhcnQgKi8KKwlhZGlhbnR1bV9oYXNoKCZzdWJrZXlzW0FFU18yNTZfS0VZ X1NJWkVdLCBpdiwgZHN0LCBidWxrX2xlbiwgJmhhc2gpOworCWxlMTI4X3N1YigmdS5ibG9jaywg JnUuYmxvY2ssICZoYXNoKTsKKwltZW1jcHkoJmRzdFtidWxrX2xlbl0sICZ1LmJsb2NrLCBzaXpl b2YodS5ibG9jaykpOworfQorCitzdGF0aWMgdm9pZCBhZGlhbnR1bV9lbmNyeXB0KGNvbnN0IHU4 IGtleVtBRElBTlRVTV9LRVlfU0laRV0sCisJCQkgICAgIGNvbnN0IHU4IGl2W0FESUFOVFVNX0lW X1NJWkVdLAorCQkJICAgICBjb25zdCB1OCAqc3JjLCB1OCAqZHN0LCBzaXplX3QgbmJ5dGVzKQor eworCWFkaWFudHVtX2NyeXB0KGtleSwgaXYsIHNyYywgZHN0LCBuYnl0ZXMsIGZhbHNlKTsKK30K Kworc3RhdGljIHZvaWQgYWRpYW50dW1fZGVjcnlwdChjb25zdCB1OCBrZXlbQURJQU5UVU1fS0VZ X1NJWkVdLAorCQkJICAgICBjb25zdCB1OCBpdltBRElBTlRVTV9JVl9TSVpFXSwKKwkJCSAgICAg Y29uc3QgdTggKnNyYywgdTggKmRzdCwgc2l6ZV90IG5ieXRlcykKK3sKKwlhZGlhbnR1bV9jcnlw dChrZXksIGl2LCBzcmMsIGRzdCwgbmJ5dGVzLCB0cnVlKTsKK30KKworI2lmZGVmIEVOQUJMRV9B TEdfVEVTVFMKKyNpbmNsdWRlIDxsaW51eC9pZl9hbGcuaD4KKyNpbmNsdWRlIDxzeXMvc29ja2V0 Lmg+CisjZGVmaW5lIFNPTF9BTEcgMjc5CitzdGF0aWMgdm9pZCBhZl9hbGdfY3J5cHQoaW50IGFs Z2ZkLCBpbnQgb3AsIGNvbnN0IHU4ICprZXksIHNpemVfdCBrZXlsZW4sCisJCQkgY29uc3QgdTgg Kml2LCBzaXplX3QgaXZsZW4sCisJCQkgY29uc3QgdTggKnNyYywgdTggKmRzdCwgc2l6ZV90IGRh dGFsZW4pCit7CisJc2l6ZV90IGNvbnRyb2xsZW4gPSBDTVNHX1NQQUNFKHNpemVvZihpbnQpKSAr CisJCQkgICAgQ01TR19TUEFDRShzaXplb2Yoc3RydWN0IGFmX2FsZ19pdikgKyBpdmxlbik7CisJ dTggKmNvbnRyb2wgPSB4bWFsbG9jKGNvbnRyb2xsZW4pOworCXN0cnVjdCBpb3ZlYyBpb3YgPSB7 IC5pb3ZfYmFzZSA9ICh1OCAqKXNyYywgLmlvdl9sZW4gPSBkYXRhbGVuIH07CisJc3RydWN0IG1z Z2hkciBtc2cgPSB7CisJCS5tc2dfaW92ID0gJmlvdiwKKwkJLm1zZ19pb3ZsZW4gPSAxLAorCQku bXNnX2NvbnRyb2wgPSBjb250cm9sLAorCQkubXNnX2NvbnRyb2xsZW4gPSBjb250cm9sbGVuLAor CX07CisJc3RydWN0IGNtc2doZHIgKmNtc2c7CisJc3RydWN0IGFmX2FsZ19pdiAqYWxnaXY7CisJ aW50IHJlcWZkOworCisJbWVtc2V0KGNvbnRyb2wsIDAsIGNvbnRyb2xsZW4pOworCisJY21zZyA9 IENNU0dfRklSU1RIRFIoJm1zZyk7CisJY21zZy0+Y21zZ19sZW4gPSBDTVNHX0xFTihzaXplb2Yo aW50KSk7CisJY21zZy0+Y21zZ19sZXZlbCA9IFNPTF9BTEc7CisJY21zZy0+Y21zZ190eXBlID0g QUxHX1NFVF9PUDsKKwkqKGludCAqKUNNU0dfREFUQShjbXNnKSA9IG9wOworCisJY21zZyA9IENN U0dfTlhUSERSKCZtc2csIGNtc2cpOworCWNtc2ctPmNtc2dfbGVuID0gQ01TR19MRU4oc2l6ZW9m KHN0cnVjdCBhZl9hbGdfaXYpICsgaXZsZW4pOworCWNtc2ctPmNtc2dfbGV2ZWwgPSBTT0xfQUxH OworCWNtc2ctPmNtc2dfdHlwZSA9IEFMR19TRVRfSVY7CisJYWxnaXYgPSAoc3RydWN0IGFmX2Fs Z19pdiAqKUNNU0dfREFUQShjbXNnKTsKKwlhbGdpdi0+aXZsZW4gPSBpdmxlbjsKKwltZW1jcHko YWxnaXYtPml2LCBpdiwgaXZsZW4pOworCisJaWYgKHNldHNvY2tvcHQoYWxnZmQsIFNPTF9BTEcs IEFMR19TRVRfS0VZLCBrZXksIGtleWxlbikgIT0gMCkKKwkJZGllX2Vycm5vKCJjYW4ndCBzZXQg a2V5IG9uIEFGX0FMRyBzb2NrZXQiKTsKKworCXJlcWZkID0gYWNjZXB0KGFsZ2ZkLCBOVUxMLCBO VUxMKTsKKwlpZiAocmVxZmQgPCAwKQorCQlkaWVfZXJybm8oImNhbid0IGFjY2VwdCgpIEFGX0FM RyBzb2NrZXQiKTsKKwlpZiAoc2VuZG1zZyhyZXFmZCwgJm1zZywgMCkgIT0gZGF0YWxlbikKKwkJ ZGllX2Vycm5vKCJjYW4ndCBzZW5kbXNnKCkgQUZfQUxHIHJlcXVlc3Qgc29ja2V0Iik7CisJaWYg KHhyZWFkKHJlcWZkLCBkc3QsIGRhdGFsZW4pICE9IGRhdGFsZW4pCisJCWRpZSgic2hvcnQgcmVh ZCBmcm9tIEFGX0FMRyByZXF1ZXN0IHNvY2tldCIpOworCWNsb3NlKHJlcWZkKTsKKworCWZyZWUo Y29udHJvbCk7Cit9CisKK3N0YXRpYyB2b2lkIHRlc3RfYWRpYW50dW0odm9pZCkKK3sKKwlpbnQg YWxnZmQgPSBzb2NrZXQoQUZfQUxHLCBTT0NLX1NFUVBBQ0tFVCwgMCk7CisJc3RydWN0IHNvY2th ZGRyX2FsZyBhZGRyID0geworCQkuc2FsZ190eXBlID0gInNrY2lwaGVyIiwKKwkJLnNhbGdfbmFt ZSA9ICJhZGlhbnR1bSh4Y2hhY2hhMTIsYWVzKSIsCisJfTsKKwl1bnNpZ25lZCBsb25nIG51bV90 ZXN0cyA9IE5VTV9BTEdfVEVTVF9JVEVSQVRJT05TOworCisJaWYgKGFsZ2ZkIDwgMCkKKwkJZGll X2Vycm5vKCJjYW4ndCBjcmVhdGUgQUZfQUxHIHNvY2tldCIpOworCWlmIChiaW5kKGFsZ2ZkLCAo c3RydWN0IHNvY2thZGRyICopJmFkZHIsIHNpemVvZihhZGRyKSkgIT0gMCkKKwkJZGllX2Vycm5v KCJjYW4ndCBiaW5kIEFGX0FMRyBzb2NrZXQgdG8gQWRpYW50dW0gYWxnb3JpdGhtIik7CisKKwl3 aGlsZSAobnVtX3Rlc3RzLS0pIHsKKwkJdTgga2V5W0FESUFOVFVNX0tFWV9TSVpFXTsKKwkJdTgg aXZbQURJQU5UVU1fSVZfU0laRV07CisJCXU4IHB0ZXh0WzQwOTZdOworCQl1OCBhY3R1YWxfY3Rl eHRbc2l6ZW9mKHB0ZXh0KV07CisJCXU4IGV4cGVjdGVkX2N0ZXh0W3NpemVvZihwdGV4dCldOwor CQl1OCBkZWNyeXB0ZWRbc2l6ZW9mKHB0ZXh0KV07CisJCWNvbnN0IHNpemVfdCBkYXRhbGVuID0g MTYgKyAocmFuZCgpICUgKHNpemVvZihwdGV4dCkgLSAxNSkpOworCisJCXJhbmRfYnl0ZXMoa2V5 LCBzaXplb2Yoa2V5KSk7CisJCXJhbmRfYnl0ZXMoaXYsIHNpemVvZihpdikpOworCQlyYW5kX2J5 dGVzKHB0ZXh0LCBkYXRhbGVuKTsKKworCQlhZGlhbnR1bV9lbmNyeXB0KGtleSwgaXYsIHB0ZXh0 LCBhY3R1YWxfY3RleHQsIGRhdGFsZW4pOworCQlhZl9hbGdfY3J5cHQoYWxnZmQsIEFMR19PUF9F TkNSWVBULCBrZXksIHNpemVvZihrZXkpLAorCQkJICAgICBpdiwgc2l6ZW9mKGl2KSwgcHRleHQs IGV4cGVjdGVkX2N0ZXh0LCBkYXRhbGVuKTsKKwkJQVNTRVJUKG1lbWNtcChhY3R1YWxfY3RleHQs IGV4cGVjdGVkX2N0ZXh0LCBkYXRhbGVuKSA9PSAwKTsKKworCQlhZGlhbnR1bV9kZWNyeXB0KGtl eSwgaXYsIGFjdHVhbF9jdGV4dCwgZGVjcnlwdGVkLCBkYXRhbGVuKTsKKwkJQVNTRVJUKG1lbWNt cChwdGV4dCwgZGVjcnlwdGVkLCBkYXRhbGVuKSA9PSAwKTsKKwl9CisJY2xvc2UoYWxnZmQpOwor fQorI2VuZGlmIC8qIEVOQUJMRV9BTEdfVEVTVFMgKi8KKworLyotLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t KgorICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWFpbiBwcm9ncmFtICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgKgorICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KKworI2Rl ZmluZSBGSUxFX05PTkNFX1NJWkUJCTE2CisjZGVmaW5lIE1BWF9LRVlfU0laRQkJNjQKKworc3Rh dGljIGNvbnN0IHN0cnVjdCBmc2NyeXB0X2NpcGhlciB7CisJY29uc3QgY2hhciAqbmFtZTsKKwl2 b2lkICgqZW5jcnlwdCkoY29uc3QgdTggKmtleSwgY29uc3QgdTggKml2LCBjb25zdCB1OCAqc3Jj LAorCQkJdTggKmRzdCwgc2l6ZV90IG5ieXRlcyk7CisJdm9pZCAoKmRlY3J5cHQpKGNvbnN0IHU4 ICprZXksIGNvbnN0IHU4ICppdiwgY29uc3QgdTggKnNyYywKKwkJCXU4ICpkc3QsIHNpemVfdCBu Ynl0ZXMpOworCWludCBrZXlzaXplOworCWludCBtaW5faW5wdXRfc2l6ZTsKK30gZnNjcnlwdF9j aXBoZXJzW10gPSB7CisJeworCQkubmFtZSA9ICJBRVMtMjU2LVhUUyIsCisJCS5lbmNyeXB0ID0g YWVzXzI1Nl94dHNfZW5jcnlwdCwKKwkJLmRlY3J5cHQgPSBhZXNfMjU2X3h0c19kZWNyeXB0LAor CQkua2V5c2l6ZSA9IDIgKiBBRVNfMjU2X0tFWV9TSVpFLAorCQkubWluX2lucHV0X3NpemUgPSBB RVNfQkxPQ0tfU0laRSwKKwl9LCB7CisJCS5uYW1lID0gIkFFUy0yNTYtQ1RTLUNCQyIsCisJCS5l bmNyeXB0ID0gYWVzXzI1Nl9jdHNfY2JjX2VuY3J5cHQsCisJCS5kZWNyeXB0ID0gYWVzXzI1Nl9j dHNfY2JjX2RlY3J5cHQsCisJCS5rZXlzaXplID0gQUVTXzI1Nl9LRVlfU0laRSwKKwkJLm1pbl9p bnB1dF9zaXplID0gQUVTX0JMT0NLX1NJWkUsCisJfSwgeworCQkubmFtZSA9ICJBRVMtMTI4LUNC Qy1FU1NJViIsCisJCS5lbmNyeXB0ID0gYWVzXzEyOF9jYmNfZXNzaXZfZW5jcnlwdCwKKwkJLmRl Y3J5cHQgPSBhZXNfMTI4X2NiY19lc3Npdl9kZWNyeXB0LAorCQkua2V5c2l6ZSA9IEFFU18xMjhf S0VZX1NJWkUsCisJCS5taW5faW5wdXRfc2l6ZSA9IEFFU19CTE9DS19TSVpFLAorCX0sIHsKKwkJ Lm5hbWUgPSAiQUVTLTEyOC1DVFMtQ0JDIiwKKwkJLmVuY3J5cHQgPSBhZXNfMTI4X2N0c19jYmNf ZW5jcnlwdCwKKwkJLmRlY3J5cHQgPSBhZXNfMTI4X2N0c19jYmNfZGVjcnlwdCwKKwkJLmtleXNp emUgPSBBRVNfMTI4X0tFWV9TSVpFLAorCQkubWluX2lucHV0X3NpemUgPSBBRVNfQkxPQ0tfU0la RSwKKwl9LCB7CisJCS5uYW1lID0gIkFkaWFudHVtIiwKKwkJLmVuY3J5cHQgPSBhZGlhbnR1bV9l bmNyeXB0LAorCQkuZGVjcnlwdCA9IGFkaWFudHVtX2RlY3J5cHQsCisJCS5rZXlzaXplID0gQURJ QU5UVU1fS0VZX1NJWkUsCisJCS5taW5faW5wdXRfc2l6ZSA9IEFFU19CTE9DS19TSVpFLAorCX0K K307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgZnNjcnlwdF9jaXBoZXIgKmZpbmRfZnNjcnlwdF9j aXBoZXIoY29uc3QgY2hhciAqbmFtZSkKK3sKKwlzaXplX3QgaTsKKworCWZvciAoaSA9IDA7IGkg PCBBUlJBWV9TSVpFKGZzY3J5cHRfY2lwaGVycyk7IGkrKykgeworCQlpZiAoc3RyY21wKGZzY3J5 cHRfY2lwaGVyc1tpXS5uYW1lLCBuYW1lKSA9PSAwKQorCQkJcmV0dXJuICZmc2NyeXB0X2NpcGhl cnNbaV07CisJfQorCXJldHVybiBOVUxMOworfQorCitzdHJ1Y3QgZnNjcnlwdF9pdiB7CisJdW5p b24geworCQlfX2xlNjQgYmxvY2tfbnVtOworCQl1OCBieXRlc1szMl07CisJfTsKK307CisKK3N0 YXRpYyB2b2lkIGNyeXB0X2xvb3AoY29uc3Qgc3RydWN0IGZzY3J5cHRfY2lwaGVyICpjaXBoZXIs IGNvbnN0IHU4ICprZXksCisJCSAgICAgICBzdHJ1Y3QgZnNjcnlwdF9pdiAqaXYsIGJvb2wgZGVj cnlwdGluZywKKwkJICAgICAgIHNpemVfdCBibG9ja19zaXplLCBzaXplX3QgcGFkZGluZykKK3sK Kwl1OCAqYnVmID0geG1hbGxvYyhibG9ja19zaXplKTsKKwlzaXplX3QgcmVzOworCisJd2hpbGUg KChyZXMgPSB4cmVhZChTVERJTl9GSUxFTk8sIGJ1ZiwgYmxvY2tfc2l6ZSkpID4gMCkgeworCQlz aXplX3QgY3J5cHRfbGVuID0gYmxvY2tfc2l6ZTsKKworCQlpZiAocGFkZGluZyA+IDApCisJCQlj cnlwdF9sZW4gPSBNSU4oUk9VTkRfVVAocmVzLCBwYWRkaW5nKSwgY3J5cHRfbGVuKTsKKworCQlj cnlwdF9sZW4gPSBNQVgoY3J5cHRfbGVuLCBjaXBoZXItPm1pbl9pbnB1dF9zaXplKTsKKworCQlt ZW1zZXQoJmJ1ZltyZXNdLCAwLCBjcnlwdF9sZW4gLSByZXMpOworCisJCWlmIChkZWNyeXB0aW5n KQorCQkJY2lwaGVyLT5kZWNyeXB0KGtleSwgaXYtPmJ5dGVzLCBidWYsIGJ1ZiwgY3J5cHRfbGVu KTsKKwkJZWxzZQorCQkJY2lwaGVyLT5lbmNyeXB0KGtleSwgaXYtPmJ5dGVzLCBidWYsIGJ1Ziwg Y3J5cHRfbGVuKTsKKworCQlmdWxsX3dyaXRlKFNURE9VVF9GSUxFTk8sIGJ1ZiwgY3J5cHRfbGVu KTsKKworCQlpdi0+YmxvY2tfbnVtID0gY3B1X3RvX2xlNjQobGU2NF90b19jcHUoaXYtPmJsb2Nr X251bSkgKyAxKTsKKwl9CisJZnJlZShidWYpOworfQorCisvKiBUaGUgc3VwcG9ydGVkIGtleSBk ZXJpdmF0aW9uIGZ1bmN0aW9ucyAqLworZW51bSBrZGZfYWxnb3JpdGhtIHsKKwlLREZfTk9ORSwK KwlLREZfQUVTXzEyOF9FQ0IsCit9OworCitzdGF0aWMgZW51bSBrZGZfYWxnb3JpdGhtIHBhcnNl X2tkZl9hbGdvcml0aG0oY29uc3QgY2hhciAqYXJnKQoreworCWlmIChzdHJjbXAoYXJnLCAibm9u ZSIpID09IDApCisJCXJldHVybiBLREZfTk9ORTsKKwlpZiAoc3RyY21wKGFyZywgIkFFUy0xMjgt RUNCIikgPT0gMCkKKwkJcmV0dXJuIEtERl9BRVNfMTI4X0VDQjsKKwlkaWUoIlVua25vd24gS0RG OiAlcyIsIGFyZyk7Cit9CisKKy8qCisgKiBHZXQgdGhlIGtleSBhbmQgc3RhcnRpbmcgSVYgd2l0 aCB3aGljaCB0aGUgZW5jcnlwdGlvbiB3aWxsIGFjdHVhbGx5IGJlIGRvbmUuCisgKiBJZiBhIEtE RiB3YXMgc3BlY2lmaWVkLCBhIHN1YmtleSBpcyBkZXJpdmVkIGZyb20gdGhlIG1hc3RlciBrZXkg YW5kIGZpbGUKKyAqIG5vbmNlLiAgT3RoZXJ3aXNlLCB0aGUgbWFzdGVyIGtleSBpcyB1c2VkIGRp cmVjdGx5LgorICovCitzdGF0aWMgdm9pZCBnZXRfa2V5X2FuZF9pdihjb25zdCB1OCAqbWFzdGVy X2tleSwgc2l6ZV90IG1hc3Rlcl9rZXlfc2l6ZSwKKwkJCSAgIGVudW0ga2RmX2FsZ29yaXRobSBr ZGYsCisJCQkgICBjb25zdCB1OCBub25jZVtGSUxFX05PTkNFX1NJWkVdLAorCQkJICAgdTggKnJl YWxfa2V5LCBzaXplX3QgcmVhbF9rZXlfc2l6ZSwKKwkJCSAgIHN0cnVjdCBmc2NyeXB0X2l2ICpp dikKK3sKKwlib29sIG5vbmNlX2luX2l2ID0gZmFsc2U7CisJc3RydWN0IGFlc19rZXkgYWVzX2tl eTsKKwlzaXplX3QgaTsKKworCUFTU0VSVChyZWFsX2tleV9zaXplIDw9IG1hc3Rlcl9rZXlfc2l6 ZSk7CisKKwltZW1zZXQoaXYsIDAsIHNpemVvZigqaXYpKTsKKworCXN3aXRjaCAoa2RmKSB7CisJ Y2FzZSBLREZfTk9ORToKKwkJbWVtY3B5KHJlYWxfa2V5LCBtYXN0ZXJfa2V5LCByZWFsX2tleV9z aXplKTsKKwkJbm9uY2VfaW5faXYgPSB0cnVlOworCQlicmVhazsKKwljYXNlIEtERl9BRVNfMTI4 X0VDQjoKKwkJaWYgKG5vbmNlID09IE5VTEwpCisJCQlkaWUoIi0tZmlsZS1ub25jZSBpcyByZXF1 aXJlZCB3aXRoIC0ta2RmPUFFUy0xMjgtRUNCIik7CisJCVNUQVRJQ19BU1NFUlQoRklMRV9OT05D RV9TSVpFID09IEFFU18xMjhfS0VZX1NJWkUpOworCQlBU1NFUlQocmVhbF9rZXlfc2l6ZSAlIEFF U19CTE9DS19TSVpFID09IDApOworCQlhZXNfc2V0a2V5KCZhZXNfa2V5LCBub25jZSwgQUVTXzEy OF9LRVlfU0laRSk7CisJCWZvciAoaSA9IDA7IGkgPCByZWFsX2tleV9zaXplOyBpICs9IEFFU19C TE9DS19TSVpFKQorCQkJYWVzX2VuY3J5cHQoJmFlc19rZXksICZtYXN0ZXJfa2V5W2ldLCAmcmVh bF9rZXlbaV0pOworCQlicmVhazsKKwlkZWZhdWx0OgorCQlBU1NFUlQoMCk7CisJfQorCisJaWYg KG5vbmNlX2luX2l2ICYmIG5vbmNlICE9IE5VTEwpCisJCW1lbWNweSgmaXYtPmJ5dGVzWzhdLCBu b25jZSwgRklMRV9OT05DRV9TSVpFKTsKK30KKworZW51bSB7CisJT1BUX0JMT0NLX1NJWkUsCisJ T1BUX0RFQ1JZUFQsCisJT1BUX0ZJTEVfTk9OQ0UsCisJT1BUX0hFTFAsCisJT1BUX0tERiwKKwlP UFRfUEFERElORywKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgb3B0aW9uIGxvbmdvcHRzW10g PSB7CisJeyAiYmxvY2stc2l6ZSIsICAgICAgcmVxdWlyZWRfYXJndW1lbnQsIE5VTEwsIE9QVF9C TE9DS19TSVpFIH0sCisJeyAiZGVjcnlwdCIsICAgICAgICAgbm9fYXJndW1lbnQsICAgICAgIE5V TEwsIE9QVF9ERUNSWVBUIH0sCisJeyAiZmlsZS1ub25jZSIsICAgICAgcmVxdWlyZWRfYXJndW1l bnQsIE5VTEwsIE9QVF9GSUxFX05PTkNFIH0sCisJeyAiaGVscCIsICAgICAgICAgICAgbm9fYXJn dW1lbnQsICAgICAgIE5VTEwsIE9QVF9IRUxQIH0sCisJeyAia2RmIiwgICAgICAgICAgICAgcmVx dWlyZWRfYXJndW1lbnQsIE5VTEwsIE9QVF9LREYgfSwKKwl7ICJwYWRkaW5nIiwgICAgICAgICBy ZXF1aXJlZF9hcmd1bWVudCwgTlVMTCwgT1BUX1BBRERJTkcgfSwKKwl7IE5VTEwsIDAsIE5VTEws IDAgfSwKK307CisKK2ludCBtYWluKGludCBhcmdjLCBjaGFyICphcmd2W10pCit7CisJc2l6ZV90 IGJsb2NrX3NpemUgPSA0MDk2OworCWJvb2wgZGVjcnlwdGluZyA9IGZhbHNlOworCXU4IF9maWxl X25vbmNlW0ZJTEVfTk9OQ0VfU0laRV07CisJdTggKmZpbGVfbm9uY2UgPSBOVUxMOworCWVudW0g a2RmX2FsZ29yaXRobSBrZGYgPSBLREZfTk9ORTsKKwlzaXplX3QgcGFkZGluZyA9IDA7CisJY29u c3Qgc3RydWN0IGZzY3J5cHRfY2lwaGVyICpjaXBoZXI7CisJdTggbWFzdGVyX2tleVtNQVhfS0VZ X1NJWkVdOworCWludCBtYXN0ZXJfa2V5X3NpemU7CisJdTggcmVhbF9rZXlbTUFYX0tFWV9TSVpF XTsKKwlzdHJ1Y3QgZnNjcnlwdF9pdiBpdjsKKwljaGFyICp0bXA7CisJaW50IGM7CisKKwlhZXNf aW5pdCgpOworCisjaWZkZWYgRU5BQkxFX0FMR19URVNUUworCXRlc3RfYWVzKCk7CisJdGVzdF9z aGEyKCk7CisJdGVzdF9hZXNfMjU2X3h0cygpOworCXRlc3RfYWVzXzI1Nl9jdHNfY2JjKCk7CisJ dGVzdF9hZGlhbnR1bSgpOworI2VuZGlmCisKKwl3aGlsZSAoKGMgPSBnZXRvcHRfbG9uZyhhcmdj LCBhcmd2LCAiIiwgbG9uZ29wdHMsIE5VTEwpKSAhPSAtMSkgeworCQlzd2l0Y2ggKGMpIHsKKwkJ Y2FzZSBPUFRfQkxPQ0tfU0laRToKKwkJCWJsb2NrX3NpemUgPSBzdHJ0b3VsKG9wdGFyZywgJnRt cCwgMTApOworCQkJaWYgKGJsb2NrX3NpemUgPD0gMCB8fCAqdG1wKQorCQkJCWRpZSgiSW52YWxp ZCBibG9jayBzaXplOiAlcyIsIG9wdGFyZyk7CisJCQlicmVhazsKKwkJY2FzZSBPUFRfREVDUllQ VDoKKwkJCWRlY3J5cHRpbmcgPSB0cnVlOworCQkJYnJlYWs7CisJCWNhc2UgT1BUX0ZJTEVfTk9O Q0U6CisJCQlpZiAoaGV4MmJpbihvcHRhcmcsIF9maWxlX25vbmNlLCBGSUxFX05PTkNFX1NJWkUp ICE9CisJCQkgICAgRklMRV9OT05DRV9TSVpFKQorCQkJCWRpZSgiSW52YWxpZCBmaWxlIG5vbmNl OiAlcyIsIG9wdGFyZyk7CisJCQlmaWxlX25vbmNlID0gX2ZpbGVfbm9uY2U7CisJCQlicmVhazsK KwkJY2FzZSBPUFRfSEVMUDoKKwkJCXVzYWdlKHN0ZG91dCk7CisJCQlyZXR1cm4gMDsKKwkJY2Fz ZSBPUFRfS0RGOgorCQkJa2RmID0gcGFyc2Vfa2RmX2FsZ29yaXRobShvcHRhcmcpOworCQkJYnJl YWs7CisJCWNhc2UgT1BUX1BBRERJTkc6CisJCQlwYWRkaW5nID0gc3RydG91bChvcHRhcmcsICZ0 bXAsIDEwKTsKKwkJCWlmIChwYWRkaW5nIDw9IDAgfHwgKnRtcCB8fCAhaXNfcG93ZXJfb2ZfMihw YWRkaW5nKSB8fAorCQkJICAgIHBhZGRpbmcgPiBJTlRfTUFYKQorCQkJCWRpZSgiSW52YWxpZCBw YWRkaW5nIGFtb3VudDogJXMiLCBvcHRhcmcpOworCQkJYnJlYWs7CisJCWRlZmF1bHQ6CisJCQl1 c2FnZShzdGRlcnIpOworCQkJcmV0dXJuIDI7CisJCX0KKwl9CisJYXJnYyAtPSBvcHRpbmQ7CisJ YXJndiArPSBvcHRpbmQ7CisKKwlpZiAoYXJnYyAhPSAyKSB7CisJCXVzYWdlKHN0ZGVycik7CisJ CXJldHVybiAyOworCX0KKworCWNpcGhlciA9IGZpbmRfZnNjcnlwdF9jaXBoZXIoYXJndlswXSk7 CisJaWYgKGNpcGhlciA9PSBOVUxMKQorCQlkaWUoIlVua25vd24gY2lwaGVyOiAlcyIsIGFyZ3Zb MF0pOworCisJaWYgKGJsb2NrX3NpemUgPCBjaXBoZXItPm1pbl9pbnB1dF9zaXplKQorCQlkaWUo IkJsb2NrIHNpemUgb2YgJXp1IGJ5dGVzIGlzIHRvbyBzbWFsbCBmb3IgY2lwaGVyICVzIiwKKwkJ ICAgIGJsb2NrX3NpemUsIGNpcGhlci0+bmFtZSk7CisKKwltYXN0ZXJfa2V5X3NpemUgPSBoZXgy YmluKGFyZ3ZbMV0sIG1hc3Rlcl9rZXksIE1BWF9LRVlfU0laRSk7CisJaWYgKG1hc3Rlcl9rZXlf c2l6ZSA8IDApCisJCWRpZSgiSW52YWxpZCBtYXN0ZXJfa2V5OiAlcyIsIGFyZ3ZbMV0pOworCWlm IChtYXN0ZXJfa2V5X3NpemUgPCBjaXBoZXItPmtleXNpemUpCisJCWRpZSgiTWFzdGVyIGtleSBp cyB0b28gc2hvcnQgZm9yIGNpcGhlciAlcyIsIGNpcGhlci0+bmFtZSk7CisKKwlnZXRfa2V5X2Fu ZF9pdihtYXN0ZXJfa2V5LCBtYXN0ZXJfa2V5X3NpemUsIGtkZiwgZmlsZV9ub25jZSwKKwkJICAg ICAgIHJlYWxfa2V5LCBjaXBoZXItPmtleXNpemUsICZpdik7CisKKwljcnlwdF9sb29wKGNpcGhl ciwgcmVhbF9rZXksICZpdiwgZGVjcnlwdGluZywgYmxvY2tfc2l6ZSwgcGFkZGluZyk7CisJcmV0 dXJuIDA7Cit9Ci0tIAoyLjIxLjAuNTkzLmc1MTFlYzM0NWUxOC1nb29nCgoKCl9fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCkxpbnV4LWYyZnMtZGV2ZWwgbWFp bGluZyBsaXN0CkxpbnV4LWYyZnMtZGV2ZWxAbGlzdHMuc291cmNlZm9yZ2UubmV0Cmh0dHBzOi8v bGlzdHMuc291cmNlZm9yZ2UubmV0L2xpc3RzL2xpc3RpbmZvL2xpbnV4LWYyZnMtZGV2ZWwK