lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <3605112.1758233248@warthog.procyon.org.uk>
Date: Thu, 18 Sep 2025 23:07:28 +0100
From: David Howells <dhowells@...hat.com>
To: Eric Biggers <ebiggers@...nel.org>
cc: dhowells@...hat.com, "Jason A. Donenfeld" <Jason@...c4.com>,
    Ard Biesheuvel <ardb@...nel.org>,
    Herbert Xu <herbert@...dor.apana.org.au>,
    Stephan Mueller <smueller@...onox.de>, linux-crypto@...r.kernel.org,
    keyrings@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH] lib/crypto: Add SHA3-224, SHA3-256, SHA3-384, SHA-512, SHAKE128, SHAKE256

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@...hat.com>
cc: Eric Biggers <ebiggers@...nel.org>
cc: Jason A. Donenfeld <Jason@...c4.com>
cc: Ard Biesheuvel <ardb@...nel.org>
cc: Herbert Xu <herbert@...dor.apana.org.au>
cc: Stephan Mueller <smueller@...onox.de>
cc: linux-crypto@...r.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@...zik.org>
+ *               Ard Biesheuvel <ard.biesheuvel@...aro.org>
+ *		 David Howells <dhowells@...hat.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@...hat.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@...hat.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@...hat.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@...hat.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@...hat.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@...hat.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)


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ