arch/s390/crypto/sha3_256_s390.c | 26 - include/crypto/sha3.h | 160 +++++++- lib/crypto/Kconfig | 7 lib/crypto/Makefile | 6 lib/crypto/sha3.c | 597 ++++++++++++++++++++++++++++++ lib/crypto/tests/Kconfig | 12 lib/crypto/tests/Makefile | 7 lib/crypto/tests/sha3_224_kunit.c | 32 + lib/crypto/tests/sha3_224_testvecs.h | 231 +++++++++++ lib/crypto/tests/sha3_256_kunit.c | 32 + lib/crypto/tests/sha3_256_testvecs.h | 231 +++++++++++ lib/crypto/tests/sha3_384_kunit.c | 32 + lib/crypto/tests/sha3_384_testvecs.h | 281 ++++++++++++++ lib/crypto/tests/sha3_512_kunit.c | 32 + lib/crypto/tests/sha3_512_testvecs.h | 331 ++++++++++++++++ lib/crypto/tests/sha3_shake128_kunit.c | 37 + lib/crypto/tests/sha3_shake128_testvecs.h | 181 +++++++++ lib/crypto/tests/sha3_shake256_kunit.c | 37 + lib/crypto/tests/sha3_shake256_testvecs.h | 231 +++++++++++ scripts/crypto/gen-hash-testvecs.py | 8 20 files changed, 2495 insertions(+), 16 deletions(-)
Add SHA3, providing SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128 and
SHAKE256 to lib/crypto.
The state array handling is simplified from what's in crypto/sha3_generic.c
by keeping the state array (a u64[25]) in LE form and byteswapping all the
entries before and after applying the keccak function on a BE system. This
means no byteswapping is required when XOR'ing data into the state array or
when extracting the digest. Further, this is a no-op on LE systems.
Also:
- Perform a multistage shake256 hash check in the module initialisation.
- Add kunit tests for each algorithm based on the gen-hash-testvecs.
- The conflicting static s390x crypto function names are renamed to have
an s390_ prefix.
- gen-hash-testvecs.py had to be modified to be able to generate SHAKE
hashes because Python's hashlib requires the output digest size
supplying for those two algorithms as they produce arbitrary length
digests.
Notes:
(1) I've left hooks in sha3.c for asm-optimised variants, but as I don't
entirely know what those might look like, not having implemented any,
the hooks' usability is uncertain.
(2) The SHAKE algorithms will be required for ML-DSA.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Eric Biggers <ebiggers@kernel.org>
cc: Jason A. Donenfeld <Jason@zx2c4.com>
cc: Ard Biesheuvel <ardb@kernel.org>
cc: Harald Freudenberger <freude@linux.ibm.com>
cc: Holger Dengler <dengler@linux.ibm.com>
cc: Herbert Xu <herbert@gondor.apana.org.au>
cc: Stephan Mueller <smueller@chronox.de>
cc: linux-crypto@vger.kernel.org
cc: linux-s390@vger.kernel.org
---
Changes
=======
v2)
- Simplify the endianness handling.
- Rename sha3_final() to sha3_squeeze() and don't clear the context at the
end as it's permitted to continue calling sha3_final() to extract
continuations of the digest (needed by ML-DSA).
- Don't reapply the end marker to the hash state in continuation
sha3_squeeze() unless sha3_update() gets called again (needed by
ML-DSA).
- Give sha3_squeeze() the amount of digest to produce as a parameter
rather than using ctx->digest_size and don't return the amount digested.
- Reimplement sha3_final() as a wrapper around sha3_squeeze() that
extracts ctx->digest_size amount of digest and then zeroes out the
context. The latter is necessary to avoid upsetting
hash-test-template.h.
- Provide a sha3_reinit() function to clear the state, but to leave the
parameters that indicate the hash properties unaffected, allowing for
reuse.
- Provide a sha3_set_digestsize() function to change the size of the
digest to be extracted by sha3_final(). sha3_squeeze() takes a
parameter for this instead.
- Don't pass the digest size as a parameter to shake128/256_init() but
rather default to 128/256 bits as per the function name.
- Provide a sha3_clear() function to zero out the context.
arch/s390/crypto/sha3_256_s390.c | 26 -
include/crypto/sha3.h | 160 +++++++-
lib/crypto/Kconfig | 7
lib/crypto/Makefile | 6
lib/crypto/sha3.c | 597 ++++++++++++++++++++++++++++++
lib/crypto/tests/Kconfig | 12
lib/crypto/tests/Makefile | 7
lib/crypto/tests/sha3_224_kunit.c | 32 +
lib/crypto/tests/sha3_224_testvecs.h | 231 +++++++++++
lib/crypto/tests/sha3_256_kunit.c | 32 +
lib/crypto/tests/sha3_256_testvecs.h | 231 +++++++++++
lib/crypto/tests/sha3_384_kunit.c | 32 +
lib/crypto/tests/sha3_384_testvecs.h | 281 ++++++++++++++
lib/crypto/tests/sha3_512_kunit.c | 32 +
lib/crypto/tests/sha3_512_testvecs.h | 331 ++++++++++++++++
lib/crypto/tests/sha3_shake128_kunit.c | 37 +
lib/crypto/tests/sha3_shake128_testvecs.h | 181 +++++++++
lib/crypto/tests/sha3_shake256_kunit.c | 37 +
lib/crypto/tests/sha3_shake256_testvecs.h | 231 +++++++++++
scripts/crypto/gen-hash-testvecs.py | 8
20 files changed, 2495 insertions(+), 16 deletions(-)
diff --git a/arch/s390/crypto/sha3_256_s390.c b/arch/s390/crypto/sha3_256_s390.c
index 03bb4f4bab70..fd5ecae60a57 100644
--- a/arch/s390/crypto/sha3_256_s390.c
+++ b/arch/s390/crypto/sha3_256_s390.c
@@ -19,7 +19,7 @@
#include "sha.h"
-static int sha3_256_init(struct shash_desc *desc)
+static int s390_sha3_256_init(struct shash_desc *desc)
{
struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
@@ -32,7 +32,7 @@ static int sha3_256_init(struct shash_desc *desc)
return 0;
}
-static int sha3_256_export(struct shash_desc *desc, void *out)
+static int s390_sha3_256_export(struct shash_desc *desc, void *out)
{
struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
union {
@@ -50,7 +50,7 @@ static int sha3_256_export(struct shash_desc *desc, void *out)
return 0;
}
-static int sha3_256_import(struct shash_desc *desc, const void *in)
+static int s390_sha3_256_import(struct shash_desc *desc, const void *in)
{
struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
union {
@@ -68,22 +68,22 @@ static int sha3_256_import(struct shash_desc *desc, const void *in)
return 0;
}
-static int sha3_224_import(struct shash_desc *desc, const void *in)
+static int s390_sha3_224_import(struct shash_desc *desc, const void *in)
{
struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
- sha3_256_import(desc, in);
+ s390_sha3_256_import(desc, in);
sctx->func = CPACF_KIMD_SHA3_224;
return 0;
}
static struct shash_alg sha3_256_alg = {
.digestsize = SHA3_256_DIGEST_SIZE, /* = 32 */
- .init = sha3_256_init,
+ .init = s390_sha3_256_init,
.update = s390_sha_update_blocks,
.finup = s390_sha_finup,
- .export = sha3_256_export,
- .import = sha3_256_import,
+ .export = s390_sha3_256_export,
+ .import = s390_sha3_256_import,
.descsize = S390_SHA_CTX_SIZE,
.statesize = SHA3_STATE_SIZE,
.base = {
@@ -96,22 +96,22 @@ static struct shash_alg sha3_256_alg = {
}
};
-static int sha3_224_init(struct shash_desc *desc)
+static int s390_sha3_224_init(struct shash_desc *desc)
{
struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
- sha3_256_init(desc);
+ s390_sha3_256_init(desc);
sctx->func = CPACF_KIMD_SHA3_224;
return 0;
}
static struct shash_alg sha3_224_alg = {
.digestsize = SHA3_224_DIGEST_SIZE,
- .init = sha3_224_init,
+ .init = s390_sha3_224_init,
.update = s390_sha_update_blocks,
.finup = s390_sha_finup,
- .export = sha3_256_export, /* same as for 256 */
- .import = sha3_224_import, /* function code different! */
+ .export = s390_sha3_256_export, /* same as for 256 */
+ .import = s390_sha3_224_import, /* function code different! */
.descsize = S390_SHA_CTX_SIZE,
.statesize = SHA3_STATE_SIZE,
.base = {
diff --git a/include/crypto/sha3.h b/include/crypto/sha3.h
index 41e1b83a6d91..a9adce8f2891 100644
--- a/include/crypto/sha3.h
+++ b/include/crypto/sha3.h
@@ -6,6 +6,7 @@
#define __CRYPTO_SHA3_H__
#include <linux/types.h>
+#include <linux/string.h>
#define SHA3_224_DIGEST_SIZE (224 / 8)
#define SHA3_224_BLOCK_SIZE (200 - 2 * SHA3_224_DIGEST_SIZE)
@@ -23,6 +24,14 @@
#define SHA3_512_BLOCK_SIZE (200 - 2 * SHA3_512_DIGEST_SIZE)
#define SHA3_512_EXPORT_SIZE SHA3_STATE_SIZE + SHA3_512_BLOCK_SIZE + 1
+/* SHAKE128 and SHAKE256 actually have variable digest size, but this
+ * is needed for the kunit tests.
+ */
+#define SHAKE128_DIGEST_SIZE (128 / 8)
+#define SHAKE128_BLOCK_SIZE (200 - 2 * SHAKE128_DIGEST_SIZE)
+#define SHAKE256_DIGEST_SIZE (256 / 8)
+#define SHAKE256_BLOCK_SIZE (200 - 2 * SHAKE256_DIGEST_SIZE)
+
#define SHA3_STATE_SIZE 200
struct shash_desc;
@@ -31,6 +40,155 @@ struct sha3_state {
u64 st[SHA3_STATE_SIZE / 8];
};
+struct sha3_ctx {
+ struct sha3_state state;
+ unsigned short digest_size; /* Output digest size in bytes */
+ u8 block_size; /* Block size in bytes */
+ u8 partial; /* Next state byte to absorb into */
+ u8 padding; /* Padding byte */
+ u8 squeeze_offset; /* Next state byte to extract */
+ bool end_marked; /* T if end marker inserted */
+};
+
int crypto_sha3_init(struct shash_desc *desc);
-#endif
+void sha3_init(struct sha3_ctx *ctx);
+
+/**
+ * sha3_224_init() - Initialize a SHA3-224 context for a new message
+ * @ctx: the context to initialize
+ */
+static inline void sha3_224_init(struct sha3_ctx *ctx)
+{
+ sha3_init(ctx);
+ ctx->block_size = SHA3_224_BLOCK_SIZE;
+ ctx->digest_size = SHA3_224_DIGEST_SIZE;
+ ctx->padding = 0x06;
+}
+
+/**
+ * sha3_256_init() - Initialize a SHA3-256 context for a new message
+ * @ctx: the context to initialize
+ */
+static inline void sha3_256_init(struct sha3_ctx *ctx)
+{
+ sha3_init(ctx);
+ ctx->block_size = SHA3_256_BLOCK_SIZE;
+ ctx->digest_size = SHA3_256_DIGEST_SIZE;
+ ctx->padding = 0x06;
+}
+
+/**
+ * sha3_384_init() - Initialize a SHA3-384 context for a new message
+ * @ctx: the context to initialize
+ */
+static inline void sha3_384_init(struct sha3_ctx *ctx)
+{
+ sha3_init(ctx);
+ ctx->block_size = SHA3_384_BLOCK_SIZE;
+ ctx->digest_size = SHA3_384_DIGEST_SIZE;
+ ctx->padding = 0x06;
+}
+
+/**
+ * sha3_512_init() - Initialize a SHA3-512 context for a new message
+ * @ctx: the context to initialize
+ */
+static inline void sha3_512_init(struct sha3_ctx *ctx)
+{
+ sha3_init(ctx);
+ ctx->block_size = SHA3_512_BLOCK_SIZE;
+ ctx->digest_size = SHA3_512_DIGEST_SIZE;
+ ctx->padding = 0x06;
+}
+
+/**
+ * shake128_init() - Initialize a SHAKE128 context for a new message
+ * @ctx: The context to initialize
+ */
+static inline void shake128_init(struct sha3_ctx *ctx)
+{
+ sha3_init(ctx);
+ ctx->block_size = SHAKE128_BLOCK_SIZE;
+ ctx->digest_size = SHAKE128_DIGEST_SIZE;
+ ctx->padding = 0x1f;
+}
+
+/**
+ * shake256_init() - Initialize a SHAKE256 context for a new message
+ * @ctx: the context to initialize
+ */
+static inline void shake256_init(struct sha3_ctx *ctx)
+{
+ sha3_init(ctx);
+ ctx->block_size = SHAKE256_BLOCK_SIZE;
+ ctx->digest_size = SHAKE256_DIGEST_SIZE;
+ ctx->padding = 0x1f;
+}
+
+/**
+ * sha3_set_digestsize() - Change the digest size for a SHAKE* hash
+ * @ctx: the context to modify
+ * @digest_size: The new size of the digest
+ */
+static inline void sha3_set_digestsize(struct sha3_ctx *ctx, unsigned int digest_size)
+{
+ ctx->digest_size = digest_size;
+}
+
+/**
+ * sha3_reinit() - Explicitly clear the hash working state
+ * @ctx: the context to clear
+ *
+ * Explicitly clear the hash state and reset the tracking members, but leave
+ * the hash property members unaffected.
+ */
+static inline void sha3_reinit(struct sha3_ctx *ctx)
+{
+ memzero_explicit(&ctx->state, sizeof(ctx->state));
+ ctx->partial = 0;
+ ctx->squeeze_offset = 0;
+ ctx->end_marked = false;
+}
+
+/**
+ * sha3_clear() - Explicitly clear the entire context
+ * @ctx: the context to clear
+ */
+static inline void sha3_clear(struct sha3_ctx *ctx)
+{
+ memzero_explicit(ctx, sizeof(*ctx));
+}
+
+void sha3_update(struct sha3_ctx *ctx, const u8 *data, unsigned int len);
+void sha3_squeeze(struct sha3_ctx *ctx, u8 *out, size_t out_len);
+void sha3_224(const u8 *in, size_t in_len, u8 out[SHA3_224_DIGEST_SIZE]);
+void sha3_256(const u8 *in, size_t in_len, u8 out[SHA3_256_DIGEST_SIZE]);
+void sha3_384(const u8 *in, size_t in_len, u8 out[SHA3_384_DIGEST_SIZE]);
+void sha3_512(const u8 *in, size_t in_len, u8 out[SHA3_512_DIGEST_SIZE]);
+void shake128(const u8 *in, size_t in_len, u8 *out, size_t out_len);
+void shake256(const u8 *in, size_t in_len, u8 *out, size_t out_len);
+
+/**
+ * sha3_squeeze() - Finalize a SHA3 digest of any type and extract the digest
+ * @ctx: The context to finalize; must have been initialized
+ * @out: Where to write the resulting message digest
+ * @out_size: The amount of digest to extract to @out
+ *
+ * Finish the computation of a SHA3 message digest of any type and perform the
+ * "Keccak sponge squeezing" phase. The digest is written to @out buffer and
+ * the size of the digest is returned. The amount of digest specified in @ctx
+ * will be extracted.
+ *
+ * Upon returning, the context will be zeroed out.
+ */
+static inline unsigned int sha3_final(struct sha3_ctx *ctx, u8 *out)
+{
+ unsigned int out_size = ctx->digest_size;
+
+ sha3_squeeze(ctx, out, out_size);
+ sha3_clear(ctx);
+ return out_size;
+}
+
+#endif /* __CRYPTO_SHA3_H__ */
diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig
index 1e6b008f8fca..5ea6abe934d6 100644
--- a/lib/crypto/Kconfig
+++ b/lib/crypto/Kconfig
@@ -191,6 +191,13 @@ config CRYPTO_LIB_SHA512_ARCH
default y if SPARC64
default y if X86_64
+config CRYPTO_LIB_SHA3
+ tristate
+ help
+ The SHA3 library functions.
+ Select this if your module uses any of these functions from
+ <crypto/sha3.h>.
+
config CRYPTO_LIB_SM3
tristate
diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
index 539d5d59a50e..bf73a2cfef86 100644
--- a/lib/crypto/Makefile
+++ b/lib/crypto/Makefile
@@ -149,6 +149,12 @@ endif # CONFIG_CRYPTO_LIB_SHA512_ARCH
################################################################################
+#obj-$(CONFIG_CRYPTO_LIB_SHA3) += libsha3.o
+#libsha3-y := sha3.o
+obj-$(CONFIG_CRYPTO_SHA3) += sha3.o
+
+################################################################################
+
obj-$(CONFIG_MPILIB) += mpi/
obj-$(CONFIG_CRYPTO_SELFTESTS_FULL) += simd.o
diff --git a/lib/crypto/sha3.c b/lib/crypto/sha3.c
new file mode 100644
index 000000000000..f4d7899f0042
--- /dev/null
+++ b/lib/crypto/sha3.c
@@ -0,0 +1,597 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Cryptographic API.
+ *
+ * SHA-3, as specified in
+ * https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
+ *
+ * SHA-3 code by Jeff Garzik <jeff@garzik.org>
+ * Ard Biesheuvel <ard.biesheuvel@linaro.org>
+ * David Howells <dhowells@redhat.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <crypto/sha3.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/unaligned.h>
+
+#if 0
+static void sha3_dump_state(const struct sha3_ctx *ctx, const char *prefix)
+{
+ const __be64 *p = (const __be64 *)ctx->state.st;
+
+ for (int i = 0; i < 6; i++) {
+ pr_info("SHA3 %s %016llx %016llx %016llx %016llx\n",
+ prefix,
+ be64_to_cpu(p[0]), be64_to_cpu(p[1]),
+ be64_to_cpu(p[2]), be64_to_cpu(p[3]));
+ p += 4;
+ }
+ pr_info("SHA3 %s %016llx\n", prefix, be64_to_cpu(p[0]));
+}
+#endif
+
+/*
+ * On some 32-bit architectures (h8300), GCC ends up using
+ * over 1 KB of stack if we inline the round calculation into the loop
+ * in keccakf(). On the other hand, on 64-bit architectures with plenty
+ * of [64-bit wide] general purpose registers, not inlining it severely
+ * hurts performance. So let's use 64-bitness as a heuristic to decide
+ * whether to inline or not.
+ */
+#ifdef CONFIG_64BIT
+#define SHA3_INLINE inline
+#else
+#define SHA3_INLINE noinline
+#endif
+
+#define KECCAK_ROUNDS 24
+
+static const u64 keccakf_rndc[24] = {
+ 0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
+ 0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
+ 0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
+ 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
+ 0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
+ 0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
+ 0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
+ 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
+};
+
+/* update the state with given number of rounds */
+
+static SHA3_INLINE void keccakf_round(u64 st[25])
+{
+ u64 t[5], tt, bc[5];
+
+ /* Theta */
+ bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
+ bc[1] = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21];
+ bc[2] = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22];
+ bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
+ bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
+
+ t[0] = bc[4] ^ rol64(bc[1], 1);
+ t[1] = bc[0] ^ rol64(bc[2], 1);
+ t[2] = bc[1] ^ rol64(bc[3], 1);
+ t[3] = bc[2] ^ rol64(bc[4], 1);
+ t[4] = bc[3] ^ rol64(bc[0], 1);
+
+ st[0] ^= t[0];
+
+ /* Rho Pi */
+ tt = st[1];
+ st[ 1] = rol64(st[ 6] ^ t[1], 44);
+ st[ 6] = rol64(st[ 9] ^ t[4], 20);
+ st[ 9] = rol64(st[22] ^ t[2], 61);
+ st[22] = rol64(st[14] ^ t[4], 39);
+ st[14] = rol64(st[20] ^ t[0], 18);
+ st[20] = rol64(st[ 2] ^ t[2], 62);
+ st[ 2] = rol64(st[12] ^ t[2], 43);
+ st[12] = rol64(st[13] ^ t[3], 25);
+ st[13] = rol64(st[19] ^ t[4], 8);
+ st[19] = rol64(st[23] ^ t[3], 56);
+ st[23] = rol64(st[15] ^ t[0], 41);
+ st[15] = rol64(st[ 4] ^ t[4], 27);
+ st[ 4] = rol64(st[24] ^ t[4], 14);
+ st[24] = rol64(st[21] ^ t[1], 2);
+ st[21] = rol64(st[ 8] ^ t[3], 55);
+ st[ 8] = rol64(st[16] ^ t[1], 45);
+ st[16] = rol64(st[ 5] ^ t[0], 36);
+ st[ 5] = rol64(st[ 3] ^ t[3], 28);
+ st[ 3] = rol64(st[18] ^ t[3], 21);
+ st[18] = rol64(st[17] ^ t[2], 15);
+ st[17] = rol64(st[11] ^ t[1], 10);
+ st[11] = rol64(st[ 7] ^ t[2], 6);
+ st[ 7] = rol64(st[10] ^ t[0], 3);
+ st[10] = rol64( tt ^ t[1], 1);
+
+ /* Chi */
+ bc[ 0] = ~st[ 1] & st[ 2];
+ bc[ 1] = ~st[ 2] & st[ 3];
+ bc[ 2] = ~st[ 3] & st[ 4];
+ bc[ 3] = ~st[ 4] & st[ 0];
+ bc[ 4] = ~st[ 0] & st[ 1];
+ st[ 0] ^= bc[ 0];
+ st[ 1] ^= bc[ 1];
+ st[ 2] ^= bc[ 2];
+ st[ 3] ^= bc[ 3];
+ st[ 4] ^= bc[ 4];
+
+ bc[ 0] = ~st[ 6] & st[ 7];
+ bc[ 1] = ~st[ 7] & st[ 8];
+ bc[ 2] = ~st[ 8] & st[ 9];
+ bc[ 3] = ~st[ 9] & st[ 5];
+ bc[ 4] = ~st[ 5] & st[ 6];
+ st[ 5] ^= bc[ 0];
+ st[ 6] ^= bc[ 1];
+ st[ 7] ^= bc[ 2];
+ st[ 8] ^= bc[ 3];
+ st[ 9] ^= bc[ 4];
+
+ bc[ 0] = ~st[11] & st[12];
+ bc[ 1] = ~st[12] & st[13];
+ bc[ 2] = ~st[13] & st[14];
+ bc[ 3] = ~st[14] & st[10];
+ bc[ 4] = ~st[10] & st[11];
+ st[10] ^= bc[ 0];
+ st[11] ^= bc[ 1];
+ st[12] ^= bc[ 2];
+ st[13] ^= bc[ 3];
+ st[14] ^= bc[ 4];
+
+ bc[ 0] = ~st[16] & st[17];
+ bc[ 1] = ~st[17] & st[18];
+ bc[ 2] = ~st[18] & st[19];
+ bc[ 3] = ~st[19] & st[15];
+ bc[ 4] = ~st[15] & st[16];
+ st[15] ^= bc[ 0];
+ st[16] ^= bc[ 1];
+ st[17] ^= bc[ 2];
+ st[18] ^= bc[ 3];
+ st[19] ^= bc[ 4];
+
+ bc[ 0] = ~st[21] & st[22];
+ bc[ 1] = ~st[22] & st[23];
+ bc[ 2] = ~st[23] & st[24];
+ bc[ 3] = ~st[24] & st[20];
+ bc[ 4] = ~st[20] & st[21];
+ st[20] ^= bc[ 0];
+ st[21] ^= bc[ 1];
+ st[22] ^= bc[ 2];
+ st[23] ^= bc[ 3];
+ st[24] ^= bc[ 4];
+}
+
+static void sha3_be_swap_state(u64 st[25])
+{
+#ifdef __BIG_ENDIAN
+ for (int i = 0; i < 25; i++)
+ st[i] = __builtin_bswap64(st[i]);
+#endif
+}
+
+/*
+ * Perform the mixing step.
+ */
+static void sha3_keccakf_generic(u64 st[25])
+{
+ int round;
+
+ sha3_be_swap_state(st);
+
+ for (round = 0; round < KECCAK_ROUNDS; round++) {
+ keccakf_round(st);
+ /* Iota */
+ st[0] ^= keccakf_rndc[round];
+ }
+
+ sha3_be_swap_state(st);
+}
+
+static void sha3_absorb_block_generic(struct sha3_ctx *ctx, const u8 *data)
+{
+ struct sha3_state *state = &ctx->state;
+ unsigned int bsize = ctx->block_size;
+
+ for (int i = 0; i < bsize / 8; i++)
+ state->st[i] ^= get_unaligned((u64 *)(data + 8 * i));
+ sha3_keccakf_generic(state->st);
+}
+
+/*
+ * Perform rounds of XOR'ing whole blocks of data into the state buffer and
+ * then performing a keccak mix step.
+ */
+static void
+sha3_absorb_blocks_generic(struct sha3_ctx *ctx, const u8 *data, size_t nblocks)
+{
+ do {
+ sha3_absorb_block_generic(ctx, data);
+ data += ctx->block_size;
+ } while (--nblocks);
+}
+
+#ifdef CONFIG_CRYPTO_LIB_SHA3_ARCH
+#include "sha3.h" /* $(SRCARCH)/sha3.h */
+#else
+#define sha3_keccakf sha3_keccakf_generic
+#define sha3_absorb_blocks sha3_absorb_blocks_generic
+#endif
+
+/*
+ * XOR in partial data that's insufficient to fill a whole block.
+ */
+static void sha3_absorb_xorle(struct sha3_ctx *ctx, const u8 *data,
+ unsigned int partial, unsigned int len)
+{
+ u8 *buf = (u8 *)ctx->state.st;
+
+ buf += partial;
+ for (int i = 0; i < len; i++)
+ *buf++ ^= *data++;
+}
+
+/**
+ * sha3_update() - Update a SHA3 context of any type with message data
+ * @ctx: the context to update; must have been initialized
+ * @data: the message data
+ * @len: the data length in bytes
+ *
+ * This can be called any number of times to perform the "keccak sponge
+ * absorbing" phase.
+ *
+ * It may be called again after @sha3_final() has been called to add more data
+ * to the hash. Note, however, that finalising a hash modifies the state, so
+ * {update,final,update} is not equivalent to {update,update}.
+ */
+void sha3_update(struct sha3_ctx *ctx, const u8 *data, unsigned int len)
+{
+ unsigned int partial = ctx->partial;
+ unsigned int bsize = ctx->block_size;
+
+ if (partial && partial + len >= bsize) {
+ sha3_absorb_xorle(ctx, data, partial, bsize - partial);
+ len -= bsize - partial;
+ data += bsize - partial;
+ sha3_keccakf(ctx->state.st);
+ ctx->partial = 0;
+ }
+
+ if (len >= bsize) {
+ size_t nblocks = len / bsize;
+
+ if (nblocks) {
+ sha3_absorb_blocks(ctx, data, nblocks);
+ data += nblocks * bsize;
+ len -= nblocks * bsize;
+ }
+ }
+
+ if (len) {
+ sha3_absorb_xorle(ctx, data, ctx->partial, len);
+ ctx->partial += len;
+ }
+ ctx->end_marked = false;
+}
+EXPORT_SYMBOL_GPL(sha3_update);
+
+/**
+ * sha3_squeeze() - Finalize a SHA3 digest of any type and extract the digest
+ * @ctx: the context to finalize; must have been initialized
+ * @out: Where to write the resulting message digest
+ * @out_size: The amount of digest to extract to @out
+ *
+ * Finish the computation of a SHA3 message digest of any type and perform the
+ * "Keccak sponge squeezing" phase. @out_size amount of digest is written to
+ * @out buffer.
+ *
+ * This may be called multiple times to extract continuations of the digest.
+ * Note that, for example, two consecutive 16-byte squeezes laid end-to-end
+ * will yield the same as one 32-byte squeeze.
+ *
+ * The state will have the end marker added again if any new updates have
+ * happened since the last time it was squeezed.
+ */
+void sha3_squeeze(struct sha3_ctx *ctx, u8 *out, size_t out_size)
+{
+ unsigned int squeeze_offset = ctx->squeeze_offset;
+ unsigned int digest_size = out_size;
+ unsigned int bsize = ctx->block_size;
+ u8 *p = (u8 *)ctx->state.st, end_marker = 0x80;
+
+ if (!ctx->end_marked) {
+ sha3_absorb_xorle(ctx, &ctx->padding, ctx->partial, 1);
+ sha3_absorb_xorle(ctx, &end_marker, bsize - 1, 1);
+ ctx->end_marked = true;
+ }
+
+ for (;;) {
+ if (squeeze_offset == 0) {
+ sha3_keccakf(ctx->state.st);
+ }
+
+ unsigned int part = umin(digest_size, bsize - squeeze_offset);
+
+ if (part > 0) {
+ memcpy(out, p + squeeze_offset, part);
+ digest_size -= part;
+ out += part;
+ squeeze_offset += part;
+ }
+ if (!digest_size)
+ break;
+ if (squeeze_offset >= bsize)
+ squeeze_offset -= bsize;
+ }
+
+ ctx->squeeze_offset = squeeze_offset;
+}
+EXPORT_SYMBOL_GPL(sha3_squeeze);
+
+/**
+ * sha3_init() - Initialize a SHA3 context for a new message
+ * @ctx: the context to initialize
+ *
+ * Initialize a SHA3 context for any size of SHA-3 digest.
+ */
+void sha3_init(struct sha3_ctx *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+}
+EXPORT_SYMBOL_GPL(sha3_init);
+
+/**
+ * sha3_224() - Convenience wrapper to digest a simple buffer as SHA3-224
+ * @in: The data to be digested
+ * @in_len: The amount of data to be digested
+ * @out: The buffer into which the digest will be stored (size not checked)
+ */
+void sha3_224(const u8 *in, size_t in_len, u8 out[SHA3_224_DIGEST_SIZE])
+{
+ struct sha3_ctx ctx;
+
+ sha3_224_init(&ctx);
+ sha3_update(&ctx, in, in_len);
+ sha3_final(&ctx, out);
+}
+EXPORT_SYMBOL(sha3_224);
+
+/**
+ * sha3_256() - Convenience wrapper to digest a simple buffer as SHA3-256
+ * @in: The data to be digested
+ * @in_len: The amount of data to be digested
+ * @out: The buffer into which the digest will be stored (size not checked)
+ */
+void sha3_256(const u8 *in, size_t in_len, u8 out[SHA3_256_DIGEST_SIZE])
+{
+ struct sha3_ctx ctx;
+
+ sha3_256_init(&ctx);
+ sha3_update(&ctx, in, in_len);
+ sha3_final(&ctx, out);
+}
+EXPORT_SYMBOL(sha3_256);
+
+/**
+ * sha3_384() - Convenience wrapper to digest a simple buffer as SHA3-384
+ * @in: The data to be digested
+ * @in_len: The amount of data to be digested
+ * @out: The buffer into which the digest will be stored (size not checked)
+ */
+void sha3_384(const u8 *in, size_t in_len, u8 out[SHA3_384_DIGEST_SIZE])
+{
+ struct sha3_ctx ctx;
+
+ sha3_384_init(&ctx);
+ sha3_update(&ctx, in, in_len);
+ sha3_final(&ctx, out);
+}
+EXPORT_SYMBOL(sha3_384);
+
+/**
+ * sha3_512() - Convenience wrapper to digest a simple buffer as SHA3-512
+ * @in: The data to be digested
+ * @in_len: The amount of data to be digested
+ * @out: The buffer into which the digest will be stored (size not checked)
+ */
+void sha3_512(const u8 *in, size_t in_len, u8 out[SHA3_512_DIGEST_SIZE])
+{
+ struct sha3_ctx ctx;
+
+ sha3_512_init(&ctx);
+ sha3_update(&ctx, in, in_len);
+ sha3_final(&ctx, out);
+}
+EXPORT_SYMBOL(sha3_512);
+
+/**
+ * shake128() - Convenience wrapper to digest a simple buffer as SHAKE128
+ * @in: The data to be digested
+ * @in_len: The amount of data to be digested
+ * @out: The buffer into which the digest will be stored
+ * @out_len: The size of the digest desired (variable length)
+ */
+void shake128(const u8 *in, size_t in_len, u8 *out, size_t out_len)
+{
+ struct sha3_ctx ctx;
+
+ shake128_init(&ctx);
+ sha3_update(&ctx, in, in_len);
+ sha3_squeeze(&ctx, out, out_len);
+ sha3_clear(&ctx);
+}
+EXPORT_SYMBOL(shake128);
+
+/**
+ * shake256() - Convenience wrapper to digest a simple buffer as SHAKE256
+ * @in: The data to be digested
+ * @in_len: The amount of data to be digested
+ * @out: The buffer into which the digest will be stored
+ * @out_len: The size of the digest desired (variable length)
+ */
+void shake256(const u8 *in, size_t in_len, u8 *out, size_t out_len)
+{
+ struct sha3_ctx ctx;
+
+ shake256_init(&ctx);
+ sha3_update(&ctx, in, in_len);
+ sha3_squeeze(&ctx, out, out_len);
+ sha3_clear(&ctx);
+}
+EXPORT_SYMBOL(shake256);
+
+/*
+ * Do a quick test using SHAKE256 and a 200 byte digest.
+ */
+static const u8 sha3_sample1[] __initconst =
+ "The quick red fox jumped over the lazy brown dog!\n"
+ "The quick red fox jumped over the lazy brown dog!\n"
+ "The quick red fox jumped over the lazy brown dog!\n"
+ "The quick red fox jumped over the lazy brown dog!\n";
+static const u8 sha3_sample2[] __initconst =
+ "hello\n";
+static const u8 sha3_sample_shake256_200_step1[] __initconst = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
+ 0xab, 0x06, 0xd4, 0xf9, 0x8b, 0xfd, 0xb2, 0xc4, 0xfe, 0xf1, 0xcc, 0xe2,
+ 0x40, 0x45, 0xdd, 0x15, 0xcb, 0xdd, 0x02, 0x8d, 0xb7, 0x9f, 0x1e, 0x67,
+ 0xd6, 0x7f, 0x98, 0x5e, 0x1b, 0x19, 0xf8, 0x01, 0x43, 0x82, 0xcb, 0xd8,
+ 0x5d, 0x21, 0x64, 0xa8, 0x80, 0xc9, 0x22, 0xe5, 0x07, 0xaf, 0xe2, 0x5d,
+ 0xcd, 0xc6, 0x23, 0x36, 0x2b, 0xc7, 0xc7, 0x7d, 0x09, 0x9d, 0x68, 0x05,
+ 0xe4, 0x62, 0x63, 0x1b, 0x67, 0xbc, 0xf8, 0x95, 0x07, 0xd2, 0xe4, 0xd0,
+ 0xba, 0xa2, 0x67, 0xf5, 0xe3, 0x15, 0xbc, 0x85, 0xa1, 0x50, 0xd6, 0x6f,
+ 0x6f, 0xd4, 0x54, 0x4c, 0x3f, 0x4f, 0xe5, 0x1f, 0xb7, 0x00, 0x27, 0xfc,
+ 0x15, 0x33, 0xc2, 0xf9, 0xb3, 0x4b, 0x9e, 0x81, 0xe5, 0x96, 0xbe, 0x05,
+ 0x6c, 0xac, 0xf9, 0x9f, 0x65, 0x36, 0xbb, 0x11, 0x47, 0x6d, 0xf6, 0x8f,
+ 0x9f, 0xa2, 0x77, 0x37, 0x3b, 0x18, 0x77, 0xcf, 0x65, 0xc5, 0xa1, 0x7e,
+ 0x2c, 0x0e, 0x71, 0xf0, 0x4d, 0x18, 0x67, 0xb9, 0xc4, 0x8c, 0x64, 0x3b,
+ 0x4b, 0x45, 0xea, 0x16, 0xb2, 0x4a, 0xc5, 0xf5, 0x85, 0xdc, 0xd2, 0xd9,
+ 0x13, 0x77, 0xb3, 0x19, 0xd9, 0x8c, 0x9f, 0x28, 0xe7, 0x64, 0x91, 0x0f,
+ 0x6f, 0x32, 0xbf, 0xa8, 0xa8, 0xa3, 0xff, 0x99, 0x0e, 0x0b, 0x62, 0x50,
+ 0xf8, 0x3a, 0xc2, 0xf5, 0x98, 0x21, 0xeb, 0x9d, 0xe8, 0x45, 0xf4, 0x46,
+ 0x1e, 0x8b, 0xbd, 0x10, 0x59, 0x2c, 0x87, 0xe2,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
+};
+static const u8 sha3_sample_shake256_200_step2[] __initconst = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
+ 0x5b, 0x43, 0x98, 0x3a, 0x4a, 0x5f, 0xa9, 0x14, 0xa5, 0x98, 0x26, 0xe2,
+ 0xed, 0x45, 0x6a, 0x1d, 0x61, 0x24, 0xf5, 0x0c, 0xef, 0xda, 0xc2, 0x8a,
+ 0x30, 0x0e, 0x03, 0xe5, 0x67, 0xdd, 0x7e, 0x9f, 0xa0, 0xa4, 0x07, 0x63,
+ 0xdc, 0x6b, 0x7e, 0xbd, 0xd7, 0x7d, 0x7a, 0x6d, 0x55, 0x03, 0x02, 0x18,
+ 0x12, 0x5d, 0xf9, 0x21, 0xc8, 0x78, 0x69, 0x7c, 0x64, 0x39, 0xfd, 0xf4,
+ 0xd6, 0x06, 0xe6, 0xd8, 0x6f, 0xaa, 0x04, 0x5b, 0x40, 0xf3, 0x96, 0xb2,
+ 0xb5, 0xd0, 0xb5, 0x43, 0x50, 0x9c, 0x08, 0xd6, 0x54, 0x8e, 0x8c, 0x85,
+ 0xc2, 0x34, 0xce, 0x0c, 0x24, 0x31, 0x6f, 0x49, 0xec, 0x3d, 0x13, 0x1f,
+ 0x36, 0x0a, 0x14, 0xa6, 0x5d, 0x51, 0x9a, 0x90, 0x1f, 0xf5, 0x1f, 0x61,
+ 0xb7, 0x65, 0x64, 0x2a, 0x00, 0x07, 0xe4, 0x56, 0x80, 0x5c, 0xfa, 0x03,
+ 0xc4, 0x97, 0xc1, 0x09, 0x35, 0xa2, 0x55, 0x72, 0x28, 0xe5, 0xb6, 0xef,
+ 0x8e, 0xf4, 0xc2, 0x82, 0x22, 0xc7, 0x23, 0xac, 0xcb, 0xc1, 0x03, 0x52,
+ 0x46, 0x9c, 0x17, 0xe0, 0xa3, 0x1b, 0x59, 0x9f, 0x01, 0xef, 0x5b, 0x46,
+ 0xb2, 0x4b, 0x98, 0x6b, 0x32, 0x52, 0xe3, 0x29, 0x36, 0x8f, 0x66, 0x98,
+ 0x5f, 0x6a, 0xa2, 0xf4, 0x68, 0x13, 0x5c, 0x94, 0xe4, 0x22, 0xb6, 0x83,
+ 0xa0, 0xd7, 0xa3, 0xda, 0xa4, 0x84, 0x0c, 0xf6, 0xa2, 0xa4, 0x0e, 0x08,
+ 0x6d, 0x2b, 0xd2, 0x31, 0x77, 0x36, 0xae, 0x53,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
+};
+
+static const u8 sha3_sample_shake256_200_step3[] __initconst = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
+ 0x61, 0x0a, 0x5e, 0xdf, 0xf1, 0x29, 0xae, 0x82, 0xab, 0x57, 0xa8, 0x1b,
+ 0x4e, 0x7c, 0xb9, 0x14, 0x4a, 0x32, 0x7d, 0x82, 0xdc, 0xc2, 0x48, 0x1c,
+ 0xf4, 0xa4, 0x18, 0xd5, 0x97, 0x35, 0x9a, 0x25, 0x0f, 0x5f, 0x1b, 0x04,
+ 0xf1, 0x09, 0x2a, 0xe8, 0xb6, 0xa7, 0xe1, 0x90, 0xb6, 0x4d, 0x96, 0xf1,
+ 0x7d, 0x4d, 0xb0, 0x4f, 0x44, 0xaf, 0x16, 0x4e, 0x63, 0xce, 0x46, 0x4c,
+ 0x76, 0x18, 0xbe, 0x5f, 0xf4, 0x35, 0xef, 0x1f, 0xb1, 0x97, 0x94, 0x70,
+ 0x96, 0x2f, 0xa2, 0x1b, 0xd6, 0x02, 0x51, 0x88, 0x33, 0x2b, 0x54, 0xb9,
+ 0x44, 0xb4, 0xab, 0x6f, 0xeb, 0xfc, 0xe5, 0xee, 0xe3, 0x77, 0x91, 0xed,
+ 0x3a, 0x4e, 0x60, 0x00, 0x44, 0xd1, 0xc7, 0x4a, 0x54, 0x77, 0x71, 0x95,
+ 0x53, 0x88, 0x6b, 0x1e, 0x0f, 0xfd, 0x62, 0x02, 0xa7, 0x8e, 0x05, 0x6d,
+ 0x21, 0x8f, 0x97, 0x20, 0xa0, 0xd7, 0xcf, 0xd8, 0x54, 0xec, 0x50, 0x72,
+ 0x07, 0xb8, 0x9c, 0x76, 0xdb, 0x12, 0x00, 0xd2, 0x2e, 0x93, 0xee, 0xb9,
+ 0x6a, 0x28, 0x5a, 0x46, 0x87, 0x90, 0xd5, 0xd6, 0x1d, 0x14, 0x0e, 0x16,
+ 0xf1, 0x2c, 0xed, 0x7f, 0x28, 0x34, 0x8c, 0x2b, 0x96, 0x03, 0x80, 0x80,
+ 0x9f, 0xc8, 0xf4, 0x2c, 0x53, 0xe0, 0x4b, 0x7b, 0xf4, 0x19, 0x8a, 0xc5,
+ 0xb3, 0x21, 0x17, 0xce, 0xdb, 0xbf, 0xb7, 0x6b, 0x9a, 0xb5, 0x19, 0x89,
+ 0x4c, 0x54, 0x28, 0x32, 0xe6, 0x85, 0xfa, 0x8f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
+};
+static const u8 sha3_sample_shake256_200_step4[] __initconst = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
+ 0x83, 0x99, 0xc6, 0xda, 0x75, 0x79, 0x8e, 0x47, 0x06, 0xad, 0x19, 0xcb,
+ 0x47, 0x61, 0x25, 0x6a, 0x8c, 0xa4, 0x7e, 0x74, 0xba, 0xbd, 0xda, 0xb6,
+ 0x3b, 0x08, 0x48, 0x0f, 0x55, 0xd5, 0x85, 0x78, 0x5b, 0xd4, 0x31, 0xcb,
+ 0x59, 0xff, 0x93, 0xff, 0xf6, 0x65, 0x4c, 0xf7, 0x6e, 0x4b, 0xef, 0x4d,
+ 0x0e, 0x43, 0x8a, 0x2b, 0xed, 0x10, 0x26, 0x68, 0x12, 0x63, 0xed, 0x7a,
+ 0x38, 0x0a, 0xa5, 0xd0, 0x79, 0x26, 0x75, 0xef, 0xce, 0xad, 0x6c, 0x12,
+ 0x52, 0x33, 0xec, 0xe8, 0xe1, 0x89, 0x2f, 0x0f, 0x29, 0xb0, 0xf6, 0xff,
+ 0x54, 0x11, 0xb2, 0x6b, 0x22, 0xb3, 0x48, 0x01, 0xa5, 0xcf, 0x29, 0xb7,
+ 0xaf, 0x8c, 0xec, 0x1e, 0x75, 0x3e, 0xff, 0xfb, 0x31, 0xb8, 0xf6, 0xab,
+ 0xae, 0xac, 0xec, 0xed, 0x27, 0x0b, 0x79, 0x10, 0x4f, 0x87, 0xe8, 0x43,
+ 0x28, 0x94, 0x09, 0xca, 0x48, 0x63, 0x65, 0x61, 0x86, 0x83, 0x33, 0x30,
+ 0x02, 0x6d, 0xf4, 0xef, 0x3c, 0x1a, 0x47, 0x8a, 0x25, 0x90, 0x31, 0x39,
+ 0x95, 0x1d, 0x6f, 0x11, 0x5c, 0x0c, 0x72, 0xe6, 0x1b, 0xe1, 0x60, 0x45,
+ 0x79, 0x89, 0x39, 0x48, 0x31, 0x4c, 0xc4, 0xd1, 0x08, 0x12, 0xf3, 0x5f,
+ 0x84, 0x8c, 0x86, 0xba, 0xe5, 0xf1, 0x24, 0x61, 0x2f, 0xef, 0x17, 0x16,
+ 0x4a, 0x29, 0xc0, 0xc6, 0x38, 0x47, 0x3a, 0x11, 0xc5, 0x7d, 0x62, 0x85,
+ 0x9b, 0x18, 0x92, 0x4c, 0x12, 0x92, 0x9c, 0x0b,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
+};
+
+static void __init sha3_check_digest(const u8 *digest, const u8 *sample_digest,
+ int digest_len)
+{
+ if (memcmp(digest, sample_digest, digest_len) != 0) {
+ pr_err("SHAKE256(200) failed\n");
+ for (int i = 0; i < digest_len;) {
+ int part = min(digest_len - i, 32);
+
+ pr_err("%*phN\n", part, digest + i);
+ i += part;
+ }
+ }
+}
+
+static int __init sha3_mod_init(void)
+{
+#define dsize 200
+ struct sha3_ctx ctx;
+ u8 digest[8 + dsize + 8] = {};
+
+#ifdef sha3_mod_init_arch
+ sha3_mod_init_arch();
+#endif
+
+ BUILD_BUG_ON(sizeof(digest) != sizeof(sha3_sample_shake256_200_step1) ||
+ sizeof(digest) != sizeof(sha3_sample_shake256_200_step2) ||
+ sizeof(digest) != sizeof(sha3_sample_shake256_200_step3) ||
+ sizeof(digest) != sizeof(sha3_sample_shake256_200_step4));
+
+ shake256_init(&ctx);
+ sha3_update(&ctx, sha3_sample1, sizeof(sha3_sample1) - 1);
+ sha3_squeeze(&ctx, digest + 8, dsize);
+ sha3_check_digest(digest, sha3_sample_shake256_200_step1, sizeof(digest));
+
+ sha3_squeeze(&ctx, digest + 8, dsize);
+ sha3_check_digest(digest, sha3_sample_shake256_200_step2, sizeof(digest));
+
+ sha3_squeeze(&ctx, digest + 8, dsize);
+ sha3_check_digest(digest, sha3_sample_shake256_200_step3, sizeof(digest));
+
+ sha3_update(&ctx, sha3_sample2, sizeof(sha3_sample2) - 1);
+ sha3_squeeze(&ctx, digest + 8, dsize);
+ sha3_check_digest(digest, sha3_sample_shake256_200_step4, sizeof(digest));
+ return 0;
+}
+subsys_initcall(sha3_mod_init);
+
+#ifdef sha3_mod_init_arch
+static void __exit sha3_mod_exit(void)
+{
+}
+module_exit(sha3_mod_exit);
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA-3 Secure Hash Algorithm");
diff --git a/lib/crypto/tests/Kconfig b/lib/crypto/tests/Kconfig
index de7e8babb6af..43b39616dce1 100644
--- a/lib/crypto/tests/Kconfig
+++ b/lib/crypto/tests/Kconfig
@@ -43,6 +43,18 @@ config CRYPTO_LIB_SHA512_KUNIT_TEST
KUnit tests for the SHA-384 and SHA-512 cryptographic hash functions
and their corresponding HMACs.
+config CRYPTO_LIB_SHA3_KUNIT_TEST
+ tristate "KUnit tests for SHA-3" if !KUNIT_ALL_TESTS
+ depends on KUNIT
+ default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS
+ select CRYPTO_LIB_BENCHMARK_VISIBLE
+ select CRYPTO_LIB_SHA3
+ help
+ KUnit tests for the SHA3 cryptographic hash functions, including
+ SHA3-224, SHA3-256, SHA3-386, SHA3-512, SHAKE128 and SHAKE256. Note
+ that whilst the SHAKE* hash functions can support arbitrary-length
+ digests, these tests only check the nominal digest sizes for now.
+
config CRYPTO_LIB_BENCHMARK_VISIBLE
bool
diff --git a/lib/crypto/tests/Makefile b/lib/crypto/tests/Makefile
index 8601dccd6fdd..efbe1bf2e1a9 100644
--- a/lib/crypto/tests/Makefile
+++ b/lib/crypto/tests/Makefile
@@ -4,3 +4,10 @@ obj-$(CONFIG_CRYPTO_LIB_POLY1305_KUNIT_TEST) += poly1305_kunit.o
obj-$(CONFIG_CRYPTO_LIB_SHA1_KUNIT_TEST) += sha1_kunit.o
obj-$(CONFIG_CRYPTO_LIB_SHA256_KUNIT_TEST) += sha224_kunit.o sha256_kunit.o
obj-$(CONFIG_CRYPTO_LIB_SHA512_KUNIT_TEST) += sha384_kunit.o sha512_kunit.o
+obj-$(CONFIG_CRYPTO_LIB_SHA3_KUNIT_TEST) += \
+ sha3_224_kunit.o \
+ sha3_256_kunit.o \
+ sha3_384_kunit.o \
+ sha3_512_kunit.o \
+ sha3_shake128_kunit.o \
+ sha3_shake256_kunit.o
diff --git a/lib/crypto/tests/sha3_224_kunit.c b/lib/crypto/tests/sha3_224_kunit.c
new file mode 100644
index 000000000000..c09aab76660a
--- /dev/null
+++ b/lib/crypto/tests/sha3_224_kunit.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+#include <crypto/sha3.h>
+#include "sha3_224_testvecs.h"
+
+#define HASH sha3_224
+#define HASH_CTX sha3_ctx
+#define HASH_SIZE SHA3_224_DIGEST_SIZE
+#define HASH_INIT sha3_224_init
+#define HASH_UPDATE sha3_update
+#define HASH_FINAL sha3_final
+#include "hash-test-template.h"
+
+static struct kunit_case hash_test_cases[] = {
+ HASH_KUNIT_CASES,
+ KUNIT_CASE(benchmark_hash),
+ {},
+};
+
+static struct kunit_suite hash_test_suite = {
+ .name = "sha3_224",
+ .test_cases = hash_test_cases,
+ .suite_init = hash_suite_init,
+ .suite_exit = hash_suite_exit,
+};
+kunit_test_suite(hash_test_suite);
+
+MODULE_DESCRIPTION("KUnit tests and benchmark for SHA3-224");
+MODULE_LICENSE("GPL");
diff --git a/lib/crypto/tests/sha3_224_testvecs.h b/lib/crypto/tests/sha3_224_testvecs.h
new file mode 100644
index 000000000000..0c4493117151
--- /dev/null
+++ b/lib/crypto/tests/sha3_224_testvecs.h
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* This file was generated by: ../../../scripts/crypto/gen-hash-testvecs.py sha3-224 */
+
+static const struct {
+ size_t data_len;
+ u8 digest[SHA3_224_DIGEST_SIZE];
+} hash_testvecs[] = {
+ {
+ .data_len = 0,
+ .digest = {
+ 0x6b, 0x4e, 0x03, 0x42, 0x36, 0x67, 0xdb, 0xb7,
+ 0x3b, 0x6e, 0x15, 0x45, 0x4f, 0x0e, 0xb1, 0xab,
+ 0xd4, 0x59, 0x7f, 0x9a, 0x1b, 0x07, 0x8e, 0x3f,
+ 0x5b, 0x5a, 0x6b, 0xc7,
+ },
+ },
+ {
+ .data_len = 1,
+ .digest = {
+ 0xe1, 0x62, 0xe9, 0x68, 0xe7, 0xd3, 0xeb, 0x6a,
+ 0xec, 0x68, 0x77, 0x5f, 0x34, 0xd4, 0xbc, 0x4b,
+ 0xe4, 0x5c, 0x3c, 0x1c, 0x92, 0x17, 0x20, 0x20,
+ 0x08, 0xc4, 0x42, 0x1c,
+ },
+ },
+ {
+ .data_len = 2,
+ .digest = {
+ 0x6c, 0xc1, 0x0c, 0xee, 0xd9, 0xc3, 0x82, 0xf4,
+ 0x55, 0x8c, 0xfd, 0xe7, 0x60, 0x66, 0xeb, 0xcd,
+ 0x8e, 0x5a, 0xac, 0xb8, 0x3f, 0x0e, 0x17, 0x84,
+ 0xed, 0x2d, 0xd5, 0x30,
+ },
+ },
+ {
+ .data_len = 3,
+ .digest = {
+ 0x6a, 0x40, 0xa0, 0x99, 0x78, 0x43, 0xbb, 0x63,
+ 0x38, 0x80, 0x44, 0x4b, 0xa9, 0x2e, 0x30, 0xb8,
+ 0xef, 0x93, 0x7b, 0xe1, 0x9f, 0x71, 0xeb, 0xe0,
+ 0xe8, 0xfe, 0x70, 0x09,
+ },
+ },
+ {
+ .data_len = 16,
+ .digest = {
+ 0x26, 0xce, 0x12, 0x43, 0xde, 0x89, 0x52, 0xf4,
+ 0x9a, 0x21, 0x77, 0xb0, 0x8a, 0xc0, 0x21, 0x2b,
+ 0x71, 0xd0, 0x77, 0x10, 0xdb, 0xec, 0x1f, 0xe3,
+ 0x32, 0xa9, 0xac, 0x47,
+ },
+ },
+ {
+ .data_len = 32,
+ .digest = {
+ 0x40, 0x35, 0x0c, 0xf3, 0xa7, 0x15, 0xbf, 0xfc,
+ 0xf0, 0xe2, 0x14, 0x3b, 0x97, 0x8a, 0x47, 0x5d,
+ 0x65, 0x1e, 0xd0, 0x49, 0x0d, 0x44, 0x45, 0x0b,
+ 0x01, 0x48, 0x11, 0xe1,
+ },
+ },
+ {
+ .data_len = 48,
+ .digest = {
+ 0x92, 0xa6, 0x33, 0x68, 0x48, 0xd2, 0xf1, 0xdc,
+ 0xf7, 0xcc, 0xf7, 0x7f, 0x14, 0x1e, 0x2a, 0x56,
+ 0x93, 0xcb, 0x40, 0x8c, 0x86, 0xfd, 0xef, 0xcf,
+ 0xbf, 0xc1, 0x3b, 0x3c,
+ },
+ },
+ {
+ .data_len = 49,
+ .digest = {
+ 0x97, 0xbf, 0xd2, 0x14, 0xe9, 0x95, 0x63, 0x0b,
+ 0xee, 0x16, 0x60, 0x15, 0x03, 0x19, 0xa0, 0xad,
+ 0x89, 0x7d, 0xb1, 0x50, 0x46, 0xef, 0x17, 0xd8,
+ 0xba, 0x1e, 0x92, 0x2e,
+ },
+ },
+ {
+ .data_len = 63,
+ .digest = {
+ 0x03, 0xe4, 0x9c, 0x28, 0x6e, 0x18, 0xf1, 0xb9,
+ 0x2a, 0x1a, 0xf4, 0xd4, 0x14, 0xe2, 0x69, 0x56,
+ 0x48, 0xe6, 0x02, 0x3b, 0xab, 0x17, 0xb2, 0x15,
+ 0xdd, 0x83, 0x3a, 0xa7,
+ },
+ },
+ {
+ .data_len = 64,
+ .digest = {
+ 0xdc, 0x46, 0x53, 0x27, 0x3b, 0x68, 0x2c, 0x4f,
+ 0xc2, 0x05, 0xe3, 0xa2, 0x56, 0x4f, 0x61, 0xf9,
+ 0xd9, 0x9b, 0x16, 0xf8, 0x1d, 0xb4, 0x7c, 0x30,
+ 0x85, 0xce, 0xa3, 0x00,
+ },
+ },
+ {
+ .data_len = 65,
+ .digest = {
+ 0x6c, 0x2d, 0x3b, 0x1a, 0x2d, 0xec, 0x94, 0xfa,
+ 0x1e, 0x0a, 0xc6, 0xa0, 0x62, 0x8f, 0x54, 0x0d,
+ 0xa9, 0x44, 0xdc, 0x2d, 0xb8, 0x6c, 0xb0, 0xb0,
+ 0x3f, 0x7b, 0x5e, 0xce,
+ },
+ },
+ {
+ .data_len = 127,
+ .digest = {
+ 0x71, 0xf5, 0x33, 0x38, 0x48, 0x84, 0x0a, 0x34,
+ 0xfc, 0x46, 0x1f, 0x06, 0x73, 0xab, 0x2e, 0xb0,
+ 0x3b, 0x46, 0xfb, 0x8a, 0xa6, 0x4d, 0x8e, 0xc0,
+ 0xfc, 0xd3, 0xef, 0xc8,
+ },
+ },
+ {
+ .data_len = 128,
+ .digest = {
+ 0xea, 0x18, 0xcd, 0x7b, 0x08, 0x9b, 0x2c, 0xb5,
+ 0xed, 0x5d, 0xc4, 0x86, 0xdf, 0xe9, 0x77, 0x3b,
+ 0x26, 0x49, 0x04, 0x81, 0xf1, 0x75, 0xe2, 0xcd,
+ 0x49, 0xe4, 0x38, 0xe0,
+ },
+ },
+ {
+ .data_len = 129,
+ .digest = {
+ 0xc8, 0x18, 0xde, 0x8d, 0xbc, 0xc1, 0x2d, 0xe3,
+ 0x9b, 0xad, 0xea, 0xed, 0x03, 0xa3, 0x6f, 0x69,
+ 0xd0, 0xa7, 0x40, 0x85, 0x66, 0xee, 0x6b, 0xb0,
+ 0xc9, 0x14, 0x85, 0x3a,
+ },
+ },
+ {
+ .data_len = 256,
+ .digest = {
+ 0xa9, 0x43, 0xe4, 0xbe, 0x81, 0xb9, 0xbf, 0xbf,
+ 0x2d, 0x61, 0xe0, 0x8b, 0x21, 0x83, 0xd0, 0x35,
+ 0x17, 0xf6, 0x01, 0x15, 0xde, 0x38, 0x5a, 0x7c,
+ 0x93, 0x54, 0xf2, 0x82,
+ },
+ },
+ {
+ .data_len = 511,
+ .digest = {
+ 0xb7, 0xf2, 0x8c, 0x76, 0x36, 0x8a, 0x60, 0xbd,
+ 0xf0, 0x6c, 0x08, 0x1a, 0xef, 0x6d, 0xf3, 0x4f,
+ 0x3c, 0x3c, 0x04, 0x46, 0x49, 0xb1, 0x32, 0x40,
+ 0xc5, 0x16, 0xb9, 0xce,
+ },
+ },
+ {
+ .data_len = 513,
+ .digest = {
+ 0xbf, 0xef, 0x10, 0xc6, 0x91, 0x04, 0xe2, 0x7d,
+ 0x51, 0x65, 0x88, 0xb3, 0xab, 0xdb, 0x9e, 0x98,
+ 0x8a, 0x24, 0x25, 0x19, 0xa3, 0x9d, 0x47, 0x6c,
+ 0xa0, 0xbe, 0x63, 0xee,
+ },
+ },
+ {
+ .data_len = 1000,
+ .digest = {
+ 0x8e, 0xb3, 0xa6, 0xf6, 0x13, 0x16, 0x6e, 0xbe,
+ 0x85, 0xa8, 0x38, 0x28, 0x34, 0x3b, 0x70, 0x62,
+ 0x84, 0x2e, 0x0c, 0xcb, 0xe0, 0x03, 0x6c, 0x6a,
+ 0x3d, 0xfc, 0x34, 0x4b,
+ },
+ },
+ {
+ .data_len = 3333,
+ .digest = {
+ 0x80, 0x77, 0x1f, 0x95, 0xe6, 0x1f, 0x0e, 0xa8,
+ 0xf8, 0x5f, 0xad, 0x36, 0x2c, 0xe5, 0x43, 0x9d,
+ 0x7d, 0x09, 0x17, 0x71, 0x70, 0x5a, 0x77, 0xdc,
+ 0x11, 0x28, 0x9c, 0x41,
+ },
+ },
+ {
+ .data_len = 4096,
+ .digest = {
+ 0x8b, 0x70, 0x82, 0x24, 0x53, 0x8d, 0xca, 0x05,
+ 0x95, 0x15, 0xc8, 0x1b, 0xca, 0xcc, 0x25, 0x63,
+ 0xfe, 0x73, 0x83, 0xf0, 0x8f, 0xfb, 0xb9, 0x1b,
+ 0x48, 0xa3, 0x54, 0x91,
+ },
+ },
+ {
+ .data_len = 4128,
+ .digest = {
+ 0x50, 0x2a, 0x17, 0x3f, 0xd4, 0x65, 0x81, 0x41,
+ 0x34, 0x17, 0x34, 0xe8, 0x12, 0xbd, 0x2e, 0x66,
+ 0x93, 0x30, 0xf5, 0xc9, 0xae, 0x31, 0x9f, 0x97,
+ 0xd7, 0x0e, 0xfe, 0x7b,
+ },
+ },
+ {
+ .data_len = 4160,
+ .digest = {
+ 0x9f, 0x8d, 0x09, 0xe4, 0x05, 0x3c, 0x54, 0x8b,
+ 0x26, 0xf9, 0x65, 0x9b, 0x16, 0xbe, 0x0a, 0x48,
+ 0xf1, 0x5a, 0x93, 0xb4, 0xfe, 0xca, 0x93, 0x39,
+ 0x86, 0x4c, 0xe2, 0xaa,
+ },
+ },
+ {
+ .data_len = 4224,
+ .digest = {
+ 0xd9, 0x0f, 0x61, 0xfa, 0xb8, 0x13, 0xb2, 0xc8,
+ 0x84, 0xb6, 0x0e, 0x53, 0x43, 0xe1, 0x28, 0x23,
+ 0xab, 0xb9, 0x4a, 0x5a, 0xb3, 0x39, 0x31, 0xf6,
+ 0x5d, 0x36, 0x1e, 0x6b,
+ },
+ },
+ {
+ .data_len = 16384,
+ .digest = {
+ 0x74, 0xd4, 0x26, 0x55, 0x7f, 0xef, 0x2a, 0x4a,
+ 0x4f, 0xf9, 0x6f, 0x29, 0xf2, 0xd4, 0xd7, 0x5d,
+ 0xc9, 0x88, 0x7a, 0xfb, 0x5f, 0x75, 0xde, 0x0a,
+ 0x46, 0x83, 0x2a, 0x76,
+ },
+ },
+};
+
+static const u8 hash_testvec_consolidated[SHA3_224_DIGEST_SIZE] = {
+ 0x83, 0xf2, 0x88, 0x34, 0x20, 0x45, 0x9f, 0xd2,
+ 0x5e, 0x9d, 0x36, 0xc0, 0x42, 0xcc, 0x74, 0xd8,
+ 0x06, 0xd9, 0x9f, 0xbf, 0x39, 0x32, 0x59, 0x4e,
+ 0x6e, 0x12, 0x62, 0x8b,
+};
diff --git a/lib/crypto/tests/sha3_256_kunit.c b/lib/crypto/tests/sha3_256_kunit.c
new file mode 100644
index 000000000000..04f0ebce6223
--- /dev/null
+++ b/lib/crypto/tests/sha3_256_kunit.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+#include <crypto/sha3.h>
+#include "sha3_256_testvecs.h"
+
+#define HASH sha3_256
+#define HASH_CTX sha3_ctx
+#define HASH_SIZE SHA3_256_DIGEST_SIZE
+#define HASH_INIT sha3_256_init
+#define HASH_UPDATE sha3_update
+#define HASH_FINAL sha3_final
+#include "hash-test-template.h"
+
+static struct kunit_case hash_test_cases[] = {
+ HASH_KUNIT_CASES,
+ KUNIT_CASE(benchmark_hash),
+ {},
+};
+
+static struct kunit_suite hash_test_suite = {
+ .name = "sha3_256",
+ .test_cases = hash_test_cases,
+ .suite_init = hash_suite_init,
+ .suite_exit = hash_suite_exit,
+};
+kunit_test_suite(hash_test_suite);
+
+MODULE_DESCRIPTION("KUnit tests and benchmark for SHA3-256");
+MODULE_LICENSE("GPL");
diff --git a/lib/crypto/tests/sha3_256_testvecs.h b/lib/crypto/tests/sha3_256_testvecs.h
new file mode 100644
index 000000000000..9c4c403cc6e0
--- /dev/null
+++ b/lib/crypto/tests/sha3_256_testvecs.h
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* This file was generated by: ./scripts/crypto/gen-hash-testvecs.py sha3-256 */
+
+static const struct {
+ size_t data_len;
+ u8 digest[SHA3_256_DIGEST_SIZE];
+} hash_testvecs[] = {
+ {
+ .data_len = 0,
+ .digest = {
+ 0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66,
+ 0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62,
+ 0xf5, 0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa,
+ 0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a,
+ },
+ },
+ {
+ .data_len = 1,
+ .digest = {
+ 0x11, 0x03, 0xe7, 0x84, 0x51, 0x50, 0x86, 0x35,
+ 0x71, 0x8a, 0x70, 0xe3, 0xc4, 0x26, 0x7b, 0x21,
+ 0x02, 0x13, 0xa0, 0x81, 0xe8, 0xe6, 0x14, 0x25,
+ 0x07, 0x34, 0xe5, 0xc5, 0x40, 0x06, 0xf2, 0x8b,
+ },
+ },
+ {
+ .data_len = 2,
+ .digest = {
+ 0x2f, 0x6f, 0x6d, 0x47, 0x48, 0x52, 0x11, 0xb9,
+ 0xe4, 0x3d, 0xc8, 0x71, 0xcf, 0xb2, 0xee, 0xae,
+ 0x5b, 0xf4, 0x12, 0x84, 0x5b, 0x1c, 0xec, 0x6c,
+ 0xc1, 0x66, 0x88, 0xaa, 0xc3, 0x40, 0xbd, 0x7e,
+ },
+ },
+ {
+ .data_len = 3,
+ .digest = {
+ 0xec, 0x02, 0xe8, 0x81, 0x4f, 0x84, 0x41, 0x69,
+ 0x06, 0xd8, 0xdc, 0x1d, 0x01, 0x78, 0xd7, 0xcb,
+ 0x39, 0xdf, 0xd3, 0x12, 0x1c, 0x99, 0xfd, 0xf3,
+ 0x5c, 0x83, 0xc9, 0xc2, 0x7a, 0x7b, 0x6a, 0x05,
+ },
+ },
+ {
+ .data_len = 16,
+ .digest = {
+ 0xff, 0x6f, 0xc3, 0x41, 0xc3, 0x5f, 0x34, 0x6d,
+ 0xa7, 0xdf, 0x3e, 0xc2, 0x8b, 0x29, 0xb6, 0xf1,
+ 0xf8, 0x67, 0xfd, 0xcd, 0xb1, 0x9f, 0x38, 0x08,
+ 0x1d, 0x8d, 0xd9, 0xc2, 0x43, 0x66, 0x18, 0x6c,
+ },
+ },
+ {
+ .data_len = 32,
+ .digest = {
+ 0xe4, 0xb1, 0x06, 0x17, 0xf8, 0x8b, 0x91, 0x95,
+ 0xe7, 0x57, 0x66, 0xac, 0x08, 0xb2, 0x03, 0x3e,
+ 0xf7, 0x84, 0x1f, 0xe3, 0x25, 0xa3, 0x11, 0xd2,
+ 0x11, 0xa4, 0x78, 0x74, 0x2a, 0x43, 0x20, 0xa5,
+ },
+ },
+ {
+ .data_len = 48,
+ .digest = {
+ 0xeb, 0x57, 0x5f, 0x20, 0xa3, 0x6b, 0xc7, 0xb4,
+ 0x66, 0x2a, 0xa0, 0x30, 0x3b, 0x52, 0x00, 0xc9,
+ 0xce, 0x6a, 0xd8, 0x1e, 0xbe, 0xed, 0xa1, 0xd1,
+ 0xbe, 0x63, 0xc7, 0xe1, 0xe2, 0x66, 0x67, 0x0c,
+ },
+ },
+ {
+ .data_len = 49,
+ .digest = {
+ 0xf0, 0x67, 0xad, 0x66, 0xbe, 0xec, 0x5a, 0xfd,
+ 0x29, 0xd2, 0x4f, 0x1d, 0xb2, 0x24, 0xb8, 0x90,
+ 0x05, 0x28, 0x0e, 0x66, 0x67, 0x74, 0x2d, 0xee,
+ 0x66, 0x25, 0x11, 0xd1, 0x76, 0xa2, 0xfc, 0x3a,
+ },
+ },
+ {
+ .data_len = 63,
+ .digest = {
+ 0x57, 0x56, 0x21, 0xb3, 0x2d, 0x2d, 0xe1, 0x9d,
+ 0xbf, 0x2c, 0x82, 0xa8, 0xad, 0x7e, 0x6c, 0x46,
+ 0xfb, 0x30, 0xeb, 0xce, 0xcf, 0xed, 0x2d, 0x65,
+ 0xe7, 0xe4, 0x96, 0x69, 0xe0, 0x48, 0xd2, 0xb6,
+ },
+ },
+ {
+ .data_len = 64,
+ .digest = {
+ 0x7b, 0xba, 0x67, 0x15, 0xe5, 0x21, 0xc4, 0x69,
+ 0xd3, 0xef, 0x5c, 0x97, 0x9f, 0x5b, 0xba, 0x9c,
+ 0xfa, 0x55, 0x64, 0xec, 0xb5, 0x37, 0x53, 0x1b,
+ 0x3f, 0x4c, 0x0a, 0xed, 0x51, 0x98, 0x2b, 0x52,
+ },
+ },
+ {
+ .data_len = 65,
+ .digest = {
+ 0x44, 0xb6, 0x6b, 0x83, 0x09, 0x83, 0x55, 0x83,
+ 0xde, 0x1f, 0xcc, 0x33, 0xef, 0xdc, 0x05, 0xbb,
+ 0x3b, 0x63, 0x76, 0x45, 0xe4, 0x8e, 0x14, 0x7a,
+ 0x2d, 0xae, 0x90, 0xce, 0x68, 0xc3, 0xa4, 0xf2,
+ },
+ },
+ {
+ .data_len = 127,
+ .digest = {
+ 0x50, 0x3e, 0x99, 0x4e, 0x28, 0x2b, 0xc9, 0xf4,
+ 0xf5, 0xeb, 0x2b, 0x16, 0x04, 0x2d, 0xf5, 0xbe,
+ 0xc0, 0x91, 0x41, 0x2a, 0x8e, 0x69, 0x5e, 0x39,
+ 0x53, 0x2c, 0xc1, 0x18, 0xa5, 0xeb, 0xd8, 0xda,
+ },
+ },
+ {
+ .data_len = 128,
+ .digest = {
+ 0x90, 0x0b, 0xa6, 0x92, 0x84, 0x30, 0xaf, 0xee,
+ 0x38, 0x59, 0x83, 0x83, 0xe9, 0xfe, 0xab, 0x86,
+ 0x79, 0x1b, 0xcd, 0xe7, 0x0a, 0x0f, 0x58, 0x53,
+ 0x36, 0xab, 0x12, 0xe1, 0x5c, 0x97, 0xc1, 0xfb,
+ },
+ },
+ {
+ .data_len = 129,
+ .digest = {
+ 0x2b, 0x52, 0x1e, 0x54, 0xbe, 0x38, 0x4c, 0x3e,
+ 0x73, 0x37, 0x18, 0xf5, 0x25, 0x2c, 0xc8, 0xc7,
+ 0xda, 0x7e, 0xb6, 0x47, 0x9d, 0xf4, 0x46, 0xce,
+ 0xfa, 0x80, 0x20, 0x6b, 0xbd, 0xfd, 0x2a, 0xd8,
+ },
+ },
+ {
+ .data_len = 256,
+ .digest = {
+ 0x45, 0xf0, 0xf5, 0x9b, 0xd9, 0x91, 0x26, 0xd5,
+ 0x91, 0x3b, 0xf8, 0x87, 0x8b, 0x34, 0x02, 0x31,
+ 0x64, 0xab, 0xf4, 0x1c, 0x6e, 0x34, 0x72, 0xdf,
+ 0x32, 0x6d, 0xe5, 0xd2, 0x67, 0x5e, 0x86, 0x93,
+ },
+ },
+ {
+ .data_len = 511,
+ .digest = {
+ 0xb3, 0xaf, 0x71, 0x64, 0xfa, 0xd4, 0xf1, 0x07,
+ 0x38, 0xef, 0x04, 0x8e, 0x89, 0xf4, 0x02, 0xd2,
+ 0xa5, 0xaf, 0x3b, 0xf5, 0x67, 0x56, 0xcf, 0xa9,
+ 0x8e, 0x43, 0xf5, 0xb5, 0xe3, 0x91, 0x8e, 0xe7,
+ },
+ },
+ {
+ .data_len = 513,
+ .digest = {
+ 0x51, 0xac, 0x0a, 0x65, 0xb7, 0x96, 0x20, 0xcf,
+ 0x88, 0xf6, 0x97, 0x35, 0x89, 0x0d, 0x31, 0x0f,
+ 0xbe, 0x17, 0xbe, 0x62, 0x03, 0x67, 0xc0, 0xee,
+ 0x4f, 0xc1, 0xe3, 0x7f, 0x6f, 0xab, 0xac, 0xb4,
+ },
+ },
+ {
+ .data_len = 1000,
+ .digest = {
+ 0x7e, 0xea, 0xa8, 0xd7, 0xde, 0x20, 0x1b, 0x58,
+ 0x24, 0xd8, 0x26, 0x40, 0x36, 0x5f, 0x3f, 0xaa,
+ 0xe5, 0x5a, 0xea, 0x98, 0x58, 0xd4, 0xd6, 0xfc,
+ 0x20, 0x4c, 0x5c, 0x4f, 0xaf, 0x56, 0xc7, 0xc3,
+ },
+ },
+ {
+ .data_len = 3333,
+ .digest = {
+ 0x61, 0xb1, 0xb1, 0x3e, 0x0e, 0x7e, 0x90, 0x3d,
+ 0x31, 0x54, 0xbd, 0xc9, 0x0d, 0x53, 0x62, 0xf1,
+ 0xcd, 0x18, 0x80, 0xf9, 0x91, 0x75, 0x41, 0xb3,
+ 0x51, 0x39, 0x57, 0xa7, 0xa8, 0x1e, 0xfb, 0xc9,
+ },
+ },
+ {
+ .data_len = 4096,
+ .digest = {
+ 0xab, 0x29, 0xda, 0x10, 0xc4, 0x11, 0x2d, 0x5c,
+ 0xd1, 0xce, 0x1c, 0x95, 0xfa, 0xc6, 0xc7, 0xb0,
+ 0x1b, 0xd1, 0xdc, 0x6f, 0xa0, 0x9d, 0x1b, 0x23,
+ 0xfb, 0x6e, 0x90, 0x97, 0xd0, 0x75, 0x44, 0x7a,
+ },
+ },
+ {
+ .data_len = 4128,
+ .digest = {
+ 0x02, 0x45, 0x95, 0xf4, 0x19, 0xb5, 0x93, 0x29,
+ 0x90, 0xf2, 0x63, 0x3f, 0x89, 0xe8, 0xa5, 0x31,
+ 0x76, 0xf2, 0x89, 0x79, 0x66, 0xd3, 0x96, 0xdf,
+ 0x33, 0xd1, 0xa6, 0x17, 0x73, 0xb1, 0xd0, 0x45,
+ },
+ },
+ {
+ .data_len = 4160,
+ .digest = {
+ 0xd1, 0x8e, 0x22, 0xea, 0x44, 0x87, 0x6e, 0x9d,
+ 0xfb, 0x36, 0x02, 0x20, 0x63, 0xb7, 0x69, 0x45,
+ 0x25, 0x41, 0x69, 0xe0, 0x9b, 0x87, 0xcf, 0xa3,
+ 0x51, 0xbb, 0xfc, 0x8d, 0xf7, 0x29, 0xa7, 0xea,
+ },
+ },
+ {
+ .data_len = 4224,
+ .digest = {
+ 0x11, 0x86, 0x7d, 0x84, 0xf9, 0x8c, 0x6e, 0xc4,
+ 0x64, 0x36, 0xc6, 0xf3, 0x42, 0x92, 0x31, 0x2b,
+ 0x1e, 0x12, 0xe6, 0x4d, 0xbe, 0xfa, 0x77, 0x3f,
+ 0x89, 0x41, 0x33, 0x58, 0x1c, 0x98, 0x16, 0x0a,
+ },
+ },
+ {
+ .data_len = 16384,
+ .digest = {
+ 0xb2, 0xba, 0x0c, 0x8c, 0x9d, 0xbb, 0x1e, 0xb0,
+ 0x03, 0xb5, 0xdf, 0x4f, 0xf5, 0x35, 0xdb, 0xec,
+ 0x60, 0xf2, 0x5b, 0xb6, 0xd0, 0x49, 0xd3, 0xed,
+ 0x55, 0xc0, 0x7a, 0xd7, 0xaf, 0xa1, 0xea, 0x53,
+ },
+ },
+};
+
+static const u8 hash_testvec_consolidated[SHA3_256_DIGEST_SIZE] = {
+ 0x3b, 0x33, 0x67, 0xf8, 0xea, 0x92, 0x78, 0x62,
+ 0xdd, 0xbe, 0x72, 0x15, 0xbd, 0x6f, 0xfa, 0xe5,
+ 0x5e, 0xab, 0x9f, 0xb1, 0xe4, 0x23, 0x7c, 0x2c,
+ 0x80, 0xcf, 0x09, 0x75, 0xf8, 0xe2, 0xfa, 0x30,
+};
diff --git a/lib/crypto/tests/sha3_384_kunit.c b/lib/crypto/tests/sha3_384_kunit.c
new file mode 100644
index 000000000000..5521f4ae3c25
--- /dev/null
+++ b/lib/crypto/tests/sha3_384_kunit.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+#include <crypto/sha3.h>
+#include "sha3_384_testvecs.h"
+
+#define HASH sha3_384
+#define HASH_CTX sha3_ctx
+#define HASH_SIZE SHA3_384_DIGEST_SIZE
+#define HASH_INIT sha3_384_init
+#define HASH_UPDATE sha3_update
+#define HASH_FINAL sha3_final
+#include "hash-test-template.h"
+
+static struct kunit_case hash_test_cases[] = {
+ HASH_KUNIT_CASES,
+ KUNIT_CASE(benchmark_hash),
+ {},
+};
+
+static struct kunit_suite hash_test_suite = {
+ .name = "sha3_384",
+ .test_cases = hash_test_cases,
+ .suite_init = hash_suite_init,
+ .suite_exit = hash_suite_exit,
+};
+kunit_test_suite(hash_test_suite);
+
+MODULE_DESCRIPTION("KUnit tests and benchmark for SHA3-384");
+MODULE_LICENSE("GPL");
diff --git a/lib/crypto/tests/sha3_384_testvecs.h b/lib/crypto/tests/sha3_384_testvecs.h
new file mode 100644
index 000000000000..ec412de7c759
--- /dev/null
+++ b/lib/crypto/tests/sha3_384_testvecs.h
@@ -0,0 +1,281 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* This file was generated by: ../../../scripts/crypto/gen-hash-testvecs.py sha3-384 */
+
+static const struct {
+ size_t data_len;
+ u8 digest[SHA3_384_DIGEST_SIZE];
+} hash_testvecs[] = {
+ {
+ .data_len = 0,
+ .digest = {
+ 0x0c, 0x63, 0xa7, 0x5b, 0x84, 0x5e, 0x4f, 0x7d,
+ 0x01, 0x10, 0x7d, 0x85, 0x2e, 0x4c, 0x24, 0x85,
+ 0xc5, 0x1a, 0x50, 0xaa, 0xaa, 0x94, 0xfc, 0x61,
+ 0x99, 0x5e, 0x71, 0xbb, 0xee, 0x98, 0x3a, 0x2a,
+ 0xc3, 0x71, 0x38, 0x31, 0x26, 0x4a, 0xdb, 0x47,
+ 0xfb, 0x6b, 0xd1, 0xe0, 0x58, 0xd5, 0xf0, 0x04,
+ },
+ },
+ {
+ .data_len = 1,
+ .digest = {
+ 0x15, 0x3b, 0x5d, 0xa0, 0x54, 0x73, 0x3c, 0x20,
+ 0x43, 0xdd, 0xec, 0x9c, 0x6b, 0xed, 0xf8, 0x3a,
+ 0x2d, 0xfa, 0x90, 0x72, 0x80, 0x0c, 0x6d, 0x3c,
+ 0x24, 0x4f, 0x00, 0xb6, 0xab, 0xd2, 0x16, 0xa0,
+ 0xd3, 0x4e, 0x8a, 0x10, 0x09, 0xaa, 0x28, 0x42,
+ 0xe0, 0x31, 0x06, 0x14, 0x2f, 0x31, 0x90, 0xe7,
+ },
+ },
+ {
+ .data_len = 2,
+ .digest = {
+ 0x5e, 0xa7, 0x88, 0xb5, 0x41, 0x4a, 0x47, 0xe7,
+ 0x1c, 0x42, 0xf3, 0xe8, 0x5e, 0x74, 0x35, 0x15,
+ 0x19, 0xa0, 0x81, 0xb3, 0xf2, 0x4d, 0x75, 0xc2,
+ 0x99, 0x24, 0x37, 0x69, 0xfe, 0xad, 0x31, 0x3b,
+ 0xd6, 0xdf, 0x33, 0xce, 0x20, 0x2a, 0xf3, 0x73,
+ 0xf3, 0x64, 0xba, 0x33, 0x2a, 0x7d, 0x03, 0x03,
+ },
+ },
+ {
+ .data_len = 3,
+ .digest = {
+ 0x51, 0x65, 0xc3, 0xb5, 0xed, 0x48, 0x29, 0xfd,
+ 0x6e, 0x6d, 0xc8, 0x49, 0x60, 0xd3, 0x51, 0xa1,
+ 0xec, 0x79, 0xf8, 0x43, 0x98, 0x87, 0x0c, 0x4c,
+ 0x7f, 0xca, 0x32, 0x29, 0x68, 0xe8, 0xf2, 0x59,
+ 0x01, 0x89, 0x2e, 0xbf, 0x42, 0xd1, 0x46, 0x55,
+ 0x0b, 0x3a, 0x50, 0xa2, 0x83, 0x47, 0xb4, 0x14,
+ },
+ },
+ {
+ .data_len = 16,
+ .digest = {
+ 0x2a, 0x91, 0x68, 0x9c, 0x07, 0x3c, 0x40, 0x42,
+ 0xcc, 0x8e, 0xfb, 0x90, 0xe7, 0x77, 0x14, 0x05,
+ 0x5f, 0x90, 0xf8, 0x57, 0x3c, 0x55, 0x79, 0xc3,
+ 0x59, 0x28, 0xd8, 0x1d, 0x9a, 0xeb, 0x86, 0xe9,
+ 0xfe, 0x39, 0xc2, 0xce, 0x40, 0xd0, 0xb7, 0xe2,
+ 0xba, 0xfc, 0xeb, 0x18, 0x3a, 0xaf, 0x71, 0xa2,
+ },
+ },
+ {
+ .data_len = 32,
+ .digest = {
+ 0x98, 0x36, 0x92, 0xec, 0xb6, 0xe8, 0x46, 0xc9,
+ 0x8e, 0x61, 0x2e, 0x71, 0x06, 0xfd, 0xe1, 0x23,
+ 0xff, 0x6a, 0x1d, 0xb1, 0x3b, 0x6c, 0x3d, 0x8e,
+ 0x07, 0x09, 0xf9, 0xaa, 0x89, 0xa8, 0x6b, 0x5f,
+ 0xb3, 0xf3, 0xdf, 0x09, 0xb7, 0x4d, 0xf2, 0x60,
+ 0x3c, 0x99, 0x0b, 0x75, 0xec, 0x3c, 0xe0, 0x45,
+ },
+ },
+ {
+ .data_len = 48,
+ .digest = {
+ 0xc2, 0xef, 0x71, 0x18, 0x6e, 0x8a, 0x91, 0xbf,
+ 0x8b, 0x87, 0x8b, 0xa4, 0x54, 0x32, 0x66, 0x5a,
+ 0x79, 0x6d, 0xfc, 0x19, 0x24, 0x1e, 0xa8, 0x12,
+ 0xc6, 0xf6, 0x16, 0x72, 0x10, 0xd4, 0x31, 0x52,
+ 0x70, 0x55, 0x9c, 0xa0, 0x4e, 0xab, 0x5a, 0xf5,
+ 0x8d, 0x8d, 0x28, 0x76, 0x8b, 0x55, 0x5f, 0x1d,
+ },
+ },
+ {
+ .data_len = 49,
+ .digest = {
+ 0x36, 0x8d, 0x27, 0xd9, 0x43, 0x14, 0x2e, 0xb2,
+ 0x38, 0x99, 0x10, 0x65, 0x01, 0x31, 0x6c, 0x21,
+ 0x29, 0x39, 0x4b, 0xb7, 0x82, 0x6e, 0xb8, 0xf4,
+ 0x7c, 0x0b, 0x4c, 0x6c, 0xee, 0xd9, 0xd1, 0xf0,
+ 0x36, 0x62, 0x62, 0xb3, 0x85, 0x23, 0x36, 0x17,
+ 0x83, 0x57, 0x31, 0x86, 0x21, 0x59, 0x03, 0x53,
+ },
+ },
+ {
+ .data_len = 63,
+ .digest = {
+ 0x0e, 0xb5, 0x98, 0x1c, 0x4e, 0xc1, 0x26, 0x61,
+ 0xef, 0xc4, 0xc2, 0x2d, 0xb6, 0x69, 0xfa, 0x7c,
+ 0x5a, 0xd5, 0x70, 0x87, 0x81, 0x02, 0xac, 0xfe,
+ 0x76, 0xf6, 0x78, 0x88, 0xa3, 0xc3, 0x0d, 0xa1,
+ 0xdc, 0x5e, 0xdc, 0xa3, 0x9c, 0xb2, 0x52, 0x33,
+ 0x4c, 0x3f, 0x29, 0xdc, 0x30, 0xde, 0xc5, 0x8e,
+ },
+ },
+ {
+ .data_len = 64,
+ .digest = {
+ 0xce, 0x96, 0x41, 0x75, 0x82, 0x8b, 0xac, 0xdf,
+ 0x5a, 0xce, 0x49, 0xff, 0x01, 0x96, 0x76, 0xca,
+ 0x9d, 0xdc, 0x30, 0x19, 0x64, 0x0e, 0x05, 0xd1,
+ 0x3c, 0x98, 0xc2, 0xa4, 0x95, 0xf7, 0x98, 0x9b,
+ 0x9e, 0x68, 0x5e, 0x1f, 0xb9, 0xe4, 0x9a, 0x09,
+ 0xed, 0xd9, 0xbe, 0x92, 0x9e, 0xb2, 0x20, 0x32,
+ },
+ },
+ {
+ .data_len = 65,
+ .digest = {
+ 0x0e, 0x0a, 0xb6, 0xb8, 0x4a, 0x14, 0xcd, 0xe6,
+ 0xdd, 0x02, 0xba, 0xeb, 0xb4, 0x80, 0x0f, 0x46,
+ 0x68, 0x33, 0xb4, 0x7d, 0x4c, 0x58, 0x94, 0x52,
+ 0x48, 0xdf, 0xbb, 0x7b, 0xee, 0xdd, 0x62, 0xbc,
+ 0x87, 0xa7, 0x2b, 0xdc, 0xe3, 0x20, 0x3c, 0xa2,
+ 0x49, 0x6a, 0xd7, 0x90, 0x28, 0x27, 0xe7, 0x6a,
+ },
+ },
+ {
+ .data_len = 127,
+ .digest = {
+ 0x3a, 0x13, 0xf6, 0x17, 0x77, 0xad, 0xce, 0x92,
+ 0xb8, 0xf7, 0xed, 0x1d, 0x30, 0x6c, 0x6e, 0x0e,
+ 0xdd, 0xd5, 0xab, 0x04, 0x1e, 0xe4, 0x2f, 0xaa,
+ 0xb8, 0xba, 0xc7, 0x0a, 0xa5, 0x1e, 0xcb, 0x14,
+ 0xa9, 0xec, 0x32, 0x4b, 0x12, 0x96, 0x44, 0x86,
+ 0x08, 0xbd, 0x3c, 0x38, 0x98, 0xc4, 0xe9, 0x68,
+ },
+ },
+ {
+ .data_len = 128,
+ .digest = {
+ 0x9f, 0x1b, 0x78, 0x80, 0xa9, 0x92, 0x06, 0xa4,
+ 0x18, 0x2f, 0x0d, 0xc1, 0x49, 0xa3, 0x92, 0xec,
+ 0x0a, 0xdb, 0xe0, 0xe6, 0x56, 0xa5, 0x45, 0xef,
+ 0x88, 0x14, 0x9f, 0xfc, 0x1d, 0x6e, 0x79, 0xf2,
+ 0x3c, 0x9a, 0x05, 0x55, 0xe2, 0x03, 0xa3, 0xea,
+ 0x14, 0xb4, 0x2e, 0x23, 0x63, 0xf6, 0x92, 0xcb,
+ },
+ },
+ {
+ .data_len = 129,
+ .digest = {
+ 0xd7, 0x5b, 0xb8, 0xad, 0x54, 0xfe, 0x84, 0x16,
+ 0x23, 0x02, 0x22, 0x11, 0x13, 0x1f, 0xa5, 0x16,
+ 0x43, 0xc7, 0x1d, 0x1d, 0x7f, 0x7a, 0xd1, 0x9d,
+ 0x82, 0x33, 0x4f, 0x8b, 0x29, 0x26, 0x46, 0x68,
+ 0x3c, 0x24, 0x42, 0x7e, 0x4c, 0x42, 0x5d, 0x16,
+ 0xbb, 0x18, 0xdf, 0x6e, 0xee, 0x9f, 0xcd, 0xbd,
+ },
+ },
+ {
+ .data_len = 256,
+ .digest = {
+ 0x37, 0x3c, 0x52, 0xc8, 0xc9, 0x58, 0xb8, 0x6a,
+ 0xec, 0x44, 0x92, 0x40, 0x51, 0x82, 0x0e, 0xd0,
+ 0xed, 0x33, 0x2a, 0xd0, 0x37, 0xa4, 0x96, 0x87,
+ 0x7c, 0x8c, 0xb7, 0x82, 0x1a, 0xad, 0xf7, 0x2f,
+ 0xa0, 0x31, 0xba, 0x7f, 0xcf, 0x36, 0x06, 0x0b,
+ 0x14, 0xb6, 0xdd, 0x5e, 0x22, 0xac, 0x52, 0xf8,
+ },
+ },
+ {
+ .data_len = 511,
+ .digest = {
+ 0x75, 0xfe, 0x6c, 0x93, 0xa6, 0x39, 0x07, 0x4a,
+ 0xdd, 0x74, 0x36, 0xe7, 0x80, 0xd2, 0xfd, 0xa1,
+ 0x30, 0x2e, 0x23, 0x2a, 0x50, 0xfe, 0xad, 0x14,
+ 0x3c, 0x1b, 0x62, 0x0d, 0x6e, 0x2d, 0x44, 0xe4,
+ 0x35, 0x3e, 0x90, 0x1b, 0x81, 0x3b, 0x43, 0x71,
+ 0xb8, 0xea, 0xd1, 0x92, 0xaa, 0x56, 0xec, 0x26,
+ },
+ },
+ {
+ .data_len = 513,
+ .digest = {
+ 0x18, 0xd9, 0xf5, 0x21, 0x9c, 0x8d, 0x63, 0x7a,
+ 0x64, 0x26, 0xd3, 0xe8, 0x63, 0x06, 0x3b, 0x43,
+ 0xf8, 0xfd, 0x93, 0xac, 0x06, 0x7d, 0x13, 0xac,
+ 0x26, 0x98, 0x4b, 0x51, 0x9f, 0x9b, 0x39, 0x57,
+ 0xe7, 0x3e, 0xa8, 0x32, 0x7f, 0x84, 0xd5, 0x87,
+ 0x4c, 0xd4, 0xe0, 0xd2, 0x57, 0x3a, 0x43, 0x00,
+ },
+ },
+ {
+ .data_len = 1000,
+ .digest = {
+ 0x53, 0xb5, 0xd8, 0x9d, 0x76, 0xed, 0xcf, 0xa3,
+ 0xb8, 0x3c, 0x5a, 0x37, 0xdb, 0xb4, 0xea, 0x1e,
+ 0x40, 0x67, 0xda, 0x46, 0x61, 0x18, 0xa1, 0x8d,
+ 0xaa, 0x5d, 0xf2, 0x32, 0x2c, 0x37, 0x02, 0x70,
+ 0x7d, 0x18, 0x02, 0x4e, 0xec, 0x57, 0x86, 0x71,
+ 0xfe, 0xdb, 0xa2, 0xd2, 0x39, 0x91, 0x98, 0xaa,
+ },
+ },
+ {
+ .data_len = 3333,
+ .digest = {
+ 0x34, 0xb3, 0x9a, 0x58, 0x30, 0x1f, 0x4b, 0x56,
+ 0x13, 0x32, 0x05, 0x48, 0x39, 0x3f, 0x36, 0xd5,
+ 0x5b, 0x61, 0xe7, 0x6b, 0x47, 0x2a, 0x33, 0xf5,
+ 0x76, 0x7c, 0x0c, 0x84, 0xa4, 0x04, 0x0b, 0x4e,
+ 0xb5, 0xc0, 0x7e, 0xca, 0x36, 0x04, 0x58, 0xfc,
+ 0x4d, 0x6f, 0xd1, 0x1f, 0x7d, 0x5a, 0x14, 0xa5,
+ },
+ },
+ {
+ .data_len = 4096,
+ .digest = {
+ 0x7d, 0x41, 0xba, 0xea, 0x79, 0xb9, 0xd1, 0x35,
+ 0x53, 0xc5, 0x2f, 0x54, 0x5d, 0xfc, 0x10, 0x0e,
+ 0xf0, 0xf8, 0x34, 0x57, 0x14, 0xc2, 0xc7, 0x1a,
+ 0xf8, 0x27, 0x99, 0x72, 0xa2, 0x1a, 0x7f, 0x48,
+ 0x39, 0x6d, 0x4c, 0x2a, 0xe5, 0x45, 0x7b, 0x67,
+ 0xd5, 0xbd, 0x9d, 0x5e, 0x25, 0x78, 0xc7, 0x70,
+ },
+ },
+ {
+ .data_len = 4128,
+ .digest = {
+ 0xea, 0x11, 0xff, 0x7f, 0x16, 0xab, 0x00, 0xa5,
+ 0x13, 0x23, 0x17, 0xec, 0x78, 0x63, 0xbf, 0x64,
+ 0x16, 0xc8, 0x36, 0x8b, 0xe9, 0x75, 0x80, 0x05,
+ 0x78, 0x03, 0x0d, 0x1b, 0x9d, 0xdc, 0xbc, 0xe9,
+ 0xd3, 0x71, 0x9b, 0xec, 0xa0, 0xea, 0xff, 0x1e,
+ 0xef, 0x5f, 0x85, 0xcb, 0x14, 0x43, 0x7e, 0x48,
+ },
+ },
+ {
+ .data_len = 4160,
+ .digest = {
+ 0x1b, 0x6d, 0xc4, 0x38, 0x60, 0x1b, 0xf1, 0x26,
+ 0x01, 0x24, 0x32, 0x69, 0x1f, 0x35, 0x46, 0xb6,
+ 0x0e, 0x5c, 0x3a, 0x2b, 0x5c, 0xda, 0xfa, 0x17,
+ 0x8a, 0x58, 0xb1, 0x67, 0x65, 0xb8, 0xe7, 0x3c,
+ 0x3e, 0x14, 0x64, 0xa6, 0xe5, 0xdd, 0xf6, 0x7c,
+ 0x7a, 0x0c, 0xa3, 0xa4, 0x70, 0x2a, 0xbe, 0x45,
+ },
+ },
+ {
+ .data_len = 4224,
+ .digest = {
+ 0x4a, 0x57, 0x3f, 0xe4, 0xbf, 0x4c, 0xfd, 0x2d,
+ 0x0d, 0x06, 0xdf, 0xc6, 0x13, 0xb4, 0x36, 0x51,
+ 0xc5, 0xe2, 0x65, 0xc0, 0x6d, 0x02, 0x7b, 0x68,
+ 0xd2, 0x70, 0x67, 0x5a, 0x94, 0xb3, 0x23, 0xb3,
+ 0xbb, 0x1b, 0x8b, 0x53, 0x48, 0x04, 0xcc, 0x69,
+ 0x85, 0x13, 0x6e, 0xbe, 0xdb, 0xd3, 0x31, 0x90,
+ },
+ },
+ {
+ .data_len = 16384,
+ .digest = {
+ 0x33, 0xbe, 0x6e, 0x2d, 0x97, 0x65, 0x4f, 0xe1,
+ 0xc9, 0x5f, 0xf9, 0x7c, 0x1e, 0x2a, 0xf0, 0x99,
+ 0xed, 0xa5, 0xaf, 0xac, 0x39, 0xf2, 0x33, 0x01,
+ 0x9b, 0xce, 0x33, 0x9f, 0x30, 0xa1, 0x87, 0xce,
+ 0x51, 0x45, 0x01, 0x96, 0x22, 0x40, 0xf1, 0x3f,
+ 0xca, 0xb4, 0xe7, 0x3e, 0x62, 0xbb, 0x4b, 0xc9,
+ },
+ },
+};
+
+static const u8 hash_testvec_consolidated[SHA3_384_DIGEST_SIZE] = {
+ 0x2d, 0x63, 0xd8, 0xee, 0x11, 0x58, 0x7d, 0xae,
+ 0xd9, 0x34, 0x57, 0xae, 0x99, 0x12, 0x0b, 0x04,
+ 0x94, 0x38, 0x29, 0xef, 0xcf, 0xdd, 0x65, 0xec,
+ 0xcf, 0xe6, 0x99, 0x54, 0x5f, 0x32, 0xd2, 0x57,
+ 0x8d, 0x76, 0xe5, 0x89, 0x1d, 0x28, 0x07, 0x5c,
+ 0x3b, 0xda, 0x08, 0xef, 0x85, 0x16, 0x10, 0x09,
+};
diff --git a/lib/crypto/tests/sha3_512_kunit.c b/lib/crypto/tests/sha3_512_kunit.c
new file mode 100644
index 000000000000..2762dae16aa0
--- /dev/null
+++ b/lib/crypto/tests/sha3_512_kunit.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+#include <crypto/sha3.h>
+#include "sha3_512_testvecs.h"
+
+#define HASH sha3_512
+#define HASH_CTX sha3_ctx
+#define HASH_SIZE SHA3_512_DIGEST_SIZE
+#define HASH_INIT sha3_512_init
+#define HASH_UPDATE sha3_update
+#define HASH_FINAL sha3_final
+#include "hash-test-template.h"
+
+static struct kunit_case hash_test_cases[] = {
+ HASH_KUNIT_CASES,
+ KUNIT_CASE(benchmark_hash),
+ {},
+};
+
+static struct kunit_suite hash_test_suite = {
+ .name = "sha3_512",
+ .test_cases = hash_test_cases,
+ .suite_init = hash_suite_init,
+ .suite_exit = hash_suite_exit,
+};
+kunit_test_suite(hash_test_suite);
+
+MODULE_DESCRIPTION("KUnit tests and benchmark for SHA-512 and HMAC-SHA512");
+MODULE_LICENSE("GPL");
diff --git a/lib/crypto/tests/sha3_512_testvecs.h b/lib/crypto/tests/sha3_512_testvecs.h
new file mode 100644
index 000000000000..141223038786
--- /dev/null
+++ b/lib/crypto/tests/sha3_512_testvecs.h
@@ -0,0 +1,331 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* This file was generated by: ../../../scripts/crypto/gen-hash-testvecs.py sha3-512 */
+
+static const struct {
+ size_t data_len;
+ u8 digest[SHA3_512_DIGEST_SIZE];
+} hash_testvecs[] = {
+ {
+ .data_len = 0,
+ .digest = {
+ 0xa6, 0x9f, 0x73, 0xcc, 0xa2, 0x3a, 0x9a, 0xc5,
+ 0xc8, 0xb5, 0x67, 0xdc, 0x18, 0x5a, 0x75, 0x6e,
+ 0x97, 0xc9, 0x82, 0x16, 0x4f, 0xe2, 0x58, 0x59,
+ 0xe0, 0xd1, 0xdc, 0xc1, 0x47, 0x5c, 0x80, 0xa6,
+ 0x15, 0xb2, 0x12, 0x3a, 0xf1, 0xf5, 0xf9, 0x4c,
+ 0x11, 0xe3, 0xe9, 0x40, 0x2c, 0x3a, 0xc5, 0x58,
+ 0xf5, 0x00, 0x19, 0x9d, 0x95, 0xb6, 0xd3, 0xe3,
+ 0x01, 0x75, 0x85, 0x86, 0x28, 0x1d, 0xcd, 0x26,
+ },
+ },
+ {
+ .data_len = 1,
+ .digest = {
+ 0x76, 0x8b, 0xbf, 0xff, 0xfe, 0x4f, 0xc3, 0xfc,
+ 0xb6, 0xec, 0x19, 0x02, 0x04, 0x1a, 0x82, 0x77,
+ 0xf1, 0xf1, 0x88, 0x71, 0x6d, 0xea, 0xab, 0x1e,
+ 0x4b, 0x5a, 0x23, 0x0e, 0x03, 0x2e, 0x8d, 0x9f,
+ 0x77, 0xdf, 0x9f, 0xb1, 0x1e, 0x39, 0x9e, 0x9f,
+ 0x0c, 0x37, 0x3f, 0x67, 0x89, 0x52, 0xa6, 0x88,
+ 0x0b, 0x91, 0x82, 0x83, 0x8b, 0xc5, 0x51, 0xc9,
+ 0xe2, 0x87, 0xc8, 0x48, 0x51, 0x33, 0x88, 0x1a,
+ },
+ },
+ {
+ .data_len = 2,
+ .digest = {
+ 0x2a, 0x3c, 0x9b, 0x70, 0x53, 0xd7, 0x5b, 0x42,
+ 0x7c, 0xe8, 0x52, 0x4c, 0xe3, 0x40, 0xd6, 0xbb,
+ 0x08, 0x1e, 0x97, 0x89, 0x55, 0x89, 0xe2, 0x83,
+ 0x3b, 0x85, 0x17, 0x38, 0x00, 0x0c, 0x5c, 0x82,
+ 0x1c, 0xb2, 0x25, 0x94, 0x45, 0xb4, 0x06, 0x62,
+ 0x7e, 0xe4, 0x32, 0x50, 0xae, 0x2a, 0xce, 0x4b,
+ 0x94, 0xb3, 0x02, 0xd0, 0xc9, 0x44, 0x46, 0xa0,
+ 0x77, 0x85, 0xa5, 0x38, 0xf6, 0xe3, 0x7f, 0xb5,
+ },
+ },
+ {
+ .data_len = 3,
+ .digest = {
+ 0x24, 0x08, 0x49, 0x5e, 0x5f, 0x90, 0xb2, 0x8c,
+ 0x8e, 0x41, 0x0f, 0xe6, 0x96, 0xfe, 0xb6, 0x2b,
+ 0x5c, 0x52, 0x2c, 0xba, 0x41, 0x84, 0x33, 0xd5,
+ 0xb4, 0x7c, 0xbb, 0xd8, 0x20, 0x49, 0x58, 0x0d,
+ 0x30, 0x88, 0x26, 0x92, 0x9e, 0x51, 0x78, 0x70,
+ 0x42, 0x08, 0x64, 0xb5, 0xa9, 0xf1, 0x8b, 0xea,
+ 0x75, 0x9a, 0x2b, 0x6c, 0x61, 0x9d, 0x37, 0xa3,
+ 0x48, 0x7a, 0x4d, 0xbf, 0x5c, 0x43, 0x14, 0xe7,
+ },
+ },
+ {
+ .data_len = 16,
+ .digest = {
+ 0x47, 0x4d, 0xa3, 0xec, 0xa8, 0x6d, 0x3a, 0x76,
+ 0xb4, 0x2c, 0x6c, 0xad, 0x57, 0xf6, 0x18, 0xc9,
+ 0x1b, 0xf6, 0xe4, 0x9a, 0xe3, 0xbf, 0x23, 0xf0,
+ 0x4f, 0x4b, 0xca, 0x08, 0x2b, 0xb4, 0x8c, 0xa6,
+ 0x5e, 0x61, 0xf2, 0x63, 0x85, 0xc0, 0xc6, 0x6a,
+ 0x01, 0xea, 0x84, 0x7a, 0x71, 0x08, 0x2f, 0x72,
+ 0xc1, 0x64, 0x01, 0xe9, 0x2e, 0x96, 0xe9, 0x1d,
+ 0x9a, 0x85, 0x16, 0x9c, 0xda, 0xc5, 0xa3, 0xd4,
+ },
+ },
+ {
+ .data_len = 32,
+ .digest = {
+ 0xc4, 0xfe, 0x9a, 0x2b, 0xb1, 0xb8, 0x03, 0xa5,
+ 0x9b, 0x5f, 0xd1, 0xcf, 0x8d, 0xc3, 0x16, 0xbb,
+ 0x5f, 0xbb, 0x70, 0x6b, 0x63, 0xd6, 0x7c, 0x7d,
+ 0x5f, 0xe0, 0x11, 0xeb, 0xb5, 0x39, 0x0e, 0x3f,
+ 0x12, 0x4c, 0x2e, 0x6e, 0xa6, 0xb9, 0x24, 0xa2,
+ 0x0c, 0x02, 0xf9, 0x94, 0x3c, 0x48, 0xc3, 0x8a,
+ 0x26, 0x7a, 0x80, 0x26, 0x33, 0xea, 0xaf, 0xaf,
+ 0xca, 0x92, 0x16, 0xfe, 0xec, 0xf9, 0x01, 0x6c,
+ },
+ },
+ {
+ .data_len = 48,
+ .digest = {
+ 0xa9, 0x89, 0x4c, 0x42, 0xc7, 0x77, 0x15, 0x6c,
+ 0xbc, 0x0d, 0xab, 0x5a, 0x0c, 0x4c, 0x1d, 0x47,
+ 0xc6, 0x4e, 0x0a, 0xbe, 0x6c, 0xc1, 0x6e, 0xa2,
+ 0xe9, 0x3e, 0xed, 0x9c, 0x95, 0x0b, 0xfe, 0xcb,
+ 0x7a, 0xb4, 0xb9, 0x99, 0xa0, 0x2d, 0xda, 0xf9,
+ 0xdd, 0x2a, 0x68, 0x84, 0x1d, 0x3e, 0xe1, 0x1c,
+ 0x16, 0x2c, 0x05, 0x52, 0x5d, 0x55, 0xb2, 0x97,
+ 0x16, 0x94, 0xd2, 0xa8, 0x02, 0x00, 0x1b, 0x0f,
+ },
+ },
+ {
+ .data_len = 49,
+ .digest = {
+ 0x9c, 0xeb, 0x9f, 0x21, 0x48, 0x58, 0x6f, 0x0c,
+ 0x90, 0xfc, 0x57, 0x4c, 0x36, 0xef, 0x52, 0x06,
+ 0x9b, 0x86, 0x37, 0x25, 0x96, 0x78, 0x6f, 0xb2,
+ 0x99, 0x2d, 0xad, 0x3a, 0x2b, 0xd3, 0x1b, 0x1e,
+ 0xeb, 0x82, 0x7e, 0xe2, 0x80, 0xe4, 0x89, 0x28,
+ 0x34, 0x09, 0x10, 0xd9, 0xb9, 0x67, 0xaf, 0x92,
+ 0x29, 0xfc, 0x5e, 0xa4, 0x5d, 0xd0, 0x9c, 0x57,
+ 0x58, 0xe8, 0x29, 0x77, 0x9f, 0xd3, 0x93, 0x82,
+ },
+ },
+ {
+ .data_len = 63,
+ .digest = {
+ 0x8c, 0x7b, 0x97, 0xf5, 0xfa, 0x62, 0x1a, 0xf0,
+ 0x33, 0x17, 0x24, 0xea, 0x15, 0x96, 0x34, 0x6b,
+ 0xa0, 0xb6, 0x9a, 0x01, 0xe7, 0x00, 0x19, 0x2f,
+ 0x97, 0xfb, 0x66, 0xce, 0x47, 0x72, 0x42, 0xfd,
+ 0x05, 0x3e, 0x1b, 0x27, 0xae, 0xc2, 0xa2, 0xa0,
+ 0x1d, 0x3f, 0x3a, 0x2f, 0x31, 0xd6, 0xec, 0x23,
+ 0x17, 0xb6, 0x78, 0x00, 0xfd, 0x5d, 0x00, 0x47,
+ 0xc7, 0x5b, 0xea, 0x4d, 0xee, 0xb8, 0xef, 0x86,
+ },
+ },
+ {
+ .data_len = 64,
+ .digest = {
+ 0x4d, 0xcb, 0x7b, 0xad, 0xc7, 0xd0, 0x89, 0xc7,
+ 0x2d, 0x9b, 0x4f, 0x18, 0x86, 0x1e, 0x8b, 0xfb,
+ 0xd2, 0x7c, 0xd8, 0xf4, 0xb5, 0xa4, 0x91, 0x2c,
+ 0xee, 0xc7, 0x6a, 0x97, 0xb1, 0x75, 0x23, 0xbe,
+ 0x0a, 0x29, 0x5f, 0xfa, 0x78, 0x71, 0x01, 0x71,
+ 0x04, 0xaf, 0x7a, 0xd1, 0xa4, 0xc7, 0xe0, 0xe7,
+ 0x7d, 0xc0, 0x3e, 0x3f, 0xd1, 0x11, 0x8c, 0x68,
+ 0xc6, 0x1e, 0xc4, 0xb6, 0x4d, 0x61, 0xf4, 0xed,
+ },
+ },
+ {
+ .data_len = 65,
+ .digest = {
+ 0xb4, 0x0c, 0xf8, 0x3b, 0xfe, 0x89, 0xc4, 0xc3,
+ 0x2e, 0x38, 0xd7, 0x83, 0xe2, 0x9c, 0xee, 0xbd,
+ 0x1d, 0xc3, 0xcc, 0xf0, 0x65, 0x7a, 0xf7, 0x44,
+ 0x4b, 0xec, 0xa7, 0xd3, 0x0a, 0x49, 0x8b, 0x23,
+ 0x4c, 0xee, 0x41, 0x3f, 0xfb, 0x73, 0xd3, 0x9b,
+ 0x70, 0x63, 0x1f, 0x0f, 0x88, 0x44, 0x55, 0xec,
+ 0xda, 0x7d, 0x7b, 0xfc, 0xf3, 0x58, 0xc9, 0x7c,
+ 0xb8, 0xbc, 0x92, 0xa1, 0xaf, 0xda, 0x98, 0xa8,
+ },
+ },
+ {
+ .data_len = 127,
+ .digest = {
+ 0x7d, 0xb5, 0x9f, 0xa3, 0x2e, 0x02, 0x58, 0x82,
+ 0x43, 0xd0, 0x54, 0x33, 0x7b, 0x29, 0xf5, 0x95,
+ 0x46, 0xee, 0xa9, 0x11, 0x88, 0xee, 0xbf, 0x6f,
+ 0xab, 0x70, 0xc6, 0xd0, 0x77, 0x48, 0xc1, 0x0b,
+ 0x98, 0x95, 0xb5, 0xfa, 0xb7, 0xc1, 0xe0, 0x45,
+ 0x6d, 0x01, 0x59, 0xce, 0x09, 0xaa, 0x05, 0x8d,
+ 0xed, 0x67, 0xc0, 0xf7, 0x88, 0x6f, 0xc3, 0x3f,
+ 0xd1, 0xe8, 0x12, 0x97, 0xc4, 0xcc, 0x35, 0x11,
+ },
+ },
+ {
+ .data_len = 128,
+ .digest = {
+ 0xb9, 0xf9, 0xba, 0xdc, 0xea, 0xd7, 0x15, 0x06,
+ 0xaa, 0x4a, 0x68, 0x78, 0x20, 0xcc, 0xbd, 0x08,
+ 0x4d, 0x36, 0x4f, 0x69, 0x60, 0x3f, 0x29, 0x6b,
+ 0x21, 0x8f, 0xcd, 0xb4, 0xca, 0x5a, 0xed, 0xf3,
+ 0xe8, 0x00, 0x6c, 0x5e, 0x01, 0x22, 0x4a, 0xcb,
+ 0x58, 0x34, 0x17, 0xed, 0xbe, 0x78, 0x2b, 0xd6,
+ 0x09, 0x76, 0x72, 0x9c, 0xac, 0x95, 0x76, 0x9e,
+ 0x1c, 0xdc, 0xa4, 0x18, 0x6b, 0x28, 0x7e, 0x39,
+ },
+ },
+ {
+ .data_len = 129,
+ .digest = {
+ 0xe6, 0x9e, 0xd1, 0x79, 0xbc, 0xc2, 0x1a, 0x84,
+ 0xa3, 0xb9, 0xc0, 0x7b, 0x0a, 0x08, 0xd5, 0x9a,
+ 0xe0, 0x9a, 0x24, 0xc2, 0xe3, 0x7d, 0x25, 0x2f,
+ 0xa2, 0xd7, 0x6c, 0xd5, 0xda, 0x06, 0x41, 0xe8,
+ 0x66, 0xe5, 0xbc, 0x08, 0xa6, 0x27, 0x88, 0xca,
+ 0xdc, 0x9f, 0xfd, 0x21, 0xb5, 0x11, 0x31, 0x1f,
+ 0xcc, 0xf3, 0x9c, 0xbf, 0x89, 0xda, 0x4d, 0x9c,
+ 0x04, 0xed, 0x0e, 0x30, 0xb5, 0x93, 0xb9, 0xd7,
+ },
+ },
+ {
+ .data_len = 256,
+ .digest = {
+ 0xda, 0x47, 0x2c, 0xbb, 0xe6, 0x34, 0xef, 0xaa,
+ 0x16, 0xd2, 0x6e, 0x0e, 0xd2, 0x46, 0x1b, 0xcc,
+ 0x29, 0xbe, 0xde, 0x16, 0xef, 0x7e, 0x66, 0x19,
+ 0x03, 0x37, 0x80, 0x97, 0x15, 0x45, 0x58, 0xcb,
+ 0x26, 0x21, 0xdb, 0x55, 0x8b, 0x69, 0x40, 0x9e,
+ 0x23, 0x2b, 0x95, 0xfb, 0x20, 0x96, 0x1d, 0x6e,
+ 0x3b, 0xec, 0xe3, 0x9d, 0x6a, 0x32, 0xfd, 0x07,
+ 0x88, 0x09, 0x3f, 0xca, 0x08, 0xee, 0xb2, 0x6d,
+ },
+ },
+ {
+ .data_len = 511,
+ .digest = {
+ 0x05, 0xb6, 0x9b, 0x75, 0x2d, 0x5d, 0xbd, 0xd3,
+ 0xc5, 0xb3, 0xf6, 0x58, 0x75, 0x20, 0xba, 0x38,
+ 0x57, 0xc9, 0x35, 0xce, 0xab, 0x3d, 0xd4, 0x13,
+ 0x68, 0xd0, 0x93, 0xef, 0x37, 0x16, 0x39, 0x41,
+ 0xa7, 0xe4, 0x19, 0xa0, 0x0c, 0x47, 0x1d, 0xc2,
+ 0x9d, 0xda, 0x8d, 0x02, 0x7b, 0x08, 0x23, 0x32,
+ 0xb4, 0x08, 0x09, 0xc1, 0x57, 0xb2, 0x52, 0xda,
+ 0x09, 0x24, 0x3c, 0x03, 0x13, 0x12, 0x92, 0xb0,
+ },
+ },
+ {
+ .data_len = 513,
+ .digest = {
+ 0xbf, 0x52, 0xcd, 0x71, 0xe7, 0x8d, 0x59, 0x05,
+ 0x75, 0x3a, 0xad, 0x7c, 0xc3, 0x2c, 0xbc, 0xac,
+ 0x6f, 0x13, 0xf3, 0xce, 0xbd, 0x1f, 0x1f, 0xd0,
+ 0x02, 0xbf, 0x8e, 0x59, 0xd4, 0xd7, 0xb1, 0x47,
+ 0xb5, 0x21, 0x26, 0x0f, 0x8b, 0x1e, 0xce, 0xf2,
+ 0x36, 0x29, 0x40, 0xbd, 0x27, 0xd3, 0x2f, 0x61,
+ 0x59, 0x5f, 0xed, 0xaf, 0x75, 0xe1, 0x43, 0xc0,
+ 0x1a, 0xda, 0x01, 0x7c, 0xc2, 0x6a, 0xba, 0x4e,
+ },
+ },
+ {
+ .data_len = 1000,
+ .digest = {
+ 0x0f, 0xcc, 0xcd, 0xa0, 0x1f, 0x05, 0xa1, 0xd4,
+ 0x40, 0xb1, 0xfe, 0x64, 0xa3, 0x3c, 0x02, 0x47,
+ 0x8b, 0x6b, 0xf8, 0xe0, 0xf0, 0x62, 0xf1, 0x72,
+ 0xf5, 0xd5, 0xfa, 0xb6, 0x99, 0xcd, 0xb7, 0xbe,
+ 0x7f, 0xae, 0xcc, 0xd3, 0xd9, 0x33, 0x1d, 0xc0,
+ 0x82, 0xf5, 0xef, 0xb6, 0x7c, 0xd1, 0x3d, 0x49,
+ 0xef, 0x38, 0x4e, 0xb3, 0xda, 0x48, 0xef, 0xf6,
+ 0x56, 0x62, 0x49, 0x5e, 0x19, 0x1d, 0x89, 0x8b,
+ },
+ },
+ {
+ .data_len = 3333,
+ .digest = {
+ 0x12, 0x7c, 0xfd, 0xed, 0xb2, 0x03, 0x74, 0x25,
+ 0xfc, 0x41, 0xf6, 0xd6, 0x21, 0x08, 0xcf, 0x28,
+ 0x10, 0xbe, 0xfb, 0xb8, 0x97, 0x12, 0x12, 0x7c,
+ 0x5f, 0xbc, 0x8c, 0x0d, 0xa3, 0xaa, 0xa0, 0xf2,
+ 0xc3, 0xa0, 0xab, 0xc7, 0xb5, 0xcb, 0xc0, 0xff,
+ 0x93, 0x4e, 0xae, 0x5c, 0xea, 0xef, 0x7e, 0x4f,
+ 0xc2, 0xe1, 0xca, 0x7e, 0xda, 0xb1, 0x9b, 0xb6,
+ 0x8e, 0xcf, 0x3d, 0x6d, 0x3a, 0x83, 0x29, 0x7b,
+ },
+ },
+ {
+ .data_len = 4096,
+ .digest = {
+ 0x8b, 0x07, 0xf7, 0x29, 0x0c, 0xd7, 0xba, 0x42,
+ 0x99, 0xfc, 0xb2, 0x79, 0x59, 0x8a, 0xc2, 0x87,
+ 0x80, 0x0e, 0x4d, 0x18, 0xe9, 0xb3, 0x4c, 0x50,
+ 0xd5, 0xd5, 0xd4, 0x25, 0xf0, 0x30, 0x33, 0x77,
+ 0x6c, 0xc8, 0x3e, 0xfb, 0xbc, 0xc0, 0x34, 0xeb,
+ 0xf9, 0xfb, 0x80, 0x80, 0x75, 0x1a, 0x42, 0x68,
+ 0x76, 0x7b, 0x63, 0xc1, 0xf3, 0xca, 0x28, 0x53,
+ 0xba, 0x28, 0x19, 0xa4, 0xa0, 0x0d, 0xa6, 0x29,
+ },
+ },
+ {
+ .data_len = 4128,
+ .digest = {
+ 0xee, 0xbe, 0x8d, 0xf1, 0x23, 0x57, 0x62, 0xf7,
+ 0xd6, 0x6d, 0xa0, 0x22, 0xdb, 0x0f, 0x66, 0xc3,
+ 0x0e, 0x40, 0x00, 0x1b, 0x6f, 0xc3, 0x85, 0x35,
+ 0x86, 0xe9, 0x91, 0x65, 0xc8, 0xfd, 0xb4, 0x5b,
+ 0x65, 0x43, 0x6b, 0xd6, 0xd8, 0xaf, 0xd2, 0x70,
+ 0xae, 0x8f, 0x48, 0xd5, 0x29, 0x26, 0x79, 0xc5,
+ 0x5b, 0xad, 0xe5, 0xee, 0x3b, 0x20, 0x45, 0x78,
+ 0xe0, 0x74, 0x14, 0x4e, 0xa7, 0x90, 0xb4, 0x7e,
+ },
+ },
+ {
+ .data_len = 4160,
+ .digest = {
+ 0x7f, 0x27, 0xac, 0xc0, 0x20, 0x89, 0x8b, 0x2a,
+ 0x4c, 0x93, 0x79, 0x98, 0x91, 0x17, 0x11, 0x44,
+ 0xdb, 0x21, 0x53, 0x72, 0x90, 0x1c, 0xbe, 0xa6,
+ 0x76, 0xfb, 0x59, 0x2e, 0x68, 0x6a, 0xad, 0xff,
+ 0x5b, 0x9d, 0xfa, 0x83, 0xf5, 0x26, 0xcb, 0x89,
+ 0x33, 0xbf, 0x51, 0x87, 0x1a, 0x94, 0xb2, 0x4f,
+ 0x77, 0xee, 0xab, 0xe0, 0xc8, 0x8a, 0xa2, 0x79,
+ 0x5e, 0xb0, 0xe0, 0x2d, 0x25, 0x9b, 0xff, 0x1b,
+ },
+ },
+ {
+ .data_len = 4224,
+ .digest = {
+ 0xa5, 0x86, 0x6d, 0x50, 0xbf, 0x35, 0xe6, 0x35,
+ 0x21, 0xb1, 0xab, 0x55, 0x48, 0xad, 0xbd, 0x31,
+ 0x6a, 0xb2, 0xd0, 0x4d, 0x27, 0x0b, 0x9a, 0x54,
+ 0x00, 0x53, 0xa6, 0x02, 0x5a, 0x11, 0x2e, 0xcd,
+ 0x4d, 0xa0, 0x62, 0x16, 0xf5, 0x18, 0xc1, 0x53,
+ 0x69, 0x2b, 0xd3, 0x11, 0x6f, 0x19, 0xf2, 0xbc,
+ 0x64, 0xa4, 0xce, 0xe7, 0x62, 0x97, 0xb6, 0xb3,
+ 0x4f, 0xf5, 0x2c, 0x8c, 0xa0, 0xe2, 0x36, 0xdc,
+ },
+ },
+ {
+ .data_len = 16384,
+ .digest = {
+ 0x57, 0xd6, 0xfc, 0x07, 0xa0, 0x38, 0x35, 0x9f,
+ 0x76, 0xcc, 0x39, 0xe7, 0xdc, 0x8c, 0x53, 0x75,
+ 0x71, 0x18, 0x42, 0x92, 0xea, 0xc1, 0x57, 0xce,
+ 0xf5, 0xb6, 0xdc, 0x31, 0xf1, 0x0c, 0xfb, 0x51,
+ 0xb3, 0x18, 0xd6, 0x1e, 0xd0, 0x83, 0xa5, 0xe4,
+ 0x86, 0xbe, 0xfe, 0x2c, 0xe9, 0x65, 0x1f, 0xe3,
+ 0x95, 0xce, 0x6d, 0xdf, 0x57, 0xfd, 0x44, 0x8a,
+ 0x24, 0xbd, 0x4a, 0x89, 0xb7, 0xc4, 0xdc, 0x43,
+ },
+ },
+};
+
+static const u8 hash_testvec_consolidated[SHA3_512_DIGEST_SIZE] = {
+ 0xf7, 0xdd, 0x09, 0x36, 0xf8, 0x51, 0x62, 0x2b,
+ 0xa6, 0x90, 0x6c, 0x22, 0x83, 0xe7, 0xea, 0xd3,
+ 0xbe, 0x6c, 0xb0, 0xb4, 0xef, 0x18, 0x49, 0x20,
+ 0xf6, 0x29, 0x26, 0x5e, 0xdf, 0x6d, 0x2f, 0x4d,
+ 0x74, 0xa8, 0xba, 0x68, 0x42, 0xc0, 0x9e, 0xb5,
+ 0x41, 0x33, 0x61, 0x29, 0x31, 0x59, 0x04, 0x86,
+ 0x25, 0x5f, 0x06, 0xb0, 0xc8, 0x3d, 0x5e, 0xfa,
+ 0x40, 0x99, 0x91, 0x46, 0x18, 0x2e, 0x31, 0xa5,
+};
diff --git a/lib/crypto/tests/sha3_shake128_kunit.c b/lib/crypto/tests/sha3_shake128_kunit.c
new file mode 100644
index 000000000000..6dcacd03d452
--- /dev/null
+++ b/lib/crypto/tests/sha3_shake128_kunit.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+#include <crypto/sha3.h>
+#include "sha3_shake128_testvecs.h"
+
+static void test_shake128_128(const u8 *in, size_t in_len, u8 *out)
+{
+ shake128(in, in_len, out, SHAKE128_DIGEST_SIZE);
+}
+
+#define HASH test_shake128_128
+#define HASH_CTX sha3_ctx
+#define HASH_SIZE SHAKE128_DIGEST_SIZE
+#define HASH_INIT shake128_init
+#define HASH_UPDATE sha3_update
+#define HASH_FINAL sha3_final
+#include "hash-test-template.h"
+
+static struct kunit_case hash_test_cases[] = {
+ HASH_KUNIT_CASES,
+ KUNIT_CASE(benchmark_hash),
+ {},
+};
+
+static struct kunit_suite hash_test_suite = {
+ .name = "shake128",
+ .test_cases = hash_test_cases,
+ .suite_init = hash_suite_init,
+ .suite_exit = hash_suite_exit,
+};
+kunit_test_suite(hash_test_suite);
+
+MODULE_DESCRIPTION("KUnit tests and benchmark for SHAKE-128 with 128-bit digest");
+MODULE_LICENSE("GPL");
diff --git a/lib/crypto/tests/sha3_shake128_testvecs.h b/lib/crypto/tests/sha3_shake128_testvecs.h
new file mode 100644
index 000000000000..0b7e5393de4d
--- /dev/null
+++ b/lib/crypto/tests/sha3_shake128_testvecs.h
@@ -0,0 +1,181 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* This file was generated by: ../../../scripts/crypto/gen-hash-testvecs.py shake128 */
+
+static const struct {
+ size_t data_len;
+ u8 digest[SHAKE128_DIGEST_SIZE];
+} hash_testvecs[] = {
+ {
+ .data_len = 0,
+ .digest = {
+ 0x7f, 0x9c, 0x2b, 0xa4, 0xe8, 0x8f, 0x82, 0x7d,
+ 0x61, 0x60, 0x45, 0x50, 0x76, 0x05, 0x85, 0x3e,
+ },
+ },
+ {
+ .data_len = 1,
+ .digest = {
+ 0xa6, 0x5e, 0xcf, 0x33, 0x0f, 0x30, 0x76, 0x6c,
+ 0x64, 0x9f, 0x94, 0x7a, 0x7f, 0xfa, 0x3a, 0x3a,
+ },
+ },
+ {
+ .data_len = 2,
+ .digest = {
+ 0x61, 0x70, 0x9c, 0xe0, 0x22, 0xed, 0xff, 0xad,
+ 0xfe, 0x2c, 0x70, 0xde, 0x54, 0x66, 0xe0, 0x36,
+ },
+ },
+ {
+ .data_len = 3,
+ .digest = {
+ 0xfc, 0xb1, 0x3e, 0x14, 0xc7, 0x37, 0xe4, 0xd9,
+ 0x91, 0x78, 0x88, 0x80, 0x23, 0xa5, 0xe0, 0xac,
+ },
+ },
+ {
+ .data_len = 16,
+ .digest = {
+ 0xaa, 0x42, 0x2f, 0xfb, 0x5e, 0x87, 0xf3, 0xf4,
+ 0x73, 0x28, 0x21, 0x34, 0x41, 0xc6, 0x34, 0xa4,
+ },
+ },
+ {
+ .data_len = 32,
+ .digest = {
+ 0x66, 0x01, 0x42, 0x87, 0x59, 0x1a, 0x47, 0x67,
+ 0x4e, 0x4f, 0xfc, 0x25, 0x61, 0x44, 0xda, 0x25,
+ },
+ },
+ {
+ .data_len = 48,
+ .digest = {
+ 0x76, 0xa2, 0x47, 0xff, 0x72, 0x60, 0x53, 0x86,
+ 0x7d, 0x53, 0x0f, 0xbe, 0xb6, 0x47, 0x2d, 0xee,
+ },
+ },
+ {
+ .data_len = 49,
+ .digest = {
+ 0xb2, 0xbe, 0xc4, 0x58, 0xc5, 0x92, 0x06, 0x61,
+ 0x5a, 0x08, 0x58, 0xb7, 0x43, 0xf8, 0x53, 0x95,
+ },
+ },
+ {
+ .data_len = 63,
+ .digest = {
+ 0x00, 0x45, 0xf4, 0xdf, 0x8c, 0xf9, 0xc4, 0x5e,
+ 0xb5, 0x01, 0x95, 0x4f, 0xcf, 0xd5, 0xd7, 0x3f,
+ },
+ },
+ {
+ .data_len = 64,
+ .digest = {
+ 0xff, 0x23, 0xf8, 0x05, 0x6a, 0x35, 0xe8, 0xec,
+ 0x42, 0xec, 0x8c, 0x76, 0x1e, 0x0d, 0x75, 0x38,
+ },
+ },
+ {
+ .data_len = 65,
+ .digest = {
+ 0x11, 0xcd, 0x3e, 0xcc, 0xf7, 0x2f, 0x75, 0xc5,
+ 0x5a, 0x46, 0x0c, 0x80, 0x2b, 0xed, 0xf4, 0x33,
+ },
+ },
+ {
+ .data_len = 127,
+ .digest = {
+ 0x8d, 0x00, 0xe7, 0x21, 0xbc, 0x6c, 0x29, 0xd2,
+ 0x49, 0x3f, 0x66, 0x39, 0xf2, 0xa3, 0x54, 0xa9,
+ },
+ },
+ {
+ .data_len = 128,
+ .digest = {
+ 0xf7, 0x3d, 0x71, 0x74, 0x6b, 0xd2, 0x4c, 0xe0,
+ 0x11, 0x9b, 0x14, 0xcd, 0x1e, 0x2b, 0xae, 0xd2,
+ },
+ },
+ {
+ .data_len = 129,
+ .digest = {
+ 0x8e, 0xa7, 0xdf, 0xa6, 0x32, 0x9f, 0x5c, 0x9a,
+ 0x01, 0xa2, 0xf9, 0x02, 0xf1, 0x34, 0x36, 0x30,
+ },
+ },
+ {
+ .data_len = 256,
+ .digest = {
+ 0x5c, 0x9f, 0x55, 0x8c, 0x5e, 0x08, 0x8e, 0xd8,
+ 0xa6, 0x07, 0xa9, 0xa1, 0x51, 0x42, 0xd3, 0xff,
+ },
+ },
+ {
+ .data_len = 511,
+ .digest = {
+ 0xb5, 0xc5, 0x92, 0x5b, 0xc6, 0x07, 0xd6, 0xca,
+ 0x30, 0x4d, 0x12, 0x98, 0x67, 0x8d, 0x1f, 0x0c,
+ },
+ },
+ {
+ .data_len = 513,
+ .digest = {
+ 0x99, 0x33, 0xe9, 0xf2, 0x2b, 0xd5, 0xdf, 0xc4,
+ 0x03, 0x7b, 0x48, 0xca, 0x28, 0x4d, 0x40, 0x6e,
+ },
+ },
+ {
+ .data_len = 1000,
+ .digest = {
+ 0x86, 0xbd, 0xe0, 0x6f, 0x54, 0xd7, 0xb1, 0xb2,
+ 0xda, 0xc6, 0xec, 0x26, 0xa2, 0xbf, 0x4e, 0xa4,
+ },
+ },
+ {
+ .data_len = 3333,
+ .digest = {
+ 0x8a, 0xd9, 0xb2, 0xb2, 0xbc, 0x35, 0x6e, 0x80,
+ 0x6d, 0x43, 0xe8, 0xf5, 0x3a, 0x89, 0xb8, 0x25,
+ },
+ },
+ {
+ .data_len = 4096,
+ .digest = {
+ 0xff, 0x86, 0x5d, 0xe3, 0x4f, 0xb4, 0x75, 0xb2,
+ 0x12, 0x29, 0xd0, 0xd3, 0xeb, 0x2d, 0x65, 0x91,
+ },
+ },
+ {
+ .data_len = 4128,
+ .digest = {
+ 0x99, 0x84, 0x6b, 0xaa, 0x2d, 0x54, 0xb4, 0x81,
+ 0x9d, 0x97, 0xa3, 0x23, 0x8c, 0x97, 0xfc, 0x7c,
+ },
+ },
+ {
+ .data_len = 4160,
+ .digest = {
+ 0xa8, 0x25, 0x51, 0x1c, 0x48, 0xea, 0xb4, 0xe3,
+ 0x59, 0xbb, 0x30, 0x84, 0x3e, 0x98, 0x14, 0x28,
+ },
+ },
+ {
+ .data_len = 4224,
+ .digest = {
+ 0xa4, 0x8d, 0x19, 0xff, 0xf3, 0xec, 0xa9, 0xff,
+ 0xe9, 0x16, 0x48, 0x26, 0x29, 0x4b, 0xb8, 0x8d,
+ },
+ },
+ {
+ .data_len = 16384,
+ .digest = {
+ 0x31, 0xd9, 0x5c, 0xc7, 0xbc, 0xd5, 0x6f, 0xfb,
+ 0x49, 0xd3, 0x75, 0x52, 0xcd, 0xc2, 0x1a, 0xa4,
+ },
+ },
+};
+
+static const u8 hash_testvec_consolidated[SHAKE128_DIGEST_SIZE] = {
+ 0x6f, 0x31, 0x9a, 0x7f, 0xbb, 0x0a, 0x36, 0x25,
+ 0x0e, 0x98, 0x4c, 0xe1, 0x16, 0x9a, 0xf7, 0xdd,
+};
diff --git a/lib/crypto/tests/sha3_shake256_kunit.c b/lib/crypto/tests/sha3_shake256_kunit.c
new file mode 100644
index 000000000000..62a9af574872
--- /dev/null
+++ b/lib/crypto/tests/sha3_shake256_kunit.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+#include <crypto/sha3.h>
+#include "sha3_shake256_testvecs.h"
+
+static void test_shake256_256(const u8 *in, size_t in_len, u8 *out)
+{
+ shake256(in, in_len, out, SHAKE256_DIGEST_SIZE);
+}
+
+#define HASH test_shake256_256
+#define HASH_CTX sha3_ctx
+#define HASH_SIZE SHAKE256_DIGEST_SIZE
+#define HASH_INIT shake256_init
+#define HASH_UPDATE sha3_update
+#define HASH_FINAL sha3_final
+#include "hash-test-template.h"
+
+static struct kunit_case hash_test_cases[] = {
+ HASH_KUNIT_CASES,
+ KUNIT_CASE(benchmark_hash),
+ {},
+};
+
+static struct kunit_suite hash_test_suite = {
+ .name = "shake256",
+ .test_cases = hash_test_cases,
+ .suite_init = hash_suite_init,
+ .suite_exit = hash_suite_exit,
+};
+kunit_test_suite(hash_test_suite);
+
+MODULE_DESCRIPTION("KUnit tests and benchmark for SHAKE-256 with 256-bit digest");
+MODULE_LICENSE("GPL");
diff --git a/lib/crypto/tests/sha3_shake256_testvecs.h b/lib/crypto/tests/sha3_shake256_testvecs.h
new file mode 100644
index 000000000000..ee70a677a44e
--- /dev/null
+++ b/lib/crypto/tests/sha3_shake256_testvecs.h
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* This file was generated by: ../../../scripts/crypto/gen-hash-testvecs.py shake256 */
+
+static const struct {
+ size_t data_len;
+ u8 digest[SHAKE256_DIGEST_SIZE];
+} hash_testvecs[] = {
+ {
+ .data_len = 0,
+ .digest = {
+ 0x46, 0xb9, 0xdd, 0x2b, 0x0b, 0xa8, 0x8d, 0x13,
+ 0x23, 0x3b, 0x3f, 0xeb, 0x74, 0x3e, 0xeb, 0x24,
+ 0x3f, 0xcd, 0x52, 0xea, 0x62, 0xb8, 0x1b, 0x82,
+ 0xb5, 0x0c, 0x27, 0x64, 0x6e, 0xd5, 0x76, 0x2f,
+ },
+ },
+ {
+ .data_len = 1,
+ .digest = {
+ 0x54, 0x96, 0x57, 0xea, 0x93, 0x2b, 0xb5, 0x8f,
+ 0xe5, 0xfc, 0x76, 0xe8, 0x01, 0xdd, 0xc8, 0x25,
+ 0x4e, 0x22, 0x0b, 0xa7, 0xb4, 0xe1, 0x50, 0xe2,
+ 0x34, 0x8b, 0x9e, 0xdb, 0xc2, 0xc9, 0x51, 0xa3,
+ },
+ },
+ {
+ .data_len = 2,
+ .digest = {
+ 0xf3, 0xfc, 0x74, 0x4a, 0x54, 0x34, 0x01, 0xf7,
+ 0xa7, 0xf2, 0x50, 0xa0, 0x0b, 0x2a, 0x3c, 0x4b,
+ 0x12, 0xd4, 0xd3, 0xf7, 0xd6, 0x89, 0x5d, 0xce,
+ 0xcb, 0xfe, 0xd9, 0x57, 0x28, 0x4f, 0xdc, 0x9d,
+ },
+ },
+ {
+ .data_len = 3,
+ .digest = {
+ 0x36, 0x3d, 0xd3, 0xf7, 0xf4, 0xf3, 0x1b, 0xca,
+ 0xba, 0x75, 0x81, 0x0d, 0xad, 0xb5, 0xeb, 0xad,
+ 0x74, 0x4e, 0x3c, 0xad, 0x33, 0x62, 0x4b, 0xee,
+ 0xdc, 0x15, 0x66, 0xaa, 0x61, 0x65, 0x2e, 0x5c,
+ },
+ },
+ {
+ .data_len = 16,
+ .digest = {
+ 0xc7, 0xce, 0xcb, 0x21, 0xce, 0x45, 0xbd, 0xd5,
+ 0x76, 0x31, 0x76, 0x41, 0xf4, 0x3f, 0x77, 0xbf,
+ 0x17, 0xa2, 0xd8, 0xa9, 0x8e, 0x35, 0xc2, 0x8f,
+ 0x16, 0xba, 0x50, 0x50, 0x7c, 0xf5, 0x3c, 0xa4,
+ },
+ },
+ {
+ .data_len = 32,
+ .digest = {
+ 0x61, 0x82, 0xc8, 0xea, 0x8c, 0x26, 0x46, 0x6b,
+ 0xc4, 0x54, 0xf8, 0x5f, 0x12, 0x15, 0x00, 0xe8,
+ 0xab, 0xac, 0x39, 0xb9, 0xbb, 0x60, 0x24, 0x5e,
+ 0x55, 0x2d, 0x24, 0xcc, 0x91, 0x46, 0x21, 0x8b,
+ },
+ },
+ {
+ .data_len = 48,
+ .digest = {
+ 0x68, 0xcd, 0xc9, 0x90, 0x16, 0xca, 0x72, 0xcb,
+ 0xb5, 0x84, 0x0d, 0x02, 0x89, 0x3b, 0x9c, 0x0e,
+ 0x67, 0x24, 0x0a, 0xbb, 0x5a, 0xe6, 0x3c, 0xca,
+ 0x62, 0x75, 0x0a, 0x93, 0x8e, 0xe3, 0xae, 0xed,
+ },
+ },
+ {
+ .data_len = 49,
+ .digest = {
+ 0x0c, 0xc1, 0xb0, 0xd8, 0xcb, 0xf7, 0xa7, 0x55,
+ 0x7a, 0x87, 0xb8, 0x65, 0x9c, 0x23, 0xfa, 0x02,
+ 0x34, 0x45, 0xb9, 0xe9, 0x35, 0xe8, 0x9f, 0xf2,
+ 0xcf, 0x02, 0xaa, 0x7a, 0x8d, 0x49, 0x69, 0xd0,
+ },
+ },
+ {
+ .data_len = 63,
+ .digest = {
+ 0x9b, 0x76, 0x53, 0xed, 0x46, 0x2b, 0x7d, 0x40,
+ 0xd1, 0xc7, 0x83, 0xda, 0x5e, 0xbd, 0x73, 0x69,
+ 0xc7, 0x40, 0x65, 0x44, 0x5a, 0x0e, 0xf3, 0xb5,
+ 0xfc, 0x30, 0x98, 0x00, 0x32, 0x50, 0xb8, 0x26,
+ },
+ },
+ {
+ .data_len = 64,
+ .digest = {
+ 0xab, 0xfa, 0x35, 0xcb, 0xf2, 0xc3, 0xf8, 0x8b,
+ 0x0a, 0xec, 0xb4, 0x5a, 0x45, 0x54, 0x33, 0xf7,
+ 0x13, 0x26, 0x62, 0x1c, 0x94, 0x37, 0x47, 0x07,
+ 0x24, 0xfc, 0xd4, 0x2a, 0x8e, 0x71, 0x3f, 0xf3,
+ },
+ },
+ {
+ .data_len = 65,
+ .digest = {
+ 0x45, 0x7d, 0xbb, 0x96, 0x0c, 0xb0, 0x63, 0x4e,
+ 0xc5, 0xe6, 0xfe, 0x6e, 0x78, 0x55, 0xaf, 0x2d,
+ 0x0b, 0x2b, 0x08, 0x2e, 0xbf, 0xfd, 0x4b, 0xf3,
+ 0xe0, 0x0b, 0xa7, 0x11, 0x52, 0xf7, 0x43, 0xe1,
+ },
+ },
+ {
+ .data_len = 127,
+ .digest = {
+ 0xc2, 0x66, 0xdb, 0x73, 0x17, 0x6e, 0xc1, 0xf0,
+ 0xb7, 0xad, 0x8c, 0xa8, 0x4f, 0xfc, 0x6d, 0x6b,
+ 0x96, 0xff, 0x9d, 0x63, 0x7e, 0x2a, 0x49, 0x93,
+ 0x16, 0xca, 0x78, 0x7b, 0x80, 0x19, 0x3d, 0x48,
+ },
+ },
+ {
+ .data_len = 128,
+ .digest = {
+ 0x08, 0x23, 0xfb, 0x6c, 0xcd, 0x62, 0x9d, 0x95,
+ 0x44, 0xf1, 0x62, 0xd2, 0x41, 0x54, 0x2d, 0xe4,
+ 0x55, 0x2b, 0xc6, 0x1c, 0xec, 0xb9, 0x34, 0x29,
+ 0x21, 0x4d, 0x39, 0x8e, 0xbe, 0x6c, 0x9c, 0xb3,
+ },
+ },
+ {
+ .data_len = 129,
+ .digest = {
+ 0x68, 0xe6, 0xf1, 0x5e, 0x57, 0x3a, 0x04, 0xc0,
+ 0x6a, 0x59, 0x7c, 0x80, 0x09, 0x1f, 0x9d, 0x4d,
+ 0x88, 0x73, 0xd5, 0xb3, 0x69, 0x57, 0x8a, 0xf0,
+ 0x00, 0x6c, 0xe3, 0x59, 0x8e, 0x1e, 0xcc, 0x21,
+ },
+ },
+ {
+ .data_len = 256,
+ .digest = {
+ 0x0b, 0xc3, 0xb8, 0xb5, 0x6e, 0x03, 0x62, 0xb5,
+ 0x52, 0x0a, 0xab, 0x64, 0x6a, 0xc1, 0x06, 0x50,
+ 0x57, 0xdf, 0x4a, 0x50, 0x20, 0x5e, 0x06, 0x4c,
+ 0xa3, 0xa6, 0x7c, 0x28, 0x86, 0x54, 0x67, 0x1d,
+ },
+ },
+ {
+ .data_len = 511,
+ .digest = {
+ 0x25, 0xa8, 0x9b, 0xc4, 0xee, 0xcf, 0xe8, 0xf7,
+ 0xe1, 0xb2, 0x3b, 0x91, 0xf4, 0x05, 0x89, 0x04,
+ 0x9c, 0xb0, 0x9a, 0xe4, 0x06, 0xea, 0xc0, 0x8f,
+ 0x2f, 0x7c, 0xf9, 0x4b, 0x6c, 0x53, 0x68, 0x56,
+ },
+ },
+ {
+ .data_len = 513,
+ .digest = {
+ 0x49, 0x56, 0x69, 0x90, 0x94, 0x8c, 0xbc, 0x28,
+ 0x60, 0x09, 0x87, 0xd8, 0x32, 0x9b, 0x33, 0xd6,
+ 0x6b, 0xd9, 0x1b, 0x11, 0x9a, 0x50, 0x62, 0xbf,
+ 0x8a, 0x43, 0x96, 0x5d, 0xdd, 0xef, 0x2a, 0x54,
+ },
+ },
+ {
+ .data_len = 1000,
+ .digest = {
+ 0xa2, 0xf3, 0xa6, 0x25, 0xb9, 0x4f, 0xfc, 0xa1,
+ 0x43, 0xae, 0x12, 0x03, 0x7f, 0xa7, 0x2a, 0x0b,
+ 0xcc, 0x0f, 0xd4, 0x7c, 0x22, 0x57, 0x99, 0xfe,
+ 0x9a, 0x68, 0x30, 0x64, 0xf1, 0xb1, 0xa3, 0xeb,
+ },
+ },
+ {
+ .data_len = 3333,
+ .digest = {
+ 0xba, 0x0a, 0x14, 0xbc, 0xa0, 0x6d, 0xf3, 0x68,
+ 0xb9, 0x36, 0xc4, 0x8f, 0xf8, 0x0e, 0x4c, 0x21,
+ 0x48, 0x33, 0xfe, 0x7b, 0x2d, 0x30, 0x2e, 0xed,
+ 0x43, 0xc0, 0x95, 0xf0, 0x4c, 0x6e, 0xd0, 0x31,
+ },
+ },
+ {
+ .data_len = 4096,
+ .digest = {
+ 0x8d, 0x60, 0x87, 0x64, 0x6f, 0xf0, 0xbc, 0xfd,
+ 0xb6, 0x29, 0x5d, 0xfc, 0xe5, 0x2d, 0x7d, 0x1d,
+ 0x8f, 0xd0, 0x20, 0xdd, 0xaf, 0x2c, 0x71, 0x65,
+ 0xfd, 0x95, 0x6c, 0x1b, 0x97, 0x6c, 0xd9, 0x51,
+ },
+ },
+ {
+ .data_len = 4128,
+ .digest = {
+ 0x8d, 0x1b, 0xb3, 0xdc, 0x75, 0x75, 0x90, 0x35,
+ 0x8c, 0x09, 0x26, 0x9c, 0x4a, 0x90, 0x08, 0x2e,
+ 0xd8, 0x7c, 0xf7, 0x9b, 0x57, 0xe8, 0xee, 0xe4,
+ 0xa5, 0xb0, 0xa4, 0x5f, 0x4f, 0x3b, 0x0f, 0xe2,
+ },
+ },
+ {
+ .data_len = 4160,
+ .digest = {
+ 0x24, 0xf4, 0xb6, 0x6e, 0x3f, 0x00, 0x29, 0x69,
+ 0x29, 0xc2, 0x0e, 0x9f, 0x7c, 0x6c, 0x69, 0x74,
+ 0xb6, 0x6f, 0x5e, 0xfc, 0xee, 0x71, 0xe8, 0x29,
+ 0xeb, 0x61, 0x16, 0xa8, 0xe7, 0x78, 0xe5, 0xc5,
+ },
+ },
+ {
+ .data_len = 4224,
+ .digest = {
+ 0x07, 0x42, 0xd7, 0xc8, 0x91, 0x72, 0x45, 0xe5,
+ 0x32, 0xb8, 0xa8, 0x4f, 0xf6, 0x69, 0xca, 0xae,
+ 0x2a, 0x5a, 0x67, 0x8d, 0x87, 0x63, 0x4c, 0xaa,
+ 0xc6, 0xe3, 0x5d, 0x8d, 0xf6, 0x54, 0x29, 0xbb,
+ },
+ },
+ {
+ .data_len = 16384,
+ .digest = {
+ 0x35, 0x9d, 0xd4, 0x76, 0xa9, 0xf3, 0xd8, 0x8b,
+ 0x27, 0xe8, 0x94, 0x01, 0xdd, 0xb3, 0x75, 0x03,
+ 0xd5, 0xa4, 0x96, 0xf4, 0xa0, 0x04, 0x48, 0xfd,
+ 0x5f, 0x34, 0x0e, 0x0d, 0x41, 0x3a, 0x06, 0xc8,
+ },
+ },
+};
+
+static const u8 hash_testvec_consolidated[SHAKE256_DIGEST_SIZE] = {
+ 0x4b, 0xb0, 0x5b, 0x22, 0x55, 0x3d, 0x33, 0x1a,
+ 0xe7, 0x1c, 0x8f, 0xbe, 0xcb, 0xec, 0xbd, 0x88,
+ 0x1e, 0x83, 0x49, 0x25, 0xe2, 0xff, 0xb4, 0xf6,
+ 0x10, 0xe4, 0x9c, 0x59, 0x24, 0x38, 0xe7, 0x1a,
+};
diff --git a/scripts/crypto/gen-hash-testvecs.py b/scripts/crypto/gen-hash-testvecs.py
index 4ac927d40cf5..f0bc057bd76d 100755
--- a/scripts/crypto/gen-hash-testvecs.py
+++ b/scripts/crypto/gen-hash-testvecs.py
@@ -61,6 +61,10 @@ def hash_update(ctx, data):
ctx.update(data)
def hash_final(ctx):
+ if ctx.name == "shake_128":
+ return ctx.digest(16)
+ if ctx.name == "shake_256":
+ return ctx.digest(32)
return ctx.digest()
def compute_hash(alg, data):
@@ -117,7 +121,7 @@ def gen_hmac_testvecs(alg):
ctx.update(mac)
print_static_u8_array_definition(
f'hmac_testvec_consolidated[{alg.upper()}_DIGEST_SIZE]',
- ctx.digest())
+ hash_final(ctx))
def gen_additional_poly1305_testvecs():
key = b'\xff' * POLY1305_KEY_SIZE
@@ -143,5 +147,5 @@ print(f'/* This file was generated by: {sys.argv[0]} {" ".join(sys.argv[1:])} */
gen_unkeyed_testvecs(alg)
if alg == 'poly1305':
gen_additional_poly1305_testvecs()
-else:
+elif alg != 'shake128' and alg != 'shake256':
gen_hmac_testvecs(alg)
Some more comments: On Fri, Sep 19, 2025 at 05:31:59PM +0100, David Howells wrote: > +#if 0 > +static void sha3_dump_state(const struct sha3_ctx *ctx, const char *prefix) > +{ > + const __be64 *p = (const __be64 *)ctx->state.st; > + > + for (int i = 0; i < 6; i++) { > + pr_info("SHA3 %s %016llx %016llx %016llx %016llx\n", > + prefix, > + be64_to_cpu(p[0]), be64_to_cpu(p[1]), > + be64_to_cpu(p[2]), be64_to_cpu(p[3])); > + p += 4; > + } > + pr_info("SHA3 %s %016llx\n", prefix, be64_to_cpu(p[0])); > +} > +#endif Unused code should not be added. > +/* > + * On some 32-bit architectures (h8300), GCC ends up using > + * over 1 KB of stack if we inline the round calculation into the loop > + * in keccakf(). On the other hand, on 64-bit architectures with plenty > + * of [64-bit wide] general purpose registers, not inlining it severely > + * hurts performance. So let's use 64-bitness as a heuristic to decide > + * whether to inline or not. > + */ The above comment doesn't match the code. "keccakf()" should be sha3_keccakf_generic(). > +/* update the state with given number of rounds */ > + > +static SHA3_INLINE void keccakf_round(u64 st[25]) The above comment doesn't match the code. keccakf_round() does only one round. Also, the parameter should be strongly typed: 'struct sha3_state *' Likewise in all the other functions that take the raw u64 array. > +static void sha3_be_swap_state(u64 st[25]) > +{ > +#ifdef __BIG_ENDIAN > + for (int i = 0; i < 25; i++) > + st[i] = __builtin_bswap64(st[i]); > +#endif > +} As noted by the kernel test robot, this doesn't compile on all architectures. How about: for (size_t i = 0; i < ARRAY_SIZE(state->st); i++) cpu_to_le64s(&state->st[i]); There also should be a comment somewhere that describes what's going on with the state endianness. I.e., on big endian CPUs we keep the state words as little endian to make XOR'ing data into them easier, and we swap them to native endianness temporarily when doing the permutation. > +/* > + * Perform the mixing step. > + */ > +static void sha3_keccakf_generic(u64 st[25]) > +{ > + int round; > + > + sha3_be_swap_state(st); > + > + for (round = 0; round < KECCAK_ROUNDS; round++) { > + keccakf_round(st); > + /* Iota */ > + st[0] ^= keccakf_rndc[round]; > + } In the spec, "Iota" is part of the round. Having it be separate from keccakf_round() in the code is confusing. > +/** > + * sha3_update() - Update a SHA3 context of any type with message data > + * @ctx: the context to update; must have been initialized > + * @data: the message data > + * @len: the data length in bytes > + * > + * This can be called any number of times to perform the "keccak sponge > + * absorbing" phase. > + * > + * It may be called again after @sha3_final() has been called to add more data > + * to the hash. Note, however, that finalising a hash modifies the state, so > + * {update,final,update} is not equivalent to {update,update}. > + */ Would you mind putting all the kerneldoc comments for the public API in the .h file, similar to sha1.h and sha2.h? Then they'll all be in a consistent place, and they won't have to be moved around each time we change functions to inline functions or vice versa. > +void sha3_update(struct sha3_ctx *ctx, const u8 *data, unsigned int len) > +{ > + unsigned int partial = ctx->partial; > + unsigned int bsize = ctx->block_size; > + > + if (partial && partial + len >= bsize) { > + sha3_absorb_xorle(ctx, data, partial, bsize - partial); > + len -= bsize - partial; > + data += bsize - partial; > + sha3_keccakf(ctx->state.st); > + ctx->partial = 0; > + } > + > + if (len >= bsize) { > + size_t nblocks = len / bsize; > + > + if (nblocks) { > + sha3_absorb_blocks(ctx, data, nblocks); > + data += nblocks * bsize; > + len -= nblocks * bsize; > + } The 'if (nblocks)' check above is unnecessary, since 'len >= bsize' implies there is at least one block. > +/** > + * sha3_squeeze() - Finalize a SHA3 digest of any type and extract the digest > + * @ctx: the context to finalize; must have been initialized > + * @out: Where to write the resulting message digest > + * @out_size: The amount of digest to extract to @out > + * > + * Finish the computation of a SHA3 message digest of any type and perform the > + * "Keccak sponge squeezing" phase. @out_size amount of digest is written to > + * @out buffer. > + * > + * This may be called multiple times to extract continuations of the digest. > + * Note that, for example, two consecutive 16-byte squeezes laid end-to-end > + * will yield the same as one 32-byte squeeze. > + * > + * The state will have the end marker added again if any new updates have > + * happened since the last time it was squeezed. > + */ First, this patch's proposed API is error-prone due to the weak typing that allows mixing steps of different algorithms together. For example, users could initialize a sha3_ctx with sha3_256_init() and then squeeze an arbitrary amount from it, incorrectly treating it as a XOF. It would be worth considering separating the APIs for the different algorithms that are part of SHA-3, similar to what I did with SHA-224 and SHA-256. (They would of course still share code internally, just like SHA-2.) Second, the support for update() + squeeze() + update() + squeeze() seems to be trying to achieve something that is not defined in the SHA-3 spec. Could you elaborate on what it is meant to be doing, and why it's here? According to the spec, the XOFs SHAKE128 and SHAKE256 actually just take a single message as their input. One might think the above sequence would compute SHAKE*() on the first message as well as SHAKE*() of the two messages concatenated together. But that's not what you've made it do, as you've made it apply padding after *both* messages. So, then one might think that it's meant to be a XOF on the sequence of messages, built on top of SHAKE*(). But it's not that either, since the way that you've proposed to format the sequence of messages into a longer message isn't injective. So, I can't figure out why you're supporting this usage and what it is meant to be doing. > +void sha3_squeeze(struct sha3_ctx *ctx, u8 *out, size_t out_size) > +{ > + unsigned int squeeze_offset = ctx->squeeze_offset; > + unsigned int digest_size = out_size; The digest_size variable is unnecessary, and it's also misleading since this function is used both for the digests and the XOFs. Just use the already-existing 'out_size' variable. > + unsigned int bsize = ctx->block_size; > + u8 *p = (u8 *)ctx->state.st, end_marker = 0x80; > + > + if (!ctx->end_marked) { > + sha3_absorb_xorle(ctx, &ctx->padding, ctx->partial, 1); > + sha3_absorb_xorle(ctx, &end_marker, bsize - 1, 1); > + ctx->end_marked = true; > + } > + > + for (;;) { > + if (squeeze_offset == 0) { > + sha3_keccakf(ctx->state.st); > + } > + > + unsigned int part = umin(digest_size, bsize - squeeze_offset); > + > + if (part > 0) { > + memcpy(out, p + squeeze_offset, part); > + digest_size -= part; > + out += part; > + squeeze_offset += part; > + } > + if (!digest_size) > + break; > + if (squeeze_offset >= bsize) > + squeeze_offset -= bsize; The last two lines could just set squeeze_offset to 0 unconditionally, given that the block must have been filled. > +/** > + * sha3_init() - Initialize a SHA3 context for a new message > + * @ctx: the context to initialize > + * > + * Initialize a SHA3 context for any size of SHA-3 digest. > + */ > +void sha3_init(struct sha3_ctx *ctx) > +{ > + memset(ctx, 0, sizeof(*ctx)); > +} > +EXPORT_SYMBOL_GPL(sha3_init); Here's another place where the proposed API invites misuse. If someone calls sha3_init() followed by sha3_update(), which would be a very intuitive thing to do, there will be an infinite loop, because the block_size wouldn't have been initialized. sha3_init() is actually an internal implementation detail of the real initialization functions. I recommend just removing it, and making the real initialization functions use designated initializers to assign to the whole sha3_ctx. > +/** > + * shake128() - Convenience wrapper to digest a simple buffer as SHAKE128 > + * @in: The data to be digested > + * @in_len: The amount of data to be digested > + * @out: The buffer into which the digest will be stored > + * @out_len: The size of the digest desired (variable length) > + */ Shouldn't the term "digest" be avoided when talking about the output from a XOF, to avoid confusion with traditional hash functions? > +/* > + * Do a quick test using SHAKE256 and a 200 byte digest. > + */ > +static const u8 sha3_sample1[] __initconst = > + "The quick red fox jumped over the lazy brown dog!\n" > + "The quick red fox jumped over the lazy brown dog!\n" > + "The quick red fox jumped over the lazy brown dog!\n" > + "The quick red fox jumped over the lazy brown dog!\n"; > +static const u8 sha3_sample2[] __initconst = > + "hello\n"; > +static const u8 sha3_sample_shake256_200_step1[] __initconst = { > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ > + 0xab, 0x06, 0xd4, 0xf9, 0x8b, 0xfd, 0xb2, 0xc4, 0xfe, 0xf1, 0xcc, 0xe2, > + 0x40, 0x45, 0xdd, 0x15, 0xcb, 0xdd, 0x02, 0x8d, 0xb7, 0x9f, 0x1e, 0x67, > + 0xd6, 0x7f, 0x98, 0x5e, 0x1b, 0x19, 0xf8, 0x01, 0x43, 0x82, 0xcb, 0xd8, > + 0x5d, 0x21, 0x64, 0xa8, 0x80, 0xc9, 0x22, 0xe5, 0x07, 0xaf, 0xe2, 0x5d, > + 0xcd, 0xc6, 0x23, 0x36, 0x2b, 0xc7, 0xc7, 0x7d, 0x09, 0x9d, 0x68, 0x05, > + 0xe4, 0x62, 0x63, 0x1b, 0x67, 0xbc, 0xf8, 0x95, 0x07, 0xd2, 0xe4, 0xd0, > + 0xba, 0xa2, 0x67, 0xf5, 0xe3, 0x15, 0xbc, 0x85, 0xa1, 0x50, 0xd6, 0x6f, > + 0x6f, 0xd4, 0x54, 0x4c, 0x3f, 0x4f, 0xe5, 0x1f, 0xb7, 0x00, 0x27, 0xfc, > + 0x15, 0x33, 0xc2, 0xf9, 0xb3, 0x4b, 0x9e, 0x81, 0xe5, 0x96, 0xbe, 0x05, > + 0x6c, 0xac, 0xf9, 0x9f, 0x65, 0x36, 0xbb, 0x11, 0x47, 0x6d, 0xf6, 0x8f, > + 0x9f, 0xa2, 0x77, 0x37, 0x3b, 0x18, 0x77, 0xcf, 0x65, 0xc5, 0xa1, 0x7e, > + 0x2c, 0x0e, 0x71, 0xf0, 0x4d, 0x18, 0x67, 0xb9, 0xc4, 0x8c, 0x64, 0x3b, > + 0x4b, 0x45, 0xea, 0x16, 0xb2, 0x4a, 0xc5, 0xf5, 0x85, 0xdc, 0xd2, 0xd9, > + 0x13, 0x77, 0xb3, 0x19, 0xd9, 0x8c, 0x9f, 0x28, 0xe7, 0x64, 0x91, 0x0f, > + 0x6f, 0x32, 0xbf, 0xa8, 0xa8, 0xa3, 0xff, 0x99, 0x0e, 0x0b, 0x62, 0x50, > + 0xf8, 0x3a, 0xc2, 0xf5, 0x98, 0x21, 0xeb, 0x9d, 0xe8, 0x45, 0xf4, 0x46, > + 0x1e, 0x8b, 0xbd, 0x10, 0x59, 0x2c, 0x87, 0xe2, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ > +}; > +static const u8 sha3_sample_shake256_200_step2[] __initconst = { > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ > + 0x5b, 0x43, 0x98, 0x3a, 0x4a, 0x5f, 0xa9, 0x14, 0xa5, 0x98, 0x26, 0xe2, > + 0xed, 0x45, 0x6a, 0x1d, 0x61, 0x24, 0xf5, 0x0c, 0xef, 0xda, 0xc2, 0x8a, > + 0x30, 0x0e, 0x03, 0xe5, 0x67, 0xdd, 0x7e, 0x9f, 0xa0, 0xa4, 0x07, 0x63, > + 0xdc, 0x6b, 0x7e, 0xbd, 0xd7, 0x7d, 0x7a, 0x6d, 0x55, 0x03, 0x02, 0x18, > + 0x12, 0x5d, 0xf9, 0x21, 0xc8, 0x78, 0x69, 0x7c, 0x64, 0x39, 0xfd, 0xf4, > + 0xd6, 0x06, 0xe6, 0xd8, 0x6f, 0xaa, 0x04, 0x5b, 0x40, 0xf3, 0x96, 0xb2, > + 0xb5, 0xd0, 0xb5, 0x43, 0x50, 0x9c, 0x08, 0xd6, 0x54, 0x8e, 0x8c, 0x85, > + 0xc2, 0x34, 0xce, 0x0c, 0x24, 0x31, 0x6f, 0x49, 0xec, 0x3d, 0x13, 0x1f, > + 0x36, 0x0a, 0x14, 0xa6, 0x5d, 0x51, 0x9a, 0x90, 0x1f, 0xf5, 0x1f, 0x61, > + 0xb7, 0x65, 0x64, 0x2a, 0x00, 0x07, 0xe4, 0x56, 0x80, 0x5c, 0xfa, 0x03, > + 0xc4, 0x97, 0xc1, 0x09, 0x35, 0xa2, 0x55, 0x72, 0x28, 0xe5, 0xb6, 0xef, > + 0x8e, 0xf4, 0xc2, 0x82, 0x22, 0xc7, 0x23, 0xac, 0xcb, 0xc1, 0x03, 0x52, > + 0x46, 0x9c, 0x17, 0xe0, 0xa3, 0x1b, 0x59, 0x9f, 0x01, 0xef, 0x5b, 0x46, > + 0xb2, 0x4b, 0x98, 0x6b, 0x32, 0x52, 0xe3, 0x29, 0x36, 0x8f, 0x66, 0x98, > + 0x5f, 0x6a, 0xa2, 0xf4, 0x68, 0x13, 0x5c, 0x94, 0xe4, 0x22, 0xb6, 0x83, > + 0xa0, 0xd7, 0xa3, 0xda, 0xa4, 0x84, 0x0c, 0xf6, 0xa2, 0xa4, 0x0e, 0x08, > + 0x6d, 0x2b, 0xd2, 0x31, 0x77, 0x36, 0xae, 0x53, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ > +}; > + > +static const u8 sha3_sample_shake256_200_step3[] __initconst = { > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ > + 0x61, 0x0a, 0x5e, 0xdf, 0xf1, 0x29, 0xae, 0x82, 0xab, 0x57, 0xa8, 0x1b, > + 0x4e, 0x7c, 0xb9, 0x14, 0x4a, 0x32, 0x7d, 0x82, 0xdc, 0xc2, 0x48, 0x1c, > + 0xf4, 0xa4, 0x18, 0xd5, 0x97, 0x35, 0x9a, 0x25, 0x0f, 0x5f, 0x1b, 0x04, > + 0xf1, 0x09, 0x2a, 0xe8, 0xb6, 0xa7, 0xe1, 0x90, 0xb6, 0x4d, 0x96, 0xf1, > + 0x7d, 0x4d, 0xb0, 0x4f, 0x44, 0xaf, 0x16, 0x4e, 0x63, 0xce, 0x46, 0x4c, > + 0x76, 0x18, 0xbe, 0x5f, 0xf4, 0x35, 0xef, 0x1f, 0xb1, 0x97, 0x94, 0x70, > + 0x96, 0x2f, 0xa2, 0x1b, 0xd6, 0x02, 0x51, 0x88, 0x33, 0x2b, 0x54, 0xb9, > + 0x44, 0xb4, 0xab, 0x6f, 0xeb, 0xfc, 0xe5, 0xee, 0xe3, 0x77, 0x91, 0xed, > + 0x3a, 0x4e, 0x60, 0x00, 0x44, 0xd1, 0xc7, 0x4a, 0x54, 0x77, 0x71, 0x95, > + 0x53, 0x88, 0x6b, 0x1e, 0x0f, 0xfd, 0x62, 0x02, 0xa7, 0x8e, 0x05, 0x6d, > + 0x21, 0x8f, 0x97, 0x20, 0xa0, 0xd7, 0xcf, 0xd8, 0x54, 0xec, 0x50, 0x72, > + 0x07, 0xb8, 0x9c, 0x76, 0xdb, 0x12, 0x00, 0xd2, 0x2e, 0x93, 0xee, 0xb9, > + 0x6a, 0x28, 0x5a, 0x46, 0x87, 0x90, 0xd5, 0xd6, 0x1d, 0x14, 0x0e, 0x16, > + 0xf1, 0x2c, 0xed, 0x7f, 0x28, 0x34, 0x8c, 0x2b, 0x96, 0x03, 0x80, 0x80, > + 0x9f, 0xc8, 0xf4, 0x2c, 0x53, 0xe0, 0x4b, 0x7b, 0xf4, 0x19, 0x8a, 0xc5, > + 0xb3, 0x21, 0x17, 0xce, 0xdb, 0xbf, 0xb7, 0x6b, 0x9a, 0xb5, 0x19, 0x89, > + 0x4c, 0x54, 0x28, 0x32, 0xe6, 0x85, 0xfa, 0x8f, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ > +}; > +static const u8 sha3_sample_shake256_200_step4[] __initconst = { > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ > + 0x83, 0x99, 0xc6, 0xda, 0x75, 0x79, 0x8e, 0x47, 0x06, 0xad, 0x19, 0xcb, > + 0x47, 0x61, 0x25, 0x6a, 0x8c, 0xa4, 0x7e, 0x74, 0xba, 0xbd, 0xda, 0xb6, > + 0x3b, 0x08, 0x48, 0x0f, 0x55, 0xd5, 0x85, 0x78, 0x5b, 0xd4, 0x31, 0xcb, > + 0x59, 0xff, 0x93, 0xff, 0xf6, 0x65, 0x4c, 0xf7, 0x6e, 0x4b, 0xef, 0x4d, > + 0x0e, 0x43, 0x8a, 0x2b, 0xed, 0x10, 0x26, 0x68, 0x12, 0x63, 0xed, 0x7a, > + 0x38, 0x0a, 0xa5, 0xd0, 0x79, 0x26, 0x75, 0xef, 0xce, 0xad, 0x6c, 0x12, > + 0x52, 0x33, 0xec, 0xe8, 0xe1, 0x89, 0x2f, 0x0f, 0x29, 0xb0, 0xf6, 0xff, > + 0x54, 0x11, 0xb2, 0x6b, 0x22, 0xb3, 0x48, 0x01, 0xa5, 0xcf, 0x29, 0xb7, > + 0xaf, 0x8c, 0xec, 0x1e, 0x75, 0x3e, 0xff, 0xfb, 0x31, 0xb8, 0xf6, 0xab, > + 0xae, 0xac, 0xec, 0xed, 0x27, 0x0b, 0x79, 0x10, 0x4f, 0x87, 0xe8, 0x43, > + 0x28, 0x94, 0x09, 0xca, 0x48, 0x63, 0x65, 0x61, 0x86, 0x83, 0x33, 0x30, > + 0x02, 0x6d, 0xf4, 0xef, 0x3c, 0x1a, 0x47, 0x8a, 0x25, 0x90, 0x31, 0x39, > + 0x95, 0x1d, 0x6f, 0x11, 0x5c, 0x0c, 0x72, 0xe6, 0x1b, 0xe1, 0x60, 0x45, > + 0x79, 0x89, 0x39, 0x48, 0x31, 0x4c, 0xc4, 0xd1, 0x08, 0x12, 0xf3, 0x5f, > + 0x84, 0x8c, 0x86, 0xba, 0xe5, 0xf1, 0x24, 0x61, 0x2f, 0xef, 0x17, 0x16, > + 0x4a, 0x29, 0xc0, 0xc6, 0x38, 0x47, 0x3a, 0x11, 0xc5, 0x7d, 0x62, 0x85, > + 0x9b, 0x18, 0x92, 0x4c, 0x12, 0x92, 0x9c, 0x0b, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ > +}; > + > +static void __init sha3_check_digest(const u8 *digest, const u8 *sample_digest, > + int digest_len) > +{ > + if (memcmp(digest, sample_digest, digest_len) != 0) { > + pr_err("SHAKE256(200) failed\n"); > + for (int i = 0; i < digest_len;) { > + int part = min(digest_len - i, 32); > + > + pr_err("%*phN\n", part, digest + i); > + i += part; > + } > + } > +} If a test is included at all here, it should be simpler, e.g. just compute the SHA3-256 of some short hardcoded message. That will be sufficient to test the implementation of the Keccak permutation. The real tests will be in the KUnit suite, as discussed previously. - Eric
Eric Biggers <ebiggers@kernel.org> wrote: > Also, the parameter should be strongly typed: 'struct sha3_state *' > Likewise in all the other functions that take the raw u64 array. Those function may be directly substituted by calls to assembly code - so u64[] is probably more appropriate. > > + for (round = 0; round < KECCAK_ROUNDS; round++) { > > + keccakf_round(st); > > + /* Iota */ > > + st[0] ^= keccakf_rndc[round]; > > + } > > In the spec, "Iota" is part of the round. Having it be separate from > keccakf_round() in the code is confusing. I assume that pertains to the comment about inlining in some way. This is as is in sha3_generic.c. I can move it into the round function if you like, but can you tell me what the effect will be? > Second, the support for update() + squeeze() + update() + squeeze() > seems to be trying to achieve something that is not defined in the SHA-3 > spec. Could you elaborate on what it is meant to be doing, and why it's > here? According to the spec, the XOFs SHAKE128 and SHAKE256 actually > just take a single message as their input. Turns out I was misunderstanding what I was looking at whilst trying to adapt Leancrypto's dilithium code. Whilst it does squeeze a context several times, it doesn't update it after finalising it without reinitialising it. David
On Tue, Sep 23, 2025 at 03:22:35PM +0100, David Howells wrote: > Eric Biggers <ebiggers@kernel.org> wrote: > > > Also, the parameter should be strongly typed: 'struct sha3_state *' > > Likewise in all the other functions that take the raw u64 array. > > Those function may be directly substituted by calls to assembly code - so > u64[] is probably more appropriate. We've been using strongly-typed state even for assembly functions. See the SHA-1, SHA-2, and ChaCha code. > > > + for (round = 0; round < KECCAK_ROUNDS; round++) { > > > + keccakf_round(st); > > > + /* Iota */ > > > + st[0] ^= keccakf_rndc[round]; > > > + } > > > > In the spec, "Iota" is part of the round. Having it be separate from > > keccakf_round() in the code is confusing. > > I assume that pertains to the comment about inlining in some way. This is as > is in sha3_generic.c. I can move it into the round function if you like, but > can you tell me what the effect will be? The effect will be that the code will align more closely with how the algorithm is described in the SHA-3 spec and other publications. > > Second, the support for update() + squeeze() + update() + squeeze() > > seems to be trying to achieve something that is not defined in the SHA-3 > > spec. Could you elaborate on what it is meant to be doing, and why it's > > here? According to the spec, the XOFs SHAKE128 and SHAKE256 actually > > just take a single message as their input. > > Turns out I was misunderstanding what I was looking at whilst trying to adapt > Leancrypto's dilithium code. Whilst it does squeeze a context several times, > it doesn't update it after finalising it without reinitialising it. Yes, that's what I thought. - Eric
Eric Biggers <ebiggers@kernel.org> wrote: > > I assume that pertains to the comment about inlining in some way. This is as > > is in sha3_generic.c. I can move it into the round function if you like, but > > can you tell me what the effect will be? > > The effect will be that the code will align more closely with how the > algorithm is described in the SHA-3 spec and other publications. I meant on the code produced and the stack consumed. It may align with other code, but if it runs off of the end of the stack then alignment is irrelevant. David
David Howells <dhowells@redhat.com> wrote: > Eric Biggers <ebiggers@kernel.org> wrote: > > > > I assume that pertains to the comment about inlining in some way. This > > > is as is in sha3_generic.c. I can move it into the round function if > > > you like, but can you tell me what the effect will be? > > > > The effect will be that the code will align more closely with how the > > algorithm is described in the SHA-3 spec and other publications. > > I meant on the code produced and the stack consumed. It may align with other > code, but if it runs off of the end of the stack then alignment is irrelevant. See commit 4767b9ad7d762876a5865a06465e13e139a01b6b "crypto: sha3-generic - deal with oversize stack frames" For some reason (maybe Ard can comment on it), he left the Iota function out of the keccakf_round() function. David
Eric Biggers <ebiggers@kernel.org> wrote: > > +/* update the state with given number of rounds */ > > + > > +static SHA3_INLINE void keccakf_round(u64 st[25]) > > The above comment doesn't match the code. keccakf_round() does only one > round. This is exactly as in crypto/sha3_generic.c. You may want to fix that also. > > +static void sha3_be_swap_state(u64 st[25]) > > +{ > > +#ifdef __BIG_ENDIAN > > + for (int i = 0; i < 25; i++) > > + st[i] = __builtin_bswap64(st[i]); > > +#endif > > +} > > As noted by the kernel test robot, this doesn't compile on all > architectures. How about: > > for (size_t i = 0; i < ARRAY_SIZE(state->st); i++) > cpu_to_le64s(&state->st[i]); Um. Maybe. If I'm going to do that I should probably do: for (size_t i = 0; i < ARRAY_SIZE(state->st); i++) le64_to_cpus(&state->st[i]); on the way in and: for (size_t i = 0; i < ARRAY_SIZE(state->st); i++) cpu_to_le64s(&state->st[i]); on the way out. You never know if it's PDP-11 Linux, right? ;-) > > +/* > > + * Perform the mixing step. > > + */ > > +static void sha3_keccakf_generic(u64 st[25]) > > +{ > > + int round; > > + > > + sha3_be_swap_state(st); > > + > > + for (round = 0; round < KECCAK_ROUNDS; round++) { > > + keccakf_round(st); > > + /* Iota */ > > + st[0] ^= keccakf_rndc[round]; > > + } > > In the spec, "Iota" is part of the round. Having it be separate from > keccakf_round() in the code is confusing. It's as crypto/sha3_generic.c. > Would you mind putting all the kerneldoc comments for the public API in > the .h file, similar to sha1.h and sha2.h? Then they'll all be in a > consistent place, and they won't have to be moved around each time we > change functions to inline functions or vice versa. Yes. I know include/crypto/ does it, but that really makes the header files suck as the doc-to-code ratio is too heavily in the doc's favour. Actually, this should be done properly and I'll add an API doc to Documention/crypto/. > > + if (len >= bsize) { > > + size_t nblocks = len / bsize; > > + > > + if (nblocks) { > > + sha3_absorb_blocks(ctx, data, nblocks); > > + data += nblocks * bsize; > > + len -= nblocks * bsize; > > + } > > The 'if (nblocks)' check above is unnecessary, since 'len >= bsize' > implies there is at least one block. Fair point. > > +/** > > + * sha3_squeeze() - Finalize a SHA3 digest of any type and extract the digest > > + * @ctx: the context to finalize; must have been initialized > > + * @out: Where to write the resulting message digest > > + * @out_size: The amount of digest to extract to @out > > + * > > + * Finish the computation of a SHA3 message digest of any type and perform the > > + * "Keccak sponge squeezing" phase. @out_size amount of digest is written to > > + * @out buffer. > > + * > > + * This may be called multiple times to extract continuations of the digest. > > + * Note that, for example, two consecutive 16-byte squeezes laid end-to-end > > + * will yield the same as one 32-byte squeeze. > > + * > > + * The state will have the end marker added again if any new updates have > > + * happened since the last time it was squeezed. > > + */ > > First, this patch's proposed API is error-prone due to the weak typing > that allows mixing steps of different algorithms together. For example, > users could initialize a sha3_ctx with sha3_256_init() and then squeeze > an arbitrary amount from it, incorrectly treating it as a XOF. It would > be worth considering separating the APIs for the different algorithms > that are part of SHA-3, similar to what I did with SHA-224 and SHA-256. > (They would of course still share code internally, just like SHA-2.) I disagree. You're adding excessive complexity. I would be more inclined to agree if the thing might crash because you used the wrong thing. That said, sha3_final() uses the digestsize set by sha3_whatever_init(), which could cause a problem, so I think it's better on balance to just add an extra parameter to sha3_final() to say how much digest you want and ditch ctx->digest_size. > Second, the support for update() + squeeze() + update() + squeeze() > seems to be trying to achieve something that is not defined in the SHA-3 > spec. Could you elaborate on what it is meant to be doing, and why it's > here? According to the spec, the XOFs SHAKE128 and SHAKE256 actually > just take a single message as their input. > > One might think the above sequence would compute SHAKE*() on the first > message as well as SHAKE*() of the two messages concatenated together. > But that's not what you've made it do, as you've made it apply padding > after *both* messages. So, then one might think that it's meant to be a > XOF on the sequence of messages, built on top of SHAKE*(). But it's not > that either, since the way that you've proposed to format the sequence > of messages into a longer message isn't injective. So, I can't figure > out why you're supporting this usage and what it is meant to be doing. I can't speak to that except to say that ML-DSA does exactly this as far as I can tell. > > +void sha3_squeeze(struct sha3_ctx *ctx, u8 *out, size_t out_size) > > +{ > > + unsigned int squeeze_offset = ctx->squeeze_offset; > > + unsigned int digest_size = out_size; > > The digest_size variable is unnecessary, and it's also misleading since > this function is used both for the digests and the XOFs. Just use the > already-existing 'out_size' variable. Fair point. I was setting digest_size to ctx->cigest_size if out_size was 0 and then returning it, but I'm no longer doing that. > > + unsigned int bsize = ctx->block_size; > > + u8 *p = (u8 *)ctx->state.st, end_marker = 0x80; > > + > > + if (!ctx->end_marked) { > > + sha3_absorb_xorle(ctx, &ctx->padding, ctx->partial, 1); > > + sha3_absorb_xorle(ctx, &end_marker, bsize - 1, 1); > > + ctx->end_marked = true; > > + } > > + > > + for (;;) { > > + if (squeeze_offset == 0) { > > + sha3_keccakf(ctx->state.st); > > + } > > + > > + unsigned int part = umin(digest_size, bsize - squeeze_offset); > > + > > + if (part > 0) { > > + memcpy(out, p + squeeze_offset, part); > > + digest_size -= part; > > + out += part; > > + squeeze_offset += part; > > + } > > + if (!digest_size) > > + break; > > + if (squeeze_offset >= bsize) > > + squeeze_offset -= bsize; > > The last two lines could just set squeeze_offset to 0 unconditionally, > given that the block must have been filled. Also a good point. I'm sure I tried that at some point, but it didn't work. I can't see why that should be the case though, and it should be an error if squeeze_offset > bsize. > > +/** > > + * sha3_init() - Initialize a SHA3 context for a new message > > + * @ctx: the context to initialize > > + * > > + * Initialize a SHA3 context for any size of SHA-3 digest. > > + */ > > +void sha3_init(struct sha3_ctx *ctx) > > +{ > > + memset(ctx, 0, sizeof(*ctx)); > > +} > > +EXPORT_SYMBOL_GPL(sha3_init); > > Here's another place where the proposed API invites misuse. If someone > calls sha3_init() followed by sha3_update(), which would be a very > intuitive thing to do, there will be an infinite loop, because the > block_size wouldn't have been initialized. sha3_init() is actually an > internal implementation detail of the real initialization functions. > > I recommend just removing it, and making the real initialization > functions use designated initializers to assign to the whole sha3_ctx. Okay, that's reasonable. > > +/** > > + * shake128() - Convenience wrapper to digest a simple buffer as SHAKE128 > > + * @in: The data to be digested > > + * @in_len: The amount of data to be digested > > + * @out: The buffer into which the digest will be stored > > + * @out_len: The size of the digest desired (variable length) > > + */ > > Shouldn't the term "digest" be avoided when talking about the output > from a XOF, to avoid confusion with traditional hash functions? No idea. There's not any real programmatic difference except for the padding byte. I can change it to "output" if it makes you happy. > > +/* > > + * Do a quick test using SHAKE256 and a 200 byte digest. > > + */ > > +static const u8 sha3_sample1[] __initconst = > > + "The quick red fox jumped over the lazy brown dog!\n" > > + "The quick red fox jumped over the lazy brown dog!\n" > > + "The quick red fox jumped over the lazy brown dog!\n" > > + "The quick red fox jumped over the lazy brown dog!\n"; > > +static const u8 sha3_sample2[] __initconst = > > + "hello\n"; > > +static const u8 sha3_sample_shake256_200_step1[] __initconst = { > > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ > > + 0xab, 0x06, 0xd4, 0xf9, 0x8b, 0xfd, 0xb2, 0xc4, 0xfe, 0xf1, 0xcc, 0xe2, > > + 0x40, 0x45, 0xdd, 0x15, 0xcb, 0xdd, 0x02, 0x8d, 0xb7, 0x9f, 0x1e, 0x67, > > + 0xd6, 0x7f, 0x98, 0x5e, 0x1b, 0x19, 0xf8, 0x01, 0x43, 0x82, 0xcb, 0xd8, > > + 0x5d, 0x21, 0x64, 0xa8, 0x80, 0xc9, 0x22, 0xe5, 0x07, 0xaf, 0xe2, 0x5d, > > + 0xcd, 0xc6, 0x23, 0x36, 0x2b, 0xc7, 0xc7, 0x7d, 0x09, 0x9d, 0x68, 0x05, > > + 0xe4, 0x62, 0x63, 0x1b, 0x67, 0xbc, 0xf8, 0x95, 0x07, 0xd2, 0xe4, 0xd0, > > + 0xba, 0xa2, 0x67, 0xf5, 0xe3, 0x15, 0xbc, 0x85, 0xa1, 0x50, 0xd6, 0x6f, > > + 0x6f, 0xd4, 0x54, 0x4c, 0x3f, 0x4f, 0xe5, 0x1f, 0xb7, 0x00, 0x27, 0xfc, > > + 0x15, 0x33, 0xc2, 0xf9, 0xb3, 0x4b, 0x9e, 0x81, 0xe5, 0x96, 0xbe, 0x05, > > + 0x6c, 0xac, 0xf9, 0x9f, 0x65, 0x36, 0xbb, 0x11, 0x47, 0x6d, 0xf6, 0x8f, > > + 0x9f, 0xa2, 0x77, 0x37, 0x3b, 0x18, 0x77, 0xcf, 0x65, 0xc5, 0xa1, 0x7e, > > + 0x2c, 0x0e, 0x71, 0xf0, 0x4d, 0x18, 0x67, 0xb9, 0xc4, 0x8c, 0x64, 0x3b, > > + 0x4b, 0x45, 0xea, 0x16, 0xb2, 0x4a, 0xc5, 0xf5, 0x85, 0xdc, 0xd2, 0xd9, > > + 0x13, 0x77, 0xb3, 0x19, 0xd9, 0x8c, 0x9f, 0x28, 0xe7, 0x64, 0x91, 0x0f, > > + 0x6f, 0x32, 0xbf, 0xa8, 0xa8, 0xa3, 0xff, 0x99, 0x0e, 0x0b, 0x62, 0x50, > > + 0xf8, 0x3a, 0xc2, 0xf5, 0x98, 0x21, 0xeb, 0x9d, 0xe8, 0x45, 0xf4, 0x46, > > + 0x1e, 0x8b, 0xbd, 0x10, 0x59, 0x2c, 0x87, 0xe2, > > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ > > +}; > > +static const u8 sha3_sample_shake256_200_step2[] __initconst = { > > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ > > + 0x5b, 0x43, 0x98, 0x3a, 0x4a, 0x5f, 0xa9, 0x14, 0xa5, 0x98, 0x26, 0xe2, > > + 0xed, 0x45, 0x6a, 0x1d, 0x61, 0x24, 0xf5, 0x0c, 0xef, 0xda, 0xc2, 0x8a, > > + 0x30, 0x0e, 0x03, 0xe5, 0x67, 0xdd, 0x7e, 0x9f, 0xa0, 0xa4, 0x07, 0x63, > > + 0xdc, 0x6b, 0x7e, 0xbd, 0xd7, 0x7d, 0x7a, 0x6d, 0x55, 0x03, 0x02, 0x18, > > + 0x12, 0x5d, 0xf9, 0x21, 0xc8, 0x78, 0x69, 0x7c, 0x64, 0x39, 0xfd, 0xf4, > > + 0xd6, 0x06, 0xe6, 0xd8, 0x6f, 0xaa, 0x04, 0x5b, 0x40, 0xf3, 0x96, 0xb2, > > + 0xb5, 0xd0, 0xb5, 0x43, 0x50, 0x9c, 0x08, 0xd6, 0x54, 0x8e, 0x8c, 0x85, > > + 0xc2, 0x34, 0xce, 0x0c, 0x24, 0x31, 0x6f, 0x49, 0xec, 0x3d, 0x13, 0x1f, > > + 0x36, 0x0a, 0x14, 0xa6, 0x5d, 0x51, 0x9a, 0x90, 0x1f, 0xf5, 0x1f, 0x61, > > + 0xb7, 0x65, 0x64, 0x2a, 0x00, 0x07, 0xe4, 0x56, 0x80, 0x5c, 0xfa, 0x03, > > + 0xc4, 0x97, 0xc1, 0x09, 0x35, 0xa2, 0x55, 0x72, 0x28, 0xe5, 0xb6, 0xef, > > + 0x8e, 0xf4, 0xc2, 0x82, 0x22, 0xc7, 0x23, 0xac, 0xcb, 0xc1, 0x03, 0x52, > > + 0x46, 0x9c, 0x17, 0xe0, 0xa3, 0x1b, 0x59, 0x9f, 0x01, 0xef, 0x5b, 0x46, > > + 0xb2, 0x4b, 0x98, 0x6b, 0x32, 0x52, 0xe3, 0x29, 0x36, 0x8f, 0x66, 0x98, > > + 0x5f, 0x6a, 0xa2, 0xf4, 0x68, 0x13, 0x5c, 0x94, 0xe4, 0x22, 0xb6, 0x83, > > + 0xa0, 0xd7, 0xa3, 0xda, 0xa4, 0x84, 0x0c, 0xf6, 0xa2, 0xa4, 0x0e, 0x08, > > + 0x6d, 0x2b, 0xd2, 0x31, 0x77, 0x36, 0xae, 0x53, > > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ > > +}; > > + > > +static const u8 sha3_sample_shake256_200_step3[] __initconst = { > > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ > > + 0x61, 0x0a, 0x5e, 0xdf, 0xf1, 0x29, 0xae, 0x82, 0xab, 0x57, 0xa8, 0x1b, > > + 0x4e, 0x7c, 0xb9, 0x14, 0x4a, 0x32, 0x7d, 0x82, 0xdc, 0xc2, 0x48, 0x1c, > > + 0xf4, 0xa4, 0x18, 0xd5, 0x97, 0x35, 0x9a, 0x25, 0x0f, 0x5f, 0x1b, 0x04, > > + 0xf1, 0x09, 0x2a, 0xe8, 0xb6, 0xa7, 0xe1, 0x90, 0xb6, 0x4d, 0x96, 0xf1, > > + 0x7d, 0x4d, 0xb0, 0x4f, 0x44, 0xaf, 0x16, 0x4e, 0x63, 0xce, 0x46, 0x4c, > > + 0x76, 0x18, 0xbe, 0x5f, 0xf4, 0x35, 0xef, 0x1f, 0xb1, 0x97, 0x94, 0x70, > > + 0x96, 0x2f, 0xa2, 0x1b, 0xd6, 0x02, 0x51, 0x88, 0x33, 0x2b, 0x54, 0xb9, > > + 0x44, 0xb4, 0xab, 0x6f, 0xeb, 0xfc, 0xe5, 0xee, 0xe3, 0x77, 0x91, 0xed, > > + 0x3a, 0x4e, 0x60, 0x00, 0x44, 0xd1, 0xc7, 0x4a, 0x54, 0x77, 0x71, 0x95, > > + 0x53, 0x88, 0x6b, 0x1e, 0x0f, 0xfd, 0x62, 0x02, 0xa7, 0x8e, 0x05, 0x6d, > > + 0x21, 0x8f, 0x97, 0x20, 0xa0, 0xd7, 0xcf, 0xd8, 0x54, 0xec, 0x50, 0x72, > > + 0x07, 0xb8, 0x9c, 0x76, 0xdb, 0x12, 0x00, 0xd2, 0x2e, 0x93, 0xee, 0xb9, > > + 0x6a, 0x28, 0x5a, 0x46, 0x87, 0x90, 0xd5, 0xd6, 0x1d, 0x14, 0x0e, 0x16, > > + 0xf1, 0x2c, 0xed, 0x7f, 0x28, 0x34, 0x8c, 0x2b, 0x96, 0x03, 0x80, 0x80, > > + 0x9f, 0xc8, 0xf4, 0x2c, 0x53, 0xe0, 0x4b, 0x7b, 0xf4, 0x19, 0x8a, 0xc5, > > + 0xb3, 0x21, 0x17, 0xce, 0xdb, 0xbf, 0xb7, 0x6b, 0x9a, 0xb5, 0x19, 0x89, > > + 0x4c, 0x54, 0x28, 0x32, 0xe6, 0x85, 0xfa, 0x8f, > > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ > > +}; > > +static const u8 sha3_sample_shake256_200_step4[] __initconst = { > > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ > > + 0x83, 0x99, 0xc6, 0xda, 0x75, 0x79, 0x8e, 0x47, 0x06, 0xad, 0x19, 0xcb, > > + 0x47, 0x61, 0x25, 0x6a, 0x8c, 0xa4, 0x7e, 0x74, 0xba, 0xbd, 0xda, 0xb6, > > + 0x3b, 0x08, 0x48, 0x0f, 0x55, 0xd5, 0x85, 0x78, 0x5b, 0xd4, 0x31, 0xcb, > > + 0x59, 0xff, 0x93, 0xff, 0xf6, 0x65, 0x4c, 0xf7, 0x6e, 0x4b, 0xef, 0x4d, > > + 0x0e, 0x43, 0x8a, 0x2b, 0xed, 0x10, 0x26, 0x68, 0x12, 0x63, 0xed, 0x7a, > > + 0x38, 0x0a, 0xa5, 0xd0, 0x79, 0x26, 0x75, 0xef, 0xce, 0xad, 0x6c, 0x12, > > + 0x52, 0x33, 0xec, 0xe8, 0xe1, 0x89, 0x2f, 0x0f, 0x29, 0xb0, 0xf6, 0xff, > > + 0x54, 0x11, 0xb2, 0x6b, 0x22, 0xb3, 0x48, 0x01, 0xa5, 0xcf, 0x29, 0xb7, > > + 0xaf, 0x8c, 0xec, 0x1e, 0x75, 0x3e, 0xff, 0xfb, 0x31, 0xb8, 0xf6, 0xab, > > + 0xae, 0xac, 0xec, 0xed, 0x27, 0x0b, 0x79, 0x10, 0x4f, 0x87, 0xe8, 0x43, > > + 0x28, 0x94, 0x09, 0xca, 0x48, 0x63, 0x65, 0x61, 0x86, 0x83, 0x33, 0x30, > > + 0x02, 0x6d, 0xf4, 0xef, 0x3c, 0x1a, 0x47, 0x8a, 0x25, 0x90, 0x31, 0x39, > > + 0x95, 0x1d, 0x6f, 0x11, 0x5c, 0x0c, 0x72, 0xe6, 0x1b, 0xe1, 0x60, 0x45, > > + 0x79, 0x89, 0x39, 0x48, 0x31, 0x4c, 0xc4, 0xd1, 0x08, 0x12, 0xf3, 0x5f, > > + 0x84, 0x8c, 0x86, 0xba, 0xe5, 0xf1, 0x24, 0x61, 0x2f, 0xef, 0x17, 0x16, > > + 0x4a, 0x29, 0xc0, 0xc6, 0x38, 0x47, 0x3a, 0x11, 0xc5, 0x7d, 0x62, 0x85, > > + 0x9b, 0x18, 0x92, 0x4c, 0x12, 0x92, 0x9c, 0x0b, > > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ > > +}; > > + > > +static void __init sha3_check_digest(const u8 *digest, const u8 *sample_digest, > > + int digest_len) > > +{ > > + if (memcmp(digest, sample_digest, digest_len) != 0) { > > + pr_err("SHAKE256(200) failed\n"); > > + for (int i = 0; i < digest_len;) { > > + int part = min(digest_len - i, 32); > > + > > + pr_err("%*phN\n", part, digest + i); > > + i += part; > > + } > > + } > > +} > > If a test is included at all here, it should be simpler, e.g. just > compute the SHA3-256 of some short hardcoded message. That will be > sufficient to test the implementation of the Keccak permutation. The > real tests will be in the KUnit suite, as discussed previously. No. Please stick with the one I have. It exercises the extended features used by ML-DSA that will be used for PQ module signing. David
On Sun, Sep 21, 2025 at 10:18:36PM +0100, David Howells wrote: > Eric Biggers <ebiggers@kernel.org> wrote: > > > > +/* update the state with given number of rounds */ > > > + > > > +static SHA3_INLINE void keccakf_round(u64 st[25]) > > > > The above comment doesn't match the code. keccakf_round() does only one > > round. > > This is exactly as in crypto/sha3_generic.c. You may want to fix that also. First, as I've mentioned, the SHA-3 crypto_shash algorithms will eventually need to be reimplemented on top of the library. We shouldn't have two competing SHA-3 implementations in the kernel. So sha3_generic.c will get replaced soon anyway. Second, this patch already makes changes to the SHA-3 code and doesn't simply copy it. Cleaning up some additional small things like incorrect comments would make sense, similar to how you've also cleaned up the endianness handling. If you'd like for it to instead be a simple copy followed by a separate cleanup patch, that could be okay too, but the submission would need to be organized that way. > > Would you mind putting all the kerneldoc comments for the public API in > > the .h file, similar to sha1.h and sha2.h? Then they'll all be in a > > consistent place, and they won't have to be moved around each time we > > change functions to inline functions or vice versa. > > Yes. I know include/crypto/ does it, but that really makes the header files > suck as the doc-to-code ratio is too heavily in the doc's favour. > > Actually, this should be done properly and I'll add an API doc to > Documention/crypto/. These are just functions. The first priority should be kerneldoc, as that's where most people will look. Documention/crypto/ maybe could contain a high-level overview of the various hash function APIs (not just SHA-3), but it should not be duplicative of the kerneldoc and it doesn't eliminate the need to write high-quality kerneldoc. > > First, this patch's proposed API is error-prone due to the weak typing > > that allows mixing steps of different algorithms together. For example, > > users could initialize a sha3_ctx with sha3_256_init() and then squeeze > > an arbitrary amount from it, incorrectly treating it as a XOF. It would > > be worth considering separating the APIs for the different algorithms > > that are part of SHA-3, similar to what I did with SHA-224 and SHA-256. > > (They would of course still share code internally, just like SHA-2.) > > I disagree. You're adding excessive complexity. I would be more inclined to > agree if the thing might crash because you used the wrong thing. That said, > sha3_final() uses the digestsize set by sha3_whatever_init(), which could > cause a problem, so I think it's better on balance to just add an extra > parameter to sha3_final() to say how much digest you want and ditch > ctx->digest_size. A cryptographic flaw can be as bad or worse than a crash. We need to design APIs that are easy to use correctly and hard to use incorrectly. > > Second, the support for update() + squeeze() + update() + squeeze() > > seems to be trying to achieve something that is not defined in the SHA-3 > > spec. Could you elaborate on what it is meant to be doing, and why it's > > here? According to the spec, the XOFs SHAKE128 and SHAKE256 actually > > just take a single message as their input. > > > > One might think the above sequence would compute SHAKE*() on the first > > message as well as SHAKE*() of the two messages concatenated together. > > But that's not what you've made it do, as you've made it apply padding > > after *both* messages. So, then one might think that it's meant to be a > > XOF on the sequence of messages, built on top of SHAKE*(). But it's not > > that either, since the way that you've proposed to format the sequence > > of messages into a longer message isn't injective. So, I can't figure > > out why you're supporting this usage and what it is meant to be doing. > > I can't speak to that except to say that ML-DSA does exactly this as far as I > can tell. Citation needed. > > Shouldn't the term "digest" be avoided when talking about the output > > from a XOF, to avoid confusion with traditional hash functions? > > No idea. There's not any real programmatic difference except for the padding > byte. I can change it to "output" if it makes you happy. How about reviewing the specs and seeing what terms are used? It's not about what makes me happy, but rather about using standard terminology. > > If a test is included at all here, it should be simpler, e.g. just > > compute the SHA3-256 of some short hardcoded message. That will be > > sufficient to test the implementation of the Keccak permutation. The > > real tests will be in the KUnit suite, as discussed previously. > > No. Please stick with the one I have. It exercises the extended features > used by ML-DSA that will be used for PQ module signing. That should go in the KUnit test suite. - Eric
On Fri, Sep 19, 2025 at 05:31:59PM +0100, David Howells wrote: > Add SHA3, providing SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128 and > SHAKE256 to lib/crypto. > > The state array handling is simplified from what's in crypto/sha3_generic.c > by keeping the state array (a u64[25]) in LE form and byteswapping all the > entries before and after applying the keccak function on a BE system. This > means no byteswapping is required when XOR'ing data into the state array or > when extracting the digest. Further, this is a no-op on LE systems. > > Also: > > - Perform a multistage shake256 hash check in the module initialisation. > > - Add kunit tests for each algorithm based on the gen-hash-testvecs. > > - The conflicting static s390x crypto function names are renamed to have > an s390_ prefix. > > - gen-hash-testvecs.py had to be modified to be able to generate SHAKE > hashes because Python's hashlib requires the output digest size > supplying for those two algorithms as they produce arbitrary length > digests. > > Notes: > > (1) I've left hooks in sha3.c for asm-optimised variants, but as I don't > entirely know what those might look like, not having implemented any, > the hooks' usability is uncertain. > > (2) The SHAKE algorithms will be required for ML-DSA. > > Signed-off-by: David Howells <dhowells@redhat.com> > cc: Eric Biggers <ebiggers@kernel.org> > cc: Jason A. Donenfeld <Jason@zx2c4.com> > cc: Ard Biesheuvel <ardb@kernel.org> > cc: Harald Freudenberger <freude@linux.ibm.com> > cc: Holger Dengler <dengler@linux.ibm.com> > cc: Herbert Xu <herbert@gondor.apana.org.au> > cc: Stephan Mueller <smueller@chronox.de> > cc: linux-crypto@vger.kernel.org > cc: linux-s390@vger.kernel.org > --- > Changes > ======= > v2) > - Simplify the endianness handling. > > - Rename sha3_final() to sha3_squeeze() and don't clear the context at the > end as it's permitted to continue calling sha3_final() to extract > continuations of the digest (needed by ML-DSA). > > - Don't reapply the end marker to the hash state in continuation > sha3_squeeze() unless sha3_update() gets called again (needed by > ML-DSA). > > - Give sha3_squeeze() the amount of digest to produce as a parameter > rather than using ctx->digest_size and don't return the amount digested. > > - Reimplement sha3_final() as a wrapper around sha3_squeeze() that > extracts ctx->digest_size amount of digest and then zeroes out the > context. The latter is necessary to avoid upsetting > hash-test-template.h. > > - Provide a sha3_reinit() function to clear the state, but to leave the > parameters that indicate the hash properties unaffected, allowing for > reuse. > > - Provide a sha3_set_digestsize() function to change the size of the > digest to be extracted by sha3_final(). sha3_squeeze() takes a > parameter for this instead. > > - Don't pass the digest size as a parameter to shake128/256_init() but > rather default to 128/256 bits as per the function name. > > - Provide a sha3_clear() function to zero out the context. > > arch/s390/crypto/sha3_256_s390.c | 26 - > include/crypto/sha3.h | 160 +++++++- > lib/crypto/Kconfig | 7 > lib/crypto/Makefile | 6 > lib/crypto/sha3.c | 597 ++++++++++++++++++++++++++++++ > lib/crypto/tests/Kconfig | 12 > lib/crypto/tests/Makefile | 7 > lib/crypto/tests/sha3_224_kunit.c | 32 + > lib/crypto/tests/sha3_224_testvecs.h | 231 +++++++++++ > lib/crypto/tests/sha3_256_kunit.c | 32 + > lib/crypto/tests/sha3_256_testvecs.h | 231 +++++++++++ > lib/crypto/tests/sha3_384_kunit.c | 32 + > lib/crypto/tests/sha3_384_testvecs.h | 281 ++++++++++++++ > lib/crypto/tests/sha3_512_kunit.c | 32 + > lib/crypto/tests/sha3_512_testvecs.h | 331 ++++++++++++++++ > lib/crypto/tests/sha3_shake128_kunit.c | 37 + > lib/crypto/tests/sha3_shake128_testvecs.h | 181 +++++++++ > lib/crypto/tests/sha3_shake256_kunit.c | 37 + > lib/crypto/tests/sha3_shake256_testvecs.h | 231 +++++++++++ > scripts/crypto/gen-hash-testvecs.py | 8 > 20 files changed, 2495 insertions(+), 16 deletions(-) Thanks for working on this! Some preliminary comments (it will take a few days for me to find time to fully review this): This should be based on libcrypto-next. And as with any kernel patch, it should include a base-commit so that people know where it applies to. This should be split into three patches: (1) the arch/s390/ changes, (2) adding the library functions themselves, and (3) adding the tests. We'll also need to integrate the existing arch-optimized SHA-3 code, and reimplement the SHA-3 crypto_shash algorithms on top of the library. Let me know whether you're planning to do that to. If not, I can do it. In kerneldoc comments, please make it clear that lengths are measured in bytes, and that the functions can be called in any context. The testing situation looks odd. This patch adds six KUnit test suites: one for each of the SHA-3 algorithms. But they only include the hash-test-template.h test cases, and they don't test the unique behavior of SHAKE. The KUnit tests need to fully test the library. I see you also have a test in sha3_mod_init(), which doesn't make sense. The tests should be in the KUnit test suite(s). If you intended for the sha3_mod_init() test to be a FIPS pre-operational self-test, then (1) it would first need to be confirmed with the people doing FIPS certifications that a FIPS pre-operational self-test is actually necessary here, (2) it would need to be fixed to actually fulfill the requirements for that type of test such as panicing the kernel on failure, and (3) it would need to come in its own patch with its own explanation. But, unless you are sure you actually need the FIPS test, just omit it out for now and focus on the real tests. I also think that splitting the SHA-3 tests into six KUnit test suites is awkward. I know I did something similar for SHA-2, but it made more sense for SHA-2 because (1) there are only four SHA-2 variants, (2) SHA-256 and SHA-512 don't share any code, and (3) there wasn't anything more to add on top of hash-test-template.h. In contrast, SHA-3 has six variants, which all share most of their code, and there will need to be SHA-3 specific tests (for the XOFs). I think what I'd recommend is creating a single sha3_kunit test suite. Make it instantiate hash-test-template.h once to test one of the algorithms, maybe SHA3-256. Then add test cases (that is, additional KUnit test cases in the same KUnit test suite) that cover the code specific to the other variants, including the XOFs. - Eric
Eric Biggers <ebiggers@kernel.org> wrote: > This should be based on libcrypto-next. This? https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git libcrypto-next > This should be split into three patches: (1) the arch/s390/ changes, (2) > adding the library functions themselves, and (3) adding the tests. Sure. But I'll wait a bit to see if there are any other comments first. > We'll also need to integrate the existing arch-optimized SHA-3 code, and > reimplement the SHA-3 crypto_shash algorithms on top of the library. > Let me know whether you're planning to do that to. If not, I can do it. I don't really have time at the moment. Nor am I particularly familiar with the optimised asm instructions for this on any arch. > In kerneldoc comments, please make it clear that lengths are measured in > bytes, Sure. The hash algos do love talking in terms of bits. Possibly because bytes aren't necessarily 8 bits in size on all arches? > and that the functions can be called in any context. "Context" as in? > The testing situation looks odd. This patch adds six KUnit test suites: > one for each of the SHA-3 algorithms. But they only include the > hash-test-template.h test cases, and they don't test the unique behavior > of SHAKE. The KUnit tests need to fully test the library. Yes, I'm aware of that. The hash-test-template template is rather rigid and not always correct in its assertions (for instance requiring the final function to have zeroed the context - I had to modify my API to work around the testsuite). > I see you also have a test in sha3_mod_init(), which doesn't make sense. > The tests should be in the KUnit test suite(s). If you intended for the > sha3_mod_init() test to be a FIPS pre-operational self-test, then (1) it > would first need to be confirmed with the people doing FIPS > certifications that a FIPS pre-operational self-test is actually > necessary here, (2) it would need to be fixed to actually fulfill the > requirements for that type of test such as panicing the kernel on > failure, and (3) it would need to come in its own patch with its own > explanation. But, unless you are sure you actually need the FIPS test, > just omit it out for now and focus on the real tests. I disagree. It should have at least a single self-test. If we fail to load any modules because the hash is broken on a particular CPU, it would be useful to have a note in dmesg. Loading kunit test modules becomes tricky in such a case. > I also think that splitting the SHA-3 tests into six KUnit test suites > is awkward. I know I did something similar for SHA-2, but it made more > sense for SHA-2 because (1) there are only four SHA-2 variants, (2) > SHA-256 and SHA-512 don't share any code, and (3) there wasn't anything > more to add on top of hash-test-template.h. In contrast, SHA-3 has six > variants, which all share most of their code, and there will need to be > SHA-3 specific tests (for the XOFs). Yes, but I believe you wanted me to use hash-test-template. The problem is that it hard-encodes by macroisation of the #include's file various parameters including the hash size. > I think what I'd recommend is creating a single sha3_kunit test suite. > Make it instantiate hash-test-template.h once to test one of the > algorithms, maybe SHA3-256. Then add test cases (that is, additional > KUnit test cases in the same KUnit test suite) that cover the code > specific to the other variants, including the XOFs. I could do that. It would at least exercise the common engine. Possibly all 5 different block sizes employed (128, 224, 256, 384 and 512) need to be so tested - but that only affects how much of the state array is modified directly sha3_update() and how much can be extracted from by sha3_squeeze(). The actual keccak mixing function doesn't care. Other than that, the only differences between the algorithms are the padding char and how much digest is extracted by default. On top of that, you can have a variety of different usage sequences: different sequences of updating and squeezing with different amounts of data added and extracted. I wonder if a small sampling is sufficient or whether we need some loopy thing that tries to exhaustively test a portion of the sample space. David
On Fri, Sep 19, 2025 at 08:48:00PM +0100, David Howells wrote: > Eric Biggers <ebiggers@kernel.org> wrote: > > > This should be based on libcrypto-next. > > This? > > https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git libcrypto-next Yes. > > and that the functions can be called in any context. > > "Context" as in? See the "Function context" section of Documentation/doc-guide/kernel-doc.rst > > The testing situation looks odd. This patch adds six KUnit test suites: > > one for each of the SHA-3 algorithms. But they only include the > > hash-test-template.h test cases, and they don't test the unique behavior > > of SHAKE. The KUnit tests need to fully test the library. > > Yes, I'm aware of that. The hash-test-template template is rather rigid hash-test-template.h is designed for traditional hash functions. If you'd like to extend it to support XOFs, that's one option. But I think just keeping the XOF testing in sha3_kunit.c would make sense for now. > and not always correct in its assertions (for instance requiring the > final function to have zeroed the context - I had to modify my API to > work around the testsuite). But that's the correct behavior. Callers may be hashing sensitize data, so *_final() zeroizes the context. The "multiple squeezes" use case should use different functions. > > I also think that splitting the SHA-3 tests into six KUnit test suites > > is awkward. I know I did something similar for SHA-2, but it made more > > sense for SHA-2 because (1) there are only four SHA-2 variants, (2) > > SHA-256 and SHA-512 don't share any code, and (3) there wasn't anything > > more to add on top of hash-test-template.h. In contrast, SHA-3 has six > > variants, which all share most of their code, and there will need to be > > SHA-3 specific tests (for the XOFs). > > Yes, but I believe you wanted me to use hash-test-template. The problem is > that it hard-encodes by macroisation of the #include's file various parameters > including the hash size. Did you miss my response at https://lore.kernel.org/linux-crypto/20250917192829.GA8743@quark/ ? - Eric
Eric Biggers <ebiggers@kernel.org> wrote: > > > and that the functions can be called in any context. > > > > "Context" as in? > > See the "Function context" section of > Documentation/doc-guide/kernel-doc.rst Btw, in include/crypto/sha1.h: /** * hmac_sha1_update() - Update an HMAC-SHA1 context with message data * @ctx: the HMAC context to update; must have been initialized * @data: the message data * @data_len: the data length in bytes * * This can be called any number of times. * * Context: Any context. */ static inline void hmac_sha1_update(struct hmac_sha1_ctx *ctx, const u8 *data, size_t data_len) { sha1_update(&ctx->sha_ctx, data, data_len); } for example, your specification of "Context: Any context." is probably not correct if FPU/Vector registers are used by optimised assembly as part of the function. See: void kernel_fpu_begin_mask(unsigned int kfpu_mask) { if (!irqs_disabled()) fpregs_lock(); WARN_ON_FPU(!irq_fpu_usable()); /* Toggle kernel_fpu_allowed to false: */ WARN_ON_FPU(!this_cpu_read(kernel_fpu_allowed)); this_cpu_write(kernel_fpu_allowed, false); if (!(current->flags & (PF_KTHREAD | PF_USER_WORKER)) && !test_thread_flag(TIF_NEED_FPU_LOAD)) { set_thread_flag(TIF_NEED_FPU_LOAD); save_fpregs_to_fpstate(x86_task_fpu(current)); } __cpu_invalidate_fpregs_state(); /* Put sane initial values into the control registers. */ if (likely(kfpu_mask & KFPU_MXCSR) && boot_cpu_has(X86_FEATURE_XMM)) ldmxcsr(MXCSR_DEFAULT); if (unlikely(kfpu_mask & KFPU_387) && boot_cpu_has(X86_FEATURE_FPU)) asm volatile ("fninit"); } If you try and access the function in IRQ mode, for example, you'll get a warning, and if IRQs are not disabled, it will disable BH/preemption. You also can't use it from inside something else that uses FPU registers. I suggest something like: * Context: Arch-dependent: May use the FPU/Vector unit registers. David.
On Tue, Sep 23, 2025 at 06:36:21PM +0100, David Howells wrote: > Eric Biggers <ebiggers@kernel.org> wrote: > > > > > and that the functions can be called in any context. > > > > > > "Context" as in? > > > > See the "Function context" section of > > Documentation/doc-guide/kernel-doc.rst > > Btw, in include/crypto/sha1.h: > > /** > * hmac_sha1_update() - Update an HMAC-SHA1 context with message data > * @ctx: the HMAC context to update; must have been initialized > * @data: the message data > * @data_len: the data length in bytes > * > * This can be called any number of times. > * > * Context: Any context. > */ > static inline void hmac_sha1_update(struct hmac_sha1_ctx *ctx, > const u8 *data, size_t data_len) > { > sha1_update(&ctx->sha_ctx, data, data_len); > } > > for example, your specification of "Context: Any context." is probably not > correct if FPU/Vector registers are used by optimised assembly as part of the > function. See: > > void kernel_fpu_begin_mask(unsigned int kfpu_mask) > { > if (!irqs_disabled()) > fpregs_lock(); > > WARN_ON_FPU(!irq_fpu_usable()); > > /* Toggle kernel_fpu_allowed to false: */ > WARN_ON_FPU(!this_cpu_read(kernel_fpu_allowed)); > this_cpu_write(kernel_fpu_allowed, false); > > if (!(current->flags & (PF_KTHREAD | PF_USER_WORKER)) && > !test_thread_flag(TIF_NEED_FPU_LOAD)) { > set_thread_flag(TIF_NEED_FPU_LOAD); > save_fpregs_to_fpstate(x86_task_fpu(current)); > } > __cpu_invalidate_fpregs_state(); > > /* Put sane initial values into the control registers. */ > if (likely(kfpu_mask & KFPU_MXCSR) && boot_cpu_has(X86_FEATURE_XMM)) > ldmxcsr(MXCSR_DEFAULT); > > if (unlikely(kfpu_mask & KFPU_387) && boot_cpu_has(X86_FEATURE_FPU)) > asm volatile ("fninit"); > } > > If you try and access the function in IRQ mode, for example, you'll get a > warning, and if IRQs are not disabled, it will disable BH/preemption. > > You also can't use it from inside something else that uses FPU registers. > > I suggest something like: > > * Context: Arch-dependent: May use the FPU/Vector unit registers. Kernel-mode FPU is used only when irq_fpu_usable(). The tests verify that the functions do work in IRQ context. - Eric
Am Freitag, 19. September 2025, 21:48:00 Mitteleuropäische Sommerzeit schrieb David Howells: Hi David, > > I see you also have a test in sha3_mod_init(), which doesn't make sense. > > The tests should be in the KUnit test suite(s). If you intended for the > > sha3_mod_init() test to be a FIPS pre-operational self-test, then (1) it > > would first need to be confirmed with the people doing FIPS > > certifications that a FIPS pre-operational self-test is actually > > necessary here, (2) it would need to be fixed to actually fulfill the > > requirements for that type of test such as panicing the kernel on > > failure, and (3) it would need to come in its own patch with its own > > explanation. But, unless you are sure you actually need the FIPS test, > > just omit it out for now and focus on the real tests. > > I disagree. It should have at least a single self-test. If we fail to load > any modules because the hash is broken on a particular CPU, it would be > useful to have a note in dmesg. Loading kunit test modules becomes tricky > in such a case. Just for clarifications of the FIPS requirements: One test of any of the SHA3/SHAKE algorithms during startup is sufficient for *one* Keccak implementation. FIPS wants the actual Keccak sponge being tested, it does not care for the miniscule differences between the different SHA/SHAKE definitions. Yet, if we have multiple Keccak sponge implementations, then each needs its own self test. Ciao Stephan
On Fri, Sep 19, 2025 at 09:53:17PM +0200, Stephan Mueller wrote: > Am Freitag, 19. September 2025, 21:48:00 Mitteleuropäische Sommerzeit > schrieb David Howells: > > Hi David, > > > > I see you also have a test in sha3_mod_init(), which doesn't make > sense. > > > The tests should be in the KUnit test suite(s). If you intended for > the > > > sha3_mod_init() test to be a FIPS pre-operational self-test, then (1) > it > > > would first need to be confirmed with the people doing FIPS > > > certifications that a FIPS pre-operational self-test is actually > > > necessary here, (2) it would need to be fixed to actually fulfill the > > > requirements for that type of test such as panicing the kernel on > > > failure, and (3) it would need to come in its own patch with its own > > > explanation. But, unless you are sure you actually need the FIPS test, > > > just omit it out for now and focus on the real tests. > > > > I disagree. It should have at least a single self-test. If we fail to > load > > any modules because the hash is broken on a particular CPU, it would be > > useful to have a note in dmesg. Loading kunit test modules becomes > tricky > > in such a case. Well, testing is supposed to be done before the kernel is released, not on every end user's computer. If you insist, at least keep it lightweight and make sure it doesn't detract from the real tests. > Just for clarifications of the FIPS requirements: One test of any of the > SHA3/SHAKE algorithms during startup is sufficient for *one* Keccak > implementation. FIPS wants the actual Keccak sponge being tested, it does > not care for the miniscule differences between the different SHA/SHAKE > definitions. Yes. But I'm still a bit puzzled why there suddenly seems to be interest in a FIPS pre-operational self-test for SHA-3 specifically. lib/ has had SHA-1 for two decades without a FIPS pre-operational self-test. If someone actually needs this, surely they would also need it, and have already needed it, for other algorithms? > Yet, if we have multiple Keccak sponge implementations, then each needs its > own self test. While lib/crypto/ often has multiple implementations of the algorithms, only one implementation is used on a given system. - Eric
Am Freitag, 19. September 2025, 22:47:49 Mitteleuropäische Sommerzeit schrieb Eric Biggers: Hi Eric, > Yes. But I'm still a bit puzzled why there suddenly seems to be > interest in a FIPS pre-operational self-test for SHA-3 specifically. > lib/ has had SHA-1 for two decades without a FIPS pre-operational > self-test. If someone actually needs this, surely they would also need > it, and have already needed it, for other algorithms? I just answered on the FIPS requirements as I interpreted your question in this regard. I am not saying it needs to be added here. I am currently a bit confused between crypto vs lib/crypto with its FIPS vs non-FIPS support. That, perhaps, contributed to my answer. Ciao Stephan
© 2016 - 2025 Red Hat, Inc.