[PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256

David Howells posted 1 patch 1 week, 6 days ago
There is a newer version of this series
include/crypto/sha3.h                     |  104 ++++++
lib/crypto/Kconfig                        |    7
lib/crypto/Makefile                       |    6
lib/crypto/sha3.c                         |  508 ++++++++++++++++++++++++++++++
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    |   42 ++
lib/crypto/tests/sha3_shake128_testvecs.h |  181 ++++++++++
lib/crypto/tests/sha3_shake256_kunit.c    |   42 ++
lib/crypto/tests/sha3_shake256_testvecs.h |  231 +++++++++++++
scripts/crypto/gen-hash-testvecs.py       |    8
19 files changed, 2347 insertions(+), 3 deletions(-)
[PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256
Posted by David Howells 1 week, 6 days ago
Add SHA3, providing SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128 and
SHAKE256 to lib/crypto.  Also add kunit tests for each of these.

gen-hash-testvecs.py is also 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: Herbert Xu <herbert@gondor.apana.org.au>
cc: Stephan Mueller <smueller@chronox.de>
cc: linux-crypto@vger.kernel.org
---
 include/crypto/sha3.h                     |  104 ++++++
 lib/crypto/Kconfig                        |    7 
 lib/crypto/Makefile                       |    6 
 lib/crypto/sha3.c                         |  508 ++++++++++++++++++++++++++++++
 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    |   42 ++
 lib/crypto/tests/sha3_shake128_testvecs.h |  181 ++++++++++
 lib/crypto/tests/sha3_shake256_kunit.c    |   42 ++
 lib/crypto/tests/sha3_shake256_testvecs.h |  231 +++++++++++++
 scripts/crypto/gen-hash-testvecs.py       |    8 
 19 files changed, 2347 insertions(+), 3 deletions(-)

diff --git a/include/crypto/sha3.h b/include/crypto/sha3.h
index 41e1b83a6d91..8693261e19dc 100644
--- a/include/crypto/sha3.h
+++ b/include/crypto/sha3.h
@@ -23,6 +23,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 +39,100 @@ struct sha3_state {
 	u64		st[SHA3_STATE_SIZE / 8];
 };
 
+struct sha3_ctx {
+	struct sha3_state	state;
+	__le64			buf[SHA3_224_BLOCK_SIZE / 8];
+	unsigned short		block_size;
+	unsigned short		digest_size;
+	unsigned short		partial;
+	u8			padding;
+};
+
 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
+ * @digest_size: The size of the digest desired
+ */
+static inline void shake128_init(struct sha3_ctx *ctx, unsigned int digest_size)
+{
+	sha3_init(ctx);
+	ctx->block_size  = SHAKE128_BLOCK_SIZE;
+	ctx->digest_size = digest_size;
+	ctx->padding	 = 0x1f;
+}
+
+/**
+ * shake256_init() - Initialize a SHAKE256 context for a new message
+ * @ctx: the context to initialize
+ * @digest_size: The size of the digest desired
+ */
+static inline void shake256_init(struct sha3_ctx *ctx, unsigned int digest_size)
+{
+	sha3_init(ctx);
+	ctx->block_size  = SHA3_256_BLOCK_SIZE;
+	ctx->digest_size = digest_size;
+	ctx->padding	 = 0x1f;
+}
+
+void sha3_update(struct sha3_ctx *ctx, const u8 *data, unsigned int len);
+int sha3_final(struct sha3_ctx *ctx, u8 *out);
+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]);
+int shake128(const u8 *in, size_t in_len, u8 *out, size_t out_len);
+int shake256(const u8 *in, size_t in_len, u8 *out, size_t out_len);
+
+#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..459ef9855468
--- /dev/null
+++ b/lib/crypto/sha3.c
@@ -0,0 +1,508 @@
+// 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_debug("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_debug("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];
+}
+
+/*
+ * Perform the mixing step.
+ */
+static void sha3_keccakf_generic(u64 st[25])
+{
+	int round;
+
+	for (round = 0; round < KECCAK_ROUNDS; round++) {
+		keccakf_round(st);
+		/* Iota */
+		st[0] ^= keccakf_rndc[round];
+	}
+}
+
+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_le64(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 len)
+{
+	unsigned int partial = ctx->partial;
+	u8 *buf = (u8 *)ctx->state.st;
+
+#ifdef __LITTLE_ENDIAN
+	buf += partial;
+	for (int i = 0; i < len; i++)
+		*buf++ ^= *data++;
+#else
+	for (int i = 0; i < len; i++) {
+		unsigned int woff = (partial + i) & ~7;
+		unsigned int boff = (partial + i) & 7;
+
+		buf[woff | 7 - boff] ^= *data++;
+	}
+#endif
+	ctx->partial += len;
+}
+
+/**
+ * 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 adds the message data to the digest.
+ */
+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, 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, len);
+}
+EXPORT_SYMBOL_GPL(sha3_update);
+
+/**
+ * sha3_final() - Finish computing a SHA3 message digest of any type
+ * @ctx: the context to finalize; must have been initialized
+ * @out: (output) the resulting message digest
+ *
+ * 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.  Before returning, the context @ctx is
+ * cleared so that the caller does not need to do it.
+ */
+int sha3_final(struct sha3_ctx *ctx, u8 *out)
+{
+	struct sha3_state *state = &ctx->state;
+	unsigned int digest_size = ctx->digest_size;
+	unsigned int bsize = ctx->block_size;
+	u8 end_marker = 0x80;
+
+	sha3_absorb_xorle(ctx, &ctx->padding, 1);
+	ctx->partial = bsize - 1;
+	sha3_absorb_xorle(ctx, &end_marker, 1);
+	sha3_keccakf(ctx->state.st);
+
+#ifdef __LITTLE_ENDIAN
+	for (;;) {
+		unsigned int part = umin(digest_size, bsize);
+
+		memcpy(out, state->st, part);
+		digest_size -= part;
+		if (!digest_size)
+			goto done;
+		out += part;
+		sha3_keccakf(ctx->state.st);
+	}
+#else
+	__le64 *digest = (__le64 *)out, *s;
+
+	while (digest_size >= bsize) {
+		for (int i = 0; i < bsize / 8; i++)
+			put_unaligned_le64(state->st[i], digest++);
+		digest_size -= bsize;
+		if (!digest_size)
+			goto done;
+		sha3_keccakf(ctx->state.st);
+	}
+
+	s = state->st;
+	for (; digest_size >= 8; digest_size -= 8)
+		put_unaligned_le64(*s++, digest++);
+
+	u8 *sc = (u8 *)s;
+	u8 *dc = (u8 *)digest;
+
+	for (; digest_size >= 1; digest_size -= 1)
+		*dc++ = *sc++;
+#endif
+done:
+	digest_size = ctx->digest_size;
+	memzero_explicit(ctx, sizeof(*ctx));
+	return digest_size;
+}
+EXPORT_SYMBOL_GPL(sha3_final);
+
+/**
+ * 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)
+ */
+int shake128(const u8 *in, size_t in_len, u8 *out, size_t out_len)
+{
+	struct sha3_ctx ctx;
+
+	shake128_init(&ctx, out_len);
+	sha3_update(&ctx, in, in_len);
+	return sha3_final(&ctx, out);
+}
+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)
+ */
+int shake256(const u8 *in, size_t in_len, u8 *out, size_t out_len)
+{
+	struct sha3_ctx ctx;
+
+	shake256_init(&ctx, out_len);
+	sha3_update(&ctx, in, in_len);
+	return sha3_final(&ctx, out);
+}
+EXPORT_SYMBOL(shake256);
+
+/*
+ * Do a quick test using SHAKE256 and a 200 byte digest.
+ */
+static const u8 sha3_sample[] __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_sample_shake256_200[] __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 int __init sha3_mod_init(void)
+{
+	u8 digest[8 + 200 + 8] = {};
+	int n;
+
+#ifdef sha3_mod_init_arch
+	sha3_mod_init_arch();
+#endif
+
+	n = shake256(sha3_sample, sizeof(sha3_sample) - 1, digest + 8, 200);
+
+	if (n != 200 ||
+	    sizeof(digest) != sizeof(sha3_sample_shake256_200) ||
+	    memcmp(digest, sha3_sample_shake256_200, sizeof(digest)) != 0) {
+		pr_err("SHAKE256(200) failed: len=%u\n", n);
+		for (int i = 0; i < sizeof(digest);) {
+			int part = min(sizeof(digest) - i, 32);
+
+			pr_err("%*phN\n", part, digest + i);
+			i += part;
+		}
+	}
+	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..9277327cba61
--- /dev/null
+++ b/lib/crypto/tests/sha3_shake128_kunit.c
@@ -0,0 +1,42 @@
+// 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 int test_shake128_128(const u8 *in, size_t in_len, u8 *out)
+{
+	return shake128(in, in_len, out, SHAKE128_DIGEST_SIZE);
+}
+
+static void test_shake128_init_128(struct sha3_ctx *ctx)
+{
+	return shake128_init(ctx, SHAKE128_DIGEST_SIZE);
+}
+
+#define HASH		test_shake128_128
+#define HASH_CTX	sha3_ctx
+#define HASH_SIZE	SHAKE128_DIGEST_SIZE
+#define HASH_INIT	test_shake128_init_128
+#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..8fe495811f97
--- /dev/null
+++ b/lib/crypto/tests/sha3_shake256_kunit.c
@@ -0,0 +1,42 @@
+// 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 int test_shake256_256(const u8 *in, size_t in_len, u8 *out)
+{
+	return shake256(in, in_len, out, SHAKE256_DIGEST_SIZE);
+}
+
+static void test_shake256_init_256(struct sha3_ctx *ctx)
+{
+	return shake256_init(ctx, SHAKE256_DIGEST_SIZE);
+}
+
+#define HASH		test_shake256_256
+#define HASH_CTX	sha3_ctx
+#define HASH_SIZE	SHAKE256_DIGEST_SIZE
+#define HASH_INIT	test_shake256_init_256
+#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)
Re: [PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256
Posted by kernel test robot 1 week, 5 days ago
Hi David,

kernel test robot noticed the following build warnings:

[auto build test WARNING on ebiggers/libcrypto-fixes]
[also build test WARNING on herbert-cryptodev-2.6/master herbert-crypto-2.6/master linus/master v6.17-rc6 next-20250918]
[cannot apply to ebiggers/libcrypto-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/David-Howells/lib-crypto-Add-SHA3-224-SHA3-256-SHA3-384-SHA-512-SHAKE128-SHAKE256/20250919-061024
base:   https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git libcrypto-fixes
patch link:    https://lore.kernel.org/r/3605112.1758233248%40warthog.procyon.org.uk
patch subject: [PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256
config: arc-randconfig-r112-20250919 (https://download.01.org/0day-ci/archive/20250919/202509191938.PrHY82Kd-lkp@intel.com/config)
compiler: arc-linux-gcc (GCC) 10.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250919/202509191938.PrHY82Kd-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202509191938.PrHY82Kd-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> lib/crypto/sha3.c:317:11: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le64 [usertype] *s @@     got unsigned long long * @@
   lib/crypto/sha3.c:317:11: sparse:     expected restricted __le64 [usertype] *s
   lib/crypto/sha3.c:317:11: sparse:     got unsigned long long *
>> lib/crypto/sha3.c:319:36: sparse: sparse: incorrect type in argument 1 (different base types) @@     expected unsigned long long [usertype] val @@     got restricted __le64 [usertype] @@
   lib/crypto/sha3.c:319:36: sparse:     expected unsigned long long [usertype] val
   lib/crypto/sha3.c:319:36: sparse:     got restricted __le64 [usertype]

vim +317 lib/crypto/sha3.c

   271	
   272	/**
   273	 * sha3_final() - Finish computing a SHA3 message digest of any type
   274	 * @ctx: the context to finalize; must have been initialized
   275	 * @out: (output) the resulting message digest
   276	 *
   277	 * Finish the computation of a SHA3 message digest of any type and perform the
   278	 * "Keccak sponge squeezing" phase.  The digest is written to @out buffer and
   279	 * the size of the digest is returned.  Before returning, the context @ctx is
   280	 * cleared so that the caller does not need to do it.
   281	 */
   282	int sha3_final(struct sha3_ctx *ctx, u8 *out)
   283	{
   284		struct sha3_state *state = &ctx->state;
   285		unsigned int digest_size = ctx->digest_size;
   286		unsigned int bsize = ctx->block_size;
   287		u8 end_marker = 0x80;
   288	
   289		sha3_absorb_xorle(ctx, &ctx->padding, 1);
   290		ctx->partial = bsize - 1;
   291		sha3_absorb_xorle(ctx, &end_marker, 1);
   292		sha3_keccakf(ctx->state.st);
   293	
   294	#ifdef __LITTLE_ENDIAN
   295		for (;;) {
   296			unsigned int part = umin(digest_size, bsize);
   297	
   298			memcpy(out, state->st, part);
   299			digest_size -= part;
   300			if (!digest_size)
   301				goto done;
   302			out += part;
   303			sha3_keccakf(ctx->state.st);
   304		}
   305	#else
   306		__le64 *digest = (__le64 *)out, *s;
   307	
   308		while (digest_size >= bsize) {
   309			for (int i = 0; i < bsize / 8; i++)
   310				put_unaligned_le64(state->st[i], digest++);
   311			digest_size -= bsize;
   312			if (!digest_size)
   313				goto done;
   314			sha3_keccakf(ctx->state.st);
   315		}
   316	
 > 317		s = state->st;
   318		for (; digest_size >= 8; digest_size -= 8)
 > 319			put_unaligned_le64(*s++, digest++);
   320	
   321		u8 *sc = (u8 *)s;
   322		u8 *dc = (u8 *)digest;
   323	
   324		for (; digest_size >= 1; digest_size -= 1)
   325			*dc++ = *sc++;
   326	#endif
   327	done:
   328		digest_size = ctx->digest_size;
   329		memzero_explicit(ctx, sizeof(*ctx));
   330		return digest_size;
   331	}
   332	EXPORT_SYMBOL_GPL(sha3_final);
   333	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256
Posted by kernel test robot 1 week, 5 days ago
Hi David,

kernel test robot noticed the following build errors:

[auto build test ERROR on ebiggers/libcrypto-fixes]
[also build test ERROR on herbert-cryptodev-2.6/master herbert-crypto-2.6/master linus/master v6.17-rc6 next-20250918]
[cannot apply to ebiggers/libcrypto-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/David-Howells/lib-crypto-Add-SHA3-224-SHA3-256-SHA3-384-SHA-512-SHAKE128-SHAKE256/20250919-061024
base:   https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git libcrypto-fixes
patch link:    https://lore.kernel.org/r/3605112.1758233248%40warthog.procyon.org.uk
patch subject: [PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256
config: s390-randconfig-001-20250919 (https://download.01.org/0day-ci/archive/20250919/202509191807.9daDknje-lkp@intel.com/config)
compiler: s390-linux-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250919/202509191807.9daDknje-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202509191807.9daDknje-lkp@intel.com/

All errors (new ones prefixed by >>):

>> arch/s390/crypto/sha3_256_s390.c:22:12: error: conflicting types for 'sha3_256_init'
    static int sha3_256_init(struct shash_desc *desc)
               ^~~~~~~~~~~~~
   In file included from arch/s390/crypto/sha3_256_s390.c:13:
   include/crypto/sha3.h:71:20: note: previous definition of 'sha3_256_init' was here
    static inline void sha3_256_init(struct sha3_ctx *ctx)
                       ^~~~~~~~~~~~~
>> arch/s390/crypto/sha3_256_s390.c:99:12: error: conflicting types for 'sha3_224_init'
    static int sha3_224_init(struct shash_desc *desc)
               ^~~~~~~~~~~~~
   In file included from arch/s390/crypto/sha3_256_s390.c:13:
   include/crypto/sha3.h:59:20: note: previous definition of 'sha3_224_init' was here
    static inline void sha3_224_init(struct sha3_ctx *ctx)
                       ^~~~~~~~~~~~~


vim +/sha3_256_init +22 arch/s390/crypto/sha3_256_s390.c

3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   21  
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14  @22  static int sha3_256_init(struct shash_desc *desc)
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   23  {
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   24  	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   25  
6f90ba7065515d Herbert Xu        2025-04-18   26  	sctx->first_message_part = test_facility(86);
6f90ba7065515d Herbert Xu        2025-04-18   27  	if (!sctx->first_message_part)
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   28  		memset(sctx->state, 0, sizeof(sctx->state));
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   29  	sctx->count = 0;
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   30  	sctx->func = CPACF_KIMD_SHA3_256;
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   31  
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   32  	return 0;
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   33  }
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   34  
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   35  static int sha3_256_export(struct shash_desc *desc, void *out)
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   36  {
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   37  	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
73c2437109c3ea Herbert Xu        2025-05-23   38  	union {
73c2437109c3ea Herbert Xu        2025-05-23   39  		u8 *u8;
73c2437109c3ea Herbert Xu        2025-05-23   40  		u64 *u64;
73c2437109c3ea Herbert Xu        2025-05-23   41  	} p = { .u8 = out };
73c2437109c3ea Herbert Xu        2025-05-23   42  	int i;
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   43  
6f90ba7065515d Herbert Xu        2025-04-18   44  	if (sctx->first_message_part) {
73c2437109c3ea Herbert Xu        2025-05-23   45  		memset(out, 0, SHA3_STATE_SIZE);
73c2437109c3ea Herbert Xu        2025-05-23   46  		return 0;
6f90ba7065515d Herbert Xu        2025-04-18   47  	}
73c2437109c3ea Herbert Xu        2025-05-23   48  	for (i = 0; i < SHA3_STATE_SIZE / 8; i++)
73c2437109c3ea Herbert Xu        2025-05-23   49  		put_unaligned(le64_to_cpu(sctx->sha3.state[i]), p.u64++);
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   50  	return 0;
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   51  }
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   52  
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   53  static int sha3_256_import(struct shash_desc *desc, const void *in)
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   54  {
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   55  	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
73c2437109c3ea Herbert Xu        2025-05-23   56  	union {
73c2437109c3ea Herbert Xu        2025-05-23   57  		const u8 *u8;
73c2437109c3ea Herbert Xu        2025-05-23   58  		const u64 *u64;
73c2437109c3ea Herbert Xu        2025-05-23   59  	} p = { .u8 = in };
73c2437109c3ea Herbert Xu        2025-05-23   60  	int i;
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   61  
73c2437109c3ea Herbert Xu        2025-05-23   62  	for (i = 0; i < SHA3_STATE_SIZE / 8; i++)
73c2437109c3ea Herbert Xu        2025-05-23   63  		sctx->sha3.state[i] = cpu_to_le64(get_unaligned(p.u64++));
6f90ba7065515d Herbert Xu        2025-04-18   64  	sctx->count = 0;
6f90ba7065515d Herbert Xu        2025-04-18   65  	sctx->first_message_part = 0;
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   66  	sctx->func = CPACF_KIMD_SHA3_256;
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   67  
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   68  	return 0;
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   69  }
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   70  
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   71  static int sha3_224_import(struct shash_desc *desc, const void *in)
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   72  {
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   73  	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   74  
6f90ba7065515d Herbert Xu        2025-04-18   75  	sha3_256_import(desc, in);
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   76  	sctx->func = CPACF_KIMD_SHA3_224;
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   77  	return 0;
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   78  }
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   79  
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   80  static struct shash_alg sha3_256_alg = {
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   81  	.digestsize	=	SHA3_256_DIGEST_SIZE,	   /* = 32 */
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   82  	.init		=	sha3_256_init,
6f90ba7065515d Herbert Xu        2025-04-18   83  	.update		=	s390_sha_update_blocks,
6f90ba7065515d Herbert Xu        2025-04-18   84  	.finup		=	s390_sha_finup,
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   85  	.export		=	sha3_256_export,
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   86  	.import		=	sha3_256_import,
6f90ba7065515d Herbert Xu        2025-04-18   87  	.descsize	=	S390_SHA_CTX_SIZE,
6f90ba7065515d Herbert Xu        2025-04-18   88  	.statesize	=	SHA3_STATE_SIZE,
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   89  	.base		=	{
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   90  		.cra_name	 =	"sha3-256",
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   91  		.cra_driver_name =	"sha3-256-s390",
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   92  		.cra_priority	 =	300,
6f90ba7065515d Herbert Xu        2025-04-18   93  		.cra_flags	 =	CRYPTO_AHASH_ALG_BLOCK_ONLY,
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   94  		.cra_blocksize	 =	SHA3_256_BLOCK_SIZE,
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   95  		.cra_module	 =	THIS_MODULE,
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   96  	}
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   97  };
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14   98  
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14  @99  static int sha3_224_init(struct shash_desc *desc)
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14  100  {
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14  101  	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14  102  
6f90ba7065515d Herbert Xu        2025-04-18  103  	sha3_256_init(desc);
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14  104  	sctx->func = CPACF_KIMD_SHA3_224;
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14  105  	return 0;
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14  106  }
3c2eb6b76cabb7 Joerg Schmidbauer 2019-08-14  107  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256
Posted by kernel test robot 1 week, 5 days ago
Hi David,

kernel test robot noticed the following build warnings:

[auto build test WARNING on ebiggers/libcrypto-fixes]
[also build test WARNING on herbert-cryptodev-2.6/master herbert-crypto-2.6/master linus/master v6.17-rc6 next-20250918]
[cannot apply to ebiggers/libcrypto-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/David-Howells/lib-crypto-Add-SHA3-224-SHA3-256-SHA3-384-SHA-512-SHAKE128-SHAKE256/20250919-061024
base:   https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git libcrypto-fixes
patch link:    https://lore.kernel.org/r/3605112.1758233248%40warthog.procyon.org.uk
patch subject: [PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256
config: arm-randconfig-001-20250919 (https://download.01.org/0day-ci/archive/20250919/202509191712.4MoL99fN-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 12.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250919/202509191712.4MoL99fN-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202509191712.4MoL99fN-lkp@intel.com/

All warnings (new ones prefixed by >>):

   lib/crypto/sha3.c: In function 'sha3_absorb_xorle':
>> lib/crypto/sha3.c:229:30: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
     229 |                 buf[woff | 7 - boff] ^= *data++;
         |                            ~~^~~~~~


vim +229 lib/crypto/sha3.c

   211	
   212	/*
   213	 * XOR in partial data that's insufficient to fill a whole block.
   214	 */
   215	static void sha3_absorb_xorle(struct sha3_ctx *ctx, const u8 *data, unsigned int len)
   216	{
   217		unsigned int partial = ctx->partial;
   218		u8 *buf = (u8 *)ctx->state.st;
   219	
   220	#ifdef __LITTLE_ENDIAN
   221		buf += partial;
   222		for (int i = 0; i < len; i++)
   223			*buf++ ^= *data++;
   224	#else
   225		for (int i = 0; i < len; i++) {
   226			unsigned int woff = (partial + i) & ~7;
   227			unsigned int boff = (partial + i) & 7;
   228	
 > 229			buf[woff | 7 - boff] ^= *data++;
   230		}
   231	#endif
   232		ctx->partial += len;
   233	}
   234	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256
Posted by Stephan Müller 1 week, 6 days ago
Am Freitag, 19. September 2025, 00:07:28 Mitteleuropäische Sommerzeit schrieb 
David Howells:

Hi David,

as you mentioned that this patch as a basis for ML-DSA then may I outline the 
following: the ML-DSA code requires a multi-staged squeeze operation. For 
example:

squeeze(state, 10 bytes);
squeeze(state, 10 bytes);

must be identical to

squeeze(state, 20 bytes);

With this in mind, may I highlight that potentially the following code does 
not support this notion:

> +/**
> + * sha3_final() - Finish computing a SHA3 message digest of any type
> + * @ctx: the context to finalize; must have been initialized
> + * @out: (output) the resulting message digest
> + *
> + * 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.  Before returning, the
> context @ctx is + * cleared so that the caller does not need to do it.
> + */
> +int sha3_final(struct sha3_ctx *ctx, u8 *out)
> +{
> +	struct sha3_state *state = &ctx->state;
> +	unsigned int digest_size = ctx->digest_size;
> +	unsigned int bsize = ctx->block_size;
> +	u8 end_marker = 0x80;
> +
> +	sha3_absorb_xorle(ctx, &ctx->padding, 1);
> +	ctx->partial = bsize - 1;
> +	sha3_absorb_xorle(ctx, &end_marker, 1);
> +	sha3_keccakf(ctx->state.st);

This logic above should only be invoked for the first squeeze operation.

May I suggest you consider the code at:

https://github.com/smuellerDD/leancrypto/blob/master/hash/src/sha3_c.c#L625

> +
> +#ifdef __LITTLE_ENDIAN
> +	for (;;) {
> +		unsigned int part = umin(digest_size, bsize);
> +
> +		memcpy(out, state->st, part);
> +		digest_size -= part;
> +		if (!digest_size)
> +			goto done;
> +		out += part;
> +		sha3_keccakf(ctx->state.st);
> +	}

This loop needs to honor a starting offset in case the previous call only 
requested a subset of the rate.

May I suggest to consider the code at:

https://github.com/smuellerDD/leancrypto/blob/master/hash/src/sha3_c.c#L643


> +#else
> +	__le64 *digest = (__le64 *)out, *s;
> +
> +	while (digest_size >= bsize) {
> +		for (int i = 0; i < bsize / 8; i++)
> +			put_unaligned_le64(state->st[i], digest++);
> +		digest_size -= bsize;
> +		if (!digest_size)
> +			goto done;
> +		sha3_keccakf(ctx->state.st);
> +	}
> +
> +	s = state->st;
> +	for (; digest_size >= 8; digest_size -= 8)
> +		put_unaligned_le64(*s++, digest++);
> +
> +	u8 *sc = (u8 *)s;
> +	u8 *dc = (u8 *)digest;
> +
> +	for (; digest_size >= 1; digest_size -= 1)
> +		*dc++ = *sc++;
> +#endif
> +done:
> +	digest_size = ctx->digest_size;
> +	memzero_explicit(ctx, sizeof(*ctx));

For a multi-stage squeeze, it is perhaps not helpful to zeroize the context 
here.

Ciao
Stephan
Re: [PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256
Posted by David Howells 1 week, 6 days ago
Stephan Müller <smueller@chronox.de> wrote:

> For a multi-stage squeeze, it is perhaps not helpful to zeroize the context 
> here.

Yeah - I've seen this now that I'm starting to trawl through your dilithium
code, so it will need adjusting.

David
Re: [PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256
Posted by Simo Sorce 1 week, 5 days ago
On Fri, 2025-09-19 at 07:17 +0100, David Howells wrote:
> Stephan Müller <smueller@chronox.de> wrote:
> 
> > For a multi-stage squeeze, it is perhaps not helpful to zeroize the context 
> > here.
> 
> Yeah - I've seen this now that I'm starting to trawl through your dilithium
> code, so it will need adjusting.


I strongly suggest creating a test vector where multiple absorb and
squeeze operations are done in intermixed order, and then use that test
vector in your Kunit tests to ensure changes to the code do not break
this fundamental property of the keccak sponge algorithm.

Simo.

-- 
Simo Sorce
Distinguished Engineer
RHEL Crypto Team
Red Hat, Inc
Re: [PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256
Posted by David Howells 1 week, 5 days ago
Simo Sorce <simo@redhat.com> wrote:

> I strongly suggest creating a test vector where multiple absorb and
> squeeze operations are done in intermixed order, and then use that test
> vector in your Kunit tests to ensure changes to the code do not break
> this fundamental property of the keccak sponge algorithm.

I'm putting such a beast in the module init function at least.

Annoyingly, Eric's hash-test-template.h makes some unwarranted assumptions
about the hashes it is testing - such as the final function zeroing out the
hash struct.

David
Re: [PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256
Posted by Stephan Müller 1 week, 5 days ago
Am Freitag, 19. September 2025, 17:34:36 Mitteleuropäische Sommerzeit schrieb 
David Howells:

Hi David,

> Simo Sorce <simo@redhat.com> wrote:
> > I strongly suggest creating a test vector where multiple absorb and
> > squeeze operations are done in intermixed order, and then use that test
> > vector in your Kunit tests to ensure changes to the code do not break
> > this fundamental property of the keccak sponge algorithm.
> 
> I'm putting such a beast in the module init function at least.
> 
> Annoyingly, Eric's hash-test-template.h makes some unwarranted assumptions
> about the hashes it is testing - such as the final function zeroing out the
> hash struct.

If it is of help, here is such test that I use:

https://github.com/smuellerDD/leancrypto/blob/master/hash/tests/
shake_squeeze_more_tester.c#L92

Ciao
Stephan