From 64edccea594cf7cb1e2975fdf44531e3377b32db Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 14 Dec 2025 10:17:11 -0800 Subject: [PATCH 01/53] lib/crypto: Add ML-DSA verification support Add support for verifying ML-DSA signatures. ML-DSA (Module-Lattice-Based Digital Signature Algorithm) is specified in FIPS 204 and is the standard version of Dilithium. Unlike RSA and elliptic-curve cryptography, ML-DSA is believed to be secure even against adversaries in possession of a large-scale quantum computer. Compared to the earlier patch (https://lore.kernel.org/r/20251117145606.2155773-3-dhowells@redhat.com/) that was based on "leancrypto", this implementation: - Is about 700 lines of source code instead of 4800. - Generates about 4 KB of object code instead of 28 KB. - Uses 9-13 KB of memory to verify a signature instead of 31-84 KB. - Is at least about the same speed, with a microbenchmark showing 3-5% improvements on one x86_64 CPU and -1% to 1% changes on another. When memory is a bottleneck, it's likely much faster. - Correctly implements the RejNTTPoly step of the algorithm. The API just consists of a single function mldsa_verify(), supporting pure ML-DSA with any standard parameter set (ML-DSA-44, ML-DSA-65, or ML-DSA-87) as selected by an enum. That's all that's actually needed. The following four potential features are unneeded and aren't included. However, any that ever become needed could fairly easily be added later, as they only affect how the message representative mu is calculated: - Nonempty context strings - Incremental message hashing - HashML-DSA - External mu Signing support would, of course, be a larger and more complex addition. However, the kernel doesn't, and shouldn't, need ML-DSA signing support. Note that mldsa_verify() allocates memory, so it can sleep and can fail with ENOMEM. Unfortunately we don't have much choice about that, since ML-DSA needs a lot of memory. At least callers have to check for errors anyway, since the signature could be invalid. Note that verification doesn't require constant-time code, and in fact some steps are inherently variable-time. I've used constant-time patterns in some places anyway, but technically they're not needed. Reviewed-by: David Howells Tested-by: David Howells Link: https://lore.kernel.org/r/20251214181712.29132-2-ebiggers@kernel.org Signed-off-by: Eric Biggers --- include/crypto/mldsa.h | 60 ++++ lib/crypto/Kconfig | 7 + lib/crypto/Makefile | 5 + lib/crypto/mldsa.c | 652 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 724 insertions(+) create mode 100644 include/crypto/mldsa.h create mode 100644 lib/crypto/mldsa.c diff --git a/include/crypto/mldsa.h b/include/crypto/mldsa.h new file mode 100644 index 000000000000..cf30aef29970 --- /dev/null +++ b/include/crypto/mldsa.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Support for verifying ML-DSA signatures + * + * Copyright 2025 Google LLC + */ +#ifndef _CRYPTO_MLDSA_H +#define _CRYPTO_MLDSA_H + +#include + +/* Identifier for an ML-DSA parameter set */ +enum mldsa_alg { + MLDSA44, /* ML-DSA-44 */ + MLDSA65, /* ML-DSA-65 */ + MLDSA87, /* ML-DSA-87 */ +}; + +/* Lengths of ML-DSA public keys and signatures in bytes */ +#define MLDSA44_PUBLIC_KEY_SIZE 1312 +#define MLDSA65_PUBLIC_KEY_SIZE 1952 +#define MLDSA87_PUBLIC_KEY_SIZE 2592 +#define MLDSA44_SIGNATURE_SIZE 2420 +#define MLDSA65_SIGNATURE_SIZE 3309 +#define MLDSA87_SIGNATURE_SIZE 4627 + +/** + * mldsa_verify() - Verify an ML-DSA signature + * @alg: The ML-DSA parameter set to use + * @sig: The signature + * @sig_len: Length of the signature in bytes. Should match the + * MLDSA*_SIGNATURE_SIZE constant associated with @alg, + * otherwise -EBADMSG will be returned. + * @msg: The message + * @msg_len: Length of the message in bytes + * @pk: The public key + * @pk_len: Length of the public key in bytes. Should match the + * MLDSA*_PUBLIC_KEY_SIZE constant associated with @alg, + * otherwise -EBADMSG will be returned. + * + * This verifies a signature using pure ML-DSA with the specified parameter set. + * The context string is assumed to be empty. + * + * Context: Might sleep + * + * Return: + * * 0 if the signature is valid + * * -EBADMSG if the signature and/or public key is malformed + * * -EKEYREJECTED if the signature is invalid but otherwise well-formed + * * -ENOMEM if out of memory so the validity of the signature is unknown + */ +int mldsa_verify(enum mldsa_alg alg, const u8 *sig, size_t sig_len, + const u8 *msg, size_t msg_len, const u8 *pk, size_t pk_len); + +#if IS_ENABLED(CONFIG_CRYPTO_LIB_MLDSA_KUNIT_TEST) +/* Internal function, exposed only for unit testing */ +s32 mldsa_use_hint(u8 h, s32 r, s32 gamma2); +#endif + +#endif /* _CRYPTO_MLDSA_H */ diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 6871a41e5069..ee6ab129d0cf 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -101,6 +101,13 @@ config CRYPTO_LIB_MD5_ARCH default y if PPC default y if SPARC64 +config CRYPTO_LIB_MLDSA + tristate + select CRYPTO_LIB_SHA3 + help + The ML-DSA library functions. Select this if your module uses any of + the functions from . + config CRYPTO_LIB_POLY1305 tristate help diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 330ab65b29c4..a0578105266f 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -126,6 +126,11 @@ endif # CONFIG_CRYPTO_LIB_MD5_ARCH ################################################################################ +obj-$(CONFIG_CRYPTO_LIB_MLDSA) += libmldsa.o +libmldsa-y := mldsa.o + +################################################################################ + obj-$(CONFIG_CRYPTO_LIB_POLY1305) += libpoly1305.o libpoly1305-y := poly1305.o ifeq ($(CONFIG_ARCH_SUPPORTS_INT128),y) diff --git a/lib/crypto/mldsa.c b/lib/crypto/mldsa.c new file mode 100644 index 000000000000..853cf225c133 --- /dev/null +++ b/lib/crypto/mldsa.c @@ -0,0 +1,652 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Support for verifying ML-DSA signatures + * + * Copyright 2025 Google LLC + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define Q 8380417 /* The prime q = 2^23 - 2^13 + 1 */ +#define QINV_MOD_2_32 58728449 /* Multiplicative inverse of q mod 2^32 */ +#define N 256 /* Number of components per ring element */ +#define D 13 /* Number of bits dropped from the public key vector t */ +#define RHO_LEN 32 /* Length of the public random seed in bytes */ +#define MAX_W1_ENCODED_LEN 192 /* Max encoded length of one element of w'_1 */ + +/* + * The zetas array in Montgomery form, i.e. with extra factor of 2^32. + * Reference: FIPS 204 Section 7.5 "NTT and NTT^-1" + * Generated by the following Python code: + * q=8380417; [a%q - q*(a%q > q//2) for a in [1753**(int(f'{i:08b}'[::-1], 2)) << 32 for i in range(256)]] + */ +static const s32 zetas_times_2_32[N] = { + -4186625, 25847, -2608894, -518909, 237124, -777960, -876248, + 466468, 1826347, 2353451, -359251, -2091905, 3119733, -2884855, + 3111497, 2680103, 2725464, 1024112, -1079900, 3585928, -549488, + -1119584, 2619752, -2108549, -2118186, -3859737, -1399561, -3277672, + 1757237, -19422, 4010497, 280005, 2706023, 95776, 3077325, + 3530437, -1661693, -3592148, -2537516, 3915439, -3861115, -3043716, + 3574422, -2867647, 3539968, -300467, 2348700, -539299, -1699267, + -1643818, 3505694, -3821735, 3507263, -2140649, -1600420, 3699596, + 811944, 531354, 954230, 3881043, 3900724, -2556880, 2071892, + -2797779, -3930395, -1528703, -3677745, -3041255, -1452451, 3475950, + 2176455, -1585221, -1257611, 1939314, -4083598, -1000202, -3190144, + -3157330, -3632928, 126922, 3412210, -983419, 2147896, 2715295, + -2967645, -3693493, -411027, -2477047, -671102, -1228525, -22981, + -1308169, -381987, 1349076, 1852771, -1430430, -3343383, 264944, + 508951, 3097992, 44288, -1100098, 904516, 3958618, -3724342, + -8578, 1653064, -3249728, 2389356, -210977, 759969, -1316856, + 189548, -3553272, 3159746, -1851402, -2409325, -177440, 1315589, + 1341330, 1285669, -1584928, -812732, -1439742, -3019102, -3881060, + -3628969, 3839961, 2091667, 3407706, 2316500, 3817976, -3342478, + 2244091, -2446433, -3562462, 266997, 2434439, -1235728, 3513181, + -3520352, -3759364, -1197226, -3193378, 900702, 1859098, 909542, + 819034, 495491, -1613174, -43260, -522500, -655327, -3122442, + 2031748, 3207046, -3556995, -525098, -768622, -3595838, 342297, + 286988, -2437823, 4108315, 3437287, -3342277, 1735879, 203044, + 2842341, 2691481, -2590150, 1265009, 4055324, 1247620, 2486353, + 1595974, -3767016, 1250494, 2635921, -3548272, -2994039, 1869119, + 1903435, -1050970, -1333058, 1237275, -3318210, -1430225, -451100, + 1312455, 3306115, -1962642, -1279661, 1917081, -2546312, -1374803, + 1500165, 777191, 2235880, 3406031, -542412, -2831860, -1671176, + -1846953, -2584293, -3724270, 594136, -3776993, -2013608, 2432395, + 2454455, -164721, 1957272, 3369112, 185531, -1207385, -3183426, + 162844, 1616392, 3014001, 810149, 1652634, -3694233, -1799107, + -3038916, 3523897, 3866901, 269760, 2213111, -975884, 1717735, + 472078, -426683, 1723600, -1803090, 1910376, -1667432, -1104333, + -260646, -3833893, -2939036, -2235985, -420899, -2286327, 183443, + -976891, 1612842, -3545687, -554416, 3919660, -48306, -1362209, + 3937738, 1400424, -846154, 1976782 +}; + +/* Reference: FIPS 204 Section 4 "Parameter Sets" */ +static const struct mldsa_parameter_set { + u8 k; /* num rows in the matrix A */ + u8 l; /* num columns in the matrix A */ + u8 ctilde_len; /* length of commitment hash ctilde in bytes; lambda/4 */ + u8 omega; /* max num of 1's in the hint vector h */ + u8 tau; /* num of +-1's in challenge c */ + u8 beta; /* tau times eta */ + u16 pk_len; /* length of public keys in bytes */ + u16 sig_len; /* length of signatures in bytes */ + s32 gamma1; /* coefficient range of y */ +} mldsa_parameter_sets[] = { + [MLDSA44] = { + .k = 4, + .l = 4, + .ctilde_len = 32, + .omega = 80, + .tau = 39, + .beta = 78, + .pk_len = MLDSA44_PUBLIC_KEY_SIZE, + .sig_len = MLDSA44_SIGNATURE_SIZE, + .gamma1 = 1 << 17, + }, + [MLDSA65] = { + .k = 6, + .l = 5, + .ctilde_len = 48, + .omega = 55, + .tau = 49, + .beta = 196, + .pk_len = MLDSA65_PUBLIC_KEY_SIZE, + .sig_len = MLDSA65_SIGNATURE_SIZE, + .gamma1 = 1 << 19, + }, + [MLDSA87] = { + .k = 8, + .l = 7, + .ctilde_len = 64, + .omega = 75, + .tau = 60, + .beta = 120, + .pk_len = MLDSA87_PUBLIC_KEY_SIZE, + .sig_len = MLDSA87_SIGNATURE_SIZE, + .gamma1 = 1 << 19, + }, +}; + +/* + * An element of the ring R_q (normal form) or the ring T_q (NTT form). It + * consists of N integers mod q: either the polynomial coefficients of the R_q + * element or the components of the T_q element. In either case, whether they + * are fully reduced to [0, q - 1] varies in the different parts of the code. + */ +struct mldsa_ring_elem { + s32 x[N]; +}; + +struct mldsa_verification_workspace { + /* SHAKE context for computing c, mu, and ctildeprime */ + struct shake_ctx shake; + /* The fields in this union are used in their order of declaration. */ + union { + /* The hash of the public key */ + u8 tr[64]; + /* The message representative mu */ + u8 mu[64]; + /* Temporary space for rej_ntt_poly() */ + u8 block[SHAKE128_BLOCK_SIZE + 1]; + /* Encoded element of w'_1 */ + u8 w1_encoded[MAX_W1_ENCODED_LEN]; + /* The commitment hash. Real length is params->ctilde_len */ + u8 ctildeprime[64]; + }; + /* SHAKE context for generating elements of the matrix A */ + struct shake_ctx a_shake; + /* + * An element of the matrix A generated from the public seed, or an + * element of the vector t_1 decoded from the public key and pre-scaled + * by 2^d. Both are in NTT form. To reduce memory usage, we generate + * or decode these elements only as needed. + */ + union { + struct mldsa_ring_elem a; + struct mldsa_ring_elem t1_scaled; + }; + /* The challenge c, generated from ctilde */ + struct mldsa_ring_elem c; + /* A temporary element used during calculations */ + struct mldsa_ring_elem tmp; + + /* The following fields are variable-length: */ + + /* The signer's response vector */ + struct mldsa_ring_elem z[/* l */]; + + /* The signer's hint vector */ + /* u8 h[k * N]; */ +}; + +/* + * Compute a * b * 2^-32 mod q. a * b must be in the range [-2^31 * q, 2^31 * q + * - 1] before reduction. The return value is in the range [-q + 1, q - 1]. + * + * To reduce mod q efficiently, this uses Montgomery reduction with R=2^32. + * That's where the factor of 2^-32 comes from. The caller must include a + * factor of 2^32 at some point to compensate for that. + * + * To keep the input and output ranges very close to symmetric, this + * specifically does a "signed" Montgomery reduction. That is, when computing + * d = c * q^-1 mod 2^32, this chooses a representative in [S32_MIN, S32_MAX] + * rather than [0, U32_MAX], i.e. s32 rather than u32. This matters in the + * wider multiplication d * Q when d keeps its value via sign extension. + * + * Reference: FIPS 204 Appendix A "Montgomery Multiplication". But, it doesn't + * explain it properly: it has an off-by-one error in the upper end of the input + * range, it doesn't clarify that the signed version should be used, and it + * gives an unnecessarily large output range. A better citation is perhaps the + * Dilithium reference code, which functionally matches the below code and + * merely has the (benign) off-by-one error in its documentation. + */ +static inline s32 Zq_mult(s32 a, s32 b) +{ + /* Compute the unreduced product c. */ + s64 c = (s64)a * b; + + /* + * Compute d = c * q^-1 mod 2^32. Generate a signed result, as + * explained above, but do the actual multiplication using an unsigned + * type to avoid signed integer overflow which is undefined behavior. + */ + s32 d = (u32)c * QINV_MOD_2_32; + + /* + * Compute e = c - d * q. This makes the low 32 bits zero, since + * c - (c * q^-1) * q mod 2^32 + * = c - c * (q^-1 * q) mod 2^32 + * = c - c * 1 mod 2^32 + * = c - c mod 2^32 + * = 0 mod 2^32 + */ + s64 e = c - (s64)d * Q; + + /* Finally, return e * 2^-32. */ + return e >> 32; +} + +/* + * Convert @w to its number-theoretically-transformed representation in-place. + * Reference: FIPS 204 Algorithm 41, NTT + * + * To prevent intermediate overflows, all input coefficients must have absolute + * value < q. All output components have absolute value < 9*q. + */ +static void ntt(struct mldsa_ring_elem *w) +{ + int m = 0; /* index in zetas_times_2_32 */ + + for (int len = 128; len >= 1; len /= 2) { + for (int start = 0; start < 256; start += 2 * len) { + const s32 z = zetas_times_2_32[++m]; + + for (int j = start; j < start + len; j++) { + s32 t = Zq_mult(z, w->x[j + len]); + + w->x[j + len] = w->x[j] - t; + w->x[j] += t; + } + } + } +} + +/* + * Convert @w from its number-theoretically-transformed representation in-place. + * Reference: FIPS 204 Algorithm 42, NTT^-1 + * + * This also multiplies the coefficients by 2^32, undoing an extra factor of + * 2^-32 introduced earlier, and reduces the coefficients to [0, q - 1]. + */ +static void invntt_and_mul_2_32(struct mldsa_ring_elem *w) +{ + int m = 256; /* index in zetas_times_2_32 */ + + /* Prevent intermediate overflows. */ + for (int j = 0; j < 256; j++) + w->x[j] %= Q; + + for (int len = 1; len < 256; len *= 2) { + for (int start = 0; start < 256; start += 2 * len) { + const s32 z = -zetas_times_2_32[--m]; + + for (int j = start; j < start + len; j++) { + s32 t = w->x[j]; + + w->x[j] = t + w->x[j + len]; + w->x[j + len] = Zq_mult(z, t - w->x[j + len]); + } + } + } + /* + * Multiply by 2^32 * 256^-1. 2^32 cancels the factor of 2^-32 from + * earlier Montgomery multiplications. 256^-1 is for NTT^-1. This + * itself uses Montgomery multiplication, so *another* 2^32 is needed. + * Thus the actual multiplicand is 2^32 * 2^32 * 256^-1 mod q = 41978. + * + * Finally, also reduce from [-q + 1, q - 1] to [0, q - 1]. + */ + for (int j = 0; j < 256; j++) { + w->x[j] = Zq_mult(w->x[j], 41978); + w->x[j] += (w->x[j] >> 31) & Q; + } +} + +/* + * Decode an element of t_1, i.e. the high d bits of t = A*s_1 + s_2. + * Reference: FIPS 204 Algorithm 23, pkDecode. + * Also multiply it by 2^d and convert it to NTT form. + */ +static const u8 *decode_t1_elem(struct mldsa_ring_elem *out, + const u8 *t1_encoded) +{ + for (int j = 0; j < N; j += 4, t1_encoded += 5) { + u32 v = get_unaligned_le32(t1_encoded); + + out->x[j + 0] = ((v >> 0) & 0x3ff) << D; + out->x[j + 1] = ((v >> 10) & 0x3ff) << D; + out->x[j + 2] = ((v >> 20) & 0x3ff) << D; + out->x[j + 3] = ((v >> 30) | (t1_encoded[4] << 2)) << D; + static_assert(0x3ff << D < Q); /* All coefficients < q. */ + } + ntt(out); + return t1_encoded; /* Return updated pointer. */ +} + +/* + * Decode the signer's response vector 'z' from the signature. + * Reference: FIPS 204 Algorithm 27, sigDecode. + * + * This also validates that the coefficients of z are in range, corresponding + * the infinity norm check at the end of Algorithm 8, ML-DSA.Verify_internal. + * + * Finally, this also converts z to NTT form. + */ +static bool decode_z(struct mldsa_ring_elem z[/* l */], int l, s32 gamma1, + int beta, const u8 **sig_ptr) +{ + const u8 *sig = *sig_ptr; + + for (int i = 0; i < l; i++) { + if (l == 4) { /* ML-DSA-44? */ + /* 18-bit coefficients: decode 4 from 9 bytes. */ + for (int j = 0; j < N; j += 4, sig += 9) { + u64 v = get_unaligned_le64(sig); + + z[i].x[j + 0] = (v >> 0) & 0x3ffff; + z[i].x[j + 1] = (v >> 18) & 0x3ffff; + z[i].x[j + 2] = (v >> 36) & 0x3ffff; + z[i].x[j + 3] = (v >> 54) | (sig[8] << 10); + } + } else { + /* 20-bit coefficients: decode 4 from 10 bytes. */ + for (int j = 0; j < N; j += 4, sig += 10) { + u64 v = get_unaligned_le64(sig); + + z[i].x[j + 0] = (v >> 0) & 0xfffff; + z[i].x[j + 1] = (v >> 20) & 0xfffff; + z[i].x[j + 2] = (v >> 40) & 0xfffff; + z[i].x[j + 3] = + (v >> 60) | + (get_unaligned_le16(&sig[8]) << 4); + } + } + for (int j = 0; j < N; j++) { + z[i].x[j] = gamma1 - z[i].x[j]; + if (z[i].x[j] <= -(gamma1 - beta) || + z[i].x[j] >= gamma1 - beta) + return false; + } + ntt(&z[i]); + } + *sig_ptr = sig; /* Return updated pointer. */ + return true; +} + +/* + * Decode the signer's hint vector 'h' from the signature. + * Reference: FIPS 204 Algorithm 21, HintBitUnpack + * + * Note that there are several ways in which the hint vector can be malformed. + */ +static bool decode_hint_vector(u8 h[/* k * N */], int k, int omega, const u8 *y) +{ + int index = 0; + + memset(h, 0, k * N); + for (int i = 0; i < k; i++) { + int count = y[omega + i]; /* num 1's in elems 0 through i */ + int prev = -1; + + /* Cumulative count mustn't decrease or exceed omega. */ + if (count < index || count > omega) + return false; + for (; index < count; index++) { + if (prev >= y[index]) /* Coefficients out of order? */ + return false; + prev = y[index]; + h[i * N + y[index]] = 1; + } + } + return mem_is_zero(&y[index], omega - index); +} + +/* + * Expand @seed into an element of R_q @c with coefficients in {-1, 0, 1}, + * exactly @tau of them nonzero. Reference: FIPS 204 Algorithm 29, SampleInBall + */ +static void sample_in_ball(struct mldsa_ring_elem *c, const u8 *seed, + size_t seed_len, int tau, struct shake_ctx *shake) +{ + u64 signs; + u8 j; + + shake256_init(shake); + shake_update(shake, seed, seed_len); + shake_squeeze(shake, (u8 *)&signs, sizeof(signs)); + le64_to_cpus(&signs); + *c = (struct mldsa_ring_elem){}; + for (int i = N - tau; i < N; i++, signs >>= 1) { + do { + shake_squeeze(shake, &j, 1); + } while (j > i); + c->x[i] = c->x[j]; + c->x[j] = 1 - 2 * (s32)(signs & 1); + } +} + +/* + * Expand the public seed @rho and @row_and_column into an element of T_q @out. + * Reference: FIPS 204 Algorithm 30, RejNTTPoly + * + * @shake and @block are temporary space used by the expansion. @block has + * space for one SHAKE128 block, plus an extra byte to allow reading a u32 from + * the final 3-byte group without reading out-of-bounds. + */ +static void rej_ntt_poly(struct mldsa_ring_elem *out, const u8 rho[RHO_LEN], + __le16 row_and_column, struct shake_ctx *shake, + u8 block[SHAKE128_BLOCK_SIZE + 1]) +{ + shake128_init(shake); + shake_update(shake, rho, RHO_LEN); + shake_update(shake, (u8 *)&row_and_column, sizeof(row_and_column)); + for (int i = 0; i < N;) { + shake_squeeze(shake, block, SHAKE128_BLOCK_SIZE); + block[SHAKE128_BLOCK_SIZE] = 0; /* for KMSAN */ + static_assert(SHAKE128_BLOCK_SIZE % 3 == 0); + for (int j = 0; j < SHAKE128_BLOCK_SIZE && i < N; j += 3) { + u32 x = get_unaligned_le32(&block[j]) & 0x7fffff; + + if (x < Q) /* Ignore values >= q. */ + out->x[i++] = x; + } + } +} + +/* + * Return the HighBits of r adjusted according to hint h + * Reference: FIPS 204 Algorithm 40, UseHint + * + * This is needed because of the public key compression in ML-DSA. + * + * h is either 0 or 1, r is in [0, q - 1], and gamma2 is either (q - 1) / 88 or + * (q - 1) / 32. Except when invoked via the unit test interface, gamma2 is a + * compile-time constant, so compilers will optimize the code accordingly. + */ +static __always_inline s32 use_hint(u8 h, s32 r, const s32 gamma2) +{ + const s32 m = (Q - 1) / (2 * gamma2); /* 44 or 16, compile-time const */ + s32 r1; + + /* + * Handle the special case where r - (r mod+- (2 * gamma2)) == q - 1, + * i.e. r >= q - gamma2. This is also exactly where the computation of + * r1 below would produce 'm' and would need a correction. + */ + if (r >= Q - gamma2) + return h == 0 ? 0 : m - 1; + + /* + * Compute the (non-hint-adjusted) HighBits r1 as: + * + * r1 = (r - (r mod+- (2 * gamma2))) / (2 * gamma2) + * = floor((r + gamma2 - 1) / (2 * gamma2)) + * + * Note that when '2 * gamma2' is a compile-time constant, compilers + * optimize the division to a reciprocal multiplication and shift. + */ + r1 = (u32)(r + gamma2 - 1) / (2 * gamma2); + + /* + * Return the HighBits r1: + * + 0 if the hint is 0; + * + 1 (mod m) if the hint is 1 and the LowBits are positive; + * - 1 (mod m) if the hint is 1 and the LowBits are negative or 0. + * + * r1 is in (and remains in) [0, m - 1]. Note that when 'm' is a + * compile-time constant, compilers optimize the '% m' accordingly. + */ + if (h == 0) + return r1; + if (r > r1 * (2 * gamma2)) + return (u32)(r1 + 1) % m; + return (u32)(r1 + m - 1) % m; +} + +static __always_inline void use_hint_elem(struct mldsa_ring_elem *w, + const u8 h[N], const s32 gamma2) +{ + for (int j = 0; j < N; j++) + w->x[j] = use_hint(h[j], w->x[j], gamma2); +} + +#if IS_ENABLED(CONFIG_CRYPTO_LIB_MLDSA_KUNIT_TEST) +/* Allow the __always_inline function use_hint() to be unit-tested. */ +s32 mldsa_use_hint(u8 h, s32 r, s32 gamma2) +{ + return use_hint(h, r, gamma2); +} +EXPORT_SYMBOL_IF_KUNIT(mldsa_use_hint); +#endif + +/* + * Encode one element of the commitment vector w'_1 into a byte string. + * Reference: FIPS 204 Algorithm 28, w1Encode. + * Return the number of bytes used: 192 for ML-DSA-44 and 128 for the others. + */ +static size_t encode_w1(u8 out[MAX_W1_ENCODED_LEN], + const struct mldsa_ring_elem *w1, int k) +{ + size_t pos = 0; + + static_assert(N * 6 / 8 == MAX_W1_ENCODED_LEN); + if (k == 4) { /* ML-DSA-44? */ + /* 6 bits per coefficient. Pack 4 at a time. */ + for (int j = 0; j < N; j += 4) { + u32 v = (w1->x[j + 0] << 0) | (w1->x[j + 1] << 6) | + (w1->x[j + 2] << 12) | (w1->x[j + 3] << 18); + out[pos++] = v >> 0; + out[pos++] = v >> 8; + out[pos++] = v >> 16; + } + } else { + /* 4 bits per coefficient. Pack 2 at a time. */ + for (int j = 0; j < N; j += 2) + out[pos++] = w1->x[j] | (w1->x[j + 1] << 4); + } + return pos; +} + +/* Reference: FIPS 204 Section 6.3 "ML-DSA Verifying (Internal)" */ +int mldsa_verify(enum mldsa_alg alg, const u8 *sig, size_t sig_len, + const u8 *msg, size_t msg_len, const u8 *pk, size_t pk_len) +{ + const struct mldsa_parameter_set *params = &mldsa_parameter_sets[alg]; + const int k = params->k, l = params->l; + /* For now this just does pure ML-DSA with an empty context string. */ + static const u8 msg_prefix[2] = { /* dom_sep= */ 0, /* ctx_len= */ 0 }; + const u8 *ctilde; /* The signer's commitment hash */ + const u8 *t1_encoded = &pk[RHO_LEN]; /* Next encoded element of t_1 */ + u8 *h; /* The signer's hint vector, length k * N */ + size_t w1_enc_len; + + /* Validate the public key and signature lengths. */ + if (pk_len != params->pk_len || sig_len != params->sig_len) + return -EBADMSG; + + /* + * Allocate the workspace, including variable-length fields. Its size + * depends only on the ML-DSA parameter set, not the other inputs. + * + * For freeing it, use kfree_sensitive() rather than kfree(). This is + * mainly to comply with FIPS 204 Section 3.6.3 "Intermediate Values". + * In reality it's a bit gratuitous, as this is a public key operation. + */ + struct mldsa_verification_workspace *ws __free(kfree_sensitive) = + kmalloc(sizeof(*ws) + (l * sizeof(ws->z[0])) + (k * N), + GFP_KERNEL); + if (!ws) + return -ENOMEM; + h = (u8 *)&ws->z[l]; + + /* Decode the signature. Reference: FIPS 204 Algorithm 27, sigDecode */ + ctilde = sig; + sig += params->ctilde_len; + if (!decode_z(ws->z, l, params->gamma1, params->beta, &sig)) + return -EBADMSG; + if (!decode_hint_vector(h, k, params->omega, sig)) + return -EBADMSG; + + /* Recreate the challenge c from the signer's commitment hash. */ + sample_in_ball(&ws->c, ctilde, params->ctilde_len, params->tau, + &ws->shake); + ntt(&ws->c); + + /* Compute the message representative mu. */ + shake256(pk, pk_len, ws->tr, sizeof(ws->tr)); + shake256_init(&ws->shake); + shake_update(&ws->shake, ws->tr, sizeof(ws->tr)); + shake_update(&ws->shake, msg_prefix, sizeof(msg_prefix)); + shake_update(&ws->shake, msg, msg_len); + shake_squeeze(&ws->shake, ws->mu, sizeof(ws->mu)); + + /* Start computing ctildeprime = H(mu || w1Encode(w'_1)). */ + shake256_init(&ws->shake); + shake_update(&ws->shake, ws->mu, sizeof(ws->mu)); + + /* + * Compute the commitment w'_1 from A, z, c, t_1, and h. + * + * The computation is the same for each of the k rows. Just do each row + * before moving on to the next, resulting in only one loop over k. + */ + for (int i = 0; i < k; i++) { + /* + * tmp = NTT(A) * NTT(z) * 2^-32 + * To reduce memory use, generate each element of NTT(A) + * on-demand. Note that each element is used only once. + */ + ws->tmp = (struct mldsa_ring_elem){}; + for (int j = 0; j < l; j++) { + rej_ntt_poly(&ws->a, pk /* rho is first field of pk */, + cpu_to_le16((i << 8) | j), &ws->a_shake, + ws->block); + for (int n = 0; n < N; n++) + ws->tmp.x[n] += + Zq_mult(ws->a.x[n], ws->z[j].x[n]); + } + /* All components of tmp now have abs value < l*q. */ + + /* Decode the next element of t_1. */ + t1_encoded = decode_t1_elem(&ws->t1_scaled, t1_encoded); + + /* + * tmp -= NTT(c) * NTT(t_1 * 2^d) * 2^-32 + * + * Taking a conservative bound for the output of ntt(), the + * multiplicands can have absolute value up to 9*q. That + * corresponds to a product with absolute value 81*q^2. That is + * within the limits of Zq_mult() which needs < ~256*q^2. + */ + for (int j = 0; j < N; j++) + ws->tmp.x[j] -= Zq_mult(ws->c.x[j], ws->t1_scaled.x[j]); + /* All components of tmp now have abs value < (l+1)*q. */ + + /* tmp = w'_Approx = NTT^-1(tmp) * 2^32 */ + invntt_and_mul_2_32(&ws->tmp); + /* All coefficients of tmp are now in [0, q - 1]. */ + + /* + * tmp = w'_1 = UseHint(h, w'_Approx) + * For efficiency, set gamma2 to a compile-time constant. + */ + if (k == 4) + use_hint_elem(&ws->tmp, &h[i * N], (Q - 1) / 88); + else + use_hint_elem(&ws->tmp, &h[i * N], (Q - 1) / 32); + + /* Encode and hash the next element of w'_1. */ + w1_enc_len = encode_w1(ws->w1_encoded, &ws->tmp, k); + shake_update(&ws->shake, ws->w1_encoded, w1_enc_len); + } + + /* Finish computing ctildeprime. */ + shake_squeeze(&ws->shake, ws->ctildeprime, params->ctilde_len); + + /* Verify that ctilde == ctildeprime. */ + if (memcmp(ws->ctildeprime, ctilde, params->ctilde_len) != 0) + return -EKEYREJECTED; + /* ||z||_infinity < gamma1 - beta was already checked in decode_z(). */ + return 0; +} +EXPORT_SYMBOL_GPL(mldsa_verify); + +MODULE_DESCRIPTION("ML-DSA signature verification"); +MODULE_LICENSE("GPL"); From ed894faccb8de55cd755e093c4b0971f190d384d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 14 Dec 2025 10:17:12 -0800 Subject: [PATCH 02/53] lib/crypto: tests: Add KUnit tests for ML-DSA verification Add a KUnit test suite for ML-DSA verification, including the following for each ML-DSA parameter set (ML-DSA-44, ML-DSA-65, and ML-DSA-87): - Positive test (valid signature), using vector imported from leancrypto - Various negative tests: - Wrong length for signature, message, or public key - Out-of-range coefficients in z vector - Invalid encoded hint vector - Any bit flipped in signature, message, or public key - Unit test for the internal function use_hint() - A benchmark ML-DSA inputs and outputs are very large. To keep the size of the tests down, use just one valid test vector per parameter set, and generate the negative tests at runtime by mutating the valid test vector. I also considered importing the test vectors from Wycheproof. I've tested that mldsa_verify() indeed passes all of Wycheproof's ML-DSA test vectors that use an empty context string. However, importing these permanently would add over 6 MB of source. That's too much to be a reasonable addition to the Linux kernel tree for one algorithm. It also wouldn't actually provide much better test coverage than this commit. Another potential issue is that Wycheproof uses the Apache license. Similarly, this also differs from the earlier proposal to import a long list of test vectors from leancrypto. I retained only one valid signature for each algorithm, and I also added (runtime-generated) negative tests which were missing. I think this is a better tradeoff. Reviewed-by: David Howells Tested-by: David Howells Link: https://lore.kernel.org/r/20251214181712.29132-3-ebiggers@kernel.org Signed-off-by: Eric Biggers --- lib/crypto/tests/Kconfig | 9 + lib/crypto/tests/Makefile | 1 + lib/crypto/tests/mldsa-testvecs.h | 1887 +++++++++++++++++++++++++++++ lib/crypto/tests/mldsa_kunit.c | 438 +++++++ 4 files changed, 2335 insertions(+) create mode 100644 lib/crypto/tests/mldsa-testvecs.h create mode 100644 lib/crypto/tests/mldsa_kunit.c diff --git a/lib/crypto/tests/Kconfig b/lib/crypto/tests/Kconfig index 61d435c450bb..c9165c14fc46 100644 --- a/lib/crypto/tests/Kconfig +++ b/lib/crypto/tests/Kconfig @@ -38,6 +38,15 @@ config CRYPTO_LIB_MD5_KUNIT_TEST KUnit tests for the MD5 cryptographic hash function and its corresponding HMAC. +config CRYPTO_LIB_MLDSA_KUNIT_TEST + tristate "KUnit tests for ML-DSA" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS + select CRYPTO_LIB_BENCHMARK_VISIBLE + select CRYPTO_LIB_MLDSA + help + KUnit tests for the ML-DSA digital signature algorithm. + config CRYPTO_LIB_POLY1305_KUNIT_TEST tristate "KUnit tests for Poly1305" if !KUNIT_ALL_TESTS depends on KUNIT diff --git a/lib/crypto/tests/Makefile b/lib/crypto/tests/Makefile index 5109a0651925..3dde0b40b2c5 100644 --- a/lib/crypto/tests/Makefile +++ b/lib/crypto/tests/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST) += blake2b_kunit.o obj-$(CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST) += blake2s_kunit.o obj-$(CONFIG_CRYPTO_LIB_CURVE25519_KUNIT_TEST) += curve25519_kunit.o obj-$(CONFIG_CRYPTO_LIB_MD5_KUNIT_TEST) += md5_kunit.o +obj-$(CONFIG_CRYPTO_LIB_MLDSA_KUNIT_TEST) += mldsa_kunit.o obj-$(CONFIG_CRYPTO_LIB_POLY1305_KUNIT_TEST) += poly1305_kunit.o obj-$(CONFIG_CRYPTO_LIB_POLYVAL_KUNIT_TEST) += polyval_kunit.o obj-$(CONFIG_CRYPTO_LIB_SHA1_KUNIT_TEST) += sha1_kunit.o diff --git a/lib/crypto/tests/mldsa-testvecs.h b/lib/crypto/tests/mldsa-testvecs.h new file mode 100644 index 000000000000..d2d6a042a829 --- /dev/null +++ b/lib/crypto/tests/mldsa-testvecs.h @@ -0,0 +1,1887 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* ML-DSA test vectors extracted from leancrypto */ + +struct mldsa_testvector { + enum mldsa_alg alg; + int sig_len; + int msg_len; + int pk_len; + const u8 *sig; + const u8 *msg; + const u8 *pk; +}; + +static const struct mldsa_testvector mldsa44_testvector = { + .alg = MLDSA44, + .pk_len = MLDSA44_PUBLIC_KEY_SIZE, + .pk = + (const u8[MLDSA44_PUBLIC_KEY_SIZE]) { + 0x8f, 0x61, 0x67, 0xa9, 0x7c, 0x61, 0xc2, 0xf2, 0x87, + 0xe2, 0x28, 0xf8, 0x44, 0x80, 0x6f, 0xb0, 0x10, 0xc1, + 0x14, 0xf6, 0x88, 0x42, 0x76, 0xbe, 0x05, 0xd2, 0x56, + 0xa0, 0xb7, 0x46, 0xcf, 0xc5, 0x76, 0x0a, 0x52, 0xfe, + 0xa3, 0x3c, 0x05, 0x6e, 0xd5, 0xd3, 0xbd, 0x80, 0x03, + 0x29, 0x25, 0x96, 0xdf, 0xa9, 0x5b, 0x12, 0x42, 0x89, + 0x6e, 0x03, 0x2c, 0x42, 0x64, 0xee, 0xc7, 0xf7, 0x55, + 0xfe, 0xfd, 0x15, 0x74, 0xee, 0x2d, 0xb3, 0xbf, 0xf2, + 0x24, 0xe7, 0x35, 0x45, 0x77, 0x67, 0x44, 0xd2, 0x0c, + 0x43, 0xfc, 0x7b, 0x47, 0x56, 0xad, 0xc5, 0xe7, 0x37, + 0x49, 0x21, 0x12, 0x57, 0x7f, 0xca, 0x7f, 0x5d, 0xac, + 0x62, 0x5b, 0x8d, 0xbf, 0xdb, 0x64, 0xac, 0x12, 0x1d, + 0x7f, 0x7a, 0x2f, 0xa0, 0x2c, 0xfe, 0x95, 0x4b, 0x78, + 0xdb, 0xf0, 0x98, 0x97, 0x70, 0x62, 0xfc, 0x64, 0x4a, + 0x1b, 0xbc, 0x30, 0x1b, 0x51, 0x13, 0x47, 0x6e, 0x83, + 0xd2, 0xa2, 0xcf, 0x39, 0xba, 0xd3, 0x00, 0x62, 0x7c, + 0x5b, 0xe6, 0x14, 0x55, 0xd5, 0xfc, 0xbf, 0x15, 0x65, + 0xd7, 0x1f, 0xbb, 0xf6, 0x2b, 0x46, 0x38, 0x1e, 0xf3, + 0x8f, 0x0d, 0x57, 0x8a, 0x41, 0xfb, 0x47, 0x19, 0xe1, + 0x79, 0xca, 0x98, 0x1a, 0x73, 0x4d, 0x8a, 0xc0, 0xa1, + 0xa7, 0x4a, 0x28, 0x4a, 0x92, 0x6c, 0x77, 0x4f, 0x18, + 0xe1, 0xce, 0x11, 0x14, 0xd5, 0xf6, 0xc0, 0xa8, 0x1e, + 0x26, 0x25, 0xe4, 0x30, 0xb2, 0x6f, 0x89, 0x6e, 0xc6, + 0x44, 0x1a, 0xd3, 0xca, 0xe1, 0x05, 0x0d, 0x61, 0x80, + 0xd7, 0xbc, 0x56, 0x0a, 0x57, 0x9f, 0x16, 0x40, 0x84, + 0x1e, 0xc0, 0x5e, 0xcd, 0xb6, 0xc8, 0x5d, 0x87, 0xd6, + 0xee, 0xcb, 0x21, 0x2f, 0x22, 0x9a, 0x7e, 0xea, 0x2e, + 0xf5, 0x87, 0xf0, 0x44, 0x10, 0x3d, 0x42, 0x6d, 0x3f, + 0x4f, 0xa0, 0x21, 0x8e, 0x40, 0x75, 0x3b, 0xaa, 0xd4, + 0xd9, 0x37, 0x0a, 0x35, 0x5b, 0xba, 0xbd, 0x11, 0x17, + 0x7b, 0x7e, 0xfc, 0xb1, 0x1c, 0x5c, 0x71, 0xce, 0xde, + 0xa5, 0xec, 0xd6, 0x8b, 0x50, 0x64, 0x02, 0xca, 0x84, + 0x26, 0xfe, 0x03, 0x9e, 0xaf, 0x13, 0x05, 0x1c, 0x85, + 0x32, 0x92, 0x85, 0x84, 0x83, 0xb6, 0x76, 0x27, 0xa7, + 0xd8, 0x0c, 0xa4, 0xb5, 0x65, 0x7a, 0xbf, 0x2e, 0x64, + 0xce, 0x82, 0x0d, 0x27, 0xd3, 0x2c, 0x9d, 0xb5, 0xa5, + 0x51, 0xe3, 0xab, 0xbd, 0xe2, 0xe0, 0x64, 0x71, 0x0f, + 0x99, 0x09, 0x6a, 0x40, 0x9d, 0x8c, 0x6d, 0x63, 0x70, + 0x42, 0xe2, 0xa8, 0x5c, 0x71, 0xd2, 0x88, 0x10, 0xbc, + 0x3b, 0x9d, 0xc8, 0x3a, 0x8a, 0xf3, 0x81, 0x0a, 0x0e, + 0xd8, 0xf6, 0x13, 0x90, 0xc2, 0xda, 0x4c, 0x4f, 0x6f, + 0x1f, 0x61, 0x0d, 0x46, 0xac, 0x5c, 0x4a, 0xcc, 0x23, + 0xfb, 0xf2, 0xf8, 0x9f, 0x48, 0x1f, 0xaf, 0x24, 0xb4, + 0xc7, 0xcb, 0x6f, 0x80, 0x74, 0xa3, 0xdb, 0xa8, 0x61, + 0x12, 0x60, 0x08, 0x56, 0x85, 0x47, 0x05, 0x32, 0x93, + 0x43, 0x9b, 0xa6, 0xf6, 0x56, 0x3b, 0xab, 0x93, 0x28, + 0x19, 0xda, 0xad, 0xb5, 0xaa, 0x2e, 0x83, 0x3d, 0x37, + 0x0e, 0x83, 0xf2, 0xfe, 0xdd, 0xe8, 0xd9, 0x53, 0x36, + 0x3b, 0x5d, 0x8e, 0x24, 0xa9, 0x3a, 0x8f, 0x85, 0x4b, + 0x50, 0xf7, 0x61, 0x0f, 0x20, 0x92, 0x09, 0x1f, 0xe4, + 0x24, 0x98, 0x9f, 0xa4, 0x52, 0x12, 0x2a, 0xae, 0x6f, + 0xd6, 0x0d, 0xb5, 0x22, 0x72, 0x83, 0xfb, 0x4f, 0xef, + 0xa6, 0x55, 0x9a, 0x14, 0xab, 0x82, 0x89, 0x1f, 0xf2, + 0x0b, 0x14, 0x76, 0xb7, 0xf7, 0x14, 0xdd, 0xd6, 0xc1, + 0xe8, 0xb2, 0x99, 0x23, 0x28, 0xe8, 0xa4, 0x69, 0x18, + 0xf6, 0x3e, 0xb1, 0xff, 0xde, 0xf2, 0x2c, 0x7c, 0x73, + 0x93, 0x32, 0x52, 0x06, 0xeb, 0x59, 0xb2, 0x8f, 0x2f, + 0x1d, 0x6a, 0x85, 0x74, 0xd3, 0xe5, 0xa1, 0x95, 0xe4, + 0x96, 0x1e, 0x75, 0x16, 0xe4, 0x5c, 0x40, 0xf0, 0x20, + 0xb1, 0x10, 0xe7, 0x2a, 0x70, 0x41, 0xac, 0x49, 0x40, + 0x55, 0xef, 0xd1, 0x58, 0x24, 0x6a, 0xa6, 0x20, 0xdc, + 0x23, 0xdc, 0x66, 0x45, 0x4f, 0x6a, 0x52, 0x3c, 0x61, + 0xc8, 0xfb, 0x28, 0x1e, 0x8c, 0x3f, 0xfc, 0xc7, 0x73, + 0x2f, 0xf1, 0xe2, 0x31, 0xee, 0xa0, 0x5f, 0x12, 0x3f, + 0x94, 0xe5, 0x26, 0xc0, 0x62, 0xcc, 0x67, 0x8f, 0x5d, + 0xfd, 0x3d, 0x8f, 0x16, 0xae, 0x4e, 0x04, 0x54, 0x5b, + 0x02, 0x66, 0x00, 0x70, 0xe5, 0xcc, 0xb9, 0x51, 0x8c, + 0x1a, 0x5d, 0xf0, 0xfe, 0x7d, 0x1b, 0x2f, 0x0a, 0x48, + 0x94, 0xda, 0x4b, 0xb3, 0x05, 0x75, 0x3b, 0x25, 0xda, + 0xf2, 0x12, 0x47, 0xe2, 0xd7, 0xbb, 0xe7, 0x05, 0xa2, + 0x4e, 0xaf, 0x2f, 0x29, 0x6c, 0xbd, 0x80, 0x82, 0xdf, + 0xbb, 0x4b, 0x9d, 0x29, 0x9b, 0xef, 0xff, 0x17, 0x2a, + 0xa7, 0x2f, 0x4a, 0x2e, 0xbf, 0x29, 0x38, 0xcb, 0x94, + 0x9c, 0x10, 0x87, 0x69, 0x57, 0x7d, 0xd7, 0xcf, 0xc1, + 0x57, 0x0f, 0xc2, 0x9c, 0x3b, 0x1e, 0xbc, 0x55, 0x08, + 0xb1, 0x50, 0xb0, 0x28, 0x79, 0x1d, 0xd9, 0x2f, 0xa5, + 0x12, 0xcc, 0xa7, 0x5b, 0xcb, 0x67, 0x57, 0x13, 0x4a, + 0xb3, 0xd5, 0x34, 0xea, 0xd9, 0x6b, 0x15, 0x17, 0x1f, + 0xe7, 0x52, 0x2a, 0x11, 0xdf, 0xab, 0x3a, 0x8d, 0x1b, + 0xaa, 0xfa, 0x54, 0xf0, 0x20, 0x94, 0x40, 0x2d, 0x3e, + 0xf2, 0xa2, 0x8b, 0xbb, 0x86, 0xce, 0x29, 0x87, 0xb1, + 0xfa, 0x27, 0xf2, 0x5a, 0x79, 0xc2, 0xf8, 0xe9, 0xf2, + 0x7c, 0x5a, 0xcd, 0x45, 0x8e, 0x8b, 0xba, 0xad, 0x13, + 0x52, 0x79, 0xd5, 0x0f, 0x59, 0xfb, 0x07, 0x15, 0x1f, + 0xb3, 0xe6, 0xc8, 0x66, 0xf7, 0x37, 0x19, 0xd8, 0x33, + 0xdd, 0xc1, 0xb3, 0x96, 0x4b, 0x28, 0x43, 0xf8, 0x5e, + 0xc7, 0xe8, 0x81, 0x6e, 0xd0, 0xb2, 0x5a, 0x3d, 0xf1, + 0x68, 0x8f, 0xf0, 0xf5, 0x1a, 0x6d, 0xc3, 0xaa, 0x5b, + 0x72, 0x27, 0xbd, 0xd6, 0x7c, 0x9b, 0xbf, 0x89, 0x6a, + 0x09, 0xf0, 0x48, 0xf0, 0x8c, 0x27, 0x69, 0x28, 0xf3, + 0x5f, 0x53, 0xe3, 0x4d, 0x60, 0x4a, 0xb8, 0xc5, 0xf9, + 0x85, 0x07, 0x3e, 0xfb, 0xd7, 0x21, 0x69, 0xd5, 0xec, + 0x18, 0x68, 0xb6, 0x55, 0x15, 0xac, 0x2e, 0x0f, 0x5c, + 0x2e, 0x9e, 0x12, 0x10, 0x5e, 0xc6, 0xb3, 0xcd, 0xe6, + 0x3a, 0x2f, 0x43, 0xf6, 0x75, 0x31, 0x3c, 0x90, 0x34, + 0x1c, 0x3d, 0x45, 0xaa, 0x8e, 0x08, 0xcf, 0x58, 0x67, + 0x34, 0xd4, 0x24, 0xb8, 0x20, 0x69, 0xfe, 0xf0, 0x33, + 0xe9, 0x3e, 0xbd, 0xe5, 0x18, 0x9f, 0x66, 0xc9, 0x0d, + 0x6f, 0x47, 0x99, 0xf7, 0x0c, 0xdd, 0xad, 0x8c, 0x6b, + 0x80, 0xed, 0x19, 0x61, 0x8a, 0xba, 0x62, 0x2f, 0xcc, + 0x0e, 0x47, 0xe0, 0xc6, 0x1f, 0x2f, 0x44, 0x40, 0x17, + 0xb6, 0x89, 0xc6, 0xf5, 0xc2, 0x97, 0x89, 0x38, 0x6c, + 0x8e, 0x2c, 0x46, 0x0b, 0x6e, 0x01, 0x47, 0xd3, 0x2f, + 0x58, 0xf8, 0xc7, 0x3b, 0x49, 0xb2, 0x35, 0x9f, 0x67, + 0xc9, 0x6c, 0xde, 0x30, 0x3b, 0x50, 0x19, 0x65, 0xbb, + 0x73, 0xa1, 0x47, 0x01, 0x6a, 0x3d, 0xe3, 0x85, 0x4d, + 0xd0, 0x72, 0x0d, 0xbc, 0x81, 0x52, 0xe8, 0x1a, 0x8b, + 0x85, 0x4c, 0x6f, 0x0e, 0xfc, 0x59, 0x84, 0x7a, 0xf2, + 0x28, 0x3e, 0x02, 0xcb, 0xe2, 0x4a, 0xbf, 0xac, 0x22, + 0x34, 0x86, 0xe4, 0x7d, 0x6b, 0xa3, 0x52, 0xac, 0xff, + 0xe5, 0xbe, 0x0c, 0x8d, 0xf5, 0xd8, 0xfd, 0x5a, 0x3d, + 0xad, 0x0d, 0xc0, 0x02, 0xd0, 0x58, 0x8e, 0x7c, 0x50, + 0x7c, 0x09, 0xc0, 0xdb, 0xd7, 0xdf, 0xe0, 0xb2, 0x6f, + 0xb2, 0x79, 0x0d, 0xc1, 0xa0, 0xb1, 0x7e, 0xe3, 0x0d, + 0xfc, 0x93, 0x43, 0x8c, 0x86, 0x68, 0xa6, 0x51, 0x93, + 0x42, 0xb7, 0xcd, 0x13, 0x56, 0x6e, 0xdc, 0x63, 0x51, + 0x23, 0xcf, 0x29, 0xc5, 0x5a, 0x66, 0x43, 0x80, 0xfe, + 0x28, 0x15, 0x71, 0x52, 0x87, 0xe2, 0x18, 0x10, 0xad, + 0x94, 0x47, 0x2f, 0xe3, 0x5d, 0x7a, 0x02, 0x6d, 0x31, + 0x58, 0xae, 0x2f, 0x96, 0x53, 0x1b, 0x6c, 0x0e, 0x25, + 0xea, 0x41, 0xd3, 0x29, 0x27, 0x22, 0x24, 0x8d, 0x1d, + 0x8e, 0xd1, 0x33, 0x76, 0x67, 0x7d, 0x9d, 0xd9, 0xa7, + 0x3e, 0x61, 0xd0, 0xad, 0x93, 0xb9, 0xdf, 0x87, 0x3a, + 0x7b, 0x89, 0xc7, 0x1d, 0x91, 0xec, 0x43, 0xa4, 0xdc, + 0x02, 0x88, 0x2e, 0xaa, 0xb2, 0x58, 0xa5, 0xd3, 0x68, + 0x9c, 0x9f, 0x60, 0x12, 0xc8, 0x7e, 0x7d, 0x40, 0x80, + 0xfd, 0xb4, 0xbf, 0x56, 0xf4, 0x01, 0x39, 0x3d, 0xa0, + 0x34, 0x48, 0x79, 0x75, 0xe2, 0x0f, 0x60, 0x09, 0x42, + 0x11, 0x6f, 0xa5, 0x31, 0x46, 0xb7, 0x03, 0xc8, 0x61, + 0x53, 0x39, 0x1e, 0xf4, 0x99, 0x36, 0x7d, 0xc0, 0x87, + 0xda, 0x63, 0x71, 0x9b, 0x29, 0x7b, 0x4e, 0x6f, 0x09, + 0xa2, 0x2c, 0xa5, 0xc2, 0xb9, 0xe7, 0xe0, 0x56, 0x8b, + 0x1d, 0xbb, 0xcc, 0x34, 0x8c, 0xbc, 0xb6, 0x0a, 0xc9, + 0xfa, 0x4a, 0x31, 0x63, 0x0d, 0x30, 0xff, 0x59, 0x3d, + 0x8c, 0x4d, 0x74, 0x28, 0xf4, 0xe9, 0x97, 0x43, 0x05, + 0x3a, 0x33, 0x51, 0x51, 0xe4, 0x0e, 0x33, 0xae, 0x2c, + 0xda, 0x28, 0x83, 0x93, 0x4e, 0xfe, 0x37, 0x1d, 0x6c, + 0x25, 0x1e, 0x24, 0xbc, 0x3a, 0x5c, 0x68, 0xac, 0x54, + 0x3a, 0x47, 0x74, 0x35, 0xff, 0x37, 0x80, 0x12, 0x30, + 0xd7, 0x31, 0x2a, 0x49, 0x51, 0x2d, 0x4f, 0xd2, 0x9c, + 0xca, 0x55, 0x87, 0xd0, 0x41, 0x86, 0xc7, 0xf2, 0xda, + 0xf8, 0x4b, 0x08, 0x23, 0xb3, 0x00, 0xb7, 0xb6, 0x4f, + 0x2e, 0xaf, 0xb8, 0x8e, 0xb1, 0x44, 0xe1, 0xed, 0x67, + 0xf8, 0x80, 0xa7, 0x04, 0xa0, 0x66, 0xe6, 0xb5, 0x69, + 0xca, 0x95, 0x71, 0xc8, 0x0d, 0x3d, 0xf6, 0x77, 0xfd, + 0x2c, 0x95, 0xed, 0xe5, 0x22, 0x43, 0xd9, + }, + .msg_len = 64, + .msg = + (const u8[64]) { + 0x6d, 0xb3, 0x8e, 0x80, 0xaf, 0x5f, 0x19, 0xd9, + 0xb0, 0xcf, 0xad, 0x58, 0xc7, 0x27, 0xae, 0x12, + 0x4e, 0x7d, 0xa3, 0x1a, 0xe3, 0x85, 0xc6, 0xaa, + 0xf6, 0xa1, 0x9a, 0xb1, 0xe9, 0xe0, 0xfe, 0x89, + 0x1e, 0xc5, 0x6f, 0x10, 0x18, 0x24, 0xab, 0xa8, + 0x6d, 0x03, 0xd0, 0x3d, 0xc3, 0xff, 0x67, 0xe7, + 0x3a, 0x95, 0x94, 0xc8, 0x49, 0x51, 0x8f, 0xa0, + 0x65, 0xcb, 0x20, 0x29, 0x2a, 0x6d, 0xf7, 0xf2, + }, + .sig_len = MLDSA44_SIGNATURE_SIZE, + .sig = + (const u8[MLDSA44_SIGNATURE_SIZE]) { + 0x5e, 0x05, 0x37, 0xe2, 0xc1, 0x20, 0xce, 0x7b, 0x8a, + 0xdf, 0xf2, 0x22, 0x61, 0x17, 0x58, 0xaa, 0x3c, 0xe4, + 0x82, 0x9c, 0x0e, 0xb6, 0x1f, 0xb4, 0x98, 0x0f, 0xba, + 0x8e, 0x51, 0x15, 0x67, 0x76, 0x0b, 0x98, 0x63, 0xda, + 0x17, 0xd3, 0xbb, 0xbe, 0x16, 0x29, 0x71, 0xab, 0xba, + 0x99, 0xed, 0x3f, 0xd4, 0xc2, 0x16, 0x71, 0xb6, 0x21, + 0x87, 0x48, 0xaa, 0xb5, 0x39, 0x5e, 0xfb, 0x5d, 0x68, + 0x3b, 0xd3, 0x60, 0xf4, 0x5b, 0x85, 0x2a, 0x5b, 0xb5, + 0xce, 0x6e, 0xf3, 0x39, 0xc3, 0xbe, 0x96, 0xa7, 0x61, + 0xc9, 0xbf, 0xdf, 0x33, 0x1d, 0xec, 0xb9, 0x2b, 0x7a, + 0x05, 0xce, 0x1e, 0xd9, 0x46, 0x70, 0xca, 0x54, 0xbf, + 0xdc, 0x46, 0x9e, 0x2f, 0x29, 0x18, 0x57, 0x96, 0x84, + 0xac, 0xe9, 0xd7, 0x74, 0xeb, 0x8e, 0x6b, 0xec, 0x46, + 0x9a, 0x2a, 0xfa, 0xde, 0x80, 0x09, 0x53, 0xd9, 0xeb, + 0x9d, 0xf7, 0xaa, 0xe2, 0xe5, 0xdc, 0xc3, 0xd9, 0x70, + 0xe5, 0x8b, 0xa8, 0xba, 0x2b, 0x41, 0x72, 0x92, 0x25, + 0xaf, 0xd9, 0xb4, 0x5a, 0x53, 0xb7, 0xcc, 0x1d, 0x69, + 0xf1, 0x53, 0x5b, 0x52, 0x38, 0xbc, 0x47, 0x24, 0x8c, + 0x1d, 0x28, 0x5d, 0x5c, 0x1c, 0xc9, 0x9d, 0xea, 0x1c, + 0xb1, 0xb3, 0x49, 0x68, 0xd5, 0xad, 0xdc, 0x47, 0x58, + 0x6d, 0x38, 0x33, 0xe7, 0x9b, 0xaa, 0x89, 0xb1, 0x96, + 0x0b, 0xcb, 0xc4, 0x24, 0x73, 0xf2, 0xe7, 0xb6, 0xca, + 0x74, 0x55, 0x1b, 0xb5, 0xb7, 0x9e, 0x2e, 0xe3, 0x3a, + 0x32, 0x5d, 0x1d, 0x6e, 0x15, 0xe6, 0xb8, 0xfb, 0xce, + 0x57, 0x81, 0x15, 0xb5, 0xcf, 0x67, 0x2b, 0x55, 0x4c, + 0x85, 0x6f, 0x28, 0xa6, 0xbb, 0xb4, 0x28, 0x76, 0x91, + 0xa4, 0x29, 0xa1, 0x50, 0x7c, 0xed, 0x9a, 0xfc, 0xe4, + 0xbc, 0xd7, 0x28, 0x62, 0x28, 0x61, 0x4d, 0x8d, 0x8c, + 0x5a, 0x5e, 0x4d, 0x1d, 0x5e, 0x73, 0xcc, 0x0b, 0x9d, + 0x56, 0x73, 0xc7, 0xf2, 0x26, 0xf7, 0x7e, 0x61, 0xa4, + 0x86, 0xf5, 0x1c, 0xd1, 0x00, 0xd0, 0x31, 0xc5, 0x03, + 0x17, 0x1c, 0xec, 0x04, 0xe5, 0xc7, 0x13, 0xb6, 0x81, + 0x78, 0x3d, 0x27, 0x87, 0x36, 0xf3, 0x2a, 0x59, 0x96, + 0xeb, 0x44, 0xfd, 0xb9, 0x95, 0xb7, 0x76, 0xb1, 0x08, + 0xc4, 0x98, 0xb1, 0x08, 0x36, 0x2a, 0x63, 0x72, 0x4f, + 0xef, 0x47, 0xfc, 0x84, 0x09, 0x18, 0x60, 0xb7, 0x8a, + 0xff, 0xae, 0x32, 0x3c, 0x79, 0xdf, 0xd6, 0x24, 0xbe, + 0x9c, 0x38, 0x68, 0x92, 0xde, 0x81, 0x80, 0x22, 0x06, + 0xf2, 0xe4, 0xde, 0x75, 0x4e, 0xd6, 0x36, 0x93, 0x44, + 0xd1, 0xa4, 0x2e, 0x2e, 0x05, 0x87, 0xbd, 0xf7, 0xc5, + 0xc8, 0x1c, 0x7b, 0x00, 0xe8, 0x11, 0x7f, 0xc2, 0x39, + 0x4b, 0x7b, 0x97, 0x11, 0x92, 0x6c, 0xff, 0x89, 0x7f, + 0x26, 0x89, 0x4f, 0x38, 0xfd, 0xdd, 0x08, 0xa7, 0xce, + 0x6f, 0xe8, 0x57, 0x9b, 0x46, 0xe5, 0xdb, 0x72, 0x03, + 0x1e, 0x7d, 0xb0, 0x77, 0xb9, 0xcc, 0xdb, 0x6c, 0xa7, + 0xd8, 0x30, 0x34, 0xad, 0xa7, 0xe4, 0x63, 0xf0, 0x19, + 0x0e, 0x5d, 0x3b, 0xe0, 0xff, 0x40, 0x1c, 0xa5, 0xb3, + 0xb9, 0x87, 0x6e, 0x2c, 0xf3, 0x5f, 0xcd, 0x54, 0x2a, + 0xc0, 0x6e, 0x2b, 0xd9, 0x2d, 0xcc, 0xd5, 0x68, 0x95, + 0x4a, 0x4a, 0x84, 0x60, 0x54, 0xee, 0xa0, 0x21, 0x9e, + 0x8d, 0x20, 0xcb, 0xe8, 0xc5, 0x5a, 0xba, 0xe2, 0xaa, + 0x6e, 0x1c, 0xb1, 0xdf, 0x18, 0x9f, 0x94, 0xc7, 0x77, + 0x5a, 0x2c, 0x0e, 0x05, 0xaa, 0x2a, 0x54, 0x58, 0x6c, + 0xb3, 0x2e, 0x2f, 0xa4, 0x6e, 0x98, 0xbb, 0x6f, 0x41, + 0x6d, 0xbd, 0x71, 0x95, 0xe4, 0xbc, 0x13, 0x37, 0x99, + 0x0d, 0xac, 0x27, 0x69, 0xb9, 0x0b, 0x14, 0x5f, 0x6e, + 0xd2, 0x2b, 0xe2, 0x0c, 0xc6, 0xbc, 0x10, 0x11, 0x47, + 0xb7, 0x37, 0x2c, 0x0e, 0x88, 0xcd, 0xbb, 0xf7, 0x28, + 0xd6, 0x4a, 0x9d, 0xff, 0x3c, 0x2f, 0x7d, 0x2b, 0xe8, + 0xe8, 0x9e, 0xae, 0x7b, 0xe6, 0x2a, 0xb3, 0x4e, 0x20, + 0xcc, 0xf1, 0x81, 0x8e, 0xed, 0x6d, 0xe2, 0x99, 0xf5, + 0xb5, 0x1a, 0x30, 0x95, 0x52, 0x34, 0xf5, 0x3f, 0xc3, + 0x31, 0xd6, 0xbe, 0xa2, 0xc8, 0xdc, 0xe4, 0x1c, 0xf6, + 0x0f, 0x4d, 0x0b, 0x89, 0x8e, 0x66, 0x93, 0x88, 0xb8, + 0xad, 0xbc, 0xdc, 0x96, 0x01, 0x9f, 0x16, 0x70, 0xf5, + 0x4f, 0xa4, 0x0e, 0x0f, 0xc3, 0xf6, 0x9c, 0xe1, 0xa1, + 0xe3, 0xec, 0x9d, 0x09, 0xcd, 0x90, 0x52, 0x26, 0x09, + 0xd9, 0x9c, 0xde, 0xbd, 0xdf, 0xbb, 0xf4, 0x50, 0xd1, + 0x89, 0x68, 0xf6, 0x86, 0x53, 0x33, 0x5a, 0xf6, 0x54, + 0xb5, 0x7c, 0xe1, 0xd7, 0x8d, 0xb8, 0x58, 0xf5, 0xda, + 0x14, 0xc8, 0x35, 0x1c, 0xcf, 0x44, 0x62, 0xbc, 0xd7, + 0xe3, 0xd8, 0x32, 0xcf, 0x16, 0xf5, 0x2f, 0x55, 0x23, + 0xc0, 0x1b, 0xc4, 0xe3, 0x28, 0xc8, 0xc8, 0x97, 0x70, + 0x8b, 0x06, 0x98, 0xfb, 0xf6, 0x33, 0x6b, 0x86, 0x1c, + 0xdb, 0x2a, 0x3c, 0x08, 0x08, 0x57, 0xd3, 0x4a, 0xf8, + 0x22, 0x26, 0x78, 0x65, 0x5f, 0xa6, 0xf8, 0x9f, 0x22, + 0x76, 0x62, 0xb0, 0x08, 0x68, 0x70, 0xea, 0x72, 0x57, + 0x6b, 0xe7, 0xf7, 0xc6, 0x12, 0x9a, 0x49, 0x50, 0xa9, + 0xa5, 0x6c, 0xe7, 0xda, 0xb4, 0xbf, 0xb6, 0xbf, 0x4f, + 0xdf, 0x9e, 0x9b, 0xb4, 0xb3, 0x8d, 0x1a, 0x12, 0x16, + 0x68, 0xd2, 0x63, 0xae, 0x92, 0x77, 0x1f, 0x03, 0xa5, + 0xed, 0x58, 0x3b, 0xe9, 0x0b, 0xfe, 0xfc, 0xae, 0x53, + 0x0b, 0x5f, 0x13, 0xf2, 0xd2, 0xe2, 0x0b, 0xec, 0x75, + 0x85, 0x68, 0x0c, 0x57, 0xde, 0x1b, 0x6d, 0x78, 0x0b, + 0x19, 0x66, 0xa8, 0xf5, 0x45, 0x72, 0x2b, 0x01, 0x06, + 0xf6, 0xd1, 0x47, 0x21, 0x24, 0x07, 0xf7, 0x71, 0x03, + 0xbc, 0xb0, 0x7c, 0x5b, 0x5c, 0x24, 0xff, 0x74, 0x47, + 0x62, 0x81, 0xc3, 0x0b, 0x31, 0x76, 0x90, 0x5b, 0xef, + 0x95, 0xa8, 0xa7, 0x02, 0xa1, 0xbf, 0xe1, 0xf4, 0x16, + 0x06, 0x8a, 0x97, 0x39, 0x35, 0xcf, 0xf3, 0xa7, 0x4a, + 0x43, 0xba, 0x05, 0x95, 0x7d, 0x73, 0x76, 0x7a, 0x53, + 0xef, 0xf8, 0x4e, 0xcb, 0x04, 0x70, 0x4c, 0xee, 0xff, + 0x82, 0xbd, 0xcd, 0xc1, 0xbe, 0x3d, 0x83, 0x71, 0x03, + 0xf0, 0xc0, 0x2b, 0x98, 0xf9, 0x60, 0x54, 0x02, 0x7d, + 0xa6, 0x41, 0xcc, 0xa3, 0xd7, 0x8d, 0xfd, 0xce, 0x28, + 0xae, 0x0f, 0x48, 0x17, 0x2a, 0xaf, 0xe9, 0xb9, 0x4a, + 0x8a, 0x22, 0xd2, 0x4d, 0xd3, 0x1b, 0xa3, 0x39, 0x88, + 0x8a, 0x8f, 0x5b, 0x44, 0x97, 0xb9, 0x04, 0x1b, 0x58, + 0x67, 0x74, 0x2f, 0x07, 0x7a, 0x52, 0xa9, 0x9d, 0xa4, + 0x41, 0x28, 0xf2, 0x35, 0xca, 0x68, 0x4e, 0x4a, 0x3a, + 0x66, 0xb9, 0x88, 0x2e, 0x65, 0x1d, 0x47, 0x04, 0xed, + 0xdb, 0xe1, 0x40, 0x12, 0x06, 0x13, 0x62, 0x28, 0x3d, + 0x0b, 0x35, 0x06, 0xc6, 0x2b, 0xb3, 0x71, 0x3c, 0xfa, + 0x77, 0xec, 0x47, 0x93, 0x78, 0x36, 0x25, 0x19, 0xd7, + 0x70, 0x30, 0x8a, 0x4c, 0x94, 0xdc, 0x3e, 0xeb, 0x61, + 0x25, 0xbc, 0xa0, 0x27, 0xd9, 0x17, 0xa5, 0x19, 0x4f, + 0xf4, 0x93, 0x32, 0x56, 0x9a, 0x0b, 0x77, 0xb4, 0x55, + 0x1b, 0x8f, 0x9e, 0x69, 0x5b, 0xe2, 0x6d, 0x70, 0x15, + 0x79, 0x5c, 0xf6, 0xb6, 0x04, 0xa2, 0x01, 0x37, 0x74, + 0x20, 0xb8, 0x62, 0xf6, 0x37, 0x3c, 0xab, 0xca, 0x71, + 0xa5, 0x8a, 0x56, 0x5d, 0x6a, 0x4a, 0x61, 0x2e, 0xb8, + 0x62, 0x7d, 0x47, 0x34, 0x7d, 0xcd, 0x4d, 0x70, 0x23, + 0xf5, 0xaa, 0xd1, 0xa5, 0xf0, 0x4c, 0x38, 0xc3, 0x98, + 0x79, 0x4c, 0x0b, 0x6b, 0xcc, 0xe7, 0xd7, 0x09, 0xae, + 0x23, 0x9b, 0x2f, 0xde, 0x70, 0xc6, 0xad, 0x0f, 0x66, + 0xb5, 0x78, 0x6b, 0x0b, 0xb0, 0x2e, 0x94, 0xf2, 0xa8, + 0x8b, 0x74, 0xf0, 0x03, 0x47, 0xd8, 0xec, 0xe8, 0x1f, + 0xa3, 0x7b, 0x38, 0x9e, 0x0e, 0xc0, 0x47, 0xd2, 0x0f, + 0x8e, 0x7f, 0xb1, 0x83, 0xd3, 0x86, 0x79, 0x3c, 0xa1, + 0xae, 0xc4, 0xaf, 0xae, 0x9d, 0x83, 0xc0, 0xd1, 0x2b, + 0x2b, 0xda, 0x50, 0x8c, 0xea, 0x41, 0x97, 0x9b, 0x0f, + 0x15, 0xc2, 0xe2, 0x8f, 0x39, 0x0b, 0x92, 0xdd, 0xde, + 0x52, 0x62, 0x74, 0xdc, 0xda, 0x11, 0x87, 0x4d, 0xa9, + 0x4a, 0xc5, 0x2f, 0xae, 0xaf, 0xc1, 0xc3, 0x05, 0xfa, + 0x38, 0xcc, 0x5c, 0xb1, 0x9f, 0xe0, 0x82, 0x90, 0xb3, + 0xd5, 0xdc, 0xf4, 0x55, 0xdb, 0xea, 0x94, 0x06, 0x7c, + 0x2c, 0x82, 0x78, 0xeb, 0xa5, 0x01, 0xf0, 0x3d, 0x4b, + 0x87, 0xdd, 0xd5, 0x91, 0x4f, 0xf3, 0xa7, 0xdf, 0xa1, + 0xd8, 0x31, 0xde, 0x05, 0x99, 0x67, 0x3d, 0xa4, 0x6b, + 0x19, 0xa3, 0xe8, 0x55, 0xb7, 0xf5, 0xc3, 0x63, 0x5e, + 0xd4, 0x38, 0xf9, 0x24, 0x64, 0x7d, 0x17, 0xc1, 0x07, + 0xbe, 0x39, 0x54, 0x1b, 0x44, 0xe5, 0xc6, 0x3c, 0x02, + 0xb1, 0x6f, 0xff, 0x8c, 0xcb, 0x79, 0xe2, 0xec, 0x4d, + 0x01, 0xfa, 0x7f, 0x88, 0x1d, 0xc3, 0x4c, 0x6a, 0xfb, + 0x0b, 0xc6, 0x57, 0xc3, 0xd8, 0x24, 0x47, 0x41, 0xbd, + 0x27, 0xc4, 0xd4, 0x49, 0xfb, 0x52, 0xe6, 0x77, 0x5f, + 0x0a, 0xdf, 0xea, 0xd5, 0xd3, 0x22, 0xc3, 0x53, 0x16, + 0xf3, 0x1b, 0x7b, 0x09, 0xd7, 0x10, 0x0e, 0x23, 0xae, + 0x16, 0x8a, 0x93, 0xcb, 0xc9, 0xb7, 0xb8, 0xff, 0xd2, + 0x50, 0x1f, 0x25, 0xa7, 0x71, 0x8f, 0x3f, 0xc0, 0xe1, + 0x37, 0x10, 0x0b, 0x43, 0x6e, 0x2b, 0x16, 0x59, 0x8f, + 0x77, 0x77, 0x6b, 0x77, 0xce, 0x76, 0x6b, 0x37, 0x81, + 0xaf, 0x83, 0x42, 0x92, 0x93, 0xe5, 0x39, 0xca, 0xd2, + 0x20, 0x2e, 0xcf, 0x24, 0x26, 0x4c, 0x51, 0x1c, 0x58, + 0xc5, 0x8d, 0x05, 0x11, 0xdf, 0xae, 0x51, 0x38, 0xde, + 0xab, 0x4e, 0x04, 0xc8, 0x24, 0x24, 0x0d, 0xd5, 0x9c, + 0x5b, 0x2b, 0xe6, 0x0d, 0x83, 0x95, 0xcd, 0x1c, 0x89, + 0xa1, 0xaf, 0x67, 0x47, 0xfb, 0x08, 0x02, 0xf8, 0x8b, + 0x63, 0x05, 0x73, 0x20, 0x64, 0xd7, 0x52, 0x15, 0xa4, + 0x5d, 0x63, 0x73, 0x73, 0x12, 0x0b, 0xdd, 0xfe, 0x9f, + 0xb7, 0xe8, 0xa8, 0x94, 0x3a, 0x86, 0xff, 0xcf, 0x7d, + 0x24, 0xbd, 0xb9, 0xea, 0x68, 0x23, 0xf4, 0x07, 0xc3, + 0xfe, 0x63, 0xd0, 0xab, 0x65, 0x8a, 0xf0, 0x6d, 0x81, + 0x8c, 0xc8, 0x0e, 0xc6, 0x6b, 0xdd, 0x2e, 0x65, 0x9b, + 0x17, 0xcf, 0x82, 0x69, 0x46, 0xba, 0x62, 0x5d, 0x31, + 0x33, 0x60, 0x18, 0x94, 0xa5, 0x77, 0x24, 0xc6, 0x45, + 0xe5, 0xb3, 0xd5, 0x12, 0x10, 0xc9, 0x22, 0x98, 0xf9, + 0xca, 0x20, 0x89, 0x79, 0x04, 0x08, 0xf5, 0x1c, 0xf8, + 0x50, 0x8c, 0x25, 0xaa, 0x90, 0x90, 0x44, 0xbc, 0xfb, + 0x5d, 0x3f, 0xf8, 0x38, 0x64, 0xca, 0x8d, 0xff, 0x17, + 0xce, 0x70, 0x51, 0x90, 0x75, 0x6b, 0x7d, 0x64, 0x43, + 0x56, 0xcd, 0xf8, 0x85, 0x93, 0x65, 0x09, 0x81, 0x30, + 0x76, 0x79, 0xcc, 0xdf, 0x9c, 0x6d, 0xff, 0x89, 0x38, + 0x60, 0xbf, 0x07, 0xcb, 0x2f, 0xc9, 0x87, 0xd7, 0xac, + 0x74, 0x19, 0x57, 0x90, 0x5e, 0x69, 0x61, 0xf6, 0xca, + 0xea, 0x45, 0x6b, 0xe2, 0xfe, 0x2c, 0xff, 0x1b, 0x23, + 0x15, 0x52, 0xdd, 0x57, 0xfe, 0x1d, 0x10, 0xea, 0x0f, + 0xce, 0x98, 0xe7, 0x47, 0x27, 0xec, 0x36, 0xe5, 0x68, + 0x17, 0xcf, 0xdc, 0xb9, 0xef, 0x6a, 0xbc, 0xec, 0x78, + 0x08, 0x64, 0x06, 0xe1, 0x1c, 0xc6, 0x87, 0xd6, 0x0a, + 0xb1, 0x81, 0xc6, 0xb6, 0xf8, 0x8b, 0xe3, 0x19, 0x8c, + 0xce, 0x46, 0x40, 0xc5, 0xc2, 0xae, 0x50, 0x26, 0x4a, + 0x90, 0x91, 0x8d, 0xfe, 0x6b, 0x7d, 0x0a, 0x54, 0x4a, + 0x4b, 0x48, 0x74, 0x4a, 0x37, 0x21, 0x7f, 0xdd, 0x87, + 0xa3, 0x1e, 0xac, 0xcd, 0xf5, 0x9e, 0x75, 0xa2, 0x52, + 0x63, 0x76, 0xca, 0x9e, 0x02, 0xeb, 0xe6, 0xa6, 0x73, + 0xad, 0xea, 0xe8, 0x3e, 0x6f, 0x44, 0xed, 0xe8, 0x01, + 0x29, 0x19, 0x6a, 0x20, 0x35, 0xa7, 0xf0, 0xf1, 0xaf, + 0xc0, 0x3b, 0xb1, 0xd5, 0xe4, 0xfb, 0xf7, 0xd7, 0x2f, + 0x33, 0x6c, 0x73, 0xfd, 0xe5, 0x5c, 0x63, 0xf6, 0x1c, + 0x06, 0x13, 0xaf, 0xc1, 0x80, 0x55, 0x07, 0xae, 0x8c, + 0x13, 0x74, 0xf6, 0xe0, 0x54, 0x15, 0xd8, 0xe0, 0xa5, + 0x03, 0xcf, 0x22, 0xbe, 0x18, 0xef, 0x26, 0xad, 0x9c, + 0x9d, 0x51, 0xb1, 0x3b, 0x37, 0x03, 0xbf, 0xf0, 0xc5, + 0xcb, 0x6c, 0x5d, 0x30, 0xa9, 0x5a, 0x10, 0x90, 0xfa, + 0xb4, 0xd4, 0x0e, 0x6b, 0x4a, 0x0a, 0x6c, 0x9d, 0x2e, + 0x69, 0xe8, 0xec, 0x69, 0xe2, 0x50, 0xab, 0x2f, 0xdc, + 0xff, 0xaf, 0xac, 0x65, 0xe7, 0xf0, 0xc1, 0x6f, 0x7c, + 0x2d, 0xa1, 0xeb, 0x97, 0x90, 0x7c, 0x1e, 0xa8, 0x53, + 0x1b, 0x87, 0xc5, 0xa9, 0xa1, 0xcf, 0x86, 0x7e, 0x11, + 0xf8, 0xd6, 0x14, 0xda, 0x19, 0x81, 0x19, 0xb4, 0x45, + 0x1c, 0x7c, 0xb9, 0x96, 0xa2, 0xac, 0x79, 0x24, 0x94, + 0x7c, 0xb2, 0x1e, 0x83, 0xea, 0xc4, 0xb9, 0xd2, 0x0d, + 0x4c, 0x55, 0x3d, 0x15, 0x7b, 0x65, 0xd8, 0xff, 0x03, + 0x5d, 0xed, 0x3c, 0x94, 0x76, 0x19, 0x40, 0x3b, 0xcc, + 0x45, 0xbe, 0x91, 0x19, 0x8c, 0x75, 0xe5, 0xd2, 0xbe, + 0x67, 0x40, 0xb1, 0x67, 0x8e, 0x2a, 0x34, 0xd5, 0x99, + 0xee, 0xd9, 0x4f, 0x89, 0x7c, 0xf0, 0xd6, 0x93, 0x59, + 0x4b, 0x3a, 0x8d, 0xe6, 0xbd, 0xde, 0xce, 0xef, 0x8b, + 0x3c, 0xe3, 0xf7, 0x06, 0x33, 0x27, 0x8d, 0xd9, 0x22, + 0x1a, 0x65, 0x40, 0xfc, 0x69, 0x1b, 0x7d, 0xf0, 0xed, + 0xe4, 0xe0, 0x7f, 0x6d, 0x23, 0xed, 0x11, 0xd1, 0x07, + 0xb0, 0x2f, 0x8a, 0xbf, 0x51, 0x37, 0x22, 0x04, 0xed, + 0x93, 0xea, 0x1d, 0x0b, 0x30, 0x15, 0x89, 0x22, 0x7a, + 0x45, 0x56, 0x99, 0xc6, 0xac, 0xd6, 0xce, 0x61, 0xea, + 0xb2, 0x59, 0xe8, 0xb5, 0xfc, 0x87, 0xa7, 0xfe, 0x09, + 0xa2, 0x0d, 0x5e, 0xbe, 0xb9, 0xd4, 0x9a, 0x1b, 0x60, + 0xda, 0xb9, 0x32, 0xf1, 0x30, 0x3e, 0xb2, 0x45, 0x6d, + 0x55, 0x0c, 0x2c, 0x4b, 0x9a, 0xc0, 0xbb, 0x8e, 0xac, + 0x9c, 0x95, 0x5f, 0x08, 0x88, 0xa0, 0x53, 0x05, 0x75, + 0x8d, 0x9e, 0x9d, 0x3f, 0x0f, 0xdd, 0x50, 0x0d, 0xf8, + 0x11, 0xbd, 0xf9, 0xfb, 0x22, 0x5c, 0x7b, 0x9e, 0x7c, + 0x8e, 0x2f, 0x0e, 0xdb, 0xb8, 0x1d, 0x0c, 0x5e, 0x82, + 0xf3, 0x8e, 0xec, 0x32, 0x1c, 0x59, 0x73, 0xa5, 0xf3, + 0x5b, 0x47, 0x00, 0x64, 0x89, 0x68, 0x3b, 0xaf, 0xe8, + 0xe2, 0x9b, 0xa6, 0xac, 0x2c, 0xf9, 0x2b, 0x92, 0xf3, + 0xf0, 0x5b, 0xcc, 0x75, 0x22, 0xd5, 0xf4, 0x2b, 0x06, + 0x96, 0xc8, 0x50, 0xee, 0xac, 0x62, 0x16, 0x45, 0x9e, + 0xbc, 0xcc, 0x8f, 0x5a, 0x66, 0xc6, 0x30, 0x7c, 0xe0, + 0x22, 0xcc, 0xb9, 0xda, 0x0b, 0x0a, 0xbd, 0x2a, 0x2e, + 0x46, 0x7d, 0xb6, 0x86, 0x70, 0xa3, 0x16, 0x49, 0x85, + 0x28, 0x7b, 0xe9, 0x00, 0x6b, 0xfa, 0x06, 0xb0, 0xeb, + 0xbd, 0x67, 0x28, 0x6f, 0x27, 0xd7, 0x9c, 0x7f, 0xda, + 0xec, 0xf4, 0x7e, 0x55, 0xe1, 0x0c, 0x29, 0x61, 0x7a, + 0xf5, 0xb6, 0xb8, 0xa5, 0xef, 0x36, 0x6a, 0xad, 0x59, + 0x22, 0xbd, 0x3d, 0xad, 0x86, 0xe7, 0x4c, 0x69, 0x26, + 0x0f, 0xbf, 0x67, 0xad, 0x65, 0x32, 0xbd, 0x21, 0xd6, + 0x59, 0x6b, 0xe3, 0xda, 0xc1, 0x6f, 0x82, 0x41, 0x2c, + 0xaa, 0xe4, 0x8c, 0xfc, 0x7c, 0x61, 0x28, 0x51, 0x52, + 0x3d, 0xf1, 0x84, 0xb5, 0x0b, 0xfd, 0x1f, 0x2a, 0x06, + 0x2e, 0x30, 0xed, 0x63, 0x43, 0xc9, 0x83, 0x97, 0xb1, + 0xd4, 0x80, 0x6f, 0x2c, 0x50, 0xec, 0x20, 0x95, 0x42, + 0xa0, 0x34, 0x94, 0x1a, 0xa9, 0x5e, 0x5b, 0x59, 0xe3, + 0x39, 0xac, 0xbd, 0x2f, 0x77, 0x36, 0x59, 0x9c, 0xc3, + 0x3c, 0x66, 0x87, 0xf5, 0x81, 0x4b, 0xb0, 0x10, 0x4a, + 0xe6, 0x46, 0xe7, 0xce, 0x93, 0x7b, 0x24, 0x6b, 0x2e, + 0xc1, 0xe5, 0xaf, 0x4b, 0x71, 0x22, 0xad, 0x88, 0xda, + 0x55, 0xcb, 0xe0, 0x73, 0xd1, 0x65, 0x7d, 0xa5, 0x7f, + 0x36, 0xbc, 0x42, 0xc2, 0x78, 0x9f, 0x88, 0xe8, 0xdb, + 0xff, 0x8a, 0x5a, 0x80, 0x34, 0x3a, 0x23, 0x4c, 0x8a, + 0x81, 0xff, 0xbd, 0xb7, 0x88, 0xd0, 0x73, 0x07, 0x8a, + 0x4e, 0xa7, 0x4a, 0x61, 0x0f, 0x1f, 0x1c, 0xe7, 0x34, + 0x37, 0x1c, 0x53, 0x90, 0x3b, 0xa4, 0x32, 0x6c, 0x6d, + 0xe8, 0x00, 0xde, 0xe0, 0x0c, 0x5e, 0x06, 0xef, 0xb8, + 0x48, 0x2e, 0xb3, 0xda, 0xac, 0x92, 0x4d, 0x0d, 0x95, + 0x75, 0x44, 0x01, 0x6f, 0x97, 0xc3, 0x29, 0x76, 0x33, + 0x36, 0x9a, 0xae, 0xfb, 0x1b, 0x43, 0xe5, 0xb1, 0x54, + 0x3a, 0x9c, 0x76, 0x7f, 0x76, 0x83, 0xc9, 0x9c, 0xd6, + 0x56, 0x59, 0x83, 0xa9, 0xde, 0xd7, 0xb0, 0xf3, 0x34, + 0x11, 0x31, 0x06, 0x8e, 0xe9, 0xd4, 0x79, 0xd5, 0x3d, + 0x31, 0x6b, 0x59, 0xe9, 0x54, 0x69, 0x12, 0xfd, 0x44, + 0x59, 0x4e, 0x1b, 0x3b, 0xb4, 0x12, 0xe9, 0xfb, 0xb0, + 0xb4, 0x84, 0xb9, 0x7d, 0xea, 0x4f, 0xd1, 0x5f, 0xd0, + 0x3e, 0xce, 0xef, 0x5c, 0xf7, 0xea, 0x55, 0xa0, 0x8f, + 0xa8, 0xa7, 0x98, 0xe7, 0xa1, 0x6b, 0x3f, 0xba, 0x5a, + 0x32, 0x4b, 0xfa, 0x31, 0xb6, 0x63, 0x86, 0x19, 0x00, + 0xa2, 0x6d, 0x7d, 0x15, 0x56, 0x05, 0x68, 0xa3, 0xe0, + 0xf3, 0xd4, 0x82, 0xcf, 0xeb, 0xd4, 0x1c, 0xd0, 0xb6, + 0x14, 0x5e, 0x9e, 0x6b, 0xed, 0x7a, 0x02, 0x1a, 0xcd, + 0x09, 0xdc, 0x26, 0x98, 0x50, 0x11, 0x34, 0x39, 0x50, + 0x5a, 0x70, 0x79, 0x85, 0xca, 0xd2, 0xf2, 0x0c, 0x0d, + 0x12, 0x1f, 0x2e, 0x41, 0x46, 0x51, 0x72, 0x75, 0x78, + 0x8c, 0xa4, 0xaf, 0xba, 0xca, 0xd3, 0xdf, 0xea, 0xf8, + 0x09, 0x0b, 0x36, 0x45, 0x4f, 0x77, 0x83, 0xae, 0xbc, + 0xc5, 0xce, 0xe1, 0xf6, 0x1d, 0x1e, 0x38, 0x56, 0x9c, + 0x9f, 0xb1, 0xbd, 0xda, 0xe7, 0xf0, 0xf4, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1f, 0x2c, 0x38, + }, +}; + +static const struct mldsa_testvector mldsa65_testvector = { + .alg = MLDSA65, + .pk_len = MLDSA65_PUBLIC_KEY_SIZE, + .pk = + (const u8[MLDSA65_PUBLIC_KEY_SIZE]) { + 0x9f, 0x55, 0x1e, 0x7f, 0x9c, 0x08, 0xb2, 0x83, 0xfd, + 0x5b, 0xa2, 0xac, 0x4f, 0x26, 0xc2, 0xf5, 0x06, 0x05, + 0x96, 0x08, 0x24, 0xad, 0xec, 0xe4, 0x99, 0xcc, 0x6c, + 0xbd, 0x55, 0x37, 0x15, 0x94, 0xab, 0x31, 0x9e, 0x56, + 0xe5, 0xe4, 0x55, 0xec, 0x4d, 0x49, 0x5b, 0x5a, 0x7a, + 0xe8, 0xc3, 0x4a, 0x08, 0x44, 0x4a, 0xc2, 0x2d, 0xe4, + 0x61, 0x33, 0x90, 0x20, 0x71, 0x45, 0xa5, 0x45, 0xd0, + 0x83, 0x2b, 0x32, 0x6c, 0xa7, 0x9e, 0x76, 0xcd, 0xfb, + 0x58, 0x15, 0x9e, 0x74, 0x0d, 0x67, 0x57, 0xb1, 0x06, + 0x5b, 0x5d, 0xd5, 0x1c, 0xbb, 0x95, 0x40, 0x1c, 0x71, + 0x31, 0x03, 0xef, 0xff, 0x04, 0x6b, 0xdd, 0xa2, 0xf0, + 0x32, 0x00, 0x72, 0xbc, 0x87, 0xb6, 0x2c, 0x1f, 0x90, + 0x7f, 0x92, 0xa0, 0xb2, 0x04, 0xdd, 0xa9, 0xaf, 0x7f, + 0x01, 0x28, 0x4c, 0xb2, 0x57, 0x2d, 0x56, 0x93, 0xd0, + 0xc7, 0x54, 0x02, 0x90, 0x57, 0x70, 0x23, 0x57, 0xe8, + 0xe7, 0x33, 0x32, 0x98, 0xfc, 0x9b, 0x8e, 0x6e, 0x7b, + 0xaa, 0x5d, 0xb5, 0x4e, 0xe0, 0x5d, 0x97, 0xa3, 0xea, + 0x43, 0x7e, 0xb3, 0xa4, 0x8c, 0xcf, 0xdc, 0xc0, 0x51, + 0xa7, 0x99, 0x45, 0x3d, 0x3c, 0xa0, 0xba, 0xc5, 0xff, + 0xe1, 0x89, 0xb3, 0x7d, 0xc3, 0xdc, 0xe2, 0x23, 0x81, + 0xff, 0xa9, 0xc7, 0x93, 0xc6, 0x67, 0xad, 0x94, 0xcf, + 0xeb, 0x91, 0x78, 0x15, 0x25, 0xf7, 0xf5, 0x06, 0x08, + 0x2f, 0x0c, 0xee, 0x0b, 0x6a, 0x06, 0x59, 0xe0, 0x1f, + 0x2e, 0x5a, 0x12, 0x06, 0xf5, 0xf4, 0x8e, 0x75, 0x57, + 0xa9, 0x33, 0x23, 0x0f, 0xc2, 0x6f, 0x02, 0xf8, 0x68, + 0x0f, 0x62, 0x02, 0x81, 0xfe, 0x03, 0x7c, 0xaf, 0xd7, + 0x42, 0x5b, 0xcc, 0xe7, 0x2b, 0xea, 0x49, 0xab, 0x03, + 0x6d, 0x0a, 0x02, 0xae, 0x47, 0x79, 0xce, 0xfd, 0x18, + 0x76, 0x07, 0x9e, 0xa6, 0xbf, 0x7e, 0x8d, 0x73, 0xf9, + 0x44, 0xeb, 0x8c, 0xc5, 0x59, 0xb7, 0x19, 0xf6, 0x73, + 0x53, 0x42, 0x2a, 0x55, 0x7b, 0xb4, 0x56, 0x49, 0x08, + 0x9e, 0x9a, 0x65, 0x60, 0x70, 0x1d, 0xbd, 0xc6, 0x85, + 0x29, 0xde, 0xfe, 0x44, 0xae, 0xdf, 0x25, 0xfd, 0x5b, + 0x74, 0x6c, 0x96, 0xe6, 0x81, 0x37, 0x80, 0xe0, 0x9e, + 0xf3, 0x75, 0x63, 0xb4, 0xc9, 0x2f, 0x71, 0xe6, 0xeb, + 0xdf, 0xaf, 0x7e, 0xff, 0x9e, 0xe0, 0xbf, 0xca, 0xca, + 0x11, 0xed, 0xc6, 0x04, 0xd8, 0x49, 0x13, 0x2c, 0x63, + 0xf1, 0xb3, 0x17, 0x74, 0xd9, 0x50, 0x3f, 0xb9, 0x29, + 0x0e, 0x48, 0xa7, 0xf0, 0xdc, 0x78, 0x18, 0x0e, 0x9f, + 0xb7, 0xde, 0x36, 0x79, 0x67, 0xa4, 0x23, 0x08, 0xe7, + 0x62, 0xe8, 0xa4, 0xe5, 0xcf, 0xff, 0x35, 0x55, 0x36, + 0x2e, 0x3a, 0xe4, 0x45, 0x6a, 0x80, 0xf2, 0xca, 0xe7, + 0x40, 0x79, 0x14, 0xc4, 0x62, 0x38, 0xbb, 0xd0, 0x4e, + 0x6c, 0xb5, 0x85, 0x42, 0x3f, 0x35, 0xf7, 0xd7, 0x54, + 0xb8, 0x2b, 0x8b, 0xd5, 0x6f, 0x16, 0x61, 0x27, 0x23, + 0xac, 0xdb, 0xea, 0x9b, 0x3b, 0x99, 0xcd, 0x79, 0xe6, + 0x12, 0x09, 0x99, 0x09, 0xa4, 0xe1, 0x88, 0x25, 0x00, + 0x9e, 0x60, 0x16, 0x63, 0xd7, 0x42, 0x9b, 0xcc, 0x36, + 0x9a, 0x8d, 0xa3, 0x75, 0x36, 0xa1, 0xa8, 0xfc, 0xa2, + 0xfe, 0x29, 0x26, 0x4c, 0x93, 0x21, 0x44, 0x6b, 0x1c, + 0xba, 0xbd, 0xef, 0xff, 0x6d, 0x1f, 0x2b, 0x6c, 0x66, + 0x81, 0x9a, 0x3a, 0x1d, 0x0b, 0xd7, 0x24, 0xd4, 0xb8, + 0x93, 0xb5, 0x22, 0xf9, 0xd2, 0xf4, 0xa5, 0x05, 0x78, + 0x38, 0xae, 0x58, 0xf6, 0x50, 0x8f, 0x47, 0x1d, 0xf3, + 0xfb, 0x0d, 0x04, 0x14, 0xd1, 0xd6, 0xd8, 0x2e, 0xf2, + 0xbd, 0xf5, 0x71, 0x86, 0x4c, 0xdd, 0x61, 0x24, 0x18, + 0x5b, 0x54, 0xf5, 0xcd, 0x99, 0x89, 0x01, 0x8e, 0xd1, + 0x19, 0x52, 0xbc, 0x45, 0xed, 0x0e, 0xec, 0x72, 0x2f, + 0x5a, 0xe7, 0xdf, 0x36, 0x1c, 0x57, 0x9f, 0xb2, 0x8b, + 0xf2, 0x78, 0x1b, 0x3e, 0xc5, 0x48, 0x1f, 0x27, 0x04, + 0x76, 0x10, 0x44, 0xee, 0x5c, 0x68, 0x8f, 0xca, 0xd7, + 0x31, 0xfc, 0x5c, 0x40, 0x03, 0x2e, 0xbd, 0x1d, 0x59, + 0x13, 0x57, 0xbc, 0x33, 0xc6, 0xa1, 0xa3, 0xe5, 0x55, + 0x79, 0x9b, 0x7e, 0x49, 0xbb, 0x23, 0x96, 0xc3, 0x1c, + 0xfe, 0x66, 0xeb, 0x5b, 0x5f, 0xe5, 0x03, 0xc9, 0xa4, + 0xac, 0x4d, 0xc4, 0x50, 0xbb, 0xd3, 0xc1, 0x91, 0x48, + 0xe0, 0x93, 0x92, 0x2a, 0xdb, 0x41, 0x37, 0x98, 0xbc, + 0xa2, 0x7a, 0x09, 0x92, 0x0b, 0x1c, 0xe6, 0x4b, 0x1e, + 0x8e, 0x78, 0x81, 0x74, 0x7d, 0x6b, 0x71, 0xd5, 0xe7, + 0x0e, 0x7b, 0xc2, 0x74, 0x5d, 0x89, 0xf1, 0xfa, 0x59, + 0xaa, 0xf7, 0x86, 0x66, 0x7e, 0xc2, 0x9c, 0xf4, 0xd5, + 0x8d, 0xc0, 0xb7, 0xb7, 0xa2, 0xd5, 0xcd, 0x51, 0xc3, + 0x7d, 0xa9, 0x5e, 0x46, 0xba, 0x06, 0xa3, 0x4d, 0x60, + 0xd6, 0x68, 0xc6, 0xf9, 0x63, 0x88, 0x17, 0x5c, 0x20, + 0xe1, 0xc4, 0x0f, 0x3f, 0xc1, 0xa9, 0xa7, 0x3e, 0x39, + 0xef, 0x2f, 0xaf, 0xc4, 0x69, 0x29, 0xe3, 0xd4, 0x8d, + 0xe0, 0x0e, 0x88, 0xc2, 0x93, 0x43, 0xfb, 0x28, 0xcf, + 0x5d, 0x85, 0x50, 0xf7, 0xeb, 0x42, 0xf5, 0x87, 0xde, + 0xa5, 0x65, 0xef, 0x43, 0x0c, 0x57, 0x76, 0x09, 0xf4, + 0x5f, 0xde, 0x81, 0x0a, 0xd9, 0x59, 0x41, 0xa4, 0x6a, + 0xb7, 0x05, 0xc7, 0xa5, 0xfe, 0x49, 0xd5, 0x9b, 0x57, + 0x13, 0x14, 0x66, 0xe2, 0xb9, 0xcc, 0x09, 0x35, 0xd4, + 0xb0, 0xe0, 0xd1, 0x0d, 0x7e, 0x50, 0x48, 0x45, 0x21, + 0x00, 0x67, 0xb2, 0xad, 0xa7, 0x46, 0xe2, 0x6f, 0x70, + 0xe5, 0x3c, 0x88, 0x04, 0xaa, 0x21, 0xde, 0x03, 0xb6, + 0x6f, 0xfe, 0x43, 0x51, 0xdc, 0x2e, 0x5c, 0x6c, 0x77, + 0x8f, 0x8e, 0x9d, 0x1a, 0x5b, 0x35, 0xc5, 0xe4, 0x48, + 0x82, 0x17, 0x4b, 0xf0, 0xea, 0xc9, 0x0e, 0xd2, 0x8f, + 0xcd, 0xd5, 0x01, 0xbd, 0x7f, 0x0f, 0xf5, 0xae, 0x92, + 0x28, 0x1e, 0x2c, 0xf4, 0xe9, 0x03, 0xf7, 0x0a, 0xeb, + 0x84, 0x18, 0xa1, 0x37, 0x38, 0x8a, 0x11, 0xa2, 0x5d, + 0x8c, 0xf6, 0xe4, 0x3f, 0x5b, 0x87, 0x07, 0x6b, 0xb4, + 0x07, 0xe0, 0x8f, 0x30, 0xc4, 0xfa, 0x27, 0xae, 0xfc, + 0x02, 0xd1, 0x21, 0x5c, 0xbc, 0x0b, 0x93, 0x6e, 0x7e, + 0xf9, 0x6b, 0x80, 0x7a, 0x25, 0x84, 0x20, 0xf1, 0x6a, + 0xfa, 0x75, 0xed, 0x57, 0x61, 0x62, 0xa7, 0xf6, 0x5b, + 0xe1, 0xb0, 0x38, 0xc8, 0xe9, 0x6d, 0x3f, 0xef, 0x1e, + 0x99, 0x0b, 0xb7, 0xc8, 0x9f, 0x76, 0x5c, 0x04, 0x1f, + 0x02, 0x92, 0x00, 0xa7, 0x38, 0x3d, 0x00, 0x3b, 0xa7, + 0xbc, 0x39, 0x6e, 0xab, 0xf5, 0x10, 0xa8, 0xba, 0xd6, + 0x28, 0x6b, 0x0e, 0x00, 0x48, 0xf9, 0x3b, 0x5c, 0xde, + 0x59, 0x93, 0x46, 0xd6, 0x61, 0x52, 0x81, 0x71, 0x0f, + 0x0e, 0x61, 0xac, 0xc6, 0x7f, 0x15, 0x93, 0xa7, 0xc1, + 0x16, 0xb5, 0xef, 0x85, 0xd1, 0xa7, 0x61, 0xc2, 0x85, + 0x1d, 0x61, 0xc6, 0xae, 0xb3, 0x9e, 0x8d, 0x23, 0xa3, + 0xc8, 0xd5, 0xf2, 0xc7, 0x1b, 0x7e, 0xef, 0xd2, 0xdf, + 0x25, 0xaf, 0x4e, 0x81, 0x15, 0x59, 0xe5, 0x36, 0xb1, + 0xf1, 0xd5, 0xda, 0x58, 0xd8, 0xd9, 0x0d, 0x6d, 0xc9, + 0x25, 0xb5, 0xe8, 0x1d, 0x3b, 0xca, 0x2d, 0xab, 0xf2, + 0xe2, 0xe9, 0x55, 0xd7, 0xf4, 0xc7, 0xd0, 0x57, 0x7a, + 0x86, 0x15, 0x0a, 0x5a, 0x8b, 0xd7, 0x3f, 0x66, 0x0f, + 0x80, 0xb4, 0xe0, 0x5c, 0x33, 0xed, 0xaf, 0x1b, 0x3b, + 0x6d, 0x1c, 0xd9, 0x8c, 0xb5, 0x96, 0xa3, 0xfb, 0xcf, + 0xcc, 0x97, 0x1c, 0xae, 0x06, 0x19, 0x41, 0x61, 0xf8, + 0x97, 0x6b, 0x82, 0x5e, 0x1c, 0xbf, 0x6f, 0x43, 0x3d, + 0xe5, 0x00, 0xf5, 0xfe, 0x66, 0x48, 0x26, 0x31, 0xa1, + 0x72, 0x67, 0x6e, 0xd4, 0x5b, 0x6f, 0x66, 0xde, 0x70, + 0x8b, 0x2b, 0xc3, 0xa2, 0x30, 0xe9, 0x55, 0xc8, 0xff, + 0xf8, 0xd0, 0xdd, 0xa9, 0x21, 0x85, 0x6e, 0x6c, 0x82, + 0x66, 0xcc, 0x52, 0xf0, 0x9e, 0x1e, 0xb5, 0x3a, 0xff, + 0x4c, 0xf3, 0xae, 0x02, 0xc3, 0x4b, 0x76, 0x25, 0xbd, + 0xb0, 0x21, 0x54, 0x61, 0xda, 0x16, 0xd3, 0x23, 0x86, + 0x41, 0xa1, 0x4c, 0x59, 0x15, 0x95, 0x65, 0x85, 0xb6, + 0x8e, 0xa6, 0x37, 0xc0, 0xa2, 0x71, 0x1d, 0x67, 0x44, + 0x7b, 0xe5, 0x4c, 0x4f, 0xb6, 0x2c, 0x46, 0xf7, 0x29, + 0xa5, 0xf2, 0xd3, 0x51, 0x19, 0x91, 0x4d, 0xa7, 0xb5, + 0x05, 0xb9, 0x6e, 0x61, 0x6e, 0xf8, 0xc0, 0x01, 0xe5, + 0x41, 0x0a, 0x89, 0x64, 0x77, 0xf2, 0xc8, 0x63, 0x2d, + 0x9d, 0x27, 0x7f, 0x47, 0x30, 0x39, 0xdf, 0xb6, 0x6e, + 0x4f, 0x00, 0x3f, 0x15, 0xc6, 0xaf, 0x62, 0xdf, 0x3f, + 0x47, 0xe8, 0x42, 0x90, 0x77, 0x23, 0x7a, 0xaa, 0x99, + 0x53, 0x03, 0x63, 0x60, 0x59, 0x07, 0x52, 0x3c, 0xb5, + 0x67, 0x59, 0xfe, 0x08, 0xe6, 0x43, 0x0f, 0x3b, 0x08, + 0x7c, 0xc7, 0x07, 0x3c, 0xfa, 0x65, 0xea, 0x69, 0x51, + 0x41, 0x31, 0xb3, 0x05, 0x69, 0xba, 0x2c, 0xbf, 0x89, + 0x25, 0x9e, 0xfe, 0x07, 0x13, 0x78, 0x0e, 0x16, 0x54, + 0xdf, 0x23, 0xdf, 0x10, 0x69, 0x79, 0xd0, 0x33, 0xd7, + 0x21, 0x8b, 0xc8, 0x2a, 0xd0, 0x74, 0x0a, 0xfa, 0xb1, + 0x6f, 0xa3, 0xcb, 0x1d, 0xca, 0x4f, 0x00, 0x46, 0x6c, + 0x42, 0x09, 0xe0, 0x30, 0x89, 0x08, 0x33, 0x9b, 0x7b, + 0x7b, 0x0f, 0x69, 0x5c, 0x0d, 0x34, 0x91, 0xfc, 0xfe, + 0x22, 0x82, 0x02, 0xcd, 0xfa, 0x97, 0xe8, 0x28, 0x1d, + 0xbc, 0x13, 0x0b, 0xfd, 0x47, 0xa1, 0x7e, 0xa2, 0x86, + 0x4d, 0x6f, 0x12, 0x51, 0x35, 0x7d, 0x76, 0x8a, 0x58, + 0x05, 0xb6, 0x39, 0xa1, 0x2f, 0xd7, 0xda, 0xaf, 0x00, + 0xa0, 0x1a, 0x94, 0xd8, 0x23, 0x34, 0x99, 0x5c, 0xaf, + 0xcc, 0x15, 0x4b, 0x56, 0xb2, 0xd2, 0x81, 0x07, 0xd3, + 0xf3, 0x47, 0xa2, 0x45, 0x93, 0xcb, 0xae, 0xa7, 0x6b, + 0x3f, 0xf9, 0xea, 0xfc, 0x0e, 0x64, 0xf2, 0x93, 0x7f, + 0x24, 0x22, 0x73, 0x86, 0xc7, 0x2d, 0x75, 0x9b, 0x41, + 0x8b, 0xfb, 0x3b, 0x26, 0x2a, 0xe5, 0x0b, 0xd4, 0x00, + 0xe3, 0x2c, 0x69, 0x49, 0x62, 0x6c, 0x13, 0x58, 0x6e, + 0xac, 0x43, 0xe5, 0x2b, 0x3b, 0x88, 0xdc, 0xd4, 0x41, + 0xe8, 0xee, 0x4e, 0xc3, 0x28, 0x91, 0x17, 0x9a, 0x5a, + 0xdb, 0x80, 0x8b, 0x4d, 0x64, 0xcc, 0xbe, 0x66, 0xa4, + 0x62, 0xfb, 0x13, 0x44, 0x10, 0xd9, 0xe4, 0xd5, 0xa5, + 0xae, 0x9e, 0x42, 0x50, 0xfc, 0x78, 0xad, 0xfa, 0xc4, + 0xd0, 0x5a, 0x60, 0x9b, 0x45, 0x2b, 0x61, 0x5c, 0x57, + 0xb5, 0x92, 0x28, 0xe9, 0xf5, 0x35, 0x67, 0xc1, 0x5e, + 0xa8, 0x1c, 0x99, 0x36, 0x38, 0xb8, 0x5c, 0xff, 0x3d, + 0xa0, 0xfc, 0xb0, 0xbc, 0x3d, 0x2c, 0xb4, 0x36, 0x17, + 0xb4, 0x6d, 0xb5, 0x39, 0x45, 0xa9, 0x2a, 0x6b, 0xa2, + 0x24, 0x44, 0x30, 0xab, 0x2c, 0x82, 0x36, 0xdc, 0xd6, + 0x36, 0x5d, 0x0a, 0xdc, 0xee, 0x0f, 0x2b, 0x28, 0x99, + 0xdc, 0x67, 0x0d, 0xea, 0x6e, 0x42, 0xb9, 0x45, 0x7f, + 0xd2, 0x96, 0x1e, 0x60, 0x42, 0xeb, 0x1e, 0x5f, 0x8e, + 0xa9, 0xdc, 0xd3, 0x8a, 0xd6, 0xbd, 0x4e, 0x1f, 0x42, + 0x75, 0x1d, 0xe2, 0xc6, 0x11, 0xc9, 0x80, 0x1f, 0xfe, + 0x99, 0x52, 0x4d, 0x7b, 0x35, 0xf7, 0xb7, 0xc3, 0xee, + 0xd6, 0x94, 0xf5, 0x74, 0xa0, 0x69, 0xcd, 0x1f, 0x2b, + 0xd0, 0x87, 0xf7, 0x8c, 0x69, 0xc5, 0x96, 0x70, 0x91, + 0xe8, 0x3d, 0xd2, 0xcc, 0xf1, 0x4c, 0xcd, 0xe2, 0x14, + 0x00, 0x10, 0x4a, 0xd9, 0x6a, 0x5d, 0x65, 0x2c, 0x4b, + 0x79, 0x0c, 0xc4, 0x78, 0x5e, 0xc8, 0xc5, 0x37, 0x74, + 0x6d, 0x50, 0x5c, 0x34, 0x1f, 0xe0, 0xf4, 0xe3, 0xe1, + 0x86, 0x68, 0xb1, 0xea, 0x70, 0xf0, 0xae, 0xe4, 0x59, + 0xa1, 0x08, 0x7e, 0x35, 0xa3, 0x16, 0xd2, 0xb0, 0xa3, + 0xd4, 0xb0, 0x74, 0x8c, 0x05, 0x79, 0x73, 0xfb, 0xe6, + 0x65, 0x96, 0x15, 0x07, 0xd5, 0xaf, 0x88, 0x9e, 0x6b, + 0xf0, 0xbb, 0x3f, 0xe6, 0xd1, 0x6a, 0xe7, 0xc9, 0xae, + 0xd9, 0xb0, 0x16, 0x1c, 0x40, 0xeb, 0xdb, 0xc1, 0xbf, + 0x83, 0xdb, 0x8a, 0x4f, 0x96, 0xca, 0xd7, 0x22, 0x06, + 0x87, 0x08, 0x9d, 0x65, 0x2f, 0xd9, 0x8e, 0x95, 0x6c, + 0xcc, 0xbf, 0x76, 0x2a, 0xea, 0x5c, 0x8e, 0x5b, 0x17, + 0x0f, 0x75, 0x7b, 0xfa, 0xf9, 0xfb, 0xaa, 0x92, 0xc7, + 0x7e, 0x63, 0x63, 0x54, 0xa4, 0xff, 0xf6, 0xc0, 0xc0, + 0xf5, 0x70, 0xd8, 0xe3, 0xa4, 0x79, 0x16, 0xf0, 0x6f, + 0x90, 0x5e, 0xb7, 0xab, 0x6f, 0xab, 0x75, 0x3b, 0xe1, + 0x4c, 0xa8, 0x0b, 0x72, 0x5f, 0x5f, 0x11, 0x22, 0x36, + 0x71, 0x20, 0xd3, 0x5b, 0x5e, 0x07, 0x06, 0x76, 0x1a, + 0xcc, 0x5e, 0x7c, 0x97, 0x7d, 0xb2, 0x6b, 0xf8, 0x39, + 0x89, 0x37, 0xb6, 0x6d, 0xea, 0x74, 0x57, 0x28, 0xd7, + 0x0e, 0x9b, 0xeb, 0x28, 0x88, 0x90, 0xfd, 0x2d, 0x16, + 0x21, 0x74, 0x26, 0xc5, 0xb8, 0x44, 0xad, 0x9f, 0x97, + 0xf9, 0x65, 0x36, 0xd8, 0x00, 0x59, 0x17, 0x49, 0xf9, + 0xc7, 0xb3, 0x84, 0xb9, 0xe2, 0x95, 0xe0, 0xd1, 0x7f, + 0x5f, 0xaa, 0xd7, 0xfd, 0x6a, 0x6a, 0x83, 0x14, 0x46, + 0x1d, 0x12, 0x8d, 0x09, 0xc3, 0xa5, 0xca, 0x72, 0xa3, + 0x25, 0x65, 0xb6, 0x40, 0x25, 0x04, 0x51, 0xab, 0x22, + 0xeb, 0xd7, 0x69, 0xc9, 0x22, 0x9c, 0xa0, 0x19, 0x5c, + 0x1a, 0xfd, 0x41, 0x8f, 0x98, 0xc5, 0x71, 0xb8, 0x6f, + 0x76, 0xae, 0xfa, 0x9b, 0x03, 0xab, 0x43, 0x81, 0x3b, + 0x66, 0xae, 0xf0, 0xd2, 0xb7, 0xee, 0x9a, 0xe3, 0xae, + 0x45, 0xc1, 0x86, 0xb0, 0xce, 0x9e, 0x2b, 0xec, 0xb8, + 0xcf, 0xca, 0x0e, 0x8c, 0x33, 0xfa, 0xa7, 0xef, 0xf7, + 0xfc, 0xa1, 0x41, 0x49, 0xd3, 0x6d, 0xb5, 0x58, 0xe4, + 0x0e, 0x24, 0xd2, 0x8a, 0x74, 0xc9, 0x56, 0x2e, 0x53, + 0xc7, 0x7a, 0x38, 0x0f, 0x4b, 0xd9, 0xf9, 0x2f, 0xfa, + 0x7d, 0xee, 0x14, 0x18, 0xce, 0x75, 0x42, 0x6c, 0x03, + 0x34, 0xce, 0x80, 0xec, 0xf2, 0x05, 0xf0, 0xdf, 0xcd, + 0xf8, 0xdb, 0x26, 0x7d, 0xb6, 0x3d, 0x28, 0x24, 0x7e, + 0x7e, 0x39, 0x9f, 0xa6, 0xc6, 0xeb, 0x2a, 0xc8, 0x17, + 0x94, 0xa9, 0x89, 0xf5, 0xdf, 0xcb, 0x77, 0xfd, 0xc9, + 0x9e, 0x68, 0x98, 0x7d, 0x04, 0x50, 0x3c, 0x64, 0x1d, + 0x66, 0xb0, 0x97, 0x06, 0xb6, 0x08, 0x5b, 0xe4, 0x17, + 0x44, 0xd6, 0x94, 0x39, 0x6b, 0x03, 0x2c, 0xcb, 0x5a, + 0x8d, 0x86, 0x08, 0x23, 0x4f, 0x95, 0xa8, 0x1a, + }, + .msg_len = 64, + .msg = + (const u8[64]) { + 0x1a, 0x84, 0x21, 0x0d, 0x35, 0x7a, 0x88, 0xc8, + 0x6a, 0x11, 0xe3, 0x15, 0x24, 0xec, 0x0d, 0x2e, + 0x76, 0xb9, 0xcf, 0x2b, 0x04, 0x25, 0x16, 0xae, + 0x62, 0x42, 0xa0, 0x20, 0x68, 0x25, 0x3e, 0xb4, + 0x75, 0xa7, 0x1d, 0x64, 0xc3, 0xd1, 0x08, 0x07, + 0x67, 0xb6, 0xf7, 0x76, 0x76, 0xf6, 0xd6, 0x62, + 0x66, 0x04, 0x89, 0x0c, 0x8f, 0x07, 0xac, 0xc8, + 0x51, 0x77, 0xd9, 0x47, 0x5e, 0xb5, 0x22, 0x20, + }, + .sig_len = MLDSA65_SIGNATURE_SIZE, + .sig = + (const u8[MLDSA65_SIGNATURE_SIZE]) { + 0xda, 0xcf, 0x8d, 0x67, 0x59, 0x60, 0x6c, 0x39, 0x2d, + 0x89, 0xb6, 0xa1, 0xf3, 0x8c, 0x70, 0xcf, 0x25, 0x86, + 0x21, 0xa1, 0x9f, 0x20, 0x9e, 0xf5, 0xd2, 0xdd, 0xbd, + 0x99, 0xfa, 0xe4, 0xab, 0x77, 0x31, 0x65, 0x18, 0xa1, + 0xd1, 0x3f, 0x21, 0x70, 0x36, 0xe1, 0xf9, 0x5c, 0x28, + 0xb6, 0x7d, 0x34, 0xae, 0x66, 0xc9, 0x1c, 0x8e, 0xc6, + 0xf9, 0x45, 0x8c, 0xa9, 0xb2, 0xfb, 0x0f, 0x5b, 0xb8, + 0xf9, 0xf5, 0xe2, 0x37, 0x79, 0x12, 0xda, 0xa7, 0x72, + 0x9e, 0x0d, 0xf8, 0x88, 0x5b, 0x34, 0x49, 0x6c, 0xed, + 0xa3, 0x7f, 0x86, 0xd3, 0xd9, 0x2f, 0x44, 0x08, 0x0d, + 0xb7, 0xdb, 0x4a, 0xce, 0x02, 0x14, 0x02, 0xd6, 0x40, + 0x75, 0xe3, 0xc0, 0x97, 0xfc, 0x6c, 0x6a, 0x88, 0x29, + 0x0c, 0xe2, 0x3a, 0x2b, 0x28, 0x82, 0x8f, 0x27, 0x09, + 0x69, 0x91, 0xc6, 0xc3, 0xb7, 0x07, 0x61, 0x86, 0x8d, + 0x89, 0x8a, 0xd5, 0x00, 0x3b, 0x4b, 0xfc, 0x6f, 0xb3, + 0x3f, 0x4c, 0x93, 0x31, 0xfc, 0x88, 0x53, 0x26, 0xea, + 0xe5, 0x3a, 0xfc, 0xc1, 0x59, 0x16, 0xf0, 0xb7, 0xac, + 0xde, 0x1e, 0xd8, 0x74, 0x85, 0x72, 0xd9, 0xbb, 0xbe, + 0x76, 0x32, 0x25, 0x9d, 0x21, 0xbc, 0xfd, 0x8d, 0x32, + 0xfe, 0xae, 0x24, 0xe5, 0x4a, 0xcc, 0x5d, 0x15, 0x23, + 0xd3, 0x57, 0xe7, 0xa9, 0x2c, 0x31, 0xd7, 0xc5, 0x6b, + 0x70, 0x6c, 0x22, 0x5a, 0x13, 0x1f, 0x76, 0x13, 0x78, + 0x6f, 0xac, 0x42, 0x4c, 0x46, 0x81, 0xa2, 0x20, 0x91, + 0x30, 0xed, 0xcb, 0x90, 0xfe, 0x3c, 0xa3, 0xc7, 0xb4, + 0x1f, 0x21, 0x1d, 0x98, 0x74, 0x6a, 0x3e, 0xc8, 0xcc, + 0xd2, 0x68, 0x87, 0x69, 0xa9, 0xdf, 0x50, 0xd5, 0x0a, + 0x8e, 0x10, 0x54, 0xab, 0xea, 0x65, 0x2a, 0x52, 0xd7, + 0x22, 0xae, 0x2f, 0x1e, 0xc3, 0x16, 0x58, 0x20, 0x18, + 0x6d, 0x35, 0x46, 0x31, 0x43, 0x5d, 0x62, 0xfb, 0xb1, + 0x47, 0x32, 0xfa, 0x14, 0xcc, 0x51, 0xa3, 0xcd, 0x99, + 0x4f, 0x97, 0x0f, 0xca, 0x24, 0x93, 0x17, 0xea, 0xa3, + 0xf3, 0x1f, 0xbe, 0xb5, 0xa3, 0xac, 0x80, 0xcc, 0x20, + 0x3b, 0xa6, 0xd3, 0x32, 0x72, 0x4e, 0xd9, 0x25, 0xf9, + 0xc2, 0x24, 0x15, 0xbd, 0x1e, 0x1e, 0x41, 0x8c, 0x18, + 0x8c, 0x58, 0xe8, 0x75, 0x20, 0xff, 0xa3, 0xf4, 0xd4, + 0xab, 0x75, 0x78, 0x4e, 0xbb, 0x7c, 0x94, 0x93, 0x28, + 0x5b, 0x07, 0x3a, 0x3c, 0xc9, 0xf1, 0x55, 0x3e, 0x33, + 0xed, 0xf8, 0x72, 0x55, 0xab, 0x5a, 0xea, 0xbe, 0x65, + 0xfa, 0x81, 0x50, 0xc0, 0x9d, 0x2d, 0xfb, 0x04, 0x25, + 0x7c, 0xb9, 0xee, 0xe2, 0xa3, 0x00, 0x44, 0xd3, 0x9d, + 0xee, 0x4f, 0x80, 0x77, 0xfb, 0x26, 0x6b, 0x07, 0xd0, + 0xff, 0x82, 0x39, 0x0e, 0x2b, 0x47, 0xa3, 0xe7, 0x3e, + 0xc5, 0x4e, 0x15, 0x8a, 0x48, 0x28, 0xfb, 0xf7, 0xa4, + 0x86, 0xfb, 0x77, 0x60, 0xcd, 0xc5, 0x68, 0x96, 0xd7, + 0x4c, 0x3c, 0xf2, 0x51, 0x71, 0x79, 0x2e, 0x2e, 0x57, + 0x10, 0xa7, 0xfc, 0xd1, 0xd4, 0x61, 0x71, 0x81, 0x85, + 0x74, 0x09, 0x7d, 0x80, 0xd0, 0xc2, 0xe9, 0xff, 0xb7, + 0x88, 0x53, 0x74, 0x1e, 0xb0, 0xca, 0x65, 0x48, 0x8e, + 0xdb, 0x59, 0x3a, 0xcb, 0x80, 0xeb, 0xfd, 0xd2, 0xc9, + 0x38, 0x43, 0xae, 0x76, 0xf2, 0xbb, 0x51, 0xb2, 0xcb, + 0xe6, 0x85, 0x31, 0xb5, 0x62, 0xd4, 0x5e, 0x48, 0x08, + 0xf1, 0x40, 0x5b, 0x16, 0x83, 0x5e, 0xa5, 0x9c, 0x6b, + 0x91, 0x49, 0x44, 0xff, 0x3b, 0xa9, 0x2b, 0xf3, 0x06, + 0x33, 0x9e, 0x6e, 0x3c, 0x66, 0x7e, 0x27, 0xa2, 0x59, + 0x7b, 0xe3, 0xb6, 0xb4, 0x28, 0xeb, 0x93, 0x35, 0x87, + 0xac, 0x0e, 0x0b, 0x7e, 0xbc, 0x35, 0x28, 0x72, 0x1f, + 0x26, 0x59, 0xd0, 0x1f, 0x63, 0xe4, 0x86, 0x5d, 0x70, + 0xf3, 0xa8, 0xa4, 0xb8, 0xcd, 0xb3, 0xf8, 0x8d, 0xaa, + 0x41, 0xd2, 0xcc, 0x0b, 0x15, 0x66, 0x22, 0x83, 0x92, + 0xe3, 0x0b, 0xf9, 0xea, 0xa0, 0x33, 0xa1, 0x4e, 0x92, + 0xae, 0x81, 0x95, 0xa4, 0x58, 0x3f, 0xa9, 0x15, 0x52, + 0xf9, 0xda, 0xb7, 0x10, 0x8d, 0xc6, 0xab, 0x77, 0xe9, + 0xbe, 0xad, 0xc9, 0x3a, 0x6a, 0x8d, 0x92, 0x6c, 0x69, + 0xff, 0x31, 0x49, 0x25, 0x04, 0xc8, 0x93, 0x6f, 0xc8, + 0xe7, 0x60, 0x7a, 0x76, 0xb5, 0xc1, 0x07, 0xef, 0xa3, + 0x39, 0xa6, 0xf2, 0x36, 0x04, 0xde, 0x3c, 0x4a, 0x4e, + 0x96, 0xbd, 0x64, 0x26, 0x80, 0x01, 0x88, 0x47, 0xd2, + 0xa4, 0x46, 0xcd, 0xe1, 0x30, 0x7f, 0xa3, 0x00, 0x11, + 0x38, 0x55, 0xfa, 0xeb, 0x10, 0xeb, 0xa0, 0x65, 0x04, + 0x09, 0xc8, 0xde, 0x9c, 0x73, 0xba, 0x0c, 0xbd, 0xd3, + 0xa5, 0x84, 0x5e, 0xb9, 0x3b, 0xd4, 0x94, 0xbd, 0xa6, + 0x53, 0xbe, 0x93, 0x69, 0x3e, 0xaa, 0x32, 0x31, 0x06, + 0xc8, 0x1b, 0x4a, 0x48, 0xb5, 0x17, 0x85, 0xbf, 0x72, + 0xec, 0xf5, 0x29, 0x8a, 0xd8, 0xeb, 0x99, 0x8b, 0x74, + 0x84, 0x57, 0x8c, 0xe1, 0x85, 0x94, 0xa0, 0xbc, 0x7a, + 0x14, 0xf0, 0xf4, 0x8b, 0x25, 0x37, 0x43, 0xa1, 0x34, + 0x09, 0x71, 0xca, 0x5c, 0x9f, 0x08, 0x38, 0xd9, 0x9c, + 0x0c, 0x0e, 0xcb, 0xe4, 0xad, 0x4b, 0x2a, 0x89, 0x67, + 0xf8, 0x29, 0x6c, 0x69, 0x0e, 0x5d, 0xca, 0xfa, 0xa6, + 0x6b, 0x0e, 0xb5, 0x94, 0x17, 0x71, 0xf0, 0xc9, 0xcd, + 0x02, 0x1d, 0xa5, 0xd5, 0xc6, 0xa7, 0xbc, 0x5f, 0x6e, + 0x67, 0x43, 0x68, 0xce, 0xac, 0x54, 0x81, 0x2a, 0x25, + 0x22, 0x52, 0x35, 0xad, 0x7b, 0xd5, 0x06, 0x8c, 0x00, + 0xfb, 0xca, 0xc4, 0x0a, 0x49, 0x1e, 0xc8, 0xeb, 0x77, + 0xc1, 0x63, 0x23, 0x96, 0xbd, 0x35, 0xfa, 0x13, 0xae, + 0xbf, 0x1d, 0x1e, 0x69, 0x8d, 0xb3, 0xe3, 0x07, 0xde, + 0x4e, 0xd0, 0x12, 0xa9, 0xc3, 0x36, 0x30, 0x46, 0xef, + 0x92, 0x76, 0x17, 0x8f, 0x10, 0xe7, 0xba, 0x99, 0x4b, + 0xdf, 0xad, 0xb8, 0x11, 0x80, 0xdf, 0xe7, 0xfd, 0x80, + 0x64, 0xf7, 0x2a, 0xac, 0x60, 0x2a, 0x54, 0x8f, 0x4f, + 0xaf, 0xaf, 0x60, 0xf9, 0x67, 0x20, 0x80, 0x53, 0x5c, + 0xb6, 0x81, 0xa6, 0x2a, 0x74, 0x2d, 0xc5, 0x74, 0x2a, + 0x95, 0x26, 0x13, 0x17, 0x01, 0xdd, 0x31, 0xac, 0x5a, + 0x05, 0xda, 0xde, 0xba, 0xf6, 0x37, 0x13, 0x8d, 0xe4, + 0xa8, 0x93, 0x46, 0x9e, 0xa9, 0x82, 0x24, 0x7e, 0xc8, + 0xda, 0x63, 0x89, 0xcd, 0x33, 0xc9, 0xf7, 0xf9, 0x71, + 0x35, 0xe6, 0xa5, 0x5f, 0x6b, 0x3b, 0xbb, 0x0c, 0xe0, + 0xa4, 0x0b, 0xe3, 0x29, 0xc0, 0xae, 0x8e, 0xce, 0x03, + 0x09, 0x73, 0x0e, 0x1e, 0x9c, 0xe9, 0x59, 0xb6, 0x8b, + 0x78, 0x67, 0x32, 0x8b, 0xf1, 0x93, 0xcc, 0x72, 0x1b, + 0x6f, 0xa2, 0xf1, 0x04, 0x9c, 0xfa, 0x98, 0x02, 0xca, + 0xdf, 0x35, 0x3c, 0x38, 0xac, 0xa8, 0xdb, 0x90, 0xae, + 0xaa, 0xf9, 0x70, 0xfb, 0xed, 0xbd, 0xa6, 0x25, 0x14, + 0x58, 0x09, 0x8a, 0x36, 0xaf, 0x41, 0x09, 0x19, 0xcb, + 0xd3, 0x25, 0x5d, 0x0e, 0xe6, 0x20, 0x14, 0x71, 0x24, + 0x79, 0x19, 0x55, 0xaf, 0x51, 0x5b, 0xa4, 0xc0, 0x93, + 0x9e, 0xdd, 0x88, 0x31, 0x13, 0x96, 0xbf, 0xca, 0x0a, + 0xd7, 0xbc, 0xc4, 0x00, 0xa1, 0x10, 0x2d, 0x92, 0x79, + 0xf9, 0x14, 0xdb, 0xd2, 0xba, 0x74, 0xfa, 0xa8, 0xe5, + 0x40, 0x14, 0xc2, 0x56, 0x3c, 0x7f, 0x50, 0x07, 0x60, + 0x86, 0x93, 0x51, 0x2e, 0xf9, 0x70, 0x61, 0x70, 0x0e, + 0xa4, 0x87, 0x75, 0xcc, 0x6c, 0x72, 0xb7, 0x68, 0x23, + 0xb7, 0x3d, 0x76, 0xaf, 0x96, 0x9b, 0x4a, 0xe5, 0x12, + 0x28, 0x4a, 0x8f, 0x79, 0x34, 0xff, 0xec, 0x92, 0xeb, + 0x6b, 0xaf, 0xc9, 0xbd, 0xc1, 0x77, 0x07, 0xd0, 0xfa, + 0x55, 0x57, 0x10, 0x0c, 0xad, 0x29, 0x2a, 0x79, 0xd6, + 0x09, 0x9e, 0x7d, 0x18, 0xd4, 0xd6, 0xdd, 0x72, 0x1a, + 0x8f, 0x24, 0x11, 0x70, 0xd2, 0x52, 0x36, 0x0f, 0x38, + 0x79, 0x38, 0x4a, 0x02, 0x4f, 0x73, 0x2a, 0xaa, 0x6a, + 0xb5, 0x0c, 0x72, 0x32, 0x85, 0x21, 0x76, 0x1a, 0x8a, + 0x7d, 0x51, 0x0e, 0xf1, 0xf9, 0x19, 0xfa, 0x6b, 0x9b, + 0x22, 0x71, 0x8c, 0x13, 0xcc, 0xba, 0x7d, 0xee, 0xd8, + 0x34, 0xf6, 0x85, 0x60, 0xe1, 0xe4, 0x59, 0x6e, 0x32, + 0x60, 0xd9, 0xfa, 0xb7, 0x56, 0x54, 0x25, 0xd1, 0x73, + 0x6a, 0xf2, 0xa0, 0xc7, 0xa0, 0x67, 0x10, 0x89, 0x9c, + 0x27, 0x5f, 0x7f, 0x2e, 0x5a, 0x29, 0x70, 0x7a, 0x7b, + 0xaf, 0x21, 0xd0, 0xf4, 0x06, 0xb9, 0x2d, 0xf1, 0xb8, + 0x32, 0xed, 0xc5, 0xc9, 0xac, 0x2f, 0x54, 0x0a, 0xf9, + 0x08, 0x39, 0x39, 0x7d, 0x1d, 0xaf, 0xb4, 0x5f, 0x4d, + 0x75, 0xc3, 0xe8, 0x52, 0x3a, 0x47, 0x72, 0x2c, 0xa9, + 0x2d, 0xcb, 0x74, 0x06, 0xfe, 0x69, 0xd3, 0xf3, 0x1a, + 0xb2, 0xd3, 0x01, 0xed, 0x6c, 0xc1, 0xca, 0x4f, 0xaf, + 0x11, 0x9b, 0xa2, 0x27, 0x2a, 0x59, 0x56, 0x58, 0xdf, + 0x79, 0x8b, 0xc9, 0x87, 0xe9, 0x58, 0x81, 0x48, 0xc6, + 0xb6, 0x7d, 0x60, 0x54, 0x87, 0x9c, 0x61, 0xbb, 0x4b, + 0xbb, 0x61, 0xac, 0x0a, 0x5a, 0x66, 0x7e, 0x70, 0x8b, + 0xfd, 0x92, 0x76, 0x4a, 0xa9, 0xa5, 0xc3, 0xf4, 0xf2, + 0x93, 0x48, 0xc4, 0xf3, 0x91, 0x2b, 0x60, 0x04, 0x0e, + 0xb0, 0x6b, 0x60, 0x5e, 0xf0, 0xf1, 0x54, 0x41, 0x56, + 0xdc, 0x25, 0x57, 0xc3, 0xb6, 0x0b, 0x5e, 0x15, 0xb5, + 0x2a, 0x36, 0x4f, 0xe7, 0x1d, 0x70, 0xa8, 0xa7, 0xec, + 0xd6, 0x74, 0xba, 0xa4, 0x79, 0x83, 0x7c, 0x9e, 0x1a, + 0x5d, 0x32, 0xc8, 0xcb, 0x41, 0xca, 0x04, 0xec, 0x0b, + 0x18, 0x54, 0xe1, 0x67, 0xbf, 0xa8, 0x7a, 0xc3, 0x0f, + 0x27, 0x2a, 0xaf, 0x2a, 0x41, 0x19, 0x1f, 0xe8, 0xa2, + 0xe8, 0xfa, 0xfc, 0x88, 0x41, 0x46, 0xc3, 0x1c, 0x44, + 0xe5, 0xee, 0x47, 0xec, 0xfe, 0xbf, 0xb8, 0x29, 0x2e, + 0xae, 0x47, 0x0a, 0x42, 0x69, 0x8a, 0x9a, 0x94, 0x97, + 0x9e, 0xf5, 0xb6, 0x37, 0x1c, 0x10, 0xc2, 0x99, 0xa8, + 0xe9, 0x9e, 0x0e, 0x6e, 0xb5, 0xbe, 0xba, 0x1f, 0x77, + 0xa6, 0x35, 0x02, 0x1e, 0x8c, 0xe6, 0x02, 0x53, 0xe2, + 0x9a, 0xdd, 0x09, 0x6e, 0x9b, 0x7a, 0x36, 0x4f, 0x38, + 0x8d, 0x4c, 0xa4, 0xb4, 0xff, 0x90, 0x76, 0x0d, 0x11, + 0x7d, 0xe1, 0xe9, 0x7f, 0x2a, 0x4a, 0x80, 0xe0, 0xd8, + 0x3c, 0x23, 0xd2, 0xa5, 0xe5, 0x39, 0x77, 0xbf, 0x3d, + 0x71, 0x0d, 0x45, 0xbb, 0x39, 0x66, 0x1a, 0x4d, 0x59, + 0xb7, 0xd0, 0x0a, 0xee, 0x87, 0xee, 0x1f, 0xcf, 0x6f, + 0xc2, 0x50, 0xb1, 0xa5, 0x4c, 0xee, 0x40, 0x69, 0xd7, + 0x36, 0x38, 0x14, 0xcd, 0x6a, 0x9a, 0x90, 0x40, 0xad, + 0x76, 0xf1, 0xa6, 0xd4, 0x3c, 0x75, 0x10, 0xba, 0xcb, + 0xab, 0x22, 0x28, 0x5f, 0x0c, 0xe0, 0xee, 0xf4, 0xfd, + 0x61, 0x52, 0x0a, 0x59, 0xfe, 0x61, 0xc5, 0x40, 0xf9, + 0x91, 0x8e, 0x36, 0x29, 0x63, 0x6c, 0x6e, 0x45, 0xa5, + 0x42, 0xe3, 0x36, 0x90, 0xe7, 0x90, 0x9f, 0x58, 0xbb, + 0xf9, 0x1b, 0xee, 0x2c, 0xbb, 0x3a, 0xfd, 0x3d, 0xbe, + 0x3d, 0x45, 0xf0, 0xc2, 0x18, 0xaa, 0x46, 0x10, 0x23, + 0xe9, 0x63, 0xba, 0x7f, 0xc2, 0xe1, 0xf4, 0x05, 0xdd, + 0x4a, 0x7c, 0xa8, 0xab, 0xa9, 0xbd, 0x6f, 0xdf, 0x48, + 0x59, 0x11, 0xd4, 0xba, 0x75, 0xb6, 0x22, 0xd4, 0xd7, + 0x35, 0x6f, 0x27, 0x70, 0xc7, 0x3d, 0x90, 0x06, 0x39, + 0x2a, 0x16, 0xd0, 0x8b, 0xd7, 0xfb, 0x5e, 0x85, 0x2e, + 0xb0, 0xd8, 0xc7, 0xdb, 0xe5, 0x24, 0x3a, 0x6e, 0xc4, + 0x5e, 0xd4, 0x22, 0x25, 0x14, 0xee, 0xa5, 0x30, 0x8b, + 0xd6, 0x27, 0x61, 0x33, 0x13, 0x46, 0x0b, 0x26, 0x45, + 0xa6, 0xb4, 0xfa, 0x8d, 0xa3, 0xf2, 0x27, 0xd2, 0xc5, + 0x04, 0xaa, 0x96, 0xa4, 0x55, 0xfa, 0x40, 0xf1, 0xfc, + 0x66, 0x33, 0x9e, 0x4b, 0x39, 0x75, 0xae, 0x7f, 0x52, + 0x87, 0x7b, 0x8a, 0xf9, 0x7d, 0x5f, 0x8a, 0x7e, 0xf7, + 0xfe, 0xc4, 0x7f, 0xf4, 0xf6, 0x9a, 0x86, 0x78, 0x21, + 0x02, 0x94, 0x9e, 0x50, 0x2d, 0xdc, 0xd6, 0xa5, 0x53, + 0xf1, 0xef, 0x06, 0xe8, 0xb5, 0x46, 0x81, 0xcc, 0x91, + 0x4f, 0x37, 0xee, 0x27, 0xcb, 0x91, 0xad, 0xff, 0x1d, + 0xd1, 0x00, 0xa8, 0x96, 0x22, 0xaa, 0x63, 0x23, 0x2a, + 0x7a, 0x75, 0x6f, 0xe9, 0x2d, 0x26, 0xde, 0x11, 0x97, + 0x4b, 0x17, 0x3f, 0xde, 0x51, 0x1a, 0x22, 0xed, 0x38, + 0x6f, 0x3e, 0x7a, 0xd0, 0xd6, 0x60, 0x06, 0x7e, 0x3f, + 0xa4, 0x29, 0xfa, 0x18, 0x91, 0xda, 0x73, 0x38, 0xe3, + 0xe3, 0xb5, 0xc0, 0x5b, 0x4e, 0xe8, 0x94, 0xea, 0x45, + 0x6e, 0x5b, 0x50, 0xaa, 0x38, 0xb6, 0x6f, 0xdb, 0x90, + 0x1b, 0x3b, 0x82, 0xbb, 0x0d, 0x38, 0xe3, 0xca, 0xd9, + 0xf1, 0x2e, 0x27, 0x4c, 0x2c, 0x5a, 0x42, 0xdf, 0x44, + 0xc8, 0x07, 0xe4, 0x95, 0xb5, 0xec, 0x91, 0x34, 0x1c, + 0x9a, 0x0c, 0x50, 0x1a, 0xce, 0x67, 0xe4, 0x4b, 0x87, + 0x61, 0x43, 0x95, 0x95, 0xb8, 0x8a, 0xf4, 0xc9, 0x92, + 0x33, 0x33, 0xe3, 0xfe, 0x98, 0x2a, 0xae, 0x8e, 0xf2, + 0x6b, 0x13, 0x7c, 0xe4, 0x44, 0x40, 0x66, 0xea, 0x0c, + 0xe4, 0xdb, 0x16, 0x65, 0xa8, 0x8b, 0x37, 0x08, 0xec, + 0x1e, 0xfc, 0xa6, 0xd0, 0x9b, 0x9e, 0x0a, 0xd2, 0xe3, + 0xcf, 0x5d, 0xb2, 0xaf, 0x8e, 0x05, 0x7d, 0x8d, 0x84, + 0xbc, 0x9f, 0xb1, 0xe6, 0x6a, 0x2e, 0x4b, 0x6d, 0x64, + 0x91, 0x17, 0x9d, 0xb5, 0x35, 0x15, 0x02, 0xe9, 0x1b, + 0x85, 0xc1, 0x89, 0xc2, 0x5a, 0x32, 0x3a, 0x80, 0x78, + 0x5e, 0xcc, 0x50, 0x26, 0xf5, 0x11, 0x01, 0x79, 0xf3, + 0xaf, 0xb6, 0x40, 0x00, 0x73, 0x8f, 0xeb, 0x5a, 0xd1, + 0x26, 0x00, 0xe2, 0xa3, 0xcd, 0xfd, 0xaa, 0x15, 0x5b, + 0x98, 0x2a, 0x76, 0x41, 0x07, 0xc2, 0xde, 0xb6, 0x71, + 0xe7, 0xc3, 0xe9, 0x92, 0xb3, 0xd8, 0xfe, 0xaf, 0x12, + 0x61, 0x86, 0x5b, 0x6e, 0x74, 0x45, 0x7b, 0x9b, 0x6f, + 0x1a, 0x13, 0x84, 0xf6, 0x31, 0x5f, 0x5b, 0x6c, 0xde, + 0x47, 0xb8, 0x73, 0x32, 0xc7, 0x94, 0x92, 0xa5, 0xc3, + 0x65, 0xdf, 0x96, 0x6c, 0xfd, 0xb7, 0x80, 0xfb, 0x47, + 0xba, 0x6e, 0x43, 0xb3, 0x7e, 0x86, 0xc9, 0x97, 0x45, + 0xde, 0x3f, 0x3a, 0xf6, 0xb0, 0x9e, 0x9a, 0xcb, 0xfd, + 0xf2, 0x5c, 0xba, 0x6e, 0x3f, 0xed, 0xfa, 0x74, 0x84, + 0xe2, 0xb1, 0xae, 0x66, 0x57, 0x0b, 0x96, 0x6c, 0x77, + 0xe4, 0x8a, 0x67, 0x97, 0xc7, 0xe0, 0x44, 0xb2, 0x83, + 0x2d, 0x3c, 0x2e, 0x01, 0x19, 0x2e, 0x4c, 0x74, 0xe1, + 0x35, 0x73, 0xeb, 0x85, 0x63, 0x8c, 0x3a, 0xb8, 0xbc, + 0x25, 0x6a, 0x8d, 0xaf, 0xd2, 0xfb, 0xef, 0xd3, 0x12, + 0x93, 0x0b, 0x39, 0xfa, 0x66, 0xbe, 0x3b, 0xfd, 0x6c, + 0x0b, 0xbb, 0xb2, 0x5a, 0x78, 0xa1, 0xcf, 0x8c, 0x7d, + 0x60, 0x55, 0xeb, 0x33, 0x4e, 0x8e, 0xf9, 0x19, 0x4d, + 0x42, 0xd4, 0xf8, 0xd8, 0xba, 0xad, 0x0a, 0x6e, 0x62, + 0xd4, 0xe1, 0x6a, 0xcc, 0xea, 0x09, 0x91, 0x8e, 0x62, + 0xc9, 0x1e, 0x9e, 0x48, 0xaa, 0xde, 0xf7, 0xa2, 0x5a, + 0xcb, 0x83, 0x20, 0xe8, 0xf5, 0xd1, 0xfe, 0x9d, 0x18, + 0x2f, 0xd6, 0xf8, 0x97, 0x17, 0xce, 0xc2, 0x05, 0x08, + 0xef, 0x61, 0x70, 0x9d, 0x95, 0x79, 0x59, 0x4c, 0x06, + 0x24, 0x3d, 0x24, 0x69, 0xff, 0x46, 0xda, 0xbc, 0x71, + 0x7a, 0x74, 0x93, 0x58, 0xf5, 0xc8, 0x91, 0xfb, 0x66, + 0xed, 0x78, 0x8f, 0xf8, 0x28, 0xa8, 0x1d, 0xa5, 0x3a, + 0x13, 0x76, 0xc2, 0xcc, 0xba, 0xb9, 0x56, 0x29, 0x74, + 0xd6, 0x14, 0x75, 0x58, 0xe6, 0x2e, 0x79, 0x6e, 0x9d, + 0x41, 0x94, 0x8a, 0xcf, 0xf1, 0xb1, 0xe0, 0x36, 0xe5, + 0x89, 0x9a, 0x95, 0xa1, 0x11, 0xd1, 0xbe, 0x45, 0xe4, + 0xb3, 0xb0, 0x62, 0x32, 0x1d, 0xba, 0xe0, 0xde, 0x57, + 0x81, 0x0e, 0x01, 0x9b, 0x52, 0x3d, 0xd5, 0xde, 0x3b, + 0x3a, 0xdd, 0x8f, 0xe3, 0x2e, 0xce, 0x1e, 0x89, 0x4d, + 0x81, 0xf0, 0xf6, 0x20, 0x63, 0x7a, 0x4c, 0xbb, 0x66, + 0xe0, 0xbe, 0x2b, 0xee, 0xd0, 0x3b, 0x60, 0x1e, 0x65, + 0xd1, 0x2c, 0x7c, 0x5c, 0x6c, 0x16, 0x5b, 0x90, 0xc8, + 0x05, 0x10, 0xf2, 0xde, 0x33, 0x90, 0x35, 0x69, 0x24, + 0x3f, 0xc1, 0x8f, 0x1e, 0x4a, 0x60, 0xf1, 0x03, 0x65, + 0x46, 0x40, 0x76, 0xe9, 0x83, 0x97, 0xda, 0x0b, 0xb8, + 0x22, 0xfa, 0x55, 0x99, 0xfd, 0x18, 0x24, 0xd2, 0x66, + 0xb0, 0x7b, 0x70, 0x56, 0x93, 0xad, 0x09, 0x95, 0x8e, + 0x1f, 0x2f, 0xe8, 0x12, 0x55, 0xd4, 0x1f, 0xde, 0x09, + 0x85, 0x05, 0xd1, 0xd5, 0x10, 0x2c, 0x8c, 0x6b, 0x53, + 0x28, 0xce, 0x06, 0xc5, 0x52, 0x0f, 0xfa, 0x09, 0x09, + 0x23, 0x1b, 0xe3, 0xbf, 0xb1, 0x89, 0x72, 0x26, 0x0d, + 0xa6, 0xbb, 0x7d, 0x9e, 0xdc, 0xf8, 0xf5, 0x0b, 0x8c, + 0xe0, 0xbc, 0x97, 0x3b, 0x72, 0xdd, 0xf5, 0x9d, 0xc5, + 0xb6, 0x37, 0x2c, 0x76, 0x5b, 0x58, 0x67, 0xdb, 0xed, + 0x3b, 0x6e, 0xe5, 0xe5, 0x6d, 0x6f, 0x0d, 0x7e, 0xff, + 0xa9, 0x57, 0x4a, 0x84, 0x85, 0x82, 0xac, 0x00, 0x50, + 0xa3, 0x4f, 0x87, 0xfe, 0x2a, 0x40, 0x52, 0x54, 0x81, + 0x69, 0x42, 0x0b, 0x0c, 0xd7, 0x18, 0x98, 0x01, 0x8c, + 0x5a, 0xa2, 0xf4, 0xe8, 0x61, 0xd1, 0x38, 0xfd, 0x0f, + 0x63, 0x75, 0xd3, 0x4b, 0x1d, 0xdc, 0xdf, 0xb2, 0xeb, + 0x94, 0x97, 0x5c, 0x2a, 0xb4, 0x12, 0x5c, 0x49, 0x2b, + 0xfc, 0xd0, 0x8d, 0xfb, 0xe7, 0xb3, 0xcb, 0x0f, 0x3c, + 0x2e, 0x04, 0x36, 0xa8, 0x03, 0xc9, 0xd7, 0x11, 0x2d, + 0x2a, 0x93, 0xff, 0xda, 0x26, 0xb0, 0x54, 0x7e, 0xaf, + 0x30, 0x7d, 0xce, 0x46, 0x8a, 0x3d, 0x7c, 0xa4, 0x7a, + 0x2c, 0xfa, 0xba, 0xa1, 0xc9, 0x41, 0xd3, 0xb8, 0x84, + 0x03, 0x78, 0xdd, 0xe9, 0x57, 0x19, 0x62, 0x62, 0xff, + 0x5b, 0x3b, 0x48, 0x62, 0x0e, 0xee, 0x19, 0xb0, 0x32, + 0x6e, 0x6a, 0x07, 0xd8, 0x4e, 0x25, 0x76, 0xa7, 0xe3, + 0x98, 0xa1, 0x6f, 0xb6, 0x99, 0x32, 0x67, 0x7d, 0x46, + 0x42, 0x4a, 0x82, 0xd1, 0x29, 0x1b, 0x87, 0xeb, 0x4b, + 0x9e, 0xdf, 0x69, 0x75, 0xbd, 0x4f, 0xd3, 0xde, 0xc9, + 0x83, 0xe6, 0xd6, 0xea, 0x03, 0x81, 0x12, 0xf3, 0x5d, + 0x99, 0xf1, 0xb1, 0xd9, 0x3e, 0xbe, 0xf3, 0xa8, 0xdc, + 0xb6, 0xf8, 0x4b, 0x9e, 0x26, 0x3f, 0xf0, 0x7c, 0xb3, + 0xf4, 0xca, 0x00, 0x6c, 0x6c, 0xe5, 0x43, 0xa1, 0xfd, + 0x3a, 0xf8, 0x8e, 0xe3, 0x9f, 0x88, 0xc5, 0x44, 0xfd, + 0x24, 0x69, 0x76, 0xd5, 0xcb, 0xdc, 0x9d, 0x12, 0xf3, + 0x13, 0x7e, 0xe7, 0xc3, 0xa8, 0x6a, 0xb2, 0xe0, 0xb3, + 0x1d, 0xab, 0x3b, 0xc9, 0x77, 0x3d, 0x0f, 0xc3, 0xbe, + 0x4b, 0x8b, 0x28, 0xbd, 0x7c, 0xe6, 0xb2, 0x06, 0x1f, + 0xf9, 0x8f, 0x16, 0x62, 0xbf, 0xc7, 0x55, 0x73, 0xd4, + 0xf1, 0x5a, 0x95, 0x80, 0xa3, 0x4e, 0xaa, 0x60, 0x17, + 0x3c, 0xc9, 0x5e, 0xd4, 0x0c, 0x56, 0x7a, 0x77, 0x8e, + 0x7f, 0x67, 0x08, 0x2f, 0xd9, 0x21, 0x19, 0xfd, 0x86, + 0x8c, 0x23, 0x8d, 0xf6, 0x92, 0x1f, 0x36, 0x2c, 0x7c, + 0x83, 0xbd, 0x2f, 0x6c, 0x63, 0x7c, 0xb7, 0x93, 0x74, + 0x1b, 0xc2, 0x95, 0x34, 0x26, 0x1e, 0x07, 0x87, 0x3a, + 0xb6, 0xe2, 0x39, 0x71, 0x9b, 0x20, 0xcd, 0x63, 0xf0, + 0xbf, 0x48, 0xb5, 0x0e, 0x49, 0x86, 0x50, 0x80, 0xbd, + 0xd6, 0x0e, 0xab, 0xd5, 0x69, 0x1b, 0xa4, 0xb3, 0x63, + 0x3c, 0x8f, 0xcb, 0x42, 0xdb, 0xd7, 0x1a, 0xf4, 0xdf, + 0x9e, 0x25, 0xfc, 0xd4, 0x00, 0xcb, 0xec, 0x57, 0x69, + 0x30, 0x15, 0x4d, 0x7a, 0x69, 0x28, 0x2f, 0x2b, 0x34, + 0x26, 0xd1, 0xe7, 0x01, 0x42, 0x5e, 0x02, 0xe2, 0x75, + 0xe8, 0x52, 0x8a, 0xb4, 0x71, 0xfa, 0xc3, 0x3d, 0xe6, + 0xac, 0xeb, 0xf3, 0x93, 0xe0, 0x37, 0xcd, 0x66, 0x92, + 0x66, 0x2c, 0xfe, 0x4b, 0xd6, 0x3c, 0xf1, 0x57, 0xe5, + 0xcf, 0xf5, 0xd0, 0xdb, 0x0e, 0x1f, 0x82, 0x65, 0x3b, + 0xab, 0x69, 0x42, 0x53, 0x7d, 0xa4, 0x7c, 0xb7, 0x86, + 0xeb, 0x23, 0x45, 0xa8, 0x4a, 0x73, 0xfc, 0x38, 0xc6, + 0xe5, 0x2c, 0xab, 0x80, 0xfb, 0x23, 0xb2, 0x0c, 0x53, + 0x28, 0x21, 0x37, 0x54, 0x9c, 0x72, 0x51, 0x0f, 0x44, + 0x50, 0xd3, 0xe1, 0xd5, 0xb2, 0x27, 0x83, 0xb6, 0xe9, + 0x4d, 0x64, 0x5c, 0x17, 0x0f, 0xe0, 0x13, 0xe4, 0x26, + 0x6b, 0xd0, 0xd8, 0x25, 0xe3, 0x69, 0x6a, 0x95, 0x3f, + 0x4a, 0x4e, 0xa0, 0x58, 0xbc, 0x28, 0x47, 0x8b, 0x68, + 0xe4, 0x41, 0x90, 0x46, 0x1b, 0x84, 0xa0, 0x7b, 0x46, + 0x46, 0x03, 0xee, 0x21, 0x0d, 0x34, 0xed, 0xff, 0x15, + 0x57, 0x06, 0xdf, 0x71, 0x09, 0xb2, 0x66, 0x0d, 0x6e, + 0xcc, 0xa5, 0x0c, 0xaf, 0x3f, 0x24, 0x8f, 0xd1, 0xc8, + 0x44, 0x86, 0xaf, 0xbf, 0xeb, 0x2f, 0xb9, 0xee, 0xa7, + 0xcf, 0xe4, 0xe8, 0xec, 0x47, 0x09, 0xd8, 0x95, 0x9e, + 0x3c, 0xda, 0x92, 0x41, 0x61, 0xf5, 0xc3, 0xec, 0x00, + 0xe4, 0xa3, 0x0d, 0x4a, 0xb3, 0xf6, 0x82, 0x05, 0x38, + 0x70, 0x6a, 0xd1, 0x28, 0x2c, 0xb3, 0xc6, 0xbb, 0x38, + 0xb3, 0x06, 0x7f, 0xd6, 0x4c, 0xe7, 0xfb, 0xef, 0x0d, + 0x52, 0x66, 0xbe, 0xd8, 0xa6, 0x6f, 0xe8, 0xd9, 0x42, + 0x4f, 0xad, 0xe8, 0xe8, 0x6c, 0xf9, 0xe9, 0x42, 0xd9, + 0x66, 0x6e, 0xec, 0xfe, 0xf5, 0x91, 0xbf, 0x0a, 0x98, + 0xd8, 0x7b, 0x23, 0x12, 0xa6, 0x04, 0xa8, 0xb3, 0x61, + 0x13, 0x65, 0xc0, 0xe2, 0x82, 0xb9, 0xb2, 0x38, 0x07, + 0x06, 0xca, 0x64, 0x6c, 0x23, 0x93, 0x60, 0x1d, 0x4d, + 0x38, 0x5e, 0x8e, 0x90, 0x16, 0x4a, 0xfd, 0xb3, 0xcd, + 0x84, 0x9c, 0xa5, 0xfa, 0x73, 0x2d, 0xcb, 0x87, 0x31, + 0x3d, 0xf8, 0xfc, 0xeb, 0xa7, 0x56, 0x2f, 0x5b, 0x95, + 0x9a, 0xc6, 0x82, 0x29, 0x86, 0x47, 0xe2, 0xc2, 0x84, + 0x01, 0xaf, 0xc8, 0x0b, 0x2d, 0xfb, 0x34, 0xba, 0x5d, + 0x9d, 0xd1, 0x85, 0xd5, 0x1e, 0x63, 0xcb, 0x3c, 0xa8, + 0xfa, 0x79, 0xef, 0x12, 0xa6, 0xb5, 0xdb, 0xc5, 0x1d, + 0x6a, 0xa7, 0x54, 0x58, 0x0c, 0xbe, 0x61, 0xe5, 0x96, + 0x7f, 0x4a, 0x3b, 0x59, 0x32, 0x2d, 0x06, 0x44, 0x83, + 0x5c, 0xad, 0xe9, 0xfe, 0x7c, 0xd7, 0x5b, 0x34, 0xa1, + 0xa3, 0xad, 0x9a, 0xbf, 0xd5, 0x30, 0xf0, 0x22, 0xfc, + 0x94, 0x7f, 0xd4, 0xa4, 0xca, 0x88, 0x31, 0xe7, 0xf2, + 0x89, 0x2d, 0xda, 0xe6, 0x91, 0xa6, 0x27, 0x22, 0x74, + 0x9f, 0xc6, 0x72, 0x4f, 0xf6, 0xa9, 0xfe, 0x7a, 0xf0, + 0xa8, 0x6b, 0x6c, 0x9f, 0xe9, 0x2a, 0x9b, 0x23, 0x9e, + 0xb8, 0x2b, 0x29, 0x65, 0xa7, 0x5d, 0xbd, 0x10, 0xe4, + 0x56, 0x02, 0x94, 0xdd, 0xd1, 0xab, 0x9b, 0x82, 0x2d, + 0x8d, 0xf6, 0xd3, 0x65, 0x63, 0x4a, 0xc4, 0x86, 0x61, + 0x37, 0x9f, 0xdb, 0x4b, 0x34, 0x20, 0x0a, 0xca, 0x45, + 0x6c, 0x06, 0xc4, 0x9c, 0x74, 0x4d, 0x83, 0x6a, 0x8d, + 0xad, 0xc6, 0x61, 0x3a, 0x8d, 0xde, 0x6c, 0xf9, 0x8e, + 0x33, 0xa2, 0xee, 0x99, 0xc7, 0xe4, 0x52, 0xb2, 0x44, + 0x6f, 0x2f, 0x0f, 0x41, 0xa9, 0x1a, 0xd3, 0x96, 0x42, + 0xc6, 0x49, 0x12, 0x6a, 0xf0, 0x29, 0xa9, 0x0c, 0x9c, + 0x50, 0x5d, 0x1d, 0xd1, 0x42, 0x7e, 0x6f, 0x36, 0x48, + 0x0f, 0x58, 0x14, 0x94, 0xc0, 0x10, 0x1e, 0xe0, 0xb2, + 0xdd, 0xba, 0x57, 0x91, 0x4d, 0xd5, 0xdc, 0xa6, 0x4c, + 0x68, 0x00, 0x6c, 0xb3, 0x5d, 0x32, 0x13, 0xbe, 0xa8, + 0xc3, 0xfb, 0xd4, 0x19, 0x40, 0xf5, 0x6f, 0x63, 0xa1, + 0x07, 0xbf, 0xa2, 0x8b, 0xfc, 0xfe, 0xf8, 0xa1, 0x33, + 0x70, 0x07, 0x6d, 0xc5, 0x72, 0xa0, 0x39, 0xd6, 0xd7, + 0x76, 0x6c, 0xfa, 0x1f, 0x04, 0xd6, 0x23, 0xbf, 0x66, + 0x78, 0x92, 0x00, 0x11, 0x8a, 0x75, 0x67, 0x44, 0xa6, + 0x7c, 0xd0, 0x14, 0xe6, 0xd0, 0x31, 0x6d, 0xdb, 0xc5, + 0xb1, 0xa7, 0x99, 0xc3, 0xaf, 0x18, 0x7a, 0x26, 0x46, + 0xad, 0x6d, 0x0c, 0xb6, 0xb5, 0xad, 0xc1, 0xcf, 0x60, + 0x99, 0xf5, 0x9f, 0x88, 0xaf, 0x0e, 0x37, 0x15, 0xf9, + 0x2b, 0x1a, 0x5f, 0xfb, 0xc9, 0xf8, 0xd4, 0xf0, 0x97, + 0xd2, 0x91, 0xf4, 0x94, 0xa2, 0xd3, 0x3b, 0x8b, 0x0c, + 0x22, 0xa0, 0xac, 0xb3, 0xb5, 0xdf, 0xf2, 0x27, 0x38, + 0x47, 0x53, 0x5b, 0x6e, 0x8f, 0x98, 0x9e, 0xad, 0xb6, + 0xf5, 0x0e, 0x17, 0x20, 0x35, 0x54, 0x6b, 0x73, 0xa6, + 0x64, 0x65, 0xac, 0xb8, 0xc1, 0xd3, 0xf7, 0x07, 0x82, + 0x93, 0x9d, 0xcb, 0xcc, 0xe9, 0x0c, 0x51, 0x52, 0x85, + 0x8b, 0x95, 0xa6, 0xb1, 0xce, 0xdc, 0xfa, 0x00, 0x00, + 0x08, 0x14, 0x1c, 0x23, 0x2a, 0x35, + }, +}; + +static const struct mldsa_testvector mldsa87_testvector = { + .alg = MLDSA87, + .pk_len = MLDSA87_PUBLIC_KEY_SIZE, + .pk = + (const u8[MLDSA87_PUBLIC_KEY_SIZE]) { + 0xd4, 0x9d, 0xdc, 0x3d, 0xa4, 0xa5, 0x87, 0xa5, 0x54, + 0x61, 0xf3, 0xf4, 0xe0, 0x11, 0xc9, 0x1c, 0x78, 0x0a, + 0xf1, 0x8a, 0xa8, 0xb2, 0xff, 0xb2, 0x9a, 0x2c, 0xe0, + 0x86, 0x5c, 0xaa, 0x86, 0xe0, 0xd9, 0x42, 0x54, 0x18, + 0x3e, 0x4c, 0x96, 0x1a, 0xb4, 0xc7, 0x18, 0xcf, 0x7d, + 0xca, 0xe2, 0x74, 0x6c, 0x81, 0x3e, 0xcb, 0xf8, 0x7b, + 0xc4, 0x90, 0x50, 0xd5, 0xe8, 0xd3, 0xbc, 0x8b, 0xa8, + 0x3e, 0xb0, 0x96, 0x65, 0xd7, 0xbb, 0xa9, 0xab, 0x9c, + 0x82, 0x5e, 0x6e, 0x8d, 0xf8, 0xc3, 0x6d, 0xe9, 0xbf, + 0xbd, 0x30, 0xc9, 0xca, 0x47, 0x85, 0xae, 0x6f, 0x5d, + 0x09, 0x4d, 0xd7, 0xdd, 0x05, 0x51, 0xe0, 0x9e, 0x94, + 0x3b, 0x1d, 0xfa, 0x30, 0x57, 0xdc, 0x58, 0x48, 0xe5, + 0x45, 0xf3, 0x34, 0x8a, 0x73, 0x66, 0x8a, 0xe0, 0x62, + 0x3d, 0x0d, 0xfb, 0x13, 0x52, 0x25, 0xf5, 0xd3, 0x94, + 0x15, 0x9d, 0xac, 0x6a, 0x74, 0x8a, 0x64, 0x91, 0x5b, + 0xa3, 0xe2, 0xd0, 0x5c, 0xd2, 0xee, 0x52, 0xc0, 0x0c, + 0x6c, 0x81, 0x34, 0x94, 0xfb, 0x87, 0xf6, 0x6b, 0x0f, + 0x7e, 0x99, 0xa7, 0xaf, 0xb3, 0x74, 0xa7, 0xb6, 0x64, + 0xd7, 0x36, 0x39, 0x3f, 0x7d, 0x0e, 0xc3, 0x76, 0xb3, + 0x3a, 0xc9, 0x94, 0x6f, 0xc0, 0xaa, 0x92, 0x2a, 0xf1, + 0x38, 0x8c, 0x62, 0xa1, 0x9a, 0xbe, 0x8d, 0x32, 0xec, + 0x05, 0xb9, 0x8d, 0xb0, 0xdb, 0x37, 0x8d, 0x61, 0xfa, + 0x79, 0x55, 0x1d, 0xf2, 0xc3, 0x19, 0x15, 0x3b, 0x26, + 0xef, 0xe5, 0xf3, 0x29, 0xa1, 0x13, 0x60, 0x68, 0xd3, + 0x22, 0x57, 0xcd, 0x99, 0xe6, 0x22, 0x54, 0xdf, 0x02, + 0xe4, 0xd5, 0xd2, 0x66, 0xce, 0x5a, 0x90, 0x13, 0x7e, + 0x7c, 0xad, 0x4c, 0x4c, 0xb6, 0x93, 0x65, 0xda, 0x4b, + 0xb6, 0x13, 0x0e, 0x1b, 0x36, 0xaa, 0x2c, 0xbd, 0x60, + 0x57, 0x98, 0x35, 0xa9, 0xe9, 0xad, 0xc5, 0x8e, 0x33, + 0x47, 0x00, 0xe9, 0xf2, 0x1b, 0xe7, 0x5a, 0xd0, 0x55, + 0x3b, 0x0e, 0x77, 0x09, 0x7e, 0x1f, 0x11, 0x0b, 0xf0, + 0xe4, 0x07, 0x27, 0xe7, 0x72, 0xe9, 0x50, 0x9c, 0x9c, + 0x84, 0xb0, 0x5c, 0xe0, 0x13, 0x79, 0xfa, 0x3f, 0x80, + 0x96, 0xe2, 0x04, 0xde, 0x35, 0x5f, 0xa4, 0x4e, 0x8a, + 0x12, 0x7a, 0xba, 0x53, 0x20, 0x36, 0x3d, 0xf0, 0x63, + 0xb6, 0x14, 0xab, 0xce, 0x6b, 0x24, 0xfd, 0xc9, 0xd2, + 0x52, 0xd9, 0xc0, 0x40, 0xdf, 0xdd, 0xd5, 0xc2, 0xa0, + 0xf5, 0x74, 0x46, 0x17, 0xdc, 0xf5, 0x81, 0x68, 0xbd, + 0x1a, 0x01, 0x33, 0xd0, 0x2f, 0xdc, 0x3a, 0x43, 0x4a, + 0x08, 0x07, 0x98, 0x9f, 0x75, 0x5d, 0x70, 0x15, 0x1d, + 0x58, 0x7f, 0x26, 0x30, 0x28, 0xe1, 0x17, 0x6d, 0x14, + 0x0f, 0x01, 0x4a, 0x88, 0x3b, 0xf5, 0x70, 0x1d, 0x97, + 0xd5, 0xda, 0x18, 0xa8, 0xb3, 0xa4, 0x0e, 0x04, 0x3f, + 0xe8, 0x50, 0xf4, 0x87, 0x65, 0x75, 0x5a, 0x5d, 0x2f, + 0x94, 0x63, 0x7a, 0xd0, 0x06, 0xce, 0xfb, 0xeb, 0x41, + 0x65, 0xc9, 0x55, 0x38, 0x54, 0xd3, 0xc4, 0xac, 0x24, + 0x46, 0x06, 0x2a, 0x87, 0xb1, 0x0f, 0x06, 0xd8, 0x1e, + 0xa7, 0x35, 0xc4, 0xa3, 0xdc, 0x60, 0x80, 0x83, 0xe7, + 0xf0, 0x74, 0xf6, 0xd6, 0xa7, 0x1d, 0x50, 0xff, 0xba, + 0x82, 0xc0, 0xca, 0x72, 0x6b, 0xda, 0x4a, 0xcb, 0x3b, + 0xe8, 0xa3, 0xaa, 0x32, 0x86, 0xc0, 0x94, 0x75, 0x2b, + 0x2f, 0x44, 0xad, 0x5b, 0x8d, 0xab, 0xc2, 0x03, 0x55, + 0xb1, 0x7e, 0x67, 0x07, 0x39, 0x33, 0x83, 0x67, 0xec, + 0xbf, 0x52, 0xad, 0x55, 0x37, 0x3e, 0xa1, 0x41, 0xed, + 0xa0, 0x91, 0xbf, 0x28, 0x1b, 0x04, 0x32, 0xbf, 0xf1, + 0xb0, 0x0a, 0x11, 0x99, 0x98, 0x77, 0xee, 0x14, 0x13, + 0x15, 0x13, 0xad, 0x1f, 0xb6, 0x6b, 0xcd, 0x3b, 0xb8, + 0x75, 0x9a, 0x55, 0x9b, 0x0c, 0x6c, 0xf7, 0x7c, 0x21, + 0x06, 0xb7, 0xf0, 0x43, 0x41, 0x96, 0xc1, 0x73, 0x44, + 0x53, 0xd8, 0x18, 0x3e, 0x09, 0x4e, 0xc2, 0x5f, 0xa0, + 0xd5, 0x18, 0xdb, 0x9f, 0xf4, 0xa0, 0xf8, 0x4d, 0xa7, + 0x72, 0x7e, 0x85, 0xbb, 0xb7, 0xcc, 0x7b, 0x51, 0xb0, + 0xf1, 0x5e, 0x03, 0xcd, 0xe8, 0x5b, 0x83, 0x3f, 0x95, + 0xe2, 0x0b, 0xa1, 0xc7, 0x6f, 0x74, 0x98, 0xcd, 0x95, + 0xf4, 0xd4, 0xb8, 0x40, 0xff, 0x75, 0x54, 0x83, 0x3a, + 0x2c, 0x64, 0x38, 0x10, 0xcb, 0x6d, 0xad, 0xf9, 0x91, + 0xcb, 0xcf, 0xbe, 0xf6, 0xf7, 0x94, 0x15, 0xea, 0xaf, + 0x37, 0x65, 0x7c, 0xd2, 0xff, 0x99, 0x79, 0xf8, 0x95, + 0x27, 0x75, 0x09, 0x60, 0xa4, 0x6f, 0x06, 0x0f, 0x6c, + 0x13, 0xdd, 0x32, 0x79, 0xa7, 0x40, 0xa5, 0xdd, 0x2c, + 0x22, 0xc1, 0xee, 0xc3, 0x31, 0x59, 0xb1, 0x3d, 0xa1, + 0x77, 0x69, 0xb5, 0xd6, 0xae, 0xd7, 0x86, 0xab, 0xa4, + 0xdf, 0x9f, 0x36, 0xb4, 0xb2, 0xe6, 0x88, 0xd6, 0x45, + 0x9b, 0x8b, 0x87, 0xbd, 0x27, 0xe9, 0x55, 0xd5, 0xac, + 0xe9, 0x33, 0x80, 0x00, 0x1d, 0x00, 0x21, 0x74, 0xe2, + 0x0a, 0x5b, 0xd2, 0x37, 0xab, 0x6f, 0x48, 0x5e, 0x14, + 0x76, 0x3a, 0x84, 0xf9, 0x34, 0x03, 0x74, 0x8d, 0x6c, + 0xd8, 0xd4, 0x0f, 0xc7, 0xc8, 0x0c, 0xb5, 0x18, 0x12, + 0xa5, 0x5a, 0x76, 0x4b, 0x5d, 0x1e, 0x75, 0x89, 0x3a, + 0x01, 0x60, 0xf1, 0x1e, 0x5b, 0x98, 0x71, 0x7a, 0x15, + 0x79, 0xff, 0x3d, 0x37, 0x5e, 0xc9, 0x56, 0xa5, 0x43, + 0xe7, 0xd0, 0x2b, 0x63, 0xfb, 0x2f, 0x1a, 0x55, 0x37, + 0x15, 0x02, 0x7f, 0x9a, 0x84, 0xf0, 0x07, 0x45, 0x2b, + 0xa0, 0x9a, 0xb4, 0x60, 0x4d, 0x48, 0xd5, 0xee, 0x64, + 0xf9, 0xe7, 0x4b, 0x1c, 0xb9, 0x05, 0xd1, 0xd1, 0x47, + 0x4f, 0xca, 0x26, 0x32, 0xad, 0x7b, 0x2e, 0x7e, 0x54, + 0x05, 0x96, 0x12, 0x29, 0xbc, 0xd3, 0x45, 0x4e, 0x05, + 0x83, 0x6d, 0x30, 0x38, 0xd0, 0x3c, 0x46, 0xcd, 0xb6, + 0x21, 0xb6, 0x5c, 0x2a, 0x40, 0x7a, 0x2e, 0x97, 0xd7, + 0xbf, 0xa6, 0x55, 0x2a, 0xa6, 0x28, 0x54, 0xc4, 0x66, + 0xbe, 0xf6, 0xea, 0xc1, 0x19, 0xcb, 0xcc, 0x52, 0x07, + 0xcd, 0x90, 0x3f, 0x09, 0x23, 0x77, 0xf7, 0xc6, 0x03, + 0xcc, 0x8b, 0x18, 0xac, 0x63, 0x6d, 0x2a, 0x01, 0x82, + 0xad, 0x20, 0x11, 0x82, 0xf3, 0xfe, 0x2d, 0x53, 0x3f, + 0x18, 0xb5, 0xbc, 0xf7, 0x0c, 0xa7, 0xca, 0x63, 0xfa, + 0x77, 0x8a, 0x3c, 0xc1, 0xc4, 0xb0, 0x15, 0x4b, 0x08, + 0xdd, 0xb3, 0xd2, 0x33, 0xc8, 0xc2, 0xaa, 0x1a, 0xe4, + 0x9b, 0x1b, 0x18, 0x78, 0x07, 0x6c, 0x08, 0x28, 0x3f, + 0xc6, 0xb7, 0x46, 0x8f, 0x8e, 0xc6, 0xff, 0xb1, 0x2d, + 0x63, 0x12, 0x7c, 0xe5, 0xd8, 0xa5, 0xf8, 0x64, 0x76, + 0xf7, 0x1b, 0xbc, 0x41, 0xad, 0xee, 0xe8, 0x6f, 0xd4, + 0x13, 0xea, 0x59, 0x72, 0xfa, 0x04, 0xb4, 0x6e, 0x52, + 0x3a, 0xff, 0x60, 0xa0, 0xd8, 0xdf, 0x41, 0x1a, 0x4e, + 0xc8, 0x80, 0x2d, 0x29, 0x13, 0xd3, 0xd0, 0x55, 0x20, + 0xb5, 0x33, 0x4f, 0x02, 0xd2, 0xea, 0xca, 0x94, 0x99, + 0xdf, 0x3c, 0xfd, 0xe5, 0x2b, 0x45, 0x04, 0x85, 0xfe, + 0x87, 0x42, 0x53, 0x11, 0x62, 0x2f, 0xcf, 0x05, 0x35, + 0x29, 0x6a, 0xa5, 0x37, 0x80, 0x9b, 0x4a, 0x44, 0x3c, + 0x6d, 0xe1, 0xd3, 0x88, 0x6a, 0xe7, 0x6f, 0x45, 0xfc, + 0x99, 0x33, 0xe4, 0x18, 0x62, 0x19, 0x36, 0x37, 0x6f, + 0xe9, 0x37, 0xbb, 0x86, 0xa2, 0x07, 0xec, 0xbc, 0x33, + 0x0d, 0x0a, 0x18, 0x30, 0x13, 0xcf, 0x36, 0x31, 0x2f, + 0xd2, 0xf6, 0x7e, 0xa8, 0xa4, 0x95, 0x71, 0xc8, 0x40, + 0x1f, 0x34, 0xf1, 0x95, 0xde, 0x3e, 0xe1, 0xb7, 0xef, + 0x26, 0x1e, 0x20, 0x78, 0xf8, 0x9a, 0x24, 0xbc, 0x7f, + 0x64, 0x30, 0x42, 0x63, 0x77, 0x89, 0x96, 0xf8, 0x9b, + 0x60, 0x51, 0xb3, 0x02, 0x7a, 0x64, 0x19, 0xd3, 0x13, + 0x98, 0xcd, 0xb6, 0x1e, 0x68, 0x82, 0x9b, 0x23, 0x44, + 0x3e, 0xa8, 0x57, 0xf5, 0x4d, 0xd8, 0xea, 0x93, 0x84, + 0x4e, 0x56, 0x18, 0xb7, 0x94, 0x02, 0xfa, 0x6e, 0x8e, + 0xa0, 0x75, 0xd2, 0xb4, 0xbb, 0x50, 0x6f, 0x3f, 0x58, + 0xe2, 0x28, 0xb6, 0x87, 0xd6, 0xc5, 0xe0, 0x76, 0xa6, + 0xc6, 0x5b, 0xed, 0x6b, 0x48, 0xd4, 0x25, 0xd3, 0x5f, + 0x64, 0xab, 0xe3, 0x5a, 0xae, 0x69, 0xe8, 0x06, 0xff, + 0xef, 0x67, 0x0b, 0x49, 0xe4, 0xe8, 0x31, 0xee, 0x1a, + 0x35, 0x86, 0x0c, 0x81, 0x8a, 0x1f, 0x7f, 0x06, 0x20, + 0x66, 0x81, 0x8b, 0xfb, 0xdc, 0x99, 0x78, 0x7b, 0x43, + 0x84, 0x35, 0xa7, 0x4f, 0x27, 0xb5, 0xc9, 0x44, 0xbf, + 0x05, 0x59, 0xce, 0x4c, 0xe5, 0xaa, 0x18, 0x37, 0x32, + 0x5b, 0x41, 0x62, 0x89, 0x0a, 0xec, 0x0a, 0xae, 0x67, + 0xcf, 0x0b, 0xef, 0xf6, 0x3a, 0x3b, 0x13, 0x1d, 0xf8, + 0x8b, 0x20, 0x5f, 0x2c, 0x55, 0x75, 0xec, 0xf4, 0x9d, + 0x2d, 0x0d, 0x0d, 0xb7, 0x88, 0x71, 0xf7, 0xc6, 0xf8, + 0x65, 0x1a, 0xba, 0xdb, 0xdc, 0x53, 0xd2, 0x80, 0x92, + 0x72, 0x14, 0xce, 0x68, 0xb8, 0xf4, 0x78, 0x4b, 0x92, + 0xee, 0x15, 0xfc, 0xd4, 0xe0, 0x89, 0x49, 0x82, 0xf8, + 0x7f, 0xce, 0xf6, 0xce, 0x86, 0xfa, 0xa5, 0xd9, 0x3a, + 0xfb, 0xef, 0xa8, 0xd9, 0x3b, 0x6e, 0xb5, 0xe2, 0x29, + 0x31, 0x6f, 0x5f, 0xa7, 0x34, 0x58, 0x49, 0x07, 0x9c, + 0x4d, 0x74, 0x46, 0xb6, 0xd5, 0x0c, 0x3c, 0x26, 0x4b, + 0xee, 0x37, 0x9c, 0x92, 0xa2, 0x37, 0x95, 0x35, 0x71, + 0xee, 0x46, 0xdd, 0xef, 0xd0, 0xf2, 0xd4, 0xef, 0xe0, + 0xdb, 0x28, 0xf4, 0x5d, 0x12, 0xe0, 0x85, 0x4a, 0x3c, + 0x5b, 0x2f, 0xd8, 0x9c, 0x9a, 0xcf, 0x6f, 0x01, 0xe7, + 0x1b, 0x2e, 0x41, 0x5d, 0x5d, 0xdd, 0xdd, 0xb6, 0x6d, + 0xb3, 0x7d, 0xbc, 0x33, 0x50, 0xc5, 0xaf, 0x1b, 0xee, + 0x33, 0xc4, 0x42, 0x46, 0xca, 0xe2, 0x00, 0xe9, 0xc9, + 0xec, 0x9e, 0x9b, 0x67, 0xba, 0x39, 0x3c, 0xc5, 0xa1, + 0x7d, 0xac, 0x9e, 0xbe, 0x67, 0x92, 0x20, 0x5b, 0x36, + 0x85, 0xde, 0xdd, 0xd3, 0xec, 0x4e, 0x82, 0x03, 0x4a, + 0x44, 0x6e, 0xee, 0x9c, 0xd0, 0x13, 0x9e, 0x98, 0x6f, + 0x77, 0xd8, 0xfe, 0xb7, 0x54, 0x01, 0x15, 0xcd, 0xd3, + 0x31, 0xf5, 0xd7, 0x74, 0x2d, 0x4d, 0x4f, 0x18, 0xd2, + 0x8f, 0x80, 0xb6, 0x46, 0x80, 0xa7, 0xa8, 0x8c, 0xf2, + 0x64, 0x4f, 0x40, 0x8a, 0x64, 0x96, 0x2c, 0x1e, 0xd2, + 0x3c, 0xe9, 0x50, 0xc4, 0x86, 0xd9, 0x19, 0x93, 0x7a, + 0xba, 0x95, 0x35, 0x35, 0xe3, 0x4d, 0x83, 0xda, 0x15, + 0x09, 0x87, 0xb8, 0x1a, 0x54, 0x6f, 0x61, 0xdd, 0x55, + 0x01, 0xe1, 0x39, 0x1c, 0xb2, 0xac, 0x8c, 0x15, 0x82, + 0x7c, 0xa6, 0x69, 0x54, 0x64, 0x2f, 0x5c, 0x0c, 0x79, + 0xaf, 0x85, 0x71, 0x2d, 0xff, 0xc0, 0xf2, 0x40, 0xbb, + 0x05, 0x31, 0x31, 0x00, 0x8d, 0x0c, 0x40, 0x11, 0x88, + 0xf2, 0x91, 0x9f, 0x7a, 0x8e, 0x99, 0x82, 0x72, 0xd8, + 0x45, 0x08, 0x83, 0x5c, 0x2b, 0x73, 0x46, 0xd6, 0x54, + 0x9a, 0x3d, 0x42, 0x48, 0x67, 0x19, 0x2b, 0x19, 0xae, + 0x0c, 0x16, 0x08, 0xa4, 0xec, 0x7e, 0x15, 0xad, 0x4f, + 0xa9, 0xbd, 0x4f, 0x09, 0xf0, 0xc2, 0x9f, 0xb5, 0xb7, + 0xff, 0x96, 0xf9, 0xf9, 0xc6, 0x5d, 0x57, 0x07, 0xe8, + 0xf2, 0x7c, 0x95, 0xa0, 0x8a, 0x15, 0x8b, 0x34, 0x84, + 0xb5, 0x28, 0x7a, 0xf5, 0x04, 0xb8, 0xcb, 0x5e, 0x77, + 0x4d, 0xdd, 0x14, 0x8d, 0xa6, 0xe2, 0x45, 0x44, 0xfd, + 0xd0, 0x9c, 0x41, 0x10, 0xfc, 0xe5, 0xdd, 0x2c, 0xda, + 0x6b, 0xfe, 0xf9, 0xff, 0x65, 0xe7, 0x66, 0x40, 0x69, + 0x0c, 0x09, 0x99, 0xaf, 0x02, 0xd0, 0x85, 0x55, 0xcc, + 0x0d, 0x59, 0xaa, 0xb6, 0x37, 0x9b, 0x58, 0xfa, 0xb5, + 0xc5, 0xcd, 0xd5, 0x1c, 0xf9, 0x9f, 0x31, 0x4c, 0x8a, + 0x78, 0xca, 0x1e, 0x22, 0xdc, 0x33, 0x64, 0xce, 0x56, + 0x6d, 0x57, 0xe9, 0xbd, 0xe0, 0xdd, 0x23, 0x22, 0x9c, + 0x70, 0x5a, 0xe7, 0x46, 0x08, 0xc5, 0xa6, 0x85, 0x34, + 0x5f, 0x9c, 0x96, 0xbb, 0xbe, 0xb4, 0x2f, 0xbb, 0x47, + 0xdc, 0x38, 0xad, 0xb7, 0x92, 0x08, 0x0d, 0x93, 0xf4, + 0x7f, 0xe6, 0x64, 0xa5, 0xb3, 0x9e, 0xdd, 0xdb, 0x99, + 0x8e, 0xca, 0x82, 0x4f, 0x77, 0xf7, 0xff, 0x92, 0xd3, + 0x48, 0xe0, 0x80, 0x71, 0x14, 0x61, 0x6b, 0x77, 0x1b, + 0x58, 0xbd, 0xb6, 0xb6, 0xe5, 0xb0, 0xa8, 0x16, 0xe7, + 0x4c, 0xc2, 0x5e, 0x40, 0xbc, 0x9f, 0x77, 0x76, 0x98, + 0xf7, 0x00, 0xd1, 0xdf, 0x3c, 0x2e, 0x16, 0x4f, 0xe7, + 0x91, 0xec, 0xeb, 0xfb, 0xa1, 0x9f, 0x66, 0x6d, 0xef, + 0xaf, 0x36, 0xd8, 0xb6, 0x40, 0x7e, 0x2f, 0x51, 0x3b, + 0x75, 0x56, 0x1d, 0x33, 0xee, 0x4b, 0xcf, 0x98, 0xb3, + 0x9f, 0x4f, 0xff, 0xfd, 0x2a, 0xb9, 0x4e, 0x4b, 0xe0, + 0x39, 0x60, 0xd5, 0x7c, 0xaa, 0x28, 0x7e, 0x7e, 0x27, + 0xd8, 0x09, 0x85, 0x6d, 0xfa, 0x57, 0x8a, 0xee, 0x84, + 0xbe, 0x48, 0xf9, 0x62, 0x78, 0x8a, 0x4d, 0x2a, 0x80, + 0x2f, 0x6f, 0xc9, 0xa7, 0xb5, 0x56, 0xbb, 0x58, 0xc2, + 0xb9, 0xd0, 0xfe, 0x8d, 0x68, 0x86, 0x2b, 0x7b, 0xf0, + 0x01, 0x57, 0xff, 0xaf, 0x88, 0xad, 0x53, 0xf9, 0x63, + 0xfe, 0xf4, 0x5a, 0x97, 0xb7, 0x8f, 0x92, 0x0f, 0x90, + 0x63, 0xcf, 0xfe, 0x08, 0xbc, 0x8c, 0x5a, 0x9c, 0xac, + 0x8b, 0x0a, 0x94, 0x17, 0x25, 0xae, 0x87, 0xa7, 0x1d, + 0x3f, 0x28, 0xfe, 0x45, 0x3e, 0x48, 0xef, 0x19, 0x4a, + 0xbe, 0xc6, 0xd5, 0x64, 0xe1, 0xf2, 0xf5, 0xd2, 0x3a, + 0x03, 0xe0, 0x50, 0x31, 0x7e, 0xdf, 0xd5, 0x15, 0xc6, + 0xb6, 0xb2, 0x1e, 0x44, 0x6a, 0x0f, 0x67, 0xf2, 0x34, + 0x69, 0xb9, 0xd2, 0x51, 0xeb, 0x86, 0xab, 0x7e, 0x60, + 0x68, 0xe4, 0xc2, 0x4b, 0x8b, 0xa2, 0xc6, 0x78, 0xb2, + 0x61, 0xa1, 0xe5, 0xb6, 0x33, 0x47, 0x3f, 0xfa, 0xde, + 0x5b, 0x6b, 0x95, 0x89, 0x51, 0xbb, 0xd3, 0x8a, 0x00, + 0x1d, 0xad, 0xfc, 0x7a, 0x47, 0xc8, 0xa0, 0x69, 0xa6, + 0xa3, 0x3f, 0xa9, 0xdb, 0xd8, 0xe4, 0x0d, 0x2c, 0xba, + 0x26, 0x2c, 0xa6, 0x82, 0x62, 0x5a, 0x1e, 0x9f, 0xa8, + 0x24, 0x9d, 0xe5, 0xc7, 0xcf, 0x6d, 0x2f, 0x68, 0xe1, + 0xc0, 0x04, 0xad, 0xde, 0x00, 0x5b, 0x57, 0x35, 0x2b, + 0x9a, 0x9b, 0xe5, 0x90, 0x31, 0x8a, 0x5b, 0xea, 0xe5, + 0xf6, 0x73, 0x02, 0xc1, 0x33, 0xaf, 0xe7, 0x61, 0x6c, + 0x04, 0x8c, 0x08, 0xb2, 0xfb, 0xa2, 0x18, 0x51, 0x39, + 0x1a, 0x61, 0x2c, 0x8c, 0x7d, 0x11, 0xb8, 0x2e, 0x38, + 0xb7, 0xe0, 0xde, 0x5e, 0x6f, 0xc5, 0xf4, 0x31, 0x72, + 0xcb, 0xd6, 0xec, 0xbc, 0xe9, 0x36, 0x2e, 0x2b, 0x63, + 0xea, 0xa1, 0xab, 0xf8, 0x11, 0xe7, 0x31, 0xad, 0xe4, + 0xcb, 0x23, 0xe4, 0x64, 0x54, 0x50, 0x4f, 0x15, 0x8b, + 0x58, 0xa4, 0xa1, 0x35, 0xea, 0x73, 0x3e, 0xc3, 0x3e, + 0x31, 0x81, 0x80, 0x53, 0x6a, 0x2c, 0xfe, 0xd7, 0xd8, + 0x8f, 0xe7, 0x50, 0x2d, 0x99, 0x69, 0x32, 0xfa, 0x4e, + 0xb4, 0xf9, 0x89, 0x18, 0xbe, 0x5a, 0x95, 0x7a, 0x0f, + 0x34, 0xc5, 0xd9, 0x28, 0xff, 0x93, 0x3a, 0x13, 0x22, + 0xe6, 0xdb, 0x5c, 0xfe, 0x51, 0x05, 0xaf, 0xa3, 0xcd, + 0x17, 0x01, 0xd1, 0x84, 0x76, 0x23, 0xff, 0x91, 0xc4, + 0x6b, 0xc7, 0xa8, 0x77, 0xe0, 0xda, 0x45, 0xef, 0xd7, + 0x13, 0xe3, 0x02, 0x7c, 0x74, 0x7e, 0x66, 0xbb, 0x9f, + 0x48, 0x35, 0x56, 0xa8, 0x08, 0x41, 0xf7, 0xa7, 0xe3, + 0x60, 0xa6, 0xce, 0x73, 0xdf, 0x73, 0x99, 0xc6, 0xbd, + 0x7b, 0xb4, 0xde, 0x31, 0xe6, 0x35, 0xaf, 0x3e, 0x93, + 0xd2, 0x69, 0xb5, 0xb9, 0xbe, 0x9f, 0xf4, 0x0d, 0xd8, + 0x82, 0xc1, 0x4f, 0xf6, 0xf3, 0x23, 0x1c, 0xe7, 0xff, + 0xac, 0xb2, 0x79, 0xe3, 0x62, 0x6a, 0xb7, 0x85, 0x08, + 0xda, 0x4a, 0x3f, 0x22, 0x62, 0x2b, 0xcd, 0xb7, 0x59, + 0xf5, 0x82, 0xef, 0x08, 0x7f, 0xb5, 0xa0, 0x6c, 0xba, + 0x61, 0x45, 0x8f, 0xf4, 0xa2, 0x66, 0x83, 0x72, 0x65, + 0x34, 0x34, 0x68, 0x99, 0xf5, 0x99, 0xc9, 0x52, 0x6a, + 0xc2, 0x7f, 0xde, 0x25, 0xa3, 0x7b, 0xce, 0xa3, 0xde, + 0x6d, 0x62, 0x98, 0x84, 0xe4, 0x2a, 0xe1, 0x1c, 0xa9, + 0x0b, 0x7e, 0x45, 0xd3, 0x78, 0x40, 0x85, 0x61, 0x9d, + 0xce, 0xcd, 0xfd, 0x7b, 0x66, 0x92, 0x5f, 0xb9, 0x37, + 0x04, 0xea, 0xec, 0x37, 0x32, 0xbe, 0xcd, 0x3e, 0x5e, + 0x37, 0xcd, 0xe3, 0x81, 0x92, 0x69, 0xdf, 0xa1, 0xb9, + 0x8c, 0x44, 0x43, 0xae, 0xcd, 0xe5, 0xd5, 0x4e, 0xb9, + 0x2f, 0x1e, 0xbc, 0xf2, 0xd1, 0x88, 0x93, 0xde, 0x6a, + 0x8a, 0x43, 0xa1, 0x6b, 0xdc, 0x5b, 0xd2, 0xdd, 0xe8, + 0xca, 0x0a, 0x95, 0x45, 0x9f, 0xd8, 0x8c, 0xfd, 0xe0, + 0xc3, 0xbd, 0x0e, 0xa0, 0xbd, 0x72, 0xa7, 0x77, 0x9a, + 0x79, 0xd9, 0x15, 0xad, 0x50, 0x13, 0xa7, 0x41, 0xc7, + 0xd1, 0xec, 0x2f, 0x45, 0x14, 0x02, 0xb7, 0x8e, 0x51, + 0x76, 0xd4, 0x2f, 0x1c, 0xea, 0x9c, 0x6d, 0x35, 0x1c, + 0xa7, 0xeb, 0xd7, 0x79, 0xe4, 0x35, 0xbc, 0x02, 0xa6, + 0xd0, 0x58, 0xcb, 0xdf, 0xea, 0x90, 0x16, 0x53, 0x3c, + 0xc5, 0xda, 0x36, 0x4f, 0x61, 0x4a, 0x1b, 0xfa, 0x15, + 0x52, 0x0d, 0x3d, 0x73, 0xc5, 0xfe, 0x2a, 0xa2, 0x4a, + 0x6e, 0x95, 0x99, 0xfc, 0xbf, 0xb2, 0xfc, 0x22, 0xbe, + 0x45, 0x10, 0x5a, 0xc5, 0x38, 0xa0, 0xc1, 0xba, 0x46, + 0x6d, 0x8e, 0xbe, 0x0b, 0x5f, 0xf6, 0x6f, 0xbb, 0x4d, + 0x22, 0xf5, 0x95, 0x4d, 0x12, 0xc2, 0x6f, 0x8d, 0xde, + 0x86, 0xaf, 0x3f, 0x08, 0x24, 0x56, 0xa3, 0xcd, 0xfc, + 0xeb, 0xa1, 0x3c, 0x22, 0x66, 0x45, 0x03, 0x8b, 0x04, + 0x12, 0x80, 0x34, 0xf9, 0xf4, 0x64, 0xbf, 0xb9, 0x3d, + 0xd7, 0x34, 0xe4, 0xc8, 0x8e, 0x86, 0xc9, 0x73, 0x21, + 0x7f, 0x30, 0x01, 0xc8, 0xd2, 0x91, 0x8d, 0xc4, 0xca, + 0xd5, 0x59, 0xac, 0xd7, 0xb4, 0xfb, 0x98, 0xfb, 0xc4, + 0x48, 0x82, 0x93, 0xc6, 0x58, 0x8b, 0x0c, 0xdf, 0x3f, + 0x07, 0x5a, 0x94, 0x89, 0xc6, 0xbe, 0x1a, 0x19, 0x63, + 0x8b, 0xa8, 0x0c, 0x20, 0xae, 0x9a, 0x1b, 0xd3, 0x45, + 0xa0, 0xd9, 0x8c, 0xbb, 0x67, 0xa0, 0x54, 0x86, 0x9b, + 0x7b, 0xa8, 0x16, 0x6f, 0xa4, 0x59, 0x45, 0x1e, 0x34, + 0xb5, 0xa7, 0x1b, 0x3f, 0xda, 0xc6, 0x80, 0x19, 0xdc, + 0xc2, 0xee, 0xeb, 0xd9, 0x96, 0xdc, 0x4f, 0xec, 0x02, + 0xde, 0x34, 0x43, 0x5a, 0x37, 0xc8, 0xdf, 0x3b, 0x53, + 0x82, 0xfa, 0xf8, 0x8a, 0x32, 0x97, 0x1e, 0xf6, 0x0e, + 0x7d, 0x39, 0xe0, 0xdb, 0x0b, 0x22, 0xa4, 0xd0, 0x56, + 0x13, 0xbc, 0xe9, 0x38, 0x92, 0x76, 0xff, 0x2b, 0xc2, + 0xa0, 0x98, 0x7d, 0x8c, 0x58, 0x8e, 0x7f, 0x6d, 0x80, + 0x06, 0xff, 0xc7, 0xb3, 0xb7, 0x1b, 0xac, 0xc4, 0x68, + 0x61, 0x11, 0x15, 0xb7, 0xee, 0x8d, 0x66, 0x34, 0x9f, + 0x18, 0x03, 0x88, 0xd1, 0x04, 0xd0, 0x86, 0xc0, 0xca, + 0x2a, 0xe1, 0x1b, 0x47, 0x18, 0xc9, 0x97, 0xed, 0x1f, + 0x99, 0xc6, 0xa9, 0x20, 0x3f, 0xf6, 0x43, 0x96, 0x30, + 0x8b, 0xa5, 0xcb, 0x2e, 0xc5, 0xdb, 0x26, 0xc0, 0xf6, + 0x48, 0x07, 0x3a, 0x28, 0x3e, 0x35, 0x38, 0x50, 0x80, + 0xdf, 0x80, 0xfa, 0x12, 0x92, 0x83, 0x55, 0xde, 0x31, + }, + .msg_len = 64, + .msg = + (const u8[64]) { + 0x48, 0x11, 0x92, 0xb3, 0xaa, 0x7e, 0xb3, 0x14, + 0xdc, 0x46, 0xd6, 0xbf, 0x26, 0xb2, 0x66, 0xc5, + 0xd8, 0xc4, 0x69, 0x9f, 0x67, 0x50, 0x67, 0xc0, + 0x3b, 0x8d, 0xc5, 0xb5, 0x68, 0x59, 0x6f, 0x9c, + 0xd4, 0xf2, 0x49, 0xfb, 0xa4, 0xd0, 0xbf, 0xc5, + 0x3c, 0xee, 0x3b, 0x03, 0x25, 0x6c, 0x51, 0x94, + 0xb3, 0xd4, 0xdb, 0x2a, 0xbd, 0x26, 0xef, 0x58, + 0xb3, 0x91, 0x62, 0x81, 0x1b, 0x29, 0x9c, 0x12, + }, + .sig_len = MLDSA87_SIGNATURE_SIZE, + .sig = + (const u8[MLDSA87_SIGNATURE_SIZE]) { + 0xba, 0x08, 0xf3, 0x0c, 0xa1, 0x48, 0xad, 0x67, 0x12, + 0x68, 0x51, 0x9b, 0xa4, 0x21, 0x66, 0x8d, 0xea, 0x0a, + 0x71, 0x4f, 0x4c, 0xab, 0x1b, 0x42, 0x84, 0xb7, 0x9c, + 0x78, 0xa9, 0x18, 0xd9, 0xe8, 0x08, 0x8f, 0xee, 0xf7, + 0x4b, 0xcf, 0x0e, 0xcd, 0xf6, 0x36, 0xcf, 0xd5, 0xa1, + 0x5e, 0x59, 0xc6, 0x8c, 0x6c, 0x4d, 0xfe, 0xfa, 0xfa, + 0xbc, 0x52, 0x3a, 0x35, 0xba, 0xd9, 0xe1, 0xf2, 0x26, + 0x73, 0xbd, 0x64, 0x93, 0xe7, 0x83, 0x76, 0xc4, 0xf8, + 0x4b, 0xa9, 0x91, 0x8c, 0xd2, 0xf5, 0x08, 0xe6, 0x58, + 0xcd, 0xfb, 0x90, 0xc1, 0x84, 0x72, 0x77, 0x72, 0x47, + 0x5f, 0xcb, 0x7f, 0x74, 0x85, 0x56, 0xba, 0x73, 0x86, + 0xc1, 0x32, 0x1c, 0xaf, 0xc5, 0x60, 0x2c, 0x91, 0x99, + 0x09, 0x03, 0xcb, 0xe6, 0xa4, 0xae, 0x0b, 0xdc, 0x15, + 0x70, 0x4c, 0x91, 0xa9, 0x9e, 0x5e, 0x63, 0x5c, 0x24, + 0xc9, 0x26, 0x39, 0x56, 0xe4, 0x6c, 0x2c, 0x65, 0xf8, + 0x0b, 0x4f, 0x56, 0x8f, 0x1e, 0x74, 0xda, 0x31, 0xad, + 0x8f, 0x1b, 0xa7, 0xb1, 0xb3, 0x9b, 0x48, 0x09, 0x08, + 0xdd, 0xe1, 0x25, 0x20, 0xa4, 0xc7, 0x12, 0xd4, 0xb0, + 0xa0, 0xcb, 0x90, 0xf5, 0x9f, 0xc1, 0x8b, 0xbc, 0x9d, + 0xcf, 0x78, 0xfc, 0xa1, 0x04, 0x4b, 0x0b, 0x7e, 0x82, + 0x94, 0x80, 0x0e, 0x70, 0x77, 0xce, 0x63, 0x1c, 0x43, + 0x41, 0x3f, 0x5d, 0x61, 0x1a, 0x44, 0xaa, 0xd0, 0xb7, + 0x18, 0xd8, 0x91, 0x83, 0xa4, 0xa7, 0xa1, 0x86, 0x13, + 0x54, 0xaf, 0xa8, 0xdb, 0x1a, 0xd7, 0xa9, 0x54, 0xca, + 0x67, 0xb5, 0xb6, 0xb4, 0x22, 0x1a, 0x24, 0x8e, 0x65, + 0x01, 0xa8, 0xd2, 0x15, 0x9d, 0x98, 0x59, 0x70, 0x94, + 0xb4, 0x96, 0xeb, 0xf2, 0x95, 0x41, 0x9a, 0x89, 0x02, + 0xb7, 0x6a, 0x20, 0x2a, 0x64, 0xf1, 0x1c, 0x1e, 0x3d, + 0xd8, 0xdb, 0x6d, 0xef, 0xf2, 0x1a, 0x24, 0xa4, 0xd0, + 0xb9, 0x98, 0xd3, 0xe5, 0xbd, 0x7a, 0xa3, 0xc3, 0x19, + 0x97, 0x54, 0x77, 0x97, 0xb5, 0x57, 0x93, 0x71, 0x24, + 0x91, 0x81, 0xcf, 0x5f, 0x38, 0xb9, 0xd5, 0x7e, 0x8b, + 0x0f, 0xea, 0x56, 0x49, 0xac, 0x25, 0xc4, 0x6c, 0x5e, + 0x4e, 0x08, 0x31, 0xc8, 0xdf, 0x0b, 0x19, 0xb9, 0xbc, + 0xec, 0x3b, 0x89, 0xf8, 0x98, 0xe3, 0x6c, 0xf6, 0x0f, + 0x5b, 0x7e, 0x03, 0x10, 0x68, 0x78, 0x2c, 0xfa, 0x39, + 0x5c, 0x64, 0x5b, 0xa1, 0xfc, 0x8d, 0x14, 0x87, 0x62, + 0x04, 0x57, 0xc0, 0x5b, 0x6f, 0x6e, 0x3c, 0xea, 0xe6, + 0x23, 0xde, 0x9b, 0x1d, 0x89, 0x69, 0x38, 0xfb, 0x10, + 0xab, 0xb9, 0xda, 0xee, 0xa8, 0x8d, 0x96, 0xc0, 0xa5, + 0x40, 0xce, 0x16, 0x1e, 0xf5, 0xf4, 0x74, 0x6f, 0x0e, + 0x38, 0xe5, 0x1d, 0xe6, 0x6c, 0x19, 0xa5, 0x71, 0x48, + 0xda, 0x3e, 0xe9, 0x10, 0x57, 0x16, 0x89, 0xd3, 0x5b, + 0x4a, 0x5b, 0xa9, 0xb1, 0x13, 0xad, 0x77, 0xaf, 0x1f, + 0x8b, 0x71, 0x3f, 0xff, 0x7c, 0xc4, 0x31, 0xb2, 0xa7, + 0x18, 0x2f, 0x4b, 0x99, 0xe2, 0x14, 0xbf, 0x1e, 0x69, + 0x8f, 0x56, 0xe2, 0x2c, 0x84, 0x34, 0xd6, 0x76, 0x27, + 0x06, 0x7f, 0x2e, 0x9d, 0xbe, 0x90, 0x95, 0xda, 0x5a, + 0xfb, 0xaa, 0x8a, 0x51, 0x3d, 0x97, 0xb8, 0x75, 0xe9, + 0xba, 0x2a, 0x03, 0x7e, 0xb0, 0xe3, 0xdc, 0xe3, 0x3b, + 0x2a, 0xd8, 0x77, 0xa5, 0xf3, 0x76, 0x69, 0xf1, 0xd2, + 0xd5, 0xb3, 0xba, 0xfa, 0x97, 0x55, 0x5f, 0xd1, 0xc3, + 0x10, 0x55, 0x9a, 0xb6, 0xce, 0x32, 0x80, 0x7f, 0x48, + 0xb7, 0x15, 0x85, 0x3f, 0x22, 0x58, 0x00, 0x51, 0x12, + 0x5c, 0xcc, 0xd0, 0x77, 0x26, 0x57, 0x4b, 0xbb, 0x67, + 0x21, 0x0d, 0x92, 0x80, 0xe0, 0xec, 0x2f, 0x58, 0x44, + 0x8b, 0x98, 0x70, 0x16, 0x13, 0x91, 0x38, 0xee, 0x9e, + 0x4f, 0xf2, 0x6f, 0x95, 0x49, 0xe8, 0xcc, 0xc5, 0x6d, + 0x20, 0x20, 0x4d, 0x1b, 0x08, 0xf4, 0xa5, 0x8b, 0xf3, + 0xf6, 0x89, 0x2c, 0x17, 0xa6, 0xa8, 0xa8, 0xfb, 0xab, + 0x6f, 0xa0, 0xe3, 0xcd, 0xc5, 0xfb, 0xac, 0x91, 0x42, + 0x8c, 0xf2, 0x28, 0xd1, 0x13, 0xdb, 0x63, 0x59, 0x69, + 0xab, 0x16, 0x5a, 0xaf, 0x0a, 0xfa, 0x43, 0x6d, 0x53, + 0x7f, 0x14, 0x88, 0xc8, 0xa1, 0x71, 0x45, 0x54, 0x30, + 0xa7, 0x91, 0x55, 0x44, 0x07, 0x03, 0x78, 0xf3, 0xf6, + 0x23, 0xc0, 0x21, 0x4b, 0x39, 0xc4, 0x9a, 0x5a, 0xe8, + 0xad, 0x28, 0x6b, 0xd2, 0xd7, 0xc9, 0xed, 0xf4, 0x30, + 0xff, 0xf8, 0xc4, 0x7a, 0xfe, 0x49, 0x1c, 0x28, 0xbb, + 0x89, 0xfa, 0x9d, 0x64, 0xcc, 0x37, 0x76, 0x6a, 0xf3, + 0x8b, 0x94, 0x60, 0xe0, 0xb2, 0x29, 0xf8, 0x5a, 0xc6, + 0x3e, 0xcc, 0x6f, 0x13, 0x85, 0x7c, 0xaa, 0xc4, 0x35, + 0x56, 0x9a, 0xb6, 0x96, 0x76, 0x41, 0xe2, 0x11, 0xbe, + 0x07, 0xba, 0x0c, 0x21, 0x32, 0xc3, 0xb3, 0xf3, 0x96, + 0x49, 0xa2, 0xc4, 0x49, 0x48, 0xfe, 0x17, 0xef, 0xdf, + 0x1e, 0xf3, 0xde, 0x5f, 0xa0, 0x49, 0xfc, 0xa5, 0xb5, + 0xf3, 0x4c, 0x99, 0x5f, 0xcb, 0x33, 0xc6, 0x54, 0x52, + 0xa0, 0x85, 0x16, 0x75, 0x2c, 0x5f, 0x87, 0x61, 0x58, + 0xc9, 0x23, 0x0a, 0x36, 0x66, 0x3b, 0x78, 0x65, 0xcc, + 0xd4, 0x8e, 0xe1, 0x27, 0x9a, 0x74, 0x37, 0x79, 0x4c, + 0x5c, 0x35, 0xf9, 0xa5, 0x7f, 0x79, 0x35, 0xa8, 0x7d, + 0xcf, 0x64, 0xa3, 0x44, 0xb9, 0xee, 0x1e, 0x07, 0x5c, + 0xda, 0xcd, 0x93, 0xfc, 0x33, 0x77, 0x68, 0xfc, 0xd6, + 0xea, 0xf4, 0xcd, 0x0a, 0x3a, 0xe3, 0xb3, 0xef, 0xf9, + 0xb5, 0x1a, 0x4b, 0x50, 0x2e, 0xcb, 0x88, 0x48, 0x60, + 0xc3, 0x5c, 0x1b, 0xb7, 0xcc, 0x7a, 0x49, 0x2e, 0xf0, + 0x9e, 0x96, 0x47, 0x7d, 0x82, 0x85, 0xcb, 0x37, 0x85, + 0x26, 0xfd, 0xe1, 0x13, 0x57, 0xad, 0x51, 0xdc, 0x02, + 0x8d, 0x3c, 0x4e, 0xdd, 0xf3, 0xdf, 0xbe, 0xab, 0x0d, + 0x99, 0xf8, 0x13, 0x37, 0x0b, 0x1b, 0xaf, 0x08, 0x9b, + 0x38, 0x5b, 0x3a, 0x91, 0x71, 0x9a, 0xe6, 0xc1, 0x7d, + 0xd4, 0xd8, 0xf2, 0x66, 0x57, 0x99, 0x29, 0x58, 0xb5, + 0x9d, 0x8f, 0x86, 0x7f, 0xe9, 0x17, 0xff, 0x3c, 0xfd, + 0x0a, 0xfd, 0x15, 0x5c, 0x2f, 0x77, 0x6c, 0x2b, 0x86, + 0x72, 0xcb, 0x00, 0x4d, 0x31, 0x98, 0xfe, 0x28, 0xc5, + 0x54, 0x36, 0x97, 0x8c, 0xc9, 0x31, 0xae, 0xff, 0xfc, + 0xa6, 0x15, 0xf9, 0x9d, 0x49, 0x83, 0x47, 0xb4, 0xe5, + 0x8c, 0x55, 0x2f, 0x35, 0x6d, 0x7c, 0x47, 0xb9, 0xeb, + 0x0a, 0x64, 0xea, 0x22, 0xae, 0xe3, 0x6b, 0xae, 0x0e, + 0xf8, 0xc4, 0x64, 0x18, 0x56, 0xa7, 0x78, 0x92, 0x20, + 0xe0, 0x03, 0x93, 0x42, 0x1f, 0x1a, 0x48, 0xa1, 0x11, + 0xdd, 0x83, 0x99, 0x67, 0xc5, 0xf2, 0x0a, 0x9e, 0xfa, + 0xab, 0x68, 0x54, 0x1d, 0xa7, 0xe8, 0x44, 0x5f, 0x46, + 0x23, 0xea, 0xdd, 0xb2, 0xf5, 0x83, 0x76, 0x84, 0x13, + 0xd6, 0xe4, 0xb2, 0x59, 0x92, 0x92, 0xf4, 0xb5, 0x56, + 0xd7, 0x29, 0xc7, 0x05, 0x00, 0x79, 0x17, 0x59, 0x20, + 0xc6, 0x6a, 0xdc, 0x45, 0x93, 0xe7, 0xfc, 0x29, 0x37, + 0xa7, 0x7e, 0xbc, 0x21, 0xe7, 0xe1, 0xff, 0x18, 0x54, + 0xf9, 0xd3, 0x0c, 0x78, 0xe1, 0xc9, 0x40, 0x36, 0x36, + 0x68, 0x46, 0x3c, 0x9a, 0x4d, 0xa6, 0xbc, 0xc3, 0xc7, + 0xc9, 0x8c, 0x7e, 0xc6, 0x07, 0x2a, 0xd0, 0x4d, 0x45, + 0x3d, 0x65, 0xef, 0x56, 0x7f, 0xf1, 0xcd, 0x6d, 0x97, + 0x0c, 0x11, 0x66, 0xf4, 0x27, 0xfc, 0xe3, 0xf3, 0x93, + 0x0d, 0xa1, 0x5a, 0x95, 0x86, 0xcc, 0x0f, 0xf4, 0x97, + 0xbc, 0x7c, 0x62, 0x78, 0xe5, 0x01, 0xe0, 0xc7, 0x0c, + 0xe7, 0xa9, 0x84, 0xa6, 0x17, 0xaa, 0x36, 0x06, 0x2a, + 0x0f, 0x2f, 0x7e, 0x3d, 0xe8, 0x70, 0x8d, 0x36, 0x73, + 0x9a, 0x7f, 0x47, 0x95, 0xc5, 0x5d, 0xc5, 0xfa, 0x9c, + 0x64, 0x52, 0xcb, 0x52, 0x74, 0xda, 0xb0, 0x1f, 0x82, + 0x01, 0x43, 0x98, 0xa6, 0xe7, 0xf2, 0x89, 0x51, 0x92, + 0xf8, 0x37, 0x82, 0x8e, 0x91, 0x58, 0x40, 0x2c, 0xac, + 0xcf, 0xde, 0x92, 0x63, 0x5a, 0x64, 0xf9, 0x9c, 0xa4, + 0x47, 0x6d, 0x13, 0x43, 0xd3, 0xa6, 0x89, 0xbb, 0x7b, + 0x32, 0x45, 0x2d, 0x0e, 0x52, 0x25, 0x67, 0xda, 0x1d, + 0x9e, 0x42, 0x38, 0xfc, 0x92, 0x84, 0x4d, 0x13, 0x53, + 0xef, 0x46, 0x81, 0xdd, 0xf6, 0x79, 0x9f, 0xba, 0x45, + 0x49, 0x4b, 0x93, 0x4a, 0x54, 0x1c, 0x72, 0xa0, 0xfd, + 0xa1, 0x13, 0x1c, 0x5e, 0xa5, 0x4e, 0xd5, 0xdf, 0xd1, + 0x6a, 0x40, 0x1d, 0x5e, 0x57, 0xf8, 0xe3, 0x3a, 0xe8, + 0x35, 0xf4, 0x67, 0xa2, 0x37, 0xf2, 0xe0, 0xd1, 0xfe, + 0x08, 0x5e, 0x5c, 0x41, 0x17, 0x87, 0x24, 0xae, 0xf3, + 0xe2, 0xc8, 0xb4, 0xfc, 0x3b, 0xef, 0xdb, 0x5e, 0x27, + 0x93, 0x0f, 0x01, 0xf9, 0x35, 0xcf, 0x67, 0x4f, 0x65, + 0xde, 0xca, 0xb6, 0xf1, 0x12, 0xa0, 0xd7, 0x53, 0x09, + 0xec, 0x83, 0x9a, 0xb6, 0x8f, 0xf6, 0x03, 0xdf, 0x92, + 0xa9, 0xc4, 0x85, 0x55, 0x5a, 0x74, 0x66, 0x9e, 0xc0, + 0x46, 0xc7, 0x50, 0x7b, 0xda, 0x56, 0x4a, 0xf5, 0x38, + 0x37, 0xd5, 0x82, 0x81, 0xf3, 0x2d, 0x51, 0xa6, 0xa3, + 0x34, 0xf9, 0x24, 0xed, 0x35, 0x80, 0x72, 0xae, 0x3d, + 0x8b, 0xf8, 0x66, 0xb2, 0x6c, 0x3f, 0x4e, 0x2c, 0xdb, + 0x89, 0x76, 0x95, 0x8f, 0x1a, 0xbe, 0xfc, 0x6c, 0x37, + 0xec, 0xf9, 0x80, 0x32, 0xac, 0x94, 0x97, 0x85, 0xe4, + 0xa5, 0x19, 0x32, 0x46, 0x1f, 0x98, 0x89, 0x4c, 0x85, + 0xf1, 0xfc, 0xed, 0x01, 0x98, 0x4d, 0x4a, 0xd4, 0xd1, + 0x4e, 0x82, 0x0b, 0x32, 0x0d, 0x48, 0x34, 0x64, 0x98, + 0xea, 0x6c, 0xf9, 0x11, 0x25, 0xbc, 0x48, 0xc3, 0xf4, + 0x96, 0xfc, 0x5e, 0x71, 0x5d, 0xfa, 0xf7, 0x9f, 0x75, + 0x89, 0x1d, 0xe7, 0x3b, 0x97, 0x39, 0x18, 0x90, 0xca, + 0xa5, 0x46, 0x01, 0x2a, 0x13, 0x54, 0x5c, 0x2a, 0x14, + 0xed, 0x1b, 0x65, 0x0a, 0xb0, 0xd9, 0x95, 0x01, 0xd0, + 0xb3, 0x78, 0xd6, 0xc4, 0x06, 0xf3, 0x7f, 0x51, 0xe0, + 0x39, 0xed, 0x2c, 0xf3, 0xfa, 0xc3, 0xfa, 0x1d, 0x7c, + 0x82, 0x0f, 0x45, 0xb7, 0x15, 0xcf, 0x99, 0x53, 0x59, + 0x9d, 0x54, 0x31, 0x6a, 0xf8, 0xb8, 0x73, 0x2d, 0xd1, + 0xab, 0x1b, 0x69, 0xc9, 0x86, 0xdc, 0x7a, 0xca, 0xb9, + 0x6a, 0xaf, 0x1e, 0x8f, 0x83, 0xa8, 0xf0, 0xae, 0x44, + 0x85, 0x0d, 0x1f, 0x6c, 0x3a, 0x90, 0x50, 0xef, 0x7c, + 0x3c, 0x1c, 0xc4, 0xb8, 0x66, 0x1c, 0x14, 0xf7, 0xf2, + 0x5f, 0x5c, 0x70, 0x28, 0xa7, 0x55, 0x93, 0xdb, 0xa0, + 0x95, 0x9c, 0x1b, 0xb7, 0xb6, 0x44, 0x5e, 0x98, 0x88, + 0x89, 0xb8, 0x5a, 0xee, 0xba, 0xfc, 0xc6, 0x87, 0x2a, + 0xdb, 0xb7, 0xcf, 0xb2, 0x4b, 0x96, 0x2c, 0x91, 0x54, + 0x34, 0x33, 0xfb, 0x57, 0xbe, 0xf5, 0x7b, 0xbe, 0x6b, + 0xa0, 0x3b, 0x4d, 0x09, 0x18, 0x9b, 0x75, 0x2c, 0xde, + 0x28, 0x87, 0xd3, 0x7b, 0xf5, 0xbe, 0x0d, 0x33, 0x5a, + 0x3b, 0x92, 0x41, 0x35, 0x50, 0x65, 0xc9, 0xa9, 0xfa, + 0xab, 0x22, 0x4b, 0x8c, 0x3a, 0xb1, 0x9e, 0x31, 0x41, + 0xd2, 0x2f, 0xca, 0x9e, 0xd0, 0x96, 0x0c, 0x03, 0x08, + 0xec, 0x94, 0xa5, 0xb1, 0x65, 0x2b, 0xe1, 0xe4, 0x48, + 0x11, 0xd6, 0x8c, 0x60, 0x6d, 0xf4, 0x64, 0x89, 0xa6, + 0x69, 0x4b, 0xa0, 0xbe, 0xae, 0xf5, 0xde, 0xba, 0x45, + 0x12, 0xc8, 0x28, 0xe0, 0x7a, 0xb5, 0xd4, 0x75, 0x7a, + 0x24, 0x59, 0x4f, 0xbf, 0x0a, 0xa4, 0x53, 0x9a, 0x59, + 0xca, 0x06, 0x51, 0x6d, 0xcb, 0x93, 0x63, 0x6e, 0x24, + 0xe2, 0x41, 0xa5, 0xa9, 0x19, 0xc3, 0x59, 0x9a, 0x0c, + 0xb6, 0x4e, 0x65, 0x60, 0xa0, 0x49, 0xf0, 0x7f, 0x50, + 0x96, 0xed, 0xe9, 0xfc, 0x33, 0x5b, 0x52, 0x51, 0x7e, + 0x77, 0xd7, 0xbb, 0xaf, 0xdd, 0x12, 0x4b, 0xbc, 0xc6, + 0xae, 0xca, 0x92, 0x3a, 0x9f, 0xc1, 0x0c, 0x8f, 0x01, + 0xbe, 0x4c, 0x78, 0x23, 0x7c, 0x8b, 0x82, 0xb7, 0x45, + 0x80, 0x44, 0x34, 0x9d, 0x13, 0xdb, 0xc4, 0x3f, 0x1b, + 0x39, 0xb0, 0xee, 0xa9, 0xac, 0x5e, 0x3d, 0xc3, 0x59, + 0x92, 0xcc, 0x6e, 0x6c, 0x97, 0xcc, 0xba, 0x15, 0xa6, + 0x53, 0x92, 0x76, 0x35, 0x01, 0x70, 0x16, 0xde, 0xde, + 0x56, 0xc3, 0xb3, 0x48, 0x8b, 0x4d, 0xfa, 0xa7, 0xcb, + 0x43, 0xb5, 0x76, 0x9a, 0x56, 0x03, 0xd6, 0x41, 0xbe, + 0x73, 0x89, 0x1f, 0x6f, 0x02, 0x3f, 0xcc, 0xaf, 0x49, + 0xe3, 0x5e, 0xb3, 0xf4, 0xbc, 0x61, 0xf9, 0x9e, 0x9e, + 0xec, 0x10, 0x98, 0x0d, 0x5a, 0x6d, 0xcf, 0xbf, 0xe3, + 0xe5, 0xf5, 0x1b, 0x17, 0x46, 0x7a, 0x32, 0xc7, 0x18, + 0x40, 0x20, 0x8e, 0x06, 0x62, 0x2d, 0x1b, 0x90, 0x54, + 0x4f, 0x7f, 0xe4, 0x50, 0x09, 0xdc, 0x57, 0x22, 0xe9, + 0x7c, 0x3c, 0x77, 0x57, 0xc2, 0x8b, 0xc9, 0x6a, 0x2b, + 0x31, 0xa1, 0x7f, 0x14, 0xdf, 0x22, 0x7d, 0xed, 0xc9, + 0x0d, 0xbb, 0x93, 0xba, 0x72, 0x85, 0x33, 0x58, 0x80, + 0xc0, 0xf5, 0x75, 0x5d, 0x7e, 0x5f, 0xfb, 0x41, 0xbc, + 0x5f, 0x62, 0x13, 0xb9, 0x16, 0x1e, 0xfe, 0x9e, 0x53, + 0x53, 0xce, 0xa0, 0xfc, 0x7f, 0xf6, 0x18, 0xc2, 0x0f, + 0xb9, 0x7f, 0xbf, 0x09, 0xc3, 0x37, 0x08, 0xb0, 0x1f, + 0x16, 0x80, 0x5e, 0xf6, 0xcb, 0xfe, 0x22, 0x7c, 0x07, + 0x99, 0xb3, 0x12, 0x69, 0xa4, 0x05, 0xc9, 0x29, 0xc7, + 0xd0, 0x57, 0x05, 0x33, 0x85, 0x0c, 0xd4, 0xfe, 0xfc, + 0x54, 0xa8, 0xc9, 0x7b, 0x92, 0x67, 0xa6, 0xa7, 0xbf, + 0x5f, 0xfc, 0xe9, 0x65, 0x31, 0x4f, 0x85, 0x8f, 0x89, + 0xbe, 0xa1, 0xdb, 0x6d, 0x96, 0x52, 0x09, 0x56, 0x12, + 0xc6, 0xb2, 0x28, 0x26, 0x07, 0x39, 0x21, 0x39, 0xce, + 0x55, 0xf9, 0x82, 0x23, 0xc2, 0x3f, 0x3a, 0x66, 0xc4, + 0xee, 0x10, 0x4b, 0xf1, 0x1e, 0x1d, 0x59, 0xfa, 0x28, + 0x20, 0x34, 0x26, 0x49, 0x7c, 0xc3, 0x85, 0x2f, 0x80, + 0xbe, 0x2c, 0xbc, 0x94, 0x81, 0x74, 0x2a, 0x21, 0x49, + 0x1d, 0xa7, 0xff, 0xf0, 0x21, 0x56, 0x98, 0x68, 0x8f, + 0x52, 0x2d, 0xa0, 0xf2, 0x84, 0x73, 0x2f, 0xe2, 0x90, + 0x8c, 0x56, 0xd1, 0xbf, 0x67, 0xc3, 0x19, 0x47, 0x14, + 0x71, 0x62, 0x25, 0xdc, 0x11, 0xbc, 0x24, 0xa0, 0xb2, + 0x42, 0x72, 0x37, 0x78, 0xe6, 0xe0, 0xf6, 0x8c, 0x66, + 0xe5, 0x1b, 0x7a, 0x79, 0x46, 0xc0, 0x76, 0xcd, 0xa9, + 0x3c, 0xb2, 0x17, 0x8c, 0xc9, 0xb1, 0xc4, 0x2a, 0x1f, + 0xdb, 0xf7, 0xeb, 0x8a, 0x5d, 0x29, 0xd1, 0xd1, 0x98, + 0x43, 0x9e, 0x22, 0xf3, 0x96, 0x1e, 0x83, 0xeb, 0x44, + 0x08, 0xc4, 0xa0, 0xd2, 0xd3, 0x36, 0xf8, 0x94, 0xab, + 0x3c, 0x4b, 0x68, 0xf3, 0x7c, 0x1a, 0x16, 0x1a, 0x66, + 0x77, 0x67, 0xee, 0x64, 0xc2, 0xdb, 0x53, 0xae, 0x1f, + 0xeb, 0x44, 0x77, 0x3b, 0x5f, 0x74, 0x48, 0xe9, 0x05, + 0xfa, 0x3a, 0x03, 0x1b, 0x54, 0x36, 0xb0, 0x28, 0x79, + 0x70, 0xe6, 0x2f, 0xb4, 0xf5, 0x28, 0x60, 0x1e, 0x63, + 0xf6, 0x03, 0x09, 0x4f, 0x0f, 0x7f, 0x01, 0xe5, 0x02, + 0x6a, 0x76, 0x96, 0xb9, 0x58, 0x39, 0xf9, 0xc4, 0x05, + 0xac, 0x93, 0x2f, 0x30, 0xab, 0xc5, 0x2b, 0xad, 0xed, + 0x3c, 0xb0, 0x6c, 0x66, 0x94, 0x7e, 0x79, 0x01, 0x90, + 0xf0, 0x10, 0xb5, 0xcd, 0x6b, 0x07, 0xc2, 0xe7, 0x8a, + 0xac, 0xf7, 0x5b, 0xb5, 0x11, 0xf8, 0x1a, 0x52, 0xc7, + 0x5d, 0x2c, 0xc1, 0xce, 0x8f, 0x0c, 0xc1, 0x6a, 0x95, + 0x80, 0x25, 0xf9, 0x95, 0x28, 0x18, 0x65, 0xd3, 0x15, + 0x0e, 0xbf, 0x6f, 0xa6, 0x86, 0xd9, 0xea, 0xdc, 0xb8, + 0x89, 0x02, 0x08, 0x6b, 0xd1, 0x96, 0xb1, 0x6f, 0xb1, + 0x28, 0x6b, 0xc4, 0xe3, 0xa8, 0x53, 0xd3, 0xd0, 0x67, + 0x00, 0x7c, 0xa1, 0x0a, 0xd1, 0x9a, 0x89, 0x12, 0xc9, + 0xa7, 0x3f, 0x03, 0x03, 0xad, 0x0f, 0x34, 0x2c, 0xd8, + 0xdf, 0x70, 0xed, 0x38, 0xf4, 0xb1, 0xf7, 0xb1, 0x72, + 0x5e, 0x2d, 0xa6, 0xb7, 0x8d, 0x9c, 0x7f, 0x96, 0x73, + 0xc8, 0x47, 0x46, 0x20, 0x2f, 0x44, 0x2c, 0x2b, 0xa2, + 0x30, 0xe4, 0x81, 0x91, 0x7e, 0xce, 0x4c, 0x8b, 0xcc, + 0x5f, 0xfd, 0xff, 0x2f, 0x94, 0xbd, 0xe5, 0xaf, 0x09, + 0xcd, 0xb6, 0xbc, 0x65, 0x83, 0xc3, 0xcd, 0x79, 0xc4, + 0x68, 0xda, 0x46, 0x36, 0x97, 0x52, 0x35, 0x90, 0x4f, + 0x1d, 0x8d, 0x66, 0x1f, 0xea, 0x5d, 0xef, 0xdf, 0x8c, + 0xa8, 0x6b, 0xb0, 0xdc, 0x1a, 0x1e, 0x79, 0x43, 0xe9, + 0x29, 0x71, 0x11, 0xbd, 0xe5, 0xd6, 0x71, 0xf4, 0xa7, + 0xf8, 0x64, 0x40, 0x73, 0x46, 0x5b, 0x2a, 0xb5, 0x9a, + 0xa1, 0x9a, 0x64, 0x4c, 0x5e, 0xa5, 0x8d, 0xfd, 0x49, + 0x91, 0xba, 0xe3, 0xa7, 0x19, 0xac, 0x2b, 0xe9, 0xea, + 0xf1, 0x1c, 0x85, 0x91, 0xea, 0xfb, 0xc7, 0x5c, 0x46, + 0x7e, 0xa8, 0x0a, 0x92, 0xbf, 0x61, 0x2d, 0xc2, 0x20, + 0x7e, 0xf7, 0x0d, 0xb8, 0x65, 0x41, 0x48, 0x39, 0xb9, + 0xb0, 0xd4, 0xc1, 0x84, 0xee, 0x21, 0xba, 0x9c, 0x74, + 0xf3, 0x6d, 0x0a, 0x33, 0x87, 0xab, 0x2e, 0x15, 0x1b, + 0xad, 0xac, 0x98, 0xae, 0x7c, 0xd8, 0xae, 0x03, 0x50, + 0xfa, 0xae, 0xfe, 0x8c, 0x6d, 0x51, 0x67, 0x76, 0x70, + 0xa6, 0x2f, 0x1e, 0x6a, 0x4f, 0xf0, 0xbe, 0x51, 0xbb, + 0xa6, 0x20, 0x1f, 0x56, 0x72, 0x34, 0xd0, 0x13, 0x6e, + 0x0f, 0x1a, 0xcb, 0x34, 0xe1, 0xfb, 0x3c, 0xf1, 0x43, + 0x1b, 0x73, 0x40, 0xa0, 0x1f, 0x5d, 0x40, 0x51, 0x9f, + 0x97, 0x56, 0x1f, 0x26, 0x54, 0x03, 0xb8, 0x2e, 0xfd, + 0xc7, 0x52, 0xea, 0x85, 0x5d, 0x45, 0x71, 0xa3, 0x5c, + 0x86, 0x23, 0xcb, 0x08, 0xc5, 0xd8, 0x21, 0xfd, 0x10, + 0x49, 0xac, 0xaa, 0xd5, 0x97, 0x37, 0xbb, 0xad, 0xd5, + 0x84, 0xc2, 0x65, 0xeb, 0xdd, 0x92, 0x7c, 0x50, 0x64, + 0x4f, 0x08, 0x32, 0x56, 0x81, 0x39, 0xa4, 0xfc, 0x3f, + 0x04, 0xbb, 0xde, 0xe9, 0xcd, 0xb6, 0xbb, 0x29, 0x6b, + 0x75, 0x64, 0x32, 0x5f, 0xca, 0xd0, 0x3a, 0x19, 0x3d, + 0x01, 0x8c, 0x0b, 0xd5, 0x76, 0xe6, 0x97, 0x5d, 0x73, + 0x7b, 0xb3, 0xcd, 0xdf, 0xbc, 0x29, 0xda, 0xa5, 0x22, + 0xfb, 0x1d, 0xf6, 0xf1, 0x50, 0x71, 0x50, 0xd3, 0xf8, + 0x0a, 0xbf, 0x37, 0x28, 0xca, 0x3b, 0xab, 0xec, 0xf5, + 0xee, 0x2d, 0x1e, 0x21, 0x35, 0x39, 0x56, 0x55, 0x3c, + 0x9e, 0x5a, 0x58, 0x94, 0x85, 0xa7, 0xba, 0x0d, 0xa4, + 0x0b, 0x4c, 0x73, 0xb2, 0x56, 0x68, 0x5a, 0x5d, 0x6c, + 0x18, 0xce, 0xc5, 0x25, 0x14, 0xc9, 0xb3, 0xc9, 0x94, + 0x57, 0x62, 0x95, 0xd5, 0x1c, 0xf6, 0x93, 0x12, 0x45, + 0x28, 0xa1, 0x7e, 0x96, 0x53, 0x68, 0xf5, 0x6a, 0xca, + 0xbe, 0x04, 0x94, 0x97, 0xcf, 0xb5, 0xcf, 0x70, 0xe1, + 0x7e, 0x15, 0x2d, 0x6a, 0x67, 0x0c, 0x86, 0x07, 0xd1, + 0xe2, 0x95, 0xc3, 0xd8, 0x22, 0xdf, 0x6a, 0x88, 0xc1, + 0xad, 0x83, 0x57, 0x30, 0xd0, 0x59, 0xaf, 0xf4, 0x9f, + 0x8d, 0x89, 0x7d, 0x0b, 0xee, 0xb7, 0x1c, 0xaa, 0xd2, + 0x4c, 0x7a, 0xa4, 0xfb, 0x99, 0xe0, 0x0a, 0xd7, 0x4d, + 0xc4, 0xe9, 0x88, 0x18, 0x27, 0x1d, 0xb2, 0xe9, 0x43, + 0x16, 0x25, 0x29, 0x04, 0x98, 0x81, 0xfd, 0xaf, 0xdd, + 0x3f, 0xf1, 0x61, 0x32, 0x20, 0x51, 0x96, 0xe4, 0xd2, + 0xab, 0xc4, 0x00, 0x33, 0xb4, 0x7b, 0x3c, 0xc2, 0x2d, + 0x61, 0x11, 0x4d, 0x72, 0x16, 0x6d, 0xfb, 0x24, 0x67, + 0x7c, 0xea, 0xf0, 0x79, 0xa3, 0x50, 0x93, 0xe3, 0x9b, + 0x7f, 0x89, 0xf0, 0xa6, 0x8c, 0xb0, 0xaf, 0x1c, 0xe0, + 0x91, 0xce, 0x3f, 0xe5, 0x43, 0x90, 0x41, 0x95, 0xc7, + 0x1f, 0x8f, 0x0a, 0xb2, 0x1e, 0x84, 0x3e, 0x86, 0xf0, + 0x81, 0x87, 0x8b, 0x04, 0x52, 0xa6, 0x46, 0xb0, 0xe4, + 0xf4, 0x5b, 0x97, 0x7b, 0x7b, 0x32, 0xb6, 0x17, 0x96, + 0x48, 0x12, 0xb6, 0x31, 0xf1, 0x5c, 0xd4, 0x8b, 0x93, + 0x60, 0xc4, 0x00, 0xea, 0x12, 0xe1, 0x93, 0x6f, 0x53, + 0x82, 0x2a, 0x48, 0x1d, 0xc1, 0x91, 0x79, 0x7c, 0x30, + 0x43, 0xe5, 0x1e, 0x10, 0x7e, 0x7f, 0xbc, 0x18, 0x60, + 0x03, 0x2a, 0xe5, 0xbb, 0x92, 0x7f, 0x24, 0x54, 0x12, + 0x21, 0x77, 0x89, 0xc9, 0x22, 0xfb, 0x57, 0xaa, 0x69, + 0xdd, 0x69, 0x06, 0xb0, 0xe5, 0x5b, 0x74, 0x1f, 0x02, + 0x99, 0x62, 0x56, 0x21, 0x29, 0xd2, 0x26, 0x0f, 0x6a, + 0x3a, 0x05, 0x96, 0x92, 0xb9, 0xff, 0xe9, 0x3b, 0x24, + 0x70, 0xd4, 0x13, 0xa4, 0xb2, 0x6c, 0x76, 0xe3, 0x55, + 0xe5, 0xc8, 0x18, 0x66, 0x60, 0x91, 0xba, 0x98, 0x5d, + 0x67, 0x13, 0x97, 0xce, 0x49, 0xaa, 0x52, 0x7b, 0x20, + 0x65, 0x65, 0x0a, 0x4f, 0x7b, 0x0a, 0x26, 0x62, 0xa7, + 0xb5, 0xab, 0x2d, 0x5d, 0x37, 0xad, 0xb8, 0x97, 0xcf, + 0xf5, 0x4f, 0xef, 0x03, 0xed, 0xce, 0x73, 0x68, 0x5d, + 0x9f, 0x6c, 0x3d, 0x3f, 0xd5, 0xc1, 0xca, 0x5f, 0xef, + 0xe4, 0xf8, 0xfb, 0xc7, 0xbb, 0x49, 0x30, 0x1a, 0xe1, + 0x3c, 0xd1, 0x7f, 0x7c, 0x26, 0xa2, 0x87, 0x6e, 0x80, + 0xa6, 0x47, 0x2c, 0x0f, 0xa6, 0x68, 0xf6, 0xde, 0x65, + 0x1f, 0x02, 0xa7, 0x09, 0x08, 0x34, 0xbe, 0x2c, 0xc7, + 0xed, 0x4c, 0xb0, 0xa1, 0x63, 0x63, 0x35, 0xe0, 0x11, + 0xfd, 0xe1, 0x2d, 0xb4, 0xcf, 0x9e, 0x18, 0x78, 0xa8, + 0x63, 0xbf, 0xb7, 0xe8, 0x22, 0x82, 0xc5, 0x9c, 0x0b, + 0x3a, 0x1c, 0x2f, 0x73, 0x80, 0xf1, 0xbb, 0x9a, 0x84, + 0x51, 0x2c, 0x1c, 0x2e, 0xda, 0xb8, 0xa3, 0x43, 0x4f, + 0x95, 0x8c, 0x06, 0x12, 0xdc, 0x75, 0x53, 0x01, 0xc4, + 0x50, 0x95, 0x31, 0x7e, 0x75, 0x33, 0x69, 0x3e, 0x82, + 0xad, 0x51, 0x1a, 0x4d, 0xa4, 0xe7, 0xbb, 0x7c, 0x9e, + 0x3c, 0xbc, 0x1a, 0xf7, 0x7d, 0x0f, 0xdd, 0x93, 0xb5, + 0x91, 0x61, 0x28, 0x28, 0x3b, 0x8f, 0xdd, 0xfa, 0xe6, + 0xf4, 0xcc, 0x21, 0x82, 0x0c, 0xe2, 0xe4, 0xc7, 0x39, + 0x69, 0x8e, 0xd6, 0xc0, 0x45, 0x94, 0x26, 0x27, 0x1b, + 0xca, 0x02, 0x39, 0x00, 0x12, 0xef, 0xad, 0x0f, 0xf2, + 0xdb, 0x19, 0x39, 0x6e, 0x4e, 0xfd, 0x14, 0x56, 0x3c, + 0xd3, 0xfb, 0x43, 0x2d, 0x14, 0xb1, 0x62, 0xd2, 0xc8, + 0x09, 0xe3, 0xb4, 0xf3, 0x24, 0x4e, 0xeb, 0xe5, 0xd6, + 0x42, 0x48, 0xa5, 0xf8, 0xd8, 0xcc, 0x0b, 0xd6, 0x23, + 0x59, 0x46, 0xaf, 0x15, 0xb2, 0x36, 0x2d, 0x52, 0xbe, + 0x4a, 0x5f, 0xc6, 0xb2, 0x3d, 0xc5, 0x53, 0x57, 0x35, + 0x2a, 0xa1, 0x06, 0xc8, 0x93, 0xa8, 0x3e, 0xc6, 0xcb, + 0xa4, 0xd9, 0xe4, 0x53, 0xa9, 0xe8, 0x6d, 0xe1, 0x73, + 0x97, 0xb9, 0x6f, 0xb3, 0xf8, 0x1d, 0xb4, 0xae, 0xd8, + 0x77, 0xa7, 0xef, 0xe1, 0xeb, 0x83, 0x3d, 0xc3, 0x35, + 0xf0, 0xc6, 0xd8, 0x66, 0xb5, 0x29, 0x7f, 0x74, 0xdb, + 0xa1, 0xf2, 0x16, 0xc9, 0x07, 0x0f, 0x5c, 0x3e, 0x18, + 0x64, 0x82, 0xfd, 0xae, 0x80, 0xca, 0xcf, 0xf9, 0x7e, + 0x7f, 0x36, 0x58, 0xd5, 0x4d, 0x2d, 0x5a, 0x27, 0x27, + 0xcc, 0x7e, 0x45, 0x0d, 0xf8, 0xd6, 0x5f, 0xee, 0x83, + 0x42, 0x83, 0x48, 0x0b, 0x64, 0xc6, 0x03, 0x4d, 0x1e, + 0x24, 0x90, 0xba, 0x2a, 0x92, 0x7d, 0x43, 0x77, 0x17, + 0xc8, 0xcc, 0x9f, 0x31, 0x80, 0x4e, 0x19, 0x7f, 0x8f, + 0xcf, 0xd7, 0x27, 0x48, 0x10, 0xea, 0x3d, 0xd6, 0x0f, + 0x70, 0x7a, 0xb9, 0xed, 0x53, 0x67, 0x1c, 0x56, 0xb1, + 0x78, 0xfc, 0x0c, 0xcc, 0x1f, 0xf8, 0x89, 0x45, 0x57, + 0x4a, 0x72, 0xd2, 0xa0, 0x07, 0x53, 0x73, 0x3d, 0x0e, + 0x45, 0x5a, 0x31, 0x94, 0x8f, 0x5f, 0x11, 0xe4, 0x36, + 0xe2, 0x19, 0xc4, 0x84, 0x94, 0xb9, 0xc0, 0xe6, 0x5d, + 0x66, 0x7e, 0x4c, 0x05, 0xc6, 0xcd, 0x9c, 0x6c, 0x8f, + 0x32, 0x68, 0xfb, 0x66, 0x86, 0x22, 0xf5, 0xfa, 0x9a, + 0x46, 0x26, 0xb5, 0xd5, 0xc1, 0x7d, 0xeb, 0x7b, 0x82, + 0x3e, 0x62, 0x8c, 0x76, 0x0b, 0x08, 0x1d, 0xe0, 0x75, + 0x34, 0x30, 0x4b, 0xc2, 0x4b, 0xcb, 0x49, 0xa3, 0x65, + 0x0e, 0x90, 0xd3, 0x57, 0xe5, 0xf5, 0x83, 0x1b, 0xa2, + 0xbb, 0x4a, 0x23, 0x63, 0x25, 0x64, 0xd7, 0xf1, 0x85, + 0x9b, 0xbe, 0x2e, 0xda, 0xad, 0xc8, 0x60, 0x37, 0x3c, + 0x78, 0x33, 0xb5, 0x76, 0x7c, 0xc6, 0xe5, 0x97, 0x86, + 0x6d, 0x70, 0xdc, 0x4f, 0x79, 0x39, 0xe6, 0x27, 0x78, + 0x57, 0x98, 0x69, 0x79, 0xaf, 0x0a, 0xc0, 0x64, 0x0c, + 0x1a, 0x09, 0xa0, 0x98, 0x06, 0x41, 0x5c, 0x29, 0x27, + 0xbd, 0x2e, 0xbe, 0xe8, 0x08, 0x5f, 0xdf, 0xed, 0xd9, + 0x31, 0x97, 0xdb, 0x0a, 0x1f, 0x4e, 0x1b, 0x67, 0x32, + 0xef, 0x84, 0xa2, 0x14, 0xa7, 0x83, 0x33, 0xdc, 0x40, + 0x55, 0x76, 0x27, 0x01, 0x9f, 0x98, 0x90, 0xa9, 0xfa, + 0xfb, 0x73, 0x86, 0x38, 0x6b, 0xa8, 0x57, 0xc9, 0xaa, + 0x06, 0xbf, 0x84, 0x97, 0xfa, 0xc8, 0xde, 0x67, 0x6b, + 0xa6, 0x2c, 0xa1, 0x90, 0x6c, 0x6d, 0xcd, 0xb5, 0x73, + 0x3c, 0x16, 0x68, 0xb4, 0x00, 0x55, 0xf6, 0xd8, 0x35, + 0xb0, 0xf9, 0x8e, 0x2e, 0xfb, 0x54, 0xc1, 0x8e, 0x51, + 0x90, 0x2d, 0x28, 0x83, 0x5d, 0x81, 0xd6, 0x00, 0x00, + 0x41, 0xf2, 0x97, 0xdf, 0x2f, 0x8d, 0xa8, 0xc2, 0x1d, + 0xe3, 0xbd, 0x1d, 0x2a, 0x6f, 0x4a, 0xfd, 0xd3, 0xcd, + 0x0b, 0xac, 0x28, 0x93, 0x87, 0x3e, 0xd9, 0x7b, 0x17, + 0xe2, 0x66, 0x0a, 0x6e, 0xcb, 0xa8, 0x3e, 0x3d, 0x9b, + 0x3c, 0xbe, 0x78, 0xe1, 0x2a, 0xa5, 0x42, 0x5f, 0xdc, + 0xe0, 0x0e, 0x06, 0x10, 0x59, 0xac, 0x4a, 0xd3, 0x63, + 0x95, 0x92, 0x31, 0x1c, 0x7d, 0xb1, 0x5e, 0x48, 0x01, + 0x23, 0x16, 0x61, 0xb3, 0xfc, 0xe6, 0x9a, 0x5d, 0x39, + 0xf9, 0x2f, 0xb5, 0xc6, 0x6d, 0xeb, 0xb2, 0x6e, 0x93, + 0x9d, 0x8b, 0x19, 0x74, 0xa9, 0xc4, 0x57, 0x96, 0xbc, + 0x1c, 0xbb, 0x88, 0x5a, 0xd6, 0xf7, 0xc0, 0xe2, 0xb6, + 0xf2, 0xb3, 0xf0, 0x56, 0x5b, 0x2c, 0x9e, 0xdf, 0x96, + 0x6d, 0xcc, 0x41, 0x06, 0xce, 0x1e, 0x1b, 0x3a, 0x39, + 0x67, 0xe1, 0x7e, 0x81, 0xfc, 0xff, 0x0a, 0xc0, 0xf1, + 0x76, 0x82, 0x49, 0x76, 0x88, 0x38, 0x10, 0x5c, 0x90, + 0x83, 0x4b, 0x3e, 0x8d, 0xb9, 0x35, 0x77, 0xf5, 0x4c, + 0x7e, 0x3e, 0x12, 0x54, 0xf0, 0x33, 0x56, 0xbc, 0x9b, + 0x0e, 0x10, 0x7d, 0x4a, 0xb6, 0x2d, 0x02, 0x35, 0x79, + 0xe8, 0x0c, 0x15, 0xc1, 0xde, 0xc7, 0x2a, 0x7d, 0xe1, + 0x27, 0xd4, 0x99, 0x50, 0x6b, 0xde, 0x6d, 0x02, 0x65, + 0x12, 0x88, 0xe6, 0x80, 0x13, 0x5e, 0xad, 0xb1, 0xef, + 0xe7, 0x77, 0x19, 0xc9, 0x63, 0xcf, 0x14, 0x41, 0x40, + 0x76, 0xc8, 0xa9, 0xc3, 0x08, 0x88, 0xdb, 0x44, 0x6c, + 0x10, 0x74, 0x5c, 0xf6, 0x86, 0x8c, 0x61, 0x95, 0x19, + 0x76, 0x1f, 0x3e, 0xcb, 0xdf, 0x6e, 0x08, 0x9f, 0x43, + 0xb9, 0x66, 0x2b, 0x88, 0x27, 0x48, 0xbe, 0x5d, 0x9e, + 0x83, 0x72, 0x9a, 0x43, 0x06, 0x8e, 0xf3, 0x9e, 0xba, + 0xd5, 0xd8, 0x70, 0x1b, 0xe4, 0x4e, 0x39, 0x0a, 0x37, + 0x5b, 0x2f, 0x8c, 0xa8, 0xbd, 0x3c, 0xfe, 0xb2, 0x59, + 0x5b, 0x5f, 0x5a, 0x05, 0x67, 0xc8, 0xec, 0x71, 0x5d, + 0xb5, 0x77, 0xc7, 0xb3, 0x1c, 0xb7, 0xac, 0x90, 0xf6, + 0xd3, 0xb7, 0x61, 0x65, 0xbe, 0x29, 0x8f, 0x27, 0x65, + 0x9a, 0x9a, 0x1c, 0x00, 0x82, 0xee, 0x10, 0xb9, 0x60, + 0xff, 0x9f, 0x5a, 0xbe, 0x09, 0x72, 0x63, 0x79, 0x60, + 0x50, 0x84, 0x18, 0xc9, 0xc5, 0x0d, 0x43, 0xce, 0x29, + 0x80, 0x72, 0x83, 0x12, 0x73, 0x13, 0x44, 0xec, 0x25, + 0xe5, 0x15, 0x70, 0xe2, 0x7f, 0x6b, 0x54, 0x5b, 0x58, + 0x57, 0x06, 0xdc, 0xae, 0x1f, 0x9c, 0x38, 0x4c, 0xbf, + 0x1c, 0x42, 0xb2, 0x63, 0x9c, 0xfb, 0xae, 0xc0, 0xdf, + 0xd3, 0xcc, 0xcc, 0xb9, 0x9b, 0xe9, 0x66, 0x77, 0x70, + 0x47, 0x6c, 0x8b, 0x5b, 0xc1, 0x87, 0x7a, 0x63, 0xa3, + 0x13, 0xfc, 0x2d, 0x16, 0xd3, 0xe2, 0x00, 0xe9, 0x94, + 0x11, 0xf2, 0x28, 0xda, 0x0b, 0x58, 0x09, 0x2d, 0x59, + 0x2d, 0xb5, 0x25, 0x99, 0xca, 0x63, 0xc9, 0x96, 0xa3, + 0x17, 0x2a, 0x0e, 0x22, 0x2c, 0x5f, 0x8d, 0x53, 0xc4, + 0xd1, 0x3d, 0x4e, 0x20, 0xdc, 0x44, 0x18, 0xd2, 0xd8, + 0x5c, 0x9a, 0x78, 0x0a, 0x53, 0xa8, 0x73, 0x7d, 0x98, + 0xc0, 0xba, 0xfb, 0xfe, 0x27, 0xd4, 0x82, 0x87, 0xd4, + 0x4d, 0xc0, 0xe3, 0xd1, 0xd0, 0xff, 0xf0, 0xd3, 0x04, + 0xfd, 0x11, 0xf4, 0x57, 0xc2, 0xcc, 0xcf, 0xa9, 0xe6, + 0xc5, 0x09, 0x4d, 0xcc, 0x36, 0x69, 0x26, 0x35, 0x8c, + 0xe8, 0xe2, 0xe2, 0xdd, 0x5a, 0x5f, 0xaf, 0xda, 0x38, + 0x07, 0x33, 0xfb, 0xf8, 0xfb, 0xf9, 0x62, 0x4a, 0x75, + 0xad, 0xc3, 0x95, 0xd3, 0x6e, 0x5b, 0xe3, 0x10, 0x2f, + 0x31, 0xaf, 0xcd, 0x57, 0xb9, 0x84, 0x3d, 0xa4, 0x66, + 0x3f, 0x10, 0xeb, 0xa2, 0xe2, 0xfa, 0xc7, 0xd3, 0x91, + 0x83, 0x48, 0xbb, 0x3a, 0x6c, 0xe4, 0x12, 0x1c, 0x36, + 0x44, 0xc5, 0x07, 0x07, 0x9b, 0x9d, 0x51, 0x3e, 0x74, + 0xc5, 0x35, 0x8a, 0x10, 0x9c, 0x0d, 0x81, 0xf3, 0x10, + 0x0f, 0x29, 0xaf, 0x01, 0x5d, 0x6f, 0x7f, 0x50, 0x9a, + 0xf8, 0xbf, 0x1c, 0x57, 0xfc, 0x25, 0x5c, 0x02, 0x15, + 0x43, 0x0b, 0x60, 0x21, 0xf3, 0xb1, 0x43, 0x9a, 0x41, + 0xa0, 0xc1, 0x1b, 0x7a, 0x88, 0x97, 0xfd, 0x27, 0x56, + 0xf7, 0x48, 0x1f, 0xb6, 0x9a, 0xa2, 0xb1, 0xc5, 0xab, + 0x30, 0xa1, 0x14, 0x91, 0xef, 0x14, 0xe3, 0x01, 0x73, + 0xf3, 0x8d, 0xfa, 0xd7, 0xae, 0x2f, 0x13, 0x5d, 0x66, + 0xfb, 0x1c, 0x4b, 0x2e, 0x94, 0xdb, 0x9f, 0x10, 0x5b, + 0x2a, 0x5e, 0x85, 0x98, 0x73, 0x9d, 0xcd, 0x7c, 0xa0, + 0x79, 0xb6, 0xef, 0x8e, 0xf8, 0xdd, 0x11, 0x32, 0x0d, + 0xec, 0x6a, 0x04, 0xea, 0x81, 0xd7, 0x63, 0xbd, 0x01, + 0x77, 0x3e, 0x52, 0x30, 0x88, 0x3a, 0x9e, 0x04, 0xdf, + 0x42, 0x8b, 0x40, 0x23, 0xa9, 0x5a, 0x97, 0x21, 0x55, + 0xce, 0x72, 0x21, 0x45, 0x40, 0x01, 0x66, 0x63, 0x1d, + 0xab, 0x37, 0x8d, 0xd5, 0x75, 0x56, 0xc2, 0x7c, 0xa0, + 0x9e, 0xa5, 0x85, 0xc2, 0x0b, 0x51, 0x80, 0xae, 0x0c, + 0xb3, 0xde, 0xa4, 0xb5, 0xa3, 0xa3, 0x00, 0xe1, 0xc9, + 0x09, 0xee, 0xab, 0xbb, 0x36, 0x78, 0x5b, 0x3f, 0x45, + 0x3d, 0xf6, 0xe8, 0x7e, 0xa3, 0xd7, 0x24, 0x78, 0xdf, + 0xbc, 0x9f, 0xe4, 0x4c, 0x4d, 0x22, 0xb8, 0x76, 0xb0, + 0x6a, 0xc1, 0x35, 0x66, 0xfe, 0xaf, 0xf1, 0xb4, 0x44, + 0x5e, 0xe0, 0xff, 0xcf, 0x80, 0xf8, 0xa8, 0x5f, 0x59, + 0x91, 0xa4, 0x4f, 0xc0, 0x58, 0xb1, 0x2d, 0xc9, 0x6a, + 0xcd, 0x62, 0xcb, 0x41, 0x89, 0x9d, 0x3b, 0x3e, 0x48, + 0x5f, 0x23, 0x46, 0x21, 0x8a, 0x49, 0xc0, 0x16, 0x07, + 0x4d, 0xd9, 0x26, 0xbe, 0x86, 0xfb, 0x06, 0xbd, 0x41, + 0xc5, 0xd8, 0x87, 0xf6, 0x94, 0xb1, 0xef, 0xed, 0xab, + 0xfb, 0x93, 0x48, 0x5a, 0xe7, 0x22, 0xbc, 0x2b, 0x24, + 0xb4, 0x86, 0x33, 0x9b, 0xd6, 0x09, 0x46, 0x85, 0x81, + 0x89, 0xa9, 0x30, 0x13, 0xfa, 0x08, 0x55, 0xfc, 0xe5, + 0xfb, 0xc8, 0xb2, 0xa8, 0x31, 0x4c, 0x9e, 0x1c, 0xff, + 0x80, 0x10, 0x77, 0x5f, 0xf1, 0x07, 0x14, 0xf7, 0x88, + 0xb9, 0xeb, 0x48, 0xfe, 0x18, 0x48, 0xf3, 0xaf, 0xfd, + 0x7d, 0x0c, 0x9f, 0x30, 0x11, 0xcb, 0xed, 0xfc, 0x31, + 0xf5, 0x6e, 0x72, 0xfa, 0x9a, 0x3a, 0xa5, 0x1d, 0x89, + 0x89, 0x8b, 0xc6, 0x2c, 0xaf, 0xa6, 0xef, 0xbd, 0xb4, + 0xc2, 0xa0, 0x97, 0x74, 0xd0, 0x4d, 0x72, 0xb7, 0xe8, + 0x24, 0xba, 0x5e, 0x53, 0x4b, 0x91, 0xc1, 0xe4, 0x14, + 0x22, 0x50, 0xb2, 0xc3, 0x84, 0xf4, 0xa6, 0xb3, 0xa4, + 0x99, 0xda, 0x82, 0x55, 0x8e, 0x38, 0xb4, 0x0c, 0x21, + 0xe5, 0x91, 0x30, 0xc7, 0x80, 0x55, 0xf1, 0x69, 0xde, + 0xd7, 0x82, 0xf3, 0x08, 0xd3, 0x16, 0x69, 0xe7, 0xd4, + 0xeb, 0xfc, 0x9b, 0x8f, 0xd6, 0xfc, 0xf9, 0x9f, 0x95, + 0xb3, 0x90, 0xa6, 0x12, 0x21, 0x53, 0x50, 0xd5, 0x3e, + 0x2b, 0x46, 0x14, 0x52, 0x20, 0x1c, 0x33, 0xed, 0xdd, + 0x58, 0x81, 0x92, 0x37, 0xe5, 0x99, 0x77, 0xfa, 0x29, + 0x28, 0x49, 0x07, 0xc8, 0xe2, 0x41, 0x8f, 0x77, 0x3b, + 0xb4, 0x8c, 0x34, 0x3e, 0x80, 0xcb, 0xcf, 0x73, 0x4d, + 0xfc, 0x78, 0x60, 0x9e, 0xd0, 0x86, 0xc3, 0x4d, 0xa7, + 0x40, 0x9c, 0x03, 0x72, 0x46, 0xc3, 0xc3, 0x74, 0xdf, + 0x5a, 0x47, 0x8d, 0xbc, 0xc1, 0x5b, 0x10, 0x3e, 0x7e, + 0x09, 0x3d, 0xdb, 0x0c, 0xc4, 0x3b, 0x12, 0xbf, 0x66, + 0xe2, 0xb7, 0x4c, 0x1a, 0x81, 0x58, 0x63, 0x39, 0x72, + 0xde, 0xfa, 0x5d, 0xcc, 0x2c, 0x69, 0x11, 0x0a, 0x5f, + 0xb9, 0xbc, 0xda, 0x80, 0x03, 0x8e, 0xa2, 0x02, 0x6c, + 0xc1, 0x15, 0xcc, 0xbf, 0x01, 0x14, 0xd0, 0x36, 0xad, + 0xdb, 0xb7, 0x77, 0xd6, 0x99, 0x94, 0xf5, 0xa5, 0xac, + 0xce, 0x9a, 0x23, 0x9b, 0x1e, 0xa4, 0x97, 0x7e, 0x41, + 0xc1, 0x65, 0xc7, 0x94, 0xfa, 0x07, 0x1d, 0x9a, 0x87, + 0xba, 0xee, 0xef, 0x99, 0x92, 0xaa, 0x41, 0x29, 0x03, + 0xe3, 0x01, 0x17, 0x42, 0xed, 0x11, 0x68, 0x44, 0x02, + 0xca, 0x81, 0x4b, 0x33, 0x81, 0x64, 0x30, 0x95, 0x7f, + 0x81, 0x17, 0xe6, 0x59, 0x0b, 0x4e, 0xf3, 0x4a, 0x72, + 0x0c, 0x45, 0x1e, 0x1d, 0x44, 0xe2, 0x9e, 0x45, 0x29, + 0x88, 0xb4, 0xda, 0x9b, 0x9f, 0x3e, 0x92, 0x9a, 0x0b, + 0x21, 0x2a, 0xd4, 0xa0, 0xd8, 0xd8, 0xbd, 0x06, 0x6d, + 0x71, 0x3c, 0xcc, 0xd8, 0xdc, 0x19, 0xd7, 0x8f, 0x21, + 0x01, 0x25, 0xa5, 0x15, 0x62, 0x43, 0xfa, 0xdf, 0xb9, + 0x33, 0x23, 0xd3, 0xa2, 0xab, 0xb1, 0x7e, 0x4e, 0x5e, + 0x46, 0xbd, 0x76, 0x6e, 0x18, 0x88, 0x5f, 0x85, 0x03, + 0x43, 0x57, 0xd6, 0x3a, 0xf2, 0xcc, 0x9d, 0xbc, 0x2c, + 0x67, 0xa8, 0xcd, 0xda, 0xe8, 0x39, 0x61, 0x68, 0x6d, + 0xcf, 0xeb, 0x07, 0x1f, 0x58, 0x61, 0x68, 0x6d, 0x78, + 0xa6, 0xad, 0xb6, 0x16, 0x70, 0x89, 0x49, 0x59, 0x62, + 0x76, 0xc1, 0xc3, 0xc8, 0xce, 0xe2, 0xfc, 0x42, 0x51, + 0x8d, 0xc8, 0xf1, 0x03, 0x17, 0x36, 0x55, 0x8c, 0x8e, + 0x98, 0xd1, 0x33, 0x3c, 0x4c, 0x63, 0x81, 0x97, 0xc5, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x0c, 0x16, 0x19, 0x23, 0x28, 0x30, + 0x37, + }, +}; diff --git a/lib/crypto/tests/mldsa_kunit.c b/lib/crypto/tests/mldsa_kunit.c new file mode 100644 index 000000000000..67f8f93e3dc6 --- /dev/null +++ b/lib/crypto/tests/mldsa_kunit.c @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * KUnit tests and benchmark for ML-DSA + * + * Copyright 2025 Google LLC + */ +#include +#include +#include +#include + +#define Q 8380417 /* The prime q = 2^23 - 2^13 + 1 */ + +/* ML-DSA parameters that the tests use */ +static const struct { + int sig_len; + int pk_len; + int k; + int lambda; + int gamma1; + int beta; + int omega; +} params[] = { + [MLDSA44] = { + .sig_len = MLDSA44_SIGNATURE_SIZE, + .pk_len = MLDSA44_PUBLIC_KEY_SIZE, + .k = 4, + .lambda = 128, + .gamma1 = 1 << 17, + .beta = 78, + .omega = 80, + }, + [MLDSA65] = { + .sig_len = MLDSA65_SIGNATURE_SIZE, + .pk_len = MLDSA65_PUBLIC_KEY_SIZE, + .k = 6, + .lambda = 192, + .gamma1 = 1 << 19, + .beta = 196, + .omega = 55, + }, + [MLDSA87] = { + .sig_len = MLDSA87_SIGNATURE_SIZE, + .pk_len = MLDSA87_PUBLIC_KEY_SIZE, + .k = 8, + .lambda = 256, + .gamma1 = 1 << 19, + .beta = 120, + .omega = 75, + }, +}; + +#include "mldsa-testvecs.h" + +static void do_mldsa_and_assert_success(struct kunit *test, + const struct mldsa_testvector *tv) +{ + int err = mldsa_verify(tv->alg, tv->sig, tv->sig_len, tv->msg, + tv->msg_len, tv->pk, tv->pk_len); + KUNIT_ASSERT_EQ(test, err, 0); +} + +static u8 *kunit_kmemdup_or_fail(struct kunit *test, const u8 *src, size_t len) +{ + u8 *dst = kunit_kmalloc(test, len, GFP_KERNEL); + + KUNIT_ASSERT_NOT_NULL(test, dst); + return memcpy(dst, src, len); +} + +/* + * Test that changing coefficients in a valid signature's z vector results in + * the following behavior from mldsa_verify(): + * + * * -EBADMSG if a coefficient is changed to have an out-of-range value, i.e. + * absolute value >= gamma1 - beta, corresponding to the verifier detecting + * the out-of-range coefficient and rejecting the signature as malformed + * + * * -EKEYREJECTED if a coefficient is changed to a different in-range value, + * i.e. absolute value < gamma1 - beta, corresponding to the verifier + * continuing to the "real" signature check and that check failing + */ +static void test_mldsa_z_range(struct kunit *test, + const struct mldsa_testvector *tv) +{ + u8 *sig = kunit_kmemdup_or_fail(test, tv->sig, tv->sig_len); + const int lambda = params[tv->alg].lambda; + const s32 gamma1 = params[tv->alg].gamma1; + const int beta = params[tv->alg].beta; + /* + * We just modify the first coefficient. The coefficient is gamma1 + * minus either the first 18 or 20 bits of the u32, depending on gamma1. + * + * The layout of ML-DSA signatures is ctilde || z || h. ctilde is + * lambda / 4 bytes, so z starts at &sig[lambda / 4]. + */ + u8 *z_ptr = &sig[lambda / 4]; + const u32 z_data = get_unaligned_le32(z_ptr); + const u32 mask = (gamma1 << 1) - 1; + /* These are the four boundaries of the out-of-range values. */ + const s32 out_of_range_coeffs[] = { + -gamma1 + 1, + -(gamma1 - beta), + gamma1, + gamma1 - beta, + }; + /* + * These are the two boundaries of the valid range, along with 0. We + * assume that none of these matches the original coefficient. + */ + const s32 in_range_coeffs[] = { + -(gamma1 - beta - 1), + 0, + gamma1 - beta - 1, + }; + + /* Initially the signature is valid. */ + do_mldsa_and_assert_success(test, tv); + + /* Test some out-of-range coefficients. */ + for (int i = 0; i < ARRAY_SIZE(out_of_range_coeffs); i++) { + const s32 c = out_of_range_coeffs[i]; + + put_unaligned_le32((z_data & ~mask) | (mask & (gamma1 - c)), + z_ptr); + KUNIT_ASSERT_EQ(test, -EBADMSG, + mldsa_verify(tv->alg, sig, tv->sig_len, tv->msg, + tv->msg_len, tv->pk, tv->pk_len)); + } + + /* Test some in-range coefficients. */ + for (int i = 0; i < ARRAY_SIZE(in_range_coeffs); i++) { + const s32 c = in_range_coeffs[i]; + + put_unaligned_le32((z_data & ~mask) | (mask & (gamma1 - c)), + z_ptr); + KUNIT_ASSERT_EQ(test, -EKEYREJECTED, + mldsa_verify(tv->alg, sig, tv->sig_len, tv->msg, + tv->msg_len, tv->pk, tv->pk_len)); + } +} + +/* Test that mldsa_verify() rejects malformed hint vectors with -EBADMSG. */ +static void test_mldsa_bad_hints(struct kunit *test, + const struct mldsa_testvector *tv) +{ + const int omega = params[tv->alg].omega; + const int k = params[tv->alg].k; + u8 *sig = kunit_kmemdup_or_fail(test, tv->sig, tv->sig_len); + /* Pointer to the encoded hint vector in the signature */ + u8 *hintvec = &sig[tv->sig_len - omega - k]; + u8 h; + + /* Initially the signature is valid. */ + do_mldsa_and_assert_success(test, tv); + + /* Cumulative hint count exceeds omega */ + memcpy(sig, tv->sig, tv->sig_len); + hintvec[omega + k - 1] = omega + 1; + KUNIT_ASSERT_EQ(test, -EBADMSG, + mldsa_verify(tv->alg, sig, tv->sig_len, tv->msg, + tv->msg_len, tv->pk, tv->pk_len)); + + /* Cumulative hint count decreases */ + memcpy(sig, tv->sig, tv->sig_len); + KUNIT_ASSERT_GE(test, hintvec[omega + k - 2], 1); + hintvec[omega + k - 1] = hintvec[omega + k - 2] - 1; + KUNIT_ASSERT_EQ(test, -EBADMSG, + mldsa_verify(tv->alg, sig, tv->sig_len, tv->msg, + tv->msg_len, tv->pk, tv->pk_len)); + + /* + * Hint indices out of order. To test this, swap hintvec[0] and + * hintvec[1]. This assumes that the original valid signature had at + * least two nonzero hints in the first element (asserted below). + */ + memcpy(sig, tv->sig, tv->sig_len); + KUNIT_ASSERT_GE(test, hintvec[omega], 2); + h = hintvec[0]; + hintvec[0] = hintvec[1]; + hintvec[1] = h; + KUNIT_ASSERT_EQ(test, -EBADMSG, + mldsa_verify(tv->alg, sig, tv->sig_len, tv->msg, + tv->msg_len, tv->pk, tv->pk_len)); + + /* + * Extra hint indices given. For this test to work, the original valid + * signature must have fewer than omega nonzero hints (asserted below). + */ + memcpy(sig, tv->sig, tv->sig_len); + KUNIT_ASSERT_LT(test, hintvec[omega + k - 1], omega); + hintvec[omega - 1] = 0xff; + KUNIT_ASSERT_EQ(test, -EBADMSG, + mldsa_verify(tv->alg, sig, tv->sig_len, tv->msg, + tv->msg_len, tv->pk, tv->pk_len)); +} + +static void test_mldsa_mutation(struct kunit *test, + const struct mldsa_testvector *tv) +{ + const int sig_len = tv->sig_len; + const int msg_len = tv->msg_len; + const int pk_len = tv->pk_len; + const int num_iter = 200; + u8 *sig = kunit_kmemdup_or_fail(test, tv->sig, sig_len); + u8 *msg = kunit_kmemdup_or_fail(test, tv->msg, msg_len); + u8 *pk = kunit_kmemdup_or_fail(test, tv->pk, pk_len); + + /* Initially the signature is valid. */ + do_mldsa_and_assert_success(test, tv); + + /* Changing any bit in the signature should invalidate the signature */ + for (int i = 0; i < num_iter; i++) { + size_t pos = get_random_u32_below(sig_len); + u8 b = 1 << get_random_u32_below(8); + + sig[pos] ^= b; + KUNIT_ASSERT_NE(test, 0, + mldsa_verify(tv->alg, sig, sig_len, msg, + msg_len, pk, pk_len)); + sig[pos] ^= b; + } + + /* Changing any bit in the message should invalidate the signature */ + for (int i = 0; i < num_iter; i++) { + size_t pos = get_random_u32_below(msg_len); + u8 b = 1 << get_random_u32_below(8); + + msg[pos] ^= b; + KUNIT_ASSERT_NE(test, 0, + mldsa_verify(tv->alg, sig, sig_len, msg, + msg_len, pk, pk_len)); + msg[pos] ^= b; + } + + /* Changing any bit in the public key should invalidate the signature */ + for (int i = 0; i < num_iter; i++) { + size_t pos = get_random_u32_below(pk_len); + u8 b = 1 << get_random_u32_below(8); + + pk[pos] ^= b; + KUNIT_ASSERT_NE(test, 0, + mldsa_verify(tv->alg, sig, sig_len, msg, + msg_len, pk, pk_len)); + pk[pos] ^= b; + } + + /* All changes should have been undone. */ + KUNIT_ASSERT_EQ(test, 0, + mldsa_verify(tv->alg, sig, sig_len, msg, msg_len, pk, + pk_len)); +} + +static void test_mldsa(struct kunit *test, const struct mldsa_testvector *tv) +{ + /* Valid signature */ + KUNIT_ASSERT_EQ(test, tv->sig_len, params[tv->alg].sig_len); + KUNIT_ASSERT_EQ(test, tv->pk_len, params[tv->alg].pk_len); + do_mldsa_and_assert_success(test, tv); + + /* Signature too short */ + KUNIT_ASSERT_EQ(test, -EBADMSG, + mldsa_verify(tv->alg, tv->sig, tv->sig_len - 1, tv->msg, + tv->msg_len, tv->pk, tv->pk_len)); + + /* Signature too long */ + KUNIT_ASSERT_EQ(test, -EBADMSG, + mldsa_verify(tv->alg, tv->sig, tv->sig_len + 1, tv->msg, + tv->msg_len, tv->pk, tv->pk_len)); + + /* Public key too short */ + KUNIT_ASSERT_EQ(test, -EBADMSG, + mldsa_verify(tv->alg, tv->sig, tv->sig_len, tv->msg, + tv->msg_len, tv->pk, tv->pk_len - 1)); + + /* Public key too long */ + KUNIT_ASSERT_EQ(test, -EBADMSG, + mldsa_verify(tv->alg, tv->sig, tv->sig_len, tv->msg, + tv->msg_len, tv->pk, tv->pk_len + 1)); + + /* + * Message too short. Error is EKEYREJECTED because it gets rejected by + * the "real" signature check rather than the well-formedness checks. + */ + KUNIT_ASSERT_EQ(test, -EKEYREJECTED, + mldsa_verify(tv->alg, tv->sig, tv->sig_len, tv->msg, + tv->msg_len - 1, tv->pk, tv->pk_len)); + /* + * Can't simply try (tv->msg, tv->msg_len + 1) too, as tv->msg would be + * accessed out of bounds. However, ML-DSA just hashes the message and + * doesn't handle different message lengths differently anyway. + */ + + /* Test the validity checks on the z vector. */ + test_mldsa_z_range(test, tv); + + /* Test the validity checks on the hint vector. */ + test_mldsa_bad_hints(test, tv); + + /* Test randomly mutating the inputs. */ + test_mldsa_mutation(test, tv); +} + +static void test_mldsa44(struct kunit *test) +{ + test_mldsa(test, &mldsa44_testvector); +} + +static void test_mldsa65(struct kunit *test) +{ + test_mldsa(test, &mldsa65_testvector); +} + +static void test_mldsa87(struct kunit *test) +{ + test_mldsa(test, &mldsa87_testvector); +} + +static s32 mod(s32 a, s32 m) +{ + a %= m; + if (a < 0) + a += m; + return a; +} + +static s32 symmetric_mod(s32 a, s32 m) +{ + a = mod(a, m); + if (a > m / 2) + a -= m; + return a; +} + +/* Mechanical, inefficient translation of FIPS 204 Algorithm 36, Decompose */ +static void decompose_ref(s32 r, s32 gamma2, s32 *r0, s32 *r1) +{ + s32 rplus = mod(r, Q); + + *r0 = symmetric_mod(rplus, 2 * gamma2); + if (rplus - *r0 == Q - 1) { + *r1 = 0; + *r0 = *r0 - 1; + } else { + *r1 = (rplus - *r0) / (2 * gamma2); + } +} + +/* Mechanical, inefficient translation of FIPS 204 Algorithm 40, UseHint */ +static s32 use_hint_ref(u8 h, s32 r, s32 gamma2) +{ + s32 m = (Q - 1) / (2 * gamma2); + s32 r0, r1; + + decompose_ref(r, gamma2, &r0, &r1); + if (h == 1 && r0 > 0) + return mod(r1 + 1, m); + if (h == 1 && r0 <= 0) + return mod(r1 - 1, m); + return r1; +} + +/* + * Test that for all possible inputs, mldsa_use_hint() gives the same output as + * a mechanical translation of the pseudocode from FIPS 204. + */ +static void test_mldsa_use_hint(struct kunit *test) +{ + for (int i = 0; i < 2; i++) { + const s32 gamma2 = (Q - 1) / (i == 0 ? 88 : 32); + + for (u8 h = 0; h < 2; h++) { + for (s32 r = 0; r < Q; r++) { + KUNIT_ASSERT_EQ(test, + mldsa_use_hint(h, r, gamma2), + use_hint_ref(h, r, gamma2)); + } + } + } +} + +static void benchmark_mldsa(struct kunit *test, + const struct mldsa_testvector *tv) +{ + const int warmup_niter = 200; + const int benchmark_niter = 200; + u64 t0, t1; + + if (!IS_ENABLED(CONFIG_CRYPTO_LIB_BENCHMARK)) + kunit_skip(test, "not enabled"); + + for (int i = 0; i < warmup_niter; i++) + do_mldsa_and_assert_success(test, tv); + + t0 = ktime_get_ns(); + for (int i = 0; i < benchmark_niter; i++) + do_mldsa_and_assert_success(test, tv); + t1 = ktime_get_ns(); + kunit_info(test, "%llu ops/s", + div64_u64((u64)benchmark_niter * NSEC_PER_SEC, + t1 - t0 ?: 1)); +} + +static void benchmark_mldsa44(struct kunit *test) +{ + benchmark_mldsa(test, &mldsa44_testvector); +} + +static void benchmark_mldsa65(struct kunit *test) +{ + benchmark_mldsa(test, &mldsa65_testvector); +} + +static void benchmark_mldsa87(struct kunit *test) +{ + benchmark_mldsa(test, &mldsa87_testvector); +} + +static struct kunit_case mldsa_kunit_cases[] = { + KUNIT_CASE(test_mldsa44), + KUNIT_CASE(test_mldsa65), + KUNIT_CASE(test_mldsa87), + KUNIT_CASE(test_mldsa_use_hint), + KUNIT_CASE(benchmark_mldsa44), + KUNIT_CASE(benchmark_mldsa65), + KUNIT_CASE(benchmark_mldsa87), + {}, +}; + +static struct kunit_suite mldsa_kunit_suite = { + .name = "mldsa", + .test_cases = mldsa_kunit_cases, +}; +kunit_test_suite(mldsa_kunit_suite); + +MODULE_DESCRIPTION("KUnit tests and benchmark for ML-DSA"); +MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); +MODULE_LICENSE("GPL"); From 14e15c71d7bb591fd08f527669717694810d3973 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 10 Dec 2025 17:18:33 -0800 Subject: [PATCH 03/53] lib/crypto: nh: Add NH library Add support for the NH "almost-universal hash function" to lib/crypto/, specifically the variant of NH used in Adiantum. This will replace the need for the "nhpoly1305" crypto_shash algorithm. All the implementations of "nhpoly1305" use architecture-optimized code only for the NH stage; they just use the generic C Poly1305 code for the Poly1305 stage. We can achieve the same result in a simpler way using an (architecture-optimized) nh() function combined with code in crypto/adiantum.c that passes the results to the Poly1305 library. This commit begins this cleanup by adding the nh() function. The code is derived from crypto/nhpoly1305.c and include/crypto/nhpoly1305.h. Link: https://lore.kernel.org/r/20251211011846.8179-2-ebiggers@kernel.org Signed-off-by: Eric Biggers --- include/crypto/nh.h | 52 ++++++++++++++++++++++++++++ lib/crypto/Kconfig | 10 ++++++ lib/crypto/Makefile | 8 +++++ lib/crypto/nh.c | 82 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 include/crypto/nh.h create mode 100644 lib/crypto/nh.c diff --git a/include/crypto/nh.h b/include/crypto/nh.h new file mode 100644 index 000000000000..465e85bf203f --- /dev/null +++ b/include/crypto/nh.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * NH hash function for Adiantum + */ + +#ifndef _CRYPTO_NH_H +#define _CRYPTO_NH_H + +#include + +/* NH parameterization: */ + +/* Endianness: little */ +/* Word size: 32 bits (works well on NEON, SSE2, AVX2) */ + +/* Stride: 2 words (optimal on ARM32 NEON; works okay on other CPUs too) */ +#define NH_PAIR_STRIDE 2 +#define NH_MESSAGE_UNIT (NH_PAIR_STRIDE * 2 * sizeof(u32)) + +/* Num passes (Toeplitz iteration count): 4, to give ε = 2^{-128} */ +#define NH_NUM_PASSES 4 +#define NH_HASH_BYTES (NH_NUM_PASSES * sizeof(u64)) + +/* Max message size: 1024 bytes (32x compression factor) */ +#define NH_NUM_STRIDES 64 +#define NH_MESSAGE_WORDS (NH_PAIR_STRIDE * 2 * NH_NUM_STRIDES) +#define NH_MESSAGE_BYTES (NH_MESSAGE_WORDS * sizeof(u32)) +#define NH_KEY_WORDS (NH_MESSAGE_WORDS + \ + NH_PAIR_STRIDE * 2 * (NH_NUM_PASSES - 1)) +#define NH_KEY_BYTES (NH_KEY_WORDS * sizeof(u32)) + +/** + * nh() - NH hash function for Adiantum + * @key: The key. @message_len + 48 bytes of it are used. This is NH_KEY_BYTES + * if @message_len has its maximum length of NH_MESSAGE_BYTES. + * @message: The message + * @message_len: The message length in bytes. Must be a multiple of 16 + * (NH_MESSAGE_UNIT) and at most 1024 (NH_MESSAGE_BYTES). + * @hash: (output) The resulting hash value + * + * Note: the pseudocode for NH in the Adiantum paper iterates over 1024-byte + * segments of the message, computes a 32-byte hash for each, and returns all + * the hashes concatenated together. In contrast, this function just hashes one + * segment and returns one hash. It's the caller's responsibility to call this + * function for each 1024-byte segment and collect all the hashes. + * + * Context: Any context. + */ +void nh(const u32 *key, const u8 *message, size_t message_len, + __le64 hash[NH_NUM_PASSES]); + +#endif /* _CRYPTO_NH_H */ diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index ee6ab129d0cf..f14c9f5974d8 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -108,6 +108,16 @@ config CRYPTO_LIB_MLDSA The ML-DSA library functions. Select this if your module uses any of the functions from . +config CRYPTO_LIB_NH + tristate + help + Implementation of the NH almost-universal hash function, specifically + the variant of NH used in Adiantum. + +config CRYPTO_LIB_NH_ARCH + bool + depends on CRYPTO_LIB_NH && !UML + config CRYPTO_LIB_POLY1305 tristate help diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index a0578105266f..929b84568809 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -131,6 +131,14 @@ libmldsa-y := mldsa.o ################################################################################ +obj-$(CONFIG_CRYPTO_LIB_NH) += libnh.o +libnh-y := nh.o +ifeq ($(CONFIG_CRYPTO_LIB_NH_ARCH),y) +CFLAGS_nh.o += -I$(src)/$(SRCARCH) +endif + +################################################################################ + obj-$(CONFIG_CRYPTO_LIB_POLY1305) += libpoly1305.o libpoly1305-y := poly1305.o ifeq ($(CONFIG_ARCH_SUPPORTS_INT128),y) diff --git a/lib/crypto/nh.c b/lib/crypto/nh.c new file mode 100644 index 000000000000..e1d0095b5289 --- /dev/null +++ b/lib/crypto/nh.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2018 Google LLC + */ + +/* + * Implementation of the NH almost-universal hash function, specifically the + * variant of NH used in Adiantum. This is *not* a cryptographic hash function. + * + * Reference: section 6.3 of "Adiantum: length-preserving encryption for + * entry-level processors" (https://eprint.iacr.org/2018/720.pdf). + */ + +#include +#include +#include +#include +#include + +#ifdef CONFIG_CRYPTO_LIB_NH_ARCH +#include "nh.h" /* $(SRCARCH)/nh.h */ +#else +static bool nh_arch(const u32 *key, const u8 *message, size_t message_len, + __le64 hash[NH_NUM_PASSES]) +{ + return false; +} +#endif + +void nh(const u32 *key, const u8 *message, size_t message_len, + __le64 hash[NH_NUM_PASSES]) +{ + u64 sums[4] = { 0, 0, 0, 0 }; + + if (nh_arch(key, message, message_len, hash)) + return; + + static_assert(NH_PAIR_STRIDE == 2); + static_assert(NH_NUM_PASSES == 4); + + while (message_len) { + u32 m0 = get_unaligned_le32(message + 0); + u32 m1 = get_unaligned_le32(message + 4); + u32 m2 = get_unaligned_le32(message + 8); + u32 m3 = get_unaligned_le32(message + 12); + + sums[0] += (u64)(u32)(m0 + key[0]) * (u32)(m2 + key[2]); + sums[1] += (u64)(u32)(m0 + key[4]) * (u32)(m2 + key[6]); + sums[2] += (u64)(u32)(m0 + key[8]) * (u32)(m2 + key[10]); + sums[3] += (u64)(u32)(m0 + key[12]) * (u32)(m2 + key[14]); + sums[0] += (u64)(u32)(m1 + key[1]) * (u32)(m3 + key[3]); + sums[1] += (u64)(u32)(m1 + key[5]) * (u32)(m3 + key[7]); + sums[2] += (u64)(u32)(m1 + key[9]) * (u32)(m3 + key[11]); + sums[3] += (u64)(u32)(m1 + key[13]) * (u32)(m3 + key[15]); + key += NH_MESSAGE_UNIT / sizeof(key[0]); + message += NH_MESSAGE_UNIT; + message_len -= NH_MESSAGE_UNIT; + } + + hash[0] = cpu_to_le64(sums[0]); + hash[1] = cpu_to_le64(sums[1]); + hash[2] = cpu_to_le64(sums[2]); + hash[3] = cpu_to_le64(sums[3]); +} +EXPORT_SYMBOL_GPL(nh); + +#ifdef nh_mod_init_arch +static int __init nh_mod_init(void) +{ + nh_mod_init_arch(); + return 0; +} +subsys_initcall(nh_mod_init); + +static void __exit nh_mod_exit(void) +{ +} +module_exit(nh_mod_exit); +#endif + +MODULE_DESCRIPTION("NH almost-universal hash function"); +MODULE_LICENSE("GPL"); From 7246fe6cd64475d8126a85eef6a3a425f105c203 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 10 Dec 2025 17:18:34 -0800 Subject: [PATCH 04/53] lib/crypto: tests: Add KUnit tests for NH Add some simple KUnit tests for the nh() function. These replace the test coverage which will be lost by removing the nhpoly1305 crypto_shash. Note that the NH code also continues to be tested indirectly as well, via the tests for the "adiantum(xchacha12,aes)" crypto_skcipher. Link: https://lore.kernel.org/r/20251211011846.8179-3-ebiggers@kernel.org Signed-off-by: Eric Biggers --- lib/crypto/tests/Kconfig | 8 + lib/crypto/tests/Makefile | 1 + lib/crypto/tests/nh-testvecs.h | 298 ++++++++++++++++++++++++++++ lib/crypto/tests/nh_kunit.c | 43 ++++ scripts/crypto/gen-hash-testvecs.py | 40 ++++ 5 files changed, 390 insertions(+) create mode 100644 lib/crypto/tests/nh-testvecs.h create mode 100644 lib/crypto/tests/nh_kunit.c diff --git a/lib/crypto/tests/Kconfig b/lib/crypto/tests/Kconfig index c9165c14fc46..4970463ea0aa 100644 --- a/lib/crypto/tests/Kconfig +++ b/lib/crypto/tests/Kconfig @@ -47,6 +47,14 @@ config CRYPTO_LIB_MLDSA_KUNIT_TEST help KUnit tests for the ML-DSA digital signature algorithm. +config CRYPTO_LIB_NH_KUNIT_TEST + tristate "KUnit tests for NH" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS + select CRYPTO_LIB_NH + help + KUnit tests for the NH almost-universal hash function. + config CRYPTO_LIB_POLY1305_KUNIT_TEST tristate "KUnit tests for Poly1305" if !KUNIT_ALL_TESTS depends on KUNIT diff --git a/lib/crypto/tests/Makefile b/lib/crypto/tests/Makefile index 3dde0b40b2c5..f4262379f56c 100644 --- a/lib/crypto/tests/Makefile +++ b/lib/crypto/tests/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST) += blake2s_kunit.o obj-$(CONFIG_CRYPTO_LIB_CURVE25519_KUNIT_TEST) += curve25519_kunit.o obj-$(CONFIG_CRYPTO_LIB_MD5_KUNIT_TEST) += md5_kunit.o obj-$(CONFIG_CRYPTO_LIB_MLDSA_KUNIT_TEST) += mldsa_kunit.o +obj-$(CONFIG_CRYPTO_LIB_NH_KUNIT_TEST) += nh_kunit.o obj-$(CONFIG_CRYPTO_LIB_POLY1305_KUNIT_TEST) += poly1305_kunit.o obj-$(CONFIG_CRYPTO_LIB_POLYVAL_KUNIT_TEST) += polyval_kunit.o obj-$(CONFIG_CRYPTO_LIB_SHA1_KUNIT_TEST) += sha1_kunit.o diff --git a/lib/crypto/tests/nh-testvecs.h b/lib/crypto/tests/nh-testvecs.h new file mode 100644 index 000000000000..b393e1f90f31 --- /dev/null +++ b/lib/crypto/tests/nh-testvecs.h @@ -0,0 +1,298 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* This file was generated by: ./scripts/crypto/gen-hash-testvecs.py nh */ + +static const u8 nh_test_key[NH_KEY_BYTES] = { + 0x04, 0x59, 0x66, 0x92, 0x81, 0xd7, 0xe9, 0x25, + 0x68, 0xfa, 0xb0, 0xca, 0x9f, 0xea, 0x98, 0xca, + 0xcd, 0xbf, 0x6d, 0xa5, 0x0c, 0x22, 0xc3, 0x57, + 0xdc, 0x35, 0x05, 0xdd, 0x5b, 0xb0, 0xce, 0xf6, + 0xb2, 0x4c, 0x77, 0x2e, 0xd2, 0x63, 0xf0, 0x17, + 0x60, 0xd8, 0xd3, 0xd9, 0xed, 0x34, 0xb6, 0xed, + 0x6a, 0x11, 0xc0, 0x25, 0xda, 0xba, 0x7e, 0xef, + 0x49, 0x13, 0xf7, 0xd9, 0xfc, 0xb6, 0xfd, 0x58, + 0xe9, 0x5f, 0xc5, 0xc4, 0x69, 0x89, 0xba, 0xa6, + 0x2b, 0x58, 0x8d, 0x36, 0x6c, 0xb9, 0x90, 0x1e, + 0x64, 0xc7, 0x44, 0x84, 0x03, 0x70, 0x30, 0x47, + 0xdd, 0x58, 0xf4, 0x87, 0x61, 0xfd, 0x9c, 0x6b, + 0x51, 0x1b, 0x39, 0x1d, 0x6d, 0x50, 0xae, 0x19, + 0x71, 0x03, 0xc7, 0xa7, 0x42, 0x82, 0x8f, 0xa5, + 0x63, 0x6a, 0xe2, 0x8a, 0xad, 0x4b, 0x40, 0xa7, + 0x3f, 0x8b, 0xe4, 0xae, 0xb2, 0x8a, 0x14, 0x78, + 0x91, 0x07, 0xba, 0x02, 0x08, 0xc1, 0x34, 0xb8, + 0xda, 0x61, 0x67, 0xf6, 0x98, 0x97, 0x1a, 0xcb, + 0x0f, 0x82, 0x80, 0xff, 0x02, 0x54, 0x16, 0x57, + 0x18, 0x35, 0xaf, 0x16, 0x17, 0x68, 0xcc, 0xc7, + 0x52, 0xac, 0x31, 0x39, 0x60, 0xe4, 0xb4, 0xcb, + 0x0e, 0xf9, 0x57, 0xe9, 0x96, 0xff, 0x99, 0xd6, + 0x10, 0x96, 0x09, 0xab, 0x28, 0x92, 0x1b, 0x9f, + 0x10, 0xde, 0x3e, 0x87, 0xb8, 0x9d, 0x2d, 0xa0, + 0x3c, 0x91, 0x85, 0x8c, 0x9e, 0xc0, 0x97, 0x9a, + 0xb4, 0x54, 0x7f, 0x4a, 0x63, 0xc2, 0x75, 0x0f, + 0x0d, 0x2f, 0x62, 0x56, 0x48, 0x0e, 0xb6, 0xc7, + 0xcf, 0x0d, 0x78, 0xca, 0xbd, 0x31, 0x9e, 0x4c, + 0xf7, 0x3f, 0x9e, 0xc2, 0xea, 0x5e, 0x44, 0x6d, + 0x76, 0xf9, 0xc5, 0xe0, 0x29, 0xea, 0x15, 0xbf, + 0xaf, 0xd4, 0x75, 0xc8, 0x89, 0xcf, 0x4f, 0x17, + 0xfd, 0x4a, 0x45, 0xa5, 0x4d, 0x2d, 0x87, 0x11, + 0x2b, 0x3e, 0x64, 0xa2, 0x6b, 0xc5, 0x23, 0x8c, + 0xfa, 0x71, 0x13, 0x72, 0x0e, 0x7c, 0xe1, 0x2c, + 0x9f, 0x0e, 0x29, 0xc9, 0x15, 0xde, 0x4e, 0xd7, + 0x42, 0x1f, 0x8e, 0xe1, 0x91, 0x99, 0x50, 0x38, + 0x7f, 0x15, 0xc0, 0xf6, 0x4b, 0xfd, 0x9d, 0x40, + 0xe9, 0x44, 0x51, 0xca, 0x3b, 0x83, 0x41, 0x9f, + 0x82, 0x64, 0x66, 0x22, 0x12, 0x43, 0x1c, 0x4f, + 0x45, 0x11, 0x3a, 0x46, 0xb1, 0x7c, 0x62, 0x0a, + 0x9d, 0x4c, 0x99, 0x85, 0xb0, 0x10, 0x19, 0xcf, + 0xeb, 0xf9, 0x65, 0xaf, 0xd8, 0x05, 0x9e, 0x61, + 0x03, 0x5f, 0x15, 0x99, 0xa9, 0x05, 0x20, 0xc8, + 0xaf, 0xab, 0x31, 0x9d, 0xd5, 0xdf, 0x24, 0xce, + 0x2b, 0x6d, 0xd7, 0x17, 0xc3, 0x04, 0xff, 0x82, + 0xa7, 0x18, 0x39, 0xe9, 0x0d, 0x0a, 0x5f, 0xb9, + 0xc9, 0x86, 0x1d, 0xf8, 0x02, 0x2d, 0xc3, 0x88, + 0x28, 0x73, 0x5c, 0xac, 0x25, 0xc9, 0xfe, 0xcb, + 0xd2, 0xfd, 0x63, 0x74, 0xac, 0xe1, 0xb8, 0xa2, + 0xc6, 0x2b, 0xb5, 0x40, 0x01, 0x9b, 0xed, 0xee, + 0x7b, 0x63, 0x66, 0x05, 0x45, 0xc2, 0x6c, 0xd8, + 0x58, 0xf1, 0xa1, 0x3d, 0xc8, 0x43, 0x59, 0x4b, + 0x39, 0x87, 0x24, 0x64, 0x92, 0xb0, 0xab, 0x75, + 0xf1, 0xb7, 0xbf, 0x7c, 0xde, 0xc0, 0xaf, 0x4a, + 0xc2, 0x7b, 0xd9, 0x8a, 0x99, 0xcd, 0x83, 0x01, + 0xe6, 0xae, 0xeb, 0x16, 0xe7, 0x54, 0x9c, 0x95, + 0x0a, 0x91, 0x02, 0xaf, 0x9f, 0x79, 0x40, 0x45, + 0xce, 0x47, 0x41, 0x65, 0xca, 0x80, 0x0d, 0x14, + 0x46, 0x58, 0x5d, 0x4d, 0x28, 0x55, 0x70, 0x49, + 0x7c, 0x32, 0x1f, 0x01, 0xaa, 0x05, 0x2f, 0xf1, + 0xeb, 0xa3, 0xe6, 0x1d, 0xf9, 0x43, 0xe0, 0x58, + 0x05, 0x61, 0x22, 0xc3, 0xee, 0xe4, 0x6f, 0x94, + 0xaf, 0x82, 0xda, 0x18, 0x18, 0x63, 0x9c, 0xfa, + 0xc0, 0x04, 0x27, 0xc5, 0x39, 0x5e, 0x7a, 0xa6, + 0x85, 0x46, 0xb7, 0x76, 0xc9, 0x16, 0xf2, 0xf8, + 0x40, 0x8d, 0x4b, 0x5e, 0x72, 0xf3, 0x3e, 0x12, + 0xa4, 0x80, 0x39, 0xb2, 0x92, 0xfe, 0x6e, 0x5b, + 0x5b, 0xad, 0xea, 0x29, 0xbc, 0x66, 0xe6, 0xfe, + 0x80, 0x02, 0x5d, 0x83, 0x37, 0xfc, 0xde, 0x6c, + 0x25, 0x54, 0xa2, 0xff, 0x7d, 0xb6, 0xe1, 0xd6, + 0xcf, 0xdb, 0x60, 0xe3, 0xbe, 0x2f, 0x4e, 0xb4, + 0xf5, 0xb4, 0x51, 0xf7, 0x5a, 0x25, 0xda, 0x40, + 0x84, 0x5e, 0xc0, 0x0a, 0x6b, 0xfa, 0x0c, 0xfb, + 0x5e, 0x3e, 0x12, 0x6c, 0x39, 0x35, 0xc0, 0x28, + 0xd6, 0x1b, 0x3a, 0x72, 0xc3, 0xfe, 0xa5, 0x4c, + 0x35, 0xa2, 0x42, 0xf6, 0x3d, 0xa5, 0xbf, 0xb5, + 0x39, 0xe3, 0xc9, 0xd5, 0x8c, 0x1b, 0xe5, 0xef, + 0x91, 0xd2, 0x80, 0x6f, 0xcc, 0x77, 0x44, 0x50, + 0x62, 0xc7, 0xac, 0x29, 0xcb, 0x72, 0xda, 0x6d, + 0xc5, 0xfe, 0xa7, 0xee, 0x8b, 0xeb, 0xfc, 0xa3, + 0x46, 0x18, 0x5f, 0xaa, 0xc3, 0x65, 0xd0, 0x8f, + 0x67, 0x98, 0xd6, 0xce, 0x5f, 0x84, 0xd4, 0x96, + 0x1b, 0x67, 0xa0, 0xcf, 0xfc, 0x94, 0x55, 0x5e, + 0x4b, 0x51, 0x68, 0xa7, 0x6d, 0x02, 0xf9, 0x53, + 0x54, 0x86, 0x6b, 0x53, 0x39, 0xe0, 0x36, 0x23, + 0x87, 0x1a, 0xfb, 0x53, 0x1a, 0x65, 0xd8, 0x42, + 0xa8, 0x85, 0xfd, 0x2c, 0x7f, 0x6b, 0x7f, 0x67, + 0x70, 0x23, 0x6c, 0xe9, 0x0b, 0xf0, 0x1e, 0x0d, + 0x0b, 0xb4, 0xd4, 0x96, 0x14, 0x95, 0x7e, 0xf3, + 0x9b, 0xdd, 0xd7, 0xc4, 0x24, 0x22, 0xb9, 0x9d, + 0xb3, 0xa6, 0xac, 0x09, 0x7c, 0x00, 0xbf, 0xd0, + 0xdc, 0xfb, 0x9b, 0x7c, 0x8c, 0xbd, 0xd4, 0x1a, + 0x13, 0x2b, 0x82, 0x3d, 0x7c, 0x8c, 0x10, 0x47, + 0x49, 0x6c, 0x53, 0xeb, 0xa7, 0xc2, 0xde, 0xed, + 0xe2, 0x55, 0x93, 0x2c, 0x1a, 0x5a, 0x7d, 0xe1, + 0x37, 0x62, 0xdd, 0x29, 0x1a, 0x72, 0x82, 0xc0, + 0x14, 0x73, 0x5d, 0x0e, 0x9b, 0xcc, 0x54, 0x68, + 0x3a, 0x4d, 0x56, 0x8f, 0xc9, 0x4e, 0xaf, 0x7b, + 0xde, 0x17, 0x9c, 0x5e, 0x83, 0x82, 0x22, 0xe3, + 0x28, 0xdf, 0x1b, 0xb6, 0xdb, 0x17, 0x90, 0x48, + 0xb5, 0x13, 0x4e, 0xd3, 0x97, 0x5e, 0xb3, 0x9c, + 0x16, 0x08, 0xc8, 0x77, 0xb3, 0xcd, 0x94, 0x90, + 0x4f, 0x77, 0xaf, 0x67, 0xdd, 0x80, 0x15, 0x1c, + 0x59, 0xfb, 0x3c, 0xec, 0xf8, 0xb3, 0x67, 0xfb, + 0xa0, 0x94, 0x3c, 0x53, 0x99, 0x49, 0x94, 0x2c, + 0x85, 0x26, 0x92, 0x6d, 0x8d, 0x48, 0xf6, 0x72, + 0xdd, 0xfb, 0xb2, 0x10, 0x51, 0x5b, 0xbe, 0xd5, + 0x70, 0x3d, 0x28, 0x94, 0x98, 0x4f, 0x6e, 0x20, + 0x7b, 0x7d, 0x0f, 0x56, 0xc9, 0x96, 0x5f, 0x60, + 0x2e, 0x2f, 0x9b, 0x38, 0x7f, 0xc7, 0x3c, 0x6b, + 0x2f, 0x2b, 0x8f, 0x1f, 0x07, 0x1c, 0x85, 0x57, + 0x16, 0x2e, 0xc7, 0x74, 0xe5, 0xf2, 0x0d, 0xfe, + 0xef, 0x57, 0xb0, 0xa4, 0x4f, 0x4c, 0x7d, 0x81, + 0xbb, 0xaa, 0xcb, 0xa0, 0xb0, 0x51, 0xcf, 0xc2, + 0xee, 0x90, 0x2e, 0x5e, 0x27, 0xca, 0xd3, 0xe8, + 0xf3, 0x55, 0x02, 0x56, 0x06, 0xa5, 0xad, 0xdf, + 0xa3, 0xa9, 0x06, 0x05, 0x53, 0x74, 0x55, 0xd5, + 0xd2, 0x20, 0x0a, 0x6d, 0x4a, 0xef, 0x16, 0xbf, + 0xc3, 0xb2, 0x75, 0x93, 0xd8, 0x6e, 0x0f, 0xd2, + 0xae, 0x3b, 0xc0, 0x00, 0x22, 0x6f, 0xb5, 0x0a, + 0x41, 0xfc, 0xf9, 0x41, 0xfc, 0x16, 0x4f, 0xa6, + 0x1c, 0x18, 0x41, 0x67, 0x73, 0xa8, 0x79, 0xa9, + 0x54, 0x18, 0x4e, 0x88, 0x44, 0x0f, 0xa1, 0x5b, + 0xf0, 0x68, 0xea, 0x3c, 0x62, 0x59, 0x8d, 0xc7, + 0x6f, 0xd7, 0x72, 0x20, 0x74, 0x39, 0xd4, 0x3a, + 0x41, 0x1b, 0x58, 0x57, 0x54, 0x85, 0x60, 0xca, + 0x49, 0x4b, 0xa1, 0x04, 0x91, 0xb6, 0xf2, 0xcd, + 0x62, 0x63, 0x67, 0xd1, 0xee, 0x6b, 0x9e, 0x5d, + 0xd6, 0xc4, 0x58, 0x6b, 0xe1, 0xe6, 0x4a, 0xdb, + 0xe8, 0xb1, 0x35, 0x03, 0x15, 0x8d, 0x34, 0x69, + 0x4c, 0xd2, 0x54, 0xce, 0xe8, 0x6a, 0x69, 0x6f, + 0xaa, 0xb5, 0x1f, 0x86, 0xed, 0xac, 0x4f, 0x16, + 0x1e, 0x48, 0x93, 0xe8, 0x6c, 0x24, 0x1c, 0xd0, + 0xbb, 0x61, 0xc2, 0x34, 0xdd, 0xc9, 0x5c, 0xce, +}; + +static const u8 nh_test_msg[NH_MESSAGE_BYTES] = { + 0x99, 0x57, 0x61, 0x41, 0xad, 0x08, 0x7e, 0x17, + 0xd4, 0xef, 0x0b, 0x23, 0xff, 0x0b, 0x96, 0x0a, + 0x6c, 0x98, 0xac, 0x78, 0x5e, 0xb6, 0xb2, 0x67, + 0x0f, 0x48, 0xf4, 0xa1, 0xe5, 0x1e, 0xfe, 0x83, + 0xe4, 0x56, 0x2a, 0x03, 0x64, 0xff, 0x7a, 0xf3, + 0x03, 0xfe, 0xa7, 0x86, 0xdc, 0x35, 0x79, 0x13, + 0xf8, 0xe1, 0x59, 0x19, 0x04, 0x43, 0x24, 0x82, + 0x44, 0x82, 0x41, 0x2b, 0xc7, 0xcf, 0xf5, 0xa4, + 0xdc, 0xca, 0xf5, 0x34, 0xc4, 0x23, 0x3c, 0x1f, + 0xa8, 0x84, 0x1f, 0x2a, 0xcd, 0xae, 0x9d, 0x5e, + 0x05, 0xe2, 0xfb, 0x0c, 0x68, 0x81, 0x90, 0x11, + 0x44, 0xf6, 0xdd, 0x5b, 0x51, 0xd3, 0xe0, 0xab, + 0x29, 0x3a, 0xa9, 0x9c, 0xf6, 0x7e, 0x2d, 0xe3, + 0x6c, 0x09, 0x59, 0xd7, 0xfa, 0x7f, 0x6a, 0x33, + 0x3b, 0x23, 0x7b, 0x1b, 0xb2, 0x79, 0x5f, 0x5c, + 0xb6, 0x2d, 0xb0, 0xf8, 0xab, 0x33, 0x28, 0xe0, + 0x72, 0x2e, 0x2f, 0x03, 0x22, 0x16, 0xb4, 0x87, + 0xf7, 0x14, 0x3f, 0x55, 0x8a, 0xb0, 0x47, 0xdb, + 0x42, 0x2d, 0xc0, 0x0c, 0x0a, 0x33, 0xf8, 0xab, + 0x44, 0xae, 0xa3, 0xc9, 0xfc, 0xf6, 0x34, 0x8c, + 0x60, 0x30, 0x6d, 0x31, 0x70, 0xf3, 0x39, 0x53, + 0xf1, 0x2d, 0xb9, 0x6c, 0xa6, 0x48, 0x9c, 0x9c, + 0xc2, 0x88, 0xb3, 0xa9, 0x98, 0xb6, 0xc3, 0x47, + 0x94, 0x02, 0x9d, 0x98, 0x6e, 0x25, 0x6c, 0xf5, + 0x9b, 0xc6, 0x4d, 0xee, 0x07, 0x1e, 0x25, 0x8f, + 0x01, 0xde, 0xad, 0xe5, 0x77, 0x4f, 0xd1, 0xc0, + 0x62, 0xbb, 0x3a, 0xb9, 0x83, 0x0b, 0x29, 0x76, + 0x4f, 0xb1, 0x86, 0x2c, 0x27, 0xc7, 0x38, 0x65, + 0xcb, 0x78, 0xb7, 0x02, 0x10, 0x9e, 0xde, 0x83, + 0xd1, 0xac, 0x05, 0x86, 0x23, 0xce, 0x4f, 0x8d, + 0xcc, 0x4e, 0x3f, 0x04, 0xf4, 0x39, 0x91, 0x81, + 0x1c, 0x42, 0x47, 0x4d, 0x50, 0xe5, 0x01, 0x22, + 0x98, 0xcf, 0x91, 0x36, 0xb3, 0x7c, 0xcf, 0x78, + 0x07, 0x22, 0xa9, 0x18, 0xd2, 0xcd, 0x7d, 0x4d, + 0xa6, 0xcb, 0xaa, 0x52, 0x13, 0x49, 0x64, 0xb0, + 0xa5, 0x3d, 0xc7, 0xc3, 0x10, 0x87, 0x2e, 0x76, + 0xa9, 0x52, 0xc5, 0x50, 0x18, 0xc0, 0x5d, 0xb4, + 0x4c, 0xc6, 0x7f, 0x64, 0xae, 0x53, 0xc3, 0x46, + 0x99, 0xb7, 0x61, 0x6b, 0x08, 0x43, 0x08, 0x4c, + 0x90, 0x2c, 0xee, 0x56, 0x91, 0xb4, 0x28, 0xa8, + 0xa8, 0x8b, 0x3b, 0x1a, 0x67, 0x71, 0xf2, 0x81, + 0x48, 0x20, 0x71, 0x30, 0xdd, 0x69, 0x8a, 0xc2, + 0x4c, 0x9d, 0x4e, 0x17, 0xfb, 0x2e, 0xe7, 0x9b, + 0x86, 0x94, 0xa5, 0xce, 0xf9, 0x74, 0x56, 0xff, + 0x3b, 0xff, 0xd9, 0x5a, 0xc8, 0x98, 0xf5, 0x25, + 0xa2, 0xb9, 0x66, 0x46, 0x89, 0x17, 0x39, 0x08, + 0x69, 0x03, 0x59, 0x1e, 0x13, 0x12, 0x68, 0xe7, + 0x2f, 0x00, 0xd3, 0xf3, 0x71, 0xd1, 0x20, 0xc5, + 0x0b, 0x38, 0x89, 0xda, 0x62, 0x3c, 0xce, 0xea, + 0x04, 0x19, 0x47, 0x6d, 0xd8, 0x64, 0x38, 0x60, + 0x96, 0x71, 0x68, 0x48, 0x79, 0xf8, 0xf4, 0x76, + 0x33, 0xf6, 0x60, 0x8d, 0x21, 0xd0, 0xee, 0x41, + 0xc0, 0xbe, 0x33, 0x61, 0x5e, 0x66, 0xe6, 0x16, + 0x14, 0xc7, 0xfb, 0x6c, 0xf3, 0x58, 0xef, 0x12, + 0x7c, 0x70, 0x65, 0x5d, 0x55, 0xe8, 0xf2, 0x92, + 0x3a, 0xfe, 0x34, 0x64, 0x31, 0x7c, 0x29, 0xbb, + 0x01, 0x18, 0xbd, 0xb6, 0xe4, 0x1e, 0xa4, 0xf3, + 0x7b, 0x4c, 0x6a, 0x0d, 0x01, 0xfc, 0xc7, 0x66, + 0xc3, 0x88, 0x37, 0x25, 0xcf, 0xe9, 0xca, 0x82, + 0xeb, 0xa1, 0x38, 0x40, 0xc9, 0xdb, 0x38, 0x7b, + 0x78, 0xcf, 0x11, 0xa3, 0x1c, 0x6b, 0x70, 0xc8, + 0xe1, 0x2f, 0x7c, 0x17, 0x2c, 0x58, 0x28, 0xa4, + 0x13, 0x40, 0xc7, 0x69, 0x0f, 0x04, 0xe5, 0x8e, + 0xf0, 0x67, 0x53, 0xea, 0x10, 0xf5, 0x83, 0xc9, + 0xcb, 0x6b, 0x16, 0xef, 0x2e, 0x55, 0xb3, 0xdd, + 0xed, 0xf9, 0x1a, 0x52, 0x9a, 0x73, 0x78, 0x14, + 0x14, 0x21, 0xfc, 0xef, 0x3c, 0x40, 0xa9, 0xfe, + 0xef, 0xd7, 0x6e, 0x28, 0x2f, 0xd3, 0x73, 0xed, + 0xa3, 0x73, 0xb5, 0x62, 0x41, 0xe6, 0xd4, 0x79, + 0x49, 0x31, 0x2b, 0x86, 0x74, 0x56, 0x21, 0xfe, + 0x6d, 0xb2, 0xbe, 0x81, 0x80, 0xa6, 0x81, 0x19, + 0x90, 0x79, 0x6f, 0xc4, 0x4e, 0x7d, 0x6f, 0x2f, + 0xa8, 0x6f, 0xd5, 0xc4, 0x7e, 0x23, 0x3b, 0xe6, + 0x9b, 0x60, 0x97, 0x7b, 0xe2, 0x08, 0x8a, 0xaa, + 0xc7, 0x7c, 0xf6, 0xe5, 0x01, 0x3e, 0xd2, 0x29, + 0x7d, 0xd7, 0x40, 0x84, 0x95, 0xfa, 0xdf, 0xd8, + 0x81, 0xe9, 0x5e, 0xdd, 0x0d, 0x17, 0x51, 0x6b, + 0x8c, 0x0e, 0x47, 0xf9, 0x0c, 0x92, 0x1b, 0x60, + 0xca, 0x06, 0x8a, 0xe5, 0xe8, 0x0f, 0x06, 0x75, + 0x5d, 0x76, 0xc9, 0x32, 0x2c, 0x52, 0x2c, 0x2e, + 0xd8, 0x66, 0x38, 0x75, 0x16, 0xc7, 0x7d, 0x51, + 0xc4, 0xc2, 0x22, 0xc8, 0x19, 0xfc, 0x3d, 0x69, + 0x1e, 0xd9, 0x64, 0x47, 0x5d, 0x21, 0x84, 0x46, + 0xd7, 0xe1, 0xf0, 0x95, 0x3a, 0x8f, 0xbd, 0x7a, + 0x53, 0x71, 0x4c, 0x54, 0xc1, 0x3e, 0x27, 0xde, + 0xeb, 0x04, 0x11, 0xb0, 0x33, 0x4d, 0x57, 0x0b, + 0x6b, 0x7d, 0x6c, 0xd5, 0x87, 0x7e, 0xb4, 0xe2, + 0x94, 0x9e, 0x9f, 0x74, 0xe8, 0xb7, 0xfa, 0x05, + 0x9b, 0x8f, 0x81, 0x43, 0x35, 0x82, 0xb8, 0x5b, + 0xa8, 0x5e, 0xfa, 0x7a, 0x80, 0x8d, 0xd2, 0x90, + 0x58, 0x79, 0x89, 0x56, 0x90, 0x2b, 0xff, 0x92, + 0x3c, 0x35, 0xbe, 0x99, 0x5f, 0xd2, 0x4b, 0x15, + 0x58, 0x4b, 0xbf, 0x08, 0x9b, 0x9b, 0x97, 0x10, + 0xa4, 0x55, 0xc7, 0xec, 0x29, 0xc5, 0x14, 0x3e, + 0x8f, 0x56, 0xa3, 0x92, 0x9e, 0x33, 0xcc, 0x9e, + 0x77, 0x2f, 0x33, 0xcb, 0xc4, 0xe9, 0x19, 0xf4, + 0x32, 0x2b, 0xef, 0x6c, 0x1c, 0x92, 0x2c, 0x45, + 0x88, 0x74, 0x5f, 0xcf, 0x56, 0xfd, 0x87, 0x5f, + 0xb6, 0x9b, 0xa2, 0x51, 0xda, 0x9b, 0x83, 0x4f, + 0xec, 0x14, 0xe8, 0xd2, 0x42, 0x03, 0xcb, 0xe8, + 0xd0, 0xb7, 0xf8, 0x38, 0xde, 0x6f, 0xdf, 0x43, + 0xfa, 0x41, 0xab, 0xec, 0x2e, 0x3c, 0x93, 0x39, + 0x76, 0xd1, 0x6f, 0x5b, 0x6c, 0x6e, 0x8d, 0xeb, + 0x45, 0x6b, 0xc5, 0x76, 0x00, 0x29, 0xca, 0x3b, + 0xdb, 0x78, 0xc2, 0x32, 0x09, 0x39, 0x19, 0x50, + 0xa2, 0x44, 0x92, 0x09, 0xdb, 0x8b, 0x9e, 0x16, + 0x76, 0x7f, 0xf1, 0x78, 0x7b, 0xb2, 0x51, 0xbc, + 0x28, 0xbd, 0xb0, 0x7f, 0x25, 0x63, 0x7d, 0x34, + 0xfb, 0xf6, 0x36, 0x24, 0xc7, 0xf9, 0x41, 0xb6, + 0x2a, 0x06, 0xfc, 0xf0, 0x83, 0xf2, 0x12, 0x3d, + 0x60, 0x2e, 0x10, 0x70, 0x31, 0x6f, 0x37, 0x08, + 0x3e, 0x91, 0x93, 0xb5, 0xda, 0xb8, 0x4c, 0x1b, + 0xd8, 0xb8, 0x3b, 0xd5, 0x3e, 0xb6, 0xc0, 0xbb, + 0x38, 0x0f, 0xd2, 0x68, 0x4f, 0x78, 0x56, 0xf6, + 0xda, 0x65, 0xb4, 0x0b, 0xb4, 0xaf, 0xa8, 0x19, + 0x2f, 0x70, 0x55, 0xe0, 0x47, 0x31, 0x9f, 0x37, + 0x1a, 0x47, 0xb9, 0x0c, 0x97, 0x79, 0xfc, 0xa9, + 0x76, 0xe6, 0xfa, 0x38, 0x67, 0x25, 0xd3, 0x89, + 0x8d, 0xad, 0xc6, 0x11, 0x2d, 0x77, 0x0b, 0x35, + 0xa2, 0xe2, 0xdf, 0xc8, 0x94, 0xd5, 0xdf, 0xd2, + 0x69, 0x2a, 0x99, 0x93, 0xfa, 0x4a, 0x5f, 0xc7, + 0x8a, 0x14, 0x5f, 0x2a, 0xf3, 0x02, 0xf0, 0x3e, + 0x21, 0x8e, 0x2e, 0x4b, 0xc4, 0xd2, 0xc8, 0xa6, + 0x41, 0x6e, 0x17, 0x36, 0xe9, 0xad, 0x73, 0x33, + 0x6c, 0xea, 0xc2, 0x31, 0x8f, 0x30, 0x51, 0x5c, + 0x1c, 0x20, 0xe6, 0x05, 0x1a, 0x17, 0x15, 0x5d, + 0x3e, 0x8f, 0xd2, 0x7f, 0xa1, 0xc5, 0x47, 0xb3, + 0xb2, 0x9c, 0xe8, 0xf0, 0x6d, 0xc1, 0xc3, 0xa2, +}; + +static const u8 nh_test_val16[NH_HASH_BYTES] = { + 0x30, 0x77, 0x55, 0x7c, 0x45, 0xd8, 0xce, 0xf7, + 0x2a, 0xb5, 0x14, 0x8c, 0x35, 0x7e, 0xaa, 0x00, + 0x50, 0xbc, 0x50, 0x7c, 0xd3, 0x20, 0x7c, 0x9c, + 0xb4, 0xf1, 0x91, 0x26, 0x81, 0x03, 0xa5, 0x68, +}; + +static const u8 nh_test_val96[NH_HASH_BYTES] = { + 0xd2, 0x19, 0xca, 0xa5, 0x6c, 0x0c, 0xdf, 0x2f, + 0x69, 0xfa, 0x75, 0xc1, 0x63, 0xdb, 0xfa, 0x4d, + 0x45, 0x2b, 0xb8, 0xdb, 0xac, 0xee, 0x61, 0xc6, + 0x7a, 0x83, 0xb6, 0x0f, 0x32, 0x82, 0xe4, 0xd0, +}; + +static const u8 nh_test_val256[NH_HASH_BYTES] = { + 0x33, 0x8f, 0xb4, 0x96, 0xf1, 0xb6, 0xf1, 0xb5, + 0x05, 0x19, 0xbb, 0x6b, 0xda, 0xd9, 0x95, 0x75, + 0x96, 0x3f, 0x8b, 0x42, 0xb6, 0xcd, 0xb7, 0xb7, + 0xe7, 0x97, 0xb5, 0xa9, 0x0b, 0xd7, 0xdd, 0x33, +}; + +static const u8 nh_test_val1024[NH_HASH_BYTES] = { + 0x32, 0x3d, 0x51, 0xe1, 0x77, 0xb6, 0xac, 0x06, + 0x84, 0x67, 0xb7, 0xf2, 0x24, 0xe7, 0xec, 0xfd, + 0x96, 0x64, 0xff, 0x55, 0xc7, 0x1b, 0xf9, 0xdc, + 0xa3, 0xc7, 0x32, 0x06, 0x79, 0xcf, 0xca, 0xb6, +}; diff --git a/lib/crypto/tests/nh_kunit.c b/lib/crypto/tests/nh_kunit.c new file mode 100644 index 000000000000..a8a3c3f345cb --- /dev/null +++ b/lib/crypto/tests/nh_kunit.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2025 Google LLC + */ +#include +#include +#include "nh-testvecs.h" + +static void test_nh(struct kunit *test) +{ + u32 *key = kunit_kmalloc(test, NH_KEY_BYTES, GFP_KERNEL); + __le64 hash[NH_NUM_PASSES]; + + KUNIT_ASSERT_NOT_NULL(test, key); + memcpy(key, nh_test_key, NH_KEY_BYTES); + le32_to_cpu_array(key, NH_KEY_WORDS); + + nh(key, nh_test_msg, 16, hash); + KUNIT_ASSERT_MEMEQ(test, hash, nh_test_val16, NH_HASH_BYTES); + + nh(key, nh_test_msg, 96, hash); + KUNIT_ASSERT_MEMEQ(test, hash, nh_test_val96, NH_HASH_BYTES); + + nh(key, nh_test_msg, 256, hash); + KUNIT_ASSERT_MEMEQ(test, hash, nh_test_val256, NH_HASH_BYTES); + + nh(key, nh_test_msg, 1024, hash); + KUNIT_ASSERT_MEMEQ(test, hash, nh_test_val1024, NH_HASH_BYTES); +} + +static struct kunit_case nh_test_cases[] = { + KUNIT_CASE(test_nh), + {}, +}; + +static struct kunit_suite nh_test_suite = { + .name = "nh", + .test_cases = nh_test_cases, +}; +kunit_test_suite(nh_test_suite); + +MODULE_DESCRIPTION("KUnit tests for NH"); +MODULE_LICENSE("GPL"); diff --git a/scripts/crypto/gen-hash-testvecs.py b/scripts/crypto/gen-hash-testvecs.py index c773294fba64..8eeb650fcada 100755 --- a/scripts/crypto/gen-hash-testvecs.py +++ b/scripts/crypto/gen-hash-testvecs.py @@ -184,6 +184,44 @@ def gen_additional_blake2_testvecs(alg): f'{alg}_keyed_testvec_consolidated[{alg_digest_size_const(alg)}]', compute_hash(alg, hashes)) +def nh_extract_int(bytestr, pos, length): + assert pos % 8 == 0 and length % 8 == 0 + return int.from_bytes(bytestr[pos//8 : pos//8 + length//8], byteorder='little') + +# The NH "almost-universal hash function" used in Adiantum. This is a +# straightforward translation of the pseudocode from Section 6.3 of the Adiantum +# paper (https://eprint.iacr.org/2018/720.pdf), except the outer loop is omitted +# because we assume len(msg) <= 1024. (The kernel's nh() function is only +# expected to handle up to 1024 bytes; it's just called repeatedly as needed.) +def nh(key, msg): + (w, s, r, u) = (32, 2, 4, 8192) + l = 8 * len(msg) + assert l <= u + assert l % (2*s*w) == 0 + h = bytes() + for i in range(0, 2*s*w*r, 2*s*w): + p = 0 + for j in range(0, l, 2*s*w): + for k in range(0, w*s, w): + a0 = nh_extract_int(key, i + j + k, w) + a1 = nh_extract_int(key, i + j + k + s*w, w) + b0 = nh_extract_int(msg, j + k, w) + b1 = nh_extract_int(msg, j + k + s*w, w) + p += ((a0 + b0) % 2**w) * ((a1 + b1) % 2**w) + h += (p % 2**64).to_bytes(8, byteorder='little') + return h + +def gen_nh_testvecs(): + NH_KEY_BYTES = 1072 + NH_MESSAGE_BYTES = 1024 + key = rand_bytes(NH_KEY_BYTES) + msg = rand_bytes(NH_MESSAGE_BYTES) + print_static_u8_array_definition('nh_test_key[NH_KEY_BYTES]', key) + print_static_u8_array_definition('nh_test_msg[NH_MESSAGE_BYTES]', msg) + for length in [16, 96, 256, 1024]: + print_static_u8_array_definition(f'nh_test_val{length}[NH_HASH_BYTES]', + nh(key, msg[:length])) + def gen_additional_poly1305_testvecs(): key = b'\xff' * POLY1305_KEY_SIZE data = b'' @@ -217,6 +255,8 @@ print(f'/* This file was generated by: {sys.argv[0]} {" ".join(sys.argv[1:])} */ if alg.startswith('blake2'): gen_unkeyed_testvecs(alg) gen_additional_blake2_testvecs(alg) +elif alg == 'nh': + gen_nh_testvecs() elif alg == 'poly1305': gen_unkeyed_testvecs(alg) gen_additional_poly1305_testvecs() From 29e39a11f541d068ed7155368f4a79aa0ddf9c52 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 10 Dec 2025 17:18:35 -0800 Subject: [PATCH 05/53] lib/crypto: arm/nh: Migrate optimized code into library Migrate the arm32 NEON implementation of NH into lib/crypto/. This makes the nh() function be optimized on arm32 kernels. Note: this temporarily makes the adiantum template not utilize the arm32 optimized NH code. This is resolved in a later commit that converts the adiantum template to use nh() instead of "nhpoly1305". Link: https://lore.kernel.org/r/20251211011846.8179-4-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/arm/crypto/Kconfig | 10 --- arch/arm/crypto/Makefile | 2 - arch/arm/crypto/nhpoly1305-neon-glue.c | 80 ------------------- lib/crypto/Kconfig | 1 + lib/crypto/Makefile | 1 + .../crypto => lib/crypto/arm}/nh-neon-core.S | 0 lib/crypto/arm/nh.h | 33 ++++++++ 7 files changed, 35 insertions(+), 92 deletions(-) delete mode 100644 arch/arm/crypto/nhpoly1305-neon-glue.c rename {arch/arm/crypto => lib/crypto/arm}/nh-neon-core.S (100%) create mode 100644 lib/crypto/arm/nh.h diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig index f30d743df264..3eb5071bea14 100644 --- a/arch/arm/crypto/Kconfig +++ b/arch/arm/crypto/Kconfig @@ -23,16 +23,6 @@ config CRYPTO_GHASH_ARM_CE that is part of the ARMv8 Crypto Extensions, or a slower variant that uses the vmull.p8 instruction that is part of the basic NEON ISA. -config CRYPTO_NHPOLY1305_NEON - tristate "Hash functions: NHPoly1305 (NEON)" - depends on KERNEL_MODE_NEON - select CRYPTO_NHPOLY1305 - help - NHPoly1305 hash function (Adiantum) - - Architecture: arm using: - - NEON (Advanced SIMD) extensions - config CRYPTO_AES_ARM tristate "Ciphers: AES" select CRYPTO_ALGAPI diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile index 86dd43313dbf..d6683e9d4992 100644 --- a/arch/arm/crypto/Makefile +++ b/arch/arm/crypto/Makefile @@ -5,7 +5,6 @@ obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o -obj-$(CONFIG_CRYPTO_NHPOLY1305_NEON) += nhpoly1305-neon.o obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o @@ -14,4 +13,3 @@ aes-arm-y := aes-cipher-core.o aes-cipher-glue.o aes-arm-bs-y := aes-neonbs-core.o aes-neonbs-glue.o aes-arm-ce-y := aes-ce-core.o aes-ce-glue.o ghash-arm-ce-y := ghash-ce-core.o ghash-ce-glue.o -nhpoly1305-neon-y := nh-neon-core.o nhpoly1305-neon-glue.o diff --git a/arch/arm/crypto/nhpoly1305-neon-glue.c b/arch/arm/crypto/nhpoly1305-neon-glue.c deleted file mode 100644 index 62cf7ccdde73..000000000000 --- a/arch/arm/crypto/nhpoly1305-neon-glue.c +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * NHPoly1305 - ε-almost-∆-universal hash function for Adiantum - * (NEON accelerated version) - * - * Copyright 2018 Google LLC - */ - -#include -#include -#include -#include -#include -#include - -asmlinkage void nh_neon(const u32 *key, const u8 *message, size_t message_len, - __le64 hash[NH_NUM_PASSES]); - -static int nhpoly1305_neon_update(struct shash_desc *desc, - const u8 *src, unsigned int srclen) -{ - if (srclen < 64 || !crypto_simd_usable()) - return crypto_nhpoly1305_update(desc, src, srclen); - - do { - unsigned int n = min_t(unsigned int, srclen, SZ_4K); - - kernel_neon_begin(); - crypto_nhpoly1305_update_helper(desc, src, n, nh_neon); - kernel_neon_end(); - src += n; - srclen -= n; - } while (srclen); - return 0; -} - -static int nhpoly1305_neon_digest(struct shash_desc *desc, - const u8 *src, unsigned int srclen, u8 *out) -{ - return crypto_nhpoly1305_init(desc) ?: - nhpoly1305_neon_update(desc, src, srclen) ?: - crypto_nhpoly1305_final(desc, out); -} - -static struct shash_alg nhpoly1305_alg = { - .base.cra_name = "nhpoly1305", - .base.cra_driver_name = "nhpoly1305-neon", - .base.cra_priority = 200, - .base.cra_ctxsize = sizeof(struct nhpoly1305_key), - .base.cra_module = THIS_MODULE, - .digestsize = POLY1305_DIGEST_SIZE, - .init = crypto_nhpoly1305_init, - .update = nhpoly1305_neon_update, - .final = crypto_nhpoly1305_final, - .digest = nhpoly1305_neon_digest, - .setkey = crypto_nhpoly1305_setkey, - .descsize = sizeof(struct nhpoly1305_state), -}; - -static int __init nhpoly1305_mod_init(void) -{ - if (!(elf_hwcap & HWCAP_NEON)) - return -ENODEV; - - return crypto_register_shash(&nhpoly1305_alg); -} - -static void __exit nhpoly1305_mod_exit(void) -{ - crypto_unregister_shash(&nhpoly1305_alg); -} - -module_init(nhpoly1305_mod_init); -module_exit(nhpoly1305_mod_exit); - -MODULE_DESCRIPTION("NHPoly1305 ε-almost-∆-universal hash function (NEON-accelerated)"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Eric Biggers "); -MODULE_ALIAS_CRYPTO("nhpoly1305"); -MODULE_ALIAS_CRYPTO("nhpoly1305-neon"); diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index f14c9f5974d8..c6ee7ca77632 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -117,6 +117,7 @@ config CRYPTO_LIB_NH config CRYPTO_LIB_NH_ARCH bool depends on CRYPTO_LIB_NH && !UML + default y if ARM && KERNEL_MODE_NEON config CRYPTO_LIB_POLY1305 tristate diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 929b84568809..6dae7e182847 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -135,6 +135,7 @@ obj-$(CONFIG_CRYPTO_LIB_NH) += libnh.o libnh-y := nh.o ifeq ($(CONFIG_CRYPTO_LIB_NH_ARCH),y) CFLAGS_nh.o += -I$(src)/$(SRCARCH) +libnh-$(CONFIG_ARM) += arm/nh-neon-core.o endif ################################################################################ diff --git a/arch/arm/crypto/nh-neon-core.S b/lib/crypto/arm/nh-neon-core.S similarity index 100% rename from arch/arm/crypto/nh-neon-core.S rename to lib/crypto/arm/nh-neon-core.S diff --git a/lib/crypto/arm/nh.h b/lib/crypto/arm/nh.h new file mode 100644 index 000000000000..c9f39d819336 --- /dev/null +++ b/lib/crypto/arm/nh.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ARM32 accelerated implementation of NH + * + * Copyright 2018 Google LLC + */ + +#include +#include + +static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon); + +asmlinkage void nh_neon(const u32 *key, const u8 *message, size_t message_len, + __le64 hash[NH_NUM_PASSES]); + +static bool nh_arch(const u32 *key, const u8 *message, size_t message_len, + __le64 hash[NH_NUM_PASSES]) +{ + if (static_branch_likely(&have_neon) && message_len >= 64 && + may_use_simd()) { + scoped_ksimd() + nh_neon(key, message, message_len, hash); + return true; + } + return false; +} + +#define nh_mod_init_arch nh_mod_init_arch +static void nh_mod_init_arch(void) +{ + if (elf_hwcap & HWCAP_NEON) + static_branch_enable(&have_neon); +} From b4a8528d17fbcd9027290c168efd6ba7ac4d4cd2 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 10 Dec 2025 17:18:36 -0800 Subject: [PATCH 06/53] lib/crypto: arm64/nh: Migrate optimized code into library Migrate the arm64 NEON implementation of NH into lib/crypto/. This makes the nh() function be optimized on arm64 kernels. Note: this temporarily makes the adiantum template not utilize the arm64 optimized NH code. This is resolved in a later commit that converts the adiantum template to use nh() instead of "nhpoly1305". Link: https://lore.kernel.org/r/20251211011846.8179-5-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/arm64/crypto/Kconfig | 10 --- arch/arm64/crypto/Makefile | 3 - arch/arm64/crypto/nhpoly1305-neon-glue.c | 79 ------------------- lib/crypto/Kconfig | 1 + lib/crypto/Makefile | 1 + .../crypto/arm64}/nh-neon-core.S | 3 +- lib/crypto/arm64/nh.h | 34 ++++++++ 7 files changed, 37 insertions(+), 94 deletions(-) delete mode 100644 arch/arm64/crypto/nhpoly1305-neon-glue.c rename {arch/arm64/crypto => lib/crypto/arm64}/nh-neon-core.S (97%) create mode 100644 lib/crypto/arm64/nh.h diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig index bdd276a6e540..da1c9ea8ea83 100644 --- a/arch/arm64/crypto/Kconfig +++ b/arch/arm64/crypto/Kconfig @@ -15,16 +15,6 @@ config CRYPTO_GHASH_ARM64_CE Architecture: arm64 using: - ARMv8 Crypto Extensions -config CRYPTO_NHPOLY1305_NEON - tristate "Hash functions: NHPoly1305 (NEON)" - depends on KERNEL_MODE_NEON - select CRYPTO_NHPOLY1305 - help - NHPoly1305 hash function (Adiantum) - - Architecture: arm64 using: - - NEON (Advanced SIMD) extensions - config CRYPTO_SM3_NEON tristate "Hash functions: SM3 (NEON)" depends on KERNEL_MODE_NEON diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile index 1e330aa08d3f..3ab4b58e5c4c 100644 --- a/arch/arm64/crypto/Makefile +++ b/arch/arm64/crypto/Makefile @@ -41,9 +41,6 @@ aes-ce-blk-y := aes-glue-ce.o aes-ce.o obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) += aes-neon-blk.o aes-neon-blk-y := aes-glue-neon.o aes-neon.o -obj-$(CONFIG_CRYPTO_NHPOLY1305_NEON) += nhpoly1305-neon.o -nhpoly1305-neon-y := nh-neon-core.o nhpoly1305-neon-glue.o - obj-$(CONFIG_CRYPTO_AES_ARM64) += aes-arm64.o aes-arm64-y := aes-cipher-core.o aes-cipher-glue.o diff --git a/arch/arm64/crypto/nhpoly1305-neon-glue.c b/arch/arm64/crypto/nhpoly1305-neon-glue.c deleted file mode 100644 index 013de6ac569a..000000000000 --- a/arch/arm64/crypto/nhpoly1305-neon-glue.c +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * NHPoly1305 - ε-almost-∆-universal hash function for Adiantum - * (ARM64 NEON accelerated version) - * - * Copyright 2018 Google LLC - */ - -#include -#include -#include -#include -#include -#include - -asmlinkage void nh_neon(const u32 *key, const u8 *message, size_t message_len, - __le64 hash[NH_NUM_PASSES]); - -static int nhpoly1305_neon_update(struct shash_desc *desc, - const u8 *src, unsigned int srclen) -{ - if (srclen < 64 || !crypto_simd_usable()) - return crypto_nhpoly1305_update(desc, src, srclen); - - do { - unsigned int n = min_t(unsigned int, srclen, SZ_4K); - - scoped_ksimd() - crypto_nhpoly1305_update_helper(desc, src, n, nh_neon); - src += n; - srclen -= n; - } while (srclen); - return 0; -} - -static int nhpoly1305_neon_digest(struct shash_desc *desc, - const u8 *src, unsigned int srclen, u8 *out) -{ - return crypto_nhpoly1305_init(desc) ?: - nhpoly1305_neon_update(desc, src, srclen) ?: - crypto_nhpoly1305_final(desc, out); -} - -static struct shash_alg nhpoly1305_alg = { - .base.cra_name = "nhpoly1305", - .base.cra_driver_name = "nhpoly1305-neon", - .base.cra_priority = 200, - .base.cra_ctxsize = sizeof(struct nhpoly1305_key), - .base.cra_module = THIS_MODULE, - .digestsize = POLY1305_DIGEST_SIZE, - .init = crypto_nhpoly1305_init, - .update = nhpoly1305_neon_update, - .final = crypto_nhpoly1305_final, - .digest = nhpoly1305_neon_digest, - .setkey = crypto_nhpoly1305_setkey, - .descsize = sizeof(struct nhpoly1305_state), -}; - -static int __init nhpoly1305_mod_init(void) -{ - if (!cpu_have_named_feature(ASIMD)) - return -ENODEV; - - return crypto_register_shash(&nhpoly1305_alg); -} - -static void __exit nhpoly1305_mod_exit(void) -{ - crypto_unregister_shash(&nhpoly1305_alg); -} - -module_init(nhpoly1305_mod_init); -module_exit(nhpoly1305_mod_exit); - -MODULE_DESCRIPTION("NHPoly1305 ε-almost-∆-universal hash function (NEON-accelerated)"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Eric Biggers "); -MODULE_ALIAS_CRYPTO("nhpoly1305"); -MODULE_ALIAS_CRYPTO("nhpoly1305-neon"); diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index c6ee7ca77632..aa3f850ece24 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -118,6 +118,7 @@ config CRYPTO_LIB_NH_ARCH bool depends on CRYPTO_LIB_NH && !UML default y if ARM && KERNEL_MODE_NEON + default y if ARM64 && KERNEL_MODE_NEON config CRYPTO_LIB_POLY1305 tristate diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 6dae7e182847..e3a13952bc2a 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -136,6 +136,7 @@ libnh-y := nh.o ifeq ($(CONFIG_CRYPTO_LIB_NH_ARCH),y) CFLAGS_nh.o += -I$(src)/$(SRCARCH) libnh-$(CONFIG_ARM) += arm/nh-neon-core.o +libnh-$(CONFIG_ARM64) += arm64/nh-neon-core.o endif ################################################################################ diff --git a/arch/arm64/crypto/nh-neon-core.S b/lib/crypto/arm64/nh-neon-core.S similarity index 97% rename from arch/arm64/crypto/nh-neon-core.S rename to lib/crypto/arm64/nh-neon-core.S index 13eda08fda1e..6fa57fce8085 100644 --- a/arch/arm64/crypto/nh-neon-core.S +++ b/lib/crypto/arm64/nh-neon-core.S @@ -8,7 +8,6 @@ */ #include -#include KEY .req x0 MESSAGE .req x1 @@ -63,7 +62,7 @@ * * It's guaranteed that message_len % 16 == 0. */ -SYM_TYPED_FUNC_START(nh_neon) +SYM_FUNC_START(nh_neon) ld1 {K0.4s,K1.4s}, [KEY], #32 movi PASS0_SUMS.2d, #0 diff --git a/lib/crypto/arm64/nh.h b/lib/crypto/arm64/nh.h new file mode 100644 index 000000000000..08902630bdd1 --- /dev/null +++ b/lib/crypto/arm64/nh.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ARM64 accelerated implementation of NH + * + * Copyright 2018 Google LLC + */ + +#include +#include +#include + +static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon); + +asmlinkage void nh_neon(const u32 *key, const u8 *message, size_t message_len, + __le64 hash[NH_NUM_PASSES]); + +static bool nh_arch(const u32 *key, const u8 *message, size_t message_len, + __le64 hash[NH_NUM_PASSES]) +{ + if (static_branch_likely(&have_neon) && message_len >= 64 && + may_use_simd()) { + scoped_ksimd() + nh_neon(key, message, message_len, hash); + return true; + } + return false; +} + +#define nh_mod_init_arch nh_mod_init_arch +static void nh_mod_init_arch(void) +{ + if (cpu_have_named_feature(ASIMD)) + static_branch_enable(&have_neon); +} From a229d83235c7627c490deb7dd4744a72567cea12 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 10 Dec 2025 17:18:37 -0800 Subject: [PATCH 07/53] lib/crypto: x86/nh: Migrate optimized code into library Migrate the x86_64 implementations of NH into lib/crypto/. This makes the nh() function be optimized on x86_64 kernels. Note: this temporarily makes the adiantum template not utilize the x86_64 optimized NH code. This is resolved in a later commit that converts the adiantum template to use nh() instead of "nhpoly1305". Link: https://lore.kernel.org/r/20251211011846.8179-6-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/x86/crypto/Kconfig | 20 ----- arch/x86/crypto/Makefile | 5 -- arch/x86/crypto/nhpoly1305-avx2-glue.c | 81 ------------------- arch/x86/crypto/nhpoly1305-sse2-glue.c | 80 ------------------ lib/crypto/Kconfig | 1 + lib/crypto/Makefile | 1 + .../crypto/x86/nh-avx2.S | 3 +- .../crypto/x86/nh-sse2.S | 3 +- lib/crypto/x86/nh.h | 45 +++++++++++ 9 files changed, 49 insertions(+), 190 deletions(-) delete mode 100644 arch/x86/crypto/nhpoly1305-avx2-glue.c delete mode 100644 arch/x86/crypto/nhpoly1305-sse2-glue.c rename arch/x86/crypto/nh-avx2-x86_64.S => lib/crypto/x86/nh-avx2.S (98%) rename arch/x86/crypto/nh-sse2-x86_64.S => lib/crypto/x86/nh-sse2.S (97%) create mode 100644 lib/crypto/x86/nh.h diff --git a/arch/x86/crypto/Kconfig b/arch/x86/crypto/Kconfig index 3fd2423d3cf8..ebb0838eaf30 100644 --- a/arch/x86/crypto/Kconfig +++ b/arch/x86/crypto/Kconfig @@ -333,26 +333,6 @@ config CRYPTO_AEGIS128_AESNI_SSE2 - AES-NI (AES New Instructions) - SSE4.1 (Streaming SIMD Extensions 4.1) -config CRYPTO_NHPOLY1305_SSE2 - tristate "Hash functions: NHPoly1305 (SSE2)" - depends on 64BIT - select CRYPTO_NHPOLY1305 - help - NHPoly1305 hash function for Adiantum - - Architecture: x86_64 using: - - SSE2 (Streaming SIMD Extensions 2) - -config CRYPTO_NHPOLY1305_AVX2 - tristate "Hash functions: NHPoly1305 (AVX2)" - depends on 64BIT - select CRYPTO_NHPOLY1305 - help - NHPoly1305 hash function for Adiantum - - Architecture: x86_64 using: - - AVX2 (Advanced Vector Extensions 2) - config CRYPTO_SM3_AVX_X86_64 tristate "Hash functions: SM3 (AVX)" depends on 64BIT diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index 5f2fb4f148fe..b21ad0978c52 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -53,11 +53,6 @@ aesni-intel-$(CONFIG_64BIT) += aes-ctr-avx-x86_64.o \ obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o -obj-$(CONFIG_CRYPTO_NHPOLY1305_SSE2) += nhpoly1305-sse2.o -nhpoly1305-sse2-y := nh-sse2-x86_64.o nhpoly1305-sse2-glue.o -obj-$(CONFIG_CRYPTO_NHPOLY1305_AVX2) += nhpoly1305-avx2.o -nhpoly1305-avx2-y := nh-avx2-x86_64.o nhpoly1305-avx2-glue.o - obj-$(CONFIG_CRYPTO_SM3_AVX_X86_64) += sm3-avx-x86_64.o sm3-avx-x86_64-y := sm3-avx-asm_64.o sm3_avx_glue.o diff --git a/arch/x86/crypto/nhpoly1305-avx2-glue.c b/arch/x86/crypto/nhpoly1305-avx2-glue.c deleted file mode 100644 index c3a872f4d6a7..000000000000 --- a/arch/x86/crypto/nhpoly1305-avx2-glue.c +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * NHPoly1305 - ε-almost-∆-universal hash function for Adiantum - * (AVX2 accelerated version) - * - * Copyright 2018 Google LLC - */ - -#include -#include -#include -#include -#include -#include - -asmlinkage void nh_avx2(const u32 *key, const u8 *message, size_t message_len, - __le64 hash[NH_NUM_PASSES]); - -static int nhpoly1305_avx2_update(struct shash_desc *desc, - const u8 *src, unsigned int srclen) -{ - if (srclen < 64 || !crypto_simd_usable()) - return crypto_nhpoly1305_update(desc, src, srclen); - - do { - unsigned int n = min_t(unsigned int, srclen, SZ_4K); - - kernel_fpu_begin(); - crypto_nhpoly1305_update_helper(desc, src, n, nh_avx2); - kernel_fpu_end(); - src += n; - srclen -= n; - } while (srclen); - return 0; -} - -static int nhpoly1305_avx2_digest(struct shash_desc *desc, - const u8 *src, unsigned int srclen, u8 *out) -{ - return crypto_nhpoly1305_init(desc) ?: - nhpoly1305_avx2_update(desc, src, srclen) ?: - crypto_nhpoly1305_final(desc, out); -} - -static struct shash_alg nhpoly1305_alg = { - .base.cra_name = "nhpoly1305", - .base.cra_driver_name = "nhpoly1305-avx2", - .base.cra_priority = 300, - .base.cra_ctxsize = sizeof(struct nhpoly1305_key), - .base.cra_module = THIS_MODULE, - .digestsize = POLY1305_DIGEST_SIZE, - .init = crypto_nhpoly1305_init, - .update = nhpoly1305_avx2_update, - .final = crypto_nhpoly1305_final, - .digest = nhpoly1305_avx2_digest, - .setkey = crypto_nhpoly1305_setkey, - .descsize = sizeof(struct nhpoly1305_state), -}; - -static int __init nhpoly1305_mod_init(void) -{ - if (!boot_cpu_has(X86_FEATURE_AVX2) || - !boot_cpu_has(X86_FEATURE_OSXSAVE)) - return -ENODEV; - - return crypto_register_shash(&nhpoly1305_alg); -} - -static void __exit nhpoly1305_mod_exit(void) -{ - crypto_unregister_shash(&nhpoly1305_alg); -} - -module_init(nhpoly1305_mod_init); -module_exit(nhpoly1305_mod_exit); - -MODULE_DESCRIPTION("NHPoly1305 ε-almost-∆-universal hash function (AVX2-accelerated)"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Eric Biggers "); -MODULE_ALIAS_CRYPTO("nhpoly1305"); -MODULE_ALIAS_CRYPTO("nhpoly1305-avx2"); diff --git a/arch/x86/crypto/nhpoly1305-sse2-glue.c b/arch/x86/crypto/nhpoly1305-sse2-glue.c deleted file mode 100644 index a268a8439a5c..000000000000 --- a/arch/x86/crypto/nhpoly1305-sse2-glue.c +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * NHPoly1305 - ε-almost-∆-universal hash function for Adiantum - * (SSE2 accelerated version) - * - * Copyright 2018 Google LLC - */ - -#include -#include -#include -#include -#include -#include - -asmlinkage void nh_sse2(const u32 *key, const u8 *message, size_t message_len, - __le64 hash[NH_NUM_PASSES]); - -static int nhpoly1305_sse2_update(struct shash_desc *desc, - const u8 *src, unsigned int srclen) -{ - if (srclen < 64 || !crypto_simd_usable()) - return crypto_nhpoly1305_update(desc, src, srclen); - - do { - unsigned int n = min_t(unsigned int, srclen, SZ_4K); - - kernel_fpu_begin(); - crypto_nhpoly1305_update_helper(desc, src, n, nh_sse2); - kernel_fpu_end(); - src += n; - srclen -= n; - } while (srclen); - return 0; -} - -static int nhpoly1305_sse2_digest(struct shash_desc *desc, - const u8 *src, unsigned int srclen, u8 *out) -{ - return crypto_nhpoly1305_init(desc) ?: - nhpoly1305_sse2_update(desc, src, srclen) ?: - crypto_nhpoly1305_final(desc, out); -} - -static struct shash_alg nhpoly1305_alg = { - .base.cra_name = "nhpoly1305", - .base.cra_driver_name = "nhpoly1305-sse2", - .base.cra_priority = 200, - .base.cra_ctxsize = sizeof(struct nhpoly1305_key), - .base.cra_module = THIS_MODULE, - .digestsize = POLY1305_DIGEST_SIZE, - .init = crypto_nhpoly1305_init, - .update = nhpoly1305_sse2_update, - .final = crypto_nhpoly1305_final, - .digest = nhpoly1305_sse2_digest, - .setkey = crypto_nhpoly1305_setkey, - .descsize = sizeof(struct nhpoly1305_state), -}; - -static int __init nhpoly1305_mod_init(void) -{ - if (!boot_cpu_has(X86_FEATURE_XMM2)) - return -ENODEV; - - return crypto_register_shash(&nhpoly1305_alg); -} - -static void __exit nhpoly1305_mod_exit(void) -{ - crypto_unregister_shash(&nhpoly1305_alg); -} - -module_init(nhpoly1305_mod_init); -module_exit(nhpoly1305_mod_exit); - -MODULE_DESCRIPTION("NHPoly1305 ε-almost-∆-universal hash function (SSE2-accelerated)"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Eric Biggers "); -MODULE_ALIAS_CRYPTO("nhpoly1305"); -MODULE_ALIAS_CRYPTO("nhpoly1305-sse2"); diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index aa3f850ece24..33cf46bbadc8 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -119,6 +119,7 @@ config CRYPTO_LIB_NH_ARCH depends on CRYPTO_LIB_NH && !UML default y if ARM && KERNEL_MODE_NEON default y if ARM64 && KERNEL_MODE_NEON + default y if X86_64 config CRYPTO_LIB_POLY1305 tristate diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index e3a13952bc2a..45128eccedef 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -137,6 +137,7 @@ ifeq ($(CONFIG_CRYPTO_LIB_NH_ARCH),y) CFLAGS_nh.o += -I$(src)/$(SRCARCH) libnh-$(CONFIG_ARM) += arm/nh-neon-core.o libnh-$(CONFIG_ARM64) += arm64/nh-neon-core.o +libnh-$(CONFIG_X86) += x86/nh-sse2.o x86/nh-avx2.o endif ################################################################################ diff --git a/arch/x86/crypto/nh-avx2-x86_64.S b/lib/crypto/x86/nh-avx2.S similarity index 98% rename from arch/x86/crypto/nh-avx2-x86_64.S rename to lib/crypto/x86/nh-avx2.S index 791386d9a83a..9c085a31b137 100644 --- a/arch/x86/crypto/nh-avx2-x86_64.S +++ b/lib/crypto/x86/nh-avx2.S @@ -8,7 +8,6 @@ */ #include -#include #define PASS0_SUMS %ymm0 #define PASS1_SUMS %ymm1 @@ -70,7 +69,7 @@ * * It's guaranteed that message_len % 16 == 0. */ -SYM_TYPED_FUNC_START(nh_avx2) +SYM_FUNC_START(nh_avx2) vmovdqu 0x00(KEY), K0 vmovdqu 0x10(KEY), K1 diff --git a/arch/x86/crypto/nh-sse2-x86_64.S b/lib/crypto/x86/nh-sse2.S similarity index 97% rename from arch/x86/crypto/nh-sse2-x86_64.S rename to lib/crypto/x86/nh-sse2.S index 75fb994b6d17..d36c0e6d5556 100644 --- a/arch/x86/crypto/nh-sse2-x86_64.S +++ b/lib/crypto/x86/nh-sse2.S @@ -8,7 +8,6 @@ */ #include -#include #define PASS0_SUMS %xmm0 #define PASS1_SUMS %xmm1 @@ -72,7 +71,7 @@ * * It's guaranteed that message_len % 16 == 0. */ -SYM_TYPED_FUNC_START(nh_sse2) +SYM_FUNC_START(nh_sse2) movdqu 0x00(KEY), K0 movdqu 0x10(KEY), K1 diff --git a/lib/crypto/x86/nh.h b/lib/crypto/x86/nh.h new file mode 100644 index 000000000000..83361c2e9783 --- /dev/null +++ b/lib/crypto/x86/nh.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * x86_64 accelerated implementation of NH + * + * Copyright 2018 Google LLC + */ + +#include +#include + +static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_sse2); +static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_avx2); + +asmlinkage void nh_sse2(const u32 *key, const u8 *message, size_t message_len, + __le64 hash[NH_NUM_PASSES]); +asmlinkage void nh_avx2(const u32 *key, const u8 *message, size_t message_len, + __le64 hash[NH_NUM_PASSES]); + +static bool nh_arch(const u32 *key, const u8 *message, size_t message_len, + __le64 hash[NH_NUM_PASSES]) +{ + if (message_len >= 64 && static_branch_likely(&have_sse2) && + irq_fpu_usable()) { + kernel_fpu_begin(); + if (static_branch_likely(&have_avx2)) + nh_avx2(key, message, message_len, hash); + else + nh_sse2(key, message, message_len, hash); + kernel_fpu_end(); + return true; + } + return false; +} + +#define nh_mod_init_arch nh_mod_init_arch +static void nh_mod_init_arch(void) +{ + if (boot_cpu_has(X86_FEATURE_XMM2)) { + static_branch_enable(&have_sse2); + if (boot_cpu_has(X86_FEATURE_AVX2) && + cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, + NULL)) + static_branch_enable(&have_avx2); + } +} From 76987479c1a66f60126afe28e3cff01f3fc0f1ae Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 10 Dec 2025 17:18:38 -0800 Subject: [PATCH 08/53] crypto: adiantum - Convert to use NH library Reimplement the Adiantum message hashing using the nh() library function, combined with some code which directly handles the Poly1305 stage. The latter code is derived from crypto/nhpoly1305.c. This eliminates the dependency on the "nhpoly1305" crypto_shash algorithm, which existed only to fit Adiantum message hashing into the traditional Linux crypto API paradigm. Now that simple, architecture-optimized library functions are a well-established option too, we can switch to this simpler implementation. Note: I've dropped the support for the optional third parameter of the adiantum template, which specified the nhpoly1305 implementation. We could keep accepting some strings in this parameter for backwards compatibility, but I don't think it's being used. I believe only "adiantum(xchacha12,aes)" and "adiantum(xchacha20,aes)" are used. Link: https://lore.kernel.org/r/20251211011846.8179-7-ebiggers@kernel.org Signed-off-by: Eric Biggers --- crypto/Kconfig | 2 +- crypto/adiantum.c | 295 +++++++++++++++++++++++++++++----------------- crypto/testmgr.c | 4 +- 3 files changed, 191 insertions(+), 110 deletions(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index 2e5b195b1b06..89d1ccaa1fa0 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -601,9 +601,9 @@ menu "Length-preserving ciphers and modes" config CRYPTO_ADIANTUM tristate "Adiantum" select CRYPTO_CHACHA20 + select CRYPTO_LIB_NH select CRYPTO_LIB_POLY1305 select CRYPTO_LIB_POLY1305_GENERIC - select CRYPTO_NHPOLY1305 select CRYPTO_MANAGER help Adiantum tweakable, length-preserving encryption mode diff --git a/crypto/adiantum.c b/crypto/adiantum.c index a6bca877c3c7..bbe519fbd739 100644 --- a/crypto/adiantum.c +++ b/crypto/adiantum.c @@ -20,23 +20,14 @@ * * - Stream cipher: XChaCha12 or XChaCha20 * - Block cipher: any with a 128-bit block size and 256-bit key - * - * This implementation doesn't currently allow other ε-∆U hash functions, i.e. - * HPolyC is not supported. This is because Adiantum is ~20% faster than HPolyC - * but still provably as secure, and also the ε-∆U hash function of HBSH is - * formally defined to take two inputs (tweak, message) which makes it difficult - * to wrap with the crypto_shash API. Rather, some details need to be handled - * here. Nevertheless, if needed in the future, support for other ε-∆U hash - * functions could be added here. */ #include #include #include -#include #include #include -#include +#include #include #include @@ -50,7 +41,7 @@ #define BLOCKCIPHER_KEY_SIZE 32 /* Size of the hash key (K_H) in bytes */ -#define HASH_KEY_SIZE (POLY1305_BLOCK_SIZE + NHPOLY1305_KEY_SIZE) +#define HASH_KEY_SIZE (2 * POLY1305_BLOCK_SIZE + NH_KEY_BYTES) /* * The specification allows variable-length tweaks, but Linux's crypto API @@ -64,14 +55,31 @@ struct adiantum_instance_ctx { struct crypto_skcipher_spawn streamcipher_spawn; struct crypto_cipher_spawn blockcipher_spawn; - struct crypto_shash_spawn hash_spawn; }; struct adiantum_tfm_ctx { struct crypto_skcipher *streamcipher; struct crypto_cipher *blockcipher; - struct crypto_shash *hash; struct poly1305_core_key header_hash_key; + struct poly1305_core_key msg_poly_key; + u32 nh_key[NH_KEY_WORDS]; +}; + +struct nhpoly1305_ctx { + /* Running total of polynomial evaluation */ + struct poly1305_state poly_state; + + /* Partial block buffer */ + u8 buffer[NH_MESSAGE_UNIT]; + unsigned int buflen; + + /* + * Number of bytes remaining until the current NH message reaches + * NH_MESSAGE_BYTES. When nonzero, 'nh_hash' holds the partial NH hash. + */ + unsigned int nh_remaining; + + __le64 nh_hash[NH_NUM_PASSES]; }; struct adiantum_request_ctx { @@ -98,9 +106,12 @@ struct adiantum_request_ctx { */ le128 header_hash; - /* Sub-requests, must be last */ + /* + * skcipher sub-request size is unknown at compile-time, so it needs to + * go after the members with known sizes. + */ union { - struct shash_desc hash_desc; + struct nhpoly1305_ctx hash_ctx; struct skcipher_request streamcipher_req; } u; }; @@ -170,12 +181,11 @@ static int adiantum_setkey(struct crypto_skcipher *tfm, const u8 *key, /* Set the hash key (K_H) */ poly1305_core_setkey(&tctx->header_hash_key, keyp); keyp += POLY1305_BLOCK_SIZE; - - crypto_shash_clear_flags(tctx->hash, CRYPTO_TFM_REQ_MASK); - crypto_shash_set_flags(tctx->hash, crypto_skcipher_get_flags(tfm) & - CRYPTO_TFM_REQ_MASK); - err = crypto_shash_setkey(tctx->hash, keyp, NHPOLY1305_KEY_SIZE); - keyp += NHPOLY1305_KEY_SIZE; + poly1305_core_setkey(&tctx->msg_poly_key, keyp); + keyp += POLY1305_BLOCK_SIZE; + for (int i = 0; i < NH_KEY_WORDS; i++) + tctx->nh_key[i] = get_unaligned_le32(&keyp[i * 4]); + keyp += NH_KEY_BYTES; WARN_ON(keyp != &data->derived_keys[ARRAY_SIZE(data->derived_keys)]); out: kfree_sensitive(data); @@ -243,35 +253,143 @@ static void adiantum_hash_header(struct skcipher_request *req) poly1305_core_emit(&state, NULL, &rctx->header_hash); } -/* Hash the left-hand part (the "bulk") of the message using NHPoly1305 */ -static int adiantum_hash_message(struct skcipher_request *req, - struct scatterlist *sgl, unsigned int nents, - le128 *digest) +/* Pass the next NH hash value through Poly1305 */ +static void process_nh_hash_value(struct nhpoly1305_ctx *ctx, + const struct adiantum_tfm_ctx *key) { + static_assert(NH_HASH_BYTES % POLY1305_BLOCK_SIZE == 0); + + poly1305_core_blocks(&ctx->poly_state, &key->msg_poly_key, ctx->nh_hash, + NH_HASH_BYTES / POLY1305_BLOCK_SIZE, 1); +} + +/* + * Feed the next portion of the message data, as a whole number of 16-byte + * "NH message units", through NH and Poly1305. Each NH hash is taken over + * 1024 bytes, except possibly the final one which is taken over a multiple of + * 16 bytes up to 1024. Also, in the case where data is passed in misaligned + * chunks, we combine partial hashes; the end result is the same either way. + */ +static void nhpoly1305_units(struct nhpoly1305_ctx *ctx, + const struct adiantum_tfm_ctx *key, + const u8 *data, size_t len) +{ + do { + unsigned int bytes; + + if (ctx->nh_remaining == 0) { + /* Starting a new NH message */ + bytes = min(len, NH_MESSAGE_BYTES); + nh(key->nh_key, data, bytes, ctx->nh_hash); + ctx->nh_remaining = NH_MESSAGE_BYTES - bytes; + } else { + /* Continuing a previous NH message */ + __le64 tmp_hash[NH_NUM_PASSES]; + unsigned int pos; + + pos = NH_MESSAGE_BYTES - ctx->nh_remaining; + bytes = min(len, ctx->nh_remaining); + nh(&key->nh_key[pos / 4], data, bytes, tmp_hash); + for (int i = 0; i < NH_NUM_PASSES; i++) + le64_add_cpu(&ctx->nh_hash[i], + le64_to_cpu(tmp_hash[i])); + ctx->nh_remaining -= bytes; + } + if (ctx->nh_remaining == 0) + process_nh_hash_value(ctx, key); + data += bytes; + len -= bytes; + } while (len); +} + +static void nhpoly1305_init(struct nhpoly1305_ctx *ctx) +{ + poly1305_core_init(&ctx->poly_state); + ctx->buflen = 0; + ctx->nh_remaining = 0; +} + +static void nhpoly1305_update(struct nhpoly1305_ctx *ctx, + const struct adiantum_tfm_ctx *key, + const u8 *data, size_t len) +{ + unsigned int bytes; + + if (ctx->buflen) { + bytes = min(len, (int)NH_MESSAGE_UNIT - ctx->buflen); + memcpy(&ctx->buffer[ctx->buflen], data, bytes); + ctx->buflen += bytes; + if (ctx->buflen < NH_MESSAGE_UNIT) + return; + nhpoly1305_units(ctx, key, ctx->buffer, NH_MESSAGE_UNIT); + ctx->buflen = 0; + data += bytes; + len -= bytes; + } + + if (len >= NH_MESSAGE_UNIT) { + bytes = round_down(len, NH_MESSAGE_UNIT); + nhpoly1305_units(ctx, key, data, bytes); + data += bytes; + len -= bytes; + } + + if (len) { + memcpy(ctx->buffer, data, len); + ctx->buflen = len; + } +} + +static void nhpoly1305_final(struct nhpoly1305_ctx *ctx, + const struct adiantum_tfm_ctx *key, le128 *out) +{ + if (ctx->buflen) { + memset(&ctx->buffer[ctx->buflen], 0, + NH_MESSAGE_UNIT - ctx->buflen); + nhpoly1305_units(ctx, key, ctx->buffer, NH_MESSAGE_UNIT); + } + + if (ctx->nh_remaining) + process_nh_hash_value(ctx, key); + + poly1305_core_emit(&ctx->poly_state, NULL, out); +} + +/* + * Hash the left-hand part (the "bulk") of the message as follows: + * + * H_L ← Poly1305_{K_L}(NH_{K_N}(pad_{128}(L))) + * + * See section 6.4 of the Adiantum paper. This is an ε-almost-∆-universal + * (ε-∆U) hash function for equal-length inputs over Z/(2^{128}Z), where the "∆" + * operation is addition. It hashes 1024-byte chunks of the input with the NH + * hash function, reducing the input length by 32x. The resulting NH hashes are + * evaluated as a polynomial in GF(2^{130}-5), like in the Poly1305 MAC. Note + * that the polynomial evaluation by itself would suffice to achieve the ε-∆U + * property; NH is used for performance since it's much faster than Poly1305. + */ +static void adiantum_hash_message(struct skcipher_request *req, + struct scatterlist *sgl, unsigned int nents, + le128 *out) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); struct adiantum_request_ctx *rctx = skcipher_request_ctx(req); const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE; - struct shash_desc *hash_desc = &rctx->u.hash_desc; struct sg_mapping_iter miter; unsigned int i, n; - int err; - err = crypto_shash_init(hash_desc); - if (err) - return err; + nhpoly1305_init(&rctx->u.hash_ctx); sg_miter_start(&miter, sgl, nents, SG_MITER_FROM_SG | SG_MITER_ATOMIC); for (i = 0; i < bulk_len; i += n) { sg_miter_next(&miter); n = min_t(unsigned int, miter.length, bulk_len - i); - err = crypto_shash_update(hash_desc, miter.addr, n); - if (err) - break; + nhpoly1305_update(&rctx->u.hash_ctx, tctx, miter.addr, n); } sg_miter_stop(&miter); - if (err) - return err; - return crypto_shash_final(hash_desc, (u8 *)digest); + nhpoly1305_final(&rctx->u.hash_ctx, tctx, out); } /* Continue Adiantum encryption/decryption after the stream cipher step */ @@ -284,7 +402,6 @@ static int adiantum_finish(struct skcipher_request *req) struct scatterlist *dst = req->dst; const unsigned int dst_nents = sg_nents(dst); le128 digest; - int err; /* If decrypting, decrypt C_M with the block cipher to get P_M */ if (!rctx->enc) @@ -296,28 +413,22 @@ static int adiantum_finish(struct skcipher_request *req) * enc: C_R = C_M - H_{K_H}(T, C_L) * dec: P_R = P_M - H_{K_H}(T, P_L) */ - rctx->u.hash_desc.tfm = tctx->hash; le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &rctx->header_hash); if (dst_nents == 1 && dst->offset + req->cryptlen <= PAGE_SIZE) { /* Fast path for single-page destination */ struct page *page = sg_page(dst); void *virt = kmap_local_page(page) + dst->offset; - err = crypto_shash_digest(&rctx->u.hash_desc, virt, bulk_len, - (u8 *)&digest); - if (err) { - kunmap_local(virt); - return err; - } + nhpoly1305_init(&rctx->u.hash_ctx); + nhpoly1305_update(&rctx->u.hash_ctx, tctx, virt, bulk_len); + nhpoly1305_final(&rctx->u.hash_ctx, tctx, &digest); le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); memcpy(virt + bulk_len, &rctx->rbuf.bignum, sizeof(le128)); flush_dcache_page(page); kunmap_local(virt); } else { /* Slow path that works for any destination scatterlist */ - err = adiantum_hash_message(req, dst, dst_nents, &digest); - if (err) - return err; + adiantum_hash_message(req, dst, dst_nents, &digest); le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); scatterwalk_map_and_copy(&rctx->rbuf.bignum, dst, bulk_len, sizeof(le128), 1); @@ -345,7 +456,6 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc) const unsigned int src_nents = sg_nents(src); unsigned int stream_len; le128 digest; - int err; if (req->cryptlen < BLOCKCIPHER_BLOCK_SIZE) return -EINVAL; @@ -358,23 +468,21 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc) * dec: C_M = C_R + H_{K_H}(T, C_L) */ adiantum_hash_header(req); - rctx->u.hash_desc.tfm = tctx->hash; if (src_nents == 1 && src->offset + req->cryptlen <= PAGE_SIZE) { /* Fast path for single-page source */ void *virt = kmap_local_page(sg_page(src)) + src->offset; - err = crypto_shash_digest(&rctx->u.hash_desc, virt, bulk_len, - (u8 *)&digest); + nhpoly1305_init(&rctx->u.hash_ctx); + nhpoly1305_update(&rctx->u.hash_ctx, tctx, virt, bulk_len); + nhpoly1305_final(&rctx->u.hash_ctx, tctx, &digest); memcpy(&rctx->rbuf.bignum, virt + bulk_len, sizeof(le128)); kunmap_local(virt); } else { /* Slow path that works for any source scatterlist */ - err = adiantum_hash_message(req, src, src_nents, &digest); + adiantum_hash_message(req, src, src_nents, &digest); scatterwalk_map_and_copy(&rctx->rbuf.bignum, src, bulk_len, sizeof(le128), 0); } - if (err) - return err; le128_add(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &rctx->header_hash); le128_add(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); @@ -431,8 +539,6 @@ static int adiantum_init_tfm(struct crypto_skcipher *tfm) struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); struct crypto_skcipher *streamcipher; struct crypto_cipher *blockcipher; - struct crypto_shash *hash; - unsigned int subreq_size; int err; streamcipher = crypto_spawn_skcipher(&ictx->streamcipher_spawn); @@ -445,32 +551,18 @@ static int adiantum_init_tfm(struct crypto_skcipher *tfm) goto err_free_streamcipher; } - hash = crypto_spawn_shash(&ictx->hash_spawn); - if (IS_ERR(hash)) { - err = PTR_ERR(hash); - goto err_free_blockcipher; - } - tctx->streamcipher = streamcipher; tctx->blockcipher = blockcipher; - tctx->hash = hash; BUILD_BUG_ON(offsetofend(struct adiantum_request_ctx, u) != sizeof(struct adiantum_request_ctx)); - subreq_size = max(sizeof_field(struct adiantum_request_ctx, - u.hash_desc) + - crypto_shash_descsize(hash), - sizeof_field(struct adiantum_request_ctx, - u.streamcipher_req) + - crypto_skcipher_reqsize(streamcipher)); - - crypto_skcipher_set_reqsize(tfm, - offsetof(struct adiantum_request_ctx, u) + - subreq_size); + crypto_skcipher_set_reqsize( + tfm, max(sizeof(struct adiantum_request_ctx), + offsetofend(struct adiantum_request_ctx, + u.streamcipher_req) + + crypto_skcipher_reqsize(streamcipher))); return 0; -err_free_blockcipher: - crypto_free_cipher(blockcipher); err_free_streamcipher: crypto_free_skcipher(streamcipher); return err; @@ -482,7 +574,6 @@ static void adiantum_exit_tfm(struct crypto_skcipher *tfm) crypto_free_skcipher(tctx->streamcipher); crypto_free_cipher(tctx->blockcipher); - crypto_free_shash(tctx->hash); } static void adiantum_free_instance(struct skcipher_instance *inst) @@ -491,7 +582,6 @@ static void adiantum_free_instance(struct skcipher_instance *inst) crypto_drop_skcipher(&ictx->streamcipher_spawn); crypto_drop_cipher(&ictx->blockcipher_spawn); - crypto_drop_shash(&ictx->hash_spawn); kfree(inst); } @@ -499,9 +589,9 @@ static void adiantum_free_instance(struct skcipher_instance *inst) * Check for a supported set of inner algorithms. * See the comment at the beginning of this file. */ -static bool adiantum_supported_algorithms(struct skcipher_alg_common *streamcipher_alg, - struct crypto_alg *blockcipher_alg, - struct shash_alg *hash_alg) +static bool +adiantum_supported_algorithms(struct skcipher_alg_common *streamcipher_alg, + struct crypto_alg *blockcipher_alg) { if (strcmp(streamcipher_alg->base.cra_name, "xchacha12") != 0 && strcmp(streamcipher_alg->base.cra_name, "xchacha20") != 0) @@ -513,21 +603,16 @@ static bool adiantum_supported_algorithms(struct skcipher_alg_common *streamciph if (blockcipher_alg->cra_blocksize != BLOCKCIPHER_BLOCK_SIZE) return false; - if (strcmp(hash_alg->base.cra_name, "nhpoly1305") != 0) - return false; - return true; } static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) { u32 mask; - const char *nhpoly1305_name; struct skcipher_instance *inst; struct adiantum_instance_ctx *ictx; struct skcipher_alg_common *streamcipher_alg; struct crypto_alg *blockcipher_alg; - struct shash_alg *hash_alg; int err; err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER, &mask); @@ -555,23 +640,21 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) goto err_free_inst; blockcipher_alg = crypto_spawn_cipher_alg(&ictx->blockcipher_spawn); - /* NHPoly1305 ε-∆U hash function */ - nhpoly1305_name = crypto_attr_alg_name(tb[3]); - if (nhpoly1305_name == ERR_PTR(-ENOENT)) - nhpoly1305_name = "nhpoly1305"; - err = crypto_grab_shash(&ictx->hash_spawn, - skcipher_crypto_instance(inst), - nhpoly1305_name, 0, mask); - if (err) + /* + * Originally there was an optional third parameter, for requesting a + * specific implementation of "nhpoly1305" for message hashing. This is + * no longer supported. The best implementation is just always used. + */ + if (crypto_attr_alg_name(tb[3]) != ERR_PTR(-ENOENT)) { + err = -ENOENT; goto err_free_inst; - hash_alg = crypto_spawn_shash_alg(&ictx->hash_spawn); + } /* Check the set of algorithms */ - if (!adiantum_supported_algorithms(streamcipher_alg, blockcipher_alg, - hash_alg)) { - pr_warn("Unsupported Adiantum instantiation: (%s,%s,%s)\n", + if (!adiantum_supported_algorithms(streamcipher_alg, blockcipher_alg)) { + pr_warn("Unsupported Adiantum instantiation: (%s,%s)\n", streamcipher_alg->base.cra_name, - blockcipher_alg->cra_name, hash_alg->base.cra_name); + blockcipher_alg->cra_name); err = -EINVAL; goto err_free_inst; } @@ -584,10 +667,8 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) blockcipher_alg->cra_name) >= CRYPTO_MAX_ALG_NAME) goto err_free_inst; if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, - "adiantum(%s,%s,%s)", - streamcipher_alg->base.cra_driver_name, - blockcipher_alg->cra_driver_name, - hash_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) + "adiantum(%s,%s)", streamcipher_alg->base.cra_driver_name, + blockcipher_alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) goto err_free_inst; inst->alg.base.cra_blocksize = BLOCKCIPHER_BLOCK_SIZE; @@ -596,12 +677,12 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) /* * The block cipher is only invoked once per message, so for long * messages (e.g. sectors for disk encryption) its performance doesn't - * matter as much as that of the stream cipher and hash function. Thus, - * weigh the block cipher's ->cra_priority less. + * matter as much as that of the stream cipher. Thus, weigh the block + * cipher's ->cra_priority less. */ inst->alg.base.cra_priority = (4 * streamcipher_alg->base.cra_priority + - 2 * hash_alg->base.cra_priority + - blockcipher_alg->cra_priority) / 7; + blockcipher_alg->cra_priority) / + 5; inst->alg.setkey = adiantum_setkey; inst->alg.encrypt = adiantum_encrypt; @@ -622,7 +703,7 @@ err_free_inst: return err; } -/* adiantum(streamcipher_name, blockcipher_name [, nhpoly1305_name]) */ +/* adiantum(streamcipher_name, blockcipher_name) */ static struct crypto_template adiantum_tmpl = { .name = "adiantum", .create = adiantum_create, diff --git a/crypto/testmgr.c b/crypto/testmgr.c index a302be53896d..d9fc671d5941 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -4061,14 +4061,14 @@ static int alg_test_null(const struct alg_test_desc *desc, static const struct alg_test_desc alg_test_descs[] = { { .alg = "adiantum(xchacha12,aes)", - .generic_driver = "adiantum(xchacha12-lib,aes-generic,nhpoly1305-generic)", + .generic_driver = "adiantum(xchacha12-lib,aes-generic)", .test = alg_test_skcipher, .suite = { .cipher = __VECS(adiantum_xchacha12_aes_tv_template) }, }, { .alg = "adiantum(xchacha20,aes)", - .generic_driver = "adiantum(xchacha20-lib,aes-generic,nhpoly1305-generic)", + .generic_driver = "adiantum(xchacha20-lib,aes-generic)", .test = alg_test_skcipher, .suite = { .cipher = __VECS(adiantum_xchacha20_aes_tv_template) From cd912b3452d14c40e77b3be82854df00bfd38a41 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 10 Dec 2025 17:18:39 -0800 Subject: [PATCH 09/53] crypto: adiantum - Use scatter_walk API instead of sg_miter Make adiantum_hash_message() use the scatter_walk API instead of sg_miter. scatter_walk is a bit simpler and also more efficient. For example, unlike sg_miter, scatter_walk doesn't require that the number of scatterlist entries be calculated up-front. Link: https://lore.kernel.org/r/20251211011846.8179-8-ebiggers@kernel.org Signed-off-by: Eric Biggers --- crypto/adiantum.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/crypto/adiantum.c b/crypto/adiantum.c index bbe519fbd739..519e95228ad8 100644 --- a/crypto/adiantum.c +++ b/crypto/adiantum.c @@ -369,26 +369,23 @@ static void nhpoly1305_final(struct nhpoly1305_ctx *ctx, * property; NH is used for performance since it's much faster than Poly1305. */ static void adiantum_hash_message(struct skcipher_request *req, - struct scatterlist *sgl, unsigned int nents, - le128 *out) + struct scatterlist *sgl, le128 *out) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); struct adiantum_request_ctx *rctx = skcipher_request_ctx(req); - const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE; - struct sg_mapping_iter miter; - unsigned int i, n; + unsigned int len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE; + struct scatter_walk walk; nhpoly1305_init(&rctx->u.hash_ctx); + scatterwalk_start(&walk, sgl); + while (len) { + unsigned int n = scatterwalk_next(&walk, len); - sg_miter_start(&miter, sgl, nents, SG_MITER_FROM_SG | SG_MITER_ATOMIC); - for (i = 0; i < bulk_len; i += n) { - sg_miter_next(&miter); - n = min_t(unsigned int, miter.length, bulk_len - i); - nhpoly1305_update(&rctx->u.hash_ctx, tctx, miter.addr, n); + nhpoly1305_update(&rctx->u.hash_ctx, tctx, walk.addr, n); + scatterwalk_done_src(&walk, n); + len -= n; } - sg_miter_stop(&miter); - nhpoly1305_final(&rctx->u.hash_ctx, tctx, out); } @@ -400,7 +397,6 @@ static int adiantum_finish(struct skcipher_request *req) struct adiantum_request_ctx *rctx = skcipher_request_ctx(req); const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE; struct scatterlist *dst = req->dst; - const unsigned int dst_nents = sg_nents(dst); le128 digest; /* If decrypting, decrypt C_M with the block cipher to get P_M */ @@ -414,7 +410,8 @@ static int adiantum_finish(struct skcipher_request *req) * dec: P_R = P_M - H_{K_H}(T, P_L) */ le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &rctx->header_hash); - if (dst_nents == 1 && dst->offset + req->cryptlen <= PAGE_SIZE) { + if (dst->length >= req->cryptlen && + dst->offset + req->cryptlen <= PAGE_SIZE) { /* Fast path for single-page destination */ struct page *page = sg_page(dst); void *virt = kmap_local_page(page) + dst->offset; @@ -428,7 +425,7 @@ static int adiantum_finish(struct skcipher_request *req) kunmap_local(virt); } else { /* Slow path that works for any destination scatterlist */ - adiantum_hash_message(req, dst, dst_nents, &digest); + adiantum_hash_message(req, dst, &digest); le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); scatterwalk_map_and_copy(&rctx->rbuf.bignum, dst, bulk_len, sizeof(le128), 1); @@ -453,7 +450,6 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc) struct adiantum_request_ctx *rctx = skcipher_request_ctx(req); const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE; struct scatterlist *src = req->src; - const unsigned int src_nents = sg_nents(src); unsigned int stream_len; le128 digest; @@ -468,7 +464,8 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc) * dec: C_M = C_R + H_{K_H}(T, C_L) */ adiantum_hash_header(req); - if (src_nents == 1 && src->offset + req->cryptlen <= PAGE_SIZE) { + if (src->length >= req->cryptlen && + src->offset + req->cryptlen <= PAGE_SIZE) { /* Fast path for single-page source */ void *virt = kmap_local_page(sg_page(src)) + src->offset; @@ -479,7 +476,7 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc) kunmap_local(virt); } else { /* Slow path that works for any source scatterlist */ - adiantum_hash_message(req, src, src_nents, &digest); + adiantum_hash_message(req, src, &digest); scatterwalk_map_and_copy(&rctx->rbuf.bignum, src, bulk_len, sizeof(le128), 0); } From 73c203fe5564e6e4ec37b7e140214a334d584369 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 10 Dec 2025 17:18:40 -0800 Subject: [PATCH 10/53] crypto: adiantum - Use memcpy_{to,from}_sglist() Call the newer, easier-to-read functions memcpy_to_sglist() and memcpy_from_sglist() directly instead of calling scatterwalk_map_and_copy(). No change in behavior. Acked-by: Herbert Xu Link: https://lore.kernel.org/r/20251211011846.8179-9-ebiggers@kernel.org Signed-off-by: Eric Biggers --- crypto/adiantum.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crypto/adiantum.c b/crypto/adiantum.c index 519e95228ad8..6d882f926ab0 100644 --- a/crypto/adiantum.c +++ b/crypto/adiantum.c @@ -427,8 +427,8 @@ static int adiantum_finish(struct skcipher_request *req) /* Slow path that works for any destination scatterlist */ adiantum_hash_message(req, dst, &digest); le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); - scatterwalk_map_and_copy(&rctx->rbuf.bignum, dst, - bulk_len, sizeof(le128), 1); + memcpy_to_sglist(dst, bulk_len, &rctx->rbuf.bignum, + sizeof(le128)); } return 0; } @@ -477,8 +477,8 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc) } else { /* Slow path that works for any source scatterlist */ adiantum_hash_message(req, src, &digest); - scatterwalk_map_and_copy(&rctx->rbuf.bignum, src, - bulk_len, sizeof(le128), 0); + memcpy_from_sglist(&rctx->rbuf.bignum, src, bulk_len, + sizeof(le128)); } le128_add(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &rctx->header_hash); le128_add(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); From 2f64821329d82ad2646efe59a40aaf40099bc9c3 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 10 Dec 2025 17:18:41 -0800 Subject: [PATCH 11/53] crypto: adiantum - Drop support for asynchronous xchacha ciphers This feature isn't useful in practice. Simplify and streamline the code in the synchronous case, i.e. the case that actually matters, instead. For example, by no longer having to support resuming the calculation after an asynchronous return of the xchacha cipher, we can just keep more of the state on the stack instead of in the request context. Link: https://lore.kernel.org/r/20251211011846.8179-10-ebiggers@kernel.org Signed-off-by: Eric Biggers --- crypto/adiantum.c | 176 +++++++++++++++++++--------------------------- 1 file changed, 71 insertions(+), 105 deletions(-) diff --git a/crypto/adiantum.c b/crypto/adiantum.c index 6d882f926ab0..5ddf585abb66 100644 --- a/crypto/adiantum.c +++ b/crypto/adiantum.c @@ -83,29 +83,6 @@ struct nhpoly1305_ctx { }; struct adiantum_request_ctx { - - /* - * Buffer for right-hand part of data, i.e. - * - * P_L => P_M => C_M => C_R when encrypting, or - * C_R => C_M => P_M => P_L when decrypting. - * - * Also used to build the IV for the stream cipher. - */ - union { - u8 bytes[XCHACHA_IV_SIZE]; - __le32 words[XCHACHA_IV_SIZE / sizeof(__le32)]; - le128 bignum; /* interpret as element of Z/(2^{128}Z) */ - } rbuf; - - bool enc; /* true if encrypting, false if decrypting */ - - /* - * The result of the Poly1305 ε-∆U hash function applied to - * (bulk length, tweak) - */ - le128 header_hash; - /* * skcipher sub-request size is unknown at compile-time, so it needs to * go after the members with known sizes. @@ -216,7 +193,7 @@ static inline void le128_sub(le128 *r, const le128 *v1, const le128 *v2) /* * Apply the Poly1305 ε-∆U hash function to (bulk length, tweak) and save the - * result to rctx->header_hash. This is the calculation + * result to @out. This is the calculation * * H_T ← Poly1305_{K_T}(bin_{128}(|L|) || T) * @@ -226,11 +203,10 @@ static inline void le128_sub(le128 *r, const le128 *v1, const le128 *v2) * inputs only) taken over the left-hand part (the "bulk") of the message, to * give the overall Adiantum hash of the (tweak, left-hand part) pair. */ -static void adiantum_hash_header(struct skcipher_request *req) +static void adiantum_hash_header(struct skcipher_request *req, le128 *out) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); - struct adiantum_request_ctx *rctx = skcipher_request_ctx(req); const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE; struct { __le64 message_bits; @@ -250,7 +226,7 @@ static void adiantum_hash_header(struct skcipher_request *req) poly1305_core_blocks(&state, &tctx->header_hash_key, req->iv, TWEAK_SIZE / POLY1305_BLOCK_SIZE, 1); - poly1305_core_emit(&state, NULL, &rctx->header_hash); + poly1305_core_emit(&state, NULL, out); } /* Pass the next NH hash value through Poly1305 */ @@ -389,81 +365,39 @@ static void adiantum_hash_message(struct skcipher_request *req, nhpoly1305_final(&rctx->u.hash_ctx, tctx, out); } -/* Continue Adiantum encryption/decryption after the stream cipher step */ -static int adiantum_finish(struct skcipher_request *req) -{ - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); - const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); - struct adiantum_request_ctx *rctx = skcipher_request_ctx(req); - const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE; - struct scatterlist *dst = req->dst; - le128 digest; - - /* If decrypting, decrypt C_M with the block cipher to get P_M */ - if (!rctx->enc) - crypto_cipher_decrypt_one(tctx->blockcipher, rctx->rbuf.bytes, - rctx->rbuf.bytes); - - /* - * Second hash step - * enc: C_R = C_M - H_{K_H}(T, C_L) - * dec: P_R = P_M - H_{K_H}(T, P_L) - */ - le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &rctx->header_hash); - if (dst->length >= req->cryptlen && - dst->offset + req->cryptlen <= PAGE_SIZE) { - /* Fast path for single-page destination */ - struct page *page = sg_page(dst); - void *virt = kmap_local_page(page) + dst->offset; - - nhpoly1305_init(&rctx->u.hash_ctx); - nhpoly1305_update(&rctx->u.hash_ctx, tctx, virt, bulk_len); - nhpoly1305_final(&rctx->u.hash_ctx, tctx, &digest); - le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); - memcpy(virt + bulk_len, &rctx->rbuf.bignum, sizeof(le128)); - flush_dcache_page(page); - kunmap_local(virt); - } else { - /* Slow path that works for any destination scatterlist */ - adiantum_hash_message(req, dst, &digest); - le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); - memcpy_to_sglist(dst, bulk_len, &rctx->rbuf.bignum, - sizeof(le128)); - } - return 0; -} - -static void adiantum_streamcipher_done(void *data, int err) -{ - struct skcipher_request *req = data; - - if (!err) - err = adiantum_finish(req); - - skcipher_request_complete(req, err); -} - static int adiantum_crypt(struct skcipher_request *req, bool enc) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); struct adiantum_request_ctx *rctx = skcipher_request_ctx(req); const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE; - struct scatterlist *src = req->src; + struct scatterlist *src = req->src, *dst = req->dst; + /* + * Buffer for right-hand part of data, i.e. + * + * P_L => P_M => C_M => C_R when encrypting, or + * C_R => C_M => P_M => P_L when decrypting. + * + * Also used to build the IV for the stream cipher. + */ + union { + u8 bytes[XCHACHA_IV_SIZE]; + __le32 words[XCHACHA_IV_SIZE / sizeof(__le32)]; + le128 bignum; /* interpret as element of Z/(2^{128}Z) */ + } rbuf; + le128 header_hash, msg_hash; unsigned int stream_len; - le128 digest; + int err; if (req->cryptlen < BLOCKCIPHER_BLOCK_SIZE) return -EINVAL; - rctx->enc = enc; - /* * First hash step * enc: P_M = P_R + H_{K_H}(T, P_L) * dec: C_M = C_R + H_{K_H}(T, C_L) */ - adiantum_hash_header(req); + adiantum_hash_header(req, &header_hash); if (src->length >= req->cryptlen && src->offset + req->cryptlen <= PAGE_SIZE) { /* Fast path for single-page source */ @@ -471,30 +405,29 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc) nhpoly1305_init(&rctx->u.hash_ctx); nhpoly1305_update(&rctx->u.hash_ctx, tctx, virt, bulk_len); - nhpoly1305_final(&rctx->u.hash_ctx, tctx, &digest); - memcpy(&rctx->rbuf.bignum, virt + bulk_len, sizeof(le128)); + nhpoly1305_final(&rctx->u.hash_ctx, tctx, &msg_hash); + memcpy(&rbuf.bignum, virt + bulk_len, sizeof(le128)); kunmap_local(virt); } else { /* Slow path that works for any source scatterlist */ - adiantum_hash_message(req, src, &digest); - memcpy_from_sglist(&rctx->rbuf.bignum, src, bulk_len, - sizeof(le128)); + adiantum_hash_message(req, src, &msg_hash); + memcpy_from_sglist(&rbuf.bignum, src, bulk_len, sizeof(le128)); } - le128_add(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &rctx->header_hash); - le128_add(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); + le128_add(&rbuf.bignum, &rbuf.bignum, &header_hash); + le128_add(&rbuf.bignum, &rbuf.bignum, &msg_hash); /* If encrypting, encrypt P_M with the block cipher to get C_M */ if (enc) - crypto_cipher_encrypt_one(tctx->blockcipher, rctx->rbuf.bytes, - rctx->rbuf.bytes); + crypto_cipher_encrypt_one(tctx->blockcipher, rbuf.bytes, + rbuf.bytes); /* Initialize the rest of the XChaCha IV (first part is C_M) */ BUILD_BUG_ON(BLOCKCIPHER_BLOCK_SIZE != 16); BUILD_BUG_ON(XCHACHA_IV_SIZE != 32); /* nonce || stream position */ - rctx->rbuf.words[4] = cpu_to_le32(1); - rctx->rbuf.words[5] = 0; - rctx->rbuf.words[6] = 0; - rctx->rbuf.words[7] = 0; + rbuf.words[4] = cpu_to_le32(1); + rbuf.words[5] = 0; + rbuf.words[6] = 0; + rbuf.words[7] = 0; /* * XChaCha needs to be done on all the data except the last 16 bytes; @@ -511,12 +444,44 @@ static int adiantum_crypt(struct skcipher_request *req, bool enc) skcipher_request_set_tfm(&rctx->u.streamcipher_req, tctx->streamcipher); skcipher_request_set_crypt(&rctx->u.streamcipher_req, req->src, - req->dst, stream_len, &rctx->rbuf); + req->dst, stream_len, &rbuf); skcipher_request_set_callback(&rctx->u.streamcipher_req, - req->base.flags, - adiantum_streamcipher_done, req); - return crypto_skcipher_encrypt(&rctx->u.streamcipher_req) ?: - adiantum_finish(req); + req->base.flags, NULL, NULL); + err = crypto_skcipher_encrypt(&rctx->u.streamcipher_req); + if (err) + return err; + + /* If decrypting, decrypt C_M with the block cipher to get P_M */ + if (!enc) + crypto_cipher_decrypt_one(tctx->blockcipher, rbuf.bytes, + rbuf.bytes); + + /* + * Second hash step + * enc: C_R = C_M - H_{K_H}(T, C_L) + * dec: P_R = P_M - H_{K_H}(T, P_L) + */ + le128_sub(&rbuf.bignum, &rbuf.bignum, &header_hash); + if (dst->length >= req->cryptlen && + dst->offset + req->cryptlen <= PAGE_SIZE) { + /* Fast path for single-page destination */ + struct page *page = sg_page(dst); + void *virt = kmap_local_page(page) + dst->offset; + + nhpoly1305_init(&rctx->u.hash_ctx); + nhpoly1305_update(&rctx->u.hash_ctx, tctx, virt, bulk_len); + nhpoly1305_final(&rctx->u.hash_ctx, tctx, &msg_hash); + le128_sub(&rbuf.bignum, &rbuf.bignum, &msg_hash); + memcpy(virt + bulk_len, &rbuf.bignum, sizeof(le128)); + flush_dcache_page(page); + kunmap_local(virt); + } else { + /* Slow path that works for any destination scatterlist */ + adiantum_hash_message(req, dst, &msg_hash); + le128_sub(&rbuf.bignum, &rbuf.bignum, &msg_hash); + memcpy_to_sglist(dst, bulk_len, &rbuf.bignum, sizeof(le128)); + } + return 0; } static int adiantum_encrypt(struct skcipher_request *req) @@ -624,7 +589,8 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) /* Stream cipher, e.g. "xchacha12" */ err = crypto_grab_skcipher(&ictx->streamcipher_spawn, skcipher_crypto_instance(inst), - crypto_attr_alg_name(tb[1]), 0, mask); + crypto_attr_alg_name(tb[1]), 0, + mask | CRYPTO_ALG_ASYNC /* sync only */); if (err) goto err_free_inst; streamcipher_alg = crypto_spawn_skcipher_alg_common(&ictx->streamcipher_spawn); From f676740c426535d0d2097e0b9adedb085634039b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 10 Dec 2025 17:18:42 -0800 Subject: [PATCH 12/53] crypto: nhpoly1305 - Remove crypto_shash support Remove nhpoly1305 support from crypto_shash. It no longer has any user now that crypto/adiantum.c no longer uses it. Acked-by: Herbert Xu Link: https://lore.kernel.org/r/20251211011846.8179-11-ebiggers@kernel.org Signed-off-by: Eric Biggers --- crypto/Kconfig | 6 - crypto/Makefile | 1 - crypto/nhpoly1305.c | 255 ------------------------------------ include/crypto/nhpoly1305.h | 74 ----------- 4 files changed, 336 deletions(-) delete mode 100644 crypto/nhpoly1305.c delete mode 100644 include/crypto/nhpoly1305.h diff --git a/crypto/Kconfig b/crypto/Kconfig index 89d1ccaa1fa0..12a87f7cf150 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -759,12 +759,6 @@ config CRYPTO_XTS implementation currently can't handle a sectorsize which is not a multiple of 16 bytes. -config CRYPTO_NHPOLY1305 - tristate - select CRYPTO_HASH - select CRYPTO_LIB_POLY1305 - select CRYPTO_LIB_POLY1305_GENERIC - endmenu menu "AEAD (authenticated encryption with associated data) ciphers" diff --git a/crypto/Makefile b/crypto/Makefile index 16a35649dd91..23d3db7be425 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -94,7 +94,6 @@ obj-$(CONFIG_CRYPTO_CTR) += ctr.o obj-$(CONFIG_CRYPTO_XCTR) += xctr.o obj-$(CONFIG_CRYPTO_HCTR2) += hctr2.o obj-$(CONFIG_CRYPTO_ADIANTUM) += adiantum.o -obj-$(CONFIG_CRYPTO_NHPOLY1305) += nhpoly1305.o obj-$(CONFIG_CRYPTO_GCM) += gcm.o obj-$(CONFIG_CRYPTO_CCM) += ccm.o obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o diff --git a/crypto/nhpoly1305.c b/crypto/nhpoly1305.c deleted file mode 100644 index 2b648615b5ec..000000000000 --- a/crypto/nhpoly1305.c +++ /dev/null @@ -1,255 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * NHPoly1305 - ε-almost-∆-universal hash function for Adiantum - * - * Copyright 2018 Google LLC - */ - -/* - * "NHPoly1305" is the main component of Adiantum hashing. - * Specifically, it is the calculation - * - * H_L ← Poly1305_{K_L}(NH_{K_N}(pad_{128}(L))) - * - * from the procedure in section 6.4 of the Adiantum paper [1]. It is an - * ε-almost-∆-universal (ε-∆U) hash function for equal-length inputs over - * Z/(2^{128}Z), where the "∆" operation is addition. It hashes 1024-byte - * chunks of the input with the NH hash function [2], reducing the input length - * by 32x. The resulting NH digests are evaluated as a polynomial in - * GF(2^{130}-5), like in the Poly1305 MAC [3]. Note that the polynomial - * evaluation by itself would suffice to achieve the ε-∆U property; NH is used - * for performance since it's over twice as fast as Poly1305. - * - * This is *not* a cryptographic hash function; do not use it as such! - * - * [1] Adiantum: length-preserving encryption for entry-level processors - * (https://eprint.iacr.org/2018/720.pdf) - * [2] UMAC: Fast and Secure Message Authentication - * (https://fastcrypto.org/umac/umac_proc.pdf) - * [3] The Poly1305-AES message-authentication code - * (https://cr.yp.to/mac/poly1305-20050329.pdf) - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static void nh_generic(const u32 *key, const u8 *message, size_t message_len, - __le64 hash[NH_NUM_PASSES]) -{ - u64 sums[4] = { 0, 0, 0, 0 }; - - BUILD_BUG_ON(NH_PAIR_STRIDE != 2); - BUILD_BUG_ON(NH_NUM_PASSES != 4); - - while (message_len) { - u32 m0 = get_unaligned_le32(message + 0); - u32 m1 = get_unaligned_le32(message + 4); - u32 m2 = get_unaligned_le32(message + 8); - u32 m3 = get_unaligned_le32(message + 12); - - sums[0] += (u64)(u32)(m0 + key[ 0]) * (u32)(m2 + key[ 2]); - sums[1] += (u64)(u32)(m0 + key[ 4]) * (u32)(m2 + key[ 6]); - sums[2] += (u64)(u32)(m0 + key[ 8]) * (u32)(m2 + key[10]); - sums[3] += (u64)(u32)(m0 + key[12]) * (u32)(m2 + key[14]); - sums[0] += (u64)(u32)(m1 + key[ 1]) * (u32)(m3 + key[ 3]); - sums[1] += (u64)(u32)(m1 + key[ 5]) * (u32)(m3 + key[ 7]); - sums[2] += (u64)(u32)(m1 + key[ 9]) * (u32)(m3 + key[11]); - sums[3] += (u64)(u32)(m1 + key[13]) * (u32)(m3 + key[15]); - key += NH_MESSAGE_UNIT / sizeof(key[0]); - message += NH_MESSAGE_UNIT; - message_len -= NH_MESSAGE_UNIT; - } - - hash[0] = cpu_to_le64(sums[0]); - hash[1] = cpu_to_le64(sums[1]); - hash[2] = cpu_to_le64(sums[2]); - hash[3] = cpu_to_le64(sums[3]); -} - -/* Pass the next NH hash value through Poly1305 */ -static void process_nh_hash_value(struct nhpoly1305_state *state, - const struct nhpoly1305_key *key) -{ - BUILD_BUG_ON(NH_HASH_BYTES % POLY1305_BLOCK_SIZE != 0); - - poly1305_core_blocks(&state->poly_state, &key->poly_key, state->nh_hash, - NH_HASH_BYTES / POLY1305_BLOCK_SIZE, 1); -} - -/* - * Feed the next portion of the source data, as a whole number of 16-byte - * "NH message units", through NH and Poly1305. Each NH hash is taken over - * 1024 bytes, except possibly the final one which is taken over a multiple of - * 16 bytes up to 1024. Also, in the case where data is passed in misaligned - * chunks, we combine partial hashes; the end result is the same either way. - */ -static void nhpoly1305_units(struct nhpoly1305_state *state, - const struct nhpoly1305_key *key, - const u8 *src, unsigned int srclen, nh_t nh_fn) -{ - do { - unsigned int bytes; - - if (state->nh_remaining == 0) { - /* Starting a new NH message */ - bytes = min_t(unsigned int, srclen, NH_MESSAGE_BYTES); - nh_fn(key->nh_key, src, bytes, state->nh_hash); - state->nh_remaining = NH_MESSAGE_BYTES - bytes; - } else { - /* Continuing a previous NH message */ - __le64 tmp_hash[NH_NUM_PASSES]; - unsigned int pos; - int i; - - pos = NH_MESSAGE_BYTES - state->nh_remaining; - bytes = min(srclen, state->nh_remaining); - nh_fn(&key->nh_key[pos / 4], src, bytes, tmp_hash); - for (i = 0; i < NH_NUM_PASSES; i++) - le64_add_cpu(&state->nh_hash[i], - le64_to_cpu(tmp_hash[i])); - state->nh_remaining -= bytes; - } - if (state->nh_remaining == 0) - process_nh_hash_value(state, key); - src += bytes; - srclen -= bytes; - } while (srclen); -} - -int crypto_nhpoly1305_setkey(struct crypto_shash *tfm, - const u8 *key, unsigned int keylen) -{ - struct nhpoly1305_key *ctx = crypto_shash_ctx(tfm); - int i; - - if (keylen != NHPOLY1305_KEY_SIZE) - return -EINVAL; - - poly1305_core_setkey(&ctx->poly_key, key); - key += POLY1305_BLOCK_SIZE; - - for (i = 0; i < NH_KEY_WORDS; i++) - ctx->nh_key[i] = get_unaligned_le32(key + i * sizeof(u32)); - - return 0; -} -EXPORT_SYMBOL(crypto_nhpoly1305_setkey); - -int crypto_nhpoly1305_init(struct shash_desc *desc) -{ - struct nhpoly1305_state *state = shash_desc_ctx(desc); - - poly1305_core_init(&state->poly_state); - state->buflen = 0; - state->nh_remaining = 0; - return 0; -} -EXPORT_SYMBOL(crypto_nhpoly1305_init); - -int crypto_nhpoly1305_update_helper(struct shash_desc *desc, - const u8 *src, unsigned int srclen, - nh_t nh_fn) -{ - struct nhpoly1305_state *state = shash_desc_ctx(desc); - const struct nhpoly1305_key *key = crypto_shash_ctx(desc->tfm); - unsigned int bytes; - - if (state->buflen) { - bytes = min(srclen, (int)NH_MESSAGE_UNIT - state->buflen); - memcpy(&state->buffer[state->buflen], src, bytes); - state->buflen += bytes; - if (state->buflen < NH_MESSAGE_UNIT) - return 0; - nhpoly1305_units(state, key, state->buffer, NH_MESSAGE_UNIT, - nh_fn); - state->buflen = 0; - src += bytes; - srclen -= bytes; - } - - if (srclen >= NH_MESSAGE_UNIT) { - bytes = round_down(srclen, NH_MESSAGE_UNIT); - nhpoly1305_units(state, key, src, bytes, nh_fn); - src += bytes; - srclen -= bytes; - } - - if (srclen) { - memcpy(state->buffer, src, srclen); - state->buflen = srclen; - } - return 0; -} -EXPORT_SYMBOL(crypto_nhpoly1305_update_helper); - -int crypto_nhpoly1305_update(struct shash_desc *desc, - const u8 *src, unsigned int srclen) -{ - return crypto_nhpoly1305_update_helper(desc, src, srclen, nh_generic); -} -EXPORT_SYMBOL(crypto_nhpoly1305_update); - -int crypto_nhpoly1305_final_helper(struct shash_desc *desc, u8 *dst, nh_t nh_fn) -{ - struct nhpoly1305_state *state = shash_desc_ctx(desc); - const struct nhpoly1305_key *key = crypto_shash_ctx(desc->tfm); - - if (state->buflen) { - memset(&state->buffer[state->buflen], 0, - NH_MESSAGE_UNIT - state->buflen); - nhpoly1305_units(state, key, state->buffer, NH_MESSAGE_UNIT, - nh_fn); - } - - if (state->nh_remaining) - process_nh_hash_value(state, key); - - poly1305_core_emit(&state->poly_state, NULL, dst); - return 0; -} -EXPORT_SYMBOL(crypto_nhpoly1305_final_helper); - -int crypto_nhpoly1305_final(struct shash_desc *desc, u8 *dst) -{ - return crypto_nhpoly1305_final_helper(desc, dst, nh_generic); -} -EXPORT_SYMBOL(crypto_nhpoly1305_final); - -static struct shash_alg nhpoly1305_alg = { - .base.cra_name = "nhpoly1305", - .base.cra_driver_name = "nhpoly1305-generic", - .base.cra_priority = 100, - .base.cra_ctxsize = sizeof(struct nhpoly1305_key), - .base.cra_module = THIS_MODULE, - .digestsize = POLY1305_DIGEST_SIZE, - .init = crypto_nhpoly1305_init, - .update = crypto_nhpoly1305_update, - .final = crypto_nhpoly1305_final, - .setkey = crypto_nhpoly1305_setkey, - .descsize = sizeof(struct nhpoly1305_state), -}; - -static int __init nhpoly1305_mod_init(void) -{ - return crypto_register_shash(&nhpoly1305_alg); -} - -static void __exit nhpoly1305_mod_exit(void) -{ - crypto_unregister_shash(&nhpoly1305_alg); -} - -module_init(nhpoly1305_mod_init); -module_exit(nhpoly1305_mod_exit); - -MODULE_DESCRIPTION("NHPoly1305 ε-almost-∆-universal hash function"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Eric Biggers "); -MODULE_ALIAS_CRYPTO("nhpoly1305"); -MODULE_ALIAS_CRYPTO("nhpoly1305-generic"); diff --git a/include/crypto/nhpoly1305.h b/include/crypto/nhpoly1305.h deleted file mode 100644 index 306925fea190..000000000000 --- a/include/crypto/nhpoly1305.h +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Common values and helper functions for the NHPoly1305 hash function. - */ - -#ifndef _NHPOLY1305_H -#define _NHPOLY1305_H - -#include -#include - -/* NH parameterization: */ - -/* Endianness: little */ -/* Word size: 32 bits (works well on NEON, SSE2, AVX2) */ - -/* Stride: 2 words (optimal on ARM32 NEON; works okay on other CPUs too) */ -#define NH_PAIR_STRIDE 2 -#define NH_MESSAGE_UNIT (NH_PAIR_STRIDE * 2 * sizeof(u32)) - -/* Num passes (Toeplitz iteration count): 4, to give ε = 2^{-128} */ -#define NH_NUM_PASSES 4 -#define NH_HASH_BYTES (NH_NUM_PASSES * sizeof(u64)) - -/* Max message size: 1024 bytes (32x compression factor) */ -#define NH_NUM_STRIDES 64 -#define NH_MESSAGE_WORDS (NH_PAIR_STRIDE * 2 * NH_NUM_STRIDES) -#define NH_MESSAGE_BYTES (NH_MESSAGE_WORDS * sizeof(u32)) -#define NH_KEY_WORDS (NH_MESSAGE_WORDS + \ - NH_PAIR_STRIDE * 2 * (NH_NUM_PASSES - 1)) -#define NH_KEY_BYTES (NH_KEY_WORDS * sizeof(u32)) - -#define NHPOLY1305_KEY_SIZE (POLY1305_BLOCK_SIZE + NH_KEY_BYTES) - -struct nhpoly1305_key { - struct poly1305_core_key poly_key; - u32 nh_key[NH_KEY_WORDS]; -}; - -struct nhpoly1305_state { - - /* Running total of polynomial evaluation */ - struct poly1305_state poly_state; - - /* Partial block buffer */ - u8 buffer[NH_MESSAGE_UNIT]; - unsigned int buflen; - - /* - * Number of bytes remaining until the current NH message reaches - * NH_MESSAGE_BYTES. When nonzero, 'nh_hash' holds the partial NH hash. - */ - unsigned int nh_remaining; - - __le64 nh_hash[NH_NUM_PASSES]; -}; - -typedef void (*nh_t)(const u32 *key, const u8 *message, size_t message_len, - __le64 hash[NH_NUM_PASSES]); - -int crypto_nhpoly1305_setkey(struct crypto_shash *tfm, - const u8 *key, unsigned int keylen); - -int crypto_nhpoly1305_init(struct shash_desc *desc); -int crypto_nhpoly1305_update(struct shash_desc *desc, - const u8 *src, unsigned int srclen); -int crypto_nhpoly1305_update_helper(struct shash_desc *desc, - const u8 *src, unsigned int srclen, - nh_t nh_fn); -int crypto_nhpoly1305_final(struct shash_desc *desc, u8 *dst); -int crypto_nhpoly1305_final_helper(struct shash_desc *desc, u8 *dst, - nh_t nh_fn); - -#endif /* _NHPOLY1305_H */ From 719316ad8eb0c2cb5120ad6098af22ce73726853 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 10 Dec 2025 17:18:43 -0800 Subject: [PATCH 13/53] crypto: testmgr - Remove nhpoly1305 tests These are no longer used, since nhpoly1305 support has been removed from the crypto_shash API. Acked-by: Herbert Xu Link: https://lore.kernel.org/r/20251211011846.8179-12-ebiggers@kernel.org Signed-off-by: Eric Biggers --- crypto/testmgr.c | 6 - crypto/testmgr.h | 1372 ---------------------------------------------- 2 files changed, 1378 deletions(-) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index d9fc671d5941..5df204d9c9dd 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -5172,12 +5172,6 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .hash = __VECS(michael_mic_tv_template) } - }, { - .alg = "nhpoly1305", - .test = alg_test_hash, - .suite = { - .hash = __VECS(nhpoly1305_tv_template) - } }, { .alg = "p1363(ecdsa-nist-p192)", .test = alg_test_null, diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 80bf5f1b67a6..1a3329e1c325 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -7599,1378 +7599,6 @@ static const struct hash_testvec hmac_sha3_512_tv_template[] = { }, }; -/* NHPoly1305 test vectors from https://github.com/google/adiantum */ -static const struct hash_testvec nhpoly1305_tv_template[] = { - { - .key = "\xd2\x5d\x4c\xdd\x8d\x2b\x7f\x7a" - "\xd9\xbe\x71\xec\xd1\x83\x52\xe3" - "\xe1\xad\xd7\x5c\x0a\x75\x9d\xec" - "\x1d\x13\x7e\x5d\x71\x07\xc9\xe4" - "\x57\x2d\x44\x68\xcf\xd8\xd6\xc5" - "\x39\x69\x7d\x32\x75\x51\x4f\x7e" - "\xb2\x4c\xc6\x90\x51\x6e\xd9\xd6" - "\xa5\x8b\x2d\xf1\x94\xf9\xf7\x5e" - "\x2c\x84\x7b\x41\x0f\x88\x50\x89" - "\x30\xd9\xa1\x38\x46\x6c\xc0\x4f" - "\xe8\xdf\xdc\x66\xab\x24\x43\x41" - "\x91\x55\x29\x65\x86\x28\x5e\x45" - "\xd5\x2d\xb7\x80\x08\x9a\xc3\xd4" - "\x9a\x77\x0a\xd4\xef\x3e\xe6\x3f" - "\x6f\x2f\x9b\x3a\x7d\x12\x1e\x80" - "\x6c\x44\xa2\x25\xe1\xf6\x60\xe9" - "\x0d\xaf\xc5\x3c\xa5\x79\xae\x64" - "\xbc\xa0\x39\xa3\x4d\x10\xe5\x4d" - "\xd5\xe7\x89\x7a\x13\xee\x06\x78" - "\xdc\xa4\xdc\x14\x27\xe6\x49\x38" - "\xd0\xe0\x45\x25\x36\xc5\xf4\x79" - "\x2e\x9a\x98\x04\xe4\x2b\x46\x52" - "\x7c\x33\xca\xe2\x56\x51\x50\xe2" - "\xa5\x9a\xae\x18\x6a\x13\xf8\xd2" - "\x21\x31\x66\x02\xe2\xda\x8d\x7e" - "\x41\x19\xb2\x61\xee\x48\x8f\xf1" - "\x65\x24\x2e\x1e\x68\xce\x05\xd9" - "\x2a\xcf\xa5\x3a\x57\xdd\x35\x91" - "\x93\x01\xca\x95\xfc\x2b\x36\x04" - "\xe6\x96\x97\x28\xf6\x31\xfe\xa3" - "\x9d\xf6\x6a\x1e\x80\x8d\xdc\xec" - "\xaf\x66\x11\x13\x02\x88\xd5\x27" - "\x33\xb4\x1a\xcd\xa3\xf6\xde\x31" - "\x8e\xc0\x0e\x6c\xd8\x5a\x97\x5e" - "\xdd\xfd\x60\x69\x38\x46\x3f\x90" - "\x5e\x97\xd3\x32\x76\xc7\x82\x49" - "\xfe\xba\x06\x5f\x2f\xa2\xfd\xff" - "\x80\x05\x40\xe4\x33\x03\xfb\x10" - "\xc0\xde\x65\x8c\xc9\x8d\x3a\x9d" - "\xb5\x7b\x36\x4b\xb5\x0c\xcf\x00" - "\x9c\x87\xe4\x49\xad\x90\xda\x4a" - "\xdd\xbd\xff\xe2\x32\x57\xd6\x78" - "\x36\x39\x6c\xd3\x5b\x9b\x88\x59" - "\x2d\xf0\x46\xe4\x13\x0e\x2b\x35" - "\x0d\x0f\x73\x8a\x4f\x26\x84\x75" - "\x88\x3c\xc5\x58\x66\x18\x1a\xb4" - "\x64\x51\x34\x27\x1b\xa4\x11\xc9" - "\x6d\x91\x8a\xfa\x32\x60\x9d\xd7" - "\x87\xe5\xaa\x43\x72\xf8\xda\xd1" - "\x48\x44\x13\x61\xdc\x8c\x76\x17" - "\x0c\x85\x4e\xf3\xdd\xa2\x42\xd2" - "\x74\xc1\x30\x1b\xeb\x35\x31\x29" - "\x5b\xd7\x4c\x94\x46\x35\xa1\x23" - "\x50\xf2\xa2\x8e\x7e\x4f\x23\x4f" - "\x51\xff\xe2\xc9\xa3\x7d\x56\x8b" - "\x41\xf2\xd0\xc5\x57\x7e\x59\xac" - "\xbb\x65\xf3\xfe\xf7\x17\xef\x63" - "\x7c\x6f\x23\xdd\x22\x8e\xed\x84" - "\x0e\x3b\x09\xb3\xf3\xf4\x8f\xcd" - "\x37\xa8\xe1\xa7\x30\xdb\xb1\xa2" - "\x9c\xa2\xdf\x34\x17\x3e\x68\x44" - "\xd0\xde\x03\x50\xd1\x48\x6b\x20" - "\xe2\x63\x45\xa5\xea\x87\xc2\x42" - "\x95\x03\x49\x05\xed\xe0\x90\x29" - "\x1a\xb8\xcf\x9b\x43\xcf\x29\x7a" - "\x63\x17\x41\x9f\xe0\xc9\x10\xfd" - "\x2c\x56\x8c\x08\x55\xb4\xa9\x27" - "\x0f\x23\xb1\x05\x6a\x12\x46\xc7" - "\xe1\xfe\x28\x93\x93\xd7\x2f\xdc" - "\x98\x30\xdb\x75\x8a\xbe\x97\x7a" - "\x02\xfb\x8c\xba\xbe\x25\x09\xbe" - "\xce\xcb\xa2\xef\x79\x4d\x0e\x9d" - "\x1b\x9d\xb6\x39\x34\x38\xfa\x07" - "\xec\xe8\xfc\x32\x85\x1d\xf7\x85" - "\x63\xc3\x3c\xc0\x02\x75\xd7\x3f" - "\xb2\x68\x60\x66\x65\x81\xc6\xb1" - "\x42\x65\x4b\x4b\x28\xd7\xc7\xaa" - "\x9b\xd2\xdc\x1b\x01\xe0\x26\x39" - "\x01\xc1\x52\x14\xd1\x3f\xb7\xe6" - "\x61\x41\xc7\x93\xd2\xa2\x67\xc6" - "\xf7\x11\xb5\xf5\xea\xdd\x19\xfb" - "\x4d\x21\x12\xd6\x7d\xf1\x10\xb0" - "\x89\x07\xc7\x5a\x52\x73\x70\x2f" - "\x32\xef\x65\x2b\x12\xb2\xf0\xf5" - "\x20\xe0\x90\x59\x7e\x64\xf1\x4c" - "\x41\xb3\xa5\x91\x08\xe6\x5e\x5f" - "\x05\x56\x76\xb4\xb0\xcd\x70\x53" - "\x10\x48\x9c\xff\xc2\x69\x55\x24" - "\x87\xef\x84\xea\xfb\xa7\xbf\xa0" - "\x91\x04\xad\x4f\x8b\x57\x54\x4b" - "\xb6\xe9\xd1\xac\x37\x2f\x1d\x2e" - "\xab\xa5\xa4\xe8\xff\xfb\xd9\x39" - "\x2f\xb7\xac\xd1\xfe\x0b\x9a\x80" - "\x0f\xb6\xf4\x36\x39\x90\x51\xe3" - "\x0a\x2f\xb6\x45\x76\x89\xcd\x61" - "\xfe\x48\x5f\x75\x1d\x13\x00\x62" - "\x80\x24\x47\xe7\xbc\x37\xd7\xe3" - "\x15\xe8\x68\x22\xaf\x80\x6f\x4b" - "\xa8\x9f\x01\x10\x48\x14\xc3\x02" - "\x52\xd2\xc7\x75\x9b\x52\x6d\x30" - "\xac\x13\x85\xc8\xf7\xa3\x58\x4b" - "\x49\xf7\x1c\x45\x55\x8c\x39\x9a" - "\x99\x6d\x97\x27\x27\xe6\xab\xdd" - "\x2c\x42\x1b\x35\xdd\x9d\x73\xbb" - "\x6c\xf3\x64\xf1\xfb\xb9\xf7\xe6" - "\x4a\x3c\xc0\x92\xc0\x2e\xb7\x1a" - "\xbe\xab\xb3\x5a\xe5\xea\xb1\x48" - "\x58\x13\x53\x90\xfd\xc3\x8e\x54" - "\xf9\x18\x16\x73\xe8\xcb\x6d\x39" - "\x0e\xd7\xe0\xfe\xb6\x9f\x43\x97" - "\xe8\xd0\x85\x56\x83\x3e\x98\x68" - "\x7f\xbd\x95\xa8\x9a\x61\x21\x8f" - "\x06\x98\x34\xa6\xc8\xd6\x1d\xf3" - "\x3d\x43\xa4\x9a\x8c\xe5\xd3\x5a" - "\x32\xa2\x04\x22\xa4\x19\x1a\x46" - "\x42\x7e\x4d\xe5\xe0\xe6\x0e\xca" - "\xd5\x58\x9d\x2c\xaf\xda\x33\x5c" - "\xb0\x79\x9e\xc9\xfc\xca\xf0\x2f" - "\xa8\xb2\x77\xeb\x7a\xa2\xdd\x37" - "\x35\x83\x07\xd6\x02\x1a\xb6\x6c" - "\x24\xe2\x59\x08\x0e\xfd\x3e\x46" - "\xec\x40\x93\xf4\x00\x26\x4f\x2a" - "\xff\x47\x2f\xeb\x02\x92\x26\x5b" - "\x53\x17\xc2\x8d\x2a\xc7\xa3\x1b" - "\xcd\xbc\xa7\xe8\xd1\x76\xe3\x80" - "\x21\xca\x5d\x3b\xe4\x9c\x8f\xa9" - "\x5b\x7f\x29\x7f\x7c\xd8\xed\x6d" - "\x8c\xb2\x86\x85\xe7\x77\xf2\x85" - "\xab\x38\xa9\x9d\xc1\x4e\xc5\x64" - "\x33\x73\x8b\x59\x03\xad\x05\xdf" - "\x25\x98\x31\xde\xef\x13\xf1\x9b" - "\x3c\x91\x9d\x7b\xb1\xfa\xe6\xbf" - "\x5b\xed\xa5\x55\xe6\xea\x6c\x74" - "\xf4\xb9\xe4\x45\x64\x72\x81\xc2" - "\x4c\x28\xd4\xcd\xac\xe2\xde\xf9" - "\xeb\x5c\xeb\x61\x60\x5a\xe5\x28", - .ksize = 1088, - .plaintext = "", - .psize = 0, - .digest = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - }, { - .key = "\x29\x21\x43\xcb\xcb\x13\x07\xde" - "\xbf\x48\xdf\x8a\x7f\xa2\x84\xde" - "\x72\x23\x9d\xf5\xf0\x07\xf2\x4c" - "\x20\x3a\x93\xb9\xcd\x5d\xfe\xcb" - "\x99\x2c\x2b\x58\xc6\x50\x5f\x94" - "\x56\xc3\x7c\x0d\x02\x3f\xb8\x5e" - "\x7b\xc0\x6c\x51\x34\x76\xc0\x0e" - "\xc6\x22\xc8\x9e\x92\xa0\x21\xc9" - "\x85\x5c\x7c\xf8\xe2\x64\x47\xc9" - "\xe4\xa2\x57\x93\xf8\xa2\x69\xcd" - "\x62\x98\x99\xf4\xd7\x7b\x14\xb1" - "\xd8\x05\xff\x04\x15\xc9\xe1\x6e" - "\x9b\xe6\x50\x6b\x0b\x3f\x22\x1f" - "\x08\xde\x0c\x5b\x08\x7e\xc6\x2f" - "\x6c\xed\xd6\xb2\x15\xa4\xb3\xf9" - "\xa7\x46\x38\x2a\xea\x69\xa5\xde" - "\x02\xc3\x96\x89\x4d\x55\x3b\xed" - "\x3d\x3a\x85\x77\xbf\x97\x45\x5c" - "\x9e\x02\x69\xe2\x1b\x68\xbe\x96" - "\xfb\x64\x6f\x0f\xf6\x06\x40\x67" - "\xfa\x04\xe3\x55\xfa\xbe\xa4\x60" - "\xef\x21\x66\x97\xe6\x9d\x5c\x1f" - "\x62\x37\xaa\x31\xde\xe4\x9c\x28" - "\x95\xe0\x22\x86\xf4\x4d\xf3\x07" - "\xfd\x5f\x3a\x54\x2c\x51\x80\x71" - "\xba\x78\x69\x5b\x65\xab\x1f\x81" - "\xed\x3b\xff\x34\xa3\xfb\xbc\x73" - "\x66\x7d\x13\x7f\xdf\x6e\xe2\xe2" - "\xeb\x4f\x6c\xda\x7d\x33\x57\xd0" - "\xd3\x7c\x95\x4f\x33\x58\x21\xc7" - "\xc0\xe5\x6f\x42\x26\xc6\x1f\x5e" - "\x85\x1b\x98\x9a\xa2\x1e\x55\x77" - "\x23\xdf\x81\x5e\x79\x55\x05\xfc" - "\xfb\xda\xee\xba\x5a\xba\xf7\x77" - "\x7f\x0e\xd3\xe1\x37\xfe\x8d\x2b" - "\xd5\x3f\xfb\xd0\xc0\x3c\x0b\x3f" - "\xcf\x3c\x14\xcf\xfb\x46\x72\x4c" - "\x1f\x39\xe2\xda\x03\x71\x6d\x23" - "\xef\x93\xcd\x39\xd9\x37\x80\x4d" - "\x65\x61\xd1\x2c\x03\xa9\x47\x72" - "\x4d\x1e\x0e\x16\x33\x0f\x21\x17" - "\xec\x92\xea\x6f\x37\x22\xa4\xd8" - "\x03\x33\x9e\xd8\x03\x69\x9a\xe8" - "\xb2\x57\xaf\x78\x99\x05\x12\xab" - "\x48\x90\x80\xf0\x12\x9b\x20\x64" - "\x7a\x1d\x47\x5f\xba\x3c\xf9\xc3" - "\x0a\x0d\x8d\xa1\xf9\x1b\x82\x13" - "\x3e\x0d\xec\x0a\x83\xc0\x65\xe1" - "\xe9\x95\xff\x97\xd6\xf2\xe4\xd5" - "\x86\xc0\x1f\x29\x27\x63\xd7\xde" - "\xb7\x0a\x07\x99\x04\x2d\xa3\x89" - "\xa2\x43\xcf\xf3\xe1\x43\xac\x4a" - "\x06\x97\xd0\x05\x4f\x87\xfa\xf9" - "\x9b\xbf\x52\x70\xbd\xbc\x6c\xf3" - "\x03\x13\x60\x41\x28\x09\xec\xcc" - "\xb1\x1a\xec\xd6\xfb\x6f\x2a\x89" - "\x5d\x0b\x53\x9c\x59\xc1\x84\x21" - "\x33\x51\x47\x19\x31\x9c\xd4\x0a" - "\x4d\x04\xec\x50\x90\x61\xbd\xbc" - "\x7e\xc8\xd9\x6c\x98\x1d\x45\x41" - "\x17\x5e\x97\x1c\xc5\xa8\xe8\xea" - "\x46\x58\x53\xf7\x17\xd5\xad\x11" - "\xc8\x54\xf5\x7a\x33\x90\xf5\x19" - "\xba\x36\xb4\xfc\x52\xa5\x72\x3d" - "\x14\xbb\x55\xa7\xe9\xe3\x12\xf7" - "\x1c\x30\xa2\x82\x03\xbf\x53\x91" - "\x2e\x60\x41\x9f\x5b\x69\x39\xf6" - "\x4d\xc8\xf8\x46\x7a\x7f\xa4\x98" - "\x36\xff\x06\xcb\xca\xe7\x33\xf2" - "\xc0\x4a\xf4\x3c\x14\x44\x5f\x6b" - "\x75\xef\x02\x36\x75\x08\x14\xfd" - "\x10\x8e\xa5\x58\xd0\x30\x46\x49" - "\xaf\x3a\xf8\x40\x3d\x35\xdb\x84" - "\x11\x2e\x97\x6a\xb7\x87\x7f\xad" - "\xf1\xfa\xa5\x63\x60\xd8\x5e\xbf" - "\x41\x78\x49\xcf\x77\xbb\x56\xbb" - "\x7d\x01\x67\x05\x22\xc8\x8f\x41" - "\xba\x81\xd2\xca\x2c\x38\xac\x76" - "\x06\xc1\x1a\xc2\xce\xac\x90\x67" - "\x57\x3e\x20\x12\x5b\xd9\x97\x58" - "\x65\x05\xb7\x04\x61\x7e\xd8\x3a" - "\xbf\x55\x3b\x13\xe9\x34\x5a\x37" - "\x36\xcb\x94\x45\xc5\x32\xb3\xa0" - "\x0c\x3e\x49\xc5\xd3\xed\xa7\xf0" - "\x1c\x69\xcc\xea\xcc\x83\xc9\x16" - "\x95\x72\x4b\xf4\x89\xd5\xb9\x10" - "\xf6\x2d\x60\x15\xea\x3c\x06\x66" - "\x9f\x82\xad\x17\xce\xd2\xa4\x48" - "\x7c\x65\xd9\xf8\x02\x4d\x9b\x4c" - "\x89\x06\x3a\x34\x85\x48\x89\x86" - "\xf9\x24\xa9\x54\x72\xdb\x44\x95" - "\xc7\x44\x1c\x19\x11\x4c\x04\xdc" - "\x13\xb9\x67\xc8\xc3\x3a\x6a\x50" - "\xfa\xd1\xfb\xe1\x88\xb6\xf1\xa3" - "\xc5\x3b\xdc\x38\x45\x16\x26\x02" - "\x3b\xb8\x8f\x8b\x58\x7d\x23\x04" - "\x50\x6b\x81\x9f\xae\x66\xac\x6f" - "\xcf\x2a\x9d\xf1\xfd\x1d\x57\x07" - "\xbe\x58\xeb\x77\x0c\xe3\xc2\x19" - "\x14\x74\x1b\x51\x1c\x4f\x41\xf3" - "\x32\x89\xb3\xe7\xde\x62\xf6\x5f" - "\xc7\x6a\x4a\x2a\x5b\x0f\x5f\x87" - "\x9c\x08\xb9\x02\x88\xc8\x29\xb7" - "\x94\x52\xfa\x52\xfe\xaa\x50\x10" - "\xba\x48\x75\x5e\x11\x1b\xe6\x39" - "\xd7\x82\x2c\x87\xf1\x1e\xa4\x38" - "\x72\x3e\x51\xe7\xd8\x3e\x5b\x7b" - "\x31\x16\x89\xba\xd6\xad\x18\x5e" - "\xba\xf8\x12\xb3\xf4\x6c\x47\x30" - "\xc0\x38\x58\xb3\x10\x8d\x58\x5d" - "\xb4\xfb\x19\x7e\x41\xc3\x66\xb8" - "\xd6\x72\x84\xe1\x1a\xc2\x71\x4c" - "\x0d\x4a\x21\x7a\xab\xa2\xc0\x36" - "\x15\xc5\xe9\x46\xd7\x29\x17\x76" - "\x5e\x47\x36\x7f\x72\x05\xa7\xcc" - "\x36\x63\xf9\x47\x7d\xe6\x07\x3c" - "\x8b\x79\x1d\x96\x61\x8d\x90\x65" - "\x7c\xf5\xeb\x4e\x6e\x09\x59\x6d" - "\x62\x50\x1b\x0f\xe0\xdc\x78\xf2" - "\x5b\x83\x1a\xa1\x11\x75\xfd\x18" - "\xd7\xe2\x8d\x65\x14\x21\xce\xbe" - "\xb5\x87\xe3\x0a\xda\x24\x0a\x64" - "\xa9\x9f\x03\x8d\x46\x5d\x24\x1a" - "\x8a\x0c\x42\x01\xca\xb1\x5f\x7c" - "\xa5\xac\x32\x4a\xb8\x07\x91\x18" - "\x6f\xb0\x71\x3c\xc9\xb1\xa8\xf8" - "\x5f\x69\xa5\xa1\xca\x9e\x7a\xaa" - "\xac\xe9\xc7\x47\x41\x75\x25\xc3" - "\x73\xe2\x0b\xdd\x6d\x52\x71\xbe" - "\xc5\xdc\xb4\xe7\x01\x26\x53\x77" - "\x86\x90\x85\x68\x6b\x7b\x03\x53" - "\xda\x52\x52\x51\x68\xc8\xf3\xec" - "\x6c\xd5\x03\x7a\xa3\x0e\xb4\x02" - "\x5f\x1a\xab\xee\xca\x67\x29\x7b" - "\xbd\x96\x59\xb3\x8b\x32\x7a\x92" - "\x9f\xd8\x25\x2b\xdf\xc0\x4c\xda", - .ksize = 1088, - .plaintext = "\xbc\xda\x81\xa8\x78\x79\x1c\xbf" - "\x77\x53\xba\x4c\x30\x5b\xb8\x33", - .psize = 16, - .digest = "\x04\xbf\x7f\x6a\xce\x72\xea\x6a" - "\x79\xdb\xb0\xc9\x60\xf6\x12\xcc", - }, { - .key = "\x2e\x77\x1e\x2c\x63\x76\x34\x3f" - "\x71\x08\x4f\x5a\xe3\x3d\x74\x56" - "\xc7\x98\x46\x52\xe5\x8a\xba\x0d" - "\x72\x41\x11\x15\x14\x72\x50\x8a" - "\xd5\xec\x60\x09\xdd\x71\xcc\xb9" - "\x59\x81\x65\x2d\x9e\x50\x18\xf3" - "\x32\xf3\xf1\xe7\x01\x82\x1c\xad" - "\x88\xa0\x21\x0c\x4b\x80\x5e\x62" - "\xfc\x81\xec\x52\xaa\xe4\xa5\x86" - "\xc2\xe6\x03\x11\xdc\x66\x09\x86" - "\x3c\x3b\xf0\x59\x0f\xb3\xf7\x44" - "\x24\xb7\x88\xc5\xfc\xc8\x77\x9f" - "\x8c\x44\xc4\x11\x55\xce\x7a\xa3" - "\xe0\xa2\xb8\xbf\xb5\x3d\x07\x2c" - "\x32\xb6\x6c\xfc\xb4\x42\x95\x95" - "\x98\x32\x81\xc4\xe7\xe2\xd9\x6a" - "\x87\xf4\xf4\x1e\x74\x7c\xb5\xcd" - "\x51\x45\x68\x38\x51\xdb\x30\x74" - "\x11\xe0\xaa\xae\x19\x8f\x15\x55" - "\xdd\x47\x4a\x35\xb9\x0c\xb4\x4e" - "\xa9\xce\x2f\xfa\x8f\xc1\x8a\x5e" - "\x5b\xec\xa5\x81\x3b\xb3\x43\x06" - "\x24\x81\xf4\x24\xe2\x21\xfa\xcb" - "\x49\xa8\xf8\xbd\x31\x4a\x5b\x2d" - "\x64\x0a\x07\xf0\x80\xc9\x0d\x81" - "\x14\x58\x54\x2b\xba\x22\x31\xba" - "\xef\x66\xc9\x49\x69\x69\x83\x0d" - "\xf2\xf9\x80\x9d\x30\x36\xfb\xe3" - "\xc0\x72\x2b\xcc\x5a\x81\x2c\x5d" - "\x3b\x5e\xf8\x2b\xd3\x14\x28\x73" - "\xf9\x1c\x70\xe6\xd8\xbb\xac\x30" - "\xf9\xd9\xa0\xe2\x33\x7c\x33\x34" - "\xa5\x6a\x77\x6d\xd5\xaf\xf4\xf3" - "\xc7\xb3\x0e\x83\x3d\xcb\x01\xcc" - "\x81\xc0\xf9\x4a\xae\x36\x92\xf7" - "\x69\x7b\x65\x01\xc3\xc8\xb8\xae" - "\x16\xd8\x30\xbb\xba\x6d\x78\x6e" - "\x0d\xf0\x7d\x84\xb7\x87\xda\x28" - "\x7a\x18\x10\x0b\x29\xec\x29\xf3" - "\xb0\x7b\xa1\x28\xbf\xbc\x2b\x2c" - "\x92\x2c\x16\xfb\x02\x39\xf9\xa6" - "\xa2\x15\x05\xa6\x72\x10\xbc\x62" - "\x4a\x6e\xb8\xb5\x5d\x59\xae\x3c" - "\x32\xd3\x68\xd7\x8e\x5a\xcd\x1b" - "\xef\xf6\xa7\x5e\x10\x51\x15\x4b" - "\x2c\xe3\xba\x70\x4f\x2c\xa0\x1c" - "\x7b\x97\xd7\xb2\xa5\x05\x17\xcc" - "\xf7\x3a\x29\x6f\xd5\x4b\xb8\x24" - "\xf4\x65\x95\x12\xc0\x86\xd1\x64" - "\x81\xdf\x46\x55\x0d\x22\x06\x77" - "\xd8\xca\x8d\xc8\x87\xc3\xfa\xb9" - "\xe1\x98\x94\xe6\x7b\xed\x65\x66" - "\x0e\xc7\x25\x15\xee\x4a\xe6\x7e" - "\xea\x1b\x58\xee\x96\xa0\x75\x9a" - "\xa3\x00\x9e\x42\xc2\x26\x20\x8c" - "\x3d\x22\x1f\x94\x3e\x74\x43\x72" - "\xe9\x1d\xa6\xa1\x6c\xa7\xb8\x03" - "\xdf\xb9\x7a\xaf\xe9\xe9\x3b\xfe" - "\xdf\x91\xc1\x01\xa8\xba\x5d\x29" - "\xa5\xe0\x98\x9b\x13\xe5\x13\x11" - "\x7c\x04\x3a\xe8\x44\x7e\x78\xfc" - "\xd6\x96\xa8\xbc\x7d\xc1\x89\x3d" - "\x75\x64\xa9\x0e\x86\x33\xfb\x73" - "\xf7\x15\xbc\x2c\x9a\x3f\x29\xce" - "\x1c\x9d\x10\x4e\x85\xe1\x77\x41" - "\x01\xe2\xbc\x88\xec\x81\xef\xc2" - "\x6a\xed\x4f\xf7\xdf\xac\x10\x71" - "\x94\xed\x71\xa4\x01\xd4\xd6\xbe" - "\xfe\x3e\xc3\x92\x6a\xf2\x2b\xb5" - "\xab\x15\x96\xb7\x88\x2c\xc2\xe1" - "\xb0\x04\x22\xe7\x3d\xa9\xc9\x7d" - "\x2c\x7c\x21\xff\x97\x86\x6b\x0c" - "\x2b\x5b\xe0\xb6\x48\x74\x8f\x24" - "\xef\x8e\xdd\x0f\x2a\x5f\xff\x33" - "\xf4\x8e\xc5\xeb\x9c\xd7\x2a\x45" - "\xf3\x50\xf1\xc0\x91\x8f\xc7\xf9" - "\x97\xc1\x3c\x9c\xf4\xed\x8a\x23" - "\x61\x5b\x40\x1a\x09\xee\x23\xa8" - "\x7c\x7a\x96\xe1\x31\x55\x3d\x12" - "\x04\x1f\x21\x78\x72\xf0\x0f\xa5" - "\x80\x58\x7c\x2f\x37\xb5\x67\x24" - "\x2f\xce\xf9\xf6\x86\x9f\xb3\x34" - "\x0c\xfe\x0a\xaf\x27\xe6\x5e\x0a" - "\x21\x44\x68\xe1\x5d\x84\x25\xae" - "\x2c\x5a\x94\x66\x9a\x3f\x0e\x5a" - "\xd0\x60\x2a\xd5\x3a\x4e\x2f\x40" - "\x87\xe9\x27\x3e\xee\x92\xe1\x07" - "\x22\x43\x52\xed\x67\x49\x13\xdd" - "\x68\xd7\x54\xc2\x76\x72\x7e\x75" - "\xaf\x24\x98\x5c\xe8\x22\xaa\x35" - "\x0f\x9a\x1c\x4c\x0b\x43\x68\x99" - "\x45\xdd\xbf\x82\xa5\x6f\x0a\xef" - "\x44\x90\x85\xe7\x57\x23\x22\x41" - "\x2e\xda\x24\x28\x65\x7f\x96\x85" - "\x9f\x4b\x0d\x43\xb9\xa8\xbd\x84" - "\xad\x0b\x09\xcc\x2c\x4a\x0c\xec" - "\x71\x58\xba\xf1\xfc\x49\x4c\xca" - "\x5c\x5d\xb2\x77\x0c\x99\xae\x1c" - "\xce\x70\x05\x5b\x73\x6b\x7c\x28" - "\x3b\xeb\x21\x3f\xa3\x71\xe1\x6a" - "\xf4\x87\xd0\xbf\x73\xaa\x0b\x0b" - "\xed\x70\xb3\xd4\xa3\xca\x76\x3a" - "\xdb\xfa\xd8\x08\x95\xec\xac\x59" - "\xd0\x79\x90\xc2\x33\x7b\xcc\x28" - "\x65\xb6\x5f\x92\xc4\xac\x23\x40" - "\xd1\x20\x44\x1f\xd7\x29\xab\x46" - "\x79\x32\xc6\x8f\x79\xe5\xaa\x2c" - "\xa6\x76\x70\x3a\x9e\x46\x3f\x8c" - "\x1a\x89\x32\x28\x61\x5c\xcf\x93" - "\x1e\xde\x9e\x98\xbe\x06\x30\x23" - "\xc4\x8b\xda\x1c\xd1\x67\x46\x93" - "\x9d\x41\xa2\x8c\x03\x22\xbd\x55" - "\x7e\x91\x51\x13\xdc\xcf\x5c\x1e" - "\xcb\x5d\xfb\x14\x16\x1a\x44\x56" - "\x27\x77\xfd\xed\x7d\xbd\xd1\x49" - "\x7f\x0d\xc3\x59\x48\x6b\x3c\x02" - "\x6b\xb5\xd0\x83\xd5\x81\x29\xe7" - "\xe0\xc9\x36\x23\x8d\x41\x33\x77" - "\xff\x5f\x54\xde\x4d\x3f\xd2\x4e" - "\xb6\x4d\xdd\x85\xf8\x9b\x20\x7d" - "\x39\x27\x68\x63\xd3\x8e\x61\x39" - "\xfa\xe1\xc3\x04\x74\x27\x5a\x34" - "\x7f\xec\x59\x2d\xc5\x6e\x54\x23" - "\xf5\x7b\x4b\xbe\x58\x2b\xf2\x81" - "\x93\x63\xcc\x13\xd9\x90\xbb\x6a" - "\x41\x03\x8d\x95\xeb\xbb\x5d\x06" - "\x38\x4c\x0e\xd6\xa9\x5b\x84\x97" - "\x3e\x64\x72\xe9\x96\x07\x0f\x73" - "\x6e\xc6\x3b\x32\xbe\xac\x13\x14" - "\xd0\x0a\x17\x5f\xb9\x9c\x3e\x34" - "\xd9\xec\xd6\x8f\x89\xbf\x1e\xd3" - "\xda\x80\xb2\x29\xff\x28\x96\xb3" - "\x46\x50\x5b\x15\x80\x97\xee\x1f" - "\x6c\xd8\xe8\xe0\xbd\x09\xe7\x20" - "\x8c\x23\x8e\xd9\xbb\x92\xfa\x82" - "\xaa\x0f\xb5\xf8\x78\x60\x11\xf0", - .ksize = 1088, - .plaintext = "\x0b\xb2\x31\x2d\xad\xfe\xce\xf9" - "\xec\x5d\x3d\x64\x5f\x3f\x75\x43" - "\x05\x5b\x97", - .psize = 19, - .digest = "\x5f\x02\xae\x65\x6c\x13\x21\x67" - "\x77\x9e\xc4\x43\x58\x68\xde\x8f", - }, { - .key = "\x65\x4d\xe3\xf8\xd2\x4c\xac\x28" - "\x68\xf5\xb3\x81\x71\x4b\xa1\xfa" - "\x04\x0e\xd3\x81\x36\xbe\x0c\x81" - "\x5e\xaf\xbc\x3a\xa4\xc0\x8e\x8b" - "\x55\x63\xd3\x52\x97\x88\xd6\x19" - "\xbc\x96\xdf\x49\xff\x04\x63\xf5" - "\x0c\x11\x13\xaa\x9e\x1f\x5a\xf7" - "\xdd\xbd\x37\x80\xc3\xd0\xbe\xa7" - "\x05\xc8\x3c\x98\x1e\x05\x3c\x84" - "\x39\x61\xc4\xed\xed\x71\x1b\xc4" - "\x74\x45\x2c\xa1\x56\x70\x97\xfd" - "\x44\x18\x07\x7d\xca\x60\x1f\x73" - "\x3b\x6d\x21\xcb\x61\x87\x70\x25" - "\x46\x21\xf1\x1f\x21\x91\x31\x2d" - "\x5d\xcc\xb7\xd1\x84\x3e\x3d\xdb" - "\x03\x53\x2a\x82\xa6\x9a\x95\xbc" - "\x1a\x1e\x0a\x5e\x07\x43\xab\x43" - "\xaf\x92\x82\x06\x91\x04\x09\xf4" - "\x17\x0a\x9a\x2c\x54\xdb\xb8\xf4" - "\xd0\xf0\x10\x66\x24\x8d\xcd\xda" - "\xfe\x0e\x45\x9d\x6f\xc4\x4e\xf4" - "\x96\xaf\x13\xdc\xa9\xd4\x8c\xc4" - "\xc8\x57\x39\x3c\xc2\xd3\x0a\x76" - "\x4a\x1f\x75\x83\x44\xc7\xd1\x39" - "\xd8\xb5\x41\xba\x73\x87\xfa\x96" - "\xc7\x18\x53\xfb\x9b\xda\xa0\x97" - "\x1d\xee\x60\x85\x9e\x14\xc3\xce" - "\xc4\x05\x29\x3b\x95\x30\xa3\xd1" - "\x9f\x82\x6a\x04\xf5\xa7\x75\x57" - "\x82\x04\xfe\x71\x51\x71\xb1\x49" - "\x50\xf8\xe0\x96\xf1\xfa\xa8\x88" - "\x3f\xa0\x86\x20\xd4\x60\x79\x59" - "\x17\x2d\xd1\x09\xf4\xec\x05\x57" - "\xcf\x62\x7e\x0e\x7e\x60\x78\xe6" - "\x08\x60\x29\xd8\xd5\x08\x1a\x24" - "\xc4\x6c\x24\xe7\x92\x08\x3d\x8a" - "\x98\x7a\xcf\x99\x0a\x65\x0e\xdc" - "\x8c\x8a\xbe\x92\x82\x91\xcc\x62" - "\x30\xb6\xf4\x3f\xc6\x8a\x7f\x12" - "\x4a\x8a\x49\xfa\x3f\x5c\xd4\x5a" - "\xa6\x82\xa3\xe6\xaa\x34\x76\xb2" - "\xab\x0a\x30\xef\x6c\x77\x58\x3f" - "\x05\x6b\xcc\x5c\xae\xdc\xd7\xb9" - "\x51\x7e\x8d\x32\x5b\x24\x25\xbe" - "\x2b\x24\x01\xcf\x80\xda\x16\xd8" - "\x90\x72\x2c\xad\x34\x8d\x0c\x74" - "\x02\xcb\xfd\xcf\x6e\xef\x97\xb5" - "\x4c\xf2\x68\xca\xde\x43\x9e\x8a" - "\xc5\x5f\x31\x7f\x14\x71\x38\xec" - "\xbd\x98\xe5\x71\xc4\xb5\xdb\xef" - "\x59\xd2\xca\xc0\xc1\x86\x75\x01" - "\xd4\x15\x0d\x6f\xa4\xf7\x7b\x37" - "\x47\xda\x18\x93\x63\xda\xbe\x9e" - "\x07\xfb\xb2\x83\xd5\xc4\x34\x55" - "\xee\x73\xa1\x42\x96\xf9\x66\x41" - "\xa4\xcc\xd2\x93\x6e\xe1\x0a\xbb" - "\xd2\xdd\x18\x23\xe6\x6b\x98\x0b" - "\x8a\x83\x59\x2c\xc3\xa6\x59\x5b" - "\x01\x22\x59\xf7\xdc\xb0\x87\x7e" - "\xdb\x7d\xf4\x71\x41\xab\xbd\xee" - "\x79\xbe\x3c\x01\x76\x0b\x2d\x0a" - "\x42\xc9\x77\x8c\xbb\x54\x95\x60" - "\x43\x2e\xe0\x17\x52\xbd\x90\xc9" - "\xc2\x2c\xdd\x90\x24\x22\x76\x40" - "\x5c\xb9\x41\xc9\xa1\xd5\xbd\xe3" - "\x44\xe0\xa4\xab\xcc\xb8\xe2\x32" - "\x02\x15\x04\x1f\x8c\xec\x5d\x14" - "\xac\x18\xaa\xef\x6e\x33\x19\x6e" - "\xde\xfe\x19\xdb\xeb\x61\xca\x18" - "\xad\xd8\x3d\xbf\x09\x11\xc7\xa5" - "\x86\x0b\x0f\xe5\x3e\xde\xe8\xd9" - "\x0a\x69\x9e\x4c\x20\xff\xf9\xc5" - "\xfa\xf8\xf3\x7f\xa5\x01\x4b\x5e" - "\x0f\xf0\x3b\x68\xf0\x46\x8c\x2a" - "\x7a\xc1\x8f\xa0\xfe\x6a\x5b\x44" - "\x70\x5c\xcc\x92\x2c\x6f\x0f\xbd" - "\x25\x3e\xb7\x8e\x73\x58\xda\xc9" - "\xa5\xaa\x9e\xf3\x9b\xfd\x37\x3e" - "\xe2\x88\xa4\x7b\xc8\x5c\xa8\x93" - "\x0e\xe7\x9a\x9c\x2e\x95\x18\x9f" - "\xc8\x45\x0c\x88\x9e\x53\x4f\x3a" - "\x76\xc1\x35\xfa\x17\xd8\xac\xa0" - "\x0c\x2d\x47\x2e\x4f\x69\x9b\xf7" - "\xd0\xb6\x96\x0c\x19\xb3\x08\x01" - "\x65\x7a\x1f\xc7\x31\x86\xdb\xc8" - "\xc1\x99\x8f\xf8\x08\x4a\x9d\x23" - "\x22\xa8\xcf\x27\x01\x01\x88\x93" - "\x9c\x86\x45\xbd\xe0\x51\xca\x52" - "\x84\xba\xfe\x03\xf7\xda\xc5\xce" - "\x3e\x77\x75\x86\xaf\x84\xc8\x05" - "\x44\x01\x0f\x02\xf3\x58\xb0\x06" - "\x5a\xd7\x12\x30\x8d\xdf\x1f\x1f" - "\x0a\xe6\xd2\xea\xf6\x3a\x7a\x99" - "\x63\xe8\xd2\xc1\x4a\x45\x8b\x40" - "\x4d\x0a\xa9\x76\x92\xb3\xda\x87" - "\x36\x33\xf0\x78\xc3\x2f\x5f\x02" - "\x1a\x6a\x2c\x32\xcd\x76\xbf\xbd" - "\x5a\x26\x20\x28\x8c\x8c\xbc\x52" - "\x3d\x0a\xc9\xcb\xab\xa4\x21\xb0" - "\x54\x40\x81\x44\xc7\xd6\x1c\x11" - "\x44\xc6\x02\x92\x14\x5a\xbf\x1a" - "\x09\x8a\x18\xad\xcd\x64\x3d\x53" - "\x4a\xb6\xa5\x1b\x57\x0e\xef\xe0" - "\x8c\x44\x5f\x7d\xbd\x6c\xfd\x60" - "\xae\x02\x24\xb6\x99\xdd\x8c\xaf" - "\x59\x39\x75\x3c\xd1\x54\x7b\x86" - "\xcc\x99\xd9\x28\x0c\xb0\x94\x62" - "\xf9\x51\xd1\x19\x96\x2d\x66\xf5" - "\x55\xcf\x9e\x59\xe2\x6b\x2c\x08" - "\xc0\x54\x48\x24\x45\xc3\x8c\x73" - "\xea\x27\x6e\x66\x7d\x1d\x0e\x6e" - "\x13\xe8\x56\x65\x3a\xb0\x81\x5c" - "\xf0\xe8\xd8\x00\x6b\xcd\x8f\xad" - "\xdd\x53\xf3\xa4\x6c\x43\xd6\x31" - "\xaf\xd2\x76\x1e\x91\x12\xdb\x3c" - "\x8c\xc2\x81\xf0\x49\xdb\xe2\x6b" - "\x76\x62\x0a\x04\xe4\xaa\x8a\x7c" - "\x08\x0b\x5d\xd0\xee\x1d\xfb\xc4" - "\x02\x75\x42\xd6\xba\xa7\x22\xa8" - "\x47\x29\xb7\x85\x6d\x93\x3a\xdb" - "\x00\x53\x0b\xa2\xeb\xf8\xfe\x01" - "\x6f\x8a\x31\xd6\x17\x05\x6f\x67" - "\x88\x95\x32\xfe\x4f\xa6\x4b\xf8" - "\x03\xe4\xcd\x9a\x18\xe8\x4e\x2d" - "\xf7\x97\x9a\x0c\x7d\x9f\x7e\x44" - "\x69\x51\xe0\x32\x6b\x62\x86\x8f" - "\xa6\x8e\x0b\x21\x96\xe5\xaf\x77" - "\xc0\x83\xdf\xa5\x0e\xd0\xa1\x04" - "\xaf\xc1\x10\xcb\x5a\x40\xe4\xe3" - "\x38\x7e\x07\xe8\x4d\xfa\xed\xc5" - "\xf0\x37\xdf\xbb\x8a\xcf\x3d\xdc" - "\x61\xd2\xc6\x2b\xff\x07\xc9\x2f" - "\x0c\x2d\x5c\x07\xa8\x35\x6a\xfc" - "\xae\x09\x03\x45\x74\x51\x4d\xc4" - "\xb8\x23\x87\x4a\x99\x27\x20\x87" - "\x62\x44\x0a\x4a\xce\x78\x47\x22", - .ksize = 1088, - .plaintext = "\x8e\xb0\x4c\xde\x9c\x4a\x04\x5a" - "\xf6\xa9\x7f\x45\x25\xa5\x7b\x3a" - "\xbc\x4d\x73\x39\x81\xb5\xbd\x3d" - "\x21\x6f\xd7\x37\x50\x3c\x7b\x28" - "\xd1\x03\x3a\x17\xed\x7b\x7c\x2a" - "\x16\xbc\xdf\x19\x89\x52\x71\x31" - "\xb6\xc0\xfd\xb5\xd3\xba\x96\x99" - "\xb6\x34\x0b\xd0\x99\x93\xfc\x1a" - "\x01\x3c\x85\xc6\x9b\x78\x5c\x8b" - "\xfe\xae\xd2\xbf\xb2\x6f\xf9\xed" - "\xc8\x25\x17\xfe\x10\x3b\x7d\xda" - "\xf4\x8d\x35\x4b\x7c\x7b\x82\xe7" - "\xc2\xb3\xee\x60\x4a\x03\x86\xc9" - "\x4e\xb5\xc4\xbe\xd2\xbd\x66\xf1" - "\x13\xf1\x09\xab\x5d\xca\x63\x1f" - "\xfc\xfb\x57\x2a\xfc\xca\x66\xd8" - "\x77\x84\x38\x23\x1d\xac\xd3\xb3" - "\x7a\xad\x4c\x70\xfa\x9c\xc9\x61" - "\xa6\x1b\xba\x33\x4b\x4e\x33\xec" - "\xa0\xa1\x64\x39\x40\x05\x1c\xc2" - "\x3f\x49\x9d\xae\xf2\xc5\xf2\xc5" - "\xfe\xe8\xf4\xc2\xf9\x96\x2d\x28" - "\x92\x30\x44\xbc\xd2\x7f\xe1\x6e" - "\x62\x02\x8f\x3d\x1c\x80\xda\x0e" - "\x6a\x90\x7e\x75\xff\xec\x3e\xc4" - "\xcd\x16\x34\x3b\x05\x6d\x4d\x20" - "\x1c\x7b\xf5\x57\x4f\xfa\x3d\xac" - "\xd0\x13\x55\xe8\xb3\xe1\x1b\x78" - "\x30\xe6\x9f\x84\xd4\x69\xd1\x08" - "\x12\x77\xa7\x4a\xbd\xc0\xf2\xd2" - "\x78\xdd\xa3\x81\x12\xcb\x6c\x14" - "\x90\x61\xe2\x84\xc6\x2b\x16\xcc" - "\x40\x99\x50\x88\x01\x09\x64\x4f" - "\x0a\x80\xbe\x61\xae\x46\xc9\x0a" - "\x5d\xe0\xfb\x72\x7a\x1a\xdd\x61" - "\x63\x20\x05\xa0\x4a\xf0\x60\x69" - "\x7f\x92\xbc\xbf\x4e\x39\x4d\xdd" - "\x74\xd1\xb7\xc0\x5a\x34\xb7\xae" - "\x76\x65\x2e\xbc\x36\xb9\x04\x95" - "\x42\xe9\x6f\xca\x78\xb3\x72\x07" - "\xa3\xba\x02\x94\x67\x4c\xb1\xd7" - "\xe9\x30\x0d\xf0\x3b\xb8\x10\x6d" - "\xea\x2b\x21\xbf\x74\x59\x82\x97" - "\x85\xaa\xf1\xd7\x54\x39\xeb\x05" - "\xbd\xf3\x40\xa0\x97\xe6\x74\xfe" - "\xb4\x82\x5b\xb1\x36\xcb\xe8\x0d" - "\xce\x14\xd9\xdf\xf1\x94\x22\xcd" - "\xd6\x00\xba\x04\x4c\x05\x0c\xc0" - "\xd1\x5a\xeb\x52\xd5\xa8\x8e\xc8" - "\x97\xa1\xaa\xc1\xea\xc1\xbe\x7c" - "\x36\xb3\x36\xa0\xc6\x76\x66\xc5" - "\xe2\xaf\xd6\x5c\xe2\xdb\x2c\xb3" - "\x6c\xb9\x99\x7f\xff\x9f\x03\x24" - "\xe1\x51\x44\x66\xd8\x0c\x5d\x7f" - "\x5c\x85\x22\x2a\xcf\x6d\x79\x28" - "\xab\x98\x01\x72\xfe\x80\x87\x5f" - "\x46\xba\xef\x81\x24\xee\xbf\xb0" - "\x24\x74\xa3\x65\x97\x12\xc4\xaf" - "\x8b\xa0\x39\xda\x8a\x7e\x74\x6e" - "\x1b\x42\xb4\x44\x37\xfc\x59\xfd" - "\x86\xed\xfb\x8c\x66\x33\xda\x63" - "\x75\xeb\xe1\xa4\x85\x4f\x50\x8f" - "\x83\x66\x0d\xd3\x37\xfa\xe6\x9c" - "\x4f\x30\x87\x35\x18\xe3\x0b\xb7" - "\x6e\x64\x54\xcd\x70\xb3\xde\x54" - "\xb7\x1d\xe6\x4c\x4d\x55\x12\x12" - "\xaf\x5f\x7f\x5e\xee\x9d\xe8\x8e" - "\x32\x9d\x4e\x75\xeb\xc6\xdd\xaa" - "\x48\x82\xa4\x3f\x3c\xd7\xd3\xa8" - "\x63\x9e\x64\xfe\xe3\x97\x00\x62" - "\xe5\x40\x5d\xc3\xad\x72\xe1\x28" - "\x18\x50\xb7\x75\xef\xcd\x23\xbf" - "\x3f\xc0\x51\x36\xf8\x41\xc3\x08" - "\xcb\xf1\x8d\x38\x34\xbd\x48\x45" - "\x75\xed\xbc\x65\x7b\xb5\x0c\x9b" - "\xd7\x67\x7d\x27\xb4\xc4\x80\xd7" - "\xa9\xb9\xc7\x4a\x97\xaa\xda\xc8" - "\x3c\x74\xcf\x36\x8f\xe4\x41\xe3" - "\xd4\xd3\x26\xa7\xf3\x23\x9d\x8f" - "\x6c\x20\x05\x32\x3e\xe0\xc3\xc8" - "\x56\x3f\xa7\x09\xb7\xfb\xc7\xf7" - "\xbe\x2a\xdd\x0f\x06\x7b\x0d\xdd" - "\xb0\xb4\x86\x17\xfd\xb9\x04\xe5" - "\xc0\x64\x5d\xad\x2a\x36\x38\xdb" - "\x24\xaf\x5b\xff\xca\xf9\x41\xe8" - "\xf9\x2f\x1e\x5e\xf9\xf5\xd5\xf2" - "\xb2\x88\xca\xc9\xa1\x31\xe2\xe8" - "\x10\x95\x65\xbf\xf1\x11\x61\x7a" - "\x30\x1a\x54\x90\xea\xd2\x30\xf6" - "\xa5\xad\x60\xf9\x4d\x84\x21\x1b" - "\xe4\x42\x22\xc8\x12\x4b\xb0\x58" - "\x3e\x9c\x2d\x32\x95\x0a\x8e\xb0" - "\x0a\x7e\x77\x2f\xe8\x97\x31\x6a" - "\xf5\x59\xb4\x26\xe6\x37\x12\xc9" - "\xcb\xa0\x58\x33\x6f\xd5\x55\x55" - "\x3c\xa1\x33\xb1\x0b\x7e\x2e\xb4" - "\x43\x2a\x84\x39\xf0\x9c\xf4\x69" - "\x4f\x1e\x79\xa6\x15\x1b\x87\xbb" - "\xdb\x9b\xe0\xf1\x0b\xba\xe3\x6e" - "\xcc\x2f\x49\x19\x22\x29\xfc\x71" - "\xbb\x77\x38\x18\x61\xaf\x85\x76" - "\xeb\xd1\x09\xcc\x86\x04\x20\x9a" - "\x66\x53\x2f\x44\x8b\xc6\xa3\xd2" - "\x5f\xc7\x79\x82\x66\xa8\x6e\x75" - "\x7d\x94\xd1\x86\x75\x0f\xa5\x4f" - "\x3c\x7a\x33\xce\xd1\x6e\x9d\x7b" - "\x1f\x91\x37\xb8\x37\x80\xfb\xe0" - "\x52\x26\xd0\x9a\xd4\x48\x02\x41" - "\x05\xe3\x5a\x94\xf1\x65\x61\x19" - "\xb8\x88\x4e\x2b\xea\xba\x8b\x58" - "\x8b\x42\x01\x00\xa8\xfe\x00\x5c" - "\xfe\x1c\xee\x31\x15\x69\xfa\xb3" - "\x9b\x5f\x22\x8e\x0d\x2c\xe3\xa5" - "\x21\xb9\x99\x8a\x8e\x94\x5a\xef" - "\x13\x3e\x99\x96\x79\x6e\xd5\x42" - "\x36\x03\xa9\xe2\xca\x65\x4e\x8a" - "\x8a\x30\xd2\x7d\x74\xe7\xf0\xaa" - "\x23\x26\xdd\xcb\x82\x39\xfc\x9d" - "\x51\x76\x21\x80\xa2\xbe\x93\x03" - "\x47\xb0\xc1\xb6\xdc\x63\xfd\x9f" - "\xca\x9d\xa5\xca\x27\x85\xe2\xd8" - "\x15\x5b\x7e\x14\x7a\xc4\x89\xcc" - "\x74\x14\x4b\x46\xd2\xce\xac\x39" - "\x6b\x6a\x5a\xa4\x0e\xe3\x7b\x15" - "\x94\x4b\x0f\x74\xcb\x0c\x7f\xa9" - "\xbe\x09\x39\xa3\xdd\x56\x5c\xc7" - "\x99\x56\x65\x39\xf4\x0b\x7d\x87" - "\xec\xaa\xe3\x4d\x22\x65\x39\x4e", - .psize = 1024, - .digest = "\x64\x3a\xbc\xc3\x3f\x74\x40\x51" - "\x6e\x56\x01\x1a\x51\xec\x36\xde", - }, { - .key = "\x1b\x82\x2e\x1b\x17\x23\xb9\x6d" - "\xdc\x9c\xda\x99\x07\xe3\x5f\xd8" - "\xd2\xf8\x43\x80\x8d\x86\x7d\x80" - "\x1a\xd0\xcc\x13\xb9\x11\x05\x3f" - "\x7e\xcf\x7e\x80\x0e\xd8\x25\x48" - "\x8b\xaa\x63\x83\x92\xd0\x72\xf5" - "\x4f\x67\x7e\x50\x18\x25\xa4\xd1" - "\xe0\x7e\x1e\xba\xd8\xa7\x6e\xdb" - "\x1a\xcc\x0d\xfe\x9f\x6d\x22\x35" - "\xe1\xe6\xe0\xa8\x7b\x9c\xb1\x66" - "\xa3\xf8\xff\x4d\x90\x84\x28\xbc" - "\xdc\x19\xc7\x91\x49\xfc\xf6\x33" - "\xc9\x6e\x65\x7f\x28\x6f\x68\x2e" - "\xdf\x1a\x75\xe9\xc2\x0c\x96\xb9" - "\x31\x22\xc4\x07\xc6\x0a\x2f\xfd" - "\x36\x06\x5f\x5c\xc5\xb1\x3a\xf4" - "\x5e\x48\xa4\x45\x2b\x88\xa7\xee" - "\xa9\x8b\x52\xcc\x99\xd9\x2f\xb8" - "\xa4\x58\x0a\x13\xeb\x71\x5a\xfa" - "\xe5\x5e\xbe\xf2\x64\xad\x75\xbc" - "\x0b\x5b\x34\x13\x3b\x23\x13\x9a" - "\x69\x30\x1e\x9a\xb8\x03\xb8\x8b" - "\x3e\x46\x18\x6d\x38\xd9\xb3\xd8" - "\xbf\xf1\xd0\x28\xe6\x51\x57\x80" - "\x5e\x99\xfb\xd0\xce\x1e\x83\xf7" - "\xe9\x07\x5a\x63\xa9\xef\xce\xa5" - "\xfb\x3f\x37\x17\xfc\x0b\x37\x0e" - "\xbb\x4b\x21\x62\xb7\x83\x0e\xa9" - "\x9e\xb0\xc4\xad\x47\xbe\x35\xe7" - "\x51\xb2\xf2\xac\x2b\x65\x7b\x48" - "\xe3\x3f\x5f\xb6\x09\x04\x0c\x58" - "\xce\x99\xa9\x15\x2f\x4e\xc1\xf2" - "\x24\x48\xc0\xd8\x6c\xd3\x76\x17" - "\x83\x5d\xe6\xe3\xfd\x01\x8e\xf7" - "\x42\xa5\x04\x29\x30\xdf\xf9\x00" - "\x4a\xdc\x71\x22\x1a\x33\x15\xb6" - "\xd7\x72\xfb\x9a\xb8\xeb\x2b\x38" - "\xea\xa8\x61\xa8\x90\x11\x9d\x73" - "\x2e\x6c\xce\x81\x54\x5a\x9f\xcd" - "\xcf\xd5\xbd\x26\x5d\x66\xdb\xfb" - "\xdc\x1e\x7c\x10\xfe\x58\x82\x10" - "\x16\x24\x01\xce\x67\x55\x51\xd1" - "\xdd\x6b\x44\xa3\x20\x8e\xa9\xa6" - "\x06\xa8\x29\x77\x6e\x00\x38\x5b" - "\xde\x4d\x58\xd8\x1f\x34\xdf\xf9" - "\x2c\xac\x3e\xad\xfb\x92\x0d\x72" - "\x39\xa4\xac\x44\x10\xc0\x43\xc4" - "\xa4\x77\x3b\xfc\xc4\x0d\x37\xd3" - "\x05\x84\xda\x53\x71\xf8\x80\xd3" - "\x34\x44\xdb\x09\xb4\x2b\x8e\xe3" - "\x00\x75\x50\x9e\x43\x22\x00\x0b" - "\x7c\x70\xab\xd4\x41\xf1\x93\xcd" - "\x25\x2d\x84\x74\xb5\xf2\x92\xcd" - "\x0a\x28\xea\x9a\x49\x02\x96\xcb" - "\x85\x9e\x2f\x33\x03\x86\x1d\xdc" - "\x1d\x31\xd5\xfc\x9d\xaa\xc5\xe9" - "\x9a\xc4\x57\xf5\x35\xed\xf4\x4b" - "\x3d\x34\xc2\x29\x13\x86\x36\x42" - "\x5d\xbf\x90\x86\x13\x77\xe5\xc3" - "\x62\xb4\xfe\x0b\x70\x39\x35\x65" - "\x02\xea\xf6\xce\x57\x0c\xbb\x74" - "\x29\xe3\xfd\x60\x90\xfd\x10\x38" - "\xd5\x4e\x86\xbd\x37\x70\xf0\x97" - "\xa6\xab\x3b\x83\x64\x52\xca\x66" - "\x2f\xf9\xa4\xca\x3a\x55\x6b\xb0" - "\xe8\x3a\x34\xdb\x9e\x48\x50\x2f" - "\x3b\xef\xfd\x08\x2d\x5f\xc1\x37" - "\x5d\xbe\x73\xe4\xd8\xe9\xac\xca" - "\x8a\xaa\x48\x7c\x5c\xf4\xa6\x96" - "\x5f\xfa\x70\xa6\xb7\x8b\x50\xcb" - "\xa6\xf5\xa9\xbd\x7b\x75\x4c\x22" - "\x0b\x19\x40\x2e\xc9\x39\x39\x32" - "\x83\x03\xa8\xa4\x98\xe6\x8e\x16" - "\xb9\xde\x08\xc5\xfc\xbf\xad\x39" - "\xa8\xc7\x93\x6c\x6f\x23\xaf\xc1" - "\xab\xe1\xdf\xbb\x39\xae\x93\x29" - "\x0e\x7d\x80\x8d\x3e\x65\xf3\xfd" - "\x96\x06\x65\x90\xa1\x28\x64\x4b" - "\x69\xf9\xa8\x84\x27\x50\xfc\x87" - "\xf7\xbf\x55\x8e\x56\x13\x58\x7b" - "\x85\xb4\x6a\x72\x0f\x40\xf1\x4f" - "\x83\x81\x1f\x76\xde\x15\x64\x7a" - "\x7a\x80\xe4\xc7\x5e\x63\x01\x91" - "\xd7\x6b\xea\x0b\x9b\xa2\x99\x3b" - "\x6c\x88\xd8\xfd\x59\x3c\x8d\x22" - "\x86\x56\xbe\xab\xa1\x37\x08\x01" - "\x50\x85\x69\x29\xee\x9f\xdf\x21" - "\x3e\x20\x20\xf5\xb0\xbb\x6b\xd0" - "\x9c\x41\x38\xec\x54\x6f\x2d\xbd" - "\x0f\xe1\xbd\xf1\x2b\x6e\x60\x56" - "\x29\xe5\x7a\x70\x1c\xe2\xfc\x97" - "\x82\x68\x67\xd9\x3d\x1f\xfb\xd8" - "\x07\x9f\xbf\x96\x74\xba\x6a\x0e" - "\x10\x48\x20\xd8\x13\x1e\xb5\x44" - "\xf2\xcc\xb1\x8b\xfb\xbb\xec\xd7" - "\x37\x70\x1f\x7c\x55\xd2\x4b\xb9" - "\xfd\x70\x5e\xa3\x91\x73\x63\x52" - "\x13\x47\x5a\x06\xfb\x01\x67\xa5" - "\xc0\xd0\x49\x19\x56\x66\x9a\x77" - "\x64\xaf\x8c\x25\x91\x52\x87\x0e" - "\x18\xf3\x5f\x97\xfd\x71\x13\xf8" - "\x05\xa5\x39\xcc\x65\xd3\xcc\x63" - "\x5b\xdb\x5f\x7e\x5f\x6e\xad\xc4" - "\xf4\xa0\xc5\xc2\x2b\x4d\x97\x38" - "\x4f\xbc\xfa\x33\x17\xb4\x47\xb9" - "\x43\x24\x15\x8d\xd2\xed\x80\x68" - "\x84\xdb\x04\x80\xca\x5e\x6a\x35" - "\x2c\x2c\xe7\xc5\x03\x5f\x54\xb0" - "\x5e\x4f\x1d\x40\x54\x3d\x78\x9a" - "\xac\xda\x80\x27\x4d\x15\x4c\x1a" - "\x6e\x80\xc9\xc4\x3b\x84\x0e\xd9" - "\x2e\x93\x01\x8c\xc3\xc8\x91\x4b" - "\xb3\xaa\x07\x04\x68\x5b\x93\xa5" - "\xe7\xc4\x9d\xe7\x07\xee\xf5\x3b" - "\x40\x89\xcc\x60\x34\x9d\xb4\x06" - "\x1b\xef\x92\xe6\xc1\x2a\x7d\x0f" - "\x81\xaa\x56\xe3\xd7\xed\xa7\xd4" - "\xa7\x3a\x49\xc4\xad\x81\x5c\x83" - "\x55\x8e\x91\x54\xb7\x7d\x65\xa5" - "\x06\x16\xd5\x9a\x16\xc1\xb0\xa2" - "\x06\xd8\x98\x47\x73\x7e\x73\xa0" - "\xb8\x23\xb1\x52\xbf\x68\x74\x5d" - "\x0b\xcb\xfa\x8c\x46\xe3\x24\xe6" - "\xab\xd4\x69\x8d\x8c\xf2\x8a\x59" - "\xbe\x48\x46\x50\x8c\x9a\xe8\xe3" - "\x31\x55\x0a\x06\xed\x4f\xf8\xb7" - "\x4f\xe3\x85\x17\x30\xbd\xd5\x20" - "\xe7\x5b\xb2\x32\xcf\x6b\x16\x44" - "\xd2\xf5\x7e\xd7\xd1\x2f\xee\x64" - "\x3e\x9d\x10\xef\x27\x35\x43\x64" - "\x67\xfb\x7a\x7b\xe0\x62\x31\x9a" - "\x4d\xdf\xa5\xab\xc0\x20\xbb\x01" - "\xe9\x7b\x54\xf1\xde\xb2\x79\x50" - "\x6c\x4b\x91\xdb\x7f\xbb\x50\xc1" - "\x55\x44\x38\x9a\xe0\x9f\xe8\x29" - "\x6f\x15\xf8\x4e\xa6\xec\xa0\x60", - .ksize = 1088, - .plaintext = "\x15\x68\x9e\x2f\xad\x15\x52\xdf" - "\xf0\x42\x62\x24\x2a\x2d\xea\xbf" - "\xc7\xf3\xb4\x1a\xf5\xed\xb2\x08" - "\x15\x60\x1c\x00\x77\xbf\x0b\x0e" - "\xb7\x2c\xcf\x32\x3a\xc7\x01\x77" - "\xef\xa6\x75\xd0\x29\xc7\x68\x20" - "\xb2\x92\x25\xbf\x12\x34\xe9\xa4" - "\xfd\x32\x7b\x3f\x7c\xbd\xa5\x02" - "\x38\x41\xde\xc9\xc1\x09\xd9\xfc" - "\x6e\x78\x22\x83\x18\xf7\x50\x8d" - "\x8f\x9c\x2d\x02\xa5\x30\xac\xff" - "\xea\x63\x2e\x80\x37\x83\xb0\x58" - "\xda\x2f\xef\x21\x55\xba\x7b\xb1" - "\xb6\xed\xf5\xd2\x4d\xaa\x8c\xa9" - "\xdd\xdb\x0f\xb4\xce\xc1\x9a\xb1" - "\xc1\xdc\xbd\xab\x86\xc2\xdf\x0b" - "\xe1\x2c\xf9\xbe\xf6\xd8\xda\x62" - "\x72\xdd\x98\x09\x52\xc0\xc4\xb6" - "\x7b\x17\x5c\xf5\xd8\x4b\x88\xd6" - "\x6b\xbf\x84\x4a\x3f\xf5\x4d\xd2" - "\x94\xe2\x9c\xff\xc7\x3c\xd9\xc8" - "\x37\x38\xbc\x8c\xf3\xe7\xb7\xd0" - "\x1d\x78\xc4\x39\x07\xc8\x5e\x79" - "\xb6\x5a\x90\x5b\x6e\x97\xc9\xd4" - "\x82\x9c\xf3\x83\x7a\xe7\x97\xfc" - "\x1d\xbb\xef\xdb\xce\xe0\x82\xad" - "\xca\x07\x6c\x54\x62\x6f\x81\xe6" - "\x7a\x5a\x96\x6e\x80\x3a\xa2\x37" - "\x6f\xc6\xa4\x29\xc3\x9e\x19\x94" - "\x9f\xb0\x3e\x38\xfb\x3c\x2b\x7d" - "\xaa\xb8\x74\xda\x54\x23\x51\x12" - "\x4b\x96\x36\x8f\x91\x4f\x19\x37" - "\x83\xc9\xdd\xc7\x1a\x32\x2d\xab" - "\xc7\x89\xe2\x07\x47\x6c\xe8\xa6" - "\x70\x6b\x8e\x0c\xda\x5c\x6a\x59" - "\x27\x33\x0e\xe1\xe1\x20\xe8\xc8" - "\xae\xdc\xd0\xe3\x6d\xa8\xa6\x06" - "\x41\xb4\xd4\xd4\xcf\x91\x3e\x06" - "\xb0\x9a\xf7\xf1\xaa\xa6\x23\x92" - "\x10\x86\xf0\x94\xd1\x7c\x2e\x07" - "\x30\xfb\xc5\xd8\xf3\x12\xa9\xe8" - "\x22\x1c\x97\x1a\xad\x96\xb0\xa1" - "\x72\x6a\x6b\xb4\xfd\xf7\xe8\xfa" - "\xe2\x74\xd8\x65\x8d\x35\x17\x4b" - "\x00\x23\x5c\x8c\x70\xad\x71\xa2" - "\xca\xc5\x6c\x59\xbf\xb4\xc0\x6d" - "\x86\x98\x3e\x19\x5a\x90\x92\xb1" - "\x66\x57\x6a\x91\x68\x7c\xbc\xf3" - "\xf1\xdb\x94\xf8\x48\xf1\x36\xd8" - "\x78\xac\x1c\xa9\xcc\xd6\x27\xba" - "\x91\x54\x22\xf5\xe6\x05\x3f\xcc" - "\xc2\x8f\x2c\x3b\x2b\xc3\x2b\x2b" - "\x3b\xb8\xb6\x29\xb7\x2f\x94\xb6" - "\x7b\xfc\x94\x3e\xd0\x7a\x41\x59" - "\x7b\x1f\x9a\x09\xa6\xed\x4a\x82" - "\x9d\x34\x1c\xbd\x4e\x1c\x3a\x66" - "\x80\x74\x0e\x9a\x4f\x55\x54\x47" - "\x16\xba\x2a\x0a\x03\x35\x99\xa3" - "\x5c\x63\x8d\xa2\x72\x8b\x17\x15" - "\x68\x39\x73\xeb\xec\xf2\xe8\xf5" - "\x95\x32\x27\xd6\xc4\xfe\xb0\x51" - "\xd5\x0c\x50\xc5\xcd\x6d\x16\xb3" - "\xa3\x1e\x95\x69\xad\x78\x95\x06" - "\xb9\x46\xf2\x6d\x24\x5a\x99\x76" - "\x73\x6a\x91\xa6\xac\x12\xe1\x28" - "\x79\xbc\x08\x4e\x97\x00\x98\x63" - "\x07\x1c\x4e\xd1\x68\xf3\xb3\x81" - "\xa8\xa6\x5f\xf1\x01\xc9\xc1\xaf" - "\x3a\x96\xf9\x9d\xb5\x5a\x5f\x8f" - "\x7e\xc1\x7e\x77\x0a\x40\xc8\x8e" - "\xfc\x0e\xed\xe1\x0d\xb0\xe5\x5e" - "\x5e\x6f\xf5\x7f\xab\x33\x7d\xcd" - "\xf0\x09\x4b\xb2\x11\x37\xdc\x65" - "\x97\x32\x62\x71\x3a\x29\x54\xb9" - "\xc7\xa4\xbf\x75\x0f\xf9\x40\xa9" - "\x8d\xd7\x8b\xa7\xe0\x9a\xbe\x15" - "\xc6\xda\xd8\x00\x14\x69\x1a\xaf" - "\x5f\x79\xc3\xf5\xbb\x6c\x2a\x9d" - "\xdd\x3c\x5f\x97\x21\xe1\x3a\x03" - "\x84\x6a\xe9\x76\x11\x1f\xd3\xd5" - "\xf0\x54\x20\x4d\xc2\x91\xc3\xa4" - "\x36\x25\xbe\x1b\x2a\x06\xb7\xf3" - "\xd1\xd0\x55\x29\x81\x4c\x83\xa3" - "\xa6\x84\x1e\x5c\xd1\xd0\x6c\x90" - "\xa4\x11\xf0\xd7\x63\x6a\x48\x05" - "\xbc\x48\x18\x53\xcd\xb0\x8d\xdb" - "\xdc\xfe\x55\x11\x5c\x51\xb3\xab" - "\xab\x63\x3e\x31\x5a\x8b\x93\x63" - "\x34\xa9\xba\x2b\x69\x1a\xc0\xe3" - "\xcb\x41\xbc\xd7\xf5\x7f\x82\x3e" - "\x01\xa3\x3c\x72\xf4\xfe\xdf\xbe" - "\xb1\x67\x17\x2b\x37\x60\x0d\xca" - "\x6f\xc3\x94\x2c\xd2\x92\x6d\x9d" - "\x75\x18\x77\xaa\x29\x38\x96\xed" - "\x0e\x20\x70\x92\xd5\xd0\xb4\x00" - "\xc0\x31\xf2\xc9\x43\x0e\x75\x1d" - "\x4b\x64\xf2\x1f\xf2\x29\x6c\x7b" - "\x7f\xec\x59\x7d\x8c\x0d\xd4\xd3" - "\xac\x53\x4c\xa3\xde\x42\x92\x95" - "\x6d\xa3\x4f\xd0\xe6\x3d\xe7\xec" - "\x7a\x4d\x68\xf1\xfe\x67\x66\x09" - "\x83\x22\xb1\x98\x43\x8c\xab\xb8" - "\x45\xe6\x6d\xdf\x5e\x50\x71\xce" - "\xf5\x4e\x40\x93\x2b\xfa\x86\x0e" - "\xe8\x30\xbd\x82\xcc\x1c\x9c\x5f" - "\xad\xfd\x08\x31\xbe\x52\xe7\xe6" - "\xf2\x06\x01\x62\x25\x15\x99\x74" - "\x33\x51\x52\x57\x3f\x57\x87\x61" - "\xb9\x7f\x29\x3d\xcd\x92\x5e\xa6" - "\x5c\x3b\xf1\xed\x5f\xeb\x82\xed" - "\x56\x7b\x61\xe7\xfd\x02\x47\x0e" - "\x2a\x15\xa4\xce\x43\x86\x9b\xe1" - "\x2b\x4c\x2a\xd9\x42\x97\xf7\x9a" - "\xe5\x47\x46\x48\xd3\x55\x6f\x4d" - "\xd9\xeb\x4b\xdd\x7b\x21\x2f\xb3" - "\xa8\x36\x28\xdf\xca\xf1\xf6\xd9" - "\x10\xf6\x1c\xfd\x2e\x0c\x27\xe0" - "\x01\xb3\xff\x6d\x47\x08\x4d\xd4" - "\x00\x25\xee\x55\x4a\xe9\xe8\x5b" - "\xd8\xf7\x56\x12\xd4\x50\xb2\xe5" - "\x51\x6f\x34\x63\x69\xd2\x4e\x96" - "\x4e\xbc\x79\xbf\x18\xae\xc6\x13" - "\x80\x92\x77\xb0\xb4\x0f\x29\x94" - "\x6f\x4c\xbb\x53\x11\x36\xc3\x9f" - "\x42\x8e\x96\x8a\x91\xc8\xe9\xfc" - "\xfe\xbf\x7c\x2d\x6f\xf9\xb8\x44" - "\x89\x1b\x09\x53\x0a\x2a\x92\xc3" - "\x54\x7a\x3a\xf9\xe2\xe4\x75\x87" - "\xa0\x5e\x4b\x03\x7a\x0d\x8a\xf4" - "\x55\x59\x94\x2b\x63\x96\x0e\xf5", - .psize = 1040, - .digest = "\xb5\xb9\x08\xb3\x24\x3e\x03\xf0" - "\xd6\x0b\x57\xbc\x0a\x6d\x89\x59", - }, { - .key = "\xf6\x34\x42\x71\x35\x52\x8b\x58" - "\x02\x3a\x8e\x4a\x8d\x41\x13\xe9" - "\x7f\xba\xb9\x55\x9d\x73\x4d\xf8" - "\x3f\x5d\x73\x15\xff\xd3\x9e\x7f" - "\x20\x2a\x6a\xa8\xd1\xf0\x8f\x12" - "\x6b\x02\xd8\x6c\xde\xba\x80\x22" - "\x19\x37\xc8\xd0\x4e\x89\x17\x7c" - "\x7c\xdd\x88\xfd\x41\xc0\x04\xb7" - "\x1d\xac\x19\xe3\x20\xc7\x16\xcf" - "\x58\xee\x1d\x7a\x61\x69\xa9\x12" - "\x4b\xef\x4f\xb6\x38\xdd\x78\xf8" - "\x28\xee\x70\x08\xc7\x7c\xcc\xc8" - "\x1e\x41\xf5\x80\x86\x70\xd0\xf0" - "\xa3\x87\x6b\x0a\x00\xd2\x41\x28" - "\x74\x26\xf1\x24\xf3\xd0\x28\x77" - "\xd7\xcd\xf6\x2d\x61\xf4\xa2\x13" - "\x77\xb4\x6f\xa0\xf4\xfb\xd6\xb5" - "\x38\x9d\x5a\x0c\x51\xaf\xad\x63" - "\x27\x67\x8c\x01\xea\x42\x1a\x66" - "\xda\x16\x7c\x3c\x30\x0c\x66\x53" - "\x1c\x88\xa4\x5c\xb2\xe3\x78\x0a" - "\x13\x05\x6d\xe2\xaf\xb3\xe4\x75" - "\x00\x99\x58\xee\x76\x09\x64\xaa" - "\xbb\x2e\xb1\x81\xec\xd8\x0e\xd3" - "\x0c\x33\x5d\xb7\x98\xef\x36\xb6" - "\xd2\x65\x69\x41\x70\x12\xdc\x25" - "\x41\x03\x99\x81\x41\x19\x62\x13" - "\xd1\x0a\x29\xc5\x8c\xe0\x4c\xf3" - "\xd6\xef\x4c\xf4\x1d\x83\x2e\x6d" - "\x8e\x14\x87\xed\x80\xe0\xaa\xd3" - "\x08\x04\x73\x1a\x84\x40\xf5\x64" - "\xbd\x61\x32\x65\x40\x42\xfb\xb0" - "\x40\xf6\x40\x8d\xc7\x7f\x14\xd0" - "\x83\x99\xaa\x36\x7e\x60\xc6\xbf" - "\x13\x8a\xf9\x21\xe4\x7e\x68\x87" - "\xf3\x33\x86\xb4\xe0\x23\x7e\x0a" - "\x21\xb1\xf5\xad\x67\x3c\x9c\x9d" - "\x09\xab\xaf\x5f\xba\xe0\xd0\x82" - "\x48\x22\x70\xb5\x6d\x53\xd6\x0e" - "\xde\x64\x92\x41\xb0\xd3\xfb\xda" - "\x21\xfe\xab\xea\x20\xc4\x03\x58" - "\x18\x2e\x7d\x2f\x03\xa9\x47\x66" - "\xdf\x7b\xa4\x6b\x34\x6b\x55\x9c" - "\x4f\xd7\x9c\x47\xfb\xa9\x42\xec" - "\x5a\x12\xfd\xfe\x76\xa0\x92\x9d" - "\xfe\x1e\x16\xdd\x24\x2a\xe4\x27" - "\xd5\xa9\xf2\x05\x4f\x83\xa2\xaf" - "\xfe\xee\x83\x7a\xad\xde\xdf\x9a" - "\x80\xd5\x81\x14\x93\x16\x7e\x46" - "\x47\xc2\x14\xef\x49\x6e\xb9\xdb" - "\x40\xe8\x06\x6f\x9c\x2a\xfd\x62" - "\x06\x46\xfd\x15\x1d\x36\x61\x6f" - "\x77\x77\x5e\x64\xce\x78\x1b\x85" - "\xbf\x50\x9a\xfd\x67\xa6\x1a\x65" - "\xad\x5b\x33\x30\xf1\x71\xaa\xd9" - "\x23\x0d\x92\x24\x5f\xae\x57\xb0" - "\x24\x37\x0a\x94\x12\xfb\xb5\xb1" - "\xd3\xb8\x1d\x12\x29\xb0\x80\x24" - "\x2d\x47\x9f\x96\x1f\x95\xf1\xb1" - "\xda\x35\xf6\x29\xe0\xe1\x23\x96" - "\xc7\xe8\x22\x9b\x7c\xac\xf9\x41" - "\x39\x01\xe5\x73\x15\x5e\x99\xec" - "\xb4\xc1\xf4\xe7\xa7\x97\x6a\xd5" - "\x90\x9a\xa0\x1d\xf3\x5a\x8b\x5f" - "\xdf\x01\x52\xa4\x93\x31\x97\xb0" - "\x93\x24\xb5\xbc\xb2\x14\x24\x98" - "\x4a\x8f\x19\x85\xc3\x2d\x0f\x74" - "\x9d\x16\x13\x80\x5e\x59\x62\x62" - "\x25\xe0\xd1\x2f\x64\xef\xba\xac" - "\xcd\x09\x07\x15\x8a\xcf\x73\xb5" - "\x8b\xc9\xd8\x24\xb0\x53\xd5\x6f" - "\xe1\x2b\x77\xb1\xc5\xe4\xa7\x0e" - "\x18\x45\xab\x36\x03\x59\xa8\xbd" - "\x43\xf0\xd8\x2c\x1a\x69\x96\xbb" - "\x13\xdf\x6c\x33\x77\xdf\x25\x34" - "\x5b\xa5\x5b\x8c\xf9\x51\x05\xd4" - "\x8b\x8b\x44\x87\x49\xfc\xa0\x8f" - "\x45\x15\x5b\x40\x42\xc4\x09\x92" - "\x98\x0c\x4d\xf4\x26\x37\x1b\x13" - "\x76\x01\x93\x8d\x4f\xe6\xed\x18" - "\xd0\x79\x7b\x3f\x44\x50\xcb\xee" - "\xf7\x4a\xc9\x9e\xe0\x96\x74\xa7" - "\xe6\x93\xb2\x53\xca\x55\xa8\xdc" - "\x1e\x68\x07\x87\xb7\x2e\xc1\x08" - "\xb2\xa4\x5b\xaf\xc6\xdb\x5c\x66" - "\x41\x1c\x51\xd9\xb0\x07\x00\x0d" - "\xf0\x4c\xdc\x93\xde\xa9\x1e\x8e" - "\xd3\x22\x62\xd8\x8b\x88\x2c\xea" - "\x5e\xf1\x6e\x14\x40\xc7\xbe\xaa" - "\x42\x28\xd0\x26\x30\x78\x01\x9b" - "\x83\x07\xbc\x94\xc7\x57\xa2\x9f" - "\x03\x07\xff\x16\xff\x3c\x6e\x48" - "\x0a\xd0\xdd\x4c\xf6\x64\x9a\xf1" - "\xcd\x30\x12\x82\x2c\x38\xd3\x26" - "\x83\xdb\xab\x3e\xc6\xf8\xe6\xfa" - "\x77\x0a\x78\x82\x75\xf8\x63\x51" - "\x59\xd0\x8d\x24\x9f\x25\xe6\xa3" - "\x4c\xbc\x34\xfc\xe3\x10\xc7\x62" - "\xd4\x23\xc8\x3d\xa7\xc6\xa6\x0a" - "\x4f\x7e\x29\x9d\x6d\xbe\xb5\xf1" - "\xdf\xa4\x53\xfa\xc0\x23\x0f\x37" - "\x84\x68\xd0\xb5\xc8\xc6\xae\xf8" - "\xb7\x8d\xb3\x16\xfe\x8f\x87\xad" - "\xd0\xc1\x08\xee\x12\x1c\x9b\x1d" - "\x90\xf8\xd1\x63\xa4\x92\x3c\xf0" - "\xc7\x34\xd8\xf1\x14\xed\xa3\xbc" - "\x17\x7e\xd4\x62\x42\x54\x57\x2c" - "\x3e\x7a\x35\x35\x17\x0f\x0b\x7f" - "\x81\xa1\x3f\xd0\xcd\xc8\x3b\x96" - "\xe9\xe0\x4a\x04\xe1\xb6\x3c\xa1" - "\xd6\xca\xc4\xbd\xb6\xb5\x95\x34" - "\x12\x9d\xc5\x96\xf2\xdf\xba\x54" - "\x76\xd1\xb2\x6b\x3b\x39\xe0\xb9" - "\x18\x62\xfb\xf7\xfc\x12\xf1\x5f" - "\x7e\xc7\xe3\x59\x4c\xa6\xc2\x3d" - "\x40\x15\xf9\xa3\x95\x64\x4c\x74" - "\x8b\x73\x77\x33\x07\xa7\x04\x1d" - "\x33\x5a\x7e\x8f\xbd\x86\x01\x4f" - "\x3e\xb9\x27\x6f\xe2\x41\xf7\x09" - "\x67\xfd\x29\x28\xc5\xe4\xf6\x18" - "\x4c\x1b\x49\xb2\x9c\x5b\xf6\x81" - "\x4f\xbb\x5c\xcc\x0b\xdf\x84\x23" - "\x58\xd6\x28\x34\x93\x3a\x25\x97" - "\xdf\xb2\xc3\x9e\x97\x38\x0b\x7d" - "\x10\xb3\x54\x35\x23\x8c\x64\xee" - "\xf0\xd8\x66\xff\x8b\x22\xd2\x5b" - "\x05\x16\x3c\x89\xf7\xb1\x75\xaf" - "\xc0\xae\x6a\x4f\x3f\xaf\x9a\xf4" - "\xf4\x9a\x24\xd9\x80\x82\xc0\x12" - "\xde\x96\xd1\xbe\x15\x0b\x8d\x6a" - "\xd7\x12\xe4\x85\x9f\x83\xc9\xc3" - "\xff\x0b\xb5\xaf\x3b\xd8\x6d\x67" - "\x81\x45\xe6\xac\xec\xc1\x7b\x16" - "\x18\x0a\xce\x4b\xc0\x2e\x76\xbc" - "\x1b\xfa\xb4\x34\xb8\xfc\x3e\xc8" - "\x5d\x90\x71\x6d\x7a\x79\xef\x06", - .ksize = 1088, - .plaintext = "\xaa\x5d\x54\xcb\xea\x1e\x46\x0f" - "\x45\x87\x70\x51\x8a\x66\x7a\x33" - "\xb4\x18\xff\xa9\x82\xf9\x45\x4b" - "\x93\xae\x2e\x7f\xab\x98\xfe\xbf" - "\x01\xee\xe5\xa0\x37\x8f\x57\xa6" - "\xb0\x76\x0d\xa4\xd6\x28\x2b\x5d" - "\xe1\x03\xd6\x1c\x6f\x34\x0d\xe7" - "\x61\x2d\x2e\xe5\xae\x5d\x47\xc7" - "\x80\x4b\x18\x8f\xa8\x99\xbc\x28" - "\xed\x1d\x9d\x86\x7d\xd7\x41\xd1" - "\xe0\x2b\xe1\x8c\x93\x2a\xa7\x80" - "\xe1\x07\xa0\xa9\x9f\x8c\x8d\x1a" - "\x55\xfc\x6b\x24\x7a\xbd\x3e\x51" - "\x68\x4b\x26\x59\xc8\xa7\x16\xd9" - "\xb9\x61\x13\xde\x8b\x63\x1c\xf6" - "\x60\x01\xfb\x08\xb3\x5b\x0a\xbf" - "\x34\x73\xda\x87\x87\x3d\x6f\x97" - "\x4a\x0c\xa3\x58\x20\xa2\xc0\x81" - "\x5b\x8c\xef\xa9\xc2\x01\x1e\x64" - "\x83\x8c\xbc\x03\xb6\xd0\x29\x9f" - "\x54\xe2\xce\x8b\xc2\x07\x85\x78" - "\x25\x38\x96\x4c\xb4\xbe\x17\x4a" - "\x65\xa6\xfa\x52\x9d\x66\x9d\x65" - "\x4a\xd1\x01\x01\xf0\xcb\x13\xcc" - "\xa5\x82\xf3\xf2\x66\xcd\x3f\x9d" - "\xd1\xaa\xe4\x67\xea\xf2\xad\x88" - "\x56\x76\xa7\x9b\x59\x3c\xb1\x5d" - "\x78\xfd\x69\x79\x74\x78\x43\x26" - "\x7b\xde\x3f\xf1\xf5\x4e\x14\xd9" - "\x15\xf5\x75\xb5\x2e\x19\xf3\x0c" - "\x48\x72\xd6\x71\x6d\x03\x6e\xaa" - "\xa7\x08\xf9\xaa\x70\xa3\x0f\x4d" - "\x12\x8a\xdd\xe3\x39\x73\x7e\xa7" - "\xea\x1f\x6d\x06\x26\x2a\xf2\xc5" - "\x52\xb4\xbf\xfd\x52\x0c\x06\x60" - "\x90\xd1\xb2\x7b\x56\xae\xac\x58" - "\x5a\x6b\x50\x2a\xf5\xe0\x30\x3c" - "\x2a\x98\x0f\x1b\x5b\x0a\x84\x6c" - "\x31\xae\x92\xe2\xd4\xbb\x7f\x59" - "\x26\x10\xb9\x89\x37\x68\x26\xbf" - "\x41\xc8\x49\xc4\x70\x35\x7d\xff" - "\x2d\x7f\xf6\x8a\x93\x68\x8c\x78" - "\x0d\x53\xce\x7d\xff\x7d\xfb\xae" - "\x13\x1b\x75\xc4\x78\xd7\x71\xd8" - "\xea\xd3\xf4\x9d\x95\x64\x8e\xb4" - "\xde\xb8\xe4\xa6\x68\xc8\xae\x73" - "\x58\xaf\xa8\xb0\x5a\x20\xde\x87" - "\x43\xb9\x0f\xe3\xad\x41\x4b\xd5" - "\xb7\xad\x16\x00\xa6\xff\xf6\x74" - "\xbf\x8c\x9f\xb3\x58\x1b\xb6\x55" - "\xa9\x90\x56\x28\xf0\xb5\x13\x4e" - "\x9e\xf7\x25\x86\xe0\x07\x7b\x98" - "\xd8\x60\x5d\x38\x95\x3c\xe4\x22" - "\x16\x2f\xb2\xa2\xaf\xe8\x90\x17" - "\xec\x11\x83\x1a\xf4\xa9\x26\xda" - "\x39\x72\xf5\x94\x61\x05\x51\xec" - "\xa8\x30\x8b\x2c\x13\xd0\x72\xac" - "\xb9\xd2\xa0\x4c\x4b\x78\xe8\x6e" - "\x04\x85\xe9\x04\x49\x82\x91\xff" - "\x89\xe5\xab\x4c\xaa\x37\x03\x12" - "\xca\x8b\x74\x10\xfd\x9e\xd9\x7b" - "\xcb\xdb\x82\x6e\xce\x2e\x33\x39" - "\xce\xd2\x84\x6e\x34\x71\x51\x6e" - "\x0d\xd6\x01\x87\xc7\xfa\x0a\xd3" - "\xad\x36\xf3\x4c\x9f\x96\x5e\x62" - "\x62\x54\xc3\x03\x78\xd6\xab\xdd" - "\x89\x73\x55\x25\x30\xf8\xa7\xe6" - "\x4f\x11\x0c\x7c\x0a\xa1\x2b\x7b" - "\x3d\x0d\xde\x81\xd4\x9d\x0b\xae" - "\xdf\x00\xf9\x4c\xb6\x90\x8e\x16" - "\xcb\x11\xc8\xd1\x2e\x73\x13\x75" - "\x75\x3e\xaa\xf5\xee\x02\xb3\x18" - "\xa6\x2d\xf5\x3b\x51\xd1\x1f\x47" - "\x6b\x2c\xdb\xc4\x10\xe0\xc8\xba" - "\x9d\xac\xb1\x9d\x75\xd5\x41\x0e" - "\x7e\xbe\x18\x5b\xa4\x1f\xf8\x22" - "\x4c\xc1\x68\xda\x6d\x51\x34\x6c" - "\x19\x59\xec\xb5\xb1\xec\xa7\x03" - "\xca\x54\x99\x63\x05\x6c\xb1\xac" - "\x9c\x31\xd6\xdb\xba\x7b\x14\x12" - "\x7a\xc3\x2f\xbf\x8d\xdc\x37\x46" - "\xdb\xd2\xbc\xd4\x2f\xab\x30\xd5" - "\xed\x34\x99\x8e\x83\x3e\xbe\x4c" - "\x86\x79\x58\xe0\x33\x8d\x9a\xb8" - "\xa9\xa6\x90\x46\xa2\x02\xb8\xdd" - "\xf5\xf9\x1a\x5c\x8c\x01\xaa\x6e" - "\xb4\x22\x12\xf5\x0c\x1b\x9b\x7a" - "\xc3\x80\xf3\x06\x00\x5f\x30\xd5" - "\x06\xdb\x7d\x82\xc2\xd4\x0b\x4c" - "\x5f\xe9\xc5\xf5\xdf\x97\x12\xbf" - "\x56\xaf\x9b\x69\xcd\xee\x30\xb4" - "\xa8\x71\xff\x3e\x7d\x73\x7a\xb4" - "\x0d\xa5\x46\x7a\xf3\xf4\x15\x87" - "\x5d\x93\x2b\x8c\x37\x64\xb5\xdd" - "\x48\xd1\xe5\x8c\xae\xd4\xf1\x76" - "\xda\xf4\xba\x9e\x25\x0e\xad\xa3" - "\x0d\x08\x7c\xa8\x82\x16\x8d\x90" - "\x56\x40\x16\x84\xe7\x22\x53\x3a" - "\x58\xbc\xb9\x8f\x33\xc8\xc2\x84" - "\x22\xe6\x0d\xe7\xb3\xdc\x5d\xdf" - "\xd7\x2a\x36\xe4\x16\x06\x07\xd2" - "\x97\x60\xb2\xf5\x5e\x14\xc9\xfd" - "\x8b\x05\xd1\xce\xee\x9a\x65\x99" - "\xb7\xae\x19\xb7\xc8\xbc\xd5\xa2" - "\x7b\x95\xe1\xcc\xba\x0d\xdc\x8a" - "\x1d\x59\x52\x50\xaa\x16\x02\x82" - "\xdf\x61\x33\x2e\x44\xce\x49\xc7" - "\xe5\xc6\x2e\x76\xcf\x80\x52\xf0" - "\x3d\x17\x34\x47\x3f\xd3\x80\x48" - "\xa2\xba\xd5\xc7\x7b\x02\x28\xdb" - "\xac\x44\xc7\x6e\x05\x5c\xc2\x79" - "\xb3\x7d\x6a\x47\x77\x66\xf1\x38" - "\xf0\xf5\x4f\x27\x1a\x31\xca\x6c" - "\x72\x95\x92\x8e\x3f\xb0\xec\x1d" - "\xc7\x2a\xff\x73\xee\xdf\x55\x80" - "\x93\xd2\xbd\x34\xd3\x9f\x00\x51" - "\xfb\x2e\x41\xba\x6c\x5a\x7c\x17" - "\x7f\xe6\x70\xac\x8d\x39\x3f\x77" - "\xe2\x23\xac\x8f\x72\x4e\xe4\x53" - "\xcc\xf1\x1b\xf1\x35\xfe\x52\xa4" - "\xd6\xb8\x40\x6b\xc1\xfd\xa0\xa1" - "\xf5\x46\x65\xc2\x50\xbb\x43\xe2" - "\xd1\x43\x28\x34\x74\xf5\x87\xa0" - "\xf2\x5e\x27\x3b\x59\x2b\x3e\x49" - "\xdf\x46\xee\xaf\x71\xd7\x32\x36" - "\xc7\x14\x0b\x58\x6e\x3e\x2d\x41" - "\xfa\x75\x66\x3a\x54\xe0\xb2\xb9" - "\xaf\xdd\x04\x80\x15\x19\x3f\x6f" - "\xce\x12\xb4\xd8\xe8\x89\x3c\x05" - "\x30\xeb\xf3\x3d\xcd\x27\xec\xdc" - "\x56\x70\x12\xcf\x78\x2b\x77\xbf" - "\x22\xf0\x1b\x17\x9c\xcc\xd6\x1b" - "\x2d\x3d\xa0\x3b\xd8\xc9\x70\xa4" - "\x7a\x3e\x07\xb9\x06\xc3\xfa\xb0" - "\x33\xee\xc1\xd8\xf6\xe0\xf0\xb2" - "\x61\x12\x69\xb0\x5f\x28\x99\xda" - "\xc3\x61\x48\xfa\x07\x16\x03\xc4" - "\xa8\xe1\x3c\xe8\x0e\x64\x15\x30" - "\xc1\x9d\x84\x2f\x73\x98\x0e\x3a" - "\xf2\x86\x21\xa4\x9e\x1d\xb5\x86" - "\x16\xdb\x2b\x9a\x06\x64\x8e\x79" - "\x8d\x76\x3e\xc3\xc2\x64\x44\xe3" - "\xda\xbc\x1a\x52\xd7\x61\x03\x65" - "\x54\x32\x77\x01\xed\x9d\x8a\x43" - "\x25\x24\xe3\xc1\xbe\xb8\x2f\xcb" - "\x89\x14\x64\xab\xf6\xa0\x6e\x02" - "\x57\xe4\x7d\xa9\x4e\x9a\x03\x36" - "\xad\xf1\xb1\xfc\x0b\xe6\x79\x51" - "\x9f\x81\x77\xc4\x14\x78\x9d\xbf" - "\xb6\xd6\xa3\x8c\xba\x0b\x26\xe7" - "\xc8\xb9\x5c\xcc\xe1\x5f\xd5\xc6" - "\xc4\xca\xc2\xa3\x45\xba\x94\x13" - "\xb2\x8f\xc3\x54\x01\x09\xe7\x8b" - "\xda\x2a\x0a\x11\x02\x43\xcb\x57" - "\xc9\xcc\xb5\x5c\xab\xc4\xec\x54" - "\x00\x06\x34\xe1\x6e\x03\x89\x7c" - "\xc6\xfb\x6a\xc7\x60\x43\xd6\xc5" - "\xb5\x68\x72\x89\x8f\x42\xc3\x74" - "\xbd\x25\xaa\x9f\x67\xb5\xdf\x26" - "\x20\xe8\xb7\x01\x3c\xe4\x77\xce" - "\xc4\x65\xa7\x23\x79\xea\x33\xc7" - "\x82\x14\x5c\x82\xf2\x4e\x3d\xf6" - "\xc6\x4a\x0e\x29\xbb\xec\x44\xcd" - "\x2f\xd1\x4f\x21\x71\xa9\xce\x0f" - "\x5c\xf2\x72\x5c\x08\x2e\x21\xd2" - "\xc3\x29\x13\xd8\xac\xc3\xda\x13" - "\x1a\x9d\xa7\x71\x1d\x27\x1d\x27" - "\x1d\xea\xab\x44\x79\xad\xe5\xeb" - "\xef\x1f\x22\x0a\x44\x4f\xcb\x87" - "\xa7\x58\x71\x0e\x66\xf8\x60\xbf" - "\x60\x74\x4a\xb4\xec\x2e\xfe\xd3" - "\xf5\xb8\xfe\x46\x08\x50\x99\x6c" - "\x66\xa5\xa8\x34\x44\xb5\xe5\xf0" - "\xdd\x2c\x67\x4e\x35\x96\x8e\x67" - "\x48\x3f\x5f\x37\x44\x60\x51\x2e" - "\x14\x91\x5e\x57\xc3\x0e\x79\x77" - "\x2f\x03\xf4\xe2\x1c\x72\xbf\x85" - "\x5d\xd3\x17\xdf\x6c\xc5\x70\x24" - "\x42\xdf\x51\x4e\x2a\xb2\xd2\x5b" - "\x9e\x69\x83\x41\x11\xfe\x73\x22" - "\xde\x8a\x9e\xd8\x8a\xfb\x20\x38" - "\xd8\x47\x6f\xd5\xed\x8f\x41\xfd" - "\x13\x7a\x18\x03\x7d\x0f\xcd\x7d" - "\xa6\x7d\x31\x9e\xf1\x8f\x30\xa3" - "\x8b\x4c\x24\xb7\xf5\x48\xd7\xd9" - "\x12\xe7\x84\x97\x5c\x31\x6d\xfb" - "\xdf\xf3\xd3\xd1\xd5\x0c\x30\x06" - "\x01\x6a\xbc\x6c\x78\x7b\xa6\x50" - "\xfa\x0f\x3c\x42\x2d\xa5\xa3\x3b" - "\xcf\x62\x50\xff\x71\x6d\xe7\xda" - "\x27\xab\xc6\x67\x16\x65\x68\x64" - "\xc7\xd5\x5f\x81\xa9\xf6\x65\xb3" - "\x5e\x43\x91\x16\xcd\x3d\x55\x37" - "\x55\xb3\xf0\x28\xc5\x54\x19\xc0" - "\xe0\xd6\x2a\x61\xd4\xc8\x72\x51" - "\xe9\xa1\x7b\x48\x21\xad\x44\x09" - "\xe4\x01\x61\x3c\x8a\x5b\xf9\xa1" - "\x6e\x1b\xdf\xc0\x04\xa8\x8b\xf2" - "\x21\xbe\x34\x7b\xfc\xa1\xcd\xc9" - "\xa9\x96\xf4\xa4\x4c\xf7\x4e\x8f" - "\x84\xcc\xd3\xa8\x92\x77\x8f\x36" - "\xe2\x2e\x8c\x33\xe8\x84\xa6\x0c" - "\x6c\x8a\xda\x14\x32\xc2\x96\xff" - "\xc6\x4a\xc2\x9b\x30\x7f\xd1\x29" - "\xc0\xd5\x78\x41\x00\x80\x80\x03" - "\x2a\xb1\xde\x26\x03\x48\x49\xee" - "\x57\x14\x76\x51\x3c\x36\x5d\x0a" - "\x5c\x9f\xe8\xd8\x53\xdb\x4f\xd4" - "\x38\xbf\x66\xc9\x75\x12\x18\x75" - "\x34\x2d\x93\x22\x96\x51\x24\x6e" - "\x4e\xd9\x30\xea\x67\xff\x92\x1c" - "\x16\x26\xe9\xb5\x33\xab\x8c\x22" - "\x47\xdb\xa0\x2c\x08\xf0\x12\x69" - "\x7e\x93\x52\xda\xa5\xe5\xca\xc1" - "\x0f\x55\x2a\xbd\x09\x30\x88\x1b" - "\x9c\xc6\x9f\xe6\xdb\xa6\x92\xeb" - "\xf4\xbd\x5c\xc4\xdb\xc6\x71\x09" - "\xab\x5e\x48\x0c\xed\x6f\xda\x8e" - "\x8d\x0c\x98\x71\x7d\x10\xd0\x9c" - "\x20\x9b\x79\x53\x26\x5d\xb9\x85" - "\x8a\x31\xb8\xc5\x1c\x97\xde\x88" - "\x61\x55\x7f\x7c\x21\x06\xea\xc4" - "\x5f\xaf\xf2\xf0\xd5\x5e\x7d\xb4" - "\x6e\xcf\xe9\xae\x1b\x0e\x11\x80" - "\xc1\x9a\x74\x7e\x52\x6f\xa0\xb7" - "\x24\xcd\x8d\x0a\x11\x40\x63\x72" - "\xfa\xe2\xc5\xb3\x94\xef\x29\xa2" - "\x1a\x23\x43\x04\x37\x55\x0d\xe9" - "\x83\xb2\x29\x51\x49\x64\xa0\xbd" - "\xde\x73\xfd\xa5\x7c\x95\x70\x62" - "\x58\xdc\xe2\xd0\xbf\x98\xf5\x8a" - "\x6a\xfd\xce\xa8\x0e\x42\x2a\xeb" - "\xd2\xff\x83\x27\x53\x5c\xa0\x6e" - "\x93\xef\xe2\xb9\x5d\x35\xd6\x98" - "\xf6\x71\x19\x7a\x54\xa1\xa7\xe8" - "\x09\xfe\xf6\x9e\xc7\xbd\x3e\x29" - "\xbd\x6b\x17\xf4\xe7\x3e\x10\x5c" - "\xc1\xd2\x59\x4f\x4b\x12\x1a\x5b" - "\x50\x80\x59\xb9\xec\x13\x66\xa8" - "\xd2\x31\x7b\x6a\x61\x22\xdd\x7d" - "\x61\xee\x87\x16\x46\x9f\xf9\xc7" - "\x41\xee\x74\xf8\xd0\x96\x2c\x76" - "\x2a\xac\x7d\x6e\x9f\x0e\x7f\x95" - "\xfe\x50\x16\xb2\x23\xca\x62\xd5" - "\x68\xcf\x07\x3f\x3f\x97\x85\x2a" - "\x0c\x25\x45\xba\xdb\x32\xcb\x83" - "\x8c\x4f\xe0\x6d\x9a\x99\xf9\xc9" - "\xda\xd4\x19\x31\xc1\x7c\x6d\xd9" - "\x9c\x56\xd3\xec\xc1\x81\x4c\xed" - "\x28\x9d\x87\xeb\x19\xd7\x1a\x4f" - "\x04\x6a\xcb\x1f\xcf\x1f\xa2\x16" - "\xfc\x2a\x0d\xa1\x14\x2d\xfa\xc5" - "\x5a\xd2\xc5\xf9\x19\x7c\x20\x1f" - "\x2d\x10\xc0\x66\x7c\xd9\x2d\xe5" - "\x88\x70\x59\xa7\x85\xd5\x2e\x7c" - "\x5c\xe3\xb7\x12\xd6\x97\x3f\x29", - .psize = 2048, - .digest = "\x37\x90\x92\xc2\xeb\x01\x87\xd9" - "\x95\xc7\x91\xc3\x17\x8b\x38\x52", - } -}; - - /* * DES test vectors. */ From 0d8e6c0a1178cbe88e38113bf2a4277b4b21a76f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 10 Dec 2025 17:18:44 -0800 Subject: [PATCH 14/53] fscrypt: Drop obsolete recommendation to enable optimized NHPoly1305 CONFIG_CRYPTO_NHPOLY1305_NEON, CONFIG_CRYPTO_NHPOLY1305_SSE2, and CONFIG_CRYPTO_NHPOLY1305_AVX2 no longer exist. The equivalent optimizations are now just enabled automatically when Adiantum support is enabled. Update the fscrypt documentation accordingly. Link: https://lore.kernel.org/r/20251211011846.8179-13-ebiggers@kernel.org Signed-off-by: Eric Biggers --- Documentation/filesystems/fscrypt.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst index 70af896822e1..c0dd35f1af12 100644 --- a/Documentation/filesystems/fscrypt.rst +++ b/Documentation/filesystems/fscrypt.rst @@ -455,11 +455,6 @@ API, but the filenames mode still does. - Adiantum - Mandatory: - CONFIG_CRYPTO_ADIANTUM - - Recommended: - - arm32: CONFIG_CRYPTO_NHPOLY1305_NEON - - arm64: CONFIG_CRYPTO_NHPOLY1305_NEON - - x86: CONFIG_CRYPTO_NHPOLY1305_SSE2 - - x86: CONFIG_CRYPTO_NHPOLY1305_AVX2 - AES-128-CBC-ESSIV and AES-128-CBC-CTS: - Mandatory: From c8bf0b969d274036e82381818630eb8651c294f2 Mon Sep 17 00:00:00 2001 From: "Rusydi H. Makarim" Date: Sun, 14 Dec 2025 18:15:12 +0700 Subject: [PATCH 15/53] lib/crypto: md5: Use rol32() instead of open-coding it For the bitwise left rotation in MD5STEP, use rol32() from instead of open-coding it. Signed-off-by: Rusydi H. Makarim Link: https://lore.kernel.org/r/20251214-rol32_in_md5-v1-1-20f5f11a92b2@kriptograf.id Signed-off-by: Eric Biggers --- lib/crypto/md5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/crypto/md5.c b/lib/crypto/md5.c index c0610ea1370e..c4af57db0ea8 100644 --- a/lib/crypto/md5.c +++ b/lib/crypto/md5.c @@ -29,7 +29,7 @@ static const struct md5_block_state md5_iv = { #define F4(x, y, z) (y ^ (x | ~z)) #define MD5STEP(f, w, x, y, z, in, s) \ - (w += f(x, y, z) + in, w = (w << s | w >> (32 - s)) + x) + (w += f(x, y, z) + in, w = rol32(w, s) + x) static void md5_block_generic(struct md5_block_state *state, const u8 data[MD5_BLOCK_SIZE]) From 0d92c555320ad34e67523063e32630cfad13af5f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 4 Jan 2026 21:36:52 -0800 Subject: [PATCH 16/53] lib/crypto: nh: Restore dependency of arch code on !KMSAN Since the architecture-specific implementations of NH initialize memory in assembly code, they aren't compatible with KMSAN as-is. Fixes: 382de740759a ("lib/crypto: nh: Add NH library") Link: https://lore.kernel.org/r/20260105053652.1708299-1-ebiggers@kernel.org Signed-off-by: Eric Biggers --- lib/crypto/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 33cf46bbadc8..781a42c5c572 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -116,7 +116,7 @@ config CRYPTO_LIB_NH config CRYPTO_LIB_NH_ARCH bool - depends on CRYPTO_LIB_NH && !UML + depends on CRYPTO_LIB_NH && !UML && !KMSAN default y if ARM && KERNEL_MODE_NEON default y if ARM64 && KERNEL_MODE_NEON default y if X86_64 From 959a634ebcda02e0add101024a5793323d66cda5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 6 Jan 2026 20:42:15 -0800 Subject: [PATCH 17/53] lib/crypto: mldsa: Add FIPS cryptographic algorithm self-test Since ML-DSA is FIPS-approved, add the boot-time self-test which is apparently required. Just add a test vector manually for now, borrowed from lib/crypto/tests/mldsa-testvecs.h (where in turn it's borrowed from leancrypto). The SHA-* FIPS test vectors are generated by scripts/crypto/gen-fips-testvecs.py instead, but the common Python libraries don't support ML-DSA yet. Acked-by: Ard Biesheuvel Reviewed-by: David Howells Link: https://lore.kernel.org/r/20260107044215.109930-1-ebiggers@kernel.org Signed-off-by: Eric Biggers --- lib/crypto/fips-mldsa.h | 458 ++++++++++++++++++++++++++++++++++++++++ lib/crypto/mldsa.c | 31 +++ 2 files changed, 489 insertions(+) create mode 100644 lib/crypto/fips-mldsa.h diff --git a/lib/crypto/fips-mldsa.h b/lib/crypto/fips-mldsa.h new file mode 100644 index 000000000000..1b9a60a59e68 --- /dev/null +++ b/lib/crypto/fips-mldsa.h @@ -0,0 +1,458 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* ML-DSA test vector extracted from leancrypto */ + +#include + +static const u8 fips_test_mldsa65_signature[] __initconst __maybe_unused = { + 0xda, 0xcf, 0x8d, 0x67, 0x59, 0x60, 0x6c, 0x39, 0x2d, 0x89, 0xb6, 0xa1, + 0xf3, 0x8c, 0x70, 0xcf, 0x25, 0x86, 0x21, 0xa1, 0x9f, 0x20, 0x9e, 0xf5, + 0xd2, 0xdd, 0xbd, 0x99, 0xfa, 0xe4, 0xab, 0x77, 0x31, 0x65, 0x18, 0xa1, + 0xd1, 0x3f, 0x21, 0x70, 0x36, 0xe1, 0xf9, 0x5c, 0x28, 0xb6, 0x7d, 0x34, + 0xae, 0x66, 0xc9, 0x1c, 0x8e, 0xc6, 0xf9, 0x45, 0x8c, 0xa9, 0xb2, 0xfb, + 0x0f, 0x5b, 0xb8, 0xf9, 0xf5, 0xe2, 0x37, 0x79, 0x12, 0xda, 0xa7, 0x72, + 0x9e, 0x0d, 0xf8, 0x88, 0x5b, 0x34, 0x49, 0x6c, 0xed, 0xa3, 0x7f, 0x86, + 0xd3, 0xd9, 0x2f, 0x44, 0x08, 0x0d, 0xb7, 0xdb, 0x4a, 0xce, 0x02, 0x14, + 0x02, 0xd6, 0x40, 0x75, 0xe3, 0xc0, 0x97, 0xfc, 0x6c, 0x6a, 0x88, 0x29, + 0x0c, 0xe2, 0x3a, 0x2b, 0x28, 0x82, 0x8f, 0x27, 0x09, 0x69, 0x91, 0xc6, + 0xc3, 0xb7, 0x07, 0x61, 0x86, 0x8d, 0x89, 0x8a, 0xd5, 0x00, 0x3b, 0x4b, + 0xfc, 0x6f, 0xb3, 0x3f, 0x4c, 0x93, 0x31, 0xfc, 0x88, 0x53, 0x26, 0xea, + 0xe5, 0x3a, 0xfc, 0xc1, 0x59, 0x16, 0xf0, 0xb7, 0xac, 0xde, 0x1e, 0xd8, + 0x74, 0x85, 0x72, 0xd9, 0xbb, 0xbe, 0x76, 0x32, 0x25, 0x9d, 0x21, 0xbc, + 0xfd, 0x8d, 0x32, 0xfe, 0xae, 0x24, 0xe5, 0x4a, 0xcc, 0x5d, 0x15, 0x23, + 0xd3, 0x57, 0xe7, 0xa9, 0x2c, 0x31, 0xd7, 0xc5, 0x6b, 0x70, 0x6c, 0x22, + 0x5a, 0x13, 0x1f, 0x76, 0x13, 0x78, 0x6f, 0xac, 0x42, 0x4c, 0x46, 0x81, + 0xa2, 0x20, 0x91, 0x30, 0xed, 0xcb, 0x90, 0xfe, 0x3c, 0xa3, 0xc7, 0xb4, + 0x1f, 0x21, 0x1d, 0x98, 0x74, 0x6a, 0x3e, 0xc8, 0xcc, 0xd2, 0x68, 0x87, + 0x69, 0xa9, 0xdf, 0x50, 0xd5, 0x0a, 0x8e, 0x10, 0x54, 0xab, 0xea, 0x65, + 0x2a, 0x52, 0xd7, 0x22, 0xae, 0x2f, 0x1e, 0xc3, 0x16, 0x58, 0x20, 0x18, + 0x6d, 0x35, 0x46, 0x31, 0x43, 0x5d, 0x62, 0xfb, 0xb1, 0x47, 0x32, 0xfa, + 0x14, 0xcc, 0x51, 0xa3, 0xcd, 0x99, 0x4f, 0x97, 0x0f, 0xca, 0x24, 0x93, + 0x17, 0xea, 0xa3, 0xf3, 0x1f, 0xbe, 0xb5, 0xa3, 0xac, 0x80, 0xcc, 0x20, + 0x3b, 0xa6, 0xd3, 0x32, 0x72, 0x4e, 0xd9, 0x25, 0xf9, 0xc2, 0x24, 0x15, + 0xbd, 0x1e, 0x1e, 0x41, 0x8c, 0x18, 0x8c, 0x58, 0xe8, 0x75, 0x20, 0xff, + 0xa3, 0xf4, 0xd4, 0xab, 0x75, 0x78, 0x4e, 0xbb, 0x7c, 0x94, 0x93, 0x28, + 0x5b, 0x07, 0x3a, 0x3c, 0xc9, 0xf1, 0x55, 0x3e, 0x33, 0xed, 0xf8, 0x72, + 0x55, 0xab, 0x5a, 0xea, 0xbe, 0x65, 0xfa, 0x81, 0x50, 0xc0, 0x9d, 0x2d, + 0xfb, 0x04, 0x25, 0x7c, 0xb9, 0xee, 0xe2, 0xa3, 0x00, 0x44, 0xd3, 0x9d, + 0xee, 0x4f, 0x80, 0x77, 0xfb, 0x26, 0x6b, 0x07, 0xd0, 0xff, 0x82, 0x39, + 0x0e, 0x2b, 0x47, 0xa3, 0xe7, 0x3e, 0xc5, 0x4e, 0x15, 0x8a, 0x48, 0x28, + 0xfb, 0xf7, 0xa4, 0x86, 0xfb, 0x77, 0x60, 0xcd, 0xc5, 0x68, 0x96, 0xd7, + 0x4c, 0x3c, 0xf2, 0x51, 0x71, 0x79, 0x2e, 0x2e, 0x57, 0x10, 0xa7, 0xfc, + 0xd1, 0xd4, 0x61, 0x71, 0x81, 0x85, 0x74, 0x09, 0x7d, 0x80, 0xd0, 0xc2, + 0xe9, 0xff, 0xb7, 0x88, 0x53, 0x74, 0x1e, 0xb0, 0xca, 0x65, 0x48, 0x8e, + 0xdb, 0x59, 0x3a, 0xcb, 0x80, 0xeb, 0xfd, 0xd2, 0xc9, 0x38, 0x43, 0xae, + 0x76, 0xf2, 0xbb, 0x51, 0xb2, 0xcb, 0xe6, 0x85, 0x31, 0xb5, 0x62, 0xd4, + 0x5e, 0x48, 0x08, 0xf1, 0x40, 0x5b, 0x16, 0x83, 0x5e, 0xa5, 0x9c, 0x6b, + 0x91, 0x49, 0x44, 0xff, 0x3b, 0xa9, 0x2b, 0xf3, 0x06, 0x33, 0x9e, 0x6e, + 0x3c, 0x66, 0x7e, 0x27, 0xa2, 0x59, 0x7b, 0xe3, 0xb6, 0xb4, 0x28, 0xeb, + 0x93, 0x35, 0x87, 0xac, 0x0e, 0x0b, 0x7e, 0xbc, 0x35, 0x28, 0x72, 0x1f, + 0x26, 0x59, 0xd0, 0x1f, 0x63, 0xe4, 0x86, 0x5d, 0x70, 0xf3, 0xa8, 0xa4, + 0xb8, 0xcd, 0xb3, 0xf8, 0x8d, 0xaa, 0x41, 0xd2, 0xcc, 0x0b, 0x15, 0x66, + 0x22, 0x83, 0x92, 0xe3, 0x0b, 0xf9, 0xea, 0xa0, 0x33, 0xa1, 0x4e, 0x92, + 0xae, 0x81, 0x95, 0xa4, 0x58, 0x3f, 0xa9, 0x15, 0x52, 0xf9, 0xda, 0xb7, + 0x10, 0x8d, 0xc6, 0xab, 0x77, 0xe9, 0xbe, 0xad, 0xc9, 0x3a, 0x6a, 0x8d, + 0x92, 0x6c, 0x69, 0xff, 0x31, 0x49, 0x25, 0x04, 0xc8, 0x93, 0x6f, 0xc8, + 0xe7, 0x60, 0x7a, 0x76, 0xb5, 0xc1, 0x07, 0xef, 0xa3, 0x39, 0xa6, 0xf2, + 0x36, 0x04, 0xde, 0x3c, 0x4a, 0x4e, 0x96, 0xbd, 0x64, 0x26, 0x80, 0x01, + 0x88, 0x47, 0xd2, 0xa4, 0x46, 0xcd, 0xe1, 0x30, 0x7f, 0xa3, 0x00, 0x11, + 0x38, 0x55, 0xfa, 0xeb, 0x10, 0xeb, 0xa0, 0x65, 0x04, 0x09, 0xc8, 0xde, + 0x9c, 0x73, 0xba, 0x0c, 0xbd, 0xd3, 0xa5, 0x84, 0x5e, 0xb9, 0x3b, 0xd4, + 0x94, 0xbd, 0xa6, 0x53, 0xbe, 0x93, 0x69, 0x3e, 0xaa, 0x32, 0x31, 0x06, + 0xc8, 0x1b, 0x4a, 0x48, 0xb5, 0x17, 0x85, 0xbf, 0x72, 0xec, 0xf5, 0x29, + 0x8a, 0xd8, 0xeb, 0x99, 0x8b, 0x74, 0x84, 0x57, 0x8c, 0xe1, 0x85, 0x94, + 0xa0, 0xbc, 0x7a, 0x14, 0xf0, 0xf4, 0x8b, 0x25, 0x37, 0x43, 0xa1, 0x34, + 0x09, 0x71, 0xca, 0x5c, 0x9f, 0x08, 0x38, 0xd9, 0x9c, 0x0c, 0x0e, 0xcb, + 0xe4, 0xad, 0x4b, 0x2a, 0x89, 0x67, 0xf8, 0x29, 0x6c, 0x69, 0x0e, 0x5d, + 0xca, 0xfa, 0xa6, 0x6b, 0x0e, 0xb5, 0x94, 0x17, 0x71, 0xf0, 0xc9, 0xcd, + 0x02, 0x1d, 0xa5, 0xd5, 0xc6, 0xa7, 0xbc, 0x5f, 0x6e, 0x67, 0x43, 0x68, + 0xce, 0xac, 0x54, 0x81, 0x2a, 0x25, 0x22, 0x52, 0x35, 0xad, 0x7b, 0xd5, + 0x06, 0x8c, 0x00, 0xfb, 0xca, 0xc4, 0x0a, 0x49, 0x1e, 0xc8, 0xeb, 0x77, + 0xc1, 0x63, 0x23, 0x96, 0xbd, 0x35, 0xfa, 0x13, 0xae, 0xbf, 0x1d, 0x1e, + 0x69, 0x8d, 0xb3, 0xe3, 0x07, 0xde, 0x4e, 0xd0, 0x12, 0xa9, 0xc3, 0x36, + 0x30, 0x46, 0xef, 0x92, 0x76, 0x17, 0x8f, 0x10, 0xe7, 0xba, 0x99, 0x4b, + 0xdf, 0xad, 0xb8, 0x11, 0x80, 0xdf, 0xe7, 0xfd, 0x80, 0x64, 0xf7, 0x2a, + 0xac, 0x60, 0x2a, 0x54, 0x8f, 0x4f, 0xaf, 0xaf, 0x60, 0xf9, 0x67, 0x20, + 0x80, 0x53, 0x5c, 0xb6, 0x81, 0xa6, 0x2a, 0x74, 0x2d, 0xc5, 0x74, 0x2a, + 0x95, 0x26, 0x13, 0x17, 0x01, 0xdd, 0x31, 0xac, 0x5a, 0x05, 0xda, 0xde, + 0xba, 0xf6, 0x37, 0x13, 0x8d, 0xe4, 0xa8, 0x93, 0x46, 0x9e, 0xa9, 0x82, + 0x24, 0x7e, 0xc8, 0xda, 0x63, 0x89, 0xcd, 0x33, 0xc9, 0xf7, 0xf9, 0x71, + 0x35, 0xe6, 0xa5, 0x5f, 0x6b, 0x3b, 0xbb, 0x0c, 0xe0, 0xa4, 0x0b, 0xe3, + 0x29, 0xc0, 0xae, 0x8e, 0xce, 0x03, 0x09, 0x73, 0x0e, 0x1e, 0x9c, 0xe9, + 0x59, 0xb6, 0x8b, 0x78, 0x67, 0x32, 0x8b, 0xf1, 0x93, 0xcc, 0x72, 0x1b, + 0x6f, 0xa2, 0xf1, 0x04, 0x9c, 0xfa, 0x98, 0x02, 0xca, 0xdf, 0x35, 0x3c, + 0x38, 0xac, 0xa8, 0xdb, 0x90, 0xae, 0xaa, 0xf9, 0x70, 0xfb, 0xed, 0xbd, + 0xa6, 0x25, 0x14, 0x58, 0x09, 0x8a, 0x36, 0xaf, 0x41, 0x09, 0x19, 0xcb, + 0xd3, 0x25, 0x5d, 0x0e, 0xe6, 0x20, 0x14, 0x71, 0x24, 0x79, 0x19, 0x55, + 0xaf, 0x51, 0x5b, 0xa4, 0xc0, 0x93, 0x9e, 0xdd, 0x88, 0x31, 0x13, 0x96, + 0xbf, 0xca, 0x0a, 0xd7, 0xbc, 0xc4, 0x00, 0xa1, 0x10, 0x2d, 0x92, 0x79, + 0xf9, 0x14, 0xdb, 0xd2, 0xba, 0x74, 0xfa, 0xa8, 0xe5, 0x40, 0x14, 0xc2, + 0x56, 0x3c, 0x7f, 0x50, 0x07, 0x60, 0x86, 0x93, 0x51, 0x2e, 0xf9, 0x70, + 0x61, 0x70, 0x0e, 0xa4, 0x87, 0x75, 0xcc, 0x6c, 0x72, 0xb7, 0x68, 0x23, + 0xb7, 0x3d, 0x76, 0xaf, 0x96, 0x9b, 0x4a, 0xe5, 0x12, 0x28, 0x4a, 0x8f, + 0x79, 0x34, 0xff, 0xec, 0x92, 0xeb, 0x6b, 0xaf, 0xc9, 0xbd, 0xc1, 0x77, + 0x07, 0xd0, 0xfa, 0x55, 0x57, 0x10, 0x0c, 0xad, 0x29, 0x2a, 0x79, 0xd6, + 0x09, 0x9e, 0x7d, 0x18, 0xd4, 0xd6, 0xdd, 0x72, 0x1a, 0x8f, 0x24, 0x11, + 0x70, 0xd2, 0x52, 0x36, 0x0f, 0x38, 0x79, 0x38, 0x4a, 0x02, 0x4f, 0x73, + 0x2a, 0xaa, 0x6a, 0xb5, 0x0c, 0x72, 0x32, 0x85, 0x21, 0x76, 0x1a, 0x8a, + 0x7d, 0x51, 0x0e, 0xf1, 0xf9, 0x19, 0xfa, 0x6b, 0x9b, 0x22, 0x71, 0x8c, + 0x13, 0xcc, 0xba, 0x7d, 0xee, 0xd8, 0x34, 0xf6, 0x85, 0x60, 0xe1, 0xe4, + 0x59, 0x6e, 0x32, 0x60, 0xd9, 0xfa, 0xb7, 0x56, 0x54, 0x25, 0xd1, 0x73, + 0x6a, 0xf2, 0xa0, 0xc7, 0xa0, 0x67, 0x10, 0x89, 0x9c, 0x27, 0x5f, 0x7f, + 0x2e, 0x5a, 0x29, 0x70, 0x7a, 0x7b, 0xaf, 0x21, 0xd0, 0xf4, 0x06, 0xb9, + 0x2d, 0xf1, 0xb8, 0x32, 0xed, 0xc5, 0xc9, 0xac, 0x2f, 0x54, 0x0a, 0xf9, + 0x08, 0x39, 0x39, 0x7d, 0x1d, 0xaf, 0xb4, 0x5f, 0x4d, 0x75, 0xc3, 0xe8, + 0x52, 0x3a, 0x47, 0x72, 0x2c, 0xa9, 0x2d, 0xcb, 0x74, 0x06, 0xfe, 0x69, + 0xd3, 0xf3, 0x1a, 0xb2, 0xd3, 0x01, 0xed, 0x6c, 0xc1, 0xca, 0x4f, 0xaf, + 0x11, 0x9b, 0xa2, 0x27, 0x2a, 0x59, 0x56, 0x58, 0xdf, 0x79, 0x8b, 0xc9, + 0x87, 0xe9, 0x58, 0x81, 0x48, 0xc6, 0xb6, 0x7d, 0x60, 0x54, 0x87, 0x9c, + 0x61, 0xbb, 0x4b, 0xbb, 0x61, 0xac, 0x0a, 0x5a, 0x66, 0x7e, 0x70, 0x8b, + 0xfd, 0x92, 0x76, 0x4a, 0xa9, 0xa5, 0xc3, 0xf4, 0xf2, 0x93, 0x48, 0xc4, + 0xf3, 0x91, 0x2b, 0x60, 0x04, 0x0e, 0xb0, 0x6b, 0x60, 0x5e, 0xf0, 0xf1, + 0x54, 0x41, 0x56, 0xdc, 0x25, 0x57, 0xc3, 0xb6, 0x0b, 0x5e, 0x15, 0xb5, + 0x2a, 0x36, 0x4f, 0xe7, 0x1d, 0x70, 0xa8, 0xa7, 0xec, 0xd6, 0x74, 0xba, + 0xa4, 0x79, 0x83, 0x7c, 0x9e, 0x1a, 0x5d, 0x32, 0xc8, 0xcb, 0x41, 0xca, + 0x04, 0xec, 0x0b, 0x18, 0x54, 0xe1, 0x67, 0xbf, 0xa8, 0x7a, 0xc3, 0x0f, + 0x27, 0x2a, 0xaf, 0x2a, 0x41, 0x19, 0x1f, 0xe8, 0xa2, 0xe8, 0xfa, 0xfc, + 0x88, 0x41, 0x46, 0xc3, 0x1c, 0x44, 0xe5, 0xee, 0x47, 0xec, 0xfe, 0xbf, + 0xb8, 0x29, 0x2e, 0xae, 0x47, 0x0a, 0x42, 0x69, 0x8a, 0x9a, 0x94, 0x97, + 0x9e, 0xf5, 0xb6, 0x37, 0x1c, 0x10, 0xc2, 0x99, 0xa8, 0xe9, 0x9e, 0x0e, + 0x6e, 0xb5, 0xbe, 0xba, 0x1f, 0x77, 0xa6, 0x35, 0x02, 0x1e, 0x8c, 0xe6, + 0x02, 0x53, 0xe2, 0x9a, 0xdd, 0x09, 0x6e, 0x9b, 0x7a, 0x36, 0x4f, 0x38, + 0x8d, 0x4c, 0xa4, 0xb4, 0xff, 0x90, 0x76, 0x0d, 0x11, 0x7d, 0xe1, 0xe9, + 0x7f, 0x2a, 0x4a, 0x80, 0xe0, 0xd8, 0x3c, 0x23, 0xd2, 0xa5, 0xe5, 0x39, + 0x77, 0xbf, 0x3d, 0x71, 0x0d, 0x45, 0xbb, 0x39, 0x66, 0x1a, 0x4d, 0x59, + 0xb7, 0xd0, 0x0a, 0xee, 0x87, 0xee, 0x1f, 0xcf, 0x6f, 0xc2, 0x50, 0xb1, + 0xa5, 0x4c, 0xee, 0x40, 0x69, 0xd7, 0x36, 0x38, 0x14, 0xcd, 0x6a, 0x9a, + 0x90, 0x40, 0xad, 0x76, 0xf1, 0xa6, 0xd4, 0x3c, 0x75, 0x10, 0xba, 0xcb, + 0xab, 0x22, 0x28, 0x5f, 0x0c, 0xe0, 0xee, 0xf4, 0xfd, 0x61, 0x52, 0x0a, + 0x59, 0xfe, 0x61, 0xc5, 0x40, 0xf9, 0x91, 0x8e, 0x36, 0x29, 0x63, 0x6c, + 0x6e, 0x45, 0xa5, 0x42, 0xe3, 0x36, 0x90, 0xe7, 0x90, 0x9f, 0x58, 0xbb, + 0xf9, 0x1b, 0xee, 0x2c, 0xbb, 0x3a, 0xfd, 0x3d, 0xbe, 0x3d, 0x45, 0xf0, + 0xc2, 0x18, 0xaa, 0x46, 0x10, 0x23, 0xe9, 0x63, 0xba, 0x7f, 0xc2, 0xe1, + 0xf4, 0x05, 0xdd, 0x4a, 0x7c, 0xa8, 0xab, 0xa9, 0xbd, 0x6f, 0xdf, 0x48, + 0x59, 0x11, 0xd4, 0xba, 0x75, 0xb6, 0x22, 0xd4, 0xd7, 0x35, 0x6f, 0x27, + 0x70, 0xc7, 0x3d, 0x90, 0x06, 0x39, 0x2a, 0x16, 0xd0, 0x8b, 0xd7, 0xfb, + 0x5e, 0x85, 0x2e, 0xb0, 0xd8, 0xc7, 0xdb, 0xe5, 0x24, 0x3a, 0x6e, 0xc4, + 0x5e, 0xd4, 0x22, 0x25, 0x14, 0xee, 0xa5, 0x30, 0x8b, 0xd6, 0x27, 0x61, + 0x33, 0x13, 0x46, 0x0b, 0x26, 0x45, 0xa6, 0xb4, 0xfa, 0x8d, 0xa3, 0xf2, + 0x27, 0xd2, 0xc5, 0x04, 0xaa, 0x96, 0xa4, 0x55, 0xfa, 0x40, 0xf1, 0xfc, + 0x66, 0x33, 0x9e, 0x4b, 0x39, 0x75, 0xae, 0x7f, 0x52, 0x87, 0x7b, 0x8a, + 0xf9, 0x7d, 0x5f, 0x8a, 0x7e, 0xf7, 0xfe, 0xc4, 0x7f, 0xf4, 0xf6, 0x9a, + 0x86, 0x78, 0x21, 0x02, 0x94, 0x9e, 0x50, 0x2d, 0xdc, 0xd6, 0xa5, 0x53, + 0xf1, 0xef, 0x06, 0xe8, 0xb5, 0x46, 0x81, 0xcc, 0x91, 0x4f, 0x37, 0xee, + 0x27, 0xcb, 0x91, 0xad, 0xff, 0x1d, 0xd1, 0x00, 0xa8, 0x96, 0x22, 0xaa, + 0x63, 0x23, 0x2a, 0x7a, 0x75, 0x6f, 0xe9, 0x2d, 0x26, 0xde, 0x11, 0x97, + 0x4b, 0x17, 0x3f, 0xde, 0x51, 0x1a, 0x22, 0xed, 0x38, 0x6f, 0x3e, 0x7a, + 0xd0, 0xd6, 0x60, 0x06, 0x7e, 0x3f, 0xa4, 0x29, 0xfa, 0x18, 0x91, 0xda, + 0x73, 0x38, 0xe3, 0xe3, 0xb5, 0xc0, 0x5b, 0x4e, 0xe8, 0x94, 0xea, 0x45, + 0x6e, 0x5b, 0x50, 0xaa, 0x38, 0xb6, 0x6f, 0xdb, 0x90, 0x1b, 0x3b, 0x82, + 0xbb, 0x0d, 0x38, 0xe3, 0xca, 0xd9, 0xf1, 0x2e, 0x27, 0x4c, 0x2c, 0x5a, + 0x42, 0xdf, 0x44, 0xc8, 0x07, 0xe4, 0x95, 0xb5, 0xec, 0x91, 0x34, 0x1c, + 0x9a, 0x0c, 0x50, 0x1a, 0xce, 0x67, 0xe4, 0x4b, 0x87, 0x61, 0x43, 0x95, + 0x95, 0xb8, 0x8a, 0xf4, 0xc9, 0x92, 0x33, 0x33, 0xe3, 0xfe, 0x98, 0x2a, + 0xae, 0x8e, 0xf2, 0x6b, 0x13, 0x7c, 0xe4, 0x44, 0x40, 0x66, 0xea, 0x0c, + 0xe4, 0xdb, 0x16, 0x65, 0xa8, 0x8b, 0x37, 0x08, 0xec, 0x1e, 0xfc, 0xa6, + 0xd0, 0x9b, 0x9e, 0x0a, 0xd2, 0xe3, 0xcf, 0x5d, 0xb2, 0xaf, 0x8e, 0x05, + 0x7d, 0x8d, 0x84, 0xbc, 0x9f, 0xb1, 0xe6, 0x6a, 0x2e, 0x4b, 0x6d, 0x64, + 0x91, 0x17, 0x9d, 0xb5, 0x35, 0x15, 0x02, 0xe9, 0x1b, 0x85, 0xc1, 0x89, + 0xc2, 0x5a, 0x32, 0x3a, 0x80, 0x78, 0x5e, 0xcc, 0x50, 0x26, 0xf5, 0x11, + 0x01, 0x79, 0xf3, 0xaf, 0xb6, 0x40, 0x00, 0x73, 0x8f, 0xeb, 0x5a, 0xd1, + 0x26, 0x00, 0xe2, 0xa3, 0xcd, 0xfd, 0xaa, 0x15, 0x5b, 0x98, 0x2a, 0x76, + 0x41, 0x07, 0xc2, 0xde, 0xb6, 0x71, 0xe7, 0xc3, 0xe9, 0x92, 0xb3, 0xd8, + 0xfe, 0xaf, 0x12, 0x61, 0x86, 0x5b, 0x6e, 0x74, 0x45, 0x7b, 0x9b, 0x6f, + 0x1a, 0x13, 0x84, 0xf6, 0x31, 0x5f, 0x5b, 0x6c, 0xde, 0x47, 0xb8, 0x73, + 0x32, 0xc7, 0x94, 0x92, 0xa5, 0xc3, 0x65, 0xdf, 0x96, 0x6c, 0xfd, 0xb7, + 0x80, 0xfb, 0x47, 0xba, 0x6e, 0x43, 0xb3, 0x7e, 0x86, 0xc9, 0x97, 0x45, + 0xde, 0x3f, 0x3a, 0xf6, 0xb0, 0x9e, 0x9a, 0xcb, 0xfd, 0xf2, 0x5c, 0xba, + 0x6e, 0x3f, 0xed, 0xfa, 0x74, 0x84, 0xe2, 0xb1, 0xae, 0x66, 0x57, 0x0b, + 0x96, 0x6c, 0x77, 0xe4, 0x8a, 0x67, 0x97, 0xc7, 0xe0, 0x44, 0xb2, 0x83, + 0x2d, 0x3c, 0x2e, 0x01, 0x19, 0x2e, 0x4c, 0x74, 0xe1, 0x35, 0x73, 0xeb, + 0x85, 0x63, 0x8c, 0x3a, 0xb8, 0xbc, 0x25, 0x6a, 0x8d, 0xaf, 0xd2, 0xfb, + 0xef, 0xd3, 0x12, 0x93, 0x0b, 0x39, 0xfa, 0x66, 0xbe, 0x3b, 0xfd, 0x6c, + 0x0b, 0xbb, 0xb2, 0x5a, 0x78, 0xa1, 0xcf, 0x8c, 0x7d, 0x60, 0x55, 0xeb, + 0x33, 0x4e, 0x8e, 0xf9, 0x19, 0x4d, 0x42, 0xd4, 0xf8, 0xd8, 0xba, 0xad, + 0x0a, 0x6e, 0x62, 0xd4, 0xe1, 0x6a, 0xcc, 0xea, 0x09, 0x91, 0x8e, 0x62, + 0xc9, 0x1e, 0x9e, 0x48, 0xaa, 0xde, 0xf7, 0xa2, 0x5a, 0xcb, 0x83, 0x20, + 0xe8, 0xf5, 0xd1, 0xfe, 0x9d, 0x18, 0x2f, 0xd6, 0xf8, 0x97, 0x17, 0xce, + 0xc2, 0x05, 0x08, 0xef, 0x61, 0x70, 0x9d, 0x95, 0x79, 0x59, 0x4c, 0x06, + 0x24, 0x3d, 0x24, 0x69, 0xff, 0x46, 0xda, 0xbc, 0x71, 0x7a, 0x74, 0x93, + 0x58, 0xf5, 0xc8, 0x91, 0xfb, 0x66, 0xed, 0x78, 0x8f, 0xf8, 0x28, 0xa8, + 0x1d, 0xa5, 0x3a, 0x13, 0x76, 0xc2, 0xcc, 0xba, 0xb9, 0x56, 0x29, 0x74, + 0xd6, 0x14, 0x75, 0x58, 0xe6, 0x2e, 0x79, 0x6e, 0x9d, 0x41, 0x94, 0x8a, + 0xcf, 0xf1, 0xb1, 0xe0, 0x36, 0xe5, 0x89, 0x9a, 0x95, 0xa1, 0x11, 0xd1, + 0xbe, 0x45, 0xe4, 0xb3, 0xb0, 0x62, 0x32, 0x1d, 0xba, 0xe0, 0xde, 0x57, + 0x81, 0x0e, 0x01, 0x9b, 0x52, 0x3d, 0xd5, 0xde, 0x3b, 0x3a, 0xdd, 0x8f, + 0xe3, 0x2e, 0xce, 0x1e, 0x89, 0x4d, 0x81, 0xf0, 0xf6, 0x20, 0x63, 0x7a, + 0x4c, 0xbb, 0x66, 0xe0, 0xbe, 0x2b, 0xee, 0xd0, 0x3b, 0x60, 0x1e, 0x65, + 0xd1, 0x2c, 0x7c, 0x5c, 0x6c, 0x16, 0x5b, 0x90, 0xc8, 0x05, 0x10, 0xf2, + 0xde, 0x33, 0x90, 0x35, 0x69, 0x24, 0x3f, 0xc1, 0x8f, 0x1e, 0x4a, 0x60, + 0xf1, 0x03, 0x65, 0x46, 0x40, 0x76, 0xe9, 0x83, 0x97, 0xda, 0x0b, 0xb8, + 0x22, 0xfa, 0x55, 0x99, 0xfd, 0x18, 0x24, 0xd2, 0x66, 0xb0, 0x7b, 0x70, + 0x56, 0x93, 0xad, 0x09, 0x95, 0x8e, 0x1f, 0x2f, 0xe8, 0x12, 0x55, 0xd4, + 0x1f, 0xde, 0x09, 0x85, 0x05, 0xd1, 0xd5, 0x10, 0x2c, 0x8c, 0x6b, 0x53, + 0x28, 0xce, 0x06, 0xc5, 0x52, 0x0f, 0xfa, 0x09, 0x09, 0x23, 0x1b, 0xe3, + 0xbf, 0xb1, 0x89, 0x72, 0x26, 0x0d, 0xa6, 0xbb, 0x7d, 0x9e, 0xdc, 0xf8, + 0xf5, 0x0b, 0x8c, 0xe0, 0xbc, 0x97, 0x3b, 0x72, 0xdd, 0xf5, 0x9d, 0xc5, + 0xb6, 0x37, 0x2c, 0x76, 0x5b, 0x58, 0x67, 0xdb, 0xed, 0x3b, 0x6e, 0xe5, + 0xe5, 0x6d, 0x6f, 0x0d, 0x7e, 0xff, 0xa9, 0x57, 0x4a, 0x84, 0x85, 0x82, + 0xac, 0x00, 0x50, 0xa3, 0x4f, 0x87, 0xfe, 0x2a, 0x40, 0x52, 0x54, 0x81, + 0x69, 0x42, 0x0b, 0x0c, 0xd7, 0x18, 0x98, 0x01, 0x8c, 0x5a, 0xa2, 0xf4, + 0xe8, 0x61, 0xd1, 0x38, 0xfd, 0x0f, 0x63, 0x75, 0xd3, 0x4b, 0x1d, 0xdc, + 0xdf, 0xb2, 0xeb, 0x94, 0x97, 0x5c, 0x2a, 0xb4, 0x12, 0x5c, 0x49, 0x2b, + 0xfc, 0xd0, 0x8d, 0xfb, 0xe7, 0xb3, 0xcb, 0x0f, 0x3c, 0x2e, 0x04, 0x36, + 0xa8, 0x03, 0xc9, 0xd7, 0x11, 0x2d, 0x2a, 0x93, 0xff, 0xda, 0x26, 0xb0, + 0x54, 0x7e, 0xaf, 0x30, 0x7d, 0xce, 0x46, 0x8a, 0x3d, 0x7c, 0xa4, 0x7a, + 0x2c, 0xfa, 0xba, 0xa1, 0xc9, 0x41, 0xd3, 0xb8, 0x84, 0x03, 0x78, 0xdd, + 0xe9, 0x57, 0x19, 0x62, 0x62, 0xff, 0x5b, 0x3b, 0x48, 0x62, 0x0e, 0xee, + 0x19, 0xb0, 0x32, 0x6e, 0x6a, 0x07, 0xd8, 0x4e, 0x25, 0x76, 0xa7, 0xe3, + 0x98, 0xa1, 0x6f, 0xb6, 0x99, 0x32, 0x67, 0x7d, 0x46, 0x42, 0x4a, 0x82, + 0xd1, 0x29, 0x1b, 0x87, 0xeb, 0x4b, 0x9e, 0xdf, 0x69, 0x75, 0xbd, 0x4f, + 0xd3, 0xde, 0xc9, 0x83, 0xe6, 0xd6, 0xea, 0x03, 0x81, 0x12, 0xf3, 0x5d, + 0x99, 0xf1, 0xb1, 0xd9, 0x3e, 0xbe, 0xf3, 0xa8, 0xdc, 0xb6, 0xf8, 0x4b, + 0x9e, 0x26, 0x3f, 0xf0, 0x7c, 0xb3, 0xf4, 0xca, 0x00, 0x6c, 0x6c, 0xe5, + 0x43, 0xa1, 0xfd, 0x3a, 0xf8, 0x8e, 0xe3, 0x9f, 0x88, 0xc5, 0x44, 0xfd, + 0x24, 0x69, 0x76, 0xd5, 0xcb, 0xdc, 0x9d, 0x12, 0xf3, 0x13, 0x7e, 0xe7, + 0xc3, 0xa8, 0x6a, 0xb2, 0xe0, 0xb3, 0x1d, 0xab, 0x3b, 0xc9, 0x77, 0x3d, + 0x0f, 0xc3, 0xbe, 0x4b, 0x8b, 0x28, 0xbd, 0x7c, 0xe6, 0xb2, 0x06, 0x1f, + 0xf9, 0x8f, 0x16, 0x62, 0xbf, 0xc7, 0x55, 0x73, 0xd4, 0xf1, 0x5a, 0x95, + 0x80, 0xa3, 0x4e, 0xaa, 0x60, 0x17, 0x3c, 0xc9, 0x5e, 0xd4, 0x0c, 0x56, + 0x7a, 0x77, 0x8e, 0x7f, 0x67, 0x08, 0x2f, 0xd9, 0x21, 0x19, 0xfd, 0x86, + 0x8c, 0x23, 0x8d, 0xf6, 0x92, 0x1f, 0x36, 0x2c, 0x7c, 0x83, 0xbd, 0x2f, + 0x6c, 0x63, 0x7c, 0xb7, 0x93, 0x74, 0x1b, 0xc2, 0x95, 0x34, 0x26, 0x1e, + 0x07, 0x87, 0x3a, 0xb6, 0xe2, 0x39, 0x71, 0x9b, 0x20, 0xcd, 0x63, 0xf0, + 0xbf, 0x48, 0xb5, 0x0e, 0x49, 0x86, 0x50, 0x80, 0xbd, 0xd6, 0x0e, 0xab, + 0xd5, 0x69, 0x1b, 0xa4, 0xb3, 0x63, 0x3c, 0x8f, 0xcb, 0x42, 0xdb, 0xd7, + 0x1a, 0xf4, 0xdf, 0x9e, 0x25, 0xfc, 0xd4, 0x00, 0xcb, 0xec, 0x57, 0x69, + 0x30, 0x15, 0x4d, 0x7a, 0x69, 0x28, 0x2f, 0x2b, 0x34, 0x26, 0xd1, 0xe7, + 0x01, 0x42, 0x5e, 0x02, 0xe2, 0x75, 0xe8, 0x52, 0x8a, 0xb4, 0x71, 0xfa, + 0xc3, 0x3d, 0xe6, 0xac, 0xeb, 0xf3, 0x93, 0xe0, 0x37, 0xcd, 0x66, 0x92, + 0x66, 0x2c, 0xfe, 0x4b, 0xd6, 0x3c, 0xf1, 0x57, 0xe5, 0xcf, 0xf5, 0xd0, + 0xdb, 0x0e, 0x1f, 0x82, 0x65, 0x3b, 0xab, 0x69, 0x42, 0x53, 0x7d, 0xa4, + 0x7c, 0xb7, 0x86, 0xeb, 0x23, 0x45, 0xa8, 0x4a, 0x73, 0xfc, 0x38, 0xc6, + 0xe5, 0x2c, 0xab, 0x80, 0xfb, 0x23, 0xb2, 0x0c, 0x53, 0x28, 0x21, 0x37, + 0x54, 0x9c, 0x72, 0x51, 0x0f, 0x44, 0x50, 0xd3, 0xe1, 0xd5, 0xb2, 0x27, + 0x83, 0xb6, 0xe9, 0x4d, 0x64, 0x5c, 0x17, 0x0f, 0xe0, 0x13, 0xe4, 0x26, + 0x6b, 0xd0, 0xd8, 0x25, 0xe3, 0x69, 0x6a, 0x95, 0x3f, 0x4a, 0x4e, 0xa0, + 0x58, 0xbc, 0x28, 0x47, 0x8b, 0x68, 0xe4, 0x41, 0x90, 0x46, 0x1b, 0x84, + 0xa0, 0x7b, 0x46, 0x46, 0x03, 0xee, 0x21, 0x0d, 0x34, 0xed, 0xff, 0x15, + 0x57, 0x06, 0xdf, 0x71, 0x09, 0xb2, 0x66, 0x0d, 0x6e, 0xcc, 0xa5, 0x0c, + 0xaf, 0x3f, 0x24, 0x8f, 0xd1, 0xc8, 0x44, 0x86, 0xaf, 0xbf, 0xeb, 0x2f, + 0xb9, 0xee, 0xa7, 0xcf, 0xe4, 0xe8, 0xec, 0x47, 0x09, 0xd8, 0x95, 0x9e, + 0x3c, 0xda, 0x92, 0x41, 0x61, 0xf5, 0xc3, 0xec, 0x00, 0xe4, 0xa3, 0x0d, + 0x4a, 0xb3, 0xf6, 0x82, 0x05, 0x38, 0x70, 0x6a, 0xd1, 0x28, 0x2c, 0xb3, + 0xc6, 0xbb, 0x38, 0xb3, 0x06, 0x7f, 0xd6, 0x4c, 0xe7, 0xfb, 0xef, 0x0d, + 0x52, 0x66, 0xbe, 0xd8, 0xa6, 0x6f, 0xe8, 0xd9, 0x42, 0x4f, 0xad, 0xe8, + 0xe8, 0x6c, 0xf9, 0xe9, 0x42, 0xd9, 0x66, 0x6e, 0xec, 0xfe, 0xf5, 0x91, + 0xbf, 0x0a, 0x98, 0xd8, 0x7b, 0x23, 0x12, 0xa6, 0x04, 0xa8, 0xb3, 0x61, + 0x13, 0x65, 0xc0, 0xe2, 0x82, 0xb9, 0xb2, 0x38, 0x07, 0x06, 0xca, 0x64, + 0x6c, 0x23, 0x93, 0x60, 0x1d, 0x4d, 0x38, 0x5e, 0x8e, 0x90, 0x16, 0x4a, + 0xfd, 0xb3, 0xcd, 0x84, 0x9c, 0xa5, 0xfa, 0x73, 0x2d, 0xcb, 0x87, 0x31, + 0x3d, 0xf8, 0xfc, 0xeb, 0xa7, 0x56, 0x2f, 0x5b, 0x95, 0x9a, 0xc6, 0x82, + 0x29, 0x86, 0x47, 0xe2, 0xc2, 0x84, 0x01, 0xaf, 0xc8, 0x0b, 0x2d, 0xfb, + 0x34, 0xba, 0x5d, 0x9d, 0xd1, 0x85, 0xd5, 0x1e, 0x63, 0xcb, 0x3c, 0xa8, + 0xfa, 0x79, 0xef, 0x12, 0xa6, 0xb5, 0xdb, 0xc5, 0x1d, 0x6a, 0xa7, 0x54, + 0x58, 0x0c, 0xbe, 0x61, 0xe5, 0x96, 0x7f, 0x4a, 0x3b, 0x59, 0x32, 0x2d, + 0x06, 0x44, 0x83, 0x5c, 0xad, 0xe9, 0xfe, 0x7c, 0xd7, 0x5b, 0x34, 0xa1, + 0xa3, 0xad, 0x9a, 0xbf, 0xd5, 0x30, 0xf0, 0x22, 0xfc, 0x94, 0x7f, 0xd4, + 0xa4, 0xca, 0x88, 0x31, 0xe7, 0xf2, 0x89, 0x2d, 0xda, 0xe6, 0x91, 0xa6, + 0x27, 0x22, 0x74, 0x9f, 0xc6, 0x72, 0x4f, 0xf6, 0xa9, 0xfe, 0x7a, 0xf0, + 0xa8, 0x6b, 0x6c, 0x9f, 0xe9, 0x2a, 0x9b, 0x23, 0x9e, 0xb8, 0x2b, 0x29, + 0x65, 0xa7, 0x5d, 0xbd, 0x10, 0xe4, 0x56, 0x02, 0x94, 0xdd, 0xd1, 0xab, + 0x9b, 0x82, 0x2d, 0x8d, 0xf6, 0xd3, 0x65, 0x63, 0x4a, 0xc4, 0x86, 0x61, + 0x37, 0x9f, 0xdb, 0x4b, 0x34, 0x20, 0x0a, 0xca, 0x45, 0x6c, 0x06, 0xc4, + 0x9c, 0x74, 0x4d, 0x83, 0x6a, 0x8d, 0xad, 0xc6, 0x61, 0x3a, 0x8d, 0xde, + 0x6c, 0xf9, 0x8e, 0x33, 0xa2, 0xee, 0x99, 0xc7, 0xe4, 0x52, 0xb2, 0x44, + 0x6f, 0x2f, 0x0f, 0x41, 0xa9, 0x1a, 0xd3, 0x96, 0x42, 0xc6, 0x49, 0x12, + 0x6a, 0xf0, 0x29, 0xa9, 0x0c, 0x9c, 0x50, 0x5d, 0x1d, 0xd1, 0x42, 0x7e, + 0x6f, 0x36, 0x48, 0x0f, 0x58, 0x14, 0x94, 0xc0, 0x10, 0x1e, 0xe0, 0xb2, + 0xdd, 0xba, 0x57, 0x91, 0x4d, 0xd5, 0xdc, 0xa6, 0x4c, 0x68, 0x00, 0x6c, + 0xb3, 0x5d, 0x32, 0x13, 0xbe, 0xa8, 0xc3, 0xfb, 0xd4, 0x19, 0x40, 0xf5, + 0x6f, 0x63, 0xa1, 0x07, 0xbf, 0xa2, 0x8b, 0xfc, 0xfe, 0xf8, 0xa1, 0x33, + 0x70, 0x07, 0x6d, 0xc5, 0x72, 0xa0, 0x39, 0xd6, 0xd7, 0x76, 0x6c, 0xfa, + 0x1f, 0x04, 0xd6, 0x23, 0xbf, 0x66, 0x78, 0x92, 0x00, 0x11, 0x8a, 0x75, + 0x67, 0x44, 0xa6, 0x7c, 0xd0, 0x14, 0xe6, 0xd0, 0x31, 0x6d, 0xdb, 0xc5, + 0xb1, 0xa7, 0x99, 0xc3, 0xaf, 0x18, 0x7a, 0x26, 0x46, 0xad, 0x6d, 0x0c, + 0xb6, 0xb5, 0xad, 0xc1, 0xcf, 0x60, 0x99, 0xf5, 0x9f, 0x88, 0xaf, 0x0e, + 0x37, 0x15, 0xf9, 0x2b, 0x1a, 0x5f, 0xfb, 0xc9, 0xf8, 0xd4, 0xf0, 0x97, + 0xd2, 0x91, 0xf4, 0x94, 0xa2, 0xd3, 0x3b, 0x8b, 0x0c, 0x22, 0xa0, 0xac, + 0xb3, 0xb5, 0xdf, 0xf2, 0x27, 0x38, 0x47, 0x53, 0x5b, 0x6e, 0x8f, 0x98, + 0x9e, 0xad, 0xb6, 0xf5, 0x0e, 0x17, 0x20, 0x35, 0x54, 0x6b, 0x73, 0xa6, + 0x64, 0x65, 0xac, 0xb8, 0xc1, 0xd3, 0xf7, 0x07, 0x82, 0x93, 0x9d, 0xcb, + 0xcc, 0xe9, 0x0c, 0x51, 0x52, 0x85, 0x8b, 0x95, 0xa6, 0xb1, 0xce, 0xdc, + 0xfa, 0x00, 0x00, 0x08, 0x14, 0x1c, 0x23, 0x2a, 0x35, +}; + +static const u8 fips_test_mldsa65_public_key[] __initconst __maybe_unused = { + 0x9f, 0x55, 0x1e, 0x7f, 0x9c, 0x08, 0xb2, 0x83, 0xfd, 0x5b, 0xa2, 0xac, + 0x4f, 0x26, 0xc2, 0xf5, 0x06, 0x05, 0x96, 0x08, 0x24, 0xad, 0xec, 0xe4, + 0x99, 0xcc, 0x6c, 0xbd, 0x55, 0x37, 0x15, 0x94, 0xab, 0x31, 0x9e, 0x56, + 0xe5, 0xe4, 0x55, 0xec, 0x4d, 0x49, 0x5b, 0x5a, 0x7a, 0xe8, 0xc3, 0x4a, + 0x08, 0x44, 0x4a, 0xc2, 0x2d, 0xe4, 0x61, 0x33, 0x90, 0x20, 0x71, 0x45, + 0xa5, 0x45, 0xd0, 0x83, 0x2b, 0x32, 0x6c, 0xa7, 0x9e, 0x76, 0xcd, 0xfb, + 0x58, 0x15, 0x9e, 0x74, 0x0d, 0x67, 0x57, 0xb1, 0x06, 0x5b, 0x5d, 0xd5, + 0x1c, 0xbb, 0x95, 0x40, 0x1c, 0x71, 0x31, 0x03, 0xef, 0xff, 0x04, 0x6b, + 0xdd, 0xa2, 0xf0, 0x32, 0x00, 0x72, 0xbc, 0x87, 0xb6, 0x2c, 0x1f, 0x90, + 0x7f, 0x92, 0xa0, 0xb2, 0x04, 0xdd, 0xa9, 0xaf, 0x7f, 0x01, 0x28, 0x4c, + 0xb2, 0x57, 0x2d, 0x56, 0x93, 0xd0, 0xc7, 0x54, 0x02, 0x90, 0x57, 0x70, + 0x23, 0x57, 0xe8, 0xe7, 0x33, 0x32, 0x98, 0xfc, 0x9b, 0x8e, 0x6e, 0x7b, + 0xaa, 0x5d, 0xb5, 0x4e, 0xe0, 0x5d, 0x97, 0xa3, 0xea, 0x43, 0x7e, 0xb3, + 0xa4, 0x8c, 0xcf, 0xdc, 0xc0, 0x51, 0xa7, 0x99, 0x45, 0x3d, 0x3c, 0xa0, + 0xba, 0xc5, 0xff, 0xe1, 0x89, 0xb3, 0x7d, 0xc3, 0xdc, 0xe2, 0x23, 0x81, + 0xff, 0xa9, 0xc7, 0x93, 0xc6, 0x67, 0xad, 0x94, 0xcf, 0xeb, 0x91, 0x78, + 0x15, 0x25, 0xf7, 0xf5, 0x06, 0x08, 0x2f, 0x0c, 0xee, 0x0b, 0x6a, 0x06, + 0x59, 0xe0, 0x1f, 0x2e, 0x5a, 0x12, 0x06, 0xf5, 0xf4, 0x8e, 0x75, 0x57, + 0xa9, 0x33, 0x23, 0x0f, 0xc2, 0x6f, 0x02, 0xf8, 0x68, 0x0f, 0x62, 0x02, + 0x81, 0xfe, 0x03, 0x7c, 0xaf, 0xd7, 0x42, 0x5b, 0xcc, 0xe7, 0x2b, 0xea, + 0x49, 0xab, 0x03, 0x6d, 0x0a, 0x02, 0xae, 0x47, 0x79, 0xce, 0xfd, 0x18, + 0x76, 0x07, 0x9e, 0xa6, 0xbf, 0x7e, 0x8d, 0x73, 0xf9, 0x44, 0xeb, 0x8c, + 0xc5, 0x59, 0xb7, 0x19, 0xf6, 0x73, 0x53, 0x42, 0x2a, 0x55, 0x7b, 0xb4, + 0x56, 0x49, 0x08, 0x9e, 0x9a, 0x65, 0x60, 0x70, 0x1d, 0xbd, 0xc6, 0x85, + 0x29, 0xde, 0xfe, 0x44, 0xae, 0xdf, 0x25, 0xfd, 0x5b, 0x74, 0x6c, 0x96, + 0xe6, 0x81, 0x37, 0x80, 0xe0, 0x9e, 0xf3, 0x75, 0x63, 0xb4, 0xc9, 0x2f, + 0x71, 0xe6, 0xeb, 0xdf, 0xaf, 0x7e, 0xff, 0x9e, 0xe0, 0xbf, 0xca, 0xca, + 0x11, 0xed, 0xc6, 0x04, 0xd8, 0x49, 0x13, 0x2c, 0x63, 0xf1, 0xb3, 0x17, + 0x74, 0xd9, 0x50, 0x3f, 0xb9, 0x29, 0x0e, 0x48, 0xa7, 0xf0, 0xdc, 0x78, + 0x18, 0x0e, 0x9f, 0xb7, 0xde, 0x36, 0x79, 0x67, 0xa4, 0x23, 0x08, 0xe7, + 0x62, 0xe8, 0xa4, 0xe5, 0xcf, 0xff, 0x35, 0x55, 0x36, 0x2e, 0x3a, 0xe4, + 0x45, 0x6a, 0x80, 0xf2, 0xca, 0xe7, 0x40, 0x79, 0x14, 0xc4, 0x62, 0x38, + 0xbb, 0xd0, 0x4e, 0x6c, 0xb5, 0x85, 0x42, 0x3f, 0x35, 0xf7, 0xd7, 0x54, + 0xb8, 0x2b, 0x8b, 0xd5, 0x6f, 0x16, 0x61, 0x27, 0x23, 0xac, 0xdb, 0xea, + 0x9b, 0x3b, 0x99, 0xcd, 0x79, 0xe6, 0x12, 0x09, 0x99, 0x09, 0xa4, 0xe1, + 0x88, 0x25, 0x00, 0x9e, 0x60, 0x16, 0x63, 0xd7, 0x42, 0x9b, 0xcc, 0x36, + 0x9a, 0x8d, 0xa3, 0x75, 0x36, 0xa1, 0xa8, 0xfc, 0xa2, 0xfe, 0x29, 0x26, + 0x4c, 0x93, 0x21, 0x44, 0x6b, 0x1c, 0xba, 0xbd, 0xef, 0xff, 0x6d, 0x1f, + 0x2b, 0x6c, 0x66, 0x81, 0x9a, 0x3a, 0x1d, 0x0b, 0xd7, 0x24, 0xd4, 0xb8, + 0x93, 0xb5, 0x22, 0xf9, 0xd2, 0xf4, 0xa5, 0x05, 0x78, 0x38, 0xae, 0x58, + 0xf6, 0x50, 0x8f, 0x47, 0x1d, 0xf3, 0xfb, 0x0d, 0x04, 0x14, 0xd1, 0xd6, + 0xd8, 0x2e, 0xf2, 0xbd, 0xf5, 0x71, 0x86, 0x4c, 0xdd, 0x61, 0x24, 0x18, + 0x5b, 0x54, 0xf5, 0xcd, 0x99, 0x89, 0x01, 0x8e, 0xd1, 0x19, 0x52, 0xbc, + 0x45, 0xed, 0x0e, 0xec, 0x72, 0x2f, 0x5a, 0xe7, 0xdf, 0x36, 0x1c, 0x57, + 0x9f, 0xb2, 0x8b, 0xf2, 0x78, 0x1b, 0x3e, 0xc5, 0x48, 0x1f, 0x27, 0x04, + 0x76, 0x10, 0x44, 0xee, 0x5c, 0x68, 0x8f, 0xca, 0xd7, 0x31, 0xfc, 0x5c, + 0x40, 0x03, 0x2e, 0xbd, 0x1d, 0x59, 0x13, 0x57, 0xbc, 0x33, 0xc6, 0xa1, + 0xa3, 0xe5, 0x55, 0x79, 0x9b, 0x7e, 0x49, 0xbb, 0x23, 0x96, 0xc3, 0x1c, + 0xfe, 0x66, 0xeb, 0x5b, 0x5f, 0xe5, 0x03, 0xc9, 0xa4, 0xac, 0x4d, 0xc4, + 0x50, 0xbb, 0xd3, 0xc1, 0x91, 0x48, 0xe0, 0x93, 0x92, 0x2a, 0xdb, 0x41, + 0x37, 0x98, 0xbc, 0xa2, 0x7a, 0x09, 0x92, 0x0b, 0x1c, 0xe6, 0x4b, 0x1e, + 0x8e, 0x78, 0x81, 0x74, 0x7d, 0x6b, 0x71, 0xd5, 0xe7, 0x0e, 0x7b, 0xc2, + 0x74, 0x5d, 0x89, 0xf1, 0xfa, 0x59, 0xaa, 0xf7, 0x86, 0x66, 0x7e, 0xc2, + 0x9c, 0xf4, 0xd5, 0x8d, 0xc0, 0xb7, 0xb7, 0xa2, 0xd5, 0xcd, 0x51, 0xc3, + 0x7d, 0xa9, 0x5e, 0x46, 0xba, 0x06, 0xa3, 0x4d, 0x60, 0xd6, 0x68, 0xc6, + 0xf9, 0x63, 0x88, 0x17, 0x5c, 0x20, 0xe1, 0xc4, 0x0f, 0x3f, 0xc1, 0xa9, + 0xa7, 0x3e, 0x39, 0xef, 0x2f, 0xaf, 0xc4, 0x69, 0x29, 0xe3, 0xd4, 0x8d, + 0xe0, 0x0e, 0x88, 0xc2, 0x93, 0x43, 0xfb, 0x28, 0xcf, 0x5d, 0x85, 0x50, + 0xf7, 0xeb, 0x42, 0xf5, 0x87, 0xde, 0xa5, 0x65, 0xef, 0x43, 0x0c, 0x57, + 0x76, 0x09, 0xf4, 0x5f, 0xde, 0x81, 0x0a, 0xd9, 0x59, 0x41, 0xa4, 0x6a, + 0xb7, 0x05, 0xc7, 0xa5, 0xfe, 0x49, 0xd5, 0x9b, 0x57, 0x13, 0x14, 0x66, + 0xe2, 0xb9, 0xcc, 0x09, 0x35, 0xd4, 0xb0, 0xe0, 0xd1, 0x0d, 0x7e, 0x50, + 0x48, 0x45, 0x21, 0x00, 0x67, 0xb2, 0xad, 0xa7, 0x46, 0xe2, 0x6f, 0x70, + 0xe5, 0x3c, 0x88, 0x04, 0xaa, 0x21, 0xde, 0x03, 0xb6, 0x6f, 0xfe, 0x43, + 0x51, 0xdc, 0x2e, 0x5c, 0x6c, 0x77, 0x8f, 0x8e, 0x9d, 0x1a, 0x5b, 0x35, + 0xc5, 0xe4, 0x48, 0x82, 0x17, 0x4b, 0xf0, 0xea, 0xc9, 0x0e, 0xd2, 0x8f, + 0xcd, 0xd5, 0x01, 0xbd, 0x7f, 0x0f, 0xf5, 0xae, 0x92, 0x28, 0x1e, 0x2c, + 0xf4, 0xe9, 0x03, 0xf7, 0x0a, 0xeb, 0x84, 0x18, 0xa1, 0x37, 0x38, 0x8a, + 0x11, 0xa2, 0x5d, 0x8c, 0xf6, 0xe4, 0x3f, 0x5b, 0x87, 0x07, 0x6b, 0xb4, + 0x07, 0xe0, 0x8f, 0x30, 0xc4, 0xfa, 0x27, 0xae, 0xfc, 0x02, 0xd1, 0x21, + 0x5c, 0xbc, 0x0b, 0x93, 0x6e, 0x7e, 0xf9, 0x6b, 0x80, 0x7a, 0x25, 0x84, + 0x20, 0xf1, 0x6a, 0xfa, 0x75, 0xed, 0x57, 0x61, 0x62, 0xa7, 0xf6, 0x5b, + 0xe1, 0xb0, 0x38, 0xc8, 0xe9, 0x6d, 0x3f, 0xef, 0x1e, 0x99, 0x0b, 0xb7, + 0xc8, 0x9f, 0x76, 0x5c, 0x04, 0x1f, 0x02, 0x92, 0x00, 0xa7, 0x38, 0x3d, + 0x00, 0x3b, 0xa7, 0xbc, 0x39, 0x6e, 0xab, 0xf5, 0x10, 0xa8, 0xba, 0xd6, + 0x28, 0x6b, 0x0e, 0x00, 0x48, 0xf9, 0x3b, 0x5c, 0xde, 0x59, 0x93, 0x46, + 0xd6, 0x61, 0x52, 0x81, 0x71, 0x0f, 0x0e, 0x61, 0xac, 0xc6, 0x7f, 0x15, + 0x93, 0xa7, 0xc1, 0x16, 0xb5, 0xef, 0x85, 0xd1, 0xa7, 0x61, 0xc2, 0x85, + 0x1d, 0x61, 0xc6, 0xae, 0xb3, 0x9e, 0x8d, 0x23, 0xa3, 0xc8, 0xd5, 0xf2, + 0xc7, 0x1b, 0x7e, 0xef, 0xd2, 0xdf, 0x25, 0xaf, 0x4e, 0x81, 0x15, 0x59, + 0xe5, 0x36, 0xb1, 0xf1, 0xd5, 0xda, 0x58, 0xd8, 0xd9, 0x0d, 0x6d, 0xc9, + 0x25, 0xb5, 0xe8, 0x1d, 0x3b, 0xca, 0x2d, 0xab, 0xf2, 0xe2, 0xe9, 0x55, + 0xd7, 0xf4, 0xc7, 0xd0, 0x57, 0x7a, 0x86, 0x15, 0x0a, 0x5a, 0x8b, 0xd7, + 0x3f, 0x66, 0x0f, 0x80, 0xb4, 0xe0, 0x5c, 0x33, 0xed, 0xaf, 0x1b, 0x3b, + 0x6d, 0x1c, 0xd9, 0x8c, 0xb5, 0x96, 0xa3, 0xfb, 0xcf, 0xcc, 0x97, 0x1c, + 0xae, 0x06, 0x19, 0x41, 0x61, 0xf8, 0x97, 0x6b, 0x82, 0x5e, 0x1c, 0xbf, + 0x6f, 0x43, 0x3d, 0xe5, 0x00, 0xf5, 0xfe, 0x66, 0x48, 0x26, 0x31, 0xa1, + 0x72, 0x67, 0x6e, 0xd4, 0x5b, 0x6f, 0x66, 0xde, 0x70, 0x8b, 0x2b, 0xc3, + 0xa2, 0x30, 0xe9, 0x55, 0xc8, 0xff, 0xf8, 0xd0, 0xdd, 0xa9, 0x21, 0x85, + 0x6e, 0x6c, 0x82, 0x66, 0xcc, 0x52, 0xf0, 0x9e, 0x1e, 0xb5, 0x3a, 0xff, + 0x4c, 0xf3, 0xae, 0x02, 0xc3, 0x4b, 0x76, 0x25, 0xbd, 0xb0, 0x21, 0x54, + 0x61, 0xda, 0x16, 0xd3, 0x23, 0x86, 0x41, 0xa1, 0x4c, 0x59, 0x15, 0x95, + 0x65, 0x85, 0xb6, 0x8e, 0xa6, 0x37, 0xc0, 0xa2, 0x71, 0x1d, 0x67, 0x44, + 0x7b, 0xe5, 0x4c, 0x4f, 0xb6, 0x2c, 0x46, 0xf7, 0x29, 0xa5, 0xf2, 0xd3, + 0x51, 0x19, 0x91, 0x4d, 0xa7, 0xb5, 0x05, 0xb9, 0x6e, 0x61, 0x6e, 0xf8, + 0xc0, 0x01, 0xe5, 0x41, 0x0a, 0x89, 0x64, 0x77, 0xf2, 0xc8, 0x63, 0x2d, + 0x9d, 0x27, 0x7f, 0x47, 0x30, 0x39, 0xdf, 0xb6, 0x6e, 0x4f, 0x00, 0x3f, + 0x15, 0xc6, 0xaf, 0x62, 0xdf, 0x3f, 0x47, 0xe8, 0x42, 0x90, 0x77, 0x23, + 0x7a, 0xaa, 0x99, 0x53, 0x03, 0x63, 0x60, 0x59, 0x07, 0x52, 0x3c, 0xb5, + 0x67, 0x59, 0xfe, 0x08, 0xe6, 0x43, 0x0f, 0x3b, 0x08, 0x7c, 0xc7, 0x07, + 0x3c, 0xfa, 0x65, 0xea, 0x69, 0x51, 0x41, 0x31, 0xb3, 0x05, 0x69, 0xba, + 0x2c, 0xbf, 0x89, 0x25, 0x9e, 0xfe, 0x07, 0x13, 0x78, 0x0e, 0x16, 0x54, + 0xdf, 0x23, 0xdf, 0x10, 0x69, 0x79, 0xd0, 0x33, 0xd7, 0x21, 0x8b, 0xc8, + 0x2a, 0xd0, 0x74, 0x0a, 0xfa, 0xb1, 0x6f, 0xa3, 0xcb, 0x1d, 0xca, 0x4f, + 0x00, 0x46, 0x6c, 0x42, 0x09, 0xe0, 0x30, 0x89, 0x08, 0x33, 0x9b, 0x7b, + 0x7b, 0x0f, 0x69, 0x5c, 0x0d, 0x34, 0x91, 0xfc, 0xfe, 0x22, 0x82, 0x02, + 0xcd, 0xfa, 0x97, 0xe8, 0x28, 0x1d, 0xbc, 0x13, 0x0b, 0xfd, 0x47, 0xa1, + 0x7e, 0xa2, 0x86, 0x4d, 0x6f, 0x12, 0x51, 0x35, 0x7d, 0x76, 0x8a, 0x58, + 0x05, 0xb6, 0x39, 0xa1, 0x2f, 0xd7, 0xda, 0xaf, 0x00, 0xa0, 0x1a, 0x94, + 0xd8, 0x23, 0x34, 0x99, 0x5c, 0xaf, 0xcc, 0x15, 0x4b, 0x56, 0xb2, 0xd2, + 0x81, 0x07, 0xd3, 0xf3, 0x47, 0xa2, 0x45, 0x93, 0xcb, 0xae, 0xa7, 0x6b, + 0x3f, 0xf9, 0xea, 0xfc, 0x0e, 0x64, 0xf2, 0x93, 0x7f, 0x24, 0x22, 0x73, + 0x86, 0xc7, 0x2d, 0x75, 0x9b, 0x41, 0x8b, 0xfb, 0x3b, 0x26, 0x2a, 0xe5, + 0x0b, 0xd4, 0x00, 0xe3, 0x2c, 0x69, 0x49, 0x62, 0x6c, 0x13, 0x58, 0x6e, + 0xac, 0x43, 0xe5, 0x2b, 0x3b, 0x88, 0xdc, 0xd4, 0x41, 0xe8, 0xee, 0x4e, + 0xc3, 0x28, 0x91, 0x17, 0x9a, 0x5a, 0xdb, 0x80, 0x8b, 0x4d, 0x64, 0xcc, + 0xbe, 0x66, 0xa4, 0x62, 0xfb, 0x13, 0x44, 0x10, 0xd9, 0xe4, 0xd5, 0xa5, + 0xae, 0x9e, 0x42, 0x50, 0xfc, 0x78, 0xad, 0xfa, 0xc4, 0xd0, 0x5a, 0x60, + 0x9b, 0x45, 0x2b, 0x61, 0x5c, 0x57, 0xb5, 0x92, 0x28, 0xe9, 0xf5, 0x35, + 0x67, 0xc1, 0x5e, 0xa8, 0x1c, 0x99, 0x36, 0x38, 0xb8, 0x5c, 0xff, 0x3d, + 0xa0, 0xfc, 0xb0, 0xbc, 0x3d, 0x2c, 0xb4, 0x36, 0x17, 0xb4, 0x6d, 0xb5, + 0x39, 0x45, 0xa9, 0x2a, 0x6b, 0xa2, 0x24, 0x44, 0x30, 0xab, 0x2c, 0x82, + 0x36, 0xdc, 0xd6, 0x36, 0x5d, 0x0a, 0xdc, 0xee, 0x0f, 0x2b, 0x28, 0x99, + 0xdc, 0x67, 0x0d, 0xea, 0x6e, 0x42, 0xb9, 0x45, 0x7f, 0xd2, 0x96, 0x1e, + 0x60, 0x42, 0xeb, 0x1e, 0x5f, 0x8e, 0xa9, 0xdc, 0xd3, 0x8a, 0xd6, 0xbd, + 0x4e, 0x1f, 0x42, 0x75, 0x1d, 0xe2, 0xc6, 0x11, 0xc9, 0x80, 0x1f, 0xfe, + 0x99, 0x52, 0x4d, 0x7b, 0x35, 0xf7, 0xb7, 0xc3, 0xee, 0xd6, 0x94, 0xf5, + 0x74, 0xa0, 0x69, 0xcd, 0x1f, 0x2b, 0xd0, 0x87, 0xf7, 0x8c, 0x69, 0xc5, + 0x96, 0x70, 0x91, 0xe8, 0x3d, 0xd2, 0xcc, 0xf1, 0x4c, 0xcd, 0xe2, 0x14, + 0x00, 0x10, 0x4a, 0xd9, 0x6a, 0x5d, 0x65, 0x2c, 0x4b, 0x79, 0x0c, 0xc4, + 0x78, 0x5e, 0xc8, 0xc5, 0x37, 0x74, 0x6d, 0x50, 0x5c, 0x34, 0x1f, 0xe0, + 0xf4, 0xe3, 0xe1, 0x86, 0x68, 0xb1, 0xea, 0x70, 0xf0, 0xae, 0xe4, 0x59, + 0xa1, 0x08, 0x7e, 0x35, 0xa3, 0x16, 0xd2, 0xb0, 0xa3, 0xd4, 0xb0, 0x74, + 0x8c, 0x05, 0x79, 0x73, 0xfb, 0xe6, 0x65, 0x96, 0x15, 0x07, 0xd5, 0xaf, + 0x88, 0x9e, 0x6b, 0xf0, 0xbb, 0x3f, 0xe6, 0xd1, 0x6a, 0xe7, 0xc9, 0xae, + 0xd9, 0xb0, 0x16, 0x1c, 0x40, 0xeb, 0xdb, 0xc1, 0xbf, 0x83, 0xdb, 0x8a, + 0x4f, 0x96, 0xca, 0xd7, 0x22, 0x06, 0x87, 0x08, 0x9d, 0x65, 0x2f, 0xd9, + 0x8e, 0x95, 0x6c, 0xcc, 0xbf, 0x76, 0x2a, 0xea, 0x5c, 0x8e, 0x5b, 0x17, + 0x0f, 0x75, 0x7b, 0xfa, 0xf9, 0xfb, 0xaa, 0x92, 0xc7, 0x7e, 0x63, 0x63, + 0x54, 0xa4, 0xff, 0xf6, 0xc0, 0xc0, 0xf5, 0x70, 0xd8, 0xe3, 0xa4, 0x79, + 0x16, 0xf0, 0x6f, 0x90, 0x5e, 0xb7, 0xab, 0x6f, 0xab, 0x75, 0x3b, 0xe1, + 0x4c, 0xa8, 0x0b, 0x72, 0x5f, 0x5f, 0x11, 0x22, 0x36, 0x71, 0x20, 0xd3, + 0x5b, 0x5e, 0x07, 0x06, 0x76, 0x1a, 0xcc, 0x5e, 0x7c, 0x97, 0x7d, 0xb2, + 0x6b, 0xf8, 0x39, 0x89, 0x37, 0xb6, 0x6d, 0xea, 0x74, 0x57, 0x28, 0xd7, + 0x0e, 0x9b, 0xeb, 0x28, 0x88, 0x90, 0xfd, 0x2d, 0x16, 0x21, 0x74, 0x26, + 0xc5, 0xb8, 0x44, 0xad, 0x9f, 0x97, 0xf9, 0x65, 0x36, 0xd8, 0x00, 0x59, + 0x17, 0x49, 0xf9, 0xc7, 0xb3, 0x84, 0xb9, 0xe2, 0x95, 0xe0, 0xd1, 0x7f, + 0x5f, 0xaa, 0xd7, 0xfd, 0x6a, 0x6a, 0x83, 0x14, 0x46, 0x1d, 0x12, 0x8d, + 0x09, 0xc3, 0xa5, 0xca, 0x72, 0xa3, 0x25, 0x65, 0xb6, 0x40, 0x25, 0x04, + 0x51, 0xab, 0x22, 0xeb, 0xd7, 0x69, 0xc9, 0x22, 0x9c, 0xa0, 0x19, 0x5c, + 0x1a, 0xfd, 0x41, 0x8f, 0x98, 0xc5, 0x71, 0xb8, 0x6f, 0x76, 0xae, 0xfa, + 0x9b, 0x03, 0xab, 0x43, 0x81, 0x3b, 0x66, 0xae, 0xf0, 0xd2, 0xb7, 0xee, + 0x9a, 0xe3, 0xae, 0x45, 0xc1, 0x86, 0xb0, 0xce, 0x9e, 0x2b, 0xec, 0xb8, + 0xcf, 0xca, 0x0e, 0x8c, 0x33, 0xfa, 0xa7, 0xef, 0xf7, 0xfc, 0xa1, 0x41, + 0x49, 0xd3, 0x6d, 0xb5, 0x58, 0xe4, 0x0e, 0x24, 0xd2, 0x8a, 0x74, 0xc9, + 0x56, 0x2e, 0x53, 0xc7, 0x7a, 0x38, 0x0f, 0x4b, 0xd9, 0xf9, 0x2f, 0xfa, + 0x7d, 0xee, 0x14, 0x18, 0xce, 0x75, 0x42, 0x6c, 0x03, 0x34, 0xce, 0x80, + 0xec, 0xf2, 0x05, 0xf0, 0xdf, 0xcd, 0xf8, 0xdb, 0x26, 0x7d, 0xb6, 0x3d, + 0x28, 0x24, 0x7e, 0x7e, 0x39, 0x9f, 0xa6, 0xc6, 0xeb, 0x2a, 0xc8, 0x17, + 0x94, 0xa9, 0x89, 0xf5, 0xdf, 0xcb, 0x77, 0xfd, 0xc9, 0x9e, 0x68, 0x98, + 0x7d, 0x04, 0x50, 0x3c, 0x64, 0x1d, 0x66, 0xb0, 0x97, 0x06, 0xb6, 0x08, + 0x5b, 0xe4, 0x17, 0x44, 0xd6, 0x94, 0x39, 0x6b, 0x03, 0x2c, 0xcb, 0x5a, + 0x8d, 0x86, 0x08, 0x23, 0x4f, 0x95, 0xa8, 0x1a, +}; + +static const u8 fips_test_mldsa65_message[] __initconst __maybe_unused = { + 0x1a, 0x84, 0x21, 0x0d, 0x35, 0x7a, 0x88, 0xc8, 0x6a, 0x11, 0xe3, + 0x15, 0x24, 0xec, 0x0d, 0x2e, 0x76, 0xb9, 0xcf, 0x2b, 0x04, 0x25, + 0x16, 0xae, 0x62, 0x42, 0xa0, 0x20, 0x68, 0x25, 0x3e, 0xb4, 0x75, + 0xa7, 0x1d, 0x64, 0xc3, 0xd1, 0x08, 0x07, 0x67, 0xb6, 0xf7, 0x76, + 0x76, 0xf6, 0xd6, 0x62, 0x66, 0x04, 0x89, 0x0c, 0x8f, 0x07, 0xac, + 0xc8, 0x51, 0x77, 0xd9, 0x47, 0x5e, 0xb5, 0x22, 0x20, +}; diff --git a/lib/crypto/mldsa.c b/lib/crypto/mldsa.c index 853cf225c133..ba0c0468956e 100644 --- a/lib/crypto/mldsa.c +++ b/lib/crypto/mldsa.c @@ -13,6 +13,7 @@ #include #include #include +#include "fips-mldsa.h" #define Q 8380417 /* The prime q = 2^23 - 2^13 + 1 */ #define QINV_MOD_2_32 58728449 /* Multiplicative inverse of q mod 2^32 */ @@ -648,5 +649,35 @@ int mldsa_verify(enum mldsa_alg alg, const u8 *sig, size_t sig_len, } EXPORT_SYMBOL_GPL(mldsa_verify); +#ifdef CONFIG_CRYPTO_FIPS +static int __init mldsa_mod_init(void) +{ + if (fips_enabled) { + /* + * FIPS cryptographic algorithm self-test. As per the FIPS + * Implementation Guidance, testing any ML-DSA parameter set + * satisfies the test requirement for all of them, and only a + * positive test is required. + */ + int err = mldsa_verify(MLDSA65, fips_test_mldsa65_signature, + sizeof(fips_test_mldsa65_signature), + fips_test_mldsa65_message, + sizeof(fips_test_mldsa65_message), + fips_test_mldsa65_public_key, + sizeof(fips_test_mldsa65_public_key)); + if (err) + panic("mldsa: FIPS self-test failed; err=%pe\n", + ERR_PTR(err)); + } + return 0; +} +subsys_initcall(mldsa_mod_init); + +static void __exit mldsa_mod_exit(void) +{ +} +module_exit(mldsa_mod_exit); +#endif /* CONFIG_CRYPTO_FIPS */ + MODULE_DESCRIPTION("ML-DSA signature verification"); MODULE_LICENSE("GPL"); From b599aacf12620b6964f140d2833860affc0ab676 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:19:59 -0800 Subject: [PATCH 18/53] crypto: powerpc/aes - Rename struct aes_key Rename struct aes_key in aesp8-ppc.h and aes-gcm-p10-glue.c to p8_aes_key and p10_aes_key, respectively. This frees up the name to use in the library API in . Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-2-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/powerpc/crypto/aes-gcm-p10-glue.c | 4 ++-- arch/powerpc/crypto/aes.c | 4 ++-- arch/powerpc/crypto/aes_cbc.c | 4 ++-- arch/powerpc/crypto/aes_ctr.c | 2 +- arch/powerpc/crypto/aes_xts.c | 6 +++--- arch/powerpc/crypto/aesp8-ppc.h | 23 ++++++++++++----------- 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/arch/powerpc/crypto/aes-gcm-p10-glue.c b/arch/powerpc/crypto/aes-gcm-p10-glue.c index 85f4fd4b1bdc..f3417436d3f7 100644 --- a/arch/powerpc/crypto/aes-gcm-p10-glue.c +++ b/arch/powerpc/crypto/aes-gcm-p10-glue.c @@ -44,7 +44,7 @@ asmlinkage void gcm_ghash_p10(unsigned char *Xi, unsigned char *Htable, unsigned char *aad, unsigned int alen); asmlinkage void gcm_update(u8 *iv, void *Xi); -struct aes_key { +struct p10_aes_key { u8 key[AES_MAX_KEYLENGTH]; u64 rounds; }; @@ -63,7 +63,7 @@ struct Hash_ctx { }; struct p10_aes_gcm_ctx { - struct aes_key enc_key; + struct p10_aes_key enc_key; u8 nonce[RFC4106_NONCE_SIZE]; }; diff --git a/arch/powerpc/crypto/aes.c b/arch/powerpc/crypto/aes.c index 3f1e5e894902..b7192ee719fc 100644 --- a/arch/powerpc/crypto/aes.c +++ b/arch/powerpc/crypto/aes.c @@ -21,8 +21,8 @@ struct p8_aes_ctx { struct crypto_cipher *fallback; - struct aes_key enc_key; - struct aes_key dec_key; + struct p8_aes_key enc_key; + struct p8_aes_key dec_key; }; static int p8_aes_init(struct crypto_tfm *tfm) diff --git a/arch/powerpc/crypto/aes_cbc.c b/arch/powerpc/crypto/aes_cbc.c index 5f2a4f375eef..4a9f285f0970 100644 --- a/arch/powerpc/crypto/aes_cbc.c +++ b/arch/powerpc/crypto/aes_cbc.c @@ -21,8 +21,8 @@ struct p8_aes_cbc_ctx { struct crypto_skcipher *fallback; - struct aes_key enc_key; - struct aes_key dec_key; + struct p8_aes_key enc_key; + struct p8_aes_key dec_key; }; static int p8_aes_cbc_init(struct crypto_skcipher *tfm) diff --git a/arch/powerpc/crypto/aes_ctr.c b/arch/powerpc/crypto/aes_ctr.c index e27c4036e711..7dbd06f442db 100644 --- a/arch/powerpc/crypto/aes_ctr.c +++ b/arch/powerpc/crypto/aes_ctr.c @@ -21,7 +21,7 @@ struct p8_aes_ctr_ctx { struct crypto_skcipher *fallback; - struct aes_key enc_key; + struct p8_aes_key enc_key; }; static int p8_aes_ctr_init(struct crypto_skcipher *tfm) diff --git a/arch/powerpc/crypto/aes_xts.c b/arch/powerpc/crypto/aes_xts.c index 9440e771cede..b4c760e465ea 100644 --- a/arch/powerpc/crypto/aes_xts.c +++ b/arch/powerpc/crypto/aes_xts.c @@ -22,9 +22,9 @@ struct p8_aes_xts_ctx { struct crypto_skcipher *fallback; - struct aes_key enc_key; - struct aes_key dec_key; - struct aes_key tweak_key; + struct p8_aes_key enc_key; + struct p8_aes_key dec_key; + struct p8_aes_key tweak_key; }; static int p8_aes_xts_init(struct crypto_skcipher *tfm) diff --git a/arch/powerpc/crypto/aesp8-ppc.h b/arch/powerpc/crypto/aesp8-ppc.h index 5764d4438388..0bea010128cb 100644 --- a/arch/powerpc/crypto/aesp8-ppc.h +++ b/arch/powerpc/crypto/aesp8-ppc.h @@ -2,7 +2,7 @@ #include #include -struct aes_key { +struct p8_aes_key { u8 key[AES_MAX_KEYLENGTH]; int rounds; }; @@ -14,17 +14,18 @@ extern struct skcipher_alg p8_aes_ctr_alg; extern struct skcipher_alg p8_aes_xts_alg; int aes_p8_set_encrypt_key(const u8 *userKey, const int bits, - struct aes_key *key); + struct p8_aes_key *key); int aes_p8_set_decrypt_key(const u8 *userKey, const int bits, - struct aes_key *key); -void aes_p8_encrypt(const u8 *in, u8 *out, const struct aes_key *key); -void aes_p8_decrypt(const u8 *in, u8 *out, const struct aes_key *key); + struct p8_aes_key *key); +void aes_p8_encrypt(const u8 *in, u8 *out, const struct p8_aes_key *key); +void aes_p8_decrypt(const u8 *in, u8 *out, const struct p8_aes_key *key); void aes_p8_cbc_encrypt(const u8 *in, u8 *out, size_t len, - const struct aes_key *key, u8 *iv, const int enc); -void aes_p8_ctr32_encrypt_blocks(const u8 *in, u8 *out, - size_t len, const struct aes_key *key, - const u8 *iv); + const struct p8_aes_key *key, u8 *iv, const int enc); +void aes_p8_ctr32_encrypt_blocks(const u8 *in, u8 *out, size_t len, + const struct p8_aes_key *key, const u8 *iv); void aes_p8_xts_encrypt(const u8 *in, u8 *out, size_t len, - const struct aes_key *key1, const struct aes_key *key2, u8 *iv); + const struct p8_aes_key *key1, + const struct p8_aes_key *key2, u8 *iv); void aes_p8_xts_decrypt(const u8 *in, u8 *out, size_t len, - const struct aes_key *key1, const struct aes_key *key2, u8 *iv); + const struct p8_aes_key *key1, + const struct p8_aes_key *key2, u8 *iv); From a22fd0e3c495dd2d706c49c26663476e24d96e7d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:00 -0800 Subject: [PATCH 19/53] lib/crypto: aes: Introduce improved AES library The kernel's AES library currently has the following issues: - It doesn't take advantage of the architecture-optimized AES code, including the implementations using AES instructions. - It's much slower than even the other software AES implementations: 2-4 times slower than "aes-generic", "aes-arm", and "aes-arm64". - It requires that both the encryption and decryption round keys be computed and cached. This is wasteful for users that need only the forward (encryption) direction of the cipher: the key struct is 484 bytes when only 244 are actually needed. This missed optimization is very common, as many AES modes (e.g. GCM, CFB, CTR, CMAC, and even the tweak key in XTS) use the cipher only in the forward (encryption) direction even when doing decryption. - It doesn't provide the flexibility to customize the prepared key format. The API is defined to do key expansion, and several callers in drivers/crypto/ use it specifically to expand the key. This is an issue when integrating the existing powerpc, s390, and sparc code, which is necessary to provide full parity with the traditional API. To resolve these issues, I'm proposing the following changes: 1. New structs 'aes_key' and 'aes_enckey' are introduced, with corresponding functions aes_preparekey() and aes_prepareenckey(). Generally these structs will include the encryption+decryption round keys and the encryption round keys, respectively. However, the exact format will be under control of the architecture-specific AES code. (The verb "prepare" is chosen over "expand" since key expansion isn't necessarily done. It's also consistent with hmac*_preparekey().) 2. aes_encrypt() and aes_decrypt() will be changed to operate on the new structs instead of struct crypto_aes_ctx. 3. aes_encrypt() and aes_decrypt() will use architecture-optimized code when available, or else fall back to a new generic AES implementation that unifies the existing two fragmented generic AES implementations. The new generic AES implementation uses tables for both SubBytes and MixColumns, making it almost as fast as "aes-generic". However, instead of aes-generic's huge 8192-byte tables per direction, it uses only 1024 bytes for encryption and 1280 bytes for decryption (similar to "aes-arm"). The cost is just some extra rotations. The new generic AES implementation also includes table prefetching, making it have some "constant-time hardening". That's an improvement from aes-generic which has no constant-time hardening. It does slightly regress in constant-time hardening vs. the old lib/crypto/aes.c which had smaller tables, and from aes-fixed-time which disabled IRQs on top of that. But I think this is tolerable. The real solutions for constant-time AES are AES instructions or bit-slicing. The table-based code remains a best-effort fallback for the increasingly-rare case where a real solution is unavailable. 4. crypto_aes_ctx and aes_expandkey() will remain for now, but only for callers that are using them specifically for the AES key expansion (as opposed to en/decrypting data with the AES library). This commit begins the migration process by introducing the new structs and functions, backed by the new generic AES implementation. To allow callers to be incrementally converted, aes_encrypt() and aes_decrypt() are temporarily changed into macros that use a _Generic expression to call either the old functions (which take crypto_aes_ctx) or the new functions (which take the new types). Once all callers have been updated, these macros will go away, the old functions will be removed, and the "_new" suffix will be dropped from the new functions. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-3-ebiggers@kernel.org Signed-off-by: Eric Biggers --- include/crypto/aes.h | 157 +++++++++++++++-- lib/crypto/Kconfig | 4 + lib/crypto/Makefile | 11 +- lib/crypto/aes.c | 397 +++++++++++++++++++++++++++++++++++++------ 4 files changed, 500 insertions(+), 69 deletions(-) diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 9339da7c20a8..e8b83d4849fe 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -18,6 +18,60 @@ #define AES_MAX_KEYLENGTH (15 * 16) #define AES_MAX_KEYLENGTH_U32 (AES_MAX_KEYLENGTH / sizeof(u32)) +union aes_enckey_arch { + u32 rndkeys[AES_MAX_KEYLENGTH_U32]; +}; + +union aes_invkey_arch { + u32 inv_rndkeys[AES_MAX_KEYLENGTH_U32]; +}; + +/** + * struct aes_enckey - An AES key prepared for encryption + * @len: Key length in bytes: 16 for AES-128, 24 for AES-192, 32 for AES-256. + * @nrounds: Number of rounds: 10 for AES-128, 12 for AES-192, 14 for AES-256. + * This is '6 + @len / 4' and is cached so that AES implementations + * that need it don't have to recompute it for each en/decryption. + * @padding: Padding to make offsetof(@k) be a multiple of 16, so that aligning + * this struct to a 16-byte boundary results in @k also being 16-byte + * aligned. Users aren't required to align this struct to 16 bytes, + * but it may slightly improve performance. + * @k: This typically contains the AES round keys as an array of '@nrounds + 1' + * groups of four u32 words. However, architecture-specific implementations + * of AES may store something else here, e.g. just the raw key if it's all + * they need. + * + * Note that this struct is about half the size of struct aes_key. This is + * separate from struct aes_key so that modes that need only AES encryption + * (e.g. AES-GCM, AES-CTR, AES-CMAC, tweak key in AES-XTS) don't incur the time + * and space overhead of computing and caching the decryption round keys. + * + * Note that there's no decryption-only equivalent (i.e. "struct aes_deckey"), + * since (a) it's rare that modes need decryption-only, and (b) some AES + * implementations use the same @k for both encryption and decryption, either + * always or conditionally; in the latter case both @k and @inv_k are needed. + */ +struct aes_enckey { + u32 len; + u32 nrounds; + u32 padding[2]; + union aes_enckey_arch k; +}; + +/** + * struct aes_key - An AES key prepared for encryption and decryption + * @aes_enckey: Common fields and the key prepared for encryption + * @inv_k: This generally contains the round keys for the AES Equivalent + * Inverse Cipher, as an array of '@nrounds + 1' groups of four u32 + * words. However, architecture-specific implementations of AES may + * store something else here. For example, they may leave this field + * uninitialized if they use @k for both encryption and decryption. + */ +struct aes_key { + struct aes_enckey; /* Include all fields of aes_enckey. */ + union aes_invkey_arch inv_k; +}; + /* * Please ensure that the first two fields are 16-byte aligned * relative to the start of the structure, i.e., don't move them! @@ -34,7 +88,7 @@ extern const u32 crypto_it_tab[4][256] ____cacheline_aligned; /* * validate key length for AES algorithms */ -static inline int aes_check_keylen(unsigned int keylen) +static inline int aes_check_keylen(size_t keylen) { switch (keylen) { case AES_KEYSIZE_128: @@ -69,23 +123,104 @@ int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, unsigned int key_len); /** - * aes_encrypt - Encrypt a single AES block - * @ctx: Context struct containing the key schedule - * @out: Buffer to store the ciphertext - * @in: Buffer containing the plaintext + * aes_preparekey() - Prepare an AES key for encryption and decryption + * @key: (output) The key structure to initialize + * @in_key: The raw AES key + * @key_len: Length of the raw key in bytes. Should be either AES_KEYSIZE_128, + * AES_KEYSIZE_192, or AES_KEYSIZE_256. + * + * This prepares an AES key for both the encryption and decryption directions of + * the block cipher. Typically this involves expanding the raw key into both + * the standard round keys and the Equivalent Inverse Cipher round keys, but + * some architecture-specific implementations don't do the full expansion here. + * + * The caller is responsible for zeroizing both the struct aes_key and the raw + * key once they are no longer needed. + * + * If you don't need decryption support, use aes_prepareenckey() instead. + * + * Return: 0 on success or -EINVAL if the given key length is invalid. No other + * errors are possible, so callers that always pass a valid key length + * don't need to check for errors. + * + * Context: Any context. */ -void aes_encrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); +int aes_preparekey(struct aes_key *key, const u8 *in_key, size_t key_len); /** - * aes_decrypt - Decrypt a single AES block - * @ctx: Context struct containing the key schedule - * @out: Buffer to store the plaintext - * @in: Buffer containing the ciphertext + * aes_prepareenckey() - Prepare an AES key for encryption-only + * @key: (output) The key structure to initialize + * @in_key: The raw AES key + * @key_len: Length of the raw key in bytes. Should be either AES_KEYSIZE_128, + * AES_KEYSIZE_192, or AES_KEYSIZE_256. + * + * This prepares an AES key for only the encryption direction of the block + * cipher. Typically this involves expanding the raw key into only the standard + * round keys, resulting in a struct about half the size of struct aes_key. + * + * The caller is responsible for zeroizing both the struct aes_enckey and the + * raw key once they are no longer needed. + * + * Note that while the resulting prepared key supports only AES encryption, it + * can still be used for decrypting in a mode of operation that uses AES in only + * the encryption (forward) direction, for example counter mode. + * + * Return: 0 on success or -EINVAL if the given key length is invalid. No other + * errors are possible, so callers that always pass a valid key length + * don't need to check for errors. + * + * Context: Any context. */ -void aes_decrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); +int aes_prepareenckey(struct aes_enckey *key, const u8 *in_key, size_t key_len); + +typedef union { + const struct aes_enckey *enc_key; + const struct aes_key *full_key; +} aes_encrypt_arg __attribute__ ((__transparent_union__)); + +/** + * aes_encrypt() - Encrypt a single AES block + * @key: The AES key, as a pointer to either an encryption-only key + * (struct aes_enckey) or a full, bidirectional key (struct aes_key). + * @out: Buffer to store the ciphertext block + * @in: Buffer containing the plaintext block + * + * Context: Any context. + */ +#define aes_encrypt(key, out, in) \ + _Generic((key), \ + struct crypto_aes_ctx *: aes_encrypt_old((const struct crypto_aes_ctx *)(key), (out), (in)), \ + const struct crypto_aes_ctx *: aes_encrypt_old((const struct crypto_aes_ctx *)(key), (out), (in)), \ + struct aes_enckey *: aes_encrypt_new((const struct aes_enckey *)(key), (out), (in)), \ + const struct aes_enckey *: aes_encrypt_new((const struct aes_enckey *)(key), (out), (in)), \ + struct aes_key *: aes_encrypt_new((const struct aes_key *)(key), (out), (in)), \ + const struct aes_key *: aes_encrypt_new((const struct aes_key *)(key), (out), (in))) +void aes_encrypt_old(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); +void aes_encrypt_new(aes_encrypt_arg key, u8 out[at_least AES_BLOCK_SIZE], + const u8 in[at_least AES_BLOCK_SIZE]); + +/** + * aes_decrypt() - Decrypt a single AES block + * @key: The AES key, previously initialized by aes_preparekey() + * @out: Buffer to store the plaintext block + * @in: Buffer containing the ciphertext block + * + * Context: Any context. + */ +#define aes_decrypt(key, out, in) \ + _Generic((key), \ + struct crypto_aes_ctx *: aes_decrypt_old((const struct crypto_aes_ctx *)(key), (out), (in)), \ + const struct crypto_aes_ctx *: aes_decrypt_old((const struct crypto_aes_ctx *)(key), (out), (in)), \ + struct aes_key *: aes_decrypt_new((const struct aes_key *)(key), (out), (in)), \ + const struct aes_key *: aes_decrypt_new((const struct aes_key *)(key), (out), (in))) +void aes_decrypt_old(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); +void aes_decrypt_new(const struct aes_key *key, u8 out[at_least AES_BLOCK_SIZE], + const u8 in[at_least AES_BLOCK_SIZE]); extern const u8 crypto_aes_sbox[]; extern const u8 crypto_aes_inv_sbox[]; +extern const u32 aes_enc_tab[256]; +extern const u32 aes_dec_tab[256]; void aescfb_encrypt(const struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src, int len, const u8 iv[AES_BLOCK_SIZE]); diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 781a42c5c572..4efad77daa24 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -11,6 +11,10 @@ config CRYPTO_LIB_UTILS config CRYPTO_LIB_AES tristate +config CRYPTO_LIB_AES_ARCH + bool + depends on CRYPTO_LIB_AES && !UML && !KMSAN + config CRYPTO_LIB_AESCFB tristate select CRYPTO_LIB_AES diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 45128eccedef..01193b3f47ba 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -15,8 +15,15 @@ obj-$(CONFIG_CRYPTO_HASH_INFO) += hash_info.o obj-$(CONFIG_CRYPTO_LIB_UTILS) += libcryptoutils.o libcryptoutils-y := memneq.o utils.o -obj-$(CONFIG_CRYPTO_LIB_AES) += libaes.o -libaes-y := aes.o +################################################################################ + +obj-$(CONFIG_CRYPTO_LIB_AES) += libaes.o +libaes-y := aes.o +ifeq ($(CONFIG_CRYPTO_LIB_AES_ARCH),y) +CFLAGS_aes.o += -I$(src)/$(SRCARCH) +endif # CONFIG_CRYPTO_LIB_AES_ARCH + +################################################################################ obj-$(CONFIG_CRYPTO_LIB_AESCFB) += libaescfb.o libaescfb-y := aescfb.o diff --git a/lib/crypto/aes.c b/lib/crypto/aes.c index 102aaa76bc8d..88da68dcf5a8 100644 --- a/lib/crypto/aes.c +++ b/lib/crypto/aes.c @@ -1,9 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2017-2019 Linaro Ltd + * Copyright 2026 Google LLC */ #include +#include #include #include #include @@ -89,6 +91,110 @@ extern const u8 crypto_aes_inv_sbox[256] __alias(aes_inv_sbox); EXPORT_SYMBOL(crypto_aes_sbox); EXPORT_SYMBOL(crypto_aes_inv_sbox); +/* aes_enc_tab[i] contains MixColumn([SubByte(i), 0, 0, 0]). */ +const u32 ____cacheline_aligned aes_enc_tab[256] = { + 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6, + 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, + 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 0x45caca8f, 0x9d82821f, + 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, + 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, + 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, + 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551, + 0x34e5e5d1, 0x08f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, + 0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, + 0x0f05050a, 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, + 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d, + 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, + 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, + 0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, + 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d, + 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, + 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, + 0x55333366, 0x94858511, 0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe, + 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, + 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1, + 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5, + 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, + 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755, + 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, + 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, + 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, + 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264, + 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8, + 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, + 0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, + 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac, + 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, + 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657, + 0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, + 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c, + 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c, + 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, + 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, + 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, + 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, + 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, + 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, + 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c, +}; +EXPORT_SYMBOL(aes_enc_tab); + +/* aes_dec_tab[i] contains InvMixColumn([InvSubByte(i), 0, 0, 0]). */ +const u32 ____cacheline_aligned aes_dec_tab[256] = { + 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, + 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, + 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, 0x495ab1de, 0x671bba25, + 0x980eea45, 0xe1c0fe5d, 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, + 0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458, + 0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927, + 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 0x184adf63, 0x82311ae5, + 0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, + 0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, + 0x578f1fe3, 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3, + 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a, 0x92b479a7, + 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4, + 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040, + 0x069f715e, 0x51106ebd, 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, + 0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6, + 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, + 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000, 0x83868009, 0x48ed2b32, + 0xac70111e, 0x4e725a6c, 0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36, + 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, + 0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, + 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0x0b0d090e, 0xadc78bf2, + 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, + 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 0x7629438b, 0xdcc623cb, + 0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, + 0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc, + 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, + 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, 0xc74e4987, 0xc1d138d9, + 0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, + 0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, + 0x5ef7392e, 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf, + 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd, 0xf418596e, + 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef, + 0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 0xafb2a431, 0x31233f2a, + 0x3094a5c6, 0xc066a235, 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, + 0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43, + 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546, + 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92, + 0x335610e9, 0x1347d66d, 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, + 0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, + 0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, + 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0x0c25e2bc, + 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, + 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0, +}; +EXPORT_SYMBOL(aes_dec_tab); + +/* Prefetch data into L1 cache. @mem should be cacheline-aligned. */ +static __always_inline void aes_prefetch(const void *mem, size_t len) +{ + for (size_t i = 0; i < len; i += L1_CACHE_BYTES) + *(volatile const u8 *)(mem + i); + barrier(); +} + static u32 mul_by_x(u32 w) { u32 x = w & 0x7f7f7f7f; @@ -169,38 +275,17 @@ static u32 subw(u32 in) (aes_sbox[(in >> 24) & 0xff] << 24); } -/** - * aes_expandkey - Expands the AES key as described in FIPS-197 - * @ctx: The location where the computed key will be stored. - * @in_key: The supplied key. - * @key_len: The length of the supplied key. - * - * Returns 0 on success. The function fails only if an invalid key size (or - * pointer) is supplied. - * The expanded key size is 240 bytes (max of 14 rounds with a unique 16 bytes - * key schedule plus a 16 bytes key which is used before the first round). - * The decryption key is prepared for the "Equivalent Inverse Cipher" as - * described in FIPS-197. The first slot (16 bytes) of each key (enc or dec) is - * for the initial combination, the second slot for the first round and so on. - */ -int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, - unsigned int key_len) +static void aes_expandkey_generic(u32 rndkeys[], u32 *inv_rndkeys, + const u8 *in_key, int key_len) { u32 kwords = key_len / sizeof(u32); u32 rc, i, j; - int err; - - err = aes_check_keylen(key_len); - if (err) - return err; - - ctx->key_length = key_len; for (i = 0; i < kwords; i++) - ctx->key_enc[i] = get_unaligned_le32(in_key + i * sizeof(u32)); + rndkeys[i] = get_unaligned_le32(&in_key[i * sizeof(u32)]); for (i = 0, rc = 1; i < 10; i++, rc = mul_by_x(rc)) { - u32 *rki = ctx->key_enc + (i * kwords); + u32 *rki = &rndkeys[i * kwords]; u32 *rko = rki + kwords; rko[0] = ror32(subw(rki[kwords - 1]), 8) ^ rc ^ rki[0]; @@ -229,34 +314,38 @@ int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, * the Inverse Mix Columns transformation to all but the first and * the last one. */ - ctx->key_dec[0] = ctx->key_enc[key_len + 24]; - ctx->key_dec[1] = ctx->key_enc[key_len + 25]; - ctx->key_dec[2] = ctx->key_enc[key_len + 26]; - ctx->key_dec[3] = ctx->key_enc[key_len + 27]; + if (inv_rndkeys) { + inv_rndkeys[0] = rndkeys[key_len + 24]; + inv_rndkeys[1] = rndkeys[key_len + 25]; + inv_rndkeys[2] = rndkeys[key_len + 26]; + inv_rndkeys[3] = rndkeys[key_len + 27]; - for (i = 4, j = key_len + 20; j > 0; i += 4, j -= 4) { - ctx->key_dec[i] = inv_mix_columns(ctx->key_enc[j]); - ctx->key_dec[i + 1] = inv_mix_columns(ctx->key_enc[j + 1]); - ctx->key_dec[i + 2] = inv_mix_columns(ctx->key_enc[j + 2]); - ctx->key_dec[i + 3] = inv_mix_columns(ctx->key_enc[j + 3]); + for (i = 4, j = key_len + 20; j > 0; i += 4, j -= 4) { + inv_rndkeys[i] = inv_mix_columns(rndkeys[j]); + inv_rndkeys[i + 1] = inv_mix_columns(rndkeys[j + 1]); + inv_rndkeys[i + 2] = inv_mix_columns(rndkeys[j + 2]); + inv_rndkeys[i + 3] = inv_mix_columns(rndkeys[j + 3]); + } + + inv_rndkeys[i] = rndkeys[0]; + inv_rndkeys[i + 1] = rndkeys[1]; + inv_rndkeys[i + 2] = rndkeys[2]; + inv_rndkeys[i + 3] = rndkeys[3]; } +} - ctx->key_dec[i] = ctx->key_enc[0]; - ctx->key_dec[i + 1] = ctx->key_enc[1]; - ctx->key_dec[i + 2] = ctx->key_enc[2]; - ctx->key_dec[i + 3] = ctx->key_enc[3]; - +int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, + unsigned int key_len) +{ + if (aes_check_keylen(key_len) != 0) + return -EINVAL; + ctx->key_length = key_len; + aes_expandkey_generic(ctx->key_enc, ctx->key_dec, in_key, key_len); return 0; } EXPORT_SYMBOL(aes_expandkey); -/** - * aes_encrypt - Encrypt a single AES block - * @ctx: Context struct containing the key schedule - * @out: Buffer to store the ciphertext - * @in: Buffer containing the plaintext - */ -void aes_encrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in) +void aes_encrypt_old(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in) { const u32 *rkp = ctx->key_enc + 4; int rounds = 6 + ctx->key_length / 4; @@ -299,15 +388,117 @@ void aes_encrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in) put_unaligned_le32(subshift(st1, 2) ^ rkp[6], out + 8); put_unaligned_le32(subshift(st1, 3) ^ rkp[7], out + 12); } -EXPORT_SYMBOL(aes_encrypt); +EXPORT_SYMBOL(aes_encrypt_old); -/** - * aes_decrypt - Decrypt a single AES block - * @ctx: Context struct containing the key schedule - * @out: Buffer to store the plaintext - * @in: Buffer containing the ciphertext - */ -void aes_decrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in) +static __always_inline u32 enc_quarterround(const u32 w[4], int i, u32 rk) +{ + return rk ^ aes_enc_tab[(u8)w[i]] ^ + rol32(aes_enc_tab[(u8)(w[(i + 1) % 4] >> 8)], 8) ^ + rol32(aes_enc_tab[(u8)(w[(i + 2) % 4] >> 16)], 16) ^ + rol32(aes_enc_tab[(u8)(w[(i + 3) % 4] >> 24)], 24); +} + +static __always_inline u32 enclast_quarterround(const u32 w[4], int i, u32 rk) +{ + return rk ^ ((aes_enc_tab[(u8)w[i]] & 0x0000ff00) >> 8) ^ + (aes_enc_tab[(u8)(w[(i + 1) % 4] >> 8)] & 0x0000ff00) ^ + ((aes_enc_tab[(u8)(w[(i + 2) % 4] >> 16)] & 0x0000ff00) << 8) ^ + ((aes_enc_tab[(u8)(w[(i + 3) % 4] >> 24)] & 0x0000ff00) << 16); +} + +static void __maybe_unused aes_encrypt_generic(const u32 rndkeys[], int nrounds, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + const u32 *rkp = rndkeys; + int n = nrounds - 1; + u32 w[4]; + + w[0] = get_unaligned_le32(&in[0]) ^ *rkp++; + w[1] = get_unaligned_le32(&in[4]) ^ *rkp++; + w[2] = get_unaligned_le32(&in[8]) ^ *rkp++; + w[3] = get_unaligned_le32(&in[12]) ^ *rkp++; + + /* + * Prefetch the table before doing data and key-dependent loads from it. + * + * This is intended only as a basic constant-time hardening measure that + * avoids interfering with performance too much. Its effectiveness is + * not guaranteed. For proper constant-time AES, a CPU that supports + * AES instructions should be used instead. + */ + aes_prefetch(aes_enc_tab, sizeof(aes_enc_tab)); + + do { + u32 w0 = enc_quarterround(w, 0, *rkp++); + u32 w1 = enc_quarterround(w, 1, *rkp++); + u32 w2 = enc_quarterround(w, 2, *rkp++); + u32 w3 = enc_quarterround(w, 3, *rkp++); + + w[0] = w0; + w[1] = w1; + w[2] = w2; + w[3] = w3; + } while (--n); + + put_unaligned_le32(enclast_quarterround(w, 0, *rkp++), &out[0]); + put_unaligned_le32(enclast_quarterround(w, 1, *rkp++), &out[4]); + put_unaligned_le32(enclast_quarterround(w, 2, *rkp++), &out[8]); + put_unaligned_le32(enclast_quarterround(w, 3, *rkp++), &out[12]); +} + +static __always_inline u32 dec_quarterround(const u32 w[4], int i, u32 rk) +{ + return rk ^ aes_dec_tab[(u8)w[i]] ^ + rol32(aes_dec_tab[(u8)(w[(i + 3) % 4] >> 8)], 8) ^ + rol32(aes_dec_tab[(u8)(w[(i + 2) % 4] >> 16)], 16) ^ + rol32(aes_dec_tab[(u8)(w[(i + 1) % 4] >> 24)], 24); +} + +static __always_inline u32 declast_quarterround(const u32 w[4], int i, u32 rk) +{ + return rk ^ aes_inv_sbox[(u8)w[i]] ^ + ((u32)aes_inv_sbox[(u8)(w[(i + 3) % 4] >> 8)] << 8) ^ + ((u32)aes_inv_sbox[(u8)(w[(i + 2) % 4] >> 16)] << 16) ^ + ((u32)aes_inv_sbox[(u8)(w[(i + 1) % 4] >> 24)] << 24); +} + +static void __maybe_unused aes_decrypt_generic(const u32 inv_rndkeys[], + int nrounds, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + const u32 *rkp = inv_rndkeys; + int n = nrounds - 1; + u32 w[4]; + + w[0] = get_unaligned_le32(&in[0]) ^ *rkp++; + w[1] = get_unaligned_le32(&in[4]) ^ *rkp++; + w[2] = get_unaligned_le32(&in[8]) ^ *rkp++; + w[3] = get_unaligned_le32(&in[12]) ^ *rkp++; + + aes_prefetch(aes_dec_tab, sizeof(aes_dec_tab)); + + do { + u32 w0 = dec_quarterround(w, 0, *rkp++); + u32 w1 = dec_quarterround(w, 1, *rkp++); + u32 w2 = dec_quarterround(w, 2, *rkp++); + u32 w3 = dec_quarterround(w, 3, *rkp++); + + w[0] = w0; + w[1] = w1; + w[2] = w2; + w[3] = w3; + } while (--n); + + aes_prefetch((const void *)aes_inv_sbox, sizeof(aes_inv_sbox)); + put_unaligned_le32(declast_quarterround(w, 0, *rkp++), &out[0]); + put_unaligned_le32(declast_quarterround(w, 1, *rkp++), &out[4]); + put_unaligned_le32(declast_quarterround(w, 2, *rkp++), &out[8]); + put_unaligned_le32(declast_quarterround(w, 3, *rkp++), &out[12]); +} + +void aes_decrypt_old(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in) { const u32 *rkp = ctx->key_dec + 4; int rounds = 6 + ctx->key_length / 4; @@ -350,8 +541,102 @@ void aes_decrypt(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in) put_unaligned_le32(inv_subshift(st1, 2) ^ rkp[6], out + 8); put_unaligned_le32(inv_subshift(st1, 3) ^ rkp[7], out + 12); } -EXPORT_SYMBOL(aes_decrypt); +EXPORT_SYMBOL(aes_decrypt_old); -MODULE_DESCRIPTION("Generic AES library"); +/* + * Note: the aes_prepare*key_* names reflect the fact that the implementation + * might not actually expand the key. (The s390 code for example doesn't.) + * Where the key is expanded we use the more specific names aes_expandkey_*. + * + * aes_preparekey_arch() is passed an optional pointer 'inv_k' which points to + * the area to store the prepared decryption key. It will be NULL if the user + * is requesting encryption-only. aes_preparekey_arch() is also passed a valid + * 'key_len' and 'nrounds', corresponding to AES-128, AES-192, or AES-256. + */ +#ifdef CONFIG_CRYPTO_LIB_AES_ARCH +/* An arch-specific implementation of AES is available. Include it. */ +#include "aes.h" /* $(SRCARCH)/aes.h */ +#else +/* No arch-specific implementation of AES is available. Use generic code. */ + +static void aes_preparekey_arch(union aes_enckey_arch *k, + union aes_invkey_arch *inv_k, + const u8 *in_key, int key_len, int nrounds) +{ + aes_expandkey_generic(k->rndkeys, inv_k ? inv_k->inv_rndkeys : NULL, + in_key, key_len); +} + +static void aes_encrypt_arch(const struct aes_enckey *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + aes_encrypt_generic(key->k.rndkeys, key->nrounds, out, in); +} + +static void aes_decrypt_arch(const struct aes_key *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + aes_decrypt_generic(key->inv_k.inv_rndkeys, key->nrounds, out, in); +} +#endif + +static int __aes_preparekey(struct aes_enckey *enc_key, + union aes_invkey_arch *inv_k, + const u8 *in_key, size_t key_len) +{ + if (aes_check_keylen(key_len) != 0) + return -EINVAL; + enc_key->len = key_len; + enc_key->nrounds = 6 + key_len / 4; + aes_preparekey_arch(&enc_key->k, inv_k, in_key, key_len, + enc_key->nrounds); + return 0; +} + +int aes_preparekey(struct aes_key *key, const u8 *in_key, size_t key_len) +{ + return __aes_preparekey((struct aes_enckey *)key, &key->inv_k, + in_key, key_len); +} +EXPORT_SYMBOL(aes_preparekey); + +int aes_prepareenckey(struct aes_enckey *key, const u8 *in_key, size_t key_len) +{ + return __aes_preparekey(key, NULL, in_key, key_len); +} +EXPORT_SYMBOL(aes_prepareenckey); + +void aes_encrypt_new(aes_encrypt_arg key, u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + aes_encrypt_arch(key.enc_key, out, in); +} +EXPORT_SYMBOL(aes_encrypt_new); + +void aes_decrypt_new(const struct aes_key *key, u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + aes_decrypt_arch(key, out, in); +} +EXPORT_SYMBOL(aes_decrypt_new); + +#ifdef aes_mod_init_arch +static int __init aes_mod_init(void) +{ + aes_mod_init_arch(); + return 0; +} +subsys_initcall(aes_mod_init); + +static void __exit aes_mod_exit(void) +{ +} +module_exit(aes_mod_exit); +#endif + +MODULE_DESCRIPTION("AES block cipher"); MODULE_AUTHOR("Ard Biesheuvel "); +MODULE_AUTHOR("Eric Biggers "); MODULE_LICENSE("GPL v2"); From a4e4e44649ba5f2d59f056ba59885fb080caa22e Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:01 -0800 Subject: [PATCH 20/53] crypto: arm/aes-neonbs - Use AES library for single blocks aes-neonbs-glue.c calls __aes_arm_encrypt() and __aes_arm_decrypt() to en/decrypt single blocks for CBC encryption, XTS tweak encryption, and XTS ciphertext stealing. In preparation for making the AES library use this same ARM-optimized single-block AES en/decryption code and making it an internal implementation detail of the AES library, replace the calls to these functions with calls to the AES library. Note that this reduces the size of the aesbs_cbc_ctx and aesbs_xts_ctx structs, since unnecessary decryption round keys are no longer included. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-4-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/arm/crypto/Kconfig | 1 - arch/arm/crypto/aes-neonbs-glue.c | 29 ++++++++++++++++------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig index 3eb5071bea14..167a648a9def 100644 --- a/arch/arm/crypto/Kconfig +++ b/arch/arm/crypto/Kconfig @@ -44,7 +44,6 @@ config CRYPTO_AES_ARM config CRYPTO_AES_ARM_BS tristate "Ciphers: AES, modes: ECB/CBC/CTR/XTS (bit-sliced NEON)" depends on KERNEL_MODE_NEON - select CRYPTO_AES_ARM select CRYPTO_SKCIPHER select CRYPTO_LIB_AES help diff --git a/arch/arm/crypto/aes-neonbs-glue.c b/arch/arm/crypto/aes-neonbs-glue.c index df5afe601e4a..c49ddafc54f3 100644 --- a/arch/arm/crypto/aes-neonbs-glue.c +++ b/arch/arm/crypto/aes-neonbs-glue.c @@ -12,7 +12,6 @@ #include #include #include -#include "aes-cipher.h" MODULE_AUTHOR("Ard Biesheuvel "); MODULE_DESCRIPTION("Bit sliced AES using NEON instructions"); @@ -48,13 +47,13 @@ struct aesbs_ctx { struct aesbs_cbc_ctx { struct aesbs_ctx key; - struct crypto_aes_ctx fallback; + struct aes_enckey fallback; }; struct aesbs_xts_ctx { struct aesbs_ctx key; - struct crypto_aes_ctx fallback; - struct crypto_aes_ctx tweak_key; + struct aes_key fallback; + struct aes_enckey tweak_key; }; static int aesbs_setkey(struct crypto_skcipher *tfm, const u8 *in_key, @@ -122,14 +121,19 @@ static int aesbs_cbc_setkey(struct crypto_skcipher *tfm, const u8 *in_key, struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); int err; - err = aes_expandkey(&ctx->fallback, in_key, key_len); + err = aes_prepareenckey(&ctx->fallback, in_key, key_len); if (err) return err; ctx->key.rounds = 6 + key_len / 4; + /* + * Note: this assumes that the arm implementation of the AES library + * stores the standard round keys in k.rndkeys. + */ kernel_neon_begin(); - aesbs_convert_key(ctx->key.rk, ctx->fallback.key_enc, ctx->key.rounds); + aesbs_convert_key(ctx->key.rk, ctx->fallback.k.rndkeys, + ctx->key.rounds); kernel_neon_end(); return 0; @@ -152,8 +156,7 @@ static int cbc_encrypt(struct skcipher_request *req) do { crypto_xor_cpy(dst, src, prev, AES_BLOCK_SIZE); - __aes_arm_encrypt(ctx->fallback.key_enc, - ctx->key.rounds, dst, dst); + aes_encrypt(&ctx->fallback, dst, dst); prev = dst; src += AES_BLOCK_SIZE; dst += AES_BLOCK_SIZE; @@ -239,10 +242,10 @@ static int aesbs_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key, return err; key_len /= 2; - err = aes_expandkey(&ctx->fallback, in_key, key_len); + err = aes_preparekey(&ctx->fallback, in_key, key_len); if (err) return err; - err = aes_expandkey(&ctx->tweak_key, in_key + key_len, key_len); + err = aes_prepareenckey(&ctx->tweak_key, in_key + key_len, key_len); if (err) return err; @@ -279,7 +282,7 @@ static int __xts_crypt(struct skcipher_request *req, bool encrypt, if (err) return err; - __aes_arm_encrypt(ctx->tweak_key.key_enc, rounds, walk.iv, walk.iv); + aes_encrypt(&ctx->tweak_key, walk.iv, walk.iv); while (walk.nbytes >= AES_BLOCK_SIZE) { unsigned int blocks = walk.nbytes / AES_BLOCK_SIZE; @@ -311,9 +314,9 @@ static int __xts_crypt(struct skcipher_request *req, bool encrypt, crypto_xor(buf, req->iv, AES_BLOCK_SIZE); if (encrypt) - __aes_arm_encrypt(ctx->fallback.key_enc, rounds, buf, buf); + aes_encrypt(&ctx->fallback, buf, buf); else - __aes_arm_decrypt(ctx->fallback.key_dec, rounds, buf, buf); + aes_decrypt(&ctx->fallback, buf, buf); crypto_xor(buf, req->iv, AES_BLOCK_SIZE); From f367305a5d0f72d2e8c656f144db424f791dc5e1 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:02 -0800 Subject: [PATCH 21/53] crypto: arm/aes - Switch to aes_enc_tab[] and aes_dec_tab[] Instead of crypto_ft_tab and crypto_it_tab from aes_generic.c, use aes_enc_tab and aes_dec_tab from lib/crypto/aes.c. These contain the same data in the first 1024 bytes (which is the part that this code uses), so the result is the same. This will allow aes_generic.c to eventually be removed. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-5-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/arm/crypto/aes-cipher-core.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/crypto/aes-cipher-core.S b/arch/arm/crypto/aes-cipher-core.S index 1da3f41359aa..87567d6822ba 100644 --- a/arch/arm/crypto/aes-cipher-core.S +++ b/arch/arm/crypto/aes-cipher-core.S @@ -192,10 +192,10 @@ .endm ENTRY(__aes_arm_encrypt) - do_crypt fround, crypto_ft_tab,, 2 + do_crypt fround, aes_enc_tab,, 2 ENDPROC(__aes_arm_encrypt) .align 5 ENTRY(__aes_arm_decrypt) - do_crypt iround, crypto_it_tab, crypto_aes_inv_sbox, 0 + do_crypt iround, aes_dec_tab, crypto_aes_inv_sbox, 0 ENDPROC(__aes_arm_decrypt) From 1cb2fcb61c6d58c59a01da1fa8330e3101818759 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:03 -0800 Subject: [PATCH 22/53] crypto: arm64/aes - Switch to aes_enc_tab[] and aes_dec_tab[] Instead of crypto_ft_tab and crypto_it_tab from aes_generic.c, use aes_enc_tab and aes_dec_tab from lib/crypto/aes.c. These contain the same data in the first 1024 bytes (which is the part that this code uses), so the result is the same. This will allow aes_generic.c to eventually be removed. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-6-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/arm64/crypto/aes-cipher-core.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/crypto/aes-cipher-core.S b/arch/arm64/crypto/aes-cipher-core.S index c9d6955f8404..651f701c56a8 100644 --- a/arch/arm64/crypto/aes-cipher-core.S +++ b/arch/arm64/crypto/aes-cipher-core.S @@ -123,10 +123,10 @@ CPU_BE( rev w7, w7 ) .endm SYM_FUNC_START(__aes_arm64_encrypt) - do_crypt fround, crypto_ft_tab, crypto_ft_tab + 1, 2 + do_crypt fround, aes_enc_tab, aes_enc_tab + 1, 2 SYM_FUNC_END(__aes_arm64_encrypt) .align 5 SYM_FUNC_START(__aes_arm64_decrypt) - do_crypt iround, crypto_it_tab, crypto_aes_inv_sbox, 0 + do_crypt iround, aes_dec_tab, crypto_aes_inv_sbox, 0 SYM_FUNC_END(__aes_arm64_decrypt) From 5be8dcc1d0dd5b4bd431d1d052e79f01dd2e33c4 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:04 -0800 Subject: [PATCH 23/53] crypto: arm64/aes - Select CRYPTO_LIB_SHA256 from correct places The call to sha256() occurs in code that is built when either CRYPTO_AES_ARM64_CE_BLK or CRYPTO_AES_ARM64_NEON_BLK. The option CRYPTO_AES_ARM64 is unrelated, notwithstanding its documentation. I'll be removing CRYPTO_AES_ARM64 soon anyway, but before doing that, fix where CRYPTO_LIB_SHA256 is selected from. Fixes: 01834444d972 ("crypto: arm64/aes - use SHA-256 library instead of crypto_shash") Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-7-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/arm64/crypto/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig index da1c9ea8ea83..4453dff8f0c1 100644 --- a/arch/arm64/crypto/Kconfig +++ b/arch/arm64/crypto/Kconfig @@ -40,7 +40,6 @@ config CRYPTO_SM3_ARM64_CE config CRYPTO_AES_ARM64 tristate "Ciphers: AES, modes: ECB, CBC, CTR, CTS, XCTR, XTS" select CRYPTO_AES - select CRYPTO_LIB_SHA256 help Block ciphers: AES cipher algorithms (FIPS-197) Length-preserving ciphers: AES with ECB, CBC, CTR, CTS, @@ -66,6 +65,7 @@ config CRYPTO_AES_ARM64_CE_BLK depends on KERNEL_MODE_NEON select CRYPTO_SKCIPHER select CRYPTO_AES_ARM64_CE + select CRYPTO_LIB_SHA256 help Length-preserving ciphers: AES cipher algorithms (FIPS-197) with block cipher modes: @@ -83,6 +83,7 @@ config CRYPTO_AES_ARM64_NEON_BLK depends on KERNEL_MODE_NEON select CRYPTO_SKCIPHER select CRYPTO_LIB_AES + select CRYPTO_LIB_SHA256 help Length-preserving ciphers: AES cipher algorithms (FIPS-197) with block cipher modes: From 637e73ef99930b2d55b91868e7297689ca06f37d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:05 -0800 Subject: [PATCH 24/53] crypto: aegis - Switch from crypto_ft_tab[] to aes_enc_tab[] Instead of crypto_ft_tab[0] from aes_generic.c, use aes_enc_tab from lib/crypto/aes.c. These contain the same data, so the result is the same. This will allow aes_generic.c to eventually be removed. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-8-ebiggers@kernel.org Signed-off-by: Eric Biggers --- crypto/Kconfig | 2 +- crypto/aegis.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index 12a87f7cf150..443fe8e016fd 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -766,7 +766,7 @@ menu "AEAD (authenticated encryption with associated data) ciphers" config CRYPTO_AEGIS128 tristate "AEGIS-128" select CRYPTO_AEAD - select CRYPTO_AES # for AES S-box tables + select CRYPTO_LIB_AES # for AES S-box tables help AEGIS-128 AEAD algorithm diff --git a/crypto/aegis.h b/crypto/aegis.h index 6ef9c174c973..ffcf8e85ea69 100644 --- a/crypto/aegis.h +++ b/crypto/aegis.h @@ -62,7 +62,7 @@ static __always_inline void crypto_aegis_aesenc(union aegis_block *dst, const union aegis_block *key) { const u8 *s = src->bytes; - const u32 *t = crypto_ft_tab[0]; + const u32 *t = aes_enc_tab; u32 d0, d1, d2, d3; d0 = t[s[ 0]] ^ rol32(t[s[ 5]], 8) ^ rol32(t[s[10]], 16) ^ rol32(t[s[15]], 24); From 641e70563ac1cc498b31f4016c1f5dde8e0e4d71 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:06 -0800 Subject: [PATCH 25/53] crypto: aes - Remove aes-fixed-time / CONFIG_CRYPTO_AES_TI Remove aes-fixed-time, i.e. CONFIG_CRYPTO_AES_TI. This was a wrapper around the 256-byte-table-based AES implementation in lib/crypto/aes.c, with extra code to enable and disable IRQs for constant-time hardening. While nice in theory, in practice this had the following issues: - For bulk en/decryption it was 2-4 times slower than aes-generic. This resulted in aes-generic still being needed, creating fragmentation. - Having both aes-generic and aes-fixed-time punted an AES implementation decision to distros and users who are generally unprepared to handle it. In practice, whether aes-fixed-time gets used tends to be incidental and not match an explicit distro or user intent. (While aes-fixed-time has a higher priority than aes-generic, whether it actually gets enabled, loaded, and used depends on the kconfig and whether a modprobe of "aes" happens to be done. It also has a lower priority than aes-arm and aes-arm64.) - My changes to the generic AES code (in other commits) significantly close the gap with aes-fixed-time anyway. The table size is reduced from 8192 bytes to 1024 bytes, and prefetching is added. - While AES code *should* be constant-time, the real solutions for that are AES instructions (which most CPUs have now) or bit-slicing. arm and arm64 already have bit-sliced AES code for many modes; generic bit-sliced code could be written but would be very slow for single blocks. Overall, I suggest that trying to write constant-time table-based AES code is a bit futile anyway, and in the rare cases where a proper AES implementation is still unavailable it's reasonable to compromise with an implementation that simply prefetches the table. Thus, this commit removes aes-fixed-time and CONFIG_CRYPTO_AES_TI. The replacement is just the existing CONFIG_CRYPTO_AES, which for now maps to the existing aes-generic code, but I'll soon be changing to use the improved AES library code instead. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-9-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/m68k/configs/amiga_defconfig | 1 - arch/m68k/configs/apollo_defconfig | 1 - arch/m68k/configs/atari_defconfig | 1 - arch/m68k/configs/bvme6000_defconfig | 1 - arch/m68k/configs/hp300_defconfig | 1 - arch/m68k/configs/mac_defconfig | 1 - arch/m68k/configs/multi_defconfig | 1 - arch/m68k/configs/mvme147_defconfig | 1 - arch/m68k/configs/mvme16x_defconfig | 1 - arch/m68k/configs/q40_defconfig | 1 - arch/m68k/configs/sun3_defconfig | 1 - arch/m68k/configs/sun3x_defconfig | 1 - arch/s390/configs/debug_defconfig | 2 +- arch/s390/configs/defconfig | 2 +- crypto/Kconfig | 21 ------- crypto/Makefile | 1 - crypto/aes_ti.c | 83 ---------------------------- 17 files changed, 2 insertions(+), 119 deletions(-) delete mode 100644 crypto/aes_ti.c diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index bfc1ee7c8158..bffcc417f44c 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -555,7 +555,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index d9d1f3c4c70d..3f894c20b132 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -512,7 +512,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index 523205adccc8..5c5603ca16aa 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -532,7 +532,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index 7b0a4ef0b010..37c747ee395e 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -504,7 +504,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index 089c5c394c62..1a376c2b8c45 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -514,7 +514,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index 5f2484c36733..2b26450692a5 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -531,7 +531,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index 74f0a1f6d871..012e0e1f506f 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -618,7 +618,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index 4bee18c820e4..37634b35bfbd 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -504,7 +504,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index 322c17e55c9a..a0d2e0070afa 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -505,7 +505,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index 82f9baab8fea..62cc3964fc34 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -521,7 +521,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index f94ad226cb5b..13107aa4a1b4 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -502,7 +502,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index a5ecfc505ab2..eaab0ba08989 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -502,7 +502,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index 0713914b25b4..09f4bdb9e64f 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -770,7 +770,7 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_AES_TI=m +CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig index c064e0cacc98..823193b9f4c6 100644 --- a/arch/s390/configs/defconfig +++ b/arch/s390/configs/defconfig @@ -754,7 +754,7 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_AES_TI=m +CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ARIA=m CONFIG_CRYPTO_BLOWFISH=m diff --git a/crypto/Kconfig b/crypto/Kconfig index 443fe8e016fd..db6b0c2fb50e 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -366,27 +366,6 @@ config CRYPTO_AES The AES specifies three key sizes: 128, 192 and 256 bits -config CRYPTO_AES_TI - tristate "AES (Advanced Encryption Standard) (fixed time)" - select CRYPTO_ALGAPI - select CRYPTO_LIB_AES - help - AES cipher algorithms (Rijndael)(FIPS-197, ISO/IEC 18033-3) - - This is a generic implementation of AES that attempts to eliminate - data dependent latencies as much as possible without affecting - performance too much. It is intended for use by the generic CCM - and GCM drivers, and other CTR or CMAC/XCBC based modes that rely - solely on encryption (although decryption is supported as well, but - with a more dramatic performance hit) - - Instead of using 16 lookup tables of 1 KB each, (8 for encryption and - 8 for decryption), this implementation only uses just two S-boxes of - 256 bytes each, and attempts to eliminate data dependent latencies by - prefetching the entire table into the cache at the start of each - block. Interrupts are also disabled to avoid races where cachelines - are evicted when the CPU is interrupted to do something else. - config CRYPTO_ANUBIS tristate "Anubis" depends on CRYPTO_USER_API_ENABLE_OBSOLETE diff --git a/crypto/Makefile b/crypto/Makefile index 23d3db7be425..be403dc20645 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -134,7 +134,6 @@ obj-$(CONFIG_CRYPTO_AES) += aes_generic.o CFLAGS_aes_generic.o := $(call cc-option,-fno-code-hoisting) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83356 obj-$(CONFIG_CRYPTO_SM4) += sm4.o obj-$(CONFIG_CRYPTO_SM4_GENERIC) += sm4_generic.o -obj-$(CONFIG_CRYPTO_AES_TI) += aes_ti.o obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia_generic.o obj-$(CONFIG_CRYPTO_CAST_COMMON) += cast_common.o obj-$(CONFIG_CRYPTO_CAST5) += cast5_generic.o diff --git a/crypto/aes_ti.c b/crypto/aes_ti.c deleted file mode 100644 index a3b342f92fab..000000000000 --- a/crypto/aes_ti.c +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Scalar fixed time AES core transform - * - * Copyright (C) 2017 Linaro Ltd - */ - -#include -#include -#include - -static int aesti_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) -{ - struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - return aes_expandkey(ctx, in_key, key_len); -} - -static void aesti_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -{ - const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - unsigned long flags; - - /* - * Temporarily disable interrupts to avoid races where cachelines are - * evicted when the CPU is interrupted to do something else. - */ - local_irq_save(flags); - - aes_encrypt(ctx, out, in); - - local_irq_restore(flags); -} - -static void aesti_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -{ - const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - unsigned long flags; - - /* - * Temporarily disable interrupts to avoid races where cachelines are - * evicted when the CPU is interrupted to do something else. - */ - local_irq_save(flags); - - aes_decrypt(ctx, out, in); - - local_irq_restore(flags); -} - -static struct crypto_alg aes_alg = { - .cra_name = "aes", - .cra_driver_name = "aes-fixed-time", - .cra_priority = 100 + 1, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_aes_ctx), - .cra_module = THIS_MODULE, - - .cra_cipher.cia_min_keysize = AES_MIN_KEY_SIZE, - .cra_cipher.cia_max_keysize = AES_MAX_KEY_SIZE, - .cra_cipher.cia_setkey = aesti_set_key, - .cra_cipher.cia_encrypt = aesti_encrypt, - .cra_cipher.cia_decrypt = aesti_decrypt -}; - -static int __init aes_init(void) -{ - return crypto_register_alg(&aes_alg); -} - -static void __exit aes_fini(void) -{ - crypto_unregister_alg(&aes_alg); -} - -module_init(aes_init); -module_exit(aes_fini); - -MODULE_DESCRIPTION("Generic fixed time AES"); -MODULE_AUTHOR("Ard Biesheuvel "); -MODULE_LICENSE("GPL v2"); From a2484474272ef98d9580d8c610b0f7c6ed2f146c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:07 -0800 Subject: [PATCH 26/53] crypto: aes - Replace aes-generic with wrapper around lib Now that the AES library's performance has been improved, replace aes_generic.c with a new file aes.c which wraps the AES library. In preparation for making the AES library actually utilize the kernel's existing architecture-optimized AES code including AES instructions, set the driver name to "aes-lib" instead of "aes-generic". This mirrors what's been done for the hash algorithms. Update testmgr.c accordingly. Since this removes the crypto_aes_set_key() helper function, add temporary replacements for it to arch/arm/crypto/aes-cipher-glue.c and arch/arm64/crypto/aes-cipher-glue.c. This is temporary, as that code will be migrated into lib/crypto/ in later commits. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-10-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/arm/crypto/aes-cipher-glue.c | 10 +- arch/arm64/crypto/aes-cipher-glue.c | 10 +- crypto/Makefile | 3 +- crypto/aes.c | 66 ++ crypto/aes_generic.c | 1320 -------------------------- crypto/crypto_user.c | 2 +- crypto/testmgr.c | 43 +- drivers/crypto/starfive/jh7110-aes.c | 10 +- include/crypto/aes.h | 6 - 9 files changed, 117 insertions(+), 1353 deletions(-) create mode 100644 crypto/aes.c delete mode 100644 crypto/aes_generic.c diff --git a/arch/arm/crypto/aes-cipher-glue.c b/arch/arm/crypto/aes-cipher-glue.c index 29efb7833960..f302db808cd3 100644 --- a/arch/arm/crypto/aes-cipher-glue.c +++ b/arch/arm/crypto/aes-cipher-glue.c @@ -14,6 +14,14 @@ EXPORT_SYMBOL_GPL(__aes_arm_encrypt); EXPORT_SYMBOL_GPL(__aes_arm_decrypt); +static int aes_arm_setkey(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len) +{ + struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); + + return aes_expandkey(ctx, in_key, key_len); +} + static void aes_arm_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); @@ -41,7 +49,7 @@ static struct crypto_alg aes_alg = { .cra_cipher.cia_min_keysize = AES_MIN_KEY_SIZE, .cra_cipher.cia_max_keysize = AES_MAX_KEY_SIZE, - .cra_cipher.cia_setkey = crypto_aes_set_key, + .cra_cipher.cia_setkey = aes_arm_setkey, .cra_cipher.cia_encrypt = aes_arm_encrypt, .cra_cipher.cia_decrypt = aes_arm_decrypt, diff --git a/arch/arm64/crypto/aes-cipher-glue.c b/arch/arm64/crypto/aes-cipher-glue.c index 4ec55e568941..9b27cbac278b 100644 --- a/arch/arm64/crypto/aes-cipher-glue.c +++ b/arch/arm64/crypto/aes-cipher-glue.c @@ -12,6 +12,14 @@ asmlinkage void __aes_arm64_encrypt(u32 *rk, u8 *out, const u8 *in, int rounds); asmlinkage void __aes_arm64_decrypt(u32 *rk, u8 *out, const u8 *in, int rounds); +static int aes_arm64_setkey(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len) +{ + struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); + + return aes_expandkey(ctx, in_key, key_len); +} + static void aes_arm64_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); @@ -39,7 +47,7 @@ static struct crypto_alg aes_alg = { .cra_cipher.cia_min_keysize = AES_MIN_KEY_SIZE, .cra_cipher.cia_max_keysize = AES_MAX_KEY_SIZE, - .cra_cipher.cia_setkey = crypto_aes_set_key, + .cra_cipher.cia_setkey = aes_arm64_setkey, .cra_cipher.cia_encrypt = aes_arm64_encrypt, .cra_cipher.cia_decrypt = aes_arm64_decrypt }; diff --git a/crypto/Makefile b/crypto/Makefile index be403dc20645..65a2c3478814 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -130,8 +130,7 @@ obj-$(CONFIG_CRYPTO_TWOFISH) += twofish_generic.o obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o obj-$(CONFIG_CRYPTO_SERPENT) += serpent_generic.o CFLAGS_serpent_generic.o := $(call cc-option,-fsched-pressure) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149 -obj-$(CONFIG_CRYPTO_AES) += aes_generic.o -CFLAGS_aes_generic.o := $(call cc-option,-fno-code-hoisting) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83356 +obj-$(CONFIG_CRYPTO_AES) += aes.o obj-$(CONFIG_CRYPTO_SM4) += sm4.o obj-$(CONFIG_CRYPTO_SM4_GENERIC) += sm4_generic.o obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia_generic.o diff --git a/crypto/aes.c b/crypto/aes.c new file mode 100644 index 000000000000..ae8385df0ce5 --- /dev/null +++ b/crypto/aes.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Crypto API support for AES block cipher + * + * Copyright 2026 Google LLC + */ + +#include +#include +#include + +static_assert(__alignof__(struct aes_key) <= CRYPTO_MINALIGN); + +static int crypto_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len) +{ + struct aes_key *key = crypto_tfm_ctx(tfm); + + return aes_preparekey(key, in_key, key_len); +} + +static void crypto_aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +{ + const struct aes_key *key = crypto_tfm_ctx(tfm); + + aes_encrypt(key, out, in); +} + +static void crypto_aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +{ + const struct aes_key *key = crypto_tfm_ctx(tfm); + + aes_decrypt(key, out, in); +} + +static struct crypto_alg alg = { + .cra_name = "aes", + .cra_driver_name = "aes-lib", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct aes_key), + .cra_module = THIS_MODULE, + .cra_u = { .cipher = { .cia_min_keysize = AES_MIN_KEY_SIZE, + .cia_max_keysize = AES_MAX_KEY_SIZE, + .cia_setkey = crypto_aes_setkey, + .cia_encrypt = crypto_aes_encrypt, + .cia_decrypt = crypto_aes_decrypt } } +}; + +static int __init crypto_aes_mod_init(void) +{ + return crypto_register_alg(&alg); +} +module_init(crypto_aes_mod_init); + +static void __exit crypto_aes_mod_exit(void) +{ + crypto_unregister_alg(&alg); +} +module_exit(crypto_aes_mod_exit); + +MODULE_DESCRIPTION("Crypto API support for AES block cipher"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_CRYPTO("aes"); +MODULE_ALIAS_CRYPTO("aes-lib"); diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c deleted file mode 100644 index 85d2e78c8ef2..000000000000 --- a/crypto/aes_generic.c +++ /dev/null @@ -1,1320 +0,0 @@ -/* - * Cryptographic API. - * - * AES Cipher Algorithm. - * - * Based on Brian Gladman's code. - * - * Linux developers: - * Alexander Kjeldaas - * Herbert Valerio Riedel - * Kyle McMartin - * Adam J. Richter (conversion to 2.5 API). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * --------------------------------------------------------------------------- - * Copyright (c) 2002, Dr Brian Gladman , Worcester, UK. - * All rights reserved. - * - * LICENSE TERMS - * - * The free distribution and use of this software in both source and binary - * form is allowed (with or without changes) provided that: - * - * 1. distributions of this source code include the above copyright - * notice, this list of conditions and the following disclaimer; - * - * 2. distributions in binary form include the above copyright - * notice, this list of conditions and the following disclaimer - * in the documentation and/or other associated materials; - * - * 3. the copyright holder's name is not used to endorse products - * built using this software without specific written permission. - * - * ALTERNATIVELY, provided that this notice is retained in full, this product - * may be distributed under the terms of the GNU General Public License (GPL), - * in which case the provisions of the GPL apply INSTEAD OF those given above. - * - * DISCLAIMER - * - * This software is provided 'as is' with no explicit or implied warranties - * in respect of its properties, including, but not limited to, correctness - * and/or fitness for purpose. - * --------------------------------------------------------------------------- - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static inline u8 byte(const u32 x, const unsigned n) -{ - return x >> (n << 3); -} - -/* cacheline-aligned to facilitate prefetching into cache */ -__visible const u32 crypto_ft_tab[4][256] ____cacheline_aligned = { - { - 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, - 0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, - 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, - 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, - 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, - 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, - 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, - 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, - 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, - 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, - 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, - 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, - 0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, - 0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f, - 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, - 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, - 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, - 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, - 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, - 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, - 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, - 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, - 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, - 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, - 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, - 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, - 0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe, - 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, - 0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, - 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1, - 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, - 0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, - 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, - 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, - 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, - 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, - 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, - 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, - 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, - 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, - 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, - 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8, - 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, - 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, - 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, - 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, - 0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, - 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, - 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, - 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, - 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, - 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, - 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, - 0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c, - 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, - 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, - 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, - 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, - 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, - 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, - 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, - 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, - 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, - 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c, - }, { - 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, - 0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, - 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d, - 0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a, - 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87, - 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, - 0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, - 0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b, - 0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a, - 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, - 0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, - 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f, - 0x0404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e, - 0x18183028, 0x969637a1, 0x05050a0f, 0x9a9a2fb5, - 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d, - 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, - 0x0909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e, - 0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb, - 0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, - 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397, - 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, - 0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, - 0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b, - 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a, - 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, - 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, - 0x45458acf, 0xf9f9e910, 0x02020406, 0x7f7ffe81, - 0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, - 0x5151a2f3, 0xa3a35dfe, 0x404080c0, 0x8f8f058a, - 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104, - 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, - 0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, - 0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f, - 0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, - 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47, - 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695, - 0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, - 0x22224466, 0x2a2a547e, 0x90903bab, 0x88880b83, - 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c, - 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76, - 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, - 0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4, - 0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, - 0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b, - 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7, - 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, - 0x6c6cd8b4, 0x5656acfa, 0xf4f4f307, 0xeaeacf25, - 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018, - 0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72, - 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751, - 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, - 0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, - 0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa, - 0x484890d8, 0x03030605, 0xf6f6f701, 0x0e0e1c12, - 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, - 0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9, - 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233, - 0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7, - 0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920, - 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a, - 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, - 0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8, - 0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11, - 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a, - }, { - 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, - 0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, - 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b, - 0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76, - 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d, - 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, - 0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, - 0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0, - 0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26, - 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, - 0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, - 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15, - 0x04080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3, - 0x18302818, 0x9637a196, 0x050a0f05, 0x9a2fb59a, - 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2, - 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, - 0x09121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a, - 0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0, - 0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, - 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784, - 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, - 0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, - 0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39, - 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf, - 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, - 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, - 0x458acf45, 0xf9e910f9, 0x02040602, 0x7ffe817f, - 0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, - 0x51a2f351, 0xa35dfea3, 0x4080c040, 0x8f058a8f, - 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5, - 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, - 0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, - 0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec, - 0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, - 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d, - 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573, - 0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, - 0x22446622, 0x2a547e2a, 0x903bab90, 0x880b8388, - 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14, - 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db, - 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, - 0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c, - 0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, - 0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79, - 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d, - 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, - 0x6cd8b46c, 0x56acfa56, 0xf4f307f4, 0xeacf25ea, - 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808, - 0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e, - 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6, - 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, - 0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, - 0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66, - 0x4890d848, 0x03060503, 0xf6f701f6, 0x0e1c120e, - 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, - 0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e, - 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311, - 0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794, - 0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9, - 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf, - 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, - 0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868, - 0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f, - 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16, - }, { - 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, - 0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, - 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b, - 0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676, - 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d, - 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, - 0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, - 0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0, - 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626, - 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, - 0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, - 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515, - 0x080c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3, - 0x30281818, 0x37a19696, 0x0a0f0505, 0x2fb59a9a, - 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2, - 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, - 0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a, - 0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0, - 0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, - 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484, - 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, - 0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, - 0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939, - 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf, - 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, - 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, - 0x8acf4545, 0xe910f9f9, 0x04060202, 0xfe817f7f, - 0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, - 0xa2f35151, 0x5dfea3a3, 0x80c04040, 0x058a8f8f, - 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5, - 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, - 0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, - 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec, - 0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, - 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d, - 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373, - 0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, - 0x44662222, 0x547e2a2a, 0x3bab9090, 0x0b838888, - 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414, - 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb, - 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, - 0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c, - 0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, - 0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979, - 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d, - 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, - 0xd8b46c6c, 0xacfa5656, 0xf307f4f4, 0xcf25eaea, - 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808, - 0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e, - 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6, - 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, - 0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, - 0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666, - 0x90d84848, 0x06050303, 0xf701f6f6, 0x1c120e0e, - 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, - 0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e, - 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111, - 0xd2bb6969, 0xa970d9d9, 0x07898e8e, 0x33a79494, - 0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9, - 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf, - 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, - 0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868, - 0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f, - 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616, - } -}; - -static const u32 crypto_fl_tab[4][256] ____cacheline_aligned = { - { - 0x00000063, 0x0000007c, 0x00000077, 0x0000007b, - 0x000000f2, 0x0000006b, 0x0000006f, 0x000000c5, - 0x00000030, 0x00000001, 0x00000067, 0x0000002b, - 0x000000fe, 0x000000d7, 0x000000ab, 0x00000076, - 0x000000ca, 0x00000082, 0x000000c9, 0x0000007d, - 0x000000fa, 0x00000059, 0x00000047, 0x000000f0, - 0x000000ad, 0x000000d4, 0x000000a2, 0x000000af, - 0x0000009c, 0x000000a4, 0x00000072, 0x000000c0, - 0x000000b7, 0x000000fd, 0x00000093, 0x00000026, - 0x00000036, 0x0000003f, 0x000000f7, 0x000000cc, - 0x00000034, 0x000000a5, 0x000000e5, 0x000000f1, - 0x00000071, 0x000000d8, 0x00000031, 0x00000015, - 0x00000004, 0x000000c7, 0x00000023, 0x000000c3, - 0x00000018, 0x00000096, 0x00000005, 0x0000009a, - 0x00000007, 0x00000012, 0x00000080, 0x000000e2, - 0x000000eb, 0x00000027, 0x000000b2, 0x00000075, - 0x00000009, 0x00000083, 0x0000002c, 0x0000001a, - 0x0000001b, 0x0000006e, 0x0000005a, 0x000000a0, - 0x00000052, 0x0000003b, 0x000000d6, 0x000000b3, - 0x00000029, 0x000000e3, 0x0000002f, 0x00000084, - 0x00000053, 0x000000d1, 0x00000000, 0x000000ed, - 0x00000020, 0x000000fc, 0x000000b1, 0x0000005b, - 0x0000006a, 0x000000cb, 0x000000be, 0x00000039, - 0x0000004a, 0x0000004c, 0x00000058, 0x000000cf, - 0x000000d0, 0x000000ef, 0x000000aa, 0x000000fb, - 0x00000043, 0x0000004d, 0x00000033, 0x00000085, - 0x00000045, 0x000000f9, 0x00000002, 0x0000007f, - 0x00000050, 0x0000003c, 0x0000009f, 0x000000a8, - 0x00000051, 0x000000a3, 0x00000040, 0x0000008f, - 0x00000092, 0x0000009d, 0x00000038, 0x000000f5, - 0x000000bc, 0x000000b6, 0x000000da, 0x00000021, - 0x00000010, 0x000000ff, 0x000000f3, 0x000000d2, - 0x000000cd, 0x0000000c, 0x00000013, 0x000000ec, - 0x0000005f, 0x00000097, 0x00000044, 0x00000017, - 0x000000c4, 0x000000a7, 0x0000007e, 0x0000003d, - 0x00000064, 0x0000005d, 0x00000019, 0x00000073, - 0x00000060, 0x00000081, 0x0000004f, 0x000000dc, - 0x00000022, 0x0000002a, 0x00000090, 0x00000088, - 0x00000046, 0x000000ee, 0x000000b8, 0x00000014, - 0x000000de, 0x0000005e, 0x0000000b, 0x000000db, - 0x000000e0, 0x00000032, 0x0000003a, 0x0000000a, - 0x00000049, 0x00000006, 0x00000024, 0x0000005c, - 0x000000c2, 0x000000d3, 0x000000ac, 0x00000062, - 0x00000091, 0x00000095, 0x000000e4, 0x00000079, - 0x000000e7, 0x000000c8, 0x00000037, 0x0000006d, - 0x0000008d, 0x000000d5, 0x0000004e, 0x000000a9, - 0x0000006c, 0x00000056, 0x000000f4, 0x000000ea, - 0x00000065, 0x0000007a, 0x000000ae, 0x00000008, - 0x000000ba, 0x00000078, 0x00000025, 0x0000002e, - 0x0000001c, 0x000000a6, 0x000000b4, 0x000000c6, - 0x000000e8, 0x000000dd, 0x00000074, 0x0000001f, - 0x0000004b, 0x000000bd, 0x0000008b, 0x0000008a, - 0x00000070, 0x0000003e, 0x000000b5, 0x00000066, - 0x00000048, 0x00000003, 0x000000f6, 0x0000000e, - 0x00000061, 0x00000035, 0x00000057, 0x000000b9, - 0x00000086, 0x000000c1, 0x0000001d, 0x0000009e, - 0x000000e1, 0x000000f8, 0x00000098, 0x00000011, - 0x00000069, 0x000000d9, 0x0000008e, 0x00000094, - 0x0000009b, 0x0000001e, 0x00000087, 0x000000e9, - 0x000000ce, 0x00000055, 0x00000028, 0x000000df, - 0x0000008c, 0x000000a1, 0x00000089, 0x0000000d, - 0x000000bf, 0x000000e6, 0x00000042, 0x00000068, - 0x00000041, 0x00000099, 0x0000002d, 0x0000000f, - 0x000000b0, 0x00000054, 0x000000bb, 0x00000016, - }, { - 0x00006300, 0x00007c00, 0x00007700, 0x00007b00, - 0x0000f200, 0x00006b00, 0x00006f00, 0x0000c500, - 0x00003000, 0x00000100, 0x00006700, 0x00002b00, - 0x0000fe00, 0x0000d700, 0x0000ab00, 0x00007600, - 0x0000ca00, 0x00008200, 0x0000c900, 0x00007d00, - 0x0000fa00, 0x00005900, 0x00004700, 0x0000f000, - 0x0000ad00, 0x0000d400, 0x0000a200, 0x0000af00, - 0x00009c00, 0x0000a400, 0x00007200, 0x0000c000, - 0x0000b700, 0x0000fd00, 0x00009300, 0x00002600, - 0x00003600, 0x00003f00, 0x0000f700, 0x0000cc00, - 0x00003400, 0x0000a500, 0x0000e500, 0x0000f100, - 0x00007100, 0x0000d800, 0x00003100, 0x00001500, - 0x00000400, 0x0000c700, 0x00002300, 0x0000c300, - 0x00001800, 0x00009600, 0x00000500, 0x00009a00, - 0x00000700, 0x00001200, 0x00008000, 0x0000e200, - 0x0000eb00, 0x00002700, 0x0000b200, 0x00007500, - 0x00000900, 0x00008300, 0x00002c00, 0x00001a00, - 0x00001b00, 0x00006e00, 0x00005a00, 0x0000a000, - 0x00005200, 0x00003b00, 0x0000d600, 0x0000b300, - 0x00002900, 0x0000e300, 0x00002f00, 0x00008400, - 0x00005300, 0x0000d100, 0x00000000, 0x0000ed00, - 0x00002000, 0x0000fc00, 0x0000b100, 0x00005b00, - 0x00006a00, 0x0000cb00, 0x0000be00, 0x00003900, - 0x00004a00, 0x00004c00, 0x00005800, 0x0000cf00, - 0x0000d000, 0x0000ef00, 0x0000aa00, 0x0000fb00, - 0x00004300, 0x00004d00, 0x00003300, 0x00008500, - 0x00004500, 0x0000f900, 0x00000200, 0x00007f00, - 0x00005000, 0x00003c00, 0x00009f00, 0x0000a800, - 0x00005100, 0x0000a300, 0x00004000, 0x00008f00, - 0x00009200, 0x00009d00, 0x00003800, 0x0000f500, - 0x0000bc00, 0x0000b600, 0x0000da00, 0x00002100, - 0x00001000, 0x0000ff00, 0x0000f300, 0x0000d200, - 0x0000cd00, 0x00000c00, 0x00001300, 0x0000ec00, - 0x00005f00, 0x00009700, 0x00004400, 0x00001700, - 0x0000c400, 0x0000a700, 0x00007e00, 0x00003d00, - 0x00006400, 0x00005d00, 0x00001900, 0x00007300, - 0x00006000, 0x00008100, 0x00004f00, 0x0000dc00, - 0x00002200, 0x00002a00, 0x00009000, 0x00008800, - 0x00004600, 0x0000ee00, 0x0000b800, 0x00001400, - 0x0000de00, 0x00005e00, 0x00000b00, 0x0000db00, - 0x0000e000, 0x00003200, 0x00003a00, 0x00000a00, - 0x00004900, 0x00000600, 0x00002400, 0x00005c00, - 0x0000c200, 0x0000d300, 0x0000ac00, 0x00006200, - 0x00009100, 0x00009500, 0x0000e400, 0x00007900, - 0x0000e700, 0x0000c800, 0x00003700, 0x00006d00, - 0x00008d00, 0x0000d500, 0x00004e00, 0x0000a900, - 0x00006c00, 0x00005600, 0x0000f400, 0x0000ea00, - 0x00006500, 0x00007a00, 0x0000ae00, 0x00000800, - 0x0000ba00, 0x00007800, 0x00002500, 0x00002e00, - 0x00001c00, 0x0000a600, 0x0000b400, 0x0000c600, - 0x0000e800, 0x0000dd00, 0x00007400, 0x00001f00, - 0x00004b00, 0x0000bd00, 0x00008b00, 0x00008a00, - 0x00007000, 0x00003e00, 0x0000b500, 0x00006600, - 0x00004800, 0x00000300, 0x0000f600, 0x00000e00, - 0x00006100, 0x00003500, 0x00005700, 0x0000b900, - 0x00008600, 0x0000c100, 0x00001d00, 0x00009e00, - 0x0000e100, 0x0000f800, 0x00009800, 0x00001100, - 0x00006900, 0x0000d900, 0x00008e00, 0x00009400, - 0x00009b00, 0x00001e00, 0x00008700, 0x0000e900, - 0x0000ce00, 0x00005500, 0x00002800, 0x0000df00, - 0x00008c00, 0x0000a100, 0x00008900, 0x00000d00, - 0x0000bf00, 0x0000e600, 0x00004200, 0x00006800, - 0x00004100, 0x00009900, 0x00002d00, 0x00000f00, - 0x0000b000, 0x00005400, 0x0000bb00, 0x00001600, - }, { - 0x00630000, 0x007c0000, 0x00770000, 0x007b0000, - 0x00f20000, 0x006b0000, 0x006f0000, 0x00c50000, - 0x00300000, 0x00010000, 0x00670000, 0x002b0000, - 0x00fe0000, 0x00d70000, 0x00ab0000, 0x00760000, - 0x00ca0000, 0x00820000, 0x00c90000, 0x007d0000, - 0x00fa0000, 0x00590000, 0x00470000, 0x00f00000, - 0x00ad0000, 0x00d40000, 0x00a20000, 0x00af0000, - 0x009c0000, 0x00a40000, 0x00720000, 0x00c00000, - 0x00b70000, 0x00fd0000, 0x00930000, 0x00260000, - 0x00360000, 0x003f0000, 0x00f70000, 0x00cc0000, - 0x00340000, 0x00a50000, 0x00e50000, 0x00f10000, - 0x00710000, 0x00d80000, 0x00310000, 0x00150000, - 0x00040000, 0x00c70000, 0x00230000, 0x00c30000, - 0x00180000, 0x00960000, 0x00050000, 0x009a0000, - 0x00070000, 0x00120000, 0x00800000, 0x00e20000, - 0x00eb0000, 0x00270000, 0x00b20000, 0x00750000, - 0x00090000, 0x00830000, 0x002c0000, 0x001a0000, - 0x001b0000, 0x006e0000, 0x005a0000, 0x00a00000, - 0x00520000, 0x003b0000, 0x00d60000, 0x00b30000, - 0x00290000, 0x00e30000, 0x002f0000, 0x00840000, - 0x00530000, 0x00d10000, 0x00000000, 0x00ed0000, - 0x00200000, 0x00fc0000, 0x00b10000, 0x005b0000, - 0x006a0000, 0x00cb0000, 0x00be0000, 0x00390000, - 0x004a0000, 0x004c0000, 0x00580000, 0x00cf0000, - 0x00d00000, 0x00ef0000, 0x00aa0000, 0x00fb0000, - 0x00430000, 0x004d0000, 0x00330000, 0x00850000, - 0x00450000, 0x00f90000, 0x00020000, 0x007f0000, - 0x00500000, 0x003c0000, 0x009f0000, 0x00a80000, - 0x00510000, 0x00a30000, 0x00400000, 0x008f0000, - 0x00920000, 0x009d0000, 0x00380000, 0x00f50000, - 0x00bc0000, 0x00b60000, 0x00da0000, 0x00210000, - 0x00100000, 0x00ff0000, 0x00f30000, 0x00d20000, - 0x00cd0000, 0x000c0000, 0x00130000, 0x00ec0000, - 0x005f0000, 0x00970000, 0x00440000, 0x00170000, - 0x00c40000, 0x00a70000, 0x007e0000, 0x003d0000, - 0x00640000, 0x005d0000, 0x00190000, 0x00730000, - 0x00600000, 0x00810000, 0x004f0000, 0x00dc0000, - 0x00220000, 0x002a0000, 0x00900000, 0x00880000, - 0x00460000, 0x00ee0000, 0x00b80000, 0x00140000, - 0x00de0000, 0x005e0000, 0x000b0000, 0x00db0000, - 0x00e00000, 0x00320000, 0x003a0000, 0x000a0000, - 0x00490000, 0x00060000, 0x00240000, 0x005c0000, - 0x00c20000, 0x00d30000, 0x00ac0000, 0x00620000, - 0x00910000, 0x00950000, 0x00e40000, 0x00790000, - 0x00e70000, 0x00c80000, 0x00370000, 0x006d0000, - 0x008d0000, 0x00d50000, 0x004e0000, 0x00a90000, - 0x006c0000, 0x00560000, 0x00f40000, 0x00ea0000, - 0x00650000, 0x007a0000, 0x00ae0000, 0x00080000, - 0x00ba0000, 0x00780000, 0x00250000, 0x002e0000, - 0x001c0000, 0x00a60000, 0x00b40000, 0x00c60000, - 0x00e80000, 0x00dd0000, 0x00740000, 0x001f0000, - 0x004b0000, 0x00bd0000, 0x008b0000, 0x008a0000, - 0x00700000, 0x003e0000, 0x00b50000, 0x00660000, - 0x00480000, 0x00030000, 0x00f60000, 0x000e0000, - 0x00610000, 0x00350000, 0x00570000, 0x00b90000, - 0x00860000, 0x00c10000, 0x001d0000, 0x009e0000, - 0x00e10000, 0x00f80000, 0x00980000, 0x00110000, - 0x00690000, 0x00d90000, 0x008e0000, 0x00940000, - 0x009b0000, 0x001e0000, 0x00870000, 0x00e90000, - 0x00ce0000, 0x00550000, 0x00280000, 0x00df0000, - 0x008c0000, 0x00a10000, 0x00890000, 0x000d0000, - 0x00bf0000, 0x00e60000, 0x00420000, 0x00680000, - 0x00410000, 0x00990000, 0x002d0000, 0x000f0000, - 0x00b00000, 0x00540000, 0x00bb0000, 0x00160000, - }, { - 0x63000000, 0x7c000000, 0x77000000, 0x7b000000, - 0xf2000000, 0x6b000000, 0x6f000000, 0xc5000000, - 0x30000000, 0x01000000, 0x67000000, 0x2b000000, - 0xfe000000, 0xd7000000, 0xab000000, 0x76000000, - 0xca000000, 0x82000000, 0xc9000000, 0x7d000000, - 0xfa000000, 0x59000000, 0x47000000, 0xf0000000, - 0xad000000, 0xd4000000, 0xa2000000, 0xaf000000, - 0x9c000000, 0xa4000000, 0x72000000, 0xc0000000, - 0xb7000000, 0xfd000000, 0x93000000, 0x26000000, - 0x36000000, 0x3f000000, 0xf7000000, 0xcc000000, - 0x34000000, 0xa5000000, 0xe5000000, 0xf1000000, - 0x71000000, 0xd8000000, 0x31000000, 0x15000000, - 0x04000000, 0xc7000000, 0x23000000, 0xc3000000, - 0x18000000, 0x96000000, 0x05000000, 0x9a000000, - 0x07000000, 0x12000000, 0x80000000, 0xe2000000, - 0xeb000000, 0x27000000, 0xb2000000, 0x75000000, - 0x09000000, 0x83000000, 0x2c000000, 0x1a000000, - 0x1b000000, 0x6e000000, 0x5a000000, 0xa0000000, - 0x52000000, 0x3b000000, 0xd6000000, 0xb3000000, - 0x29000000, 0xe3000000, 0x2f000000, 0x84000000, - 0x53000000, 0xd1000000, 0x00000000, 0xed000000, - 0x20000000, 0xfc000000, 0xb1000000, 0x5b000000, - 0x6a000000, 0xcb000000, 0xbe000000, 0x39000000, - 0x4a000000, 0x4c000000, 0x58000000, 0xcf000000, - 0xd0000000, 0xef000000, 0xaa000000, 0xfb000000, - 0x43000000, 0x4d000000, 0x33000000, 0x85000000, - 0x45000000, 0xf9000000, 0x02000000, 0x7f000000, - 0x50000000, 0x3c000000, 0x9f000000, 0xa8000000, - 0x51000000, 0xa3000000, 0x40000000, 0x8f000000, - 0x92000000, 0x9d000000, 0x38000000, 0xf5000000, - 0xbc000000, 0xb6000000, 0xda000000, 0x21000000, - 0x10000000, 0xff000000, 0xf3000000, 0xd2000000, - 0xcd000000, 0x0c000000, 0x13000000, 0xec000000, - 0x5f000000, 0x97000000, 0x44000000, 0x17000000, - 0xc4000000, 0xa7000000, 0x7e000000, 0x3d000000, - 0x64000000, 0x5d000000, 0x19000000, 0x73000000, - 0x60000000, 0x81000000, 0x4f000000, 0xdc000000, - 0x22000000, 0x2a000000, 0x90000000, 0x88000000, - 0x46000000, 0xee000000, 0xb8000000, 0x14000000, - 0xde000000, 0x5e000000, 0x0b000000, 0xdb000000, - 0xe0000000, 0x32000000, 0x3a000000, 0x0a000000, - 0x49000000, 0x06000000, 0x24000000, 0x5c000000, - 0xc2000000, 0xd3000000, 0xac000000, 0x62000000, - 0x91000000, 0x95000000, 0xe4000000, 0x79000000, - 0xe7000000, 0xc8000000, 0x37000000, 0x6d000000, - 0x8d000000, 0xd5000000, 0x4e000000, 0xa9000000, - 0x6c000000, 0x56000000, 0xf4000000, 0xea000000, - 0x65000000, 0x7a000000, 0xae000000, 0x08000000, - 0xba000000, 0x78000000, 0x25000000, 0x2e000000, - 0x1c000000, 0xa6000000, 0xb4000000, 0xc6000000, - 0xe8000000, 0xdd000000, 0x74000000, 0x1f000000, - 0x4b000000, 0xbd000000, 0x8b000000, 0x8a000000, - 0x70000000, 0x3e000000, 0xb5000000, 0x66000000, - 0x48000000, 0x03000000, 0xf6000000, 0x0e000000, - 0x61000000, 0x35000000, 0x57000000, 0xb9000000, - 0x86000000, 0xc1000000, 0x1d000000, 0x9e000000, - 0xe1000000, 0xf8000000, 0x98000000, 0x11000000, - 0x69000000, 0xd9000000, 0x8e000000, 0x94000000, - 0x9b000000, 0x1e000000, 0x87000000, 0xe9000000, - 0xce000000, 0x55000000, 0x28000000, 0xdf000000, - 0x8c000000, 0xa1000000, 0x89000000, 0x0d000000, - 0xbf000000, 0xe6000000, 0x42000000, 0x68000000, - 0x41000000, 0x99000000, 0x2d000000, 0x0f000000, - 0xb0000000, 0x54000000, 0xbb000000, 0x16000000, - } -}; - -__visible const u32 crypto_it_tab[4][256] ____cacheline_aligned = { - { - 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, - 0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b, - 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, - 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, - 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d, - 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, - 0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, - 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e, - 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927, - 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, - 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, - 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, - 0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, - 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, - 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3, - 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, - 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e, - 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4, - 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, - 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd, - 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, - 0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060, - 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967, - 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, - 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000, - 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, - 0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36, - 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, - 0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b, - 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, - 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, - 0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, - 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, - 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, - 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, - 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, - 0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, - 0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177, - 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, - 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, - 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, - 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, - 0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54, - 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, - 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf, - 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, - 0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83, - 0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef, - 0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, - 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235, - 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, - 0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117, - 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4, - 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546, - 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, - 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, - 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, - 0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, - 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, - 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, - 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, - 0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff, - 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, - 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0, - }, { - 0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, - 0x6bab3bcb, 0x459d1ff1, 0x58faacab, 0x03e34b93, - 0xfa302055, 0x6d76adf6, 0x76cc8891, 0x4c02f525, - 0xd7e54ffc, 0xcb2ac5d7, 0x44352680, 0xa362b58f, - 0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1, - 0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6, - 0x5f8f03e7, 0x9c921595, 0x7a6dbfeb, 0x595295da, - 0x83bed42d, 0x217458d3, 0x69e04929, 0xc8c98e44, - 0x89c2756a, 0x798ef478, 0x3e58996b, 0x71b927dd, - 0x4fe1beb6, 0xad88f017, 0xac20c966, 0x3ace7db4, - 0x4adf6318, 0x311ae582, 0x33519760, 0x7f536245, - 0x7764b1e0, 0xae6bbb84, 0xa081fe1c, 0x2b08f994, - 0x68487058, 0xfd458f19, 0x6cde9487, 0xf87b52b7, - 0xd373ab23, 0x024b72e2, 0x8f1fe357, 0xab55662a, - 0x28ebb207, 0xc2b52f03, 0x7bc5869a, 0x0837d3a5, - 0x872830f2, 0xa5bf23b2, 0x6a0302ba, 0x8216ed5c, - 0x1ccf8a2b, 0xb479a792, 0xf207f3f0, 0xe2694ea1, - 0xf4da65cd, 0xbe0506d5, 0x6234d11f, 0xfea6c48a, - 0x532e349d, 0x55f3a2a0, 0xe18a0532, 0xebf6a475, - 0xec830b39, 0xef6040aa, 0x9f715e06, 0x106ebd51, - 0x8a213ef9, 0x06dd963d, 0x053eddae, 0xbde64d46, - 0x8d5491b5, 0x5dc47105, 0xd406046f, 0x155060ff, - 0xfb981924, 0xe9bdd697, 0x434089cc, 0x9ed96777, - 0x42e8b0bd, 0x8b890788, 0x5b19e738, 0xeec879db, - 0x0a7ca147, 0x0f427ce9, 0x1e84f8c9, 0x00000000, - 0x86800983, 0xed2b3248, 0x70111eac, 0x725a6c4e, - 0xff0efdfb, 0x38850f56, 0xd5ae3d1e, 0x392d3627, - 0xd90f0a64, 0xa65c6821, 0x545b9bd1, 0x2e36243a, - 0x670a0cb1, 0xe757930f, 0x96eeb4d2, 0x919b1b9e, - 0xc5c0804f, 0x20dc61a2, 0x4b775a69, 0x1a121c16, - 0xba93e20a, 0x2aa0c0e5, 0xe0223c43, 0x171b121d, - 0x0d090e0b, 0xc78bf2ad, 0xa8b62db9, 0xa91e14c8, - 0x19f15785, 0x0775af4c, 0xdd99eebb, 0x607fa3fd, - 0x2601f79f, 0xf5725cbc, 0x3b6644c5, 0x7efb5b34, - 0x29438b76, 0xc623cbdc, 0xfcedb668, 0xf1e4b863, - 0xdc31d7ca, 0x85634210, 0x22971340, 0x11c68420, - 0x244a857d, 0x3dbbd2f8, 0x32f9ae11, 0xa129c76d, - 0x2f9e1d4b, 0x30b2dcf3, 0x52860dec, 0xe3c177d0, - 0x16b32b6c, 0xb970a999, 0x489411fa, 0x64e94722, - 0x8cfca8c4, 0x3ff0a01a, 0x2c7d56d8, 0x903322ef, - 0x4e4987c7, 0xd138d9c1, 0xa2ca8cfe, 0x0bd49836, - 0x81f5a6cf, 0xde7aa528, 0x8eb7da26, 0xbfad3fa4, - 0x9d3a2ce4, 0x9278500d, 0xcc5f6a9b, 0x467e5462, - 0x138df6c2, 0xb8d890e8, 0xf7392e5e, 0xafc382f5, - 0x805d9fbe, 0x93d0697c, 0x2dd56fa9, 0x1225cfb3, - 0x99acc83b, 0x7d1810a7, 0x639ce86e, 0xbb3bdb7b, - 0x7826cd09, 0x18596ef4, 0xb79aec01, 0x9a4f83a8, - 0x6e95e665, 0xe6ffaa7e, 0xcfbc2108, 0xe815efe6, - 0x9be7bad9, 0x366f4ace, 0x099fead4, 0x7cb029d6, - 0xb2a431af, 0x233f2a31, 0x94a5c630, 0x66a235c0, - 0xbc4e7437, 0xca82fca6, 0xd090e0b0, 0xd8a73315, - 0x9804f14a, 0xdaec41f7, 0x50cd7f0e, 0xf691172f, - 0xd64d768d, 0xb0ef434d, 0x4daacc54, 0x0496e4df, - 0xb5d19ee3, 0x886a4c1b, 0x1f2cc1b8, 0x5165467f, - 0xea5e9d04, 0x358c015d, 0x7487fa73, 0x410bfb2e, - 0x1d67b35a, 0xd2db9252, 0x5610e933, 0x47d66d13, - 0x61d79a8c, 0x0ca1377a, 0x14f8598e, 0x3c13eb89, - 0x27a9ceee, 0xc961b735, 0xe51ce1ed, 0xb1477a3c, - 0xdfd29c59, 0x73f2553f, 0xce141879, 0x37c773bf, - 0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886, - 0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, - 0xc31d1672, 0x25e2bc0c, 0x493c288b, 0x950dff41, - 0x01a83971, 0xb30c08de, 0xe4b4d89c, 0xc1566490, - 0x84cb7b61, 0xb632d570, 0x5c6c4874, 0x57b8d042, - }, { - 0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, - 0xab3bcb6b, 0x9d1ff145, 0xfaacab58, 0xe34b9303, - 0x302055fa, 0x76adf66d, 0xcc889176, 0x02f5254c, - 0xe54ffcd7, 0x2ac5d7cb, 0x35268044, 0x62b58fa3, - 0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0, - 0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9, - 0x8f03e75f, 0x9215959c, 0x6dbfeb7a, 0x5295da59, - 0xbed42d83, 0x7458d321, 0xe0492969, 0xc98e44c8, - 0xc2756a89, 0x8ef47879, 0x58996b3e, 0xb927dd71, - 0xe1beb64f, 0x88f017ad, 0x20c966ac, 0xce7db43a, - 0xdf63184a, 0x1ae58231, 0x51976033, 0x5362457f, - 0x64b1e077, 0x6bbb84ae, 0x81fe1ca0, 0x08f9942b, - 0x48705868, 0x458f19fd, 0xde94876c, 0x7b52b7f8, - 0x73ab23d3, 0x4b72e202, 0x1fe3578f, 0x55662aab, - 0xebb20728, 0xb52f03c2, 0xc5869a7b, 0x37d3a508, - 0x2830f287, 0xbf23b2a5, 0x0302ba6a, 0x16ed5c82, - 0xcf8a2b1c, 0x79a792b4, 0x07f3f0f2, 0x694ea1e2, - 0xda65cdf4, 0x0506d5be, 0x34d11f62, 0xa6c48afe, - 0x2e349d53, 0xf3a2a055, 0x8a0532e1, 0xf6a475eb, - 0x830b39ec, 0x6040aaef, 0x715e069f, 0x6ebd5110, - 0x213ef98a, 0xdd963d06, 0x3eddae05, 0xe64d46bd, - 0x5491b58d, 0xc471055d, 0x06046fd4, 0x5060ff15, - 0x981924fb, 0xbdd697e9, 0x4089cc43, 0xd967779e, - 0xe8b0bd42, 0x8907888b, 0x19e7385b, 0xc879dbee, - 0x7ca1470a, 0x427ce90f, 0x84f8c91e, 0x00000000, - 0x80098386, 0x2b3248ed, 0x111eac70, 0x5a6c4e72, - 0x0efdfbff, 0x850f5638, 0xae3d1ed5, 0x2d362739, - 0x0f0a64d9, 0x5c6821a6, 0x5b9bd154, 0x36243a2e, - 0x0a0cb167, 0x57930fe7, 0xeeb4d296, 0x9b1b9e91, - 0xc0804fc5, 0xdc61a220, 0x775a694b, 0x121c161a, - 0x93e20aba, 0xa0c0e52a, 0x223c43e0, 0x1b121d17, - 0x090e0b0d, 0x8bf2adc7, 0xb62db9a8, 0x1e14c8a9, - 0xf1578519, 0x75af4c07, 0x99eebbdd, 0x7fa3fd60, - 0x01f79f26, 0x725cbcf5, 0x6644c53b, 0xfb5b347e, - 0x438b7629, 0x23cbdcc6, 0xedb668fc, 0xe4b863f1, - 0x31d7cadc, 0x63421085, 0x97134022, 0xc6842011, - 0x4a857d24, 0xbbd2f83d, 0xf9ae1132, 0x29c76da1, - 0x9e1d4b2f, 0xb2dcf330, 0x860dec52, 0xc177d0e3, - 0xb32b6c16, 0x70a999b9, 0x9411fa48, 0xe9472264, - 0xfca8c48c, 0xf0a01a3f, 0x7d56d82c, 0x3322ef90, - 0x4987c74e, 0x38d9c1d1, 0xca8cfea2, 0xd498360b, - 0xf5a6cf81, 0x7aa528de, 0xb7da268e, 0xad3fa4bf, - 0x3a2ce49d, 0x78500d92, 0x5f6a9bcc, 0x7e546246, - 0x8df6c213, 0xd890e8b8, 0x392e5ef7, 0xc382f5af, - 0x5d9fbe80, 0xd0697c93, 0xd56fa92d, 0x25cfb312, - 0xacc83b99, 0x1810a77d, 0x9ce86e63, 0x3bdb7bbb, - 0x26cd0978, 0x596ef418, 0x9aec01b7, 0x4f83a89a, - 0x95e6656e, 0xffaa7ee6, 0xbc2108cf, 0x15efe6e8, - 0xe7bad99b, 0x6f4ace36, 0x9fead409, 0xb029d67c, - 0xa431afb2, 0x3f2a3123, 0xa5c63094, 0xa235c066, - 0x4e7437bc, 0x82fca6ca, 0x90e0b0d0, 0xa73315d8, - 0x04f14a98, 0xec41f7da, 0xcd7f0e50, 0x91172ff6, - 0x4d768dd6, 0xef434db0, 0xaacc544d, 0x96e4df04, - 0xd19ee3b5, 0x6a4c1b88, 0x2cc1b81f, 0x65467f51, - 0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0x0bfb2e41, - 0x67b35a1d, 0xdb9252d2, 0x10e93356, 0xd66d1347, - 0xd79a8c61, 0xa1377a0c, 0xf8598e14, 0x13eb893c, - 0xa9ceee27, 0x61b735c9, 0x1ce1ede5, 0x477a3cb1, - 0xd29c59df, 0xf2553f73, 0x141879ce, 0xc773bf37, - 0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db, - 0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, - 0x1d1672c3, 0xe2bc0c25, 0x3c288b49, 0x0dff4195, - 0xa8397101, 0x0c08deb3, 0xb4d89ce4, 0x566490c1, - 0xcb7b6184, 0x32d570b6, 0x6c48745c, 0xb8d04257, - }, { - 0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, - 0x3bcb6bab, 0x1ff1459d, 0xacab58fa, 0x4b9303e3, - 0x2055fa30, 0xadf66d76, 0x889176cc, 0xf5254c02, - 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435, 0xb58fa362, - 0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe, - 0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3, - 0x03e75f8f, 0x15959c92, 0xbfeb7a6d, 0x95da5952, - 0xd42d83be, 0x58d32174, 0x492969e0, 0x8e44c8c9, - 0x756a89c2, 0xf478798e, 0x996b3e58, 0x27dd71b9, - 0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace, - 0x63184adf, 0xe582311a, 0x97603351, 0x62457f53, - 0xb1e07764, 0xbb84ae6b, 0xfe1ca081, 0xf9942b08, - 0x70586848, 0x8f19fd45, 0x94876cde, 0x52b7f87b, - 0xab23d373, 0x72e2024b, 0xe3578f1f, 0x662aab55, - 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837, - 0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216, - 0x8a2b1ccf, 0xa792b479, 0xf3f0f207, 0x4ea1e269, - 0x65cdf4da, 0x06d5be05, 0xd11f6234, 0xc48afea6, - 0x349d532e, 0xa2a055f3, 0x0532e18a, 0xa475ebf6, - 0x0b39ec83, 0x40aaef60, 0x5e069f71, 0xbd51106e, - 0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6, - 0x91b58d54, 0x71055dc4, 0x046fd406, 0x60ff1550, - 0x1924fb98, 0xd697e9bd, 0x89cc4340, 0x67779ed9, - 0xb0bd42e8, 0x07888b89, 0xe7385b19, 0x79dbeec8, - 0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000, - 0x09838680, 0x3248ed2b, 0x1eac7011, 0x6c4e725a, - 0xfdfbff0e, 0x0f563885, 0x3d1ed5ae, 0x3627392d, - 0x0a64d90f, 0x6821a65c, 0x9bd1545b, 0x243a2e36, - 0x0cb1670a, 0x930fe757, 0xb4d296ee, 0x1b9e919b, - 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12, - 0xe20aba93, 0xc0e52aa0, 0x3c43e022, 0x121d171b, - 0x0e0b0d09, 0xf2adc78b, 0x2db9a8b6, 0x14c8a91e, - 0x578519f1, 0xaf4c0775, 0xeebbdd99, 0xa3fd607f, - 0xf79f2601, 0x5cbcf572, 0x44c53b66, 0x5b347efb, - 0x8b762943, 0xcbdcc623, 0xb668fced, 0xb863f1e4, - 0xd7cadc31, 0x42108563, 0x13402297, 0x842011c6, - 0x857d244a, 0xd2f83dbb, 0xae1132f9, 0xc76da129, - 0x1d4b2f9e, 0xdcf330b2, 0x0dec5286, 0x77d0e3c1, - 0x2b6c16b3, 0xa999b970, 0x11fa4894, 0x472264e9, - 0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, 0x22ef9033, - 0x87c74e49, 0xd9c1d138, 0x8cfea2ca, 0x98360bd4, - 0xa6cf81f5, 0xa528de7a, 0xda268eb7, 0x3fa4bfad, - 0x2ce49d3a, 0x500d9278, 0x6a9bcc5f, 0x5462467e, - 0xf6c2138d, 0x90e8b8d8, 0x2e5ef739, 0x82f5afc3, - 0x9fbe805d, 0x697c93d0, 0x6fa92dd5, 0xcfb31225, - 0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, - 0xcd097826, 0x6ef41859, 0xec01b79a, 0x83a89a4f, - 0xe6656e95, 0xaa7ee6ff, 0x2108cfbc, 0xefe6e815, - 0xbad99be7, 0x4ace366f, 0xead4099f, 0x29d67cb0, - 0x31afb2a4, 0x2a31233f, 0xc63094a5, 0x35c066a2, - 0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7, - 0xf14a9804, 0x41f7daec, 0x7f0e50cd, 0x172ff691, - 0x768dd64d, 0x434db0ef, 0xcc544daa, 0xe4df0496, - 0x9ee3b5d1, 0x4c1b886a, 0xc1b81f2c, 0x467f5165, - 0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b, - 0xb35a1d67, 0x9252d2db, 0xe9335610, 0x6d1347d6, - 0x9a8c61d7, 0x377a0ca1, 0x598e14f8, 0xeb893c13, - 0xceee27a9, 0xb735c961, 0xe1ede51c, 0x7a3cb147, - 0x9c59dfd2, 0x553f73f2, 0x1879ce14, 0x73bf37c7, - 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44, - 0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, - 0x1672c31d, 0xbc0c25e2, 0x288b493c, 0xff41950d, - 0x397101a8, 0x08deb30c, 0xd89ce4b4, 0x6490c156, - 0x7b6184cb, 0xd570b632, 0x48745c6c, 0xd04257b8, - } -}; - -static const u32 crypto_il_tab[4][256] ____cacheline_aligned = { - { - 0x00000052, 0x00000009, 0x0000006a, 0x000000d5, - 0x00000030, 0x00000036, 0x000000a5, 0x00000038, - 0x000000bf, 0x00000040, 0x000000a3, 0x0000009e, - 0x00000081, 0x000000f3, 0x000000d7, 0x000000fb, - 0x0000007c, 0x000000e3, 0x00000039, 0x00000082, - 0x0000009b, 0x0000002f, 0x000000ff, 0x00000087, - 0x00000034, 0x0000008e, 0x00000043, 0x00000044, - 0x000000c4, 0x000000de, 0x000000e9, 0x000000cb, - 0x00000054, 0x0000007b, 0x00000094, 0x00000032, - 0x000000a6, 0x000000c2, 0x00000023, 0x0000003d, - 0x000000ee, 0x0000004c, 0x00000095, 0x0000000b, - 0x00000042, 0x000000fa, 0x000000c3, 0x0000004e, - 0x00000008, 0x0000002e, 0x000000a1, 0x00000066, - 0x00000028, 0x000000d9, 0x00000024, 0x000000b2, - 0x00000076, 0x0000005b, 0x000000a2, 0x00000049, - 0x0000006d, 0x0000008b, 0x000000d1, 0x00000025, - 0x00000072, 0x000000f8, 0x000000f6, 0x00000064, - 0x00000086, 0x00000068, 0x00000098, 0x00000016, - 0x000000d4, 0x000000a4, 0x0000005c, 0x000000cc, - 0x0000005d, 0x00000065, 0x000000b6, 0x00000092, - 0x0000006c, 0x00000070, 0x00000048, 0x00000050, - 0x000000fd, 0x000000ed, 0x000000b9, 0x000000da, - 0x0000005e, 0x00000015, 0x00000046, 0x00000057, - 0x000000a7, 0x0000008d, 0x0000009d, 0x00000084, - 0x00000090, 0x000000d8, 0x000000ab, 0x00000000, - 0x0000008c, 0x000000bc, 0x000000d3, 0x0000000a, - 0x000000f7, 0x000000e4, 0x00000058, 0x00000005, - 0x000000b8, 0x000000b3, 0x00000045, 0x00000006, - 0x000000d0, 0x0000002c, 0x0000001e, 0x0000008f, - 0x000000ca, 0x0000003f, 0x0000000f, 0x00000002, - 0x000000c1, 0x000000af, 0x000000bd, 0x00000003, - 0x00000001, 0x00000013, 0x0000008a, 0x0000006b, - 0x0000003a, 0x00000091, 0x00000011, 0x00000041, - 0x0000004f, 0x00000067, 0x000000dc, 0x000000ea, - 0x00000097, 0x000000f2, 0x000000cf, 0x000000ce, - 0x000000f0, 0x000000b4, 0x000000e6, 0x00000073, - 0x00000096, 0x000000ac, 0x00000074, 0x00000022, - 0x000000e7, 0x000000ad, 0x00000035, 0x00000085, - 0x000000e2, 0x000000f9, 0x00000037, 0x000000e8, - 0x0000001c, 0x00000075, 0x000000df, 0x0000006e, - 0x00000047, 0x000000f1, 0x0000001a, 0x00000071, - 0x0000001d, 0x00000029, 0x000000c5, 0x00000089, - 0x0000006f, 0x000000b7, 0x00000062, 0x0000000e, - 0x000000aa, 0x00000018, 0x000000be, 0x0000001b, - 0x000000fc, 0x00000056, 0x0000003e, 0x0000004b, - 0x000000c6, 0x000000d2, 0x00000079, 0x00000020, - 0x0000009a, 0x000000db, 0x000000c0, 0x000000fe, - 0x00000078, 0x000000cd, 0x0000005a, 0x000000f4, - 0x0000001f, 0x000000dd, 0x000000a8, 0x00000033, - 0x00000088, 0x00000007, 0x000000c7, 0x00000031, - 0x000000b1, 0x00000012, 0x00000010, 0x00000059, - 0x00000027, 0x00000080, 0x000000ec, 0x0000005f, - 0x00000060, 0x00000051, 0x0000007f, 0x000000a9, - 0x00000019, 0x000000b5, 0x0000004a, 0x0000000d, - 0x0000002d, 0x000000e5, 0x0000007a, 0x0000009f, - 0x00000093, 0x000000c9, 0x0000009c, 0x000000ef, - 0x000000a0, 0x000000e0, 0x0000003b, 0x0000004d, - 0x000000ae, 0x0000002a, 0x000000f5, 0x000000b0, - 0x000000c8, 0x000000eb, 0x000000bb, 0x0000003c, - 0x00000083, 0x00000053, 0x00000099, 0x00000061, - 0x00000017, 0x0000002b, 0x00000004, 0x0000007e, - 0x000000ba, 0x00000077, 0x000000d6, 0x00000026, - 0x000000e1, 0x00000069, 0x00000014, 0x00000063, - 0x00000055, 0x00000021, 0x0000000c, 0x0000007d, - }, { - 0x00005200, 0x00000900, 0x00006a00, 0x0000d500, - 0x00003000, 0x00003600, 0x0000a500, 0x00003800, - 0x0000bf00, 0x00004000, 0x0000a300, 0x00009e00, - 0x00008100, 0x0000f300, 0x0000d700, 0x0000fb00, - 0x00007c00, 0x0000e300, 0x00003900, 0x00008200, - 0x00009b00, 0x00002f00, 0x0000ff00, 0x00008700, - 0x00003400, 0x00008e00, 0x00004300, 0x00004400, - 0x0000c400, 0x0000de00, 0x0000e900, 0x0000cb00, - 0x00005400, 0x00007b00, 0x00009400, 0x00003200, - 0x0000a600, 0x0000c200, 0x00002300, 0x00003d00, - 0x0000ee00, 0x00004c00, 0x00009500, 0x00000b00, - 0x00004200, 0x0000fa00, 0x0000c300, 0x00004e00, - 0x00000800, 0x00002e00, 0x0000a100, 0x00006600, - 0x00002800, 0x0000d900, 0x00002400, 0x0000b200, - 0x00007600, 0x00005b00, 0x0000a200, 0x00004900, - 0x00006d00, 0x00008b00, 0x0000d100, 0x00002500, - 0x00007200, 0x0000f800, 0x0000f600, 0x00006400, - 0x00008600, 0x00006800, 0x00009800, 0x00001600, - 0x0000d400, 0x0000a400, 0x00005c00, 0x0000cc00, - 0x00005d00, 0x00006500, 0x0000b600, 0x00009200, - 0x00006c00, 0x00007000, 0x00004800, 0x00005000, - 0x0000fd00, 0x0000ed00, 0x0000b900, 0x0000da00, - 0x00005e00, 0x00001500, 0x00004600, 0x00005700, - 0x0000a700, 0x00008d00, 0x00009d00, 0x00008400, - 0x00009000, 0x0000d800, 0x0000ab00, 0x00000000, - 0x00008c00, 0x0000bc00, 0x0000d300, 0x00000a00, - 0x0000f700, 0x0000e400, 0x00005800, 0x00000500, - 0x0000b800, 0x0000b300, 0x00004500, 0x00000600, - 0x0000d000, 0x00002c00, 0x00001e00, 0x00008f00, - 0x0000ca00, 0x00003f00, 0x00000f00, 0x00000200, - 0x0000c100, 0x0000af00, 0x0000bd00, 0x00000300, - 0x00000100, 0x00001300, 0x00008a00, 0x00006b00, - 0x00003a00, 0x00009100, 0x00001100, 0x00004100, - 0x00004f00, 0x00006700, 0x0000dc00, 0x0000ea00, - 0x00009700, 0x0000f200, 0x0000cf00, 0x0000ce00, - 0x0000f000, 0x0000b400, 0x0000e600, 0x00007300, - 0x00009600, 0x0000ac00, 0x00007400, 0x00002200, - 0x0000e700, 0x0000ad00, 0x00003500, 0x00008500, - 0x0000e200, 0x0000f900, 0x00003700, 0x0000e800, - 0x00001c00, 0x00007500, 0x0000df00, 0x00006e00, - 0x00004700, 0x0000f100, 0x00001a00, 0x00007100, - 0x00001d00, 0x00002900, 0x0000c500, 0x00008900, - 0x00006f00, 0x0000b700, 0x00006200, 0x00000e00, - 0x0000aa00, 0x00001800, 0x0000be00, 0x00001b00, - 0x0000fc00, 0x00005600, 0x00003e00, 0x00004b00, - 0x0000c600, 0x0000d200, 0x00007900, 0x00002000, - 0x00009a00, 0x0000db00, 0x0000c000, 0x0000fe00, - 0x00007800, 0x0000cd00, 0x00005a00, 0x0000f400, - 0x00001f00, 0x0000dd00, 0x0000a800, 0x00003300, - 0x00008800, 0x00000700, 0x0000c700, 0x00003100, - 0x0000b100, 0x00001200, 0x00001000, 0x00005900, - 0x00002700, 0x00008000, 0x0000ec00, 0x00005f00, - 0x00006000, 0x00005100, 0x00007f00, 0x0000a900, - 0x00001900, 0x0000b500, 0x00004a00, 0x00000d00, - 0x00002d00, 0x0000e500, 0x00007a00, 0x00009f00, - 0x00009300, 0x0000c900, 0x00009c00, 0x0000ef00, - 0x0000a000, 0x0000e000, 0x00003b00, 0x00004d00, - 0x0000ae00, 0x00002a00, 0x0000f500, 0x0000b000, - 0x0000c800, 0x0000eb00, 0x0000bb00, 0x00003c00, - 0x00008300, 0x00005300, 0x00009900, 0x00006100, - 0x00001700, 0x00002b00, 0x00000400, 0x00007e00, - 0x0000ba00, 0x00007700, 0x0000d600, 0x00002600, - 0x0000e100, 0x00006900, 0x00001400, 0x00006300, - 0x00005500, 0x00002100, 0x00000c00, 0x00007d00, - }, { - 0x00520000, 0x00090000, 0x006a0000, 0x00d50000, - 0x00300000, 0x00360000, 0x00a50000, 0x00380000, - 0x00bf0000, 0x00400000, 0x00a30000, 0x009e0000, - 0x00810000, 0x00f30000, 0x00d70000, 0x00fb0000, - 0x007c0000, 0x00e30000, 0x00390000, 0x00820000, - 0x009b0000, 0x002f0000, 0x00ff0000, 0x00870000, - 0x00340000, 0x008e0000, 0x00430000, 0x00440000, - 0x00c40000, 0x00de0000, 0x00e90000, 0x00cb0000, - 0x00540000, 0x007b0000, 0x00940000, 0x00320000, - 0x00a60000, 0x00c20000, 0x00230000, 0x003d0000, - 0x00ee0000, 0x004c0000, 0x00950000, 0x000b0000, - 0x00420000, 0x00fa0000, 0x00c30000, 0x004e0000, - 0x00080000, 0x002e0000, 0x00a10000, 0x00660000, - 0x00280000, 0x00d90000, 0x00240000, 0x00b20000, - 0x00760000, 0x005b0000, 0x00a20000, 0x00490000, - 0x006d0000, 0x008b0000, 0x00d10000, 0x00250000, - 0x00720000, 0x00f80000, 0x00f60000, 0x00640000, - 0x00860000, 0x00680000, 0x00980000, 0x00160000, - 0x00d40000, 0x00a40000, 0x005c0000, 0x00cc0000, - 0x005d0000, 0x00650000, 0x00b60000, 0x00920000, - 0x006c0000, 0x00700000, 0x00480000, 0x00500000, - 0x00fd0000, 0x00ed0000, 0x00b90000, 0x00da0000, - 0x005e0000, 0x00150000, 0x00460000, 0x00570000, - 0x00a70000, 0x008d0000, 0x009d0000, 0x00840000, - 0x00900000, 0x00d80000, 0x00ab0000, 0x00000000, - 0x008c0000, 0x00bc0000, 0x00d30000, 0x000a0000, - 0x00f70000, 0x00e40000, 0x00580000, 0x00050000, - 0x00b80000, 0x00b30000, 0x00450000, 0x00060000, - 0x00d00000, 0x002c0000, 0x001e0000, 0x008f0000, - 0x00ca0000, 0x003f0000, 0x000f0000, 0x00020000, - 0x00c10000, 0x00af0000, 0x00bd0000, 0x00030000, - 0x00010000, 0x00130000, 0x008a0000, 0x006b0000, - 0x003a0000, 0x00910000, 0x00110000, 0x00410000, - 0x004f0000, 0x00670000, 0x00dc0000, 0x00ea0000, - 0x00970000, 0x00f20000, 0x00cf0000, 0x00ce0000, - 0x00f00000, 0x00b40000, 0x00e60000, 0x00730000, - 0x00960000, 0x00ac0000, 0x00740000, 0x00220000, - 0x00e70000, 0x00ad0000, 0x00350000, 0x00850000, - 0x00e20000, 0x00f90000, 0x00370000, 0x00e80000, - 0x001c0000, 0x00750000, 0x00df0000, 0x006e0000, - 0x00470000, 0x00f10000, 0x001a0000, 0x00710000, - 0x001d0000, 0x00290000, 0x00c50000, 0x00890000, - 0x006f0000, 0x00b70000, 0x00620000, 0x000e0000, - 0x00aa0000, 0x00180000, 0x00be0000, 0x001b0000, - 0x00fc0000, 0x00560000, 0x003e0000, 0x004b0000, - 0x00c60000, 0x00d20000, 0x00790000, 0x00200000, - 0x009a0000, 0x00db0000, 0x00c00000, 0x00fe0000, - 0x00780000, 0x00cd0000, 0x005a0000, 0x00f40000, - 0x001f0000, 0x00dd0000, 0x00a80000, 0x00330000, - 0x00880000, 0x00070000, 0x00c70000, 0x00310000, - 0x00b10000, 0x00120000, 0x00100000, 0x00590000, - 0x00270000, 0x00800000, 0x00ec0000, 0x005f0000, - 0x00600000, 0x00510000, 0x007f0000, 0x00a90000, - 0x00190000, 0x00b50000, 0x004a0000, 0x000d0000, - 0x002d0000, 0x00e50000, 0x007a0000, 0x009f0000, - 0x00930000, 0x00c90000, 0x009c0000, 0x00ef0000, - 0x00a00000, 0x00e00000, 0x003b0000, 0x004d0000, - 0x00ae0000, 0x002a0000, 0x00f50000, 0x00b00000, - 0x00c80000, 0x00eb0000, 0x00bb0000, 0x003c0000, - 0x00830000, 0x00530000, 0x00990000, 0x00610000, - 0x00170000, 0x002b0000, 0x00040000, 0x007e0000, - 0x00ba0000, 0x00770000, 0x00d60000, 0x00260000, - 0x00e10000, 0x00690000, 0x00140000, 0x00630000, - 0x00550000, 0x00210000, 0x000c0000, 0x007d0000, - }, { - 0x52000000, 0x09000000, 0x6a000000, 0xd5000000, - 0x30000000, 0x36000000, 0xa5000000, 0x38000000, - 0xbf000000, 0x40000000, 0xa3000000, 0x9e000000, - 0x81000000, 0xf3000000, 0xd7000000, 0xfb000000, - 0x7c000000, 0xe3000000, 0x39000000, 0x82000000, - 0x9b000000, 0x2f000000, 0xff000000, 0x87000000, - 0x34000000, 0x8e000000, 0x43000000, 0x44000000, - 0xc4000000, 0xde000000, 0xe9000000, 0xcb000000, - 0x54000000, 0x7b000000, 0x94000000, 0x32000000, - 0xa6000000, 0xc2000000, 0x23000000, 0x3d000000, - 0xee000000, 0x4c000000, 0x95000000, 0x0b000000, - 0x42000000, 0xfa000000, 0xc3000000, 0x4e000000, - 0x08000000, 0x2e000000, 0xa1000000, 0x66000000, - 0x28000000, 0xd9000000, 0x24000000, 0xb2000000, - 0x76000000, 0x5b000000, 0xa2000000, 0x49000000, - 0x6d000000, 0x8b000000, 0xd1000000, 0x25000000, - 0x72000000, 0xf8000000, 0xf6000000, 0x64000000, - 0x86000000, 0x68000000, 0x98000000, 0x16000000, - 0xd4000000, 0xa4000000, 0x5c000000, 0xcc000000, - 0x5d000000, 0x65000000, 0xb6000000, 0x92000000, - 0x6c000000, 0x70000000, 0x48000000, 0x50000000, - 0xfd000000, 0xed000000, 0xb9000000, 0xda000000, - 0x5e000000, 0x15000000, 0x46000000, 0x57000000, - 0xa7000000, 0x8d000000, 0x9d000000, 0x84000000, - 0x90000000, 0xd8000000, 0xab000000, 0x00000000, - 0x8c000000, 0xbc000000, 0xd3000000, 0x0a000000, - 0xf7000000, 0xe4000000, 0x58000000, 0x05000000, - 0xb8000000, 0xb3000000, 0x45000000, 0x06000000, - 0xd0000000, 0x2c000000, 0x1e000000, 0x8f000000, - 0xca000000, 0x3f000000, 0x0f000000, 0x02000000, - 0xc1000000, 0xaf000000, 0xbd000000, 0x03000000, - 0x01000000, 0x13000000, 0x8a000000, 0x6b000000, - 0x3a000000, 0x91000000, 0x11000000, 0x41000000, - 0x4f000000, 0x67000000, 0xdc000000, 0xea000000, - 0x97000000, 0xf2000000, 0xcf000000, 0xce000000, - 0xf0000000, 0xb4000000, 0xe6000000, 0x73000000, - 0x96000000, 0xac000000, 0x74000000, 0x22000000, - 0xe7000000, 0xad000000, 0x35000000, 0x85000000, - 0xe2000000, 0xf9000000, 0x37000000, 0xe8000000, - 0x1c000000, 0x75000000, 0xdf000000, 0x6e000000, - 0x47000000, 0xf1000000, 0x1a000000, 0x71000000, - 0x1d000000, 0x29000000, 0xc5000000, 0x89000000, - 0x6f000000, 0xb7000000, 0x62000000, 0x0e000000, - 0xaa000000, 0x18000000, 0xbe000000, 0x1b000000, - 0xfc000000, 0x56000000, 0x3e000000, 0x4b000000, - 0xc6000000, 0xd2000000, 0x79000000, 0x20000000, - 0x9a000000, 0xdb000000, 0xc0000000, 0xfe000000, - 0x78000000, 0xcd000000, 0x5a000000, 0xf4000000, - 0x1f000000, 0xdd000000, 0xa8000000, 0x33000000, - 0x88000000, 0x07000000, 0xc7000000, 0x31000000, - 0xb1000000, 0x12000000, 0x10000000, 0x59000000, - 0x27000000, 0x80000000, 0xec000000, 0x5f000000, - 0x60000000, 0x51000000, 0x7f000000, 0xa9000000, - 0x19000000, 0xb5000000, 0x4a000000, 0x0d000000, - 0x2d000000, 0xe5000000, 0x7a000000, 0x9f000000, - 0x93000000, 0xc9000000, 0x9c000000, 0xef000000, - 0xa0000000, 0xe0000000, 0x3b000000, 0x4d000000, - 0xae000000, 0x2a000000, 0xf5000000, 0xb0000000, - 0xc8000000, 0xeb000000, 0xbb000000, 0x3c000000, - 0x83000000, 0x53000000, 0x99000000, 0x61000000, - 0x17000000, 0x2b000000, 0x04000000, 0x7e000000, - 0xba000000, 0x77000000, 0xd6000000, 0x26000000, - 0xe1000000, 0x69000000, 0x14000000, 0x63000000, - 0x55000000, 0x21000000, 0x0c000000, 0x7d000000, - } -}; - -EXPORT_SYMBOL_GPL(crypto_ft_tab); -EXPORT_SYMBOL_GPL(crypto_it_tab); - -/** - * crypto_aes_set_key - Set the AES key. - * @tfm: The %crypto_tfm that is used in the context. - * @in_key: The input key. - * @key_len: The size of the key. - * - * This function uses aes_expand_key() to expand the key. &crypto_aes_ctx - * _must_ be the private data embedded in @tfm which is retrieved with - * crypto_tfm_ctx(). - * - * Return: 0 on success; -EINVAL on failure (only happens for bad key lengths) - */ -int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) -{ - struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - return aes_expandkey(ctx, in_key, key_len); -} -EXPORT_SYMBOL_GPL(crypto_aes_set_key); - -/* encrypt a block of text */ - -#define f_rn(bo, bi, n, k) do { \ - bo[n] = crypto_ft_tab[0][byte(bi[n], 0)] ^ \ - crypto_ft_tab[1][byte(bi[(n + 1) & 3], 1)] ^ \ - crypto_ft_tab[2][byte(bi[(n + 2) & 3], 2)] ^ \ - crypto_ft_tab[3][byte(bi[(n + 3) & 3], 3)] ^ *(k + n); \ -} while (0) - -#define f_nround(bo, bi, k) do {\ - f_rn(bo, bi, 0, k); \ - f_rn(bo, bi, 1, k); \ - f_rn(bo, bi, 2, k); \ - f_rn(bo, bi, 3, k); \ - k += 4; \ -} while (0) - -#define f_rl(bo, bi, n, k) do { \ - bo[n] = crypto_fl_tab[0][byte(bi[n], 0)] ^ \ - crypto_fl_tab[1][byte(bi[(n + 1) & 3], 1)] ^ \ - crypto_fl_tab[2][byte(bi[(n + 2) & 3], 2)] ^ \ - crypto_fl_tab[3][byte(bi[(n + 3) & 3], 3)] ^ *(k + n); \ -} while (0) - -#define f_lround(bo, bi, k) do {\ - f_rl(bo, bi, 0, k); \ - f_rl(bo, bi, 1, k); \ - f_rl(bo, bi, 2, k); \ - f_rl(bo, bi, 3, k); \ -} while (0) - -static void crypto_aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -{ - const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - u32 b0[4], b1[4]; - const u32 *kp = ctx->key_enc + 4; - const int key_len = ctx->key_length; - - b0[0] = ctx->key_enc[0] ^ get_unaligned_le32(in); - b0[1] = ctx->key_enc[1] ^ get_unaligned_le32(in + 4); - b0[2] = ctx->key_enc[2] ^ get_unaligned_le32(in + 8); - b0[3] = ctx->key_enc[3] ^ get_unaligned_le32(in + 12); - - if (key_len > 24) { - f_nround(b1, b0, kp); - f_nround(b0, b1, kp); - } - - if (key_len > 16) { - f_nround(b1, b0, kp); - f_nround(b0, b1, kp); - } - - f_nround(b1, b0, kp); - f_nround(b0, b1, kp); - f_nround(b1, b0, kp); - f_nround(b0, b1, kp); - f_nround(b1, b0, kp); - f_nround(b0, b1, kp); - f_nround(b1, b0, kp); - f_nround(b0, b1, kp); - f_nround(b1, b0, kp); - f_lround(b0, b1, kp); - - put_unaligned_le32(b0[0], out); - put_unaligned_le32(b0[1], out + 4); - put_unaligned_le32(b0[2], out + 8); - put_unaligned_le32(b0[3], out + 12); -} - -/* decrypt a block of text */ - -#define i_rn(bo, bi, n, k) do { \ - bo[n] = crypto_it_tab[0][byte(bi[n], 0)] ^ \ - crypto_it_tab[1][byte(bi[(n + 3) & 3], 1)] ^ \ - crypto_it_tab[2][byte(bi[(n + 2) & 3], 2)] ^ \ - crypto_it_tab[3][byte(bi[(n + 1) & 3], 3)] ^ *(k + n); \ -} while (0) - -#define i_nround(bo, bi, k) do {\ - i_rn(bo, bi, 0, k); \ - i_rn(bo, bi, 1, k); \ - i_rn(bo, bi, 2, k); \ - i_rn(bo, bi, 3, k); \ - k += 4; \ -} while (0) - -#define i_rl(bo, bi, n, k) do { \ - bo[n] = crypto_il_tab[0][byte(bi[n], 0)] ^ \ - crypto_il_tab[1][byte(bi[(n + 3) & 3], 1)] ^ \ - crypto_il_tab[2][byte(bi[(n + 2) & 3], 2)] ^ \ - crypto_il_tab[3][byte(bi[(n + 1) & 3], 3)] ^ *(k + n); \ -} while (0) - -#define i_lround(bo, bi, k) do {\ - i_rl(bo, bi, 0, k); \ - i_rl(bo, bi, 1, k); \ - i_rl(bo, bi, 2, k); \ - i_rl(bo, bi, 3, k); \ -} while (0) - -static void crypto_aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -{ - const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - u32 b0[4], b1[4]; - const int key_len = ctx->key_length; - const u32 *kp = ctx->key_dec + 4; - - b0[0] = ctx->key_dec[0] ^ get_unaligned_le32(in); - b0[1] = ctx->key_dec[1] ^ get_unaligned_le32(in + 4); - b0[2] = ctx->key_dec[2] ^ get_unaligned_le32(in + 8); - b0[3] = ctx->key_dec[3] ^ get_unaligned_le32(in + 12); - - if (key_len > 24) { - i_nround(b1, b0, kp); - i_nround(b0, b1, kp); - } - - if (key_len > 16) { - i_nround(b1, b0, kp); - i_nround(b0, b1, kp); - } - - i_nround(b1, b0, kp); - i_nround(b0, b1, kp); - i_nround(b1, b0, kp); - i_nround(b0, b1, kp); - i_nround(b1, b0, kp); - i_nround(b0, b1, kp); - i_nround(b1, b0, kp); - i_nround(b0, b1, kp); - i_nround(b1, b0, kp); - i_lround(b0, b1, kp); - - put_unaligned_le32(b0[0], out); - put_unaligned_le32(b0[1], out + 4); - put_unaligned_le32(b0[2], out + 8); - put_unaligned_le32(b0[3], out + 12); -} - -static struct crypto_alg aes_alg = { - .cra_name = "aes", - .cra_driver_name = "aes-generic", - .cra_priority = 100, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_aes_ctx), - .cra_module = THIS_MODULE, - .cra_u = { - .cipher = { - .cia_min_keysize = AES_MIN_KEY_SIZE, - .cia_max_keysize = AES_MAX_KEY_SIZE, - .cia_setkey = crypto_aes_set_key, - .cia_encrypt = crypto_aes_encrypt, - .cia_decrypt = crypto_aes_decrypt - } - } -}; - -static int __init aes_init(void) -{ - return crypto_register_alg(&aes_alg); -} - -static void __exit aes_fini(void) -{ - crypto_unregister_alg(&aes_alg); -} - -module_init(aes_init); -module_exit(aes_fini); - -MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_ALIAS_CRYPTO("aes"); -MODULE_ALIAS_CRYPTO("aes-generic"); diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index aad429bef03e..3187e0d276f9 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -293,7 +293,7 @@ static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh, if (!alg) return -ENOENT; - /* We can not unregister core algorithms such as aes-generic. + /* We can not unregister core algorithms such as aes. * We would loose the reference in the crypto_alg_list to this algorithm * if we try to unregister. Unregistering such an algorithm without * removing the module is not possible, so we restrict to crypto diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 5df204d9c9dd..cbc049d697a1 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -4061,14 +4061,14 @@ static int alg_test_null(const struct alg_test_desc *desc, static const struct alg_test_desc alg_test_descs[] = { { .alg = "adiantum(xchacha12,aes)", - .generic_driver = "adiantum(xchacha12-lib,aes-generic)", + .generic_driver = "adiantum(xchacha12-lib,aes-lib)", .test = alg_test_skcipher, .suite = { .cipher = __VECS(adiantum_xchacha12_aes_tv_template) }, }, { .alg = "adiantum(xchacha20,aes)", - .generic_driver = "adiantum(xchacha20-lib,aes-generic)", + .generic_driver = "adiantum(xchacha20-lib,aes-lib)", .test = alg_test_skcipher, .suite = { .cipher = __VECS(adiantum_xchacha20_aes_tv_template) @@ -4088,7 +4088,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "authenc(hmac(sha1),cbc(aes))", - .generic_driver = "authenc(hmac-sha1-lib,cbc(aes-generic))", + .generic_driver = "authenc(hmac-sha1-lib,cbc(aes-lib))", .test = alg_test_aead, .fips_allowed = 1, .suite = { @@ -4139,7 +4139,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "authenc(hmac(sha256),cbc(aes))", - .generic_driver = "authenc(hmac-sha256-lib,cbc(aes-generic))", + .generic_driver = "authenc(hmac-sha256-lib,cbc(aes-lib))", .test = alg_test_aead, .fips_allowed = 1, .suite = { @@ -4165,7 +4165,7 @@ static const struct alg_test_desc alg_test_descs[] = { .fips_allowed = 1, }, { .alg = "authenc(hmac(sha256),cts(cbc(aes)))", - .generic_driver = "authenc(hmac-sha256-lib,cts(cbc(aes-generic)))", + .generic_driver = "authenc(hmac-sha256-lib,cts(cbc(aes-lib)))", .test = alg_test_aead, .suite = { .aead = __VECS(krb5_test_aes128_cts_hmac_sha256_128) @@ -4194,7 +4194,7 @@ static const struct alg_test_desc alg_test_descs[] = { .fips_allowed = 1, }, { .alg = "authenc(hmac(sha384),cts(cbc(aes)))", - .generic_driver = "authenc(hmac-sha384-lib,cts(cbc(aes-generic)))", + .generic_driver = "authenc(hmac-sha384-lib,cts(cbc(aes-lib)))", .test = alg_test_aead, .suite = { .aead = __VECS(krb5_test_aes256_cts_hmac_sha384_192) @@ -4205,7 +4205,7 @@ static const struct alg_test_desc alg_test_descs[] = { .fips_allowed = 1, }, { .alg = "authenc(hmac(sha512),cbc(aes))", - .generic_driver = "authenc(hmac-sha512-lib,cbc(aes-generic))", + .generic_driver = "authenc(hmac-sha512-lib,cbc(aes-lib))", .fips_allowed = 1, .test = alg_test_aead, .suite = { @@ -4267,6 +4267,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "cbc(aes)", + .generic_driver = "cbc(aes-lib)", .test = alg_test_skcipher, .fips_allowed = 1, .suite = { @@ -4362,6 +4363,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, { #endif .alg = "cbcmac(aes)", + .generic_driver = "cbcmac(aes-lib)", .test = alg_test_hash, .suite = { .hash = __VECS(aes_cbcmac_tv_template) @@ -4374,7 +4376,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ccm(aes)", - .generic_driver = "ccm_base(ctr(aes-generic),cbcmac(aes-generic))", + .generic_driver = "ccm_base(ctr(aes-lib),cbcmac(aes-lib))", .test = alg_test_aead, .fips_allowed = 1, .suite = { @@ -4402,6 +4404,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, }, { .alg = "cmac(aes)", + .generic_driver = "cmac(aes-lib)", .fips_allowed = 1, .test = alg_test_hash, .suite = { @@ -4443,6 +4446,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "ctr(aes)", + .generic_driver = "ctr(aes-lib)", .test = alg_test_skcipher, .fips_allowed = 1, .suite = { @@ -4533,6 +4537,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, { #endif .alg = "cts(cbc(aes))", + .generic_driver = "cts(cbc(aes-lib))", .test = alg_test_skcipher, .fips_allowed = 1, .suite = { @@ -4689,6 +4694,7 @@ static const struct alg_test_desc alg_test_descs[] = { .test = alg_test_null, }, { .alg = "ecb(aes)", + .generic_driver = "ecb(aes-lib)", .test = alg_test_skcipher, .fips_allowed = 1, .suite = { @@ -4881,7 +4887,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "essiv(authenc(hmac(sha256),cbc(aes)),sha256)", - .generic_driver = "essiv(authenc(hmac-sha256-lib,cbc(aes-generic)),sha256-lib)", + .generic_driver = "essiv(authenc(hmac-sha256-lib,cbc(aes-lib)),sha256-lib)", .test = alg_test_aead, .fips_allowed = 1, .suite = { @@ -4889,7 +4895,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "essiv(cbc(aes),sha256)", - .generic_driver = "essiv(cbc(aes-generic),sha256-lib)", + .generic_driver = "essiv(cbc(aes-lib),sha256-lib)", .test = alg_test_skcipher, .fips_allowed = 1, .suite = { @@ -4934,7 +4940,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, { #endif /* CONFIG_CRYPTO_DH_RFC7919_GROUPS */ .alg = "gcm(aes)", - .generic_driver = "gcm_base(ctr(aes-generic),ghash-generic)", + .generic_driver = "gcm_base(ctr(aes-lib),ghash-generic)", .test = alg_test_aead, .fips_allowed = 1, .suite = { @@ -4962,7 +4968,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "hctr2(aes)", - .generic_driver = "hctr2_base(xctr(aes-generic),polyval-lib)", + .generic_driver = "hctr2_base(xctr(aes-lib),polyval-lib)", .test = alg_test_skcipher, .suite = { .cipher = __VECS(aes_hctr2_tv_template) @@ -5080,7 +5086,7 @@ static const struct alg_test_desc alg_test_descs[] = { .suite.aead = __VECS(krb5_test_camellia_cts_cmac) }, { .alg = "lrw(aes)", - .generic_driver = "lrw(ecb(aes-generic))", + .generic_driver = "lrw(ecb(aes-lib))", .test = alg_test_skcipher, .suite = { .cipher = __VECS(aes_lrw_tv_template) @@ -5269,6 +5275,7 @@ static const struct alg_test_desc alg_test_descs[] = { .fips_allowed = 1, }, { .alg = "rfc3686(ctr(aes))", + .generic_driver = "rfc3686(ctr(aes-lib))", .test = alg_test_skcipher, .fips_allowed = 1, .suite = { @@ -5282,7 +5289,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "rfc4106(gcm(aes))", - .generic_driver = "rfc4106(gcm_base(ctr(aes-generic),ghash-generic))", + .generic_driver = "rfc4106(gcm_base(ctr(aes-lib),ghash-generic))", .test = alg_test_aead, .fips_allowed = 1, .suite = { @@ -5294,7 +5301,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "rfc4309(ccm(aes))", - .generic_driver = "rfc4309(ccm_base(ctr(aes-generic),cbcmac(aes-generic)))", + .generic_driver = "rfc4309(ccm_base(ctr(aes-lib),cbcmac(aes-lib)))", .test = alg_test_aead, .fips_allowed = 1, .suite = { @@ -5306,7 +5313,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "rfc4543(gcm(aes))", - .generic_driver = "rfc4543(gcm_base(ctr(aes-generic),ghash-generic))", + .generic_driver = "rfc4543(gcm_base(ctr(aes-lib),ghash-generic))", .test = alg_test_aead, .suite = { .aead = { @@ -5483,6 +5490,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "xcbc(aes)", + .generic_driver = "xcbc(aes-lib)", .test = alg_test_hash, .suite = { .hash = __VECS(aes_xcbc128_tv_template) @@ -5509,13 +5517,14 @@ static const struct alg_test_desc alg_test_descs[] = { }, }, { .alg = "xctr(aes)", + .generic_driver = "xctr(aes-lib)", .test = alg_test_skcipher, .suite = { .cipher = __VECS(aes_xctr_tv_template) } }, { .alg = "xts(aes)", - .generic_driver = "xts(ecb(aes-generic))", + .generic_driver = "xts(ecb(aes-lib))", .test = alg_test_skcipher, .fips_allowed = 1, .suite = { diff --git a/drivers/crypto/starfive/jh7110-aes.c b/drivers/crypto/starfive/jh7110-aes.c index 426b24889af8..f1edb4fbf364 100644 --- a/drivers/crypto/starfive/jh7110-aes.c +++ b/drivers/crypto/starfive/jh7110-aes.c @@ -983,27 +983,27 @@ static int starfive_aes_ccm_decrypt(struct aead_request *req) static int starfive_aes_ecb_init_tfm(struct crypto_skcipher *tfm) { - return starfive_aes_init_tfm(tfm, "ecb(aes-generic)"); + return starfive_aes_init_tfm(tfm, "ecb(aes-lib)"); } static int starfive_aes_cbc_init_tfm(struct crypto_skcipher *tfm) { - return starfive_aes_init_tfm(tfm, "cbc(aes-generic)"); + return starfive_aes_init_tfm(tfm, "cbc(aes-lib)"); } static int starfive_aes_ctr_init_tfm(struct crypto_skcipher *tfm) { - return starfive_aes_init_tfm(tfm, "ctr(aes-generic)"); + return starfive_aes_init_tfm(tfm, "ctr(aes-lib)"); } static int starfive_aes_ccm_init_tfm(struct crypto_aead *tfm) { - return starfive_aes_aead_init_tfm(tfm, "ccm_base(ctr(aes-generic),cbcmac(aes-generic))"); + return starfive_aes_aead_init_tfm(tfm, "ccm_base(ctr(aes-lib),cbcmac(aes-lib))"); } static int starfive_aes_gcm_init_tfm(struct crypto_aead *tfm) { - return starfive_aes_aead_init_tfm(tfm, "gcm_base(ctr(aes-generic),ghash-generic)"); + return starfive_aes_aead_init_tfm(tfm, "gcm_base(ctr(aes-lib),ghash-generic)"); } static struct skcipher_engine_alg skcipher_algs[] = { diff --git a/include/crypto/aes.h b/include/crypto/aes.h index e8b83d4849fe..66421795cdab 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -82,9 +82,6 @@ struct crypto_aes_ctx { u32 key_length; }; -extern const u32 crypto_ft_tab[4][256] ____cacheline_aligned; -extern const u32 crypto_it_tab[4][256] ____cacheline_aligned; - /* * validate key length for AES algorithms */ @@ -102,9 +99,6 @@ static inline int aes_check_keylen(size_t keylen) return 0; } -int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len); - /** * aes_expandkey - Expands the AES key as described in FIPS-197 * @ctx: The location where the computed key will be stored. From fa2297750c2cc61788d1843f358dbfecaa42944f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:08 -0800 Subject: [PATCH 27/53] lib/crypto: arm/aes: Migrate optimized code into library Move the ARM optimized single-block AES en/decryption code into lib/crypto/, wire it up to the AES library API, and remove the superseded "aes-arm" crypto_cipher algorithm. The result is that both the AES library and crypto_cipher APIs are now optimized for ARM, whereas previously only crypto_cipher was (and the optimizations weren't enabled by default, which this fixes as well). Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-11-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/arm/configs/milbeaut_m10v_defconfig | 1 - arch/arm/configs/multi_v7_defconfig | 2 +- arch/arm/configs/omap2plus_defconfig | 2 +- arch/arm/configs/pxa_defconfig | 2 +- arch/arm/crypto/Kconfig | 18 ----- arch/arm/crypto/Makefile | 2 - arch/arm/crypto/aes-cipher-glue.c | 77 ------------------- arch/arm/crypto/aes-cipher.h | 13 ---- lib/crypto/Kconfig | 1 + lib/crypto/Makefile | 3 + .../crypto/arm}/aes-cipher-core.S | 0 lib/crypto/arm/aes.h | 56 ++++++++++++++ 12 files changed, 63 insertions(+), 114 deletions(-) delete mode 100644 arch/arm/crypto/aes-cipher-glue.c delete mode 100644 arch/arm/crypto/aes-cipher.h rename {arch/arm/crypto => lib/crypto/arm}/aes-cipher-core.S (100%) create mode 100644 lib/crypto/arm/aes.h diff --git a/arch/arm/configs/milbeaut_m10v_defconfig b/arch/arm/configs/milbeaut_m10v_defconfig index a2995eb390c6..77b69d672d40 100644 --- a/arch/arm/configs/milbeaut_m10v_defconfig +++ b/arch/arm/configs/milbeaut_m10v_defconfig @@ -98,7 +98,6 @@ CONFIG_CRYPTO_SELFTESTS=y CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_SEQIV=m CONFIG_CRYPTO_GHASH_ARM_CE=m -CONFIG_CRYPTO_AES_ARM=m CONFIG_CRYPTO_AES_ARM_BS=m CONFIG_CRYPTO_AES_ARM_CE=m # CONFIG_CRYPTO_HW is not set diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 7f1fa9dd88c9..b6d3e20926bb 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -1286,7 +1286,7 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_CRYPTO_GHASH_ARM_CE=m -CONFIG_CRYPTO_AES_ARM=m +CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_AES_ARM_BS=m CONFIG_CRYPTO_AES_ARM_CE=m CONFIG_CRYPTO_DEV_SUN4I_SS=m diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 4e53c331cd84..0464f6552169 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -706,7 +706,7 @@ CONFIG_NLS_ISO8859_1=y CONFIG_SECURITY=y CONFIG_CRYPTO_MICHAEL_MIC=y CONFIG_CRYPTO_GHASH_ARM_CE=m -CONFIG_CRYPTO_AES_ARM=m +CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_AES_ARM_BS=m CONFIG_CRYPTO_DEV_OMAP=m CONFIG_CRYPTO_DEV_OMAP_SHAM=m diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig index 3ea189f1f42f..eacd08fd87ad 100644 --- a/arch/arm/configs/pxa_defconfig +++ b/arch/arm/configs/pxa_defconfig @@ -657,7 +657,7 @@ CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_AES_ARM=m +CONFIG_CRYPTO_AES=m CONFIG_FONTS=y CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig index 167a648a9def..b9c28c818b7c 100644 --- a/arch/arm/crypto/Kconfig +++ b/arch/arm/crypto/Kconfig @@ -23,24 +23,6 @@ config CRYPTO_GHASH_ARM_CE that is part of the ARMv8 Crypto Extensions, or a slower variant that uses the vmull.p8 instruction that is part of the basic NEON ISA. -config CRYPTO_AES_ARM - tristate "Ciphers: AES" - select CRYPTO_ALGAPI - select CRYPTO_AES - help - Block ciphers: AES cipher algorithms (FIPS-197) - - Architecture: arm - - On ARM processors without the Crypto Extensions, this is the - fastest AES implementation for single blocks. For multiple - blocks, the NEON bit-sliced implementation is usually faster. - - This implementation may be vulnerable to cache timing attacks, - since it uses lookup tables. However, as countermeasures it - disables IRQs and preloads the tables; it is hoped this makes - such attacks very difficult. - config CRYPTO_AES_ARM_BS tristate "Ciphers: AES, modes: ECB/CBC/CTR/XTS (bit-sliced NEON)" depends on KERNEL_MODE_NEON diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile index d6683e9d4992..e73099e120b3 100644 --- a/arch/arm/crypto/Makefile +++ b/arch/arm/crypto/Makefile @@ -3,13 +3,11 @@ # Arch-specific CryptoAPI modules. # -obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o -aes-arm-y := aes-cipher-core.o aes-cipher-glue.o aes-arm-bs-y := aes-neonbs-core.o aes-neonbs-glue.o aes-arm-ce-y := aes-ce-core.o aes-ce-glue.o ghash-arm-ce-y := ghash-ce-core.o ghash-ce-glue.o diff --git a/arch/arm/crypto/aes-cipher-glue.c b/arch/arm/crypto/aes-cipher-glue.c deleted file mode 100644 index f302db808cd3..000000000000 --- a/arch/arm/crypto/aes-cipher-glue.c +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Scalar AES core transform - * - * Copyright (C) 2017 Linaro Ltd. - * Author: Ard Biesheuvel - */ - -#include -#include -#include -#include "aes-cipher.h" - -EXPORT_SYMBOL_GPL(__aes_arm_encrypt); -EXPORT_SYMBOL_GPL(__aes_arm_decrypt); - -static int aes_arm_setkey(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) -{ - struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - return aes_expandkey(ctx, in_key, key_len); -} - -static void aes_arm_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -{ - struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - int rounds = 6 + ctx->key_length / 4; - - __aes_arm_encrypt(ctx->key_enc, rounds, in, out); -} - -static void aes_arm_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -{ - struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - int rounds = 6 + ctx->key_length / 4; - - __aes_arm_decrypt(ctx->key_dec, rounds, in, out); -} - -static struct crypto_alg aes_alg = { - .cra_name = "aes", - .cra_driver_name = "aes-arm", - .cra_priority = 200, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_aes_ctx), - .cra_module = THIS_MODULE, - - .cra_cipher.cia_min_keysize = AES_MIN_KEY_SIZE, - .cra_cipher.cia_max_keysize = AES_MAX_KEY_SIZE, - .cra_cipher.cia_setkey = aes_arm_setkey, - .cra_cipher.cia_encrypt = aes_arm_encrypt, - .cra_cipher.cia_decrypt = aes_arm_decrypt, - -#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS - .cra_alignmask = 3, -#endif -}; - -static int __init aes_init(void) -{ - return crypto_register_alg(&aes_alg); -} - -static void __exit aes_fini(void) -{ - crypto_unregister_alg(&aes_alg); -} - -module_init(aes_init); -module_exit(aes_fini); - -MODULE_DESCRIPTION("Scalar AES cipher for ARM"); -MODULE_AUTHOR("Ard Biesheuvel "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS_CRYPTO("aes"); diff --git a/arch/arm/crypto/aes-cipher.h b/arch/arm/crypto/aes-cipher.h deleted file mode 100644 index d5db2b87eb69..000000000000 --- a/arch/arm/crypto/aes-cipher.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef ARM_CRYPTO_AES_CIPHER_H -#define ARM_CRYPTO_AES_CIPHER_H - -#include -#include - -asmlinkage void __aes_arm_encrypt(const u32 rk[], int rounds, - const u8 *in, u8 *out); -asmlinkage void __aes_arm_decrypt(const u32 rk[], int rounds, - const u8 *in, u8 *out); - -#endif /* ARM_CRYPTO_AES_CIPHER_H */ diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 4efad77daa24..60420b421e04 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -14,6 +14,7 @@ config CRYPTO_LIB_AES config CRYPTO_LIB_AES_ARCH bool depends on CRYPTO_LIB_AES && !UML && !KMSAN + default y if ARM config CRYPTO_LIB_AESCFB tristate diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 01193b3f47ba..2f6b0f59eb1b 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -21,6 +21,9 @@ obj-$(CONFIG_CRYPTO_LIB_AES) += libaes.o libaes-y := aes.o ifeq ($(CONFIG_CRYPTO_LIB_AES_ARCH),y) CFLAGS_aes.o += -I$(src)/$(SRCARCH) + +libaes-$(CONFIG_ARM) += arm/aes-cipher-core.o + endif # CONFIG_CRYPTO_LIB_AES_ARCH ################################################################################ diff --git a/arch/arm/crypto/aes-cipher-core.S b/lib/crypto/arm/aes-cipher-core.S similarity index 100% rename from arch/arm/crypto/aes-cipher-core.S rename to lib/crypto/arm/aes-cipher-core.S diff --git a/lib/crypto/arm/aes.h b/lib/crypto/arm/aes.h new file mode 100644 index 000000000000..1dd7dfa657bb --- /dev/null +++ b/lib/crypto/arm/aes.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * AES block cipher, optimized for ARM + * + * Copyright (C) 2017 Linaro Ltd. + * Copyright 2026 Google LLC + */ + +asmlinkage void __aes_arm_encrypt(const u32 rk[], int rounds, + const u8 in[AES_BLOCK_SIZE], + u8 out[AES_BLOCK_SIZE]); +asmlinkage void __aes_arm_decrypt(const u32 inv_rk[], int rounds, + const u8 in[AES_BLOCK_SIZE], + u8 out[AES_BLOCK_SIZE]); + +static void aes_preparekey_arch(union aes_enckey_arch *k, + union aes_invkey_arch *inv_k, + const u8 *in_key, int key_len, int nrounds) +{ + aes_expandkey_generic(k->rndkeys, inv_k ? inv_k->inv_rndkeys : NULL, + in_key, key_len); +} + +static void aes_encrypt_arch(const struct aes_enckey *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && + !IS_ALIGNED((uintptr_t)out | (uintptr_t)in, 4)) { + u8 bounce_buf[AES_BLOCK_SIZE] __aligned(4); + + memcpy(bounce_buf, in, AES_BLOCK_SIZE); + __aes_arm_encrypt(key->k.rndkeys, key->nrounds, bounce_buf, + bounce_buf); + memcpy(out, bounce_buf, AES_BLOCK_SIZE); + return; + } + __aes_arm_encrypt(key->k.rndkeys, key->nrounds, in, out); +} + +static void aes_decrypt_arch(const struct aes_key *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && + !IS_ALIGNED((uintptr_t)out | (uintptr_t)in, 4)) { + u8 bounce_buf[AES_BLOCK_SIZE] __aligned(4); + + memcpy(bounce_buf, in, AES_BLOCK_SIZE); + __aes_arm_decrypt(key->inv_k.inv_rndkeys, key->nrounds, + bounce_buf, bounce_buf); + memcpy(out, bounce_buf, AES_BLOCK_SIZE); + return; + } + __aes_arm_decrypt(key->inv_k.inv_rndkeys, key->nrounds, in, out); +} From 2b1ef7aeeb184ee78523f3d24e221296574c6f2d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:09 -0800 Subject: [PATCH 28/53] lib/crypto: arm64/aes: Migrate optimized code into library Move the ARM64 optimized AES key expansion and single-block AES en/decryption code into lib/crypto/, wire it up to the AES library API, and remove the superseded crypto_cipher algorithms. The result is that both the AES library and crypto_cipher APIs are now optimized for ARM64, whereas previously only crypto_cipher was (and the optimizations weren't enabled by default, which this fixes as well). Note: to see the diff from arch/arm64/crypto/aes-ce-glue.c to lib/crypto/arm64/aes.h, view this commit with 'git show -M10'. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-12-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/arm64/crypto/Kconfig | 26 +-- arch/arm64/crypto/Makefile | 6 - arch/arm64/crypto/aes-ce-ccm-glue.c | 2 - arch/arm64/crypto/aes-ce-glue.c | 178 ------------------ arch/arm64/crypto/aes-ce-setkey.h | 6 - arch/arm64/crypto/aes-cipher-glue.c | 71 ------- arch/arm64/crypto/aes-glue.c | 2 - include/crypto/aes.h | 10 + lib/crypto/Kconfig | 1 + lib/crypto/Makefile | 5 + .../crypto => lib/crypto/arm64}/aes-ce-core.S | 0 .../crypto/arm64}/aes-cipher-core.S | 0 lib/crypto/arm64/aes.h | 164 ++++++++++++++++ 13 files changed, 181 insertions(+), 290 deletions(-) delete mode 100644 arch/arm64/crypto/aes-ce-glue.c delete mode 100644 arch/arm64/crypto/aes-ce-setkey.h delete mode 100644 arch/arm64/crypto/aes-cipher-glue.c rename {arch/arm64/crypto => lib/crypto/arm64}/aes-ce-core.S (100%) rename {arch/arm64/crypto => lib/crypto/arm64}/aes-cipher-core.S (100%) create mode 100644 lib/crypto/arm64/aes.h diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig index 4453dff8f0c1..81ed892b3b72 100644 --- a/arch/arm64/crypto/Kconfig +++ b/arch/arm64/crypto/Kconfig @@ -37,34 +37,11 @@ config CRYPTO_SM3_ARM64_CE Architecture: arm64 using: - ARMv8.2 Crypto Extensions -config CRYPTO_AES_ARM64 - tristate "Ciphers: AES, modes: ECB, CBC, CTR, CTS, XCTR, XTS" - select CRYPTO_AES - help - Block ciphers: AES cipher algorithms (FIPS-197) - Length-preserving ciphers: AES with ECB, CBC, CTR, CTS, - XCTR, and XTS modes - AEAD cipher: AES with CBC, ESSIV, and SHA-256 - for fscrypt and dm-crypt - - Architecture: arm64 - -config CRYPTO_AES_ARM64_CE - tristate "Ciphers: AES (ARMv8 Crypto Extensions)" - depends on KERNEL_MODE_NEON - select CRYPTO_ALGAPI - select CRYPTO_LIB_AES - help - Block ciphers: AES cipher algorithms (FIPS-197) - - Architecture: arm64 using: - - ARMv8 Crypto Extensions - config CRYPTO_AES_ARM64_CE_BLK tristate "Ciphers: AES, modes: ECB/CBC/CTR/XTS (ARMv8 Crypto Extensions)" depends on KERNEL_MODE_NEON select CRYPTO_SKCIPHER - select CRYPTO_AES_ARM64_CE + select CRYPTO_LIB_AES select CRYPTO_LIB_SHA256 help Length-preserving ciphers: AES cipher algorithms (FIPS-197) @@ -165,7 +142,6 @@ config CRYPTO_AES_ARM64_CE_CCM tristate "AEAD cipher: AES in CCM mode (ARMv8 Crypto Extensions)" depends on KERNEL_MODE_NEON select CRYPTO_ALGAPI - select CRYPTO_AES_ARM64_CE select CRYPTO_AES_ARM64_CE_BLK select CRYPTO_AEAD select CRYPTO_LIB_AES diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile index 3ab4b58e5c4c..3574e917bc37 100644 --- a/arch/arm64/crypto/Makefile +++ b/arch/arm64/crypto/Makefile @@ -29,9 +29,6 @@ sm4-neon-y := sm4-neon-glue.o sm4-neon-core.o obj-$(CONFIG_CRYPTO_GHASH_ARM64_CE) += ghash-ce.o ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o -obj-$(CONFIG_CRYPTO_AES_ARM64_CE) += aes-ce-cipher.o -aes-ce-cipher-y := aes-ce-core.o aes-ce-glue.o - obj-$(CONFIG_CRYPTO_AES_ARM64_CE_CCM) += aes-ce-ccm.o aes-ce-ccm-y := aes-ce-ccm-glue.o aes-ce-ccm-core.o @@ -41,8 +38,5 @@ aes-ce-blk-y := aes-glue-ce.o aes-ce.o obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) += aes-neon-blk.o aes-neon-blk-y := aes-glue-neon.o aes-neon.o -obj-$(CONFIG_CRYPTO_AES_ARM64) += aes-arm64.o -aes-arm64-y := aes-cipher-core.o aes-cipher-glue.o - obj-$(CONFIG_CRYPTO_AES_ARM64_BS) += aes-neon-bs.o aes-neon-bs-y := aes-neonbs-core.o aes-neonbs-glue.o diff --git a/arch/arm64/crypto/aes-ce-ccm-glue.c b/arch/arm64/crypto/aes-ce-ccm-glue.c index c4fd648471f1..db371ac051fc 100644 --- a/arch/arm64/crypto/aes-ce-ccm-glue.c +++ b/arch/arm64/crypto/aes-ce-ccm-glue.c @@ -17,8 +17,6 @@ #include -#include "aes-ce-setkey.h" - MODULE_IMPORT_NS("CRYPTO_INTERNAL"); static int num_rounds(struct crypto_aes_ctx *ctx) diff --git a/arch/arm64/crypto/aes-ce-glue.c b/arch/arm64/crypto/aes-ce-glue.c deleted file mode 100644 index a4dad370991d..000000000000 --- a/arch/arm64/crypto/aes-ce-glue.c +++ /dev/null @@ -1,178 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * aes-ce-cipher.c - core AES cipher using ARMv8 Crypto Extensions - * - * Copyright (C) 2013 - 2017 Linaro Ltd - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "aes-ce-setkey.h" - -MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions"); -MODULE_AUTHOR("Ard Biesheuvel "); -MODULE_LICENSE("GPL v2"); - -struct aes_block { - u8 b[AES_BLOCK_SIZE]; -}; - -asmlinkage void __aes_ce_encrypt(u32 *rk, u8 *out, const u8 *in, int rounds); -asmlinkage void __aes_ce_decrypt(u32 *rk, u8 *out, const u8 *in, int rounds); - -asmlinkage u32 __aes_ce_sub(u32 l); -asmlinkage void __aes_ce_invert(struct aes_block *out, - const struct aes_block *in); - -static int num_rounds(struct crypto_aes_ctx *ctx) -{ - /* - * # of rounds specified by AES: - * 128 bit key 10 rounds - * 192 bit key 12 rounds - * 256 bit key 14 rounds - * => n byte key => 6 + (n/4) rounds - */ - return 6 + ctx->key_length / 4; -} - -static void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[]) -{ - struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - if (!crypto_simd_usable()) { - aes_encrypt(ctx, dst, src); - return; - } - - scoped_ksimd() - __aes_ce_encrypt(ctx->key_enc, dst, src, num_rounds(ctx)); -} - -static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[]) -{ - struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - if (!crypto_simd_usable()) { - aes_decrypt(ctx, dst, src); - return; - } - - scoped_ksimd() - __aes_ce_decrypt(ctx->key_dec, dst, src, num_rounds(ctx)); -} - -int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, - unsigned int key_len) -{ - /* - * The AES key schedule round constants - */ - static u8 const rcon[] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, - }; - - u32 kwords = key_len / sizeof(u32); - struct aes_block *key_enc, *key_dec; - int i, j; - - if (key_len != AES_KEYSIZE_128 && - key_len != AES_KEYSIZE_192 && - key_len != AES_KEYSIZE_256) - return -EINVAL; - - ctx->key_length = key_len; - for (i = 0; i < kwords; i++) - ctx->key_enc[i] = get_unaligned_le32(in_key + i * sizeof(u32)); - - scoped_ksimd() { - for (i = 0; i < sizeof(rcon); i++) { - u32 *rki = ctx->key_enc + (i * kwords); - u32 *rko = rki + kwords; - - rko[0] = ror32(__aes_ce_sub(rki[kwords - 1]), 8) ^ - rcon[i] ^ rki[0]; - rko[1] = rko[0] ^ rki[1]; - rko[2] = rko[1] ^ rki[2]; - rko[3] = rko[2] ^ rki[3]; - - if (key_len == AES_KEYSIZE_192) { - if (i >= 7) - break; - rko[4] = rko[3] ^ rki[4]; - rko[5] = rko[4] ^ rki[5]; - } else if (key_len == AES_KEYSIZE_256) { - if (i >= 6) - break; - rko[4] = __aes_ce_sub(rko[3]) ^ rki[4]; - rko[5] = rko[4] ^ rki[5]; - rko[6] = rko[5] ^ rki[6]; - rko[7] = rko[6] ^ rki[7]; - } - } - - /* - * Generate the decryption keys for the Equivalent Inverse - * Cipher. This involves reversing the order of the round - * keys, and applying the Inverse Mix Columns transformation on - * all but the first and the last one. - */ - key_enc = (struct aes_block *)ctx->key_enc; - key_dec = (struct aes_block *)ctx->key_dec; - j = num_rounds(ctx); - - key_dec[0] = key_enc[j]; - for (i = 1, j--; j > 0; i++, j--) - __aes_ce_invert(key_dec + i, key_enc + j); - key_dec[i] = key_enc[0]; - } - - return 0; -} -EXPORT_SYMBOL(ce_aes_expandkey); - -int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) -{ - struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - return ce_aes_expandkey(ctx, in_key, key_len); -} -EXPORT_SYMBOL(ce_aes_setkey); - -static struct crypto_alg aes_alg = { - .cra_name = "aes", - .cra_driver_name = "aes-ce", - .cra_priority = 250, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_aes_ctx), - .cra_module = THIS_MODULE, - .cra_cipher = { - .cia_min_keysize = AES_MIN_KEY_SIZE, - .cia_max_keysize = AES_MAX_KEY_SIZE, - .cia_setkey = ce_aes_setkey, - .cia_encrypt = aes_cipher_encrypt, - .cia_decrypt = aes_cipher_decrypt - } -}; - -static int __init aes_mod_init(void) -{ - return crypto_register_alg(&aes_alg); -} - -static void __exit aes_mod_exit(void) -{ - crypto_unregister_alg(&aes_alg); -} - -module_cpu_feature_match(AES, aes_mod_init); -module_exit(aes_mod_exit); diff --git a/arch/arm64/crypto/aes-ce-setkey.h b/arch/arm64/crypto/aes-ce-setkey.h deleted file mode 100644 index fd9ecf07d88c..000000000000 --- a/arch/arm64/crypto/aes-ce-setkey.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len); -int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, - unsigned int key_len); diff --git a/arch/arm64/crypto/aes-cipher-glue.c b/arch/arm64/crypto/aes-cipher-glue.c deleted file mode 100644 index 9b27cbac278b..000000000000 --- a/arch/arm64/crypto/aes-cipher-glue.c +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Scalar AES core transform - * - * Copyright (C) 2017 Linaro Ltd - */ - -#include -#include -#include - -asmlinkage void __aes_arm64_encrypt(u32 *rk, u8 *out, const u8 *in, int rounds); -asmlinkage void __aes_arm64_decrypt(u32 *rk, u8 *out, const u8 *in, int rounds); - -static int aes_arm64_setkey(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) -{ - struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - return aes_expandkey(ctx, in_key, key_len); -} - -static void aes_arm64_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -{ - struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - int rounds = 6 + ctx->key_length / 4; - - __aes_arm64_encrypt(ctx->key_enc, out, in, rounds); -} - -static void aes_arm64_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -{ - struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - int rounds = 6 + ctx->key_length / 4; - - __aes_arm64_decrypt(ctx->key_dec, out, in, rounds); -} - -static struct crypto_alg aes_alg = { - .cra_name = "aes", - .cra_driver_name = "aes-arm64", - .cra_priority = 200, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_aes_ctx), - .cra_module = THIS_MODULE, - - .cra_cipher.cia_min_keysize = AES_MIN_KEY_SIZE, - .cra_cipher.cia_max_keysize = AES_MAX_KEY_SIZE, - .cra_cipher.cia_setkey = aes_arm64_setkey, - .cra_cipher.cia_encrypt = aes_arm64_encrypt, - .cra_cipher.cia_decrypt = aes_arm64_decrypt -}; - -static int __init aes_init(void) -{ - return crypto_register_alg(&aes_alg); -} - -static void __exit aes_fini(void) -{ - crypto_unregister_alg(&aes_alg); -} - -module_init(aes_init); -module_exit(aes_fini); - -MODULE_DESCRIPTION("Scalar AES cipher for arm64"); -MODULE_AUTHOR("Ard Biesheuvel "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS_CRYPTO("aes"); diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c index c51d4487e9e9..92f43e1cd097 100644 --- a/arch/arm64/crypto/aes-glue.c +++ b/arch/arm64/crypto/aes-glue.c @@ -21,8 +21,6 @@ #include #include -#include "aes-ce-setkey.h" - #ifdef USE_V8_CRYPTO_EXTENSIONS #define MODE "ce" #define PRIO 300 diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 66421795cdab..18af1acbde58 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -116,6 +116,16 @@ static inline int aes_check_keylen(size_t keylen) int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, unsigned int key_len); +/* + * The following functions are temporarily exported for use by the AES mode + * implementations in arch/$(SRCARCH)/crypto/. These exports will go away when + * that code is migrated into lib/crypto/. + */ +#ifdef CONFIG_ARM64 +int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, + unsigned int key_len); +#endif + /** * aes_preparekey() - Prepare an AES key for encryption and decryption * @key: (output) The key structure to initialize diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 60420b421e04..ead47b2a7db6 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -15,6 +15,7 @@ config CRYPTO_LIB_AES_ARCH bool depends on CRYPTO_LIB_AES && !UML && !KMSAN default y if ARM + default y if ARM64 config CRYPTO_LIB_AESCFB tristate diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 2f6b0f59eb1b..1b690c63fafb 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -24,6 +24,11 @@ CFLAGS_aes.o += -I$(src)/$(SRCARCH) libaes-$(CONFIG_ARM) += arm/aes-cipher-core.o +ifeq ($(CONFIG_ARM64),y) +libaes-y += arm64/aes-cipher-core.o +libaes-$(CONFIG_KERNEL_MODE_NEON) += arm64/aes-ce-core.o +endif + endif # CONFIG_CRYPTO_LIB_AES_ARCH ################################################################################ diff --git a/arch/arm64/crypto/aes-ce-core.S b/lib/crypto/arm64/aes-ce-core.S similarity index 100% rename from arch/arm64/crypto/aes-ce-core.S rename to lib/crypto/arm64/aes-ce-core.S diff --git a/arch/arm64/crypto/aes-cipher-core.S b/lib/crypto/arm64/aes-cipher-core.S similarity index 100% rename from arch/arm64/crypto/aes-cipher-core.S rename to lib/crypto/arm64/aes-cipher-core.S diff --git a/lib/crypto/arm64/aes.h b/lib/crypto/arm64/aes.h new file mode 100644 index 000000000000..63eea6271ef9 --- /dev/null +++ b/lib/crypto/arm64/aes.h @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * AES block cipher, optimized for ARM64 + * + * Copyright (C) 2013 - 2017 Linaro Ltd + * Copyright 2026 Google LLC + */ + +#include +#include +#include +#include + +static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_aes); + +struct aes_block { + u8 b[AES_BLOCK_SIZE]; +}; + +asmlinkage void __aes_arm64_encrypt(const u32 rk[], u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE], int rounds); +asmlinkage void __aes_arm64_decrypt(const u32 inv_rk[], u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE], int rounds); +asmlinkage void __aes_ce_encrypt(const u32 rk[], u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE], int rounds); +asmlinkage void __aes_ce_decrypt(const u32 inv_rk[], u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE], int rounds); +asmlinkage u32 __aes_ce_sub(u32 l); +asmlinkage void __aes_ce_invert(struct aes_block *out, + const struct aes_block *in); + +/* + * Expand an AES key using the crypto extensions if supported and usable or + * generic code otherwise. The expanded key format is compatible between the + * two cases. The outputs are @rndkeys (required) and @inv_rndkeys (optional). + */ +static void aes_expandkey_arm64(u32 rndkeys[], u32 *inv_rndkeys, + const u8 *in_key, int key_len, int nrounds) +{ + /* + * The AES key schedule round constants + */ + static u8 const rcon[] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, + }; + + u32 kwords = key_len / sizeof(u32); + struct aes_block *key_enc, *key_dec; + int i, j; + + if (!IS_ENABLED(CONFIG_KERNEL_MODE_NEON) || + !static_branch_likely(&have_aes) || unlikely(!may_use_simd())) { + aes_expandkey_generic(rndkeys, inv_rndkeys, in_key, key_len); + return; + } + + for (i = 0; i < kwords; i++) + rndkeys[i] = get_unaligned_le32(&in_key[i * sizeof(u32)]); + + scoped_ksimd() { + for (i = 0; i < sizeof(rcon); i++) { + u32 *rki = &rndkeys[i * kwords]; + u32 *rko = rki + kwords; + + rko[0] = ror32(__aes_ce_sub(rki[kwords - 1]), 8) ^ + rcon[i] ^ rki[0]; + rko[1] = rko[0] ^ rki[1]; + rko[2] = rko[1] ^ rki[2]; + rko[3] = rko[2] ^ rki[3]; + + if (key_len == AES_KEYSIZE_192) { + if (i >= 7) + break; + rko[4] = rko[3] ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + } else if (key_len == AES_KEYSIZE_256) { + if (i >= 6) + break; + rko[4] = __aes_ce_sub(rko[3]) ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + rko[6] = rko[5] ^ rki[6]; + rko[7] = rko[6] ^ rki[7]; + } + } + + /* + * Generate the decryption keys for the Equivalent Inverse + * Cipher. This involves reversing the order of the round + * keys, and applying the Inverse Mix Columns transformation on + * all but the first and the last one. + */ + if (inv_rndkeys) { + key_enc = (struct aes_block *)rndkeys; + key_dec = (struct aes_block *)inv_rndkeys; + j = nrounds; + + key_dec[0] = key_enc[j]; + for (i = 1, j--; j > 0; i++, j--) + __aes_ce_invert(key_dec + i, key_enc + j); + key_dec[i] = key_enc[0]; + } + } +} + +static void aes_preparekey_arch(union aes_enckey_arch *k, + union aes_invkey_arch *inv_k, + const u8 *in_key, int key_len, int nrounds) +{ + aes_expandkey_arm64(k->rndkeys, inv_k ? inv_k->inv_rndkeys : NULL, + in_key, key_len, nrounds); +} + +/* + * This is here temporarily until the remaining AES mode implementations are + * migrated from arch/arm64/crypto/ to lib/crypto/arm64/. + */ +int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, + unsigned int key_len) +{ + if (aes_check_keylen(key_len) != 0) + return -EINVAL; + ctx->key_length = key_len; + aes_expandkey_arm64(ctx->key_enc, ctx->key_dec, in_key, key_len, + 6 + key_len / 4); + return 0; +} +EXPORT_SYMBOL(ce_aes_expandkey); + +static void aes_encrypt_arch(const struct aes_enckey *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && + static_branch_likely(&have_aes) && likely(may_use_simd())) { + scoped_ksimd() + __aes_ce_encrypt(key->k.rndkeys, out, in, key->nrounds); + } else { + __aes_arm64_encrypt(key->k.rndkeys, out, in, key->nrounds); + } +} + +static void aes_decrypt_arch(const struct aes_key *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && + static_branch_likely(&have_aes) && likely(may_use_simd())) { + scoped_ksimd() + __aes_ce_decrypt(key->inv_k.inv_rndkeys, out, in, + key->nrounds); + } else { + __aes_arm64_decrypt(key->inv_k.inv_rndkeys, out, in, + key->nrounds); + } +} + +#ifdef CONFIG_KERNEL_MODE_NEON +#define aes_mod_init_arch aes_mod_init_arch +static void aes_mod_init_arch(void) +{ + if (cpu_have_named_feature(AES)) + static_branch_enable(&have_aes); +} +#endif /* CONFIG_KERNEL_MODE_NEON */ From 0892c91b81cc889c95dc03b095b9f4a6fdf93106 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:10 -0800 Subject: [PATCH 29/53] lib/crypto: powerpc/aes: Migrate SPE optimized code into library Move the PowerPC SPE AES assembly code into lib/crypto/, wire the key expansion and single-block en/decryption functions up to the AES library API, and remove the superseded "aes-ppc-spe" crypto_cipher algorithm. The result is that both the AES library and crypto_cipher APIs are now optimized with SPE, whereas previously only crypto_cipher was (and optimizations weren't enabled by default, which this commit fixes too). Note that many of the functions in the PowerPC SPE assembly code are still used by the AES mode implementations in arch/powerpc/crypto/. For now, just export these functions. These exports will go away once the AES modes are migrated to the library as well. (Trying to split up the assembly files seemed like much more trouble than it would be worth.) Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-13-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/powerpc/crypto/Kconfig | 2 +- arch/powerpc/crypto/Makefile | 2 +- arch/powerpc/crypto/aes-spe-glue.c | 88 ++----------------- include/crypto/aes.h | 31 +++++++ lib/crypto/Kconfig | 1 + lib/crypto/Makefile | 9 ++ .../crypto/powerpc}/aes-spe-core.S | 0 .../crypto/powerpc}/aes-spe-keys.S | 0 .../crypto/powerpc}/aes-spe-modes.S | 0 .../crypto/powerpc}/aes-spe-regs.h | 0 .../crypto/powerpc}/aes-tab-4k.S | 0 lib/crypto/powerpc/aes.h | 74 ++++++++++++++++ 12 files changed, 122 insertions(+), 85 deletions(-) rename {arch/powerpc/crypto => lib/crypto/powerpc}/aes-spe-core.S (100%) rename {arch/powerpc/crypto => lib/crypto/powerpc}/aes-spe-keys.S (100%) rename {arch/powerpc/crypto => lib/crypto/powerpc}/aes-spe-modes.S (100%) rename {arch/powerpc/crypto => lib/crypto/powerpc}/aes-spe-regs.h (100%) rename {arch/powerpc/crypto => lib/crypto/powerpc}/aes-tab-4k.S (100%) create mode 100644 lib/crypto/powerpc/aes.h diff --git a/arch/powerpc/crypto/Kconfig b/arch/powerpc/crypto/Kconfig index 662aed46f9c7..2d056f1fc90f 100644 --- a/arch/powerpc/crypto/Kconfig +++ b/arch/powerpc/crypto/Kconfig @@ -5,9 +5,9 @@ menu "Accelerated Cryptographic Algorithms for CPU (powerpc)" config CRYPTO_AES_PPC_SPE tristate "Ciphers: AES, modes: ECB/CBC/CTR/XTS (SPE)" depends on SPE + select CRYPTO_LIB_AES select CRYPTO_SKCIPHER help - Block ciphers: AES cipher algorithms (FIPS-197) Length-preserving ciphers: AES with ECB, CBC, CTR, and XTS modes Architecture: powerpc using: diff --git a/arch/powerpc/crypto/Makefile b/arch/powerpc/crypto/Makefile index 5960e5300db7..e22310da86b5 100644 --- a/arch/powerpc/crypto/Makefile +++ b/arch/powerpc/crypto/Makefile @@ -9,7 +9,7 @@ obj-$(CONFIG_CRYPTO_AES_PPC_SPE) += aes-ppc-spe.o obj-$(CONFIG_CRYPTO_AES_GCM_P10) += aes-gcm-p10-crypto.o obj-$(CONFIG_CRYPTO_DEV_VMX_ENCRYPT) += vmx-crypto.o -aes-ppc-spe-y := aes-spe-core.o aes-spe-keys.o aes-tab-4k.o aes-spe-modes.o aes-spe-glue.o +aes-ppc-spe-y := aes-spe-glue.o aes-gcm-p10-crypto-y := aes-gcm-p10-glue.o aes-gcm-p10.o ghashp10-ppc.o aesp10-ppc.o vmx-crypto-objs := vmx.o aesp8-ppc.o ghashp8-ppc.o aes.o aes_cbc.o aes_ctr.o aes_xts.o ghash.o diff --git a/arch/powerpc/crypto/aes-spe-glue.c b/arch/powerpc/crypto/aes-spe-glue.c index efab78a3a8f6..7d2827e65240 100644 --- a/arch/powerpc/crypto/aes-spe-glue.c +++ b/arch/powerpc/crypto/aes-spe-glue.c @@ -51,30 +51,6 @@ struct ppc_xts_ctx { u32 rounds; }; -extern void ppc_encrypt_aes(u8 *out, const u8 *in, u32 *key_enc, u32 rounds); -extern void ppc_decrypt_aes(u8 *out, const u8 *in, u32 *key_dec, u32 rounds); -extern void ppc_encrypt_ecb(u8 *out, const u8 *in, u32 *key_enc, u32 rounds, - u32 bytes); -extern void ppc_decrypt_ecb(u8 *out, const u8 *in, u32 *key_dec, u32 rounds, - u32 bytes); -extern void ppc_encrypt_cbc(u8 *out, const u8 *in, u32 *key_enc, u32 rounds, - u32 bytes, u8 *iv); -extern void ppc_decrypt_cbc(u8 *out, const u8 *in, u32 *key_dec, u32 rounds, - u32 bytes, u8 *iv); -extern void ppc_crypt_ctr (u8 *out, const u8 *in, u32 *key_enc, u32 rounds, - u32 bytes, u8 *iv); -extern void ppc_encrypt_xts(u8 *out, const u8 *in, u32 *key_enc, u32 rounds, - u32 bytes, u8 *iv, u32 *key_twk); -extern void ppc_decrypt_xts(u8 *out, const u8 *in, u32 *key_dec, u32 rounds, - u32 bytes, u8 *iv, u32 *key_twk); - -extern void ppc_expand_key_128(u32 *key_enc, const u8 *key); -extern void ppc_expand_key_192(u32 *key_enc, const u8 *key); -extern void ppc_expand_key_256(u32 *key_enc, const u8 *key); - -extern void ppc_generate_decrypt_key(u32 *key_dec,u32 *key_enc, - unsigned int key_len); - static void spe_begin(void) { /* disable preemption and save users SPE registers if required */ @@ -89,10 +65,10 @@ static void spe_end(void) preempt_enable(); } -static int ppc_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) +static int ppc_aes_setkey_skcipher(struct crypto_skcipher *tfm, + const u8 *in_key, unsigned int key_len) { - struct ppc_aes_ctx *ctx = crypto_tfm_ctx(tfm); + struct ppc_aes_ctx *ctx = crypto_skcipher_ctx(tfm); switch (key_len) { case AES_KEYSIZE_128: @@ -116,12 +92,6 @@ static int ppc_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key, return 0; } -static int ppc_aes_setkey_skcipher(struct crypto_skcipher *tfm, - const u8 *in_key, unsigned int key_len) -{ - return ppc_aes_setkey(crypto_skcipher_tfm(tfm), in_key, key_len); -} - static int ppc_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { @@ -159,24 +129,6 @@ static int ppc_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key, return 0; } -static void ppc_aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -{ - struct ppc_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - spe_begin(); - ppc_encrypt_aes(out, in, ctx->key_enc, ctx->rounds); - spe_end(); -} - -static void ppc_aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -{ - struct ppc_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - spe_begin(); - ppc_decrypt_aes(out, in, ctx->key_dec, ctx->rounds); - spe_end(); -} - static int ppc_ecb_crypt(struct skcipher_request *req, bool enc) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); @@ -410,26 +362,6 @@ static int ppc_xts_decrypt(struct skcipher_request *req) * with kmalloc() in the crypto infrastructure */ -static struct crypto_alg aes_cipher_alg = { - .cra_name = "aes", - .cra_driver_name = "aes-ppc-spe", - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct ppc_aes_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - .cra_u = { - .cipher = { - .cia_min_keysize = AES_MIN_KEY_SIZE, - .cia_max_keysize = AES_MAX_KEY_SIZE, - .cia_setkey = ppc_aes_setkey, - .cia_encrypt = ppc_aes_encrypt, - .cia_decrypt = ppc_aes_decrypt - } - } -}; - static struct skcipher_alg aes_skcipher_algs[] = { { .base.cra_name = "ecb(aes)", @@ -488,22 +420,12 @@ static struct skcipher_alg aes_skcipher_algs[] = { static int __init ppc_aes_mod_init(void) { - int err; - - err = crypto_register_alg(&aes_cipher_alg); - if (err) - return err; - - err = crypto_register_skciphers(aes_skcipher_algs, - ARRAY_SIZE(aes_skcipher_algs)); - if (err) - crypto_unregister_alg(&aes_cipher_alg); - return err; + return crypto_register_skciphers(aes_skcipher_algs, + ARRAY_SIZE(aes_skcipher_algs)); } static void __exit ppc_aes_mod_fini(void) { - crypto_unregister_alg(&aes_cipher_alg); crypto_unregister_skciphers(aes_skcipher_algs, ARRAY_SIZE(aes_skcipher_algs)); } diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 18af1acbde58..c893c9214cb7 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -20,10 +20,22 @@ union aes_enckey_arch { u32 rndkeys[AES_MAX_KEYLENGTH_U32]; +#ifdef CONFIG_CRYPTO_LIB_AES_ARCH +#if defined(CONFIG_PPC) && defined(CONFIG_SPE) + /* Used unconditionally (when SPE AES code is enabled in kconfig) */ + u32 spe_enc_key[AES_MAX_KEYLENGTH_U32] __aligned(8); +#endif +#endif /* CONFIG_CRYPTO_LIB_AES_ARCH */ }; union aes_invkey_arch { u32 inv_rndkeys[AES_MAX_KEYLENGTH_U32]; +#ifdef CONFIG_CRYPTO_LIB_AES_ARCH +#if defined(CONFIG_PPC) && defined(CONFIG_SPE) + /* Used unconditionally (when SPE AES code is enabled in kconfig) */ + u32 spe_dec_key[AES_MAX_KEYLENGTH_U32] __aligned(8); +#endif +#endif /* CONFIG_CRYPTO_LIB_AES_ARCH */ }; /** @@ -124,6 +136,25 @@ int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, #ifdef CONFIG_ARM64 int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, unsigned int key_len); +#elif defined(CONFIG_PPC) +void ppc_expand_key_128(u32 *key_enc, const u8 *key); +void ppc_expand_key_192(u32 *key_enc, const u8 *key); +void ppc_expand_key_256(u32 *key_enc, const u8 *key); +void ppc_generate_decrypt_key(u32 *key_dec, u32 *key_enc, unsigned int key_len); +void ppc_encrypt_ecb(u8 *out, const u8 *in, u32 *key_enc, u32 rounds, + u32 bytes); +void ppc_decrypt_ecb(u8 *out, const u8 *in, u32 *key_dec, u32 rounds, + u32 bytes); +void ppc_encrypt_cbc(u8 *out, const u8 *in, u32 *key_enc, u32 rounds, u32 bytes, + u8 *iv); +void ppc_decrypt_cbc(u8 *out, const u8 *in, u32 *key_dec, u32 rounds, u32 bytes, + u8 *iv); +void ppc_crypt_ctr(u8 *out, const u8 *in, u32 *key_enc, u32 rounds, u32 bytes, + u8 *iv); +void ppc_encrypt_xts(u8 *out, const u8 *in, u32 *key_enc, u32 rounds, u32 bytes, + u8 *iv, u32 *key_twk); +void ppc_decrypt_xts(u8 *out, const u8 *in, u32 *key_dec, u32 rounds, u32 bytes, + u8 *iv, u32 *key_twk); #endif /** diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index ead47b2a7db6..cfc6171203d0 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -16,6 +16,7 @@ config CRYPTO_LIB_AES_ARCH depends on CRYPTO_LIB_AES && !UML && !KMSAN default y if ARM default y if ARM64 + default y if PPC && SPE config CRYPTO_LIB_AESCFB tristate diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 1b690c63fafb..d68fde004104 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -29,6 +29,15 @@ libaes-y += arm64/aes-cipher-core.o libaes-$(CONFIG_KERNEL_MODE_NEON) += arm64/aes-ce-core.o endif +ifeq ($(CONFIG_PPC),y) +ifeq ($(CONFIG_SPE),y) +libaes-y += powerpc/aes-spe-core.o \ + powerpc/aes-spe-keys.o \ + powerpc/aes-spe-modes.o \ + powerpc/aes-tab-4k.o +endif +endif # CONFIG_PPC + endif # CONFIG_CRYPTO_LIB_AES_ARCH ################################################################################ diff --git a/arch/powerpc/crypto/aes-spe-core.S b/lib/crypto/powerpc/aes-spe-core.S similarity index 100% rename from arch/powerpc/crypto/aes-spe-core.S rename to lib/crypto/powerpc/aes-spe-core.S diff --git a/arch/powerpc/crypto/aes-spe-keys.S b/lib/crypto/powerpc/aes-spe-keys.S similarity index 100% rename from arch/powerpc/crypto/aes-spe-keys.S rename to lib/crypto/powerpc/aes-spe-keys.S diff --git a/arch/powerpc/crypto/aes-spe-modes.S b/lib/crypto/powerpc/aes-spe-modes.S similarity index 100% rename from arch/powerpc/crypto/aes-spe-modes.S rename to lib/crypto/powerpc/aes-spe-modes.S diff --git a/arch/powerpc/crypto/aes-spe-regs.h b/lib/crypto/powerpc/aes-spe-regs.h similarity index 100% rename from arch/powerpc/crypto/aes-spe-regs.h rename to lib/crypto/powerpc/aes-spe-regs.h diff --git a/arch/powerpc/crypto/aes-tab-4k.S b/lib/crypto/powerpc/aes-tab-4k.S similarity index 100% rename from arch/powerpc/crypto/aes-tab-4k.S rename to lib/crypto/powerpc/aes-tab-4k.S diff --git a/lib/crypto/powerpc/aes.h b/lib/crypto/powerpc/aes.h new file mode 100644 index 000000000000..cf22020f9050 --- /dev/null +++ b/lib/crypto/powerpc/aes.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2015 Markus Stockhausen + * Copyright 2026 Google LLC + */ +#include +#include +#include +#include +#include +#include + +EXPORT_SYMBOL_GPL(ppc_expand_key_128); +EXPORT_SYMBOL_GPL(ppc_expand_key_192); +EXPORT_SYMBOL_GPL(ppc_expand_key_256); +EXPORT_SYMBOL_GPL(ppc_generate_decrypt_key); +EXPORT_SYMBOL_GPL(ppc_encrypt_ecb); +EXPORT_SYMBOL_GPL(ppc_decrypt_ecb); +EXPORT_SYMBOL_GPL(ppc_encrypt_cbc); +EXPORT_SYMBOL_GPL(ppc_decrypt_cbc); +EXPORT_SYMBOL_GPL(ppc_crypt_ctr); +EXPORT_SYMBOL_GPL(ppc_encrypt_xts); +EXPORT_SYMBOL_GPL(ppc_decrypt_xts); + +void ppc_encrypt_aes(u8 *out, const u8 *in, const u32 *key_enc, u32 rounds); +void ppc_decrypt_aes(u8 *out, const u8 *in, const u32 *key_dec, u32 rounds); + +static void spe_begin(void) +{ + /* disable preemption and save users SPE registers if required */ + preempt_disable(); + enable_kernel_spe(); +} + +static void spe_end(void) +{ + disable_kernel_spe(); + /* reenable preemption */ + preempt_enable(); +} + +static void aes_preparekey_arch(union aes_enckey_arch *k, + union aes_invkey_arch *inv_k, + const u8 *in_key, int key_len, int nrounds) +{ + if (key_len == AES_KEYSIZE_128) + ppc_expand_key_128(k->spe_enc_key, in_key); + else if (key_len == AES_KEYSIZE_192) + ppc_expand_key_192(k->spe_enc_key, in_key); + else + ppc_expand_key_256(k->spe_enc_key, in_key); + + if (inv_k) + ppc_generate_decrypt_key(inv_k->spe_dec_key, k->spe_enc_key, + key_len); +} + +static void aes_encrypt_arch(const struct aes_enckey *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + spe_begin(); + ppc_encrypt_aes(out, in, key->k.spe_enc_key, key->nrounds / 2 - 1); + spe_end(); +} + +static void aes_decrypt_arch(const struct aes_key *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + spe_begin(); + ppc_decrypt_aes(out, in, key->inv_k.spe_dec_key, key->nrounds / 2 - 1); + spe_end(); +} From 7cf2082e74ce7f4f4b5e14cbe67a194d75e257ef Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:11 -0800 Subject: [PATCH 30/53] lib/crypto: powerpc/aes: Migrate POWER8 optimized code into library Move the POWER8 AES assembly code into lib/crypto/, wire the key expansion and single-block en/decryption functions up to the AES library API, and remove the superseded "p8_aes" crypto_cipher algorithm. The result is that both the AES library and crypto_cipher APIs are now optimized for POWER8, whereas previously only crypto_cipher was (and optimizations weren't enabled by default, which this commit fixes too). Note that many of the functions in the POWER8 assembly code are still used by the AES mode implementations in arch/powerpc/crypto/. For now, just export these functions. These exports will go away once the AES modes are migrated to the library as well. (Trying to split up the assembly file seemed like much more trouble than it would be worth.) Another challenge with this code is that the POWER8 assembly code uses a custom format for the expanded AES key. Since that code is imported from OpenSSL and is also targeted to POWER8 (rather than POWER9 which has better data movement and byteswap instructions), that is not easily changed. For now I've just kept the custom format. To maintain full correctness, this requires executing some slow fallback code in the case where the usability of VSX changes between key expansion and use. This should be tolerable, as this case shouldn't happen in practice. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-14-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/powerpc/crypto/Makefile | 7 +- arch/powerpc/crypto/aes.c | 134 -------------- arch/powerpc/crypto/aesp8-ppc.h | 23 --- arch/powerpc/crypto/vmx.c | 10 +- include/crypto/aes.h | 41 +++++ lib/crypto/Kconfig | 2 +- lib/crypto/Makefile | 14 +- lib/crypto/powerpc/.gitignore | 2 + lib/crypto/powerpc/aes.h | 164 ++++++++++++++++++ .../crypto/powerpc}/aesp8-ppc.pl | 1 + 10 files changed, 226 insertions(+), 172 deletions(-) delete mode 100644 arch/powerpc/crypto/aes.c create mode 100644 lib/crypto/powerpc/.gitignore rename {arch/powerpc/crypto => lib/crypto/powerpc}/aesp8-ppc.pl (99%) diff --git a/arch/powerpc/crypto/Makefile b/arch/powerpc/crypto/Makefile index e22310da86b5..3ac0886282a2 100644 --- a/arch/powerpc/crypto/Makefile +++ b/arch/powerpc/crypto/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_CRYPTO_DEV_VMX_ENCRYPT) += vmx-crypto.o aes-ppc-spe-y := aes-spe-glue.o aes-gcm-p10-crypto-y := aes-gcm-p10-glue.o aes-gcm-p10.o ghashp10-ppc.o aesp10-ppc.o -vmx-crypto-objs := vmx.o aesp8-ppc.o ghashp8-ppc.o aes.o aes_cbc.o aes_ctr.o aes_xts.o ghash.o +vmx-crypto-objs := vmx.o ghashp8-ppc.o aes_cbc.o aes_ctr.o aes_xts.o ghash.o ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y) override flavour := linux-ppc64le @@ -26,15 +26,14 @@ endif quiet_cmd_perl = PERL $@ cmd_perl = $(PERL) $< $(flavour) > $@ -targets += aesp10-ppc.S ghashp10-ppc.S aesp8-ppc.S ghashp8-ppc.S +targets += aesp10-ppc.S ghashp10-ppc.S ghashp8-ppc.S $(obj)/aesp10-ppc.S $(obj)/ghashp10-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE $(call if_changed,perl) -$(obj)/aesp8-ppc.S $(obj)/ghashp8-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE +$(obj)/ghashp8-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE $(call if_changed,perl) OBJECT_FILES_NON_STANDARD_aesp10-ppc.o := y OBJECT_FILES_NON_STANDARD_ghashp10-ppc.o := y -OBJECT_FILES_NON_STANDARD_aesp8-ppc.o := y OBJECT_FILES_NON_STANDARD_ghashp8-ppc.o := y diff --git a/arch/powerpc/crypto/aes.c b/arch/powerpc/crypto/aes.c deleted file mode 100644 index b7192ee719fc..000000000000 --- a/arch/powerpc/crypto/aes.c +++ /dev/null @@ -1,134 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * AES routines supporting VMX instructions on the Power 8 - * - * Copyright (C) 2015 International Business Machines Inc. - * - * Author: Marcelo Henrique Cerri - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "aesp8-ppc.h" - -struct p8_aes_ctx { - struct crypto_cipher *fallback; - struct p8_aes_key enc_key; - struct p8_aes_key dec_key; -}; - -static int p8_aes_init(struct crypto_tfm *tfm) -{ - const char *alg = crypto_tfm_alg_name(tfm); - struct crypto_cipher *fallback; - struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - fallback = crypto_alloc_cipher(alg, 0, CRYPTO_ALG_NEED_FALLBACK); - if (IS_ERR(fallback)) { - printk(KERN_ERR - "Failed to allocate transformation for '%s': %ld\n", - alg, PTR_ERR(fallback)); - return PTR_ERR(fallback); - } - - crypto_cipher_set_flags(fallback, - crypto_cipher_get_flags((struct - crypto_cipher *) - tfm)); - ctx->fallback = fallback; - - return 0; -} - -static void p8_aes_exit(struct crypto_tfm *tfm) -{ - struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - if (ctx->fallback) { - crypto_free_cipher(ctx->fallback); - ctx->fallback = NULL; - } -} - -static int p8_aes_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) -{ - int ret; - struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - preempt_disable(); - pagefault_disable(); - enable_kernel_vsx(); - ret = aes_p8_set_encrypt_key(key, keylen * 8, &ctx->enc_key); - ret |= aes_p8_set_decrypt_key(key, keylen * 8, &ctx->dec_key); - disable_kernel_vsx(); - pagefault_enable(); - preempt_enable(); - - ret |= crypto_cipher_setkey(ctx->fallback, key, keylen); - - return ret ? -EINVAL : 0; -} - -static void p8_aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) -{ - struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - if (!crypto_simd_usable()) { - crypto_cipher_encrypt_one(ctx->fallback, dst, src); - } else { - preempt_disable(); - pagefault_disable(); - enable_kernel_vsx(); - aes_p8_encrypt(src, dst, &ctx->enc_key); - disable_kernel_vsx(); - pagefault_enable(); - preempt_enable(); - } -} - -static void p8_aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) -{ - struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - if (!crypto_simd_usable()) { - crypto_cipher_decrypt_one(ctx->fallback, dst, src); - } else { - preempt_disable(); - pagefault_disable(); - enable_kernel_vsx(); - aes_p8_decrypt(src, dst, &ctx->dec_key); - disable_kernel_vsx(); - pagefault_enable(); - preempt_enable(); - } -} - -struct crypto_alg p8_aes_alg = { - .cra_name = "aes", - .cra_driver_name = "p8_aes", - .cra_module = THIS_MODULE, - .cra_priority = 1000, - .cra_type = NULL, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER | CRYPTO_ALG_NEED_FALLBACK, - .cra_alignmask = 0, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct p8_aes_ctx), - .cra_init = p8_aes_init, - .cra_exit = p8_aes_exit, - .cra_cipher = { - .cia_min_keysize = AES_MIN_KEY_SIZE, - .cia_max_keysize = AES_MAX_KEY_SIZE, - .cia_setkey = p8_aes_setkey, - .cia_encrypt = p8_aes_encrypt, - .cia_decrypt = p8_aes_decrypt, - }, -}; diff --git a/arch/powerpc/crypto/aesp8-ppc.h b/arch/powerpc/crypto/aesp8-ppc.h index 0bea010128cb..6862c605cc33 100644 --- a/arch/powerpc/crypto/aesp8-ppc.h +++ b/arch/powerpc/crypto/aesp8-ppc.h @@ -2,30 +2,7 @@ #include #include -struct p8_aes_key { - u8 key[AES_MAX_KEYLENGTH]; - int rounds; -}; - extern struct shash_alg p8_ghash_alg; -extern struct crypto_alg p8_aes_alg; extern struct skcipher_alg p8_aes_cbc_alg; extern struct skcipher_alg p8_aes_ctr_alg; extern struct skcipher_alg p8_aes_xts_alg; - -int aes_p8_set_encrypt_key(const u8 *userKey, const int bits, - struct p8_aes_key *key); -int aes_p8_set_decrypt_key(const u8 *userKey, const int bits, - struct p8_aes_key *key); -void aes_p8_encrypt(const u8 *in, u8 *out, const struct p8_aes_key *key); -void aes_p8_decrypt(const u8 *in, u8 *out, const struct p8_aes_key *key); -void aes_p8_cbc_encrypt(const u8 *in, u8 *out, size_t len, - const struct p8_aes_key *key, u8 *iv, const int enc); -void aes_p8_ctr32_encrypt_blocks(const u8 *in, u8 *out, size_t len, - const struct p8_aes_key *key, const u8 *iv); -void aes_p8_xts_encrypt(const u8 *in, u8 *out, size_t len, - const struct p8_aes_key *key1, - const struct p8_aes_key *key2, u8 *iv); -void aes_p8_xts_decrypt(const u8 *in, u8 *out, size_t len, - const struct p8_aes_key *key1, - const struct p8_aes_key *key2, u8 *iv); diff --git a/arch/powerpc/crypto/vmx.c b/arch/powerpc/crypto/vmx.c index 0b725e826388..7d2beb774f99 100644 --- a/arch/powerpc/crypto/vmx.c +++ b/arch/powerpc/crypto/vmx.c @@ -27,13 +27,9 @@ static int __init p8_init(void) if (ret) goto err; - ret = crypto_register_alg(&p8_aes_alg); - if (ret) - goto err_unregister_ghash; - ret = crypto_register_skcipher(&p8_aes_cbc_alg); if (ret) - goto err_unregister_aes; + goto err_unregister_ghash; ret = crypto_register_skcipher(&p8_aes_ctr_alg); if (ret) @@ -49,8 +45,6 @@ err_unregister_aes_ctr: crypto_unregister_skcipher(&p8_aes_ctr_alg); err_unregister_aes_cbc: crypto_unregister_skcipher(&p8_aes_cbc_alg); -err_unregister_aes: - crypto_unregister_alg(&p8_aes_alg); err_unregister_ghash: crypto_unregister_shash(&p8_ghash_alg); err: @@ -62,7 +56,6 @@ static void __exit p8_exit(void) crypto_unregister_skcipher(&p8_aes_xts_alg); crypto_unregister_skcipher(&p8_aes_ctr_alg); crypto_unregister_skcipher(&p8_aes_cbc_alg); - crypto_unregister_alg(&p8_aes_alg); crypto_unregister_shash(&p8_ghash_alg); } @@ -74,4 +67,3 @@ MODULE_DESCRIPTION("IBM VMX cryptographic acceleration instructions " "support on Power 8"); MODULE_LICENSE("GPL"); MODULE_VERSION("1.0.0"); -MODULE_IMPORT_NS("CRYPTO_INTERNAL"); diff --git a/include/crypto/aes.h b/include/crypto/aes.h index c893c9214cb7..bff71cfaedeb 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -18,12 +18,34 @@ #define AES_MAX_KEYLENGTH (15 * 16) #define AES_MAX_KEYLENGTH_U32 (AES_MAX_KEYLENGTH / sizeof(u32)) +/* + * The POWER8 VSX optimized AES assembly code is borrowed from OpenSSL and + * inherits OpenSSL's AES_KEY format, which stores the number of rounds after + * the round keys. That assembly code is difficult to change. So for + * compatibility purposes we reserve space for the extra nrounds field on PPC64. + * + * Note: when prepared for decryption, the round keys are just the reversed + * standard round keys, not the round keys for the Equivalent Inverse Cipher. + */ +struct p8_aes_key { + u32 rndkeys[AES_MAX_KEYLENGTH_U32]; + int nrounds; +}; + union aes_enckey_arch { u32 rndkeys[AES_MAX_KEYLENGTH_U32]; #ifdef CONFIG_CRYPTO_LIB_AES_ARCH #if defined(CONFIG_PPC) && defined(CONFIG_SPE) /* Used unconditionally (when SPE AES code is enabled in kconfig) */ u32 spe_enc_key[AES_MAX_KEYLENGTH_U32] __aligned(8); +#elif defined(CONFIG_PPC) + /* + * Kernels that include the POWER8 VSX optimized AES code use this field + * when that code is usable at key preparation time. Otherwise they + * fall back to rndkeys. In the latter case, p8.nrounds (which doesn't + * overlap rndkeys) is set to 0 to differentiate the two formats. + */ + struct p8_aes_key p8; #endif #endif /* CONFIG_CRYPTO_LIB_AES_ARCH */ }; @@ -34,6 +56,9 @@ union aes_invkey_arch { #if defined(CONFIG_PPC) && defined(CONFIG_SPE) /* Used unconditionally (when SPE AES code is enabled in kconfig) */ u32 spe_dec_key[AES_MAX_KEYLENGTH_U32] __aligned(8); +#elif defined(CONFIG_PPC) + /* Used conditionally, analogous to aes_enckey_arch::p8 */ + struct p8_aes_key p8; #endif #endif /* CONFIG_CRYPTO_LIB_AES_ARCH */ }; @@ -155,6 +180,22 @@ void ppc_encrypt_xts(u8 *out, const u8 *in, u32 *key_enc, u32 rounds, u32 bytes, u8 *iv, u32 *key_twk); void ppc_decrypt_xts(u8 *out, const u8 *in, u32 *key_dec, u32 rounds, u32 bytes, u8 *iv, u32 *key_twk); +int aes_p8_set_encrypt_key(const u8 *userKey, const int bits, + struct p8_aes_key *key); +int aes_p8_set_decrypt_key(const u8 *userKey, const int bits, + struct p8_aes_key *key); +void aes_p8_encrypt(const u8 *in, u8 *out, const struct p8_aes_key *key); +void aes_p8_decrypt(const u8 *in, u8 *out, const struct p8_aes_key *key); +void aes_p8_cbc_encrypt(const u8 *in, u8 *out, size_t len, + const struct p8_aes_key *key, u8 *iv, const int enc); +void aes_p8_ctr32_encrypt_blocks(const u8 *in, u8 *out, size_t len, + const struct p8_aes_key *key, const u8 *iv); +void aes_p8_xts_encrypt(const u8 *in, u8 *out, size_t len, + const struct p8_aes_key *key1, + const struct p8_aes_key *key2, u8 *iv); +void aes_p8_xts_decrypt(const u8 *in, u8 *out, size_t len, + const struct p8_aes_key *key1, + const struct p8_aes_key *key2, u8 *iv); #endif /** diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index cfc6171203d0..a0f1c105827e 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -16,7 +16,7 @@ config CRYPTO_LIB_AES_ARCH depends on CRYPTO_LIB_AES && !UML && !KMSAN default y if ARM default y if ARM64 - default y if PPC && SPE + default y if PPC && (SPE || (PPC64 && VSX)) config CRYPTO_LIB_AESCFB tristate diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index d68fde004104..16140616ace8 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -35,7 +35,19 @@ libaes-y += powerpc/aes-spe-core.o \ powerpc/aes-spe-keys.o \ powerpc/aes-spe-modes.o \ powerpc/aes-tab-4k.o -endif +else +libaes-y += powerpc/aesp8-ppc.o +aes-perlasm-flavour-y := linux-ppc64 +aes-perlasm-flavour-$(CONFIG_PPC64_ELF_ABI_V2) := linux-ppc64-elfv2 +aes-perlasm-flavour-$(CONFIG_CPU_LITTLE_ENDIAN) := linux-ppc64le +quiet_cmd_perlasm_aes = PERLASM $@ + cmd_perlasm_aes = $(PERL) $< $(aes-perlasm-flavour-y) $@ +# Use if_changed instead of cmd, in case the flavour changed. +$(obj)/powerpc/aesp8-ppc.S: $(src)/powerpc/aesp8-ppc.pl FORCE + $(call if_changed,perlasm_aes) +targets += powerpc/aesp8-ppc.S +OBJECT_FILES_NON_STANDARD_powerpc/aesp8-ppc.o := y +endif # !CONFIG_SPE endif # CONFIG_PPC endif # CONFIG_CRYPTO_LIB_AES_ARCH diff --git a/lib/crypto/powerpc/.gitignore b/lib/crypto/powerpc/.gitignore new file mode 100644 index 000000000000..598ca7aff6b1 --- /dev/null +++ b/lib/crypto/powerpc/.gitignore @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +aesp8-ppc.S diff --git a/lib/crypto/powerpc/aes.h b/lib/crypto/powerpc/aes.h index cf22020f9050..42e0a993c619 100644 --- a/lib/crypto/powerpc/aes.h +++ b/lib/crypto/powerpc/aes.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2015 Markus Stockhausen + * Copyright (C) 2015 International Business Machines Inc. * Copyright 2026 Google LLC */ #include @@ -10,6 +11,8 @@ #include #include +#ifdef CONFIG_SPE + EXPORT_SYMBOL_GPL(ppc_expand_key_128); EXPORT_SYMBOL_GPL(ppc_expand_key_192); EXPORT_SYMBOL_GPL(ppc_expand_key_256); @@ -72,3 +75,164 @@ static void aes_decrypt_arch(const struct aes_key *key, ppc_decrypt_aes(out, in, key->inv_k.spe_dec_key, key->nrounds / 2 - 1); spe_end(); } + +#else /* CONFIG_SPE */ + +static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_vec_crypto); + +EXPORT_SYMBOL_GPL(aes_p8_set_encrypt_key); +EXPORT_SYMBOL_GPL(aes_p8_set_decrypt_key); +EXPORT_SYMBOL_GPL(aes_p8_encrypt); +EXPORT_SYMBOL_GPL(aes_p8_decrypt); +EXPORT_SYMBOL_GPL(aes_p8_cbc_encrypt); +EXPORT_SYMBOL_GPL(aes_p8_ctr32_encrypt_blocks); +EXPORT_SYMBOL_GPL(aes_p8_xts_encrypt); +EXPORT_SYMBOL_GPL(aes_p8_xts_decrypt); + +static inline bool is_vsx_format(const struct p8_aes_key *key) +{ + return key->nrounds != 0; +} + +/* + * Convert a round key from VSX to generic format by reflecting the 16 bytes, + * and (if apply_inv_mix=true) applying InvMixColumn to each column. + * + * It would be nice if the VSX and generic key formats would be compatible. But + * that's very difficult to do, with the assembly code having been borrowed from + * OpenSSL and also targeted to POWER8 rather than POWER9. + * + * Fortunately, this conversion should only be needed in extremely rare cases, + * possibly not at all in practice. It's just included for full correctness. + */ +static void rndkey_from_vsx(u32 out[4], const u32 in[4], bool apply_inv_mix) +{ + u32 k0 = swab32(in[0]); + u32 k1 = swab32(in[1]); + u32 k2 = swab32(in[2]); + u32 k3 = swab32(in[3]); + + if (apply_inv_mix) { + k0 = inv_mix_columns(k0); + k1 = inv_mix_columns(k1); + k2 = inv_mix_columns(k2); + k3 = inv_mix_columns(k3); + } + out[0] = k3; + out[1] = k2; + out[2] = k1; + out[3] = k0; +} + +static void aes_preparekey_arch(union aes_enckey_arch *k, + union aes_invkey_arch *inv_k, + const u8 *in_key, int key_len, int nrounds) +{ + const int keybits = 8 * key_len; + int ret; + + if (static_branch_likely(&have_vec_crypto) && likely(may_use_simd())) { + preempt_disable(); + pagefault_disable(); + enable_kernel_vsx(); + ret = aes_p8_set_encrypt_key(in_key, keybits, &k->p8); + /* + * aes_p8_set_encrypt_key() should never fail here, since the + * key length was already validated. + */ + WARN_ON_ONCE(ret); + if (inv_k) { + ret = aes_p8_set_decrypt_key(in_key, keybits, + &inv_k->p8); + /* ... and likewise for aes_p8_set_decrypt_key(). */ + WARN_ON_ONCE(ret); + } + disable_kernel_vsx(); + pagefault_enable(); + preempt_enable(); + } else { + aes_expandkey_generic(k->rndkeys, + inv_k ? inv_k->inv_rndkeys : NULL, + in_key, key_len); + /* Mark the key as using the generic format. */ + k->p8.nrounds = 0; + if (inv_k) + inv_k->p8.nrounds = 0; + } +} + +static void aes_encrypt_arch(const struct aes_enckey *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + if (static_branch_likely(&have_vec_crypto) && + likely(is_vsx_format(&key->k.p8) && may_use_simd())) { + preempt_disable(); + pagefault_disable(); + enable_kernel_vsx(); + aes_p8_encrypt(in, out, &key->k.p8); + disable_kernel_vsx(); + pagefault_enable(); + preempt_enable(); + } else if (unlikely(is_vsx_format(&key->k.p8))) { + /* + * This handles (the hopefully extremely rare) case where a key + * was prepared using the VSX optimized format, then encryption + * is done in a context that cannot use VSX instructions. + */ + u32 rndkeys[AES_MAX_KEYLENGTH_U32]; + + for (int i = 0; i < 4 * (key->nrounds + 1); i += 4) + rndkey_from_vsx(&rndkeys[i], + &key->k.p8.rndkeys[i], false); + aes_encrypt_generic(rndkeys, key->nrounds, out, in); + } else { + aes_encrypt_generic(key->k.rndkeys, key->nrounds, out, in); + } +} + +static void aes_decrypt_arch(const struct aes_key *key, u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + if (static_branch_likely(&have_vec_crypto) && + likely(is_vsx_format(&key->inv_k.p8) && may_use_simd())) { + preempt_disable(); + pagefault_disable(); + enable_kernel_vsx(); + aes_p8_decrypt(in, out, &key->inv_k.p8); + disable_kernel_vsx(); + pagefault_enable(); + preempt_enable(); + } else if (unlikely(is_vsx_format(&key->inv_k.p8))) { + /* + * This handles (the hopefully extremely rare) case where a key + * was prepared using the VSX optimized format, then decryption + * is done in a context that cannot use VSX instructions. + */ + u32 inv_rndkeys[AES_MAX_KEYLENGTH_U32]; + int i; + + rndkey_from_vsx(&inv_rndkeys[0], + &key->inv_k.p8.rndkeys[0], false); + for (i = 4; i < 4 * key->nrounds; i += 4) { + rndkey_from_vsx(&inv_rndkeys[i], + &key->inv_k.p8.rndkeys[i], true); + } + rndkey_from_vsx(&inv_rndkeys[i], + &key->inv_k.p8.rndkeys[i], false); + aes_decrypt_generic(inv_rndkeys, key->nrounds, out, in); + } else { + aes_decrypt_generic(key->inv_k.inv_rndkeys, key->nrounds, + out, in); + } +} + +#define aes_mod_init_arch aes_mod_init_arch +static void aes_mod_init_arch(void) +{ + if (cpu_has_feature(CPU_FTR_ARCH_207S) && + (cur_cpu_spec->cpu_user_features2 & PPC_FEATURE2_VEC_CRYPTO)) + static_branch_enable(&have_vec_crypto); +} + +#endif /* !CONFIG_SPE */ diff --git a/arch/powerpc/crypto/aesp8-ppc.pl b/lib/crypto/powerpc/aesp8-ppc.pl similarity index 99% rename from arch/powerpc/crypto/aesp8-ppc.pl rename to lib/crypto/powerpc/aesp8-ppc.pl index f729589d792e..253a06758057 100644 --- a/arch/powerpc/crypto/aesp8-ppc.pl +++ b/lib/crypto/powerpc/aesp8-ppc.pl @@ -105,6 +105,7 @@ $LITTLE_ENDIAN = ($flavour=~/le$/) ? $SIZE_T : 0; $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or ( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +( $xlate="${dir}../../../arch/powerpc/crypto/ppc-xlate.pl" and -f $xlate) or die "can't locate ppc-xlate.pl"; open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; From a4e573db06a4e8c519ec4c42f8e1249a0853367a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:12 -0800 Subject: [PATCH 31/53] lib/crypto: riscv/aes: Migrate optimized code into library Move the aes_encrypt_zvkned() and aes_decrypt_zvkned() assembly functions into lib/crypto/, wire them up to the AES library API, and remove the "aes-riscv64-zvkned" crypto_cipher algorithm. To make this possible, change the prototypes of these functions to take (rndkeys, key_len) instead of a pointer to crypto_aes_ctx, and change the RISC-V AES-XTS code to implement tweak encryption using the AES library instead of directly calling aes_encrypt_zvkned(). The result is that both the AES library and crypto_cipher APIs use RISC-V's AES instructions, whereas previously only crypto_cipher did (and it wasn't enabled by default, which this commit fixes as well). Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-15-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/riscv/crypto/Kconfig | 2 - arch/riscv/crypto/aes-macros.S | 12 +++- arch/riscv/crypto/aes-riscv64-glue.c | 81 ++----------------------- arch/riscv/crypto/aes-riscv64-zvkned.S | 27 --------- lib/crypto/Kconfig | 2 + lib/crypto/Makefile | 1 + lib/crypto/riscv/aes-riscv64-zvkned.S | 84 ++++++++++++++++++++++++++ lib/crypto/riscv/aes.h | 63 +++++++++++++++++++ 8 files changed, 166 insertions(+), 106 deletions(-) create mode 100644 lib/crypto/riscv/aes-riscv64-zvkned.S create mode 100644 lib/crypto/riscv/aes.h diff --git a/arch/riscv/crypto/Kconfig b/arch/riscv/crypto/Kconfig index 14c5acb935e9..22d4eaab15f3 100644 --- a/arch/riscv/crypto/Kconfig +++ b/arch/riscv/crypto/Kconfig @@ -6,11 +6,9 @@ config CRYPTO_AES_RISCV64 tristate "Ciphers: AES, modes: ECB, CBC, CTS, CTR, XTS" depends on 64BIT && TOOLCHAIN_HAS_VECTOR_CRYPTO && \ RISCV_EFFICIENT_VECTOR_UNALIGNED_ACCESS - select CRYPTO_ALGAPI select CRYPTO_LIB_AES select CRYPTO_SKCIPHER help - Block cipher: AES cipher algorithms Length-preserving ciphers: AES with ECB, CBC, CTS, CTR, XTS Architecture: riscv64 using: diff --git a/arch/riscv/crypto/aes-macros.S b/arch/riscv/crypto/aes-macros.S index d1a258d04bc7..1384164621a5 100644 --- a/arch/riscv/crypto/aes-macros.S +++ b/arch/riscv/crypto/aes-macros.S @@ -51,8 +51,10 @@ // - If AES-256, loads round keys into v1-v15 and continues onwards. // // Also sets vl=4 and vtype=e32,m1,ta,ma. Clobbers t0 and t1. -.macro aes_begin keyp, label128, label192 +.macro aes_begin keyp, label128, label192, key_len +.ifb \key_len lwu t0, 480(\keyp) // t0 = key length in bytes +.endif li t1, 24 // t1 = key length for AES-192 vsetivli zero, 4, e32, m1, ta, ma vle32.v v1, (\keyp) @@ -76,12 +78,20 @@ vle32.v v10, (\keyp) addi \keyp, \keyp, 16 vle32.v v11, (\keyp) +.ifb \key_len blt t0, t1, \label128 // If AES-128, goto label128. +.else + blt \key_len, t1, \label128 // If AES-128, goto label128. +.endif addi \keyp, \keyp, 16 vle32.v v12, (\keyp) addi \keyp, \keyp, 16 vle32.v v13, (\keyp) +.ifb \key_len beq t0, t1, \label192 // If AES-192, goto label192. +.else + beq \key_len, t1, \label192 // If AES-192, goto label192. +.endif // Else, it's AES-256. addi \keyp, \keyp, 16 vle32.v v14, (\keyp) diff --git a/arch/riscv/crypto/aes-riscv64-glue.c b/arch/riscv/crypto/aes-riscv64-glue.c index f814ee048555..8bbf7f348c23 100644 --- a/arch/riscv/crypto/aes-riscv64-glue.c +++ b/arch/riscv/crypto/aes-riscv64-glue.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * AES using the RISC-V vector crypto extensions. Includes the bare block - * cipher and the ECB, CBC, CBC-CTS, CTR, and XTS modes. + * AES modes using the RISC-V vector crypto extensions * * Copyright (C) 2023 VRULL GmbH * Author: Heiko Stuebner @@ -15,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -23,13 +21,6 @@ #include #include -asmlinkage void aes_encrypt_zvkned(const struct crypto_aes_ctx *key, - const u8 in[AES_BLOCK_SIZE], - u8 out[AES_BLOCK_SIZE]); -asmlinkage void aes_decrypt_zvkned(const struct crypto_aes_ctx *key, - const u8 in[AES_BLOCK_SIZE], - u8 out[AES_BLOCK_SIZE]); - asmlinkage void aes_ecb_encrypt_zvkned(const struct crypto_aes_ctx *key, const u8 *in, u8 *out, size_t len); asmlinkage void aes_ecb_decrypt_zvkned(const struct crypto_aes_ctx *key, @@ -86,14 +77,6 @@ static int riscv64_aes_setkey(struct crypto_aes_ctx *ctx, return aes_expandkey(ctx, key, keylen); } -static int riscv64_aes_setkey_cipher(struct crypto_tfm *tfm, - const u8 *key, unsigned int keylen) -{ - struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - return riscv64_aes_setkey(ctx, key, keylen); -} - static int riscv64_aes_setkey_skcipher(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen) { @@ -102,34 +85,6 @@ static int riscv64_aes_setkey_skcipher(struct crypto_skcipher *tfm, return riscv64_aes_setkey(ctx, key, keylen); } -/* Bare AES, without a mode of operation */ - -static void riscv64_aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) -{ - const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - if (crypto_simd_usable()) { - kernel_vector_begin(); - aes_encrypt_zvkned(ctx, src, dst); - kernel_vector_end(); - } else { - aes_encrypt(ctx, dst, src); - } -} - -static void riscv64_aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) -{ - const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - if (crypto_simd_usable()) { - kernel_vector_begin(); - aes_decrypt_zvkned(ctx, src, dst); - kernel_vector_end(); - } else { - aes_decrypt(ctx, dst, src); - } -} - /* AES-ECB */ static inline int riscv64_aes_ecb_crypt(struct skcipher_request *req, bool enc) @@ -338,7 +293,7 @@ static int riscv64_aes_ctr_crypt(struct skcipher_request *req) struct riscv64_aes_xts_ctx { struct crypto_aes_ctx ctx1; - struct crypto_aes_ctx ctx2; + struct aes_enckey tweak_key; }; static int riscv64_aes_xts_setkey(struct crypto_skcipher *tfm, const u8 *key, @@ -348,7 +303,7 @@ static int riscv64_aes_xts_setkey(struct crypto_skcipher *tfm, const u8 *key, return xts_verify_key(tfm, key, keylen) ?: riscv64_aes_setkey(&ctx->ctx1, key, keylen / 2) ?: - riscv64_aes_setkey(&ctx->ctx2, key + keylen / 2, keylen / 2); + aes_prepareenckey(&ctx->tweak_key, key + keylen / 2, keylen / 2); } static int riscv64_aes_xts_crypt(struct skcipher_request *req, bool enc) @@ -366,9 +321,7 @@ static int riscv64_aes_xts_crypt(struct skcipher_request *req, bool enc) return -EINVAL; /* Encrypt the IV with the tweak key to get the first tweak. */ - kernel_vector_begin(); - aes_encrypt_zvkned(&ctx->ctx2, req->iv, req->iv); - kernel_vector_end(); + aes_encrypt(&ctx->tweak_key, req->iv, req->iv); err = skcipher_walk_virt(&walk, req, false); @@ -456,23 +409,6 @@ static int riscv64_aes_xts_decrypt(struct skcipher_request *req) /* Algorithm definitions */ -static struct crypto_alg riscv64_zvkned_aes_cipher_alg = { - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_aes_ctx), - .cra_priority = 300, - .cra_name = "aes", - .cra_driver_name = "aes-riscv64-zvkned", - .cra_cipher = { - .cia_min_keysize = AES_MIN_KEY_SIZE, - .cia_max_keysize = AES_MAX_KEY_SIZE, - .cia_setkey = riscv64_aes_setkey_cipher, - .cia_encrypt = riscv64_aes_encrypt, - .cia_decrypt = riscv64_aes_decrypt, - }, - .cra_module = THIS_MODULE, -}; - static struct skcipher_alg riscv64_zvkned_aes_skcipher_algs[] = { { .setkey = riscv64_aes_setkey_skcipher, @@ -574,15 +510,11 @@ static int __init riscv64_aes_mod_init(void) if (riscv_isa_extension_available(NULL, ZVKNED) && riscv_vector_vlen() >= 128) { - err = crypto_register_alg(&riscv64_zvkned_aes_cipher_alg); - if (err) - return err; - err = crypto_register_skciphers( riscv64_zvkned_aes_skcipher_algs, ARRAY_SIZE(riscv64_zvkned_aes_skcipher_algs)); if (err) - goto unregister_zvkned_cipher_alg; + return err; if (riscv_isa_extension_available(NULL, ZVKB)) { err = crypto_register_skcipher( @@ -607,8 +539,6 @@ unregister_zvkned_zvkb_skcipher_alg: unregister_zvkned_skcipher_algs: crypto_unregister_skciphers(riscv64_zvkned_aes_skcipher_algs, ARRAY_SIZE(riscv64_zvkned_aes_skcipher_algs)); -unregister_zvkned_cipher_alg: - crypto_unregister_alg(&riscv64_zvkned_aes_cipher_alg); return err; } @@ -620,7 +550,6 @@ static void __exit riscv64_aes_mod_exit(void) crypto_unregister_skcipher(&riscv64_zvkned_zvkb_aes_skcipher_alg); crypto_unregister_skciphers(riscv64_zvkned_aes_skcipher_algs, ARRAY_SIZE(riscv64_zvkned_aes_skcipher_algs)); - crypto_unregister_alg(&riscv64_zvkned_aes_cipher_alg); } module_init(riscv64_aes_mod_init); diff --git a/arch/riscv/crypto/aes-riscv64-zvkned.S b/arch/riscv/crypto/aes-riscv64-zvkned.S index 23d063f94ce6..d0fc4581a380 100644 --- a/arch/riscv/crypto/aes-riscv64-zvkned.S +++ b/arch/riscv/crypto/aes-riscv64-zvkned.S @@ -56,33 +56,6 @@ #define LEN a3 #define IVP a4 -.macro __aes_crypt_zvkned enc, keylen - vle32.v v16, (INP) - aes_crypt v16, \enc, \keylen - vse32.v v16, (OUTP) - ret -.endm - -.macro aes_crypt_zvkned enc - aes_begin KEYP, 128f, 192f - __aes_crypt_zvkned \enc, 256 -128: - __aes_crypt_zvkned \enc, 128 -192: - __aes_crypt_zvkned \enc, 192 -.endm - -// void aes_encrypt_zvkned(const struct crypto_aes_ctx *key, -// const u8 in[16], u8 out[16]); -SYM_FUNC_START(aes_encrypt_zvkned) - aes_crypt_zvkned 1 -SYM_FUNC_END(aes_encrypt_zvkned) - -// Same prototype and calling convention as the encryption function -SYM_FUNC_START(aes_decrypt_zvkned) - aes_crypt_zvkned 0 -SYM_FUNC_END(aes_decrypt_zvkned) - .macro __aes_ecb_crypt enc, keylen srli t0, LEN, 2 // t0 is the remaining length in 32-bit words. It's a multiple of 4. diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index a0f1c105827e..2690b5ffc5ca 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -17,6 +17,8 @@ config CRYPTO_LIB_AES_ARCH default y if ARM default y if ARM64 default y if PPC && (SPE || (PPC64 && VSX)) + default y if RISCV && 64BIT && TOOLCHAIN_HAS_VECTOR_CRYPTO && \ + RISCV_EFFICIENT_VECTOR_UNALIGNED_ACCESS config CRYPTO_LIB_AESCFB tristate diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 16140616ace8..811b60787dd5 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -50,6 +50,7 @@ OBJECT_FILES_NON_STANDARD_powerpc/aesp8-ppc.o := y endif # !CONFIG_SPE endif # CONFIG_PPC +libaes-$(CONFIG_RISCV) += riscv/aes-riscv64-zvkned.o endif # CONFIG_CRYPTO_LIB_AES_ARCH ################################################################################ diff --git a/lib/crypto/riscv/aes-riscv64-zvkned.S b/lib/crypto/riscv/aes-riscv64-zvkned.S new file mode 100644 index 000000000000..0d988bc3d37b --- /dev/null +++ b/lib/crypto/riscv/aes-riscv64-zvkned.S @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause */ +// +// This file is dual-licensed, meaning that you can use it under your +// choice of either of the following two licenses: +// +// Copyright 2023 The OpenSSL Project Authors. All Rights Reserved. +// +// Licensed under the Apache License 2.0 (the "License"). You can obtain +// a copy in the file LICENSE in the source distribution or at +// https://www.openssl.org/source/license.html +// +// or +// +// Copyright (c) 2023, Christoph Müllner +// Copyright (c) 2023, Phoebe Chen +// Copyright (c) 2023, Jerry Shih +// Copyright 2024 Google LLC +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// The generated code of this file depends on the following RISC-V extensions: +// - RV64I +// - RISC-V Vector ('V') with VLEN >= 128 +// - RISC-V Vector AES block cipher extension ('Zvkned') + +#include + +.text +.option arch, +zvkned + +#include "../../arch/riscv/crypto/aes-macros.S" + +#define RNDKEYS a0 +#define KEY_LEN a1 +#define OUTP a2 +#define INP a3 + +.macro __aes_crypt_zvkned enc, keybits + vle32.v v16, (INP) + aes_crypt v16, \enc, \keybits + vse32.v v16, (OUTP) + ret +.endm + +.macro aes_crypt_zvkned enc + aes_begin RNDKEYS, 128f, 192f, KEY_LEN + __aes_crypt_zvkned \enc, 256 +128: + __aes_crypt_zvkned \enc, 128 +192: + __aes_crypt_zvkned \enc, 192 +.endm + +// void aes_encrypt_zvkned(const u32 rndkeys[], int key_len, +// u8 out[AES_BLOCK_SIZE], const u8 in[AES_BLOCK_SIZE]); +SYM_FUNC_START(aes_encrypt_zvkned) + aes_crypt_zvkned 1 +SYM_FUNC_END(aes_encrypt_zvkned) + +// void aes_decrypt_zvkned(const u32 rndkeys[], int key_len, +// u8 out[AES_BLOCK_SIZE], const u8 in[AES_BLOCK_SIZE]); +SYM_FUNC_START(aes_decrypt_zvkned) + aes_crypt_zvkned 0 +SYM_FUNC_END(aes_decrypt_zvkned) diff --git a/lib/crypto/riscv/aes.h b/lib/crypto/riscv/aes.h new file mode 100644 index 000000000000..0b26f58faf2b --- /dev/null +++ b/lib/crypto/riscv/aes.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2023 VRULL GmbH + * Copyright (C) 2023 SiFive, Inc. + * Copyright 2024 Google LLC + */ + +#include +#include + +static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_zvkned); + +void aes_encrypt_zvkned(const u32 rndkeys[], int key_len, + u8 out[AES_BLOCK_SIZE], const u8 in[AES_BLOCK_SIZE]); +void aes_decrypt_zvkned(const u32 rndkeys[], int key_len, + u8 out[AES_BLOCK_SIZE], const u8 in[AES_BLOCK_SIZE]); + +static void aes_preparekey_arch(union aes_enckey_arch *k, + union aes_invkey_arch *inv_k, + const u8 *in_key, int key_len, int nrounds) +{ + aes_expandkey_generic(k->rndkeys, inv_k ? inv_k->inv_rndkeys : NULL, + in_key, key_len); +} + +static void aes_encrypt_arch(const struct aes_enckey *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + if (static_branch_likely(&have_zvkned) && likely(may_use_simd())) { + kernel_vector_begin(); + aes_encrypt_zvkned(key->k.rndkeys, key->len, out, in); + kernel_vector_end(); + } else { + aes_encrypt_generic(key->k.rndkeys, key->nrounds, out, in); + } +} + +static void aes_decrypt_arch(const struct aes_key *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + /* + * Note that the Zvkned code uses the standard round keys, while the + * fallback uses the inverse round keys. Thus both must be present. + */ + if (static_branch_likely(&have_zvkned) && likely(may_use_simd())) { + kernel_vector_begin(); + aes_decrypt_zvkned(key->k.rndkeys, key->len, out, in); + kernel_vector_end(); + } else { + aes_decrypt_generic(key->inv_k.inv_rndkeys, key->nrounds, + out, in); + } +} + +#define aes_mod_init_arch aes_mod_init_arch +static void aes_mod_init_arch(void) +{ + if (riscv_isa_extension_available(NULL, ZVKNED) && + riscv_vector_vlen() >= 128) + static_branch_enable(&have_zvkned); +} From 0cab15611e839142f4fd3c8a366acd1f7334b30b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:13 -0800 Subject: [PATCH 32/53] lib/crypto: s390/aes: Migrate optimized code into library Implement aes_preparekey_arch(), aes_encrypt_arch(), and aes_decrypt_arch() using the CPACF AES instructions. Then, remove the superseded "aes-s390" crypto_cipher. The result is that both the AES library and crypto_cipher APIs use the CPACF AES instructions, whereas previously only crypto_cipher did (and it wasn't enabled by default, which this commit fixes as well). Note that this preserves the optimization where the AES key is stored in raw form rather than expanded form. CPACF just takes the raw key. Acked-by: Ard Biesheuvel Tested-by: Holger Dengler Reviewed-by: Holger Dengler Link: https://lore.kernel.org/r/20260112192035.10427-16-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/s390/crypto/Kconfig | 2 - arch/s390/crypto/aes_s390.c | 113 ------------------------------------ include/crypto/aes.h | 3 + lib/crypto/Kconfig | 1 + lib/crypto/s390/aes.h | 106 +++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 115 deletions(-) create mode 100644 lib/crypto/s390/aes.h diff --git a/arch/s390/crypto/Kconfig b/arch/s390/crypto/Kconfig index f838ca055f6d..79a2d0034258 100644 --- a/arch/s390/crypto/Kconfig +++ b/arch/s390/crypto/Kconfig @@ -14,10 +14,8 @@ config CRYPTO_GHASH_S390 config CRYPTO_AES_S390 tristate "Ciphers: AES, modes: ECB, CBC, CTR, XTS, GCM" - select CRYPTO_ALGAPI select CRYPTO_SKCIPHER help - Block cipher: AES cipher algorithms (FIPS 197) AEAD cipher: AES with GCM Length-preserving ciphers: AES with ECB, CBC, XTS, and CTR modes diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index d0a295435680..62edc66d5478 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -45,7 +44,6 @@ struct s390_aes_ctx { unsigned long fc; union { struct crypto_skcipher *skcipher; - struct crypto_cipher *cip; } fallback; }; @@ -72,109 +70,6 @@ struct gcm_sg_walk { unsigned int nbytes; }; -static int setkey_fallback_cip(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) -{ - struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); - - sctx->fallback.cip->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK; - sctx->fallback.cip->base.crt_flags |= (tfm->crt_flags & - CRYPTO_TFM_REQ_MASK); - - return crypto_cipher_setkey(sctx->fallback.cip, in_key, key_len); -} - -static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) -{ - struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); - unsigned long fc; - - /* Pick the correct function code based on the key length */ - fc = (key_len == 16) ? CPACF_KM_AES_128 : - (key_len == 24) ? CPACF_KM_AES_192 : - (key_len == 32) ? CPACF_KM_AES_256 : 0; - - /* Check if the function code is available */ - sctx->fc = (fc && cpacf_test_func(&km_functions, fc)) ? fc : 0; - if (!sctx->fc) - return setkey_fallback_cip(tfm, in_key, key_len); - - sctx->key_len = key_len; - memcpy(sctx->key, in_key, key_len); - return 0; -} - -static void crypto_aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -{ - struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); - - if (unlikely(!sctx->fc)) { - crypto_cipher_encrypt_one(sctx->fallback.cip, out, in); - return; - } - cpacf_km(sctx->fc, &sctx->key, out, in, AES_BLOCK_SIZE); -} - -static void crypto_aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) -{ - struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); - - if (unlikely(!sctx->fc)) { - crypto_cipher_decrypt_one(sctx->fallback.cip, out, in); - return; - } - cpacf_km(sctx->fc | CPACF_DECRYPT, - &sctx->key, out, in, AES_BLOCK_SIZE); -} - -static int fallback_init_cip(struct crypto_tfm *tfm) -{ - const char *name = tfm->__crt_alg->cra_name; - struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); - - sctx->fallback.cip = crypto_alloc_cipher(name, 0, - CRYPTO_ALG_NEED_FALLBACK); - - if (IS_ERR(sctx->fallback.cip)) { - pr_err("Allocating AES fallback algorithm %s failed\n", - name); - return PTR_ERR(sctx->fallback.cip); - } - - return 0; -} - -static void fallback_exit_cip(struct crypto_tfm *tfm) -{ - struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); - - crypto_free_cipher(sctx->fallback.cip); - sctx->fallback.cip = NULL; -} - -static struct crypto_alg aes_alg = { - .cra_name = "aes", - .cra_driver_name = "aes-s390", - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER | - CRYPTO_ALG_NEED_FALLBACK, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct s390_aes_ctx), - .cra_module = THIS_MODULE, - .cra_init = fallback_init_cip, - .cra_exit = fallback_exit_cip, - .cra_u = { - .cipher = { - .cia_min_keysize = AES_MIN_KEY_SIZE, - .cia_max_keysize = AES_MAX_KEY_SIZE, - .cia_setkey = aes_set_key, - .cia_encrypt = crypto_aes_encrypt, - .cia_decrypt = crypto_aes_decrypt, - } - } -}; - static int setkey_fallback_skcipher(struct crypto_skcipher *tfm, const u8 *key, unsigned int len) { @@ -1049,7 +944,6 @@ static struct aead_alg gcm_aes_aead = { }, }; -static struct crypto_alg *aes_s390_alg; static struct skcipher_alg *aes_s390_skcipher_algs[5]; static int aes_s390_skciphers_num; static struct aead_alg *aes_s390_aead_alg; @@ -1066,8 +960,6 @@ static int aes_s390_register_skcipher(struct skcipher_alg *alg) static void aes_s390_fini(void) { - if (aes_s390_alg) - crypto_unregister_alg(aes_s390_alg); while (aes_s390_skciphers_num--) crypto_unregister_skcipher(aes_s390_skcipher_algs[aes_s390_skciphers_num]); if (ctrblk) @@ -1090,10 +982,6 @@ static int __init aes_s390_init(void) if (cpacf_test_func(&km_functions, CPACF_KM_AES_128) || cpacf_test_func(&km_functions, CPACF_KM_AES_192) || cpacf_test_func(&km_functions, CPACF_KM_AES_256)) { - ret = crypto_register_alg(&aes_alg); - if (ret) - goto out_err; - aes_s390_alg = &aes_alg; ret = aes_s390_register_skcipher(&ecb_aes_alg); if (ret) goto out_err; @@ -1156,4 +1044,3 @@ MODULE_ALIAS_CRYPTO("aes-all"); MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); MODULE_LICENSE("GPL"); -MODULE_IMPORT_NS("CRYPTO_INTERNAL"); diff --git a/include/crypto/aes.h b/include/crypto/aes.h index bff71cfaedeb..19fd99f383fb 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -46,6 +46,9 @@ union aes_enckey_arch { * overlap rndkeys) is set to 0 to differentiate the two formats. */ struct p8_aes_key p8; +#elif defined(CONFIG_S390) + /* Used when the CPU supports CPACF AES for this key's length */ + u8 raw_key[AES_MAX_KEY_SIZE]; #endif #endif /* CONFIG_CRYPTO_LIB_AES_ARCH */ }; diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 2690b5ffc5ca..56a9b4f53b0e 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -19,6 +19,7 @@ config CRYPTO_LIB_AES_ARCH default y if PPC && (SPE || (PPC64 && VSX)) default y if RISCV && 64BIT && TOOLCHAIN_HAS_VECTOR_CRYPTO && \ RISCV_EFFICIENT_VECTOR_UNALIGNED_ACCESS + default y if S390 config CRYPTO_LIB_AESCFB tristate diff --git a/lib/crypto/s390/aes.h b/lib/crypto/s390/aes.h new file mode 100644 index 000000000000..5466f6ecbce7 --- /dev/null +++ b/lib/crypto/s390/aes.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * AES optimized using the CP Assist for Cryptographic Functions (CPACF) + * + * Copyright 2026 Google LLC + */ +#include +#include + +static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_cpacf_aes128); +static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_cpacf_aes192); +static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_cpacf_aes256); + +/* + * When the CPU supports CPACF AES for the requested key length, we need only + * save a copy of the raw AES key, as that's what the CPACF instructions need. + * + * When unsupported, fall back to the generic key expansion and en/decryption. + */ +static void aes_preparekey_arch(union aes_enckey_arch *k, + union aes_invkey_arch *inv_k, + const u8 *in_key, int key_len, int nrounds) +{ + if (key_len == AES_KEYSIZE_128) { + if (static_branch_likely(&have_cpacf_aes128)) { + memcpy(k->raw_key, in_key, AES_KEYSIZE_128); + return; + } + } else if (key_len == AES_KEYSIZE_192) { + if (static_branch_likely(&have_cpacf_aes192)) { + memcpy(k->raw_key, in_key, AES_KEYSIZE_192); + return; + } + } else { + if (static_branch_likely(&have_cpacf_aes256)) { + memcpy(k->raw_key, in_key, AES_KEYSIZE_256); + return; + } + } + aes_expandkey_generic(k->rndkeys, inv_k ? inv_k->inv_rndkeys : NULL, + in_key, key_len); +} + +static inline bool aes_crypt_s390(const struct aes_enckey *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE], int decrypt) +{ + if (key->len == AES_KEYSIZE_128) { + if (static_branch_likely(&have_cpacf_aes128)) { + cpacf_km(CPACF_KM_AES_128 | decrypt, + (void *)key->k.raw_key, out, in, + AES_BLOCK_SIZE); + return true; + } + } else if (key->len == AES_KEYSIZE_192) { + if (static_branch_likely(&have_cpacf_aes192)) { + cpacf_km(CPACF_KM_AES_192 | decrypt, + (void *)key->k.raw_key, out, in, + AES_BLOCK_SIZE); + return true; + } + } else { + if (static_branch_likely(&have_cpacf_aes256)) { + cpacf_km(CPACF_KM_AES_256 | decrypt, + (void *)key->k.raw_key, out, in, + AES_BLOCK_SIZE); + return true; + } + } + return false; +} + +static void aes_encrypt_arch(const struct aes_enckey *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + if (likely(aes_crypt_s390(key, out, in, 0))) + return; + aes_encrypt_generic(key->k.rndkeys, key->nrounds, out, in); +} + +static void aes_decrypt_arch(const struct aes_key *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + if (likely(aes_crypt_s390((const struct aes_enckey *)key, out, in, + CPACF_DECRYPT))) + return; + aes_decrypt_generic(key->inv_k.inv_rndkeys, key->nrounds, out, in); +} + +#define aes_mod_init_arch aes_mod_init_arch +static void aes_mod_init_arch(void) +{ + if (cpu_have_feature(S390_CPU_FEATURE_MSA)) { + cpacf_mask_t km_functions; + + cpacf_query(CPACF_KM, &km_functions); + if (cpacf_test_func(&km_functions, CPACF_KM_AES_128)) + static_branch_enable(&have_cpacf_aes128); + if (cpacf_test_func(&km_functions, CPACF_KM_AES_192)) + static_branch_enable(&have_cpacf_aes192); + if (cpacf_test_func(&km_functions, CPACF_KM_AES_256)) + static_branch_enable(&have_cpacf_aes256); + } +} From 293c7cd5c6c00f3b6fa0072fc4b017a3a13ad1e7 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:14 -0800 Subject: [PATCH 33/53] lib/crypto: sparc/aes: Migrate optimized code into library Move the SPARC64 AES assembly code into lib/crypto/, wire the key expansion and single-block en/decryption functions up to the AES library API, and remove the "aes-sparc64" crypto_cipher algorithm. The result is that both the AES library and crypto_cipher APIs use the SPARC64 AES opcodes, whereas previously only crypto_cipher did (and it wasn't enabled by default, which this commit fixes as well). Note that some of the functions in the SPARC64 AES assembly code are still used by the AES mode implementations in arch/sparc/crypto/aes_glue.c. For now, just export these functions. These exports will go away once the AES mode implementations are migrated to the library as well. (Trying to split up the assembly file seemed like much more trouble than it would be worth.) Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-17-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/sparc/crypto/Kconfig | 2 +- arch/sparc/crypto/Makefile | 2 +- arch/sparc/crypto/aes_glue.c | 140 +--------------- include/crypto/aes.h | 42 +++++ lib/crypto/Kconfig | 1 + lib/crypto/Makefile | 1 + lib/crypto/sparc/aes.h | 149 ++++++++++++++++++ .../crypto => lib/crypto/sparc}/aes_asm.S | 0 8 files changed, 200 insertions(+), 137 deletions(-) create mode 100644 lib/crypto/sparc/aes.h rename {arch/sparc/crypto => lib/crypto/sparc}/aes_asm.S (100%) diff --git a/arch/sparc/crypto/Kconfig b/arch/sparc/crypto/Kconfig index f755da979534..c1932ce46c7f 100644 --- a/arch/sparc/crypto/Kconfig +++ b/arch/sparc/crypto/Kconfig @@ -19,9 +19,9 @@ config CRYPTO_DES_SPARC64 config CRYPTO_AES_SPARC64 tristate "Ciphers: AES, modes: ECB, CBC, CTR" depends on SPARC64 + select CRYPTO_LIB_AES select CRYPTO_SKCIPHER help - Block ciphers: AES cipher algorithms (FIPS-197) Length-preseving ciphers: AES with ECB, CBC, and CTR modes Architecture: sparc64 using crypto instructions diff --git a/arch/sparc/crypto/Makefile b/arch/sparc/crypto/Makefile index 7b4796842ddd..cdf9f4b3efbb 100644 --- a/arch/sparc/crypto/Makefile +++ b/arch/sparc/crypto/Makefile @@ -7,6 +7,6 @@ obj-$(CONFIG_CRYPTO_AES_SPARC64) += aes-sparc64.o obj-$(CONFIG_CRYPTO_DES_SPARC64) += des-sparc64.o obj-$(CONFIG_CRYPTO_CAMELLIA_SPARC64) += camellia-sparc64.o -aes-sparc64-y := aes_asm.o aes_glue.o +aes-sparc64-y := aes_glue.o des-sparc64-y := des_asm.o des_glue.o camellia-sparc64-y := camellia_asm.o camellia_glue.o diff --git a/arch/sparc/crypto/aes_glue.c b/arch/sparc/crypto/aes_glue.c index 359f22643b05..661561837415 100644 --- a/arch/sparc/crypto/aes_glue.c +++ b/arch/sparc/crypto/aes_glue.c @@ -32,8 +32,6 @@ #include struct aes_ops { - void (*encrypt)(const u64 *key, const u32 *input, u32 *output); - void (*decrypt)(const u64 *key, const u32 *input, u32 *output); void (*load_encrypt_keys)(const u64 *key); void (*load_decrypt_keys)(const u64 *key); void (*ecb_encrypt)(const u64 *key, const u64 *input, u64 *output, @@ -55,79 +53,7 @@ struct crypto_sparc64_aes_ctx { u32 expanded_key_length; }; -extern void aes_sparc64_encrypt_128(const u64 *key, const u32 *input, - u32 *output); -extern void aes_sparc64_encrypt_192(const u64 *key, const u32 *input, - u32 *output); -extern void aes_sparc64_encrypt_256(const u64 *key, const u32 *input, - u32 *output); - -extern void aes_sparc64_decrypt_128(const u64 *key, const u32 *input, - u32 *output); -extern void aes_sparc64_decrypt_192(const u64 *key, const u32 *input, - u32 *output); -extern void aes_sparc64_decrypt_256(const u64 *key, const u32 *input, - u32 *output); - -extern void aes_sparc64_load_encrypt_keys_128(const u64 *key); -extern void aes_sparc64_load_encrypt_keys_192(const u64 *key); -extern void aes_sparc64_load_encrypt_keys_256(const u64 *key); - -extern void aes_sparc64_load_decrypt_keys_128(const u64 *key); -extern void aes_sparc64_load_decrypt_keys_192(const u64 *key); -extern void aes_sparc64_load_decrypt_keys_256(const u64 *key); - -extern void aes_sparc64_ecb_encrypt_128(const u64 *key, const u64 *input, - u64 *output, unsigned int len); -extern void aes_sparc64_ecb_encrypt_192(const u64 *key, const u64 *input, - u64 *output, unsigned int len); -extern void aes_sparc64_ecb_encrypt_256(const u64 *key, const u64 *input, - u64 *output, unsigned int len); - -extern void aes_sparc64_ecb_decrypt_128(const u64 *key, const u64 *input, - u64 *output, unsigned int len); -extern void aes_sparc64_ecb_decrypt_192(const u64 *key, const u64 *input, - u64 *output, unsigned int len); -extern void aes_sparc64_ecb_decrypt_256(const u64 *key, const u64 *input, - u64 *output, unsigned int len); - -extern void aes_sparc64_cbc_encrypt_128(const u64 *key, const u64 *input, - u64 *output, unsigned int len, - u64 *iv); - -extern void aes_sparc64_cbc_encrypt_192(const u64 *key, const u64 *input, - u64 *output, unsigned int len, - u64 *iv); - -extern void aes_sparc64_cbc_encrypt_256(const u64 *key, const u64 *input, - u64 *output, unsigned int len, - u64 *iv); - -extern void aes_sparc64_cbc_decrypt_128(const u64 *key, const u64 *input, - u64 *output, unsigned int len, - u64 *iv); - -extern void aes_sparc64_cbc_decrypt_192(const u64 *key, const u64 *input, - u64 *output, unsigned int len, - u64 *iv); - -extern void aes_sparc64_cbc_decrypt_256(const u64 *key, const u64 *input, - u64 *output, unsigned int len, - u64 *iv); - -extern void aes_sparc64_ctr_crypt_128(const u64 *key, const u64 *input, - u64 *output, unsigned int len, - u64 *iv); -extern void aes_sparc64_ctr_crypt_192(const u64 *key, const u64 *input, - u64 *output, unsigned int len, - u64 *iv); -extern void aes_sparc64_ctr_crypt_256(const u64 *key, const u64 *input, - u64 *output, unsigned int len, - u64 *iv); - static struct aes_ops aes128_ops = { - .encrypt = aes_sparc64_encrypt_128, - .decrypt = aes_sparc64_decrypt_128, .load_encrypt_keys = aes_sparc64_load_encrypt_keys_128, .load_decrypt_keys = aes_sparc64_load_decrypt_keys_128, .ecb_encrypt = aes_sparc64_ecb_encrypt_128, @@ -138,8 +64,6 @@ static struct aes_ops aes128_ops = { }; static struct aes_ops aes192_ops = { - .encrypt = aes_sparc64_encrypt_192, - .decrypt = aes_sparc64_decrypt_192, .load_encrypt_keys = aes_sparc64_load_encrypt_keys_192, .load_decrypt_keys = aes_sparc64_load_decrypt_keys_192, .ecb_encrypt = aes_sparc64_ecb_encrypt_192, @@ -150,8 +74,6 @@ static struct aes_ops aes192_ops = { }; static struct aes_ops aes256_ops = { - .encrypt = aes_sparc64_encrypt_256, - .decrypt = aes_sparc64_decrypt_256, .load_encrypt_keys = aes_sparc64_load_encrypt_keys_256, .load_decrypt_keys = aes_sparc64_load_decrypt_keys_256, .ecb_encrypt = aes_sparc64_ecb_encrypt_256, @@ -161,13 +83,10 @@ static struct aes_ops aes256_ops = { .ctr_crypt = aes_sparc64_ctr_crypt_256, }; -extern void aes_sparc64_key_expand(const u32 *in_key, u64 *output_key, - unsigned int key_len); - -static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) +static int aes_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *in_key, + unsigned int key_len) { - struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_sparc64_aes_ctx *ctx = crypto_skcipher_ctx(tfm); switch (key_len) { case AES_KEYSIZE_128: @@ -195,26 +114,6 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, return 0; } -static int aes_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *in_key, - unsigned int key_len) -{ - return aes_set_key(crypto_skcipher_tfm(tfm), in_key, key_len); -} - -static void crypto_aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) -{ - struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - ctx->ops->encrypt(&ctx->key[0], (const u32 *) src, (u32 *) dst); -} - -static void crypto_aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) -{ - struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm); - - ctx->ops->decrypt(&ctx->key[0], (const u32 *) src, (u32 *) dst); -} - static int ecb_encrypt(struct skcipher_request *req) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); @@ -358,26 +257,6 @@ static int ctr_crypt(struct skcipher_request *req) return err; } -static struct crypto_alg cipher_alg = { - .cra_name = "aes", - .cra_driver_name = "aes-sparc64", - .cra_priority = SPARC_CR_OPCODE_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_sparc64_aes_ctx), - .cra_alignmask = 3, - .cra_module = THIS_MODULE, - .cra_u = { - .cipher = { - .cia_min_keysize = AES_MIN_KEY_SIZE, - .cia_max_keysize = AES_MAX_KEY_SIZE, - .cia_setkey = aes_set_key, - .cia_encrypt = crypto_aes_encrypt, - .cia_decrypt = crypto_aes_decrypt - } - } -}; - static struct skcipher_alg skcipher_algs[] = { { .base.cra_name = "ecb(aes)", @@ -440,26 +319,17 @@ static bool __init sparc64_has_aes_opcode(void) static int __init aes_sparc64_mod_init(void) { - int err; - if (!sparc64_has_aes_opcode()) { pr_info("sparc64 aes opcodes not available.\n"); return -ENODEV; } pr_info("Using sparc64 aes opcodes optimized AES implementation\n"); - err = crypto_register_alg(&cipher_alg); - if (err) - return err; - err = crypto_register_skciphers(skcipher_algs, - ARRAY_SIZE(skcipher_algs)); - if (err) - crypto_unregister_alg(&cipher_alg); - return err; + return crypto_register_skciphers(skcipher_algs, + ARRAY_SIZE(skcipher_algs)); } static void __exit aes_sparc64_mod_fini(void) { - crypto_unregister_alg(&cipher_alg); crypto_unregister_skciphers(skcipher_algs, ARRAY_SIZE(skcipher_algs)); } diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 19fd99f383fb..4a56aed59973 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -49,6 +49,9 @@ union aes_enckey_arch { #elif defined(CONFIG_S390) /* Used when the CPU supports CPACF AES for this key's length */ u8 raw_key[AES_MAX_KEY_SIZE]; +#elif defined(CONFIG_SPARC64) + /* Used when the CPU supports the SPARC64 AES opcodes */ + u64 sparc_rndkeys[AES_MAX_KEYLENGTH / sizeof(u64)]; #endif #endif /* CONFIG_CRYPTO_LIB_AES_ARCH */ }; @@ -199,6 +202,45 @@ void aes_p8_xts_encrypt(const u8 *in, u8 *out, size_t len, void aes_p8_xts_decrypt(const u8 *in, u8 *out, size_t len, const struct p8_aes_key *key1, const struct p8_aes_key *key2, u8 *iv); +#elif defined(CONFIG_SPARC64) +void aes_sparc64_key_expand(const u32 *in_key, u64 *output_key, + unsigned int key_len); +void aes_sparc64_load_encrypt_keys_128(const u64 *key); +void aes_sparc64_load_encrypt_keys_192(const u64 *key); +void aes_sparc64_load_encrypt_keys_256(const u64 *key); +void aes_sparc64_load_decrypt_keys_128(const u64 *key); +void aes_sparc64_load_decrypt_keys_192(const u64 *key); +void aes_sparc64_load_decrypt_keys_256(const u64 *key); +void aes_sparc64_ecb_encrypt_128(const u64 *key, const u64 *input, u64 *output, + unsigned int len); +void aes_sparc64_ecb_encrypt_192(const u64 *key, const u64 *input, u64 *output, + unsigned int len); +void aes_sparc64_ecb_encrypt_256(const u64 *key, const u64 *input, u64 *output, + unsigned int len); +void aes_sparc64_ecb_decrypt_128(const u64 *key, const u64 *input, u64 *output, + unsigned int len); +void aes_sparc64_ecb_decrypt_192(const u64 *key, const u64 *input, u64 *output, + unsigned int len); +void aes_sparc64_ecb_decrypt_256(const u64 *key, const u64 *input, u64 *output, + unsigned int len); +void aes_sparc64_cbc_encrypt_128(const u64 *key, const u64 *input, u64 *output, + unsigned int len, u64 *iv); +void aes_sparc64_cbc_encrypt_192(const u64 *key, const u64 *input, u64 *output, + unsigned int len, u64 *iv); +void aes_sparc64_cbc_encrypt_256(const u64 *key, const u64 *input, u64 *output, + unsigned int len, u64 *iv); +void aes_sparc64_cbc_decrypt_128(const u64 *key, const u64 *input, u64 *output, + unsigned int len, u64 *iv); +void aes_sparc64_cbc_decrypt_192(const u64 *key, const u64 *input, u64 *output, + unsigned int len, u64 *iv); +void aes_sparc64_cbc_decrypt_256(const u64 *key, const u64 *input, u64 *output, + unsigned int len, u64 *iv); +void aes_sparc64_ctr_crypt_128(const u64 *key, const u64 *input, u64 *output, + unsigned int len, u64 *iv); +void aes_sparc64_ctr_crypt_192(const u64 *key, const u64 *input, u64 *output, + unsigned int len, u64 *iv); +void aes_sparc64_ctr_crypt_256(const u64 *key, const u64 *input, u64 *output, + unsigned int len, u64 *iv); #endif /** diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 56a9b4f53b0e..920d96e6b498 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -20,6 +20,7 @@ config CRYPTO_LIB_AES_ARCH default y if RISCV && 64BIT && TOOLCHAIN_HAS_VECTOR_CRYPTO && \ RISCV_EFFICIENT_VECTOR_UNALIGNED_ACCESS default y if S390 + default y if SPARC64 config CRYPTO_LIB_AESCFB tristate diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 811b60787dd5..761d52d91f92 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -51,6 +51,7 @@ endif # !CONFIG_SPE endif # CONFIG_PPC libaes-$(CONFIG_RISCV) += riscv/aes-riscv64-zvkned.o +libaes-$(CONFIG_SPARC) += sparc/aes_asm.o endif # CONFIG_CRYPTO_LIB_AES_ARCH ################################################################################ diff --git a/lib/crypto/sparc/aes.h b/lib/crypto/sparc/aes.h new file mode 100644 index 000000000000..e354aa507ee0 --- /dev/null +++ b/lib/crypto/sparc/aes.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * AES accelerated using the sparc64 aes opcodes + * + * Copyright (C) 2008, Intel Corp. + * Copyright (c) 2010, Intel Corporation. + * Copyright 2026 Google LLC + */ + +#include +#include +#include +#include + +static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_aes_opcodes); + +EXPORT_SYMBOL_GPL(aes_sparc64_key_expand); +EXPORT_SYMBOL_GPL(aes_sparc64_load_encrypt_keys_128); +EXPORT_SYMBOL_GPL(aes_sparc64_load_encrypt_keys_192); +EXPORT_SYMBOL_GPL(aes_sparc64_load_encrypt_keys_256); +EXPORT_SYMBOL_GPL(aes_sparc64_load_decrypt_keys_128); +EXPORT_SYMBOL_GPL(aes_sparc64_load_decrypt_keys_192); +EXPORT_SYMBOL_GPL(aes_sparc64_load_decrypt_keys_256); +EXPORT_SYMBOL_GPL(aes_sparc64_ecb_encrypt_128); +EXPORT_SYMBOL_GPL(aes_sparc64_ecb_encrypt_192); +EXPORT_SYMBOL_GPL(aes_sparc64_ecb_encrypt_256); +EXPORT_SYMBOL_GPL(aes_sparc64_ecb_decrypt_128); +EXPORT_SYMBOL_GPL(aes_sparc64_ecb_decrypt_192); +EXPORT_SYMBOL_GPL(aes_sparc64_ecb_decrypt_256); +EXPORT_SYMBOL_GPL(aes_sparc64_cbc_encrypt_128); +EXPORT_SYMBOL_GPL(aes_sparc64_cbc_encrypt_192); +EXPORT_SYMBOL_GPL(aes_sparc64_cbc_encrypt_256); +EXPORT_SYMBOL_GPL(aes_sparc64_cbc_decrypt_128); +EXPORT_SYMBOL_GPL(aes_sparc64_cbc_decrypt_192); +EXPORT_SYMBOL_GPL(aes_sparc64_cbc_decrypt_256); +EXPORT_SYMBOL_GPL(aes_sparc64_ctr_crypt_128); +EXPORT_SYMBOL_GPL(aes_sparc64_ctr_crypt_192); +EXPORT_SYMBOL_GPL(aes_sparc64_ctr_crypt_256); + +void aes_sparc64_encrypt_128(const u64 *key, const u32 *input, u32 *output); +void aes_sparc64_encrypt_192(const u64 *key, const u32 *input, u32 *output); +void aes_sparc64_encrypt_256(const u64 *key, const u32 *input, u32 *output); +void aes_sparc64_decrypt_128(const u64 *key, const u32 *input, u32 *output); +void aes_sparc64_decrypt_192(const u64 *key, const u32 *input, u32 *output); +void aes_sparc64_decrypt_256(const u64 *key, const u32 *input, u32 *output); + +static void aes_preparekey_arch(union aes_enckey_arch *k, + union aes_invkey_arch *inv_k, + const u8 *in_key, int key_len, int nrounds) +{ + if (static_branch_likely(&have_aes_opcodes)) { + u32 aligned_key[AES_MAX_KEY_SIZE / 4]; + + if (IS_ALIGNED((uintptr_t)in_key, 4)) { + aes_sparc64_key_expand((const u32 *)in_key, + k->sparc_rndkeys, key_len); + } else { + memcpy(aligned_key, in_key, key_len); + aes_sparc64_key_expand(aligned_key, + k->sparc_rndkeys, key_len); + memzero_explicit(aligned_key, key_len); + } + /* + * Note that nothing needs to be written to inv_k (if it's + * non-NULL) here, since the SPARC64 assembly code uses + * k->sparc_rndkeys for both encryption and decryption. + */ + } else { + aes_expandkey_generic(k->rndkeys, + inv_k ? inv_k->inv_rndkeys : NULL, + in_key, key_len); + } +} + +static void aes_sparc64_encrypt(const struct aes_enckey *key, + const u32 *input, u32 *output) +{ + if (key->len == AES_KEYSIZE_128) + aes_sparc64_encrypt_128(key->k.sparc_rndkeys, input, output); + else if (key->len == AES_KEYSIZE_192) + aes_sparc64_encrypt_192(key->k.sparc_rndkeys, input, output); + else + aes_sparc64_encrypt_256(key->k.sparc_rndkeys, input, output); +} + +static void aes_encrypt_arch(const struct aes_enckey *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + u32 bounce_buf[AES_BLOCK_SIZE / 4]; + + if (static_branch_likely(&have_aes_opcodes)) { + if (IS_ALIGNED((uintptr_t)in | (uintptr_t)out, 4)) { + aes_sparc64_encrypt(key, (const u32 *)in, (u32 *)out); + } else { + memcpy(bounce_buf, in, AES_BLOCK_SIZE); + aes_sparc64_encrypt(key, bounce_buf, bounce_buf); + memcpy(out, bounce_buf, AES_BLOCK_SIZE); + } + } else { + aes_encrypt_generic(key->k.rndkeys, key->nrounds, out, in); + } +} + +static void aes_sparc64_decrypt(const struct aes_key *key, + const u32 *input, u32 *output) +{ + if (key->len == AES_KEYSIZE_128) + aes_sparc64_decrypt_128(key->k.sparc_rndkeys, input, output); + else if (key->len == AES_KEYSIZE_192) + aes_sparc64_decrypt_192(key->k.sparc_rndkeys, input, output); + else + aes_sparc64_decrypt_256(key->k.sparc_rndkeys, input, output); +} + +static void aes_decrypt_arch(const struct aes_key *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + u32 bounce_buf[AES_BLOCK_SIZE / 4]; + + if (static_branch_likely(&have_aes_opcodes)) { + if (IS_ALIGNED((uintptr_t)in | (uintptr_t)out, 4)) { + aes_sparc64_decrypt(key, (const u32 *)in, (u32 *)out); + } else { + memcpy(bounce_buf, in, AES_BLOCK_SIZE); + aes_sparc64_decrypt(key, bounce_buf, bounce_buf); + memcpy(out, bounce_buf, AES_BLOCK_SIZE); + } + } else { + aes_decrypt_generic(key->inv_k.inv_rndkeys, key->nrounds, + out, in); + } +} + +#define aes_mod_init_arch aes_mod_init_arch +static void aes_mod_init_arch(void) +{ + unsigned long cfr; + + if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO)) + return; + + __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); + if (!(cfr & CFR_AES)) + return; + + static_branch_enable(&have_aes_opcodes); +} diff --git a/arch/sparc/crypto/aes_asm.S b/lib/crypto/sparc/aes_asm.S similarity index 100% rename from arch/sparc/crypto/aes_asm.S rename to lib/crypto/sparc/aes_asm.S From 24eb22d8161380eba65edc5b499299639cbe8bf9 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:15 -0800 Subject: [PATCH 34/53] lib/crypto: x86/aes: Add AES-NI optimization Optimize the AES library with x86 AES-NI instructions. The relevant existing assembly functions, aesni_set_key(), aesni_enc(), and aesni_dec(), are a bit difficult to extract into the library: - They're coupled to the code for the AES modes. - They operate on struct crypto_aes_ctx. The AES library now uses different structs. - They assume the key is 16-byte aligned. The AES library only *prefers* 16-byte alignment; it doesn't require it. Moreover, they're not all that great in the first place: - They use unrolled loops, which isn't a great choice on x86. - They use the 'aeskeygenassist' instruction, which is unnecessary, is slow on Intel CPUs, and forces the loop to be unrolled. - They have special code for AES-192 key expansion, despite that being kind of useless. AES-128 and AES-256 are the ones used in practice. These are small functions anyway. Therefore, I opted to just write replacements of these functions for the library. They address all the above issues. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-18-ebiggers@kernel.org Signed-off-by: Eric Biggers --- lib/crypto/Kconfig | 1 + lib/crypto/Makefile | 1 + lib/crypto/x86/aes-aesni.S | 261 +++++++++++++++++++++++++++++++++++++ lib/crypto/x86/aes.h | 85 ++++++++++++ 4 files changed, 348 insertions(+) create mode 100644 lib/crypto/x86/aes-aesni.S create mode 100644 lib/crypto/x86/aes.h diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 920d96e6b498..032f9755f999 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -21,6 +21,7 @@ config CRYPTO_LIB_AES_ARCH RISCV_EFFICIENT_VECTOR_UNALIGNED_ACCESS default y if S390 default y if SPARC64 + default y if X86 config CRYPTO_LIB_AESCFB tristate diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 761d52d91f92..725eef05b758 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -52,6 +52,7 @@ endif # CONFIG_PPC libaes-$(CONFIG_RISCV) += riscv/aes-riscv64-zvkned.o libaes-$(CONFIG_SPARC) += sparc/aes_asm.o +libaes-$(CONFIG_X86) += x86/aes-aesni.o endif # CONFIG_CRYPTO_LIB_AES_ARCH ################################################################################ diff --git a/lib/crypto/x86/aes-aesni.S b/lib/crypto/x86/aes-aesni.S new file mode 100644 index 000000000000..b8c3e104a3be --- /dev/null +++ b/lib/crypto/x86/aes-aesni.S @@ -0,0 +1,261 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +// +// AES block cipher using AES-NI instructions +// +// Copyright 2026 Google LLC +// +// The code in this file supports 32-bit and 64-bit CPUs, and it doesn't require +// AVX. It does use up to SSE4.1, which all CPUs with AES-NI have. +#include + +.section .rodata +#ifdef __x86_64__ +#define RODATA(label) label(%rip) +#else +#define RODATA(label) label +#endif + + // A mask for pshufb that extracts the last dword, rotates it right by 8 + // bits, and copies the result to all four dwords. +.p2align 4 +.Lmask: + .byte 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12 + + // The AES round constants, used during key expansion +.Lrcon: + .long 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 + +.text + +// Transform four dwords [a0, a1, a2, a3] in \a into +// [a0, a0^a1, a0^a1^a2, a0^a1^a2^a3]. \tmp is a temporary xmm register. +// +// Note: this could be done in four instructions, shufps + pxor + shufps + pxor, +// if the temporary register were zero-initialized ahead of time. We instead do +// it in an easier-to-understand way that doesn't require zero-initialization +// and avoids the unusual shufps instruction. movdqa is usually "free" anyway. +.macro _prefix_sum a, tmp + movdqa \a, \tmp // [a0, a1, a2, a3] + pslldq $4, \a // [0, a0, a1, a2] + pxor \tmp, \a // [a0, a0^a1, a1^a2, a2^a3] + movdqa \a, \tmp + pslldq $8, \a // [0, 0, a0, a0^a1] + pxor \tmp, \a // [a0, a0^a1, a0^a1^a2, a0^a1^a2^a3] +.endm + +.macro _gen_round_key a, b + // Compute four copies of rcon[i] ^ SubBytes(ror32(w, 8)), where w is + // the last dword of the previous round key (given in \b). + // + // 'aesenclast src, dst' does dst = src XOR SubBytes(ShiftRows(dst)). + // It is used here solely for the SubBytes and the XOR. The ShiftRows + // is a no-op because all four columns are the same here. + // + // Don't use the 'aeskeygenassist' instruction, since: + // - On most Intel CPUs it is microcoded, making it have a much higher + // latency and use more execution ports than 'aesenclast'. + // - It cannot be used in a loop, since it requires an immediate. + // - It doesn't do much more than 'aesenclast' in the first place. + movdqa \b, %xmm2 + pshufb MASK, %xmm2 + aesenclast RCON, %xmm2 + + // XOR in the prefix sum of the four dwords of \a, which is the + // previous round key (AES-128) or the first round key in the previous + // pair of round keys (AES-256). The result is the next round key. + _prefix_sum \a, tmp=%xmm3 + pxor %xmm2, \a + + // Store the next round key to memory. Also leave it in \a. + movdqu \a, (RNDKEYS) +.endm + +.macro _aes_expandkey_aesni is_aes128 +#ifdef __x86_64__ + // Arguments + .set RNDKEYS, %rdi + .set INV_RNDKEYS, %rsi + .set IN_KEY, %rdx + + // Other local variables + .set RCON_PTR, %rcx + .set COUNTER, %eax +#else + // Arguments, assuming -mregparm=3 + .set RNDKEYS, %eax + .set INV_RNDKEYS, %edx + .set IN_KEY, %ecx + + // Other local variables + .set RCON_PTR, %ebx + .set COUNTER, %esi +#endif + .set RCON, %xmm6 + .set MASK, %xmm7 + +#ifdef __i386__ + push %ebx + push %esi +#endif + +.if \is_aes128 + // AES-128: the first round key is simply a copy of the raw key. + movdqu (IN_KEY), %xmm0 + movdqu %xmm0, (RNDKEYS) +.else + // AES-256: the first two round keys are simply a copy of the raw key. + movdqu (IN_KEY), %xmm0 + movdqu %xmm0, (RNDKEYS) + movdqu 16(IN_KEY), %xmm1 + movdqu %xmm1, 16(RNDKEYS) + add $32, RNDKEYS +.endif + + // Generate the remaining round keys. + movdqa RODATA(.Lmask), MASK +.if \is_aes128 + lea RODATA(.Lrcon), RCON_PTR + mov $10, COUNTER +.Lgen_next_aes128_round_key: + add $16, RNDKEYS + movd (RCON_PTR), RCON + pshufd $0x00, RCON, RCON + add $4, RCON_PTR + _gen_round_key %xmm0, %xmm0 + dec COUNTER + jnz .Lgen_next_aes128_round_key +.else + // AES-256: only the first 7 round constants are needed, so instead of + // loading each one from memory, just start by loading [1, 1, 1, 1] and + // then generate the rest by doubling. + pshufd $0x00, RODATA(.Lrcon), RCON + pxor %xmm5, %xmm5 // All-zeroes + mov $7, COUNTER +.Lgen_next_aes256_round_key_pair: + // Generate the next AES-256 round key: either the first of a pair of + // two, or the last one. + _gen_round_key %xmm0, %xmm1 + + dec COUNTER + jz .Lgen_aes256_round_keys_done + + // Generate the second AES-256 round key of the pair. Compared to the + // first, there's no rotation and no XOR of a round constant. + pshufd $0xff, %xmm0, %xmm2 // Get four copies of last dword + aesenclast %xmm5, %xmm2 // Just does SubBytes + _prefix_sum %xmm1, tmp=%xmm3 + pxor %xmm2, %xmm1 + movdqu %xmm1, 16(RNDKEYS) + add $32, RNDKEYS + paddd RCON, RCON // RCON <<= 1 + jmp .Lgen_next_aes256_round_key_pair +.Lgen_aes256_round_keys_done: +.endif + + // If INV_RNDKEYS is non-NULL, write the round keys for the Equivalent + // Inverse Cipher to it. To do that, reverse the standard round keys, + // and apply aesimc (InvMixColumn) to each except the first and last. + test INV_RNDKEYS, INV_RNDKEYS + jz .Ldone\@ + movdqu (RNDKEYS), %xmm0 // Last standard round key + movdqu %xmm0, (INV_RNDKEYS) // => First inverse round key +.if \is_aes128 + mov $9, COUNTER +.else + mov $13, COUNTER +.endif +.Lgen_next_inv_round_key\@: + sub $16, RNDKEYS + add $16, INV_RNDKEYS + movdqu (RNDKEYS), %xmm0 + aesimc %xmm0, %xmm0 + movdqu %xmm0, (INV_RNDKEYS) + dec COUNTER + jnz .Lgen_next_inv_round_key\@ + movdqu -16(RNDKEYS), %xmm0 // First standard round key + movdqu %xmm0, 16(INV_RNDKEYS) // => Last inverse round key + +.Ldone\@: +#ifdef __i386__ + pop %esi + pop %ebx +#endif + RET +.endm + +// void aes128_expandkey_aesni(u32 rndkeys[], u32 *inv_rndkeys, +// const u8 in_key[AES_KEYSIZE_128]); +SYM_FUNC_START(aes128_expandkey_aesni) + _aes_expandkey_aesni 1 +SYM_FUNC_END(aes128_expandkey_aesni) + +// void aes256_expandkey_aesni(u32 rndkeys[], u32 *inv_rndkeys, +// const u8 in_key[AES_KEYSIZE_256]); +SYM_FUNC_START(aes256_expandkey_aesni) + _aes_expandkey_aesni 0 +SYM_FUNC_END(aes256_expandkey_aesni) + +.macro _aes_crypt_aesni enc +#ifdef __x86_64__ + .set RNDKEYS, %rdi + .set NROUNDS, %esi + .set OUT, %rdx + .set IN, %rcx +#else + // Assuming -mregparm=3 + .set RNDKEYS, %eax + .set NROUNDS, %edx + .set OUT, %ecx + .set IN, %ebx // Passed on stack +#endif + +#ifdef __i386__ + push %ebx + mov 8(%esp), %ebx +#endif + + // Zero-th round + movdqu (IN), %xmm0 + movdqu (RNDKEYS), %xmm1 + pxor %xmm1, %xmm0 + + // Normal rounds + add $16, RNDKEYS + dec NROUNDS +.Lnext_round\@: + movdqu (RNDKEYS), %xmm1 +.if \enc + aesenc %xmm1, %xmm0 +.else + aesdec %xmm1, %xmm0 +.endif + add $16, RNDKEYS + dec NROUNDS + jne .Lnext_round\@ + + // Last round + movdqu (RNDKEYS), %xmm1 +.if \enc + aesenclast %xmm1, %xmm0 +.else + aesdeclast %xmm1, %xmm0 +.endif + movdqu %xmm0, (OUT) + +#ifdef __i386__ + pop %ebx +#endif + RET +.endm + +// void aes_encrypt_aesni(const u32 rndkeys[], int nrounds, +// u8 out[AES_BLOCK_SIZE], const u8 in[AES_BLOCK_SIZE]); +SYM_FUNC_START(aes_encrypt_aesni) + _aes_crypt_aesni 1 +SYM_FUNC_END(aes_encrypt_aesni) + +// void aes_decrypt_aesni(const u32 inv_rndkeys[], int nrounds, +// u8 out[AES_BLOCK_SIZE], const u8 in[AES_BLOCK_SIZE]); +SYM_FUNC_START(aes_decrypt_aesni) + _aes_crypt_aesni 0 +SYM_FUNC_END(aes_decrypt_aesni) diff --git a/lib/crypto/x86/aes.h b/lib/crypto/x86/aes.h new file mode 100644 index 000000000000..b047dee94f57 --- /dev/null +++ b/lib/crypto/x86/aes.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * AES block cipher using AES-NI instructions + * + * Copyright 2026 Google LLC + */ + +#include + +static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_aes); + +void aes128_expandkey_aesni(u32 rndkeys[], u32 *inv_rndkeys, + const u8 in_key[AES_KEYSIZE_128]); +void aes256_expandkey_aesni(u32 rndkeys[], u32 *inv_rndkeys, + const u8 in_key[AES_KEYSIZE_256]); +void aes_encrypt_aesni(const u32 rndkeys[], int nrounds, + u8 out[AES_BLOCK_SIZE], const u8 in[AES_BLOCK_SIZE]); +void aes_decrypt_aesni(const u32 inv_rndkeys[], int nrounds, + u8 out[AES_BLOCK_SIZE], const u8 in[AES_BLOCK_SIZE]); + +/* + * Expand an AES key using AES-NI if supported and usable or generic code + * otherwise. The expanded key format is compatible between the two cases. The + * outputs are @k->rndkeys (required) and @inv_k->inv_rndkeys (optional). + * + * We could just always use the generic key expansion code. AES key expansion + * is usually less performance-critical than AES en/decryption. However, + * there's still *some* value in speed here, as well as in non-key-dependent + * execution time which AES-NI provides. So, do use AES-NI to expand AES-128 + * and AES-256 keys. (Don't bother with AES-192, as it's almost never used.) + */ +static void aes_preparekey_arch(union aes_enckey_arch *k, + union aes_invkey_arch *inv_k, + const u8 *in_key, int key_len, int nrounds) +{ + u32 *rndkeys = k->rndkeys; + u32 *inv_rndkeys = inv_k ? inv_k->inv_rndkeys : NULL; + + if (static_branch_likely(&have_aes) && key_len != AES_KEYSIZE_192 && + irq_fpu_usable()) { + kernel_fpu_begin(); + if (key_len == AES_KEYSIZE_128) + aes128_expandkey_aesni(rndkeys, inv_rndkeys, in_key); + else + aes256_expandkey_aesni(rndkeys, inv_rndkeys, in_key); + kernel_fpu_end(); + } else { + aes_expandkey_generic(rndkeys, inv_rndkeys, in_key, key_len); + } +} + +static void aes_encrypt_arch(const struct aes_enckey *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + if (static_branch_likely(&have_aes) && irq_fpu_usable()) { + kernel_fpu_begin(); + aes_encrypt_aesni(key->k.rndkeys, key->nrounds, out, in); + kernel_fpu_end(); + } else { + aes_encrypt_generic(key->k.rndkeys, key->nrounds, out, in); + } +} + +static void aes_decrypt_arch(const struct aes_key *key, + u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) +{ + if (static_branch_likely(&have_aes) && irq_fpu_usable()) { + kernel_fpu_begin(); + aes_decrypt_aesni(key->inv_k.inv_rndkeys, key->nrounds, + out, in); + kernel_fpu_end(); + } else { + aes_decrypt_generic(key->inv_k.inv_rndkeys, key->nrounds, + out, in); + } +} + +#define aes_mod_init_arch aes_mod_init_arch +static void aes_mod_init_arch(void) +{ + if (boot_cpu_has(X86_FEATURE_AES)) + static_branch_enable(&have_aes); +} From 9c941c94bcba851eb8e688a3cf7d59ce29c4eb25 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:16 -0800 Subject: [PATCH 35/53] crypto: x86/aes - Remove the superseded AES-NI crypto_cipher Remove the "aes-aesni" crypto_cipher algorithm and the code specific to its implementation. It is no longer necessary because the AES library is now optimized with x86 AES-NI, and crypto/aes.c exposes the AES library via the crypto_cipher API. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-19-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/x86/crypto/Kconfig | 2 - arch/x86/crypto/aesni-intel_asm.S | 25 ------------ arch/x86/crypto/aesni-intel_glue.c | 62 +----------------------------- 3 files changed, 1 insertion(+), 88 deletions(-) diff --git a/arch/x86/crypto/Kconfig b/arch/x86/crypto/Kconfig index ebb0838eaf30..7fb2319a0916 100644 --- a/arch/x86/crypto/Kconfig +++ b/arch/x86/crypto/Kconfig @@ -7,10 +7,8 @@ config CRYPTO_AES_NI_INTEL select CRYPTO_AEAD select CRYPTO_LIB_AES select CRYPTO_LIB_GF128MUL - select CRYPTO_ALGAPI select CRYPTO_SKCIPHER help - Block cipher: AES cipher algorithms AEAD cipher: AES with GCM Length-preserving ciphers: AES with ECB, CBC, CTS, CTR, XCTR, XTS diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S index b37881bb9f15..6abe5e38a6d7 100644 --- a/arch/x86/crypto/aesni-intel_asm.S +++ b/arch/x86/crypto/aesni-intel_asm.S @@ -436,31 +436,6 @@ SYM_FUNC_START_LOCAL(_aesni_enc4) RET SYM_FUNC_END(_aesni_enc4) -/* - * void aesni_dec (const void *ctx, u8 *dst, const u8 *src) - */ -SYM_FUNC_START(aesni_dec) - FRAME_BEGIN -#ifndef __x86_64__ - pushl KEYP - pushl KLEN - movl (FRAME_OFFSET+12)(%esp), KEYP # ctx - movl (FRAME_OFFSET+16)(%esp), OUTP # dst - movl (FRAME_OFFSET+20)(%esp), INP # src -#endif - mov 480(KEYP), KLEN # key length - add $240, KEYP - movups (INP), STATE # input - call _aesni_dec1 - movups STATE, (OUTP) #output -#ifndef __x86_64__ - popl KLEN - popl KEYP -#endif - FRAME_END - RET -SYM_FUNC_END(aesni_dec) - /* * _aesni_dec1: internal ABI * input: diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 48405e02d6e4..453e0e890041 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -60,7 +60,6 @@ static inline void *aes_align_addr(void *addr) asmlinkage void aesni_set_key(struct crypto_aes_ctx *ctx, const u8 *in_key, unsigned int key_len); asmlinkage void aesni_enc(const void *ctx, u8 *out, const u8 *in); -asmlinkage void aesni_dec(const void *ctx, u8 *out, const u8 *in); asmlinkage void aesni_ecb_enc(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in, unsigned int len); asmlinkage void aesni_ecb_dec(struct crypto_aes_ctx *ctx, u8 *out, @@ -113,39 +112,6 @@ static int aes_set_key_common(struct crypto_aes_ctx *ctx, return 0; } -static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) -{ - return aes_set_key_common(aes_ctx(crypto_tfm_ctx(tfm)), in_key, - key_len); -} - -static void aesni_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) -{ - struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm)); - - if (!crypto_simd_usable()) { - aes_encrypt(ctx, dst, src); - } else { - kernel_fpu_begin(); - aesni_enc(ctx, dst, src); - kernel_fpu_end(); - } -} - -static void aesni_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) -{ - struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm)); - - if (!crypto_simd_usable()) { - aes_decrypt(ctx, dst, src); - } else { - kernel_fpu_begin(); - aesni_dec(ctx, dst, src); - kernel_fpu_end(); - } -} - static int aesni_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int len) { @@ -544,25 +510,6 @@ static int xts_decrypt_aesni(struct skcipher_request *req) return xts_crypt(req, aesni_xts_encrypt_iv, aesni_xts_decrypt); } -static struct crypto_alg aesni_cipher_alg = { - .cra_name = "aes", - .cra_driver_name = "aes-aesni", - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = CRYPTO_AES_CTX_SIZE, - .cra_module = THIS_MODULE, - .cra_u = { - .cipher = { - .cia_min_keysize = AES_MIN_KEY_SIZE, - .cia_max_keysize = AES_MAX_KEY_SIZE, - .cia_setkey = aes_set_key, - .cia_encrypt = aesni_encrypt, - .cia_decrypt = aesni_decrypt - } - } -}; - static struct skcipher_alg aesni_skciphers[] = { { .base = { @@ -1689,14 +1636,10 @@ static int __init aesni_init(void) if (!x86_match_cpu(aesni_cpu_id)) return -ENODEV; - err = crypto_register_alg(&aesni_cipher_alg); - if (err) - return err; - err = crypto_register_skciphers(aesni_skciphers, ARRAY_SIZE(aesni_skciphers)); if (err) - goto unregister_cipher; + return err; err = crypto_register_aeads(aes_gcm_algs_aesni, ARRAY_SIZE(aes_gcm_algs_aesni)); @@ -1716,8 +1659,6 @@ unregister_avx: unregister_skciphers: crypto_unregister_skciphers(aesni_skciphers, ARRAY_SIZE(aesni_skciphers)); -unregister_cipher: - crypto_unregister_alg(&aesni_cipher_alg); return err; } @@ -1727,7 +1668,6 @@ static void __exit aesni_exit(void) ARRAY_SIZE(aes_gcm_algs_aesni)); crypto_unregister_skciphers(aesni_skciphers, ARRAY_SIZE(aesni_skciphers)); - crypto_unregister_alg(&aesni_cipher_alg); unregister_avx_algs(); } From 7f6dfeb943bf06dd55a588e992dcc108ffe3db2c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:17 -0800 Subject: [PATCH 36/53] Bluetooth: SMP: Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-20-ebiggers@kernel.org Signed-off-by: Eric Biggers --- net/bluetooth/smp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 3a1ce04a7a53..bf61e8841535 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -374,7 +374,7 @@ static int smp_h7(struct crypto_shash *tfm_cmac, const u8 w[16], static int smp_e(const u8 *k, u8 *r) { - struct crypto_aes_ctx ctx; + struct aes_enckey aes; uint8_t tmp[16], data[16]; int err; @@ -383,7 +383,7 @@ static int smp_e(const u8 *k, u8 *r) /* The most significant octet of key corresponds to k[0] */ swap_buf(k, tmp, 16); - err = aes_expandkey(&ctx, tmp, 16); + err = aes_prepareenckey(&aes, tmp, 16); if (err) { BT_ERR("cipher setkey failed: %d", err); return err; @@ -392,14 +392,14 @@ static int smp_e(const u8 *k, u8 *r) /* Most significant octet of plaintextData corresponds to data[0] */ swap_buf(r, data, 16); - aes_encrypt(&ctx, data, data); + aes_encrypt(&aes, data, data); /* Most significant octet of encryptedData corresponds to data[0] */ swap_buf(data, r, 16); SMP_DBG("r %16phN", r); - memzero_explicit(&ctx, sizeof(ctx)); + memzero_explicit(&aes, sizeof(aes)); return err; } From 1f161437c6738ed59ad67a2c67f30b2e9fdf81b4 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:18 -0800 Subject: [PATCH 37/53] chelsio: Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-21-ebiggers@kernel.org Signed-off-by: Eric Biggers --- .../ethernet/chelsio/inline_crypto/ch_ipsec/chcr_ipsec.c | 4 ++-- .../ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c | 8 ++++---- .../net/ethernet/chelsio/inline_crypto/chtls/chtls_hw.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/chelsio/inline_crypto/ch_ipsec/chcr_ipsec.c b/drivers/net/ethernet/chelsio/inline_crypto/ch_ipsec/chcr_ipsec.c index 49b57bb5fac1..074717d4bb16 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/ch_ipsec/chcr_ipsec.c +++ b/drivers/net/ethernet/chelsio/inline_crypto/ch_ipsec/chcr_ipsec.c @@ -170,7 +170,7 @@ static int ch_ipsec_setkey(struct xfrm_state *x, unsigned char *key = x->aead->alg_key; int ck_size, key_ctx_size = 0; unsigned char ghash_h[AEAD_H_SIZE]; - struct crypto_aes_ctx aes; + struct aes_enckey aes; int ret = 0; if (keylen > 3) { @@ -204,7 +204,7 @@ static int ch_ipsec_setkey(struct xfrm_state *x, /* Calculate the H = CIPH(K, 0 repeated 16 times). * It will go in key context */ - ret = aes_expandkey(&aes, key, keylen); + ret = aes_prepareenckey(&aes, key, keylen); if (ret) { sa_entry->enckey_len = 0; goto out; diff --git a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c index 4e2096e49684..b8ebb56de65e 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c +++ b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c @@ -76,7 +76,7 @@ static int chcr_ktls_save_keys(struct chcr_ktls_info *tx_info, unsigned char ghash_h[TLS_CIPHER_AES_GCM_256_TAG_SIZE]; struct tls12_crypto_info_aes_gcm_128 *info_128_gcm; struct ktls_key_ctx *kctx = &tx_info->key_ctx; - struct crypto_aes_ctx aes_ctx; + struct aes_enckey aes; unsigned char *key, *salt; switch (crypto_info->cipher_type) { @@ -138,13 +138,13 @@ static int chcr_ktls_save_keys(struct chcr_ktls_info *tx_info, * It will go in key context */ - ret = aes_expandkey(&aes_ctx, key, keylen); + ret = aes_prepareenckey(&aes, key, keylen); if (ret) goto out; memset(ghash_h, 0, ghash_size); - aes_encrypt(&aes_ctx, ghash_h, ghash_h); - memzero_explicit(&aes_ctx, sizeof(aes_ctx)); + aes_encrypt(&aes, ghash_h, ghash_h); + memzero_explicit(&aes, sizeof(aes)); /* fill the Key context */ if (direction == TLS_OFFLOAD_CTX_DIR_TX) { diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_hw.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_hw.c index fab6df21f01c..d84473ca844d 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_hw.c +++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_hw.c @@ -247,7 +247,7 @@ static int chtls_key_info(struct chtls_sock *csk, unsigned char *key_p, *salt; unsigned char ghash_h[AEAD_H_SIZE]; int ck_size, key_ctx_size, kctx_mackey_size, salt_size; - struct crypto_aes_ctx aes; + struct aes_enckey aes; int ret; key_ctx_size = sizeof(struct _key_ctx) + @@ -291,7 +291,7 @@ static int chtls_key_info(struct chtls_sock *csk, /* Calculate the H = CIPH(K, 0 repeated 16 times). * It will go in key context */ - ret = aes_expandkey(&aes, key, keylen); + ret = aes_prepareenckey(&aes, key, keylen); if (ret) return ret; From 12b03936a02fd17fd7c7a9711c225f34332c6c57 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:19 -0800 Subject: [PATCH 38/53] net: phy: mscc: macsec: Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-22-ebiggers@kernel.org Signed-off-by: Eric Biggers --- drivers/net/phy/mscc/mscc_macsec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/phy/mscc/mscc_macsec.c b/drivers/net/phy/mscc/mscc_macsec.c index 4f39ba63a9a9..9a38a29cf397 100644 --- a/drivers/net/phy/mscc/mscc_macsec.c +++ b/drivers/net/phy/mscc/mscc_macsec.c @@ -504,15 +504,15 @@ static u32 vsc8584_macsec_flow_context_id(struct macsec_flow *flow) static int vsc8584_macsec_derive_key(const u8 *key, u16 key_len, u8 hkey[16]) { const u8 input[AES_BLOCK_SIZE] = {0}; - struct crypto_aes_ctx ctx; + struct aes_enckey aes; int ret; - ret = aes_expandkey(&ctx, key, key_len); + ret = aes_prepareenckey(&aes, key, key_len); if (ret) return ret; - aes_encrypt(&ctx, hkey, input); - memzero_explicit(&ctx, sizeof(ctx)); + aes_encrypt(&aes, hkey, input); + memzero_explicit(&aes, sizeof(aes)); return 0; } From 60fb28ca028634210e12a4e674d3563f741e617c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:20 -0800 Subject: [PATCH 39/53] staging: rtl8723bs: core: Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-23-ebiggers@kernel.org Signed-off-by: Eric Biggers --- drivers/staging/rtl8723bs/core/rtw_security.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_security.c b/drivers/staging/rtl8723bs/core/rtw_security.c index 2f941ffbd465..8ee5bed252bf 100644 --- a/drivers/staging/rtl8723bs/core/rtw_security.c +++ b/drivers/staging/rtl8723bs/core/rtw_security.c @@ -637,11 +637,11 @@ exit: /****************************************/ static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext) { - struct crypto_aes_ctx ctx; + struct aes_enckey aes; - aes_expandkey(&ctx, key, 16); - aes_encrypt(&ctx, ciphertext, data); - memzero_explicit(&ctx, sizeof(ctx)); + aes_prepareenckey(&aes, key, 16); + aes_encrypt(&aes, ciphertext, data); + memzero_explicit(&aes, sizeof(aes)); } /************************************************/ @@ -1406,13 +1406,13 @@ static void gf_mulx(u8 *pad) static int omac1_aes_128_vector(u8 *key, size_t num_elem, u8 *addr[], size_t *len, u8 *mac) { - struct crypto_aes_ctx ctx; + struct aes_enckey aes; u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; u8 *pos, *end; size_t i, e, left, total_len; int ret; - ret = aes_expandkey(&ctx, key, 16); + ret = aes_prepareenckey(&aes, key, 16); if (ret) return -1; memset(cbc, 0, AES_BLOCK_SIZE); @@ -1436,12 +1436,12 @@ static int omac1_aes_128_vector(u8 *key, size_t num_elem, } } if (left > AES_BLOCK_SIZE) - aes_encrypt(&ctx, cbc, cbc); + aes_encrypt(&aes, cbc, cbc); left -= AES_BLOCK_SIZE; } memset(pad, 0, AES_BLOCK_SIZE); - aes_encrypt(&ctx, pad, pad); + aes_encrypt(&aes, pad, pad); gf_mulx(pad); if (left || total_len == 0) { @@ -1459,8 +1459,8 @@ static int omac1_aes_128_vector(u8 *key, size_t num_elem, for (i = 0; i < AES_BLOCK_SIZE; i++) pad[i] ^= cbc[i]; - aes_encrypt(&ctx, pad, mac); - memzero_explicit(&ctx, sizeof(ctx)); + aes_encrypt(&aes, pad, mac); + memzero_explicit(&aes, sizeof(aes)); return 0; } From cf4b7b99a6058227351164edc8f81d90771ac4ef Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:21 -0800 Subject: [PATCH 40/53] crypto: arm/ghash - Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-24-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/arm/crypto/ghash-ce-glue.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/arm/crypto/ghash-ce-glue.c b/arch/arm/crypto/ghash-ce-glue.c index a52dcc8c1e33..454adcc62cc6 100644 --- a/arch/arm/crypto/ghash-ce-glue.c +++ b/arch/arm/crypto/ghash-ce-glue.c @@ -204,20 +204,24 @@ static int gcm_aes_setkey(struct crypto_aead *tfm, const u8 *inkey, unsigned int keylen) { struct gcm_key *ctx = crypto_aead_ctx(tfm); - struct crypto_aes_ctx aes_ctx; + struct aes_enckey aes_key; be128 h, k; int ret; - ret = aes_expandkey(&aes_ctx, inkey, keylen); + ret = aes_prepareenckey(&aes_key, inkey, keylen); if (ret) return -EINVAL; - aes_encrypt(&aes_ctx, (u8 *)&k, (u8[AES_BLOCK_SIZE]){}); + aes_encrypt(&aes_key, (u8 *)&k, (u8[AES_BLOCK_SIZE]){}); - memcpy(ctx->rk, aes_ctx.key_enc, sizeof(ctx->rk)); + /* + * Note: this assumes that the arm implementation of the AES library + * stores the standard round keys in k.rndkeys. + */ + memcpy(ctx->rk, aes_key.k.rndkeys, sizeof(ctx->rk)); ctx->rounds = 6 + keylen / 4; - memzero_explicit(&aes_ctx, sizeof(aes_ctx)); + memzero_explicit(&aes_key, sizeof(aes_key)); ghash_reflect(ctx->h[0], &k); From 370960c153db82fbdd55539be4d4eb41ef3a7e40 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:22 -0800 Subject: [PATCH 41/53] crypto: arm64/ghash - Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-25-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/arm64/crypto/ghash-ce-glue.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/arch/arm64/crypto/ghash-ce-glue.c b/arch/arm64/crypto/ghash-ce-glue.c index ef249d06c92c..63bb9e062251 100644 --- a/arch/arm64/crypto/ghash-ce-glue.c +++ b/arch/arm64/crypto/ghash-ce-glue.c @@ -40,7 +40,7 @@ struct arm_ghash_desc_ctx { }; struct gcm_aes_ctx { - struct crypto_aes_ctx aes_key; + struct aes_enckey aes_key; u8 nonce[RFC4106_NONCE_SIZE]; struct ghash_key ghash_key; }; @@ -186,18 +186,6 @@ static struct shash_alg ghash_alg = { .statesize = sizeof(struct ghash_desc_ctx), }; -static int num_rounds(struct crypto_aes_ctx *ctx) -{ - /* - * # of rounds specified by AES: - * 128 bit key 10 rounds - * 192 bit key 12 rounds - * 256 bit key 14 rounds - * => n byte key => 6 + (n/4) rounds - */ - return 6 + ctx->key_length / 4; -} - static int gcm_aes_setkey(struct crypto_aead *tfm, const u8 *inkey, unsigned int keylen) { @@ -206,7 +194,7 @@ static int gcm_aes_setkey(struct crypto_aead *tfm, const u8 *inkey, be128 h; int ret; - ret = aes_expandkey(&ctx->aes_key, inkey, keylen); + ret = aes_prepareenckey(&ctx->aes_key, inkey, keylen); if (ret) return -EINVAL; @@ -296,7 +284,6 @@ static int gcm_encrypt(struct aead_request *req, char *iv, int assoclen) { struct crypto_aead *aead = crypto_aead_reqtfm(req); struct gcm_aes_ctx *ctx = crypto_aead_ctx(aead); - int nrounds = num_rounds(&ctx->aes_key); struct skcipher_walk walk; u8 buf[AES_BLOCK_SIZE]; u64 dg[2] = {}; @@ -331,8 +318,8 @@ static int gcm_encrypt(struct aead_request *req, char *iv, int assoclen) scoped_ksimd() pmull_gcm_encrypt(nbytes, dst, src, ctx->ghash_key.h, - dg, iv, ctx->aes_key.key_enc, nrounds, - tag); + dg, iv, ctx->aes_key.k.rndkeys, + ctx->aes_key.nrounds, tag); if (unlikely(!nbytes)) break; @@ -359,7 +346,6 @@ static int gcm_decrypt(struct aead_request *req, char *iv, int assoclen) struct crypto_aead *aead = crypto_aead_reqtfm(req); struct gcm_aes_ctx *ctx = crypto_aead_ctx(aead); unsigned int authsize = crypto_aead_authsize(aead); - int nrounds = num_rounds(&ctx->aes_key); struct skcipher_walk walk; u8 otag[AES_BLOCK_SIZE]; u8 buf[AES_BLOCK_SIZE]; @@ -401,8 +387,9 @@ static int gcm_decrypt(struct aead_request *req, char *iv, int assoclen) scoped_ksimd() ret = pmull_gcm_decrypt(nbytes, dst, src, ctx->ghash_key.h, - dg, iv, ctx->aes_key.key_enc, - nrounds, tag, otag, authsize); + dg, iv, ctx->aes_key.k.rndkeys, + ctx->aes_key.nrounds, tag, otag, + authsize); if (unlikely(!nbytes)) break; From 104a9526e1448dc45b96534e2d78d41b3ecac3f9 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:23 -0800 Subject: [PATCH 42/53] crypto: x86/aes-gcm - Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Since this changes the format of the AES-GCM key structures that are used by the AES-GCM assembly code, the offsets in the assembly code had to be updated to match. Note that the new key structures are smaller, since the decryption round keys are no longer unnecessarily included. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-26-ebiggers@kernel.org Signed-off-by: Eric Biggers --- arch/x86/crypto/aes-gcm-aesni-x86_64.S | 33 +++++++-------- arch/x86/crypto/aes-gcm-vaes-avx2.S | 21 +++++----- arch/x86/crypto/aes-gcm-vaes-avx512.S | 25 ++++++----- arch/x86/crypto/aesni-intel_glue.c | 57 +++++++++++--------------- 4 files changed, 67 insertions(+), 69 deletions(-) diff --git a/arch/x86/crypto/aes-gcm-aesni-x86_64.S b/arch/x86/crypto/aes-gcm-aesni-x86_64.S index 7c8a8a32bd3c..6b2abb76827e 100644 --- a/arch/x86/crypto/aes-gcm-aesni-x86_64.S +++ b/arch/x86/crypto/aes-gcm-aesni-x86_64.S @@ -143,10 +143,11 @@ .octa 0 // Offsets in struct aes_gcm_key_aesni -#define OFFSETOF_AESKEYLEN 480 -#define OFFSETOF_H_POWERS 496 -#define OFFSETOF_H_POWERS_XORED 624 -#define OFFSETOF_H_TIMES_X64 688 +#define OFFSETOF_AESKEYLEN 0 +#define OFFSETOF_AESROUNDKEYS 16 +#define OFFSETOF_H_POWERS 272 +#define OFFSETOF_H_POWERS_XORED 400 +#define OFFSETOF_H_TIMES_X64 464 .text @@ -505,9 +506,9 @@ // Encrypt an all-zeroes block to get the raw hash subkey. movl OFFSETOF_AESKEYLEN(KEY), %eax - lea 6*16(KEY,%rax,4), RNDKEYLAST_PTR - movdqa (KEY), H_POW1 // Zero-th round key XOR all-zeroes block - lea 16(KEY), %rax + lea OFFSETOF_AESROUNDKEYS+6*16(KEY,%rax,4), RNDKEYLAST_PTR + movdqa OFFSETOF_AESROUNDKEYS(KEY), H_POW1 + lea OFFSETOF_AESROUNDKEYS+16(KEY), %rax 1: aesenc (%rax), H_POW1 add $16, %rax @@ -624,7 +625,7 @@ // the zero-th AES round key. Clobbers TMP0 and TMP1. .macro _ctr_begin_8x movq .Lone(%rip), TMP0 - movdqa (KEY), TMP1 // zero-th round key + movdqa OFFSETOF_AESROUNDKEYS(KEY), TMP1 // zero-th round key .irp i, 0,1,2,3,4,5,6,7 _vpshufb BSWAP_MASK, LE_CTR, AESDATA\i pxor TMP1, AESDATA\i @@ -726,7 +727,7 @@ movdqu (LE_CTR_PTR), LE_CTR movl OFFSETOF_AESKEYLEN(KEY), AESKEYLEN - lea 6*16(KEY,AESKEYLEN64,4), RNDKEYLAST_PTR + lea OFFSETOF_AESROUNDKEYS+6*16(KEY,AESKEYLEN64,4), RNDKEYLAST_PTR // If there are at least 8*16 bytes of data, then continue into the main // loop, which processes 8*16 bytes of data per iteration. @@ -745,7 +746,7 @@ .if \enc // Encrypt the first 8 plaintext blocks. _ctr_begin_8x - lea 16(KEY), %rsi + lea OFFSETOF_AESROUNDKEYS+16(KEY), %rsi .p2align 4 1: movdqa (%rsi), TMP0 @@ -767,7 +768,7 @@ // Generate the next set of 8 counter blocks and start encrypting them. _ctr_begin_8x - lea 16(KEY), %rsi + lea OFFSETOF_AESROUNDKEYS+16(KEY), %rsi // Do a round of AES, and start the GHASH update of 8 ciphertext blocks // by doing the unreduced multiplication for the first ciphertext block. @@ -869,7 +870,7 @@ // Encrypt the next counter block. _vpshufb BSWAP_MASK, LE_CTR, TMP0 paddd ONE, LE_CTR - pxor (KEY), TMP0 + pxor OFFSETOF_AESROUNDKEYS(KEY), TMP0 lea -6*16(RNDKEYLAST_PTR), %rsi // Reduce code size cmp $24, AESKEYLEN jl 128f // AES-128? @@ -926,8 +927,8 @@ // Encrypt a counter block for the last time. pshufb BSWAP_MASK, LE_CTR - pxor (KEY), LE_CTR - lea 16(KEY), %rsi + pxor OFFSETOF_AESROUNDKEYS(KEY), LE_CTR + lea OFFSETOF_AESROUNDKEYS+16(KEY), %rsi 1: aesenc (%rsi), LE_CTR add $16, %rsi @@ -1038,12 +1039,12 @@ // Make %rax point to the 6th from last AES round key. (Using signed // byte offsets -7*16 through 6*16 decreases code size.) - lea (KEY,AESKEYLEN64,4), %rax + lea OFFSETOF_AESROUNDKEYS(KEY,AESKEYLEN64,4), %rax // AES-encrypt the counter block and also multiply GHASH_ACC by H^1. // Interleave the AES and GHASH instructions to improve performance. pshufb BSWAP_MASK, %xmm0 - pxor (KEY), %xmm0 + pxor OFFSETOF_AESROUNDKEYS(KEY), %xmm0 cmp $24, AESKEYLEN jl 128f // AES-128? je 192f // AES-192? diff --git a/arch/x86/crypto/aes-gcm-vaes-avx2.S b/arch/x86/crypto/aes-gcm-vaes-avx2.S index 93c9504a488f..9cc387957fa9 100644 --- a/arch/x86/crypto/aes-gcm-vaes-avx2.S +++ b/arch/x86/crypto/aes-gcm-vaes-avx2.S @@ -122,8 +122,9 @@ .octa 2 // Offsets in struct aes_gcm_key_vaes_avx2 -#define OFFSETOF_AESKEYLEN 480 -#define OFFSETOF_H_POWERS 512 +#define OFFSETOF_AESKEYLEN 0 +#define OFFSETOF_AESROUNDKEYS 16 +#define OFFSETOF_H_POWERS 288 #define NUM_H_POWERS 8 #define OFFSETOFEND_H_POWERS (OFFSETOF_H_POWERS + (NUM_H_POWERS * 16)) #define OFFSETOF_H_POWERS_XORED OFFSETOFEND_H_POWERS @@ -240,9 +241,9 @@ SYM_FUNC_START(aes_gcm_precompute_vaes_avx2) // Encrypt an all-zeroes block to get the raw hash subkey. movl OFFSETOF_AESKEYLEN(KEY), %eax - lea 6*16(KEY,%rax,4), RNDKEYLAST_PTR - vmovdqu (KEY), H_CUR_XMM // Zero-th round key XOR all-zeroes block - lea 16(KEY), %rax + lea OFFSETOF_AESROUNDKEYS+6*16(KEY,%rax,4), RNDKEYLAST_PTR + vmovdqu OFFSETOF_AESROUNDKEYS(KEY), H_CUR_XMM + lea OFFSETOF_AESROUNDKEYS+16(KEY), %rax 1: vaesenc (%rax), H_CUR_XMM, H_CUR_XMM add $16, %rax @@ -635,7 +636,7 @@ SYM_FUNC_END(aes_gcm_aad_update_vaes_avx2) // the last AES round. Clobbers %rax and TMP0. .macro _aesenc_loop vecs:vararg _ctr_begin \vecs - lea 16(KEY), %rax + lea OFFSETOF_AESROUNDKEYS+16(KEY), %rax .Laesenc_loop\@: vbroadcasti128 (%rax), TMP0 _vaesenc TMP0, \vecs @@ -768,8 +769,8 @@ SYM_FUNC_END(aes_gcm_aad_update_vaes_avx2) // Make RNDKEYLAST_PTR point to the last AES round key. This is the // round key with index 10, 12, or 14 for AES-128, AES-192, or AES-256 // respectively. Then load the zero-th and last round keys. - lea 6*16(KEY,AESKEYLEN64,4), RNDKEYLAST_PTR - vbroadcasti128 (KEY), RNDKEY0 + lea OFFSETOF_AESROUNDKEYS+6*16(KEY,AESKEYLEN64,4), RNDKEYLAST_PTR + vbroadcasti128 OFFSETOF_AESROUNDKEYS(KEY), RNDKEY0 vbroadcasti128 (RNDKEYLAST_PTR), RNDKEYLAST // Finish initializing LE_CTR by adding 1 to the second block. @@ -1069,12 +1070,12 @@ SYM_FUNC_END(aes_gcm_aad_update_vaes_avx2) .endif // Make %rax point to the last AES round key for the chosen AES variant. - lea 6*16(KEY,AESKEYLEN64,4), %rax + lea OFFSETOF_AESROUNDKEYS+6*16(KEY,AESKEYLEN64,4), %rax // Start the AES encryption of the counter block by swapping the counter // block to big-endian and XOR-ing it with the zero-th AES round key. vpshufb BSWAP_MASK, LE_CTR, %xmm0 - vpxor (KEY), %xmm0, %xmm0 + vpxor OFFSETOF_AESROUNDKEYS(KEY), %xmm0, %xmm0 // Complete the AES encryption and multiply GHASH_ACC by H^1. // Interleave the AES and GHASH instructions to improve performance. diff --git a/arch/x86/crypto/aes-gcm-vaes-avx512.S b/arch/x86/crypto/aes-gcm-vaes-avx512.S index 06b71314d65c..516747db4659 100644 --- a/arch/x86/crypto/aes-gcm-vaes-avx512.S +++ b/arch/x86/crypto/aes-gcm-vaes-avx512.S @@ -86,10 +86,13 @@ #define NUM_H_POWERS 16 // Offset to AES key length (in bytes) in the key struct -#define OFFSETOF_AESKEYLEN 480 +#define OFFSETOF_AESKEYLEN 0 + +// Offset to AES round keys in the key struct +#define OFFSETOF_AESROUNDKEYS 16 // Offset to start of hash key powers array in the key struct -#define OFFSETOF_H_POWERS 512 +#define OFFSETOF_H_POWERS 320 // Offset to end of hash key powers array in the key struct. // @@ -301,9 +304,9 @@ SYM_FUNC_START(aes_gcm_precompute_vaes_avx512) // Encrypt an all-zeroes block to get the raw hash subkey. movl OFFSETOF_AESKEYLEN(KEY), %eax - lea 6*16(KEY,%rax,4), RNDKEYLAST_PTR - vmovdqu (KEY), %xmm0 // Zero-th round key XOR all-zeroes block - add $16, KEY + lea OFFSETOF_AESROUNDKEYS+6*16(KEY,%rax,4), RNDKEYLAST_PTR + vmovdqu OFFSETOF_AESROUNDKEYS(KEY), %xmm0 + add $OFFSETOF_AESROUNDKEYS+16, KEY 1: vaesenc (KEY), %xmm0, %xmm0 add $16, KEY @@ -790,8 +793,8 @@ SYM_FUNC_END(aes_gcm_aad_update_vaes_avx512) // Make RNDKEYLAST_PTR point to the last AES round key. This is the // round key with index 10, 12, or 14 for AES-128, AES-192, or AES-256 // respectively. Then load the zero-th and last round keys. - lea 6*16(KEY,AESKEYLEN64,4), RNDKEYLAST_PTR - vbroadcasti32x4 (KEY), RNDKEY0 + lea OFFSETOF_AESROUNDKEYS+6*16(KEY,AESKEYLEN64,4), RNDKEYLAST_PTR + vbroadcasti32x4 OFFSETOF_AESROUNDKEYS(KEY), RNDKEY0 vbroadcasti32x4 (RNDKEYLAST_PTR), RNDKEYLAST // Finish initializing LE_CTR by adding [0, 1, ...] to its low words. @@ -834,7 +837,7 @@ SYM_FUNC_END(aes_gcm_aad_update_vaes_avx512) // Encrypt the first 4 vectors of plaintext blocks. Leave the resulting // ciphertext in GHASHDATA[0-3] for GHASH. _ctr_begin_4x - lea 16(KEY), %rax + lea OFFSETOF_AESROUNDKEYS+16(KEY), %rax 1: vbroadcasti32x4 (%rax), RNDKEY _vaesenc_4x RNDKEY @@ -957,7 +960,7 @@ SYM_FUNC_END(aes_gcm_aad_update_vaes_avx512) vpshufb BSWAP_MASK, LE_CTR, %zmm0 vpaddd LE_CTR_INC, LE_CTR, LE_CTR vpxord RNDKEY0, %zmm0, %zmm0 - lea 16(KEY), %rax + lea OFFSETOF_AESROUNDKEYS+16(KEY), %rax 1: vbroadcasti32x4 (%rax), RNDKEY vaesenc RNDKEY, %zmm0, %zmm0 @@ -1087,12 +1090,12 @@ SYM_FUNC_END(aes_gcm_aad_update_vaes_avx512) .endif // Make %rax point to the last AES round key for the chosen AES variant. - lea 6*16(KEY,AESKEYLEN64,4), %rax + lea OFFSETOF_AESROUNDKEYS+6*16(KEY,AESKEYLEN64,4), %rax // Start the AES encryption of the counter block by swapping the counter // block to big-endian and XOR-ing it with the zero-th AES round key. vpshufb BSWAP_MASK, LE_CTR, %xmm0 - vpxor (KEY), %xmm0, %xmm0 + vpxor OFFSETOF_AESROUNDKEYS(KEY), %xmm0, %xmm0 // Complete the AES encryption and multiply GHASH_ACC by H^1. // Interleave the AES and GHASH instructions to improve performance. diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 453e0e890041..e6c38d1d8a92 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -780,7 +780,7 @@ DEFINE_AVX_SKCIPHER_ALGS(vaes_avx512, "vaes-avx512", 800); /* The common part of the x86_64 AES-GCM key struct */ struct aes_gcm_key { /* Expanded AES key and the AES key length in bytes */ - struct crypto_aes_ctx aes_key; + struct aes_enckey aes_key; /* RFC4106 nonce (used only by the rfc4106 algorithms) */ u32 rfc4106_nonce; @@ -789,11 +789,10 @@ struct aes_gcm_key { /* Key struct used by the AES-NI implementations of AES-GCM */ struct aes_gcm_key_aesni { /* - * Common part of the key. The assembly code requires 16-byte alignment - * for the round keys; we get this by them being located at the start of - * the struct and the whole struct being 16-byte aligned. + * Common part of the key. 16-byte alignment is required by the + * assembly code. */ - struct aes_gcm_key base; + struct aes_gcm_key base __aligned(16); /* * Powers of the hash key H^8 through H^1. These are 128-bit values. @@ -824,10 +823,9 @@ struct aes_gcm_key_aesni { struct aes_gcm_key_vaes_avx2 { /* * Common part of the key. The assembly code prefers 16-byte alignment - * for the round keys; we get this by them being located at the start of - * the struct and the whole struct being 32-byte aligned. + * for this. */ - struct aes_gcm_key base; + struct aes_gcm_key base __aligned(16); /* * Powers of the hash key H^8 through H^1. These are 128-bit values. @@ -854,10 +852,9 @@ struct aes_gcm_key_vaes_avx2 { struct aes_gcm_key_vaes_avx512 { /* * Common part of the key. The assembly code prefers 16-byte alignment - * for the round keys; we get this by them being located at the start of - * the struct and the whole struct being 64-byte aligned. + * for this. */ - struct aes_gcm_key base; + struct aes_gcm_key base __aligned(16); /* * Powers of the hash key H^16 through H^1. These are 128-bit values. @@ -1182,26 +1179,26 @@ static int gcm_setkey(struct crypto_aead *tfm, const u8 *raw_key, } /* The assembly code assumes the following offsets. */ - BUILD_BUG_ON(offsetof(struct aes_gcm_key_aesni, base.aes_key.key_enc) != 0); - BUILD_BUG_ON(offsetof(struct aes_gcm_key_aesni, base.aes_key.key_length) != 480); - BUILD_BUG_ON(offsetof(struct aes_gcm_key_aesni, h_powers) != 496); - BUILD_BUG_ON(offsetof(struct aes_gcm_key_aesni, h_powers_xored) != 624); - BUILD_BUG_ON(offsetof(struct aes_gcm_key_aesni, h_times_x64) != 688); - BUILD_BUG_ON(offsetof(struct aes_gcm_key_vaes_avx2, base.aes_key.key_enc) != 0); - BUILD_BUG_ON(offsetof(struct aes_gcm_key_vaes_avx2, base.aes_key.key_length) != 480); - BUILD_BUG_ON(offsetof(struct aes_gcm_key_vaes_avx2, h_powers) != 512); - BUILD_BUG_ON(offsetof(struct aes_gcm_key_vaes_avx2, h_powers_xored) != 640); - BUILD_BUG_ON(offsetof(struct aes_gcm_key_vaes_avx512, base.aes_key.key_enc) != 0); - BUILD_BUG_ON(offsetof(struct aes_gcm_key_vaes_avx512, base.aes_key.key_length) != 480); - BUILD_BUG_ON(offsetof(struct aes_gcm_key_vaes_avx512, h_powers) != 512); - BUILD_BUG_ON(offsetof(struct aes_gcm_key_vaes_avx512, padding) != 768); + static_assert(offsetof(struct aes_gcm_key_aesni, base.aes_key.len) == 0); + static_assert(offsetof(struct aes_gcm_key_aesni, base.aes_key.k.rndkeys) == 16); + static_assert(offsetof(struct aes_gcm_key_aesni, h_powers) == 272); + static_assert(offsetof(struct aes_gcm_key_aesni, h_powers_xored) == 400); + static_assert(offsetof(struct aes_gcm_key_aesni, h_times_x64) == 464); + static_assert(offsetof(struct aes_gcm_key_vaes_avx2, base.aes_key.len) == 0); + static_assert(offsetof(struct aes_gcm_key_vaes_avx2, base.aes_key.k.rndkeys) == 16); + static_assert(offsetof(struct aes_gcm_key_vaes_avx2, h_powers) == 288); + static_assert(offsetof(struct aes_gcm_key_vaes_avx2, h_powers_xored) == 416); + static_assert(offsetof(struct aes_gcm_key_vaes_avx512, base.aes_key.len) == 0); + static_assert(offsetof(struct aes_gcm_key_vaes_avx512, base.aes_key.k.rndkeys) == 16); + static_assert(offsetof(struct aes_gcm_key_vaes_avx512, h_powers) == 320); + static_assert(offsetof(struct aes_gcm_key_vaes_avx512, padding) == 576); + + err = aes_prepareenckey(&key->aes_key, raw_key, keylen); + if (err) + return err; if (likely(crypto_simd_usable())) { - err = aes_check_keylen(keylen); - if (err) - return err; kernel_fpu_begin(); - aesni_set_key(&key->aes_key, raw_key, keylen); aes_gcm_precompute(key, flags); kernel_fpu_end(); } else { @@ -1215,10 +1212,6 @@ static int gcm_setkey(struct crypto_aead *tfm, const u8 *raw_key, be128 h; int i; - err = aes_expandkey(&key->aes_key, raw_key, keylen); - if (err) - return err; - /* Encrypt the all-zeroes block to get the hash key H^1 */ aes_encrypt(&key->aes_key, (u8 *)&h1, (u8 *)&h1); From 0f5f4961ae53d41da5c3d3d37be796d72b38b4af Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:24 -0800 Subject: [PATCH 43/53] crypto: ccp - Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-27-ebiggers@kernel.org Signed-off-by: Eric Biggers --- drivers/crypto/ccp/ccp-crypto-aes-cmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c index d8426bdf3190..71480f7e6f6b 100644 --- a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c +++ b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c @@ -261,7 +261,7 @@ static int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, ccp_crypto_ahash_alg(crypto_ahash_tfm(tfm)); u64 k0_hi, k0_lo, k1_hi, k1_lo, k2_hi, k2_lo; u64 rb_hi = 0x00, rb_lo = 0x87; - struct crypto_aes_ctx aes; + struct aes_enckey aes; __be64 *gk; int ret; @@ -284,7 +284,7 @@ static int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, ctx->u.aes.key_len = 0; /* Set the key for the AES cipher used to generate the keys */ - ret = aes_expandkey(&aes, key, key_len); + ret = aes_prepareenckey(&aes, key, key_len); if (ret) return ret; From cafa7a0b6c90b5ef75ae8ffbdd5ff0f7191709d8 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:25 -0800 Subject: [PATCH 44/53] crypto: chelsio - Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_key and struct aes_enckey). In encryption-only use cases, this eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. Likewise for decryption. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-28-ebiggers@kernel.org Signed-off-by: Eric Biggers --- drivers/crypto/chelsio/chcr_algo.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c index 22cbc343198a..6dec42282768 100644 --- a/drivers/crypto/chelsio/chcr_algo.c +++ b/drivers/crypto/chelsio/chcr_algo.c @@ -1028,7 +1028,7 @@ static int chcr_update_tweak(struct skcipher_request *req, u8 *iv, struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm)); struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); - struct crypto_aes_ctx aes; + struct aes_key aes; int ret, i; u8 *key; unsigned int keylen; @@ -1044,9 +1044,9 @@ static int chcr_update_tweak(struct skcipher_request *req, u8 *iv, */ if (KEY_CONTEXT_CK_SIZE_G(ntohl(ablkctx->key_ctx_hdr)) == CHCR_KEYCTX_CIPHER_KEY_SIZE_192) - ret = aes_expandkey(&aes, key, keylen - 8); + ret = aes_preparekey(&aes, key, keylen - 8); else - ret = aes_expandkey(&aes, key, keylen); + ret = aes_preparekey(&aes, key, keylen); if (ret) return ret; aes_encrypt(&aes, iv, iv); @@ -3406,7 +3406,7 @@ static int chcr_gcm_setkey(struct crypto_aead *aead, const u8 *key, struct chcr_gcm_ctx *gctx = GCM_CTX(aeadctx); unsigned int ck_size; int ret = 0, key_ctx_size = 0; - struct crypto_aes_ctx aes; + struct aes_enckey aes; aeadctx->enckey_len = 0; crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK); @@ -3444,7 +3444,7 @@ static int chcr_gcm_setkey(struct crypto_aead *aead, const u8 *key, /* Calculate the H = CIPH(K, 0 repeated 16 times). * It will go in key context */ - ret = aes_expandkey(&aes, key, keylen); + ret = aes_prepareenckey(&aes, key, keylen); if (ret) { aeadctx->enckey_len = 0; goto out; From 9b95f3a4c9b8baf9fc4c2b8776f8285c05e594f5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:26 -0800 Subject: [PATCH 45/53] crypto: crypto4xx - Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-29-ebiggers@kernel.org Signed-off-by: Eric Biggers --- drivers/crypto/amcc/crypto4xx_alg.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/amcc/crypto4xx_alg.c b/drivers/crypto/amcc/crypto4xx_alg.c index 38e8a61e9166..3177dc4f5f7b 100644 --- a/drivers/crypto/amcc/crypto4xx_alg.c +++ b/drivers/crypto/amcc/crypto4xx_alg.c @@ -491,19 +491,19 @@ static int crypto4xx_aes_gcm_validate_keylen(unsigned int keylen) static int crypto4xx_compute_gcm_hash_key_sw(__le32 *hash_start, const u8 *key, unsigned int keylen) { - struct crypto_aes_ctx ctx; + struct aes_enckey aes; uint8_t src[16] = { 0 }; int rc; - rc = aes_expandkey(&ctx, key, keylen); + rc = aes_prepareenckey(&aes, key, keylen); if (rc) { - pr_err("aes_expandkey() failed: %d\n", rc); + pr_err("aes_prepareenckey() failed: %d\n", rc); return rc; } - aes_encrypt(&ctx, src, src); + aes_encrypt(&aes, src, src); crypto4xx_memcpy_to_le32(hash_start, src, 16); - memzero_explicit(&ctx, sizeof(ctx)); + memzero_explicit(&aes, sizeof(aes)); return 0; } From b2c15db74a379a50d723002799c3db0c6781c75a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:27 -0800 Subject: [PATCH 46/53] crypto: drbg - Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-30-ebiggers@kernel.org Signed-off-by: Eric Biggers --- crypto/df_sp80090a.c | 30 ++++++++++------------------- crypto/drbg.c | 12 ++++++------ drivers/crypto/xilinx/xilinx-trng.c | 8 ++++---- include/crypto/df_sp80090a.h | 2 +- 4 files changed, 21 insertions(+), 31 deletions(-) diff --git a/crypto/df_sp80090a.c b/crypto/df_sp80090a.c index dc63b31a93fc..b8134be6f7ad 100644 --- a/crypto/df_sp80090a.c +++ b/crypto/df_sp80090a.c @@ -14,27 +14,17 @@ #include #include -static void drbg_kcapi_symsetkey(struct crypto_aes_ctx *aesctx, - const unsigned char *key, - u8 keylen); -static void drbg_kcapi_symsetkey(struct crypto_aes_ctx *aesctx, - const unsigned char *key, u8 keylen) -{ - aes_expandkey(aesctx, key, keylen); -} - -static void drbg_kcapi_sym(struct crypto_aes_ctx *aesctx, - unsigned char *outval, +static void drbg_kcapi_sym(struct aes_enckey *aeskey, unsigned char *outval, const struct drbg_string *in, u8 blocklen_bytes) { /* there is only component in *in */ BUG_ON(in->len < blocklen_bytes); - aes_encrypt(aesctx, outval, in->buf); + aes_encrypt(aeskey, outval, in->buf); } /* BCC function for CTR DRBG as defined in 10.4.3 */ -static void drbg_ctr_bcc(struct crypto_aes_ctx *aesctx, +static void drbg_ctr_bcc(struct aes_enckey *aeskey, unsigned char *out, const unsigned char *key, struct list_head *in, u8 blocklen_bytes, @@ -47,7 +37,7 @@ static void drbg_ctr_bcc(struct crypto_aes_ctx *aesctx, drbg_string_fill(&data, out, blocklen_bytes); /* 10.4.3 step 2 / 4 */ - drbg_kcapi_symsetkey(aesctx, key, keylen); + aes_prepareenckey(aeskey, key, keylen); list_for_each_entry(curr, in, list) { const unsigned char *pos = curr->buf; size_t len = curr->len; @@ -56,7 +46,7 @@ static void drbg_ctr_bcc(struct crypto_aes_ctx *aesctx, /* 10.4.3 step 4.2 */ if (blocklen_bytes == cnt) { cnt = 0; - drbg_kcapi_sym(aesctx, out, &data, blocklen_bytes); + drbg_kcapi_sym(aeskey, out, &data, blocklen_bytes); } out[cnt] ^= *pos; pos++; @@ -66,7 +56,7 @@ static void drbg_ctr_bcc(struct crypto_aes_ctx *aesctx, } /* 10.4.3 step 4.2 for last block */ if (cnt) - drbg_kcapi_sym(aesctx, out, &data, blocklen_bytes); + drbg_kcapi_sym(aeskey, out, &data, blocklen_bytes); } /* @@ -110,7 +100,7 @@ static void drbg_ctr_bcc(struct crypto_aes_ctx *aesctx, */ /* Derivation Function for CTR DRBG as defined in 10.4.2 */ -int crypto_drbg_ctr_df(struct crypto_aes_ctx *aesctx, +int crypto_drbg_ctr_df(struct aes_enckey *aeskey, unsigned char *df_data, size_t bytes_to_return, struct list_head *seedlist, u8 blocklen_bytes, @@ -187,7 +177,7 @@ int crypto_drbg_ctr_df(struct crypto_aes_ctx *aesctx, */ drbg_cpu_to_be32(i, iv); /* 10.4.2 step 9.2 -- BCC and concatenation with temp */ - drbg_ctr_bcc(aesctx, temp + templen, K, &bcc_list, + drbg_ctr_bcc(aeskey, temp + templen, K, &bcc_list, blocklen_bytes, keylen); /* 10.4.2 step 9.3 */ i++; @@ -201,7 +191,7 @@ int crypto_drbg_ctr_df(struct crypto_aes_ctx *aesctx, /* 10.4.2 step 12: overwriting of outval is implemented in next step */ /* 10.4.2 step 13 */ - drbg_kcapi_symsetkey(aesctx, temp, keylen); + aes_prepareenckey(aeskey, temp, keylen); while (generated_len < bytes_to_return) { short blocklen = 0; /* @@ -209,7 +199,7 @@ int crypto_drbg_ctr_df(struct crypto_aes_ctx *aesctx, * implicit as the key is only drbg_blocklen in size based on * the implementation of the cipher function callback */ - drbg_kcapi_sym(aesctx, X, &cipherin, blocklen_bytes); + drbg_kcapi_sym(aeskey, X, &cipherin, blocklen_bytes); blocklen = (blocklen_bytes < (bytes_to_return - generated_len)) ? blocklen_bytes : diff --git a/crypto/drbg.c b/crypto/drbg.c index 1d433dae9955..85cc4549bd58 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1505,9 +1505,9 @@ static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval, #ifdef CONFIG_CRYPTO_DRBG_CTR static int drbg_fini_sym_kernel(struct drbg_state *drbg) { - struct crypto_aes_ctx *aesctx = (struct crypto_aes_ctx *)drbg->priv_data; + struct aes_enckey *aeskey = drbg->priv_data; - kfree(aesctx); + kfree(aeskey); drbg->priv_data = NULL; if (drbg->ctr_handle) @@ -1526,16 +1526,16 @@ static int drbg_fini_sym_kernel(struct drbg_state *drbg) static int drbg_init_sym_kernel(struct drbg_state *drbg) { - struct crypto_aes_ctx *aesctx; + struct aes_enckey *aeskey; struct crypto_skcipher *sk_tfm; struct skcipher_request *req; unsigned int alignmask; char ctr_name[CRYPTO_MAX_ALG_NAME]; - aesctx = kzalloc(sizeof(*aesctx), GFP_KERNEL); - if (!aesctx) + aeskey = kzalloc(sizeof(*aeskey), GFP_KERNEL); + if (!aeskey) return -ENOMEM; - drbg->priv_data = aesctx; + drbg->priv_data = aeskey; if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)", drbg->core->backend_cra_name) >= CRYPTO_MAX_ALG_NAME) { diff --git a/drivers/crypto/xilinx/xilinx-trng.c b/drivers/crypto/xilinx/xilinx-trng.c index db0fbb28ff32..5276ac2d82bb 100644 --- a/drivers/crypto/xilinx/xilinx-trng.c +++ b/drivers/crypto/xilinx/xilinx-trng.c @@ -60,7 +60,7 @@ struct xilinx_rng { void __iomem *rng_base; struct device *dev; unsigned char *scratchpadbuf; - struct crypto_aes_ctx *aesctx; + struct aes_enckey *aeskey; struct mutex lock; /* Protect access to TRNG device */ struct hwrng trng; }; @@ -198,7 +198,7 @@ static int xtrng_reseed_internal(struct xilinx_rng *rng) ret = xtrng_collect_random_data(rng, entropy, TRNG_SEED_LEN_BYTES, true); if (ret != TRNG_SEED_LEN_BYTES) return -EINVAL; - ret = crypto_drbg_ctr_df(rng->aesctx, rng->scratchpadbuf, + ret = crypto_drbg_ctr_df(rng->aeskey, rng->scratchpadbuf, TRNG_SEED_LEN_BYTES, &seedlist, AES_BLOCK_SIZE, TRNG_SEED_LEN_BYTES); if (ret) @@ -349,8 +349,8 @@ static int xtrng_probe(struct platform_device *pdev) return PTR_ERR(rng->rng_base); } - rng->aesctx = devm_kzalloc(&pdev->dev, sizeof(*rng->aesctx), GFP_KERNEL); - if (!rng->aesctx) + rng->aeskey = devm_kzalloc(&pdev->dev, sizeof(*rng->aeskey), GFP_KERNEL); + if (!rng->aeskey) return -ENOMEM; sb_size = crypto_drbg_ctr_df_datalen(TRNG_SEED_LEN_BYTES, AES_BLOCK_SIZE); diff --git a/include/crypto/df_sp80090a.h b/include/crypto/df_sp80090a.h index 6b25305fe611..cb5d6fe15d40 100644 --- a/include/crypto/df_sp80090a.h +++ b/include/crypto/df_sp80090a.h @@ -18,7 +18,7 @@ static inline int crypto_drbg_ctr_df_datalen(u8 statelen, u8 blocklen) statelen + blocklen; /* temp */ } -int crypto_drbg_ctr_df(struct crypto_aes_ctx *aes, +int crypto_drbg_ctr_df(struct aes_enckey *aes, unsigned char *df_data, size_t bytes_to_return, struct list_head *seedlist, From 65c7022be112b05c4da6e19a4b4635da45b6434d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:28 -0800 Subject: [PATCH 47/53] crypto: inside-secure - Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. This driver used crypto_aes_ctx::key_enc, but only to access the copy of the raw key that is stored at the beginning of the expanded key. To eliminate the dependency on this field, instead just access the raw key directly, which is already available in the relevant functions. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-31-ebiggers@kernel.org Signed-off-by: Eric Biggers --- drivers/crypto/inside-secure/safexcel_cipher.c | 12 +++++------- drivers/crypto/inside-secure/safexcel_hash.c | 14 +++++++------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index 919e5a2cab95..27b180057417 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -2507,19 +2507,17 @@ static int safexcel_aead_gcm_setkey(struct crypto_aead *ctfm, const u8 *key, struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); struct safexcel_crypto_priv *priv = ctx->base.priv; - struct crypto_aes_ctx aes; + struct aes_enckey aes; u32 hashkey[AES_BLOCK_SIZE >> 2]; int ret, i; - ret = aes_expandkey(&aes, key, len); - if (ret) { - memzero_explicit(&aes, sizeof(aes)); + ret = aes_prepareenckey(&aes, key, len); + if (ret) return ret; - } if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { for (i = 0; i < len / sizeof(u32); i++) { - if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) { + if (ctx->key[i] != get_unaligned((__le32 *)key + i)) { ctx->base.needs_inv = true; break; } @@ -2527,7 +2525,7 @@ static int safexcel_aead_gcm_setkey(struct crypto_aead *ctfm, const u8 *key, } for (i = 0; i < len / sizeof(u32); i++) - ctx->key[i] = cpu_to_le32(aes.key_enc[i]); + ctx->key[i] = get_unaligned((__le32 *)key + i); ctx->key_len = len; diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c index ef0ba4832928..e534b7a200cf 100644 --- a/drivers/crypto/inside-secure/safexcel_hash.c +++ b/drivers/crypto/inside-secure/safexcel_hash.c @@ -30,7 +30,7 @@ struct safexcel_ahash_ctx { bool fb_init_done; bool fb_do_setkey; - struct crypto_aes_ctx *aes; + struct aes_enckey *aes; struct crypto_ahash *fback; struct crypto_shash *shpre; struct shash_desc *shdesc; @@ -1976,7 +1976,7 @@ static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)]; int ret, i; - ret = aes_expandkey(ctx->aes, key, len); + ret = aes_prepareenckey(ctx->aes, key, len); if (ret) return ret; @@ -1990,9 +1990,9 @@ static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++) ctx->base.ipad.word[i] = swab32(key_tmp[i]); - ret = aes_expandkey(ctx->aes, - (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, - AES_MIN_KEY_SIZE); + ret = aes_prepareenckey(ctx->aes, + (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, + AES_MIN_KEY_SIZE); if (ret) return ret; @@ -2062,12 +2062,12 @@ static int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, int ret, i; /* precompute the CMAC key material */ - ret = aes_expandkey(ctx->aes, key, len); + ret = aes_prepareenckey(ctx->aes, key, len); if (ret) return ret; for (i = 0; i < len / sizeof(u32); i++) - ctx->base.ipad.word[i + 8] = swab32(ctx->aes->key_enc[i]); + ctx->base.ipad.word[i + 8] = get_unaligned_be32(&key[4 * i]); /* code below borrowed from crypto/cmac.c */ /* encrypt the zero block */ From 86120434712314077fc7aeeaaf732521d1446736 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:29 -0800 Subject: [PATCH 48/53] crypto: omap - Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-32-ebiggers@kernel.org Signed-off-by: Eric Biggers --- drivers/crypto/omap-aes-gcm.c | 6 +++--- drivers/crypto/omap-aes.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/omap-aes-gcm.c b/drivers/crypto/omap-aes-gcm.c index 1f4586509ca4..c652f9d0062f 100644 --- a/drivers/crypto/omap-aes-gcm.c +++ b/drivers/crypto/omap-aes-gcm.c @@ -177,7 +177,7 @@ static int do_encrypt_iv(struct aead_request *req, u32 *tag, u32 *iv) { struct omap_aes_gcm_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); - aes_encrypt(&ctx->actx, (u8 *)tag, (u8 *)iv); + aes_encrypt(&ctx->akey, (u8 *)tag, (const u8 *)iv); return 0; } @@ -314,7 +314,7 @@ int omap_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key, struct omap_aes_gcm_ctx *ctx = crypto_aead_ctx(tfm); int ret; - ret = aes_expandkey(&ctx->actx, key, keylen); + ret = aes_prepareenckey(&ctx->akey, key, keylen); if (ret) return ret; @@ -334,7 +334,7 @@ int omap_aes_4106gcm_setkey(struct crypto_aead *tfm, const u8 *key, return -EINVAL; keylen -= 4; - ret = aes_expandkey(&ctx->actx, key, keylen); + ret = aes_prepareenckey(&ctx->akey, key, keylen); if (ret) return ret; diff --git a/drivers/crypto/omap-aes.h b/drivers/crypto/omap-aes.h index 99c36a777e97..6aa70bde387a 100644 --- a/drivers/crypto/omap-aes.h +++ b/drivers/crypto/omap-aes.h @@ -98,7 +98,7 @@ struct omap_aes_ctx { struct omap_aes_gcm_ctx { struct omap_aes_ctx octx; - struct crypto_aes_ctx actx; + struct aes_enckey akey; }; struct omap_aes_reqctx { From 7fcb22dc7765185a86077f65179ec4fa3f30b910 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:30 -0800 Subject: [PATCH 49/53] lib/crypto: aescfb: Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-33-ebiggers@kernel.org Signed-off-by: Eric Biggers --- drivers/char/tpm/tpm2-sessions.c | 10 +++++----- include/crypto/aes.h | 4 ++-- lib/crypto/aescfb.c | 30 +++++++++++++++--------------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c index 4149379665c4..09df6353ef04 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -126,7 +126,7 @@ struct tpm2_auth { u8 session_key[SHA256_DIGEST_SIZE]; u8 passphrase[SHA256_DIGEST_SIZE]; int passphrase_len; - struct crypto_aes_ctx aes_ctx; + struct aes_enckey aes_key; /* saved session attributes: */ u8 attrs; __be32 ordinal; @@ -677,8 +677,8 @@ int tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf) auth->scratch); len = tpm_buf_read_u16(buf, &offset_p); - aes_expandkey(&auth->aes_ctx, auth->scratch, AES_KEY_BYTES); - aescfb_encrypt(&auth->aes_ctx, &buf->data[offset_p], + aes_prepareenckey(&auth->aes_key, auth->scratch, AES_KEY_BYTES); + aescfb_encrypt(&auth->aes_key, &buf->data[offset_p], &buf->data[offset_p], len, auth->scratch + AES_KEY_BYTES); /* reset p to beginning of parameters for HMAC */ @@ -858,8 +858,8 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf, auth->scratch); len = tpm_buf_read_u16(buf, &offset_p); - aes_expandkey(&auth->aes_ctx, auth->scratch, AES_KEY_BYTES); - aescfb_decrypt(&auth->aes_ctx, &buf->data[offset_p], + aes_prepareenckey(&auth->aes_key, auth->scratch, AES_KEY_BYTES); + aescfb_decrypt(&auth->aes_key, &buf->data[offset_p], &buf->data[offset_p], len, auth->scratch + AES_KEY_BYTES); } diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 4a56aed59973..4cb3c27d1bf5 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -343,9 +343,9 @@ extern const u8 crypto_aes_inv_sbox[]; extern const u32 aes_enc_tab[256]; extern const u32 aes_dec_tab[256]; -void aescfb_encrypt(const struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src, +void aescfb_encrypt(const struct aes_enckey *key, u8 *dst, const u8 *src, int len, const u8 iv[AES_BLOCK_SIZE]); -void aescfb_decrypt(const struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src, +void aescfb_decrypt(const struct aes_enckey *key, u8 *dst, const u8 *src, int len, const u8 iv[AES_BLOCK_SIZE]); #endif diff --git a/lib/crypto/aescfb.c b/lib/crypto/aescfb.c index 0f294c8cbf3c..147e5211728f 100644 --- a/lib/crypto/aescfb.c +++ b/lib/crypto/aescfb.c @@ -11,7 +11,7 @@ #include #include -static void aescfb_encrypt_block(const struct crypto_aes_ctx *ctx, void *dst, +static void aescfb_encrypt_block(const struct aes_enckey *key, void *dst, const void *src) { unsigned long flags; @@ -25,27 +25,27 @@ static void aescfb_encrypt_block(const struct crypto_aes_ctx *ctx, void *dst, * interrupts disabled. */ local_irq_save(flags); - aes_encrypt(ctx, dst, src); + aes_encrypt(key, dst, src); local_irq_restore(flags); } /** * aescfb_encrypt - Perform AES-CFB encryption on a block of data * - * @ctx: The AES-CFB key schedule + * @key: The AES-CFB key schedule * @dst: Pointer to the ciphertext output buffer * @src: Pointer the plaintext (may equal @dst for encryption in place) * @len: The size in bytes of the plaintext and ciphertext. * @iv: The initialization vector (IV) to use for this block of data */ -void aescfb_encrypt(const struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src, +void aescfb_encrypt(const struct aes_enckey *key, u8 *dst, const u8 *src, int len, const u8 iv[AES_BLOCK_SIZE]) { u8 ks[AES_BLOCK_SIZE]; const u8 *v = iv; while (len > 0) { - aescfb_encrypt_block(ctx, ks, v); + aescfb_encrypt_block(key, ks, v); crypto_xor_cpy(dst, src, ks, min(len, AES_BLOCK_SIZE)); v = dst; @@ -61,18 +61,18 @@ EXPORT_SYMBOL(aescfb_encrypt); /** * aescfb_decrypt - Perform AES-CFB decryption on a block of data * - * @ctx: The AES-CFB key schedule + * @key: The AES-CFB key schedule * @dst: Pointer to the plaintext output buffer * @src: Pointer the ciphertext (may equal @dst for decryption in place) * @len: The size in bytes of the plaintext and ciphertext. * @iv: The initialization vector (IV) to use for this block of data */ -void aescfb_decrypt(const struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src, +void aescfb_decrypt(const struct aes_enckey *key, u8 *dst, const u8 *src, int len, const u8 iv[AES_BLOCK_SIZE]) { u8 ks[2][AES_BLOCK_SIZE]; - aescfb_encrypt_block(ctx, ks[0], iv); + aescfb_encrypt_block(key, ks[0], iv); for (int i = 0; len > 0; i ^= 1) { if (len > AES_BLOCK_SIZE) @@ -81,7 +81,7 @@ void aescfb_decrypt(const struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src, * performing the XOR, as that may update in place and * overwrite the ciphertext. */ - aescfb_encrypt_block(ctx, ks[!i], src); + aescfb_encrypt_block(key, ks[!i], src); crypto_xor_cpy(dst, src, ks[i], min(len, AES_BLOCK_SIZE)); @@ -214,15 +214,15 @@ static struct { static int __init libaescfb_init(void) { for (int i = 0; i < ARRAY_SIZE(aescfb_tv); i++) { - struct crypto_aes_ctx ctx; + struct aes_enckey key; u8 buf[64]; - if (aes_expandkey(&ctx, aescfb_tv[i].key, aescfb_tv[i].klen)) { - pr_err("aes_expandkey() failed on vector %d\n", i); + if (aes_prepareenckey(&key, aescfb_tv[i].key, aescfb_tv[i].klen)) { + pr_err("aes_prepareenckey() failed on vector %d\n", i); return -ENODEV; } - aescfb_encrypt(&ctx, buf, aescfb_tv[i].ptext, aescfb_tv[i].len, + aescfb_encrypt(&key, buf, aescfb_tv[i].ptext, aescfb_tv[i].len, aescfb_tv[i].iv); if (memcmp(buf, aescfb_tv[i].ctext, aescfb_tv[i].len)) { pr_err("aescfb_encrypt() #1 failed on vector %d\n", i); @@ -230,14 +230,14 @@ static int __init libaescfb_init(void) } /* decrypt in place */ - aescfb_decrypt(&ctx, buf, buf, aescfb_tv[i].len, aescfb_tv[i].iv); + aescfb_decrypt(&key, buf, buf, aescfb_tv[i].len, aescfb_tv[i].iv); if (memcmp(buf, aescfb_tv[i].ptext, aescfb_tv[i].len)) { pr_err("aescfb_decrypt() failed on vector %d\n", i); return -ENODEV; } /* encrypt in place */ - aescfb_encrypt(&ctx, buf, buf, aescfb_tv[i].len, aescfb_tv[i].iv); + aescfb_encrypt(&key, buf, buf, aescfb_tv[i].len, aescfb_tv[i].iv); if (memcmp(buf, aescfb_tv[i].ctext, aescfb_tv[i].len)) { pr_err("aescfb_encrypt() #2 failed on vector %d\n", i); From bc79efa08c038846b962edf04dc00922b48efdc7 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:31 -0800 Subject: [PATCH 50/53] lib/crypto: aesgcm: Use new AES library API Switch from the old AES library functions (which use struct crypto_aes_ctx) to the new ones (which use struct aes_enckey). This eliminates the unnecessary computation and caching of the decryption round keys. The new AES en/decryption functions are also much faster and use AES instructions when supported by the CPU. Note that in addition to the change in the key preparation function and the key struct type itself, the change in the type of the key struct results in aes_encrypt() (which is temporarily a type-generic macro) calling the new encryption function rather than the old one. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-34-ebiggers@kernel.org Signed-off-by: Eric Biggers --- include/crypto/gcm.h | 2 +- lib/crypto/aesgcm.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/crypto/gcm.h b/include/crypto/gcm.h index fd9df607a836..b524e47bd4d0 100644 --- a/include/crypto/gcm.h +++ b/include/crypto/gcm.h @@ -66,7 +66,7 @@ static inline int crypto_ipsec_check_assoclen(unsigned int assoclen) struct aesgcm_ctx { be128 ghash_key; - struct crypto_aes_ctx aes_ctx; + struct aes_enckey aes_key; unsigned int authsize; }; diff --git a/lib/crypto/aesgcm.c b/lib/crypto/aesgcm.c index ac0b2fcfd606..02f5b5f32c76 100644 --- a/lib/crypto/aesgcm.c +++ b/lib/crypto/aesgcm.c @@ -12,7 +12,7 @@ #include #include -static void aesgcm_encrypt_block(const struct crypto_aes_ctx *ctx, void *dst, +static void aesgcm_encrypt_block(const struct aes_enckey *key, void *dst, const void *src) { unsigned long flags; @@ -26,7 +26,7 @@ static void aesgcm_encrypt_block(const struct crypto_aes_ctx *ctx, void *dst, * effective when running with interrupts disabled. */ local_irq_save(flags); - aes_encrypt(ctx, dst, src); + aes_encrypt(key, dst, src); local_irq_restore(flags); } @@ -49,12 +49,12 @@ int aesgcm_expandkey(struct aesgcm_ctx *ctx, const u8 *key, int ret; ret = crypto_gcm_check_authsize(authsize) ?: - aes_expandkey(&ctx->aes_ctx, key, keysize); + aes_prepareenckey(&ctx->aes_key, key, keysize); if (ret) return ret; ctx->authsize = authsize; - aesgcm_encrypt_block(&ctx->aes_ctx, &ctx->ghash_key, kin); + aesgcm_encrypt_block(&ctx->aes_key, &ctx->ghash_key, kin); return 0; } @@ -97,7 +97,7 @@ static void aesgcm_mac(const struct aesgcm_ctx *ctx, const u8 *src, int src_len, aesgcm_ghash(&ghash, &ctx->ghash_key, &tail, sizeof(tail)); ctr[3] = cpu_to_be32(1); - aesgcm_encrypt_block(&ctx->aes_ctx, buf, ctr); + aesgcm_encrypt_block(&ctx->aes_key, buf, ctr); crypto_xor_cpy(authtag, buf, (u8 *)&ghash, ctx->authsize); memzero_explicit(&ghash, sizeof(ghash)); @@ -119,7 +119,7 @@ static void aesgcm_crypt(const struct aesgcm_ctx *ctx, u8 *dst, const u8 *src, * len', this cannot happen, so no explicit test is necessary. */ ctr[3] = cpu_to_be32(n++); - aesgcm_encrypt_block(&ctx->aes_ctx, buf, ctr); + aesgcm_encrypt_block(&ctx->aes_key, buf, ctr); crypto_xor_cpy(dst, src, buf, min(len, AES_BLOCK_SIZE)); dst += AES_BLOCK_SIZE; From 953f2db0bfc2ab68e69f385441d0f4b54aee0cd1 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:32 -0800 Subject: [PATCH 51/53] lib/crypto: aes: Remove old AES en/decryption functions Now that all callers of the aes_encrypt() and aes_decrypt() type-generic macros are using the new types, remove the old functions. Then, replace the macro with direct calls to the new functions, dropping the "_new" suffix from them. This completes the change in the type of the key struct that is passed to aes_encrypt() and aes_decrypt(). Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-35-ebiggers@kernel.org Signed-off-by: Eric Biggers --- include/crypto/aes.h | 24 ++------- lib/crypto/aes.c | 118 +++---------------------------------------- 2 files changed, 10 insertions(+), 132 deletions(-) diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 4cb3c27d1bf5..cbf1cc96db52 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -308,17 +308,8 @@ typedef union { * * Context: Any context. */ -#define aes_encrypt(key, out, in) \ - _Generic((key), \ - struct crypto_aes_ctx *: aes_encrypt_old((const struct crypto_aes_ctx *)(key), (out), (in)), \ - const struct crypto_aes_ctx *: aes_encrypt_old((const struct crypto_aes_ctx *)(key), (out), (in)), \ - struct aes_enckey *: aes_encrypt_new((const struct aes_enckey *)(key), (out), (in)), \ - const struct aes_enckey *: aes_encrypt_new((const struct aes_enckey *)(key), (out), (in)), \ - struct aes_key *: aes_encrypt_new((const struct aes_key *)(key), (out), (in)), \ - const struct aes_key *: aes_encrypt_new((const struct aes_key *)(key), (out), (in))) -void aes_encrypt_old(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); -void aes_encrypt_new(aes_encrypt_arg key, u8 out[at_least AES_BLOCK_SIZE], - const u8 in[at_least AES_BLOCK_SIZE]); +void aes_encrypt(aes_encrypt_arg key, u8 out[at_least AES_BLOCK_SIZE], + const u8 in[at_least AES_BLOCK_SIZE]); /** * aes_decrypt() - Decrypt a single AES block @@ -328,15 +319,8 @@ void aes_encrypt_new(aes_encrypt_arg key, u8 out[at_least AES_BLOCK_SIZE], * * Context: Any context. */ -#define aes_decrypt(key, out, in) \ - _Generic((key), \ - struct crypto_aes_ctx *: aes_decrypt_old((const struct crypto_aes_ctx *)(key), (out), (in)), \ - const struct crypto_aes_ctx *: aes_decrypt_old((const struct crypto_aes_ctx *)(key), (out), (in)), \ - struct aes_key *: aes_decrypt_new((const struct aes_key *)(key), (out), (in)), \ - const struct aes_key *: aes_decrypt_new((const struct aes_key *)(key), (out), (in))) -void aes_decrypt_old(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in); -void aes_decrypt_new(const struct aes_key *key, u8 out[at_least AES_BLOCK_SIZE], - const u8 in[at_least AES_BLOCK_SIZE]); +void aes_decrypt(const struct aes_key *key, u8 out[at_least AES_BLOCK_SIZE], + const u8 in[at_least AES_BLOCK_SIZE]); extern const u8 crypto_aes_sbox[]; extern const u8 crypto_aes_inv_sbox[]; diff --git a/lib/crypto/aes.c b/lib/crypto/aes.c index 88da68dcf5a8..b7ab2d0c4e59 100644 --- a/lib/crypto/aes.c +++ b/lib/crypto/aes.c @@ -251,22 +251,6 @@ static u32 inv_mix_columns(u32 x) return mix_columns(x ^ y ^ ror32(y, 16)); } -static __always_inline u32 subshift(u32 in[], int pos) -{ - return (aes_sbox[in[pos] & 0xff]) ^ - (aes_sbox[(in[(pos + 1) % 4] >> 8) & 0xff] << 8) ^ - (aes_sbox[(in[(pos + 2) % 4] >> 16) & 0xff] << 16) ^ - (aes_sbox[(in[(pos + 3) % 4] >> 24) & 0xff] << 24); -} - -static __always_inline u32 inv_subshift(u32 in[], int pos) -{ - return (aes_inv_sbox[in[pos] & 0xff]) ^ - (aes_inv_sbox[(in[(pos + 3) % 4] >> 8) & 0xff] << 8) ^ - (aes_inv_sbox[(in[(pos + 2) % 4] >> 16) & 0xff] << 16) ^ - (aes_inv_sbox[(in[(pos + 1) % 4] >> 24) & 0xff] << 24); -} - static u32 subw(u32 in) { return (aes_sbox[in & 0xff]) ^ @@ -345,51 +329,6 @@ int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, } EXPORT_SYMBOL(aes_expandkey); -void aes_encrypt_old(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in) -{ - const u32 *rkp = ctx->key_enc + 4; - int rounds = 6 + ctx->key_length / 4; - u32 st0[4], st1[4]; - int round; - - st0[0] = ctx->key_enc[0] ^ get_unaligned_le32(in); - st0[1] = ctx->key_enc[1] ^ get_unaligned_le32(in + 4); - st0[2] = ctx->key_enc[2] ^ get_unaligned_le32(in + 8); - st0[3] = ctx->key_enc[3] ^ get_unaligned_le32(in + 12); - - /* - * Force the compiler to emit data independent Sbox references, - * by xoring the input with Sbox values that are known to add up - * to zero. This pulls the entire Sbox into the D-cache before any - * data dependent lookups are done. - */ - st0[0] ^= aes_sbox[ 0] ^ aes_sbox[ 64] ^ aes_sbox[134] ^ aes_sbox[195]; - st0[1] ^= aes_sbox[16] ^ aes_sbox[ 82] ^ aes_sbox[158] ^ aes_sbox[221]; - st0[2] ^= aes_sbox[32] ^ aes_sbox[ 96] ^ aes_sbox[160] ^ aes_sbox[234]; - st0[3] ^= aes_sbox[48] ^ aes_sbox[112] ^ aes_sbox[186] ^ aes_sbox[241]; - - for (round = 0;; round += 2, rkp += 8) { - st1[0] = mix_columns(subshift(st0, 0)) ^ rkp[0]; - st1[1] = mix_columns(subshift(st0, 1)) ^ rkp[1]; - st1[2] = mix_columns(subshift(st0, 2)) ^ rkp[2]; - st1[3] = mix_columns(subshift(st0, 3)) ^ rkp[3]; - - if (round == rounds - 2) - break; - - st0[0] = mix_columns(subshift(st1, 0)) ^ rkp[4]; - st0[1] = mix_columns(subshift(st1, 1)) ^ rkp[5]; - st0[2] = mix_columns(subshift(st1, 2)) ^ rkp[6]; - st0[3] = mix_columns(subshift(st1, 3)) ^ rkp[7]; - } - - put_unaligned_le32(subshift(st1, 0) ^ rkp[4], out); - put_unaligned_le32(subshift(st1, 1) ^ rkp[5], out + 4); - put_unaligned_le32(subshift(st1, 2) ^ rkp[6], out + 8); - put_unaligned_le32(subshift(st1, 3) ^ rkp[7], out + 12); -} -EXPORT_SYMBOL(aes_encrypt_old); - static __always_inline u32 enc_quarterround(const u32 w[4], int i, u32 rk) { return rk ^ aes_enc_tab[(u8)w[i]] ^ @@ -498,51 +437,6 @@ static void __maybe_unused aes_decrypt_generic(const u32 inv_rndkeys[], put_unaligned_le32(declast_quarterround(w, 3, *rkp++), &out[12]); } -void aes_decrypt_old(const struct crypto_aes_ctx *ctx, u8 *out, const u8 *in) -{ - const u32 *rkp = ctx->key_dec + 4; - int rounds = 6 + ctx->key_length / 4; - u32 st0[4], st1[4]; - int round; - - st0[0] = ctx->key_dec[0] ^ get_unaligned_le32(in); - st0[1] = ctx->key_dec[1] ^ get_unaligned_le32(in + 4); - st0[2] = ctx->key_dec[2] ^ get_unaligned_le32(in + 8); - st0[3] = ctx->key_dec[3] ^ get_unaligned_le32(in + 12); - - /* - * Force the compiler to emit data independent Sbox references, - * by xoring the input with Sbox values that are known to add up - * to zero. This pulls the entire Sbox into the D-cache before any - * data dependent lookups are done. - */ - st0[0] ^= aes_inv_sbox[ 0] ^ aes_inv_sbox[ 64] ^ aes_inv_sbox[129] ^ aes_inv_sbox[200]; - st0[1] ^= aes_inv_sbox[16] ^ aes_inv_sbox[ 83] ^ aes_inv_sbox[150] ^ aes_inv_sbox[212]; - st0[2] ^= aes_inv_sbox[32] ^ aes_inv_sbox[ 96] ^ aes_inv_sbox[160] ^ aes_inv_sbox[236]; - st0[3] ^= aes_inv_sbox[48] ^ aes_inv_sbox[112] ^ aes_inv_sbox[187] ^ aes_inv_sbox[247]; - - for (round = 0;; round += 2, rkp += 8) { - st1[0] = inv_mix_columns(inv_subshift(st0, 0)) ^ rkp[0]; - st1[1] = inv_mix_columns(inv_subshift(st0, 1)) ^ rkp[1]; - st1[2] = inv_mix_columns(inv_subshift(st0, 2)) ^ rkp[2]; - st1[3] = inv_mix_columns(inv_subshift(st0, 3)) ^ rkp[3]; - - if (round == rounds - 2) - break; - - st0[0] = inv_mix_columns(inv_subshift(st1, 0)) ^ rkp[4]; - st0[1] = inv_mix_columns(inv_subshift(st1, 1)) ^ rkp[5]; - st0[2] = inv_mix_columns(inv_subshift(st1, 2)) ^ rkp[6]; - st0[3] = inv_mix_columns(inv_subshift(st1, 3)) ^ rkp[7]; - } - - put_unaligned_le32(inv_subshift(st1, 0) ^ rkp[4], out); - put_unaligned_le32(inv_subshift(st1, 1) ^ rkp[5], out + 4); - put_unaligned_le32(inv_subshift(st1, 2) ^ rkp[6], out + 8); - put_unaligned_le32(inv_subshift(st1, 3) ^ rkp[7], out + 12); -} -EXPORT_SYMBOL(aes_decrypt_old); - /* * Note: the aes_prepare*key_* names reflect the fact that the implementation * might not actually expand the key. (The s390 code for example doesn't.) @@ -608,19 +502,19 @@ int aes_prepareenckey(struct aes_enckey *key, const u8 *in_key, size_t key_len) } EXPORT_SYMBOL(aes_prepareenckey); -void aes_encrypt_new(aes_encrypt_arg key, u8 out[AES_BLOCK_SIZE], - const u8 in[AES_BLOCK_SIZE]) +void aes_encrypt(aes_encrypt_arg key, u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) { aes_encrypt_arch(key.enc_key, out, in); } -EXPORT_SYMBOL(aes_encrypt_new); +EXPORT_SYMBOL(aes_encrypt); -void aes_decrypt_new(const struct aes_key *key, u8 out[AES_BLOCK_SIZE], - const u8 in[AES_BLOCK_SIZE]) +void aes_decrypt(const struct aes_key *key, u8 out[AES_BLOCK_SIZE], + const u8 in[AES_BLOCK_SIZE]) { aes_decrypt_arch(key, out, in); } -EXPORT_SYMBOL(aes_decrypt_new); +EXPORT_SYMBOL(aes_decrypt); #ifdef aes_mod_init_arch static int __init aes_mod_init(void) From fbfeca74043777b48add294089cd4c4f68ed3377 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 12 Jan 2026 11:20:33 -0800 Subject: [PATCH 52/53] lib/crypto: aes: Drop 'volatile' from aes_sbox and aes_inv_sbox The volatile keyword is no longer necessary or useful on aes_sbox and aes_inv_sbox, since the table prefetching is now done using a helper function that casts to volatile itself and also includes an optimization barrier. Since it prevents some compiler optimizations, remove it. Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20260112192035.10427-36-ebiggers@kernel.org Signed-off-by: Eric Biggers --- lib/crypto/aes.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/crypto/aes.c b/lib/crypto/aes.c index b7ab2d0c4e59..b73e19f1bb95 100644 --- a/lib/crypto/aes.c +++ b/lib/crypto/aes.c @@ -11,11 +11,7 @@ #include #include -/* - * Emit the sbox as volatile const to prevent the compiler from doing - * constant folding on sbox references involving fixed indexes. - */ -static volatile const u8 ____cacheline_aligned aes_sbox[] = { +static const u8 ____cacheline_aligned aes_sbox[] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, @@ -50,7 +46,7 @@ static volatile const u8 ____cacheline_aligned aes_sbox[] = { 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, }; -static volatile const u8 ____cacheline_aligned aes_inv_sbox[] = { +static const u8 ____cacheline_aligned aes_inv_sbox[] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, @@ -430,7 +426,7 @@ static void __maybe_unused aes_decrypt_generic(const u32 inv_rndkeys[], w[3] = w3; } while (--n); - aes_prefetch((const void *)aes_inv_sbox, sizeof(aes_inv_sbox)); + aes_prefetch(aes_inv_sbox, sizeof(aes_inv_sbox)); put_unaligned_le32(declast_quarterround(w, 0, *rkp++), &out[0]); put_unaligned_le32(declast_quarterround(w, 1, *rkp++), &out[4]); put_unaligned_le32(declast_quarterround(w, 2, *rkp++), &out[8]); From ffd42b6d0420c4be97cc28fd1bb5f4c29e286e98 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 2 Feb 2026 14:15:52 -0800 Subject: [PATCH 53/53] lib/crypto: mldsa: Clarify the documentation for mldsa_verify() slightly mldsa_verify() implements ML-DSA.Verify with ctx='', so document this more explicitly. Remove the one-liner comment above mldsa_verify() which was somewhat misleading. Reviewed-by: David Howells Link: https://lore.kernel.org/r/20260202221552.174341-1-ebiggers@kernel.org Signed-off-by: Eric Biggers --- include/crypto/mldsa.h | 4 +++- lib/crypto/mldsa.c | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/crypto/mldsa.h b/include/crypto/mldsa.h index cf30aef29970..3ef2676787c9 100644 --- a/include/crypto/mldsa.h +++ b/include/crypto/mldsa.h @@ -39,7 +39,9 @@ enum mldsa_alg { * otherwise -EBADMSG will be returned. * * This verifies a signature using pure ML-DSA with the specified parameter set. - * The context string is assumed to be empty. + * The context string is assumed to be empty. This corresponds to FIPS 204 + * Algorithm 3 "ML-DSA.Verify" with the ctx parameter set to the empty string + * and the lengths of the signature and key given explicitly by the caller. * * Context: Might sleep * diff --git a/lib/crypto/mldsa.c b/lib/crypto/mldsa.c index ba0c0468956e..c96fddc4e7dc 100644 --- a/lib/crypto/mldsa.c +++ b/lib/crypto/mldsa.c @@ -525,7 +525,6 @@ static size_t encode_w1(u8 out[MAX_W1_ENCODED_LEN], return pos; } -/* Reference: FIPS 204 Section 6.3 "ML-DSA Verifying (Internal)" */ int mldsa_verify(enum mldsa_alg alg, const u8 *sig, size_t sig_len, const u8 *msg, size_t msg_len, const u8 *pk, size_t pk_len) {