All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Biggers <ebiggers@kernel.org>
To: linux-crypto@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel <ardb@kernel.org>,
	"Jason A . Donenfeld" <Jason@zx2c4.com>,
	Eric Biggers <ebiggers@kernel.org>
Subject: [PATCH v3 1/2] lib/crypto: sha512: Add KUnit tests for SHA-384 and SHA-512
Date: Mon, 30 Jun 2025 09:20:13 -0700	[thread overview]
Message-ID: <20250630162014.6463-2-ebiggers@kernel.org> (raw)
In-Reply-To: <20250630162014.6463-1-ebiggers@kernel.org>

Add KUnit tests for the SHA-384 and SHA-512 library functions, including
the corresponding HMAC support.

Testing strategy:
- Each SHA variant gets its own KUnit test suite, but a header is used
  to share most of the test code among the SHA variants.
- Test against vectors generated by the Python hashlib and hmac modules.
- Test incremental computation.
- Test with a guard page to catch buffer overruns even in assembly code.
- Test various overlap and alignment cases.
- Compute hashes in task, softirq, and hardirq context in parallel, to
  verify that the functions work as expected in all contexts and that
  fallback code paths are exercised.
- Test that the finalization functions zeroize their context.
- Include benchmarks, guarded by a separate Kconfig option.

Acked-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
 lib/crypto/Kconfig                    |   2 +
 lib/crypto/Makefile                   |   2 +
 lib/crypto/tests/Kconfig              |  16 +
 lib/crypto/tests/Makefile             |   4 +
 lib/crypto/tests/hash-test-template.h | 512 ++++++++++++++++++++
 lib/crypto/tests/sha384-testvecs.h    | 566 ++++++++++++++++++++++
 lib/crypto/tests/sha384_kunit.c       |  48 ++
 lib/crypto/tests/sha512-testvecs.h    | 662 ++++++++++++++++++++++++++
 lib/crypto/tests/sha512_kunit.c       |  48 ++
 scripts/crypto/gen-hash-testvecs.py   |  83 ++++
 10 files changed, 1943 insertions(+)
 create mode 100644 lib/crypto/tests/Kconfig
 create mode 100644 lib/crypto/tests/Makefile
 create mode 100644 lib/crypto/tests/hash-test-template.h
 create mode 100644 lib/crypto/tests/sha384-testvecs.h
 create mode 100644 lib/crypto/tests/sha384_kunit.c
 create mode 100644 lib/crypto/tests/sha512-testvecs.h
 create mode 100644 lib/crypto/tests/sha512_kunit.c
 create mode 100755 scripts/crypto/gen-hash-testvecs.py

diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig
index 3305c69085816..2580bc90c15e2 100644
--- a/lib/crypto/Kconfig
+++ b/lib/crypto/Kconfig
@@ -1,9 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0
 
 menu "Crypto library routines"
 
+source "lib/crypto/tests/Kconfig"
+
 config CRYPTO_LIB_UTILS
 	tristate
 
 config CRYPTO_LIB_AES
 	tristate
diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
index a887bf103bf05..d92a7ba2ef0a0 100644
--- a/lib/crypto/Makefile
+++ b/lib/crypto/Makefile
@@ -1,7 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0
 
+obj-y += tests/
+
 aflags-thumb2-$(CONFIG_THUMB2_KERNEL)  := -U__thumb2__ -D__thumb2__=1
 
 quiet_cmd_perlasm = PERLASM $@
       cmd_perlasm = $(PERL) $(<) > $(@)
 
diff --git a/lib/crypto/tests/Kconfig b/lib/crypto/tests/Kconfig
new file mode 100644
index 0000000000000..90be320c25bd2
--- /dev/null
+++ b/lib/crypto/tests/Kconfig
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config CRYPTO_LIB_SHA512_KUNIT_TEST
+	tristate "KUnit tests for SHA-384 and SHA-512" if !KUNIT_ALL_TESTS
+	depends on KUNIT
+	default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS
+	select CRYPTO_LIB_SHA512
+	help
+	  KUnit tests for the SHA-384 and SHA-512 cryptographic hash functions
+	  and their corresponding HMACs.
+
+config CRYPTO_LIB_BENCHMARK
+	bool "Include benchmarks in KUnit tests for cryptographic functions"
+	depends on CRYPTO_LIB_SHA512_KUNIT_TEST
+	help
+	  Include benchmarks in the KUnit tests for cryptographic functions.
diff --git a/lib/crypto/tests/Makefile b/lib/crypto/tests/Makefile
new file mode 100644
index 0000000000000..3925dcb6513d8
--- /dev/null
+++ b/lib/crypto/tests/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_CRYPTO_LIB_SHA512_KUNIT_TEST) += sha384_kunit.o
+obj-$(CONFIG_CRYPTO_LIB_SHA512_KUNIT_TEST) += sha512_kunit.o
diff --git a/lib/crypto/tests/hash-test-template.h b/lib/crypto/tests/hash-test-template.h
new file mode 100644
index 0000000000000..3d5b838aa572a
--- /dev/null
+++ b/lib/crypto/tests/hash-test-template.h
@@ -0,0 +1,512 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright 2025 Google LLC
+ */
+#include <kunit/test.h>
+#include <linux/hrtimer.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+
+/* test_buf is a guarded buffer, i.e. &test_buf[TEST_BUF_LEN] is not mapped. */
+#define TEST_BUF_LEN 16384
+static u8 *test_buf;
+
+static u8 *orig_test_buf;
+
+static u64 random_seed;
+
+/*
+ * This is a simple linear congruential generator.  It is used only for testing,
+ * which does not require cryptographically secure random numbers.  A hard-coded
+ * algorithm is used instead of <linux/prandom.h> so that it matches the
+ * algorithm used by the test vector generation script.  This allows the input
+ * data in random test vectors to be concisely stored as just the seed.
+ */
+static u32 rand32(void)
+{
+	random_seed = (random_seed * 25214903917 + 11) & ((1ULL << 48) - 1);
+	return random_seed >> 16;
+}
+
+static void rand_bytes(u8 *out, size_t len)
+{
+	for (size_t i = 0; i < len; i++)
+		out[i] = rand32();
+}
+
+static bool rand_bool(void)
+{
+	return rand32() % 2;
+}
+
+/* Generate a random length, preferring small lengths. */
+static size_t rand_length(size_t max_len)
+{
+	size_t len;
+
+	switch (rand32() % 3) {
+	case 0:
+		len = rand32() % 128;
+		break;
+	case 1:
+		len = rand32() % 3072;
+		break;
+	default:
+		len = rand32();
+		break;
+	}
+	return len % (max_len + 1);
+}
+
+static size_t rand_offset(size_t max_offset)
+{
+	return min(rand32() % 128, max_offset);
+}
+
+static int hash_suite_init(struct kunit_suite *suite)
+{
+	/*
+	 * Allocate the test buffer using vmalloc() with a page-aligned length
+	 * so that it is immediately followed by a guard page.  This allows
+	 * buffer overreads to be detected, even in assembly code.
+	 */
+	size_t alloc_len = round_up(TEST_BUF_LEN, PAGE_SIZE);
+
+	orig_test_buf = vmalloc(alloc_len);
+	if (!orig_test_buf)
+		return -ENOMEM;
+
+	test_buf = orig_test_buf + alloc_len - TEST_BUF_LEN;
+	rand_bytes(test_buf, TEST_BUF_LEN);
+	return 0;
+}
+
+static void hash_suite_exit(struct kunit_suite *suite)
+{
+	vfree(orig_test_buf);
+	orig_test_buf = NULL;
+}
+
+static void rand_bytes_seeded_from_len(u8 *out, size_t len)
+{
+	random_seed = len;
+	rand_bytes(out, len);
+}
+
+/*
+ * Test that the hash function produces the expected results from the test
+ * vectors.
+ *
+ * Note that it's only necessary to run each test vector in one way (e.g.,
+ * one-shot instead of a chain of incremental updates), since consistency
+ * between different ways of using the APIs is verified by other test cases.
+ */
+static void test_hash_test_vectors(struct kunit *test)
+{
+	for (size_t i = 0; i < ARRAY_SIZE(HASH_TESTVECS); i++) {
+		size_t data_len = HASH_TESTVECS[i].data_len;
+		u8 actual_digest[HASH_SIZE];
+
+		KUNIT_ASSERT_LE(test, data_len, TEST_BUF_LEN);
+
+		rand_bytes_seeded_from_len(test_buf, data_len);
+
+		HASH(test_buf, data_len, actual_digest);
+		KUNIT_ASSERT_MEMEQ_MSG(
+			test, actual_digest, HASH_TESTVECS[i].digest, HASH_SIZE,
+			"Wrong result with test vector %zu; data_len=%zu", i,
+			data_len);
+	}
+}
+
+/*
+ * Test that the hash function produces the same result for a one-shot
+ * computation vs. an incremental computation.
+ */
+static void test_hash_incremental_updates(struct kunit *test)
+{
+	for (size_t i = 0; i < 1000; i++) {
+		size_t total_len, offset;
+		struct HASH_CTX ctx;
+		u8 hash1[HASH_SIZE];
+		u8 hash2[HASH_SIZE];
+		size_t num_parts = 0;
+		size_t remaining_len, cur_offset;
+
+		total_len = rand_length(TEST_BUF_LEN);
+		offset = rand_offset(TEST_BUF_LEN - total_len);
+
+		if (rand32() % 8 == 0)
+			/* Refresh the data occasionally. */
+			rand_bytes(&test_buf[offset], total_len);
+
+		/* Compute the hash value in one step. */
+		HASH(&test_buf[offset], total_len, hash1);
+
+		/* Compute the hash value incrementally. */
+		HASH_INIT(&ctx);
+		remaining_len = total_len;
+		cur_offset = offset;
+		while (rand_bool()) {
+			size_t part_len = rand_length(remaining_len);
+
+			HASH_UPDATE(&ctx, &test_buf[cur_offset], part_len);
+			num_parts++;
+			cur_offset += part_len;
+			remaining_len -= part_len;
+		}
+		if (remaining_len != 0 || rand_bool()) {
+			HASH_UPDATE(&ctx, &test_buf[cur_offset], remaining_len);
+			num_parts++;
+		}
+		HASH_FINAL(&ctx, hash2);
+
+		/* Compare the two hash values. */
+		KUNIT_ASSERT_MEMEQ_MSG(
+			test, hash1, hash2, HASH_SIZE,
+			"Incremental test failed with total_len=%zu num_parts=%zu offset=%zu\n",
+			total_len, num_parts, offset);
+	}
+}
+
+/*
+ * Test that the hash function does not overrun any buffers.  Uses a guard page
+ * to catch buffer overruns even if they occur in assembly code.
+ */
+static void test_hash_buffer_overruns(struct kunit *test)
+{
+	const size_t max_tested_len = TEST_BUF_LEN - sizeof(struct HASH_CTX);
+	void *const buf_end = &test_buf[TEST_BUF_LEN];
+	struct HASH_CTX *guarded_ctx = buf_end - sizeof(*guarded_ctx);
+
+	for (size_t i = 0; i < 100; i++) {
+		size_t len = rand_length(max_tested_len);
+		u8 hash[HASH_SIZE];
+		struct HASH_CTX ctx;
+
+		/* Check for overruns of the data buffer. */
+		HASH(buf_end - len, len, hash);
+		HASH_INIT(&ctx);
+		HASH_UPDATE(&ctx, buf_end - len, len);
+		HASH_FINAL(&ctx, hash);
+
+		/* Check for overruns of the hash value buffer. */
+		HASH(test_buf, len, buf_end - HASH_SIZE);
+		HASH_INIT(&ctx);
+		HASH_UPDATE(&ctx, test_buf, len);
+		HASH_FINAL(&ctx, buf_end - HASH_SIZE);
+
+		/* Check for overuns of the hash context. */
+		HASH_INIT(guarded_ctx);
+		HASH_UPDATE(guarded_ctx, test_buf, len);
+		HASH_FINAL(guarded_ctx, hash);
+	}
+}
+
+/*
+ * Test that the caller is permitted to alias the output digest and source data
+ * buffer, and also modify the source data buffer after it has been used.
+ */
+static void test_hash_overlaps(struct kunit *test)
+{
+	const size_t max_tested_len = TEST_BUF_LEN - HASH_SIZE;
+	u8 hash[HASH_SIZE];
+	struct HASH_CTX ctx;
+
+	for (size_t i = 0; i < 100; i++) {
+		size_t len = rand_length(max_tested_len);
+		size_t offset = HASH_SIZE + rand_offset(max_tested_len - len);
+		bool left_end = rand_bool();
+		u8 *ovl_hash = left_end ? &test_buf[offset] :
+					  &test_buf[offset + len - HASH_SIZE];
+
+		HASH(&test_buf[offset], len, hash);
+		HASH(&test_buf[offset], len, ovl_hash);
+		KUNIT_ASSERT_MEMEQ_MSG(
+			test, hash, ovl_hash, HASH_SIZE,
+			"Overlap test 1 failed with len=%zu offset=%zu left_end=%d\n",
+			len, offset, left_end);
+
+		HASH(&test_buf[offset], len, hash);
+		HASH_INIT(&ctx);
+		HASH_UPDATE(&ctx, &test_buf[offset], len);
+		HASH_FINAL(&ctx, ovl_hash);
+		KUNIT_ASSERT_MEMEQ_MSG(
+			test, hash, ovl_hash, HASH_SIZE,
+			"Overlap test 2 failed with len=%zu offset=%zu left_end=%d\n",
+			len, offset, left_end);
+
+		HASH(&test_buf[offset], len, hash);
+		HASH_INIT(&ctx);
+		HASH_UPDATE(&ctx, &test_buf[offset], len);
+		rand_bytes(&test_buf[offset], len);
+		HASH_FINAL(&ctx, ovl_hash);
+		KUNIT_ASSERT_MEMEQ_MSG(
+			test, hash, ovl_hash, HASH_SIZE,
+			"Overlap test 3 failed with len=%zu offset=%zu left_end=%d\n",
+			len, offset, left_end);
+	}
+}
+
+/*
+ * Test that if the same data is hashed at different alignments in memory, the
+ * results are the same.
+ */
+static void test_hash_alignment_consistency(struct kunit *test)
+{
+	u8 hash1[128 + HASH_SIZE];
+	u8 hash2[128 + HASH_SIZE];
+
+	for (size_t i = 0; i < 100; i++) {
+		size_t len = rand_length(TEST_BUF_LEN);
+		size_t data_offs1 = rand_offset(TEST_BUF_LEN - len);
+		size_t data_offs2 = rand_offset(TEST_BUF_LEN - len);
+		size_t hash_offs1 = rand_offset(128);
+		size_t hash_offs2 = rand_offset(128);
+
+		rand_bytes(&test_buf[data_offs1], len);
+		HASH(&test_buf[data_offs1], len, &hash1[hash_offs1]);
+		memmove(&test_buf[data_offs2], &test_buf[data_offs1], len);
+		HASH(&test_buf[data_offs2], len, &hash2[hash_offs2]);
+		KUNIT_ASSERT_MEMEQ_MSG(
+			test, &hash1[hash_offs1], &hash2[hash_offs2], HASH_SIZE,
+			"Alignment consistency test failed with len=%zu data_offs=(%zu,%zu) hash_offs=(%zu,%zu)\n",
+			len, data_offs1, data_offs2, hash_offs1, hash_offs2);
+	}
+}
+
+/* Test that HASH_FINAL zeroizes the context. */
+static void test_hash_ctx_zeroization(struct kunit *test)
+{
+	static const u8 zeroes[sizeof(struct HASH_CTX)];
+	struct HASH_CTX ctx;
+
+	HASH_INIT(&ctx);
+	HASH_UPDATE(&ctx, test_buf, 128);
+	HASH_FINAL(&ctx, test_buf);
+	KUNIT_EXPECT_MEMEQ_MSG(test, &ctx, zeroes, sizeof(ctx),
+			       "Hash context was not zeroized by finalization");
+}
+
+#define IRQ_TEST_DATA_LEN 256
+#define IRQ_TEST_NUM_BUFFERS 3
+#define IRQ_TEST_HRTIMER_INTERVAL us_to_ktime(5)
+
+struct irq_test_state {
+	struct hrtimer timer;
+	struct work_struct bh_work;
+	u8 expected_hashes[IRQ_TEST_NUM_BUFFERS][HASH_SIZE];
+	atomic_t seqno;
+	atomic_t timer_func_calls;
+	atomic_t bh_func_calls;
+	bool task_wrong_result;
+	bool timer_func_wrong_result;
+	bool bh_func_wrong_result;
+};
+
+/*
+ * Compute a hash of one of the test messages and check for the expected result
+ * that was saved earlier in @state->expected_hashes.  To increase the chance of
+ * detecting problems, this cycles through multiple messages.
+ */
+static bool irq_test_step(struct irq_test_state *state)
+{
+	u32 i = (u32)atomic_inc_return(&state->seqno) % IRQ_TEST_NUM_BUFFERS;
+	u8 actual_hash[HASH_SIZE];
+
+	HASH(&test_buf[i * IRQ_TEST_DATA_LEN], IRQ_TEST_DATA_LEN, actual_hash);
+	return memcmp(actual_hash, state->expected_hashes[i], HASH_SIZE) == 0;
+}
+
+/*
+ * This is the timer function run by the IRQ test.  It is called in hardirq
+ * context.  It computes a hash, checks for the correct result, then reschedules
+ * the timer and also the BH work.
+ */
+static enum hrtimer_restart irq_test_timer_func(struct hrtimer *timer)
+{
+	struct irq_test_state *state =
+		container_of(timer, typeof(*state), timer);
+
+	WARN_ON_ONCE(!in_hardirq());
+	atomic_inc(&state->timer_func_calls);
+	if (!irq_test_step(state))
+		state->timer_func_wrong_result = true;
+
+	hrtimer_forward_now(&state->timer, IRQ_TEST_HRTIMER_INTERVAL);
+	queue_work(system_bh_wq, &state->bh_work);
+	return HRTIMER_RESTART;
+}
+
+/* Compute a hash in softirq context and check for the expected result. */
+static void irq_test_bh_func(struct work_struct *work)
+{
+	struct irq_test_state *state =
+		container_of(work, typeof(*state), bh_work);
+
+	WARN_ON_ONCE(!in_serving_softirq());
+	atomic_inc(&state->bh_func_calls);
+	if (!irq_test_step(state))
+		state->bh_func_wrong_result = true;
+}
+
+/*
+ * Test that if hashes are computed in parallel in task, softirq, and hardirq
+ * context, then all results are as expected.
+ *
+ * The primary purpose of this test is to verify the correctness of fallback
+ * code paths that runs in contexts where the normal code path cannot be used,
+ * e.g. !may_use_simd().  These code paths are not covered by any of the other
+ * tests, which are executed by the KUnit test runner thread in task context.
+ *
+ * In addition, this test may detect issues with the architecture's
+ * irq_fpu_usable() and kernel_fpu_begin/end() or equivalent functions.
+ */
+static void test_hash_interrupt_context(struct kunit *test)
+{
+	struct irq_test_state state = {};
+	size_t i;
+	unsigned long end_jiffies;
+
+	/* Prepare some test messages and compute the expected hash of each. */
+	rand_bytes(test_buf, IRQ_TEST_NUM_BUFFERS * IRQ_TEST_DATA_LEN);
+	for (i = 0; i < IRQ_TEST_NUM_BUFFERS; i++)
+		HASH(&test_buf[i * IRQ_TEST_DATA_LEN], IRQ_TEST_DATA_LEN,
+		     state.expected_hashes[i]);
+
+	/*
+	 * Set up a hrtimer (the way we access hardirq context) and a work
+	 * struct for the BH workqueue (the way we access softirq context).
+	 */
+	hrtimer_setup_on_stack(&state.timer, irq_test_timer_func,
+			       CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	INIT_WORK(&state.bh_work, irq_test_bh_func);
+
+	/* Run for up to 100000 hashes or 1 second, whichever comes first. */
+	end_jiffies = jiffies + HZ;
+	hrtimer_start(&state.timer, IRQ_TEST_HRTIMER_INTERVAL,
+		      HRTIMER_MODE_REL);
+	for (i = 0; i < 100000 && !time_after(jiffies, end_jiffies); i++) {
+		if (!irq_test_step(&state))
+			state.task_wrong_result = true;
+	}
+
+	/* Cancel the timer and work. */
+	hrtimer_cancel(&state.timer);
+	flush_work(&state.bh_work);
+
+	/* Sanity check: the timer and BH functions should have been run. */
+	KUNIT_EXPECT_GT_MSG(test, atomic_read(&state.timer_func_calls), 0,
+			    "IRQ test failed; timer function was not called");
+	KUNIT_EXPECT_GT_MSG(test, atomic_read(&state.bh_func_calls), 0,
+			    "IRQ test failed; BH work function was not called");
+
+	/* Check the results. */
+	KUNIT_EXPECT_FALSE_MSG(test, state.task_wrong_result,
+			       "IRQ test failed; wrong result in task context");
+	KUNIT_EXPECT_FALSE_MSG(
+		test, state.timer_func_wrong_result,
+		"IRQ test failed; wrong result in timer function (hardirq context)");
+	KUNIT_EXPECT_FALSE_MSG(
+		test, state.bh_func_wrong_result,
+		"IRQ test failed; wrong result in BH work function (softirq context)");
+}
+
+#ifdef HMAC
+/*
+ * Test the corresponding HMAC variant.  This is a bit less thorough than the
+ * tests for the hash function, since HMAC is just a small C wrapper around the
+ * unkeyed hash function.
+ */
+static void test_hmac(struct kunit *test)
+{
+	u8 *raw_key = kunit_kmalloc(test, TEST_BUF_LEN, GFP_KERNEL);
+	static const u8 zeroes[sizeof(struct HMAC_CTX)];
+
+	KUNIT_ASSERT_NOT_NULL(test, raw_key);
+
+	for (size_t i = 0; i < ARRAY_SIZE(HMAC_TESTVECS); i++) {
+		size_t data_len = HMAC_TESTVECS[i].data_len;
+		size_t key_len = HMAC_TESTVECS[i].key_len;
+		struct HMAC_CTX ctx;
+		struct HMAC_KEY key;
+		u8 actual_mac[HASH_SIZE];
+
+		KUNIT_ASSERT_LE(test, data_len, TEST_BUF_LEN);
+		KUNIT_ASSERT_LE(test, key_len, TEST_BUF_LEN);
+
+		rand_bytes_seeded_from_len(test_buf, data_len);
+		rand_bytes_seeded_from_len(raw_key, key_len);
+
+		HMAC_USINGRAWKEY(raw_key, key_len, test_buf, data_len,
+				 actual_mac);
+		KUNIT_ASSERT_MEMEQ_MSG(
+			test, actual_mac, HMAC_TESTVECS[i].mac, HASH_SIZE,
+			"Wrong result with HMAC test vector %zu using raw key; data_len=%zu key_len=%zu",
+			i, data_len, key_len);
+
+		memset(actual_mac, 0xff, HASH_SIZE);
+		HMAC_SETKEY(&key, raw_key, key_len);
+		HMAC(&key, test_buf, data_len, actual_mac);
+		KUNIT_ASSERT_MEMEQ_MSG(
+			test, actual_mac, HMAC_TESTVECS[i].mac, HASH_SIZE,
+			"Wrong result with HMAC test vector %zu using key struct; data_len=%zu key_len=%zu",
+			i, data_len, key_len);
+
+		memset(actual_mac, 0xff, HASH_SIZE);
+		HMAC_INIT(&ctx, &key);
+		HMAC_UPDATE(&ctx, test_buf, data_len);
+		HMAC_FINAL(&ctx, actual_mac);
+		KUNIT_ASSERT_MEMEQ_MSG(
+			test, actual_mac, HMAC_TESTVECS[i].mac, HASH_SIZE,
+			"Wrong result with HMAC test vector %zu on init+update+final; data_len=%zu key_len=%zu",
+			i, data_len, key_len);
+		KUNIT_ASSERT_MEMEQ_MSG(
+			test, &ctx, zeroes, sizeof(ctx),
+			"HMAC context was not zeroized by finalization");
+
+		memset(actual_mac, 0xff, HASH_SIZE);
+		HMAC_INIT(&ctx, &key);
+		HMAC_UPDATE(&ctx, test_buf, data_len / 2);
+		HMAC_UPDATE(&ctx, &test_buf[data_len / 2], (data_len + 1) / 2);
+		HMAC_FINAL(&ctx, actual_mac);
+		KUNIT_ASSERT_MEMEQ_MSG(
+			test, actual_mac, HMAC_TESTVECS[i].mac, HASH_SIZE,
+			"Wrong result with HMAC test vector %zu on init+update+update+final; data_len=%zu key_len=%zu",
+			i, data_len, key_len);
+	}
+}
+#endif /* HMAC */
+
+/* Benchmark the hash function on various data lengths. */
+static void benchmark_hash(struct kunit *test)
+{
+	static const size_t lens_to_test[] = {
+		1,   16,  64,	127,  128,  200,   256,
+		511, 512, 1024, 3173, 4096, 16384,
+	};
+	size_t len, i, j, num_iters;
+	u8 hash[HASH_SIZE];
+	u64 t;
+
+	if (!IS_ENABLED(CONFIG_CRYPTO_LIB_BENCHMARK))
+		kunit_skip(test, "not enabled");
+
+	/* warm-up */
+	for (i = 0; i < 10000000; i += TEST_BUF_LEN)
+		HASH(test_buf, TEST_BUF_LEN, hash);
+
+	for (i = 0; i < ARRAY_SIZE(lens_to_test); i++) {
+		len = lens_to_test[i];
+		KUNIT_ASSERT_LE(test, len, TEST_BUF_LEN);
+		num_iters = 10000000 / (len + 128);
+		preempt_disable();
+		t = ktime_get_ns();
+		for (j = 0; j < num_iters; j++)
+			HASH(test_buf, len, hash);
+		t = ktime_get_ns() - t;
+		preempt_enable();
+		kunit_info(test, "len=%zu: %llu MB/s\n", len,
+			   div64_u64((u64)len * num_iters * 1000, t));
+	}
+}
diff --git a/lib/crypto/tests/sha384-testvecs.h b/lib/crypto/tests/sha384-testvecs.h
new file mode 100644
index 0000000000000..7ea330dfe54f3
--- /dev/null
+++ b/lib/crypto/tests/sha384-testvecs.h
@@ -0,0 +1,566 @@
+/* This file was generated by: ./scripts/crypto/gen-hash-testvecs.py sha384 */
+
+static const struct {
+	size_t data_len;
+	u8 digest[SHA384_DIGEST_SIZE];
+} sha384_testvecs[] = {
+	{
+		.data_len = 0,
+		.digest = {
+			0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38,
+			0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a,
+			0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43,
+			0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda,
+			0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb,
+			0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b,
+		},
+	},
+	{
+		.data_len = 1,
+		.digest = {
+			0x07, 0x34, 0x9d, 0x74, 0x48, 0x76, 0xa5, 0x72,
+			0x78, 0x02, 0xb8, 0x6e, 0x21, 0x59, 0xb0, 0x75,
+			0x09, 0x68, 0x11, 0x39, 0x53, 0x61, 0xee, 0x8d,
+			0xf2, 0x01, 0xf3, 0x90, 0x53, 0x7c, 0xd3, 0xde,
+			0x13, 0x9f, 0xd2, 0x74, 0x28, 0xfe, 0xe1, 0xc8,
+			0x2e, 0x95, 0xc6, 0x7d, 0x69, 0x4d, 0x04, 0xc6,
+		},
+	},
+	{
+		.data_len = 2,
+		.digest = {
+			0xc4, 0xef, 0x6e, 0x8c, 0x19, 0x1c, 0xaa, 0x0e,
+			0x86, 0xf2, 0x68, 0xa1, 0xa0, 0x2d, 0x2e, 0xb2,
+			0x84, 0xbc, 0x5d, 0x53, 0x31, 0xf8, 0x03, 0x75,
+			0x56, 0xf4, 0x8b, 0x23, 0x1a, 0x68, 0x15, 0x9a,
+			0x60, 0xb2, 0xec, 0x05, 0xe1, 0xd4, 0x5e, 0x9e,
+			0xe8, 0x7c, 0x9d, 0xe4, 0x0f, 0x9c, 0x3a, 0xdd,
+		},
+	},
+	{
+		.data_len = 3,
+		.digest = {
+			0x29, 0xd2, 0x02, 0xa2, 0x77, 0x24, 0xc7, 0xa7,
+			0x23, 0x0c, 0x3e, 0x30, 0x56, 0x47, 0xdb, 0x75,
+			0xd4, 0x41, 0xf8, 0xb3, 0x8e, 0x26, 0xf6, 0x92,
+			0xbc, 0x20, 0x2e, 0x96, 0xcc, 0x81, 0x5f, 0x32,
+			0x82, 0x60, 0xe2, 0xcf, 0x23, 0xd7, 0x3c, 0x90,
+			0xb2, 0x56, 0x8f, 0xb6, 0x0f, 0xf0, 0x6b, 0x80,
+		},
+	},
+	{
+		.data_len = 16,
+		.digest = {
+			0x21, 0x4c, 0xac, 0xfe, 0xbd, 0x40, 0x74, 0x1f,
+			0xa2, 0x2d, 0x2f, 0x35, 0x91, 0xfd, 0xc9, 0x97,
+			0x88, 0x12, 0x6c, 0x0c, 0x6e, 0xd8, 0x50, 0x0b,
+			0x4b, 0x2c, 0x89, 0xa6, 0xa6, 0x4a, 0xad, 0xd7,
+			0x72, 0x62, 0x2c, 0x62, 0x81, 0xcd, 0x24, 0x74,
+			0xf5, 0x44, 0x05, 0xa0, 0x97, 0xea, 0xf1, 0x78,
+		},
+	},
+	{
+		.data_len = 32,
+		.digest = {
+			0x06, 0x8b, 0x92, 0x9f, 0x8b, 0x64, 0xb2, 0x80,
+			0xde, 0xcc, 0xde, 0xc3, 0x2f, 0x22, 0x27, 0xe8,
+			0x3b, 0x6e, 0x16, 0x21, 0x14, 0x81, 0xbe, 0x5b,
+			0xa7, 0xa7, 0x14, 0x8a, 0x00, 0x8f, 0x0d, 0x38,
+			0x11, 0x63, 0xe8, 0x3e, 0xb9, 0xf1, 0xcf, 0x87,
+			0xb1, 0x28, 0xe5, 0xa1, 0x89, 0xa8, 0x7a, 0xde,
+		},
+	},
+	{
+		.data_len = 48,
+		.digest = {
+			0x9e, 0x37, 0x76, 0x62, 0x98, 0x39, 0xbe, 0xfd,
+			0x2b, 0x91, 0x20, 0x54, 0x8f, 0x21, 0xe7, 0x30,
+			0x0a, 0x01, 0x7a, 0x65, 0x0b, 0xc9, 0xb3, 0x89,
+			0x3c, 0xb6, 0xd3, 0xa8, 0xff, 0xc9, 0x1b, 0x5c,
+			0xd4, 0xac, 0xb4, 0x7e, 0xba, 0x94, 0xc3, 0x8a,
+			0x26, 0x41, 0xf6, 0xd5, 0xed, 0x6f, 0x27, 0xa7,
+		},
+	},
+	{
+		.data_len = 49,
+		.digest = {
+			0x03, 0x1f, 0xef, 0x5a, 0x16, 0x28, 0x78, 0x10,
+			0x29, 0xe8, 0xe2, 0xe4, 0x84, 0x36, 0x19, 0x10,
+			0xaa, 0xea, 0xde, 0x06, 0x39, 0x5f, 0xb2, 0x36,
+			0xca, 0x24, 0x4f, 0x7b, 0x66, 0xf7, 0xe7, 0x31,
+			0xf3, 0x9b, 0x74, 0x1e, 0x17, 0x20, 0x88, 0x62,
+			0x50, 0xeb, 0x5f, 0x9a, 0xa7, 0x2c, 0xf4, 0xc9,
+		},
+	},
+	{
+		.data_len = 63,
+		.digest = {
+			0x10, 0xce, 0xed, 0x26, 0xb8, 0xac, 0xc1, 0x1b,
+			0xe6, 0xb9, 0xeb, 0x7c, 0xae, 0xcd, 0x55, 0x5a,
+			0x20, 0x2a, 0x7b, 0x43, 0xe6, 0x3e, 0xf0, 0x3f,
+			0xd9, 0x2f, 0x8c, 0x52, 0xe2, 0xf0, 0xb6, 0x24,
+			0x2e, 0xa4, 0xac, 0x24, 0x3a, 0x54, 0x99, 0x71,
+			0x65, 0xab, 0x97, 0x2d, 0xb6, 0xe6, 0x94, 0x20,
+		},
+	},
+	{
+		.data_len = 64,
+		.digest = {
+			0x24, 0x6d, 0x9f, 0x59, 0x42, 0x36, 0xca, 0x34,
+			0x36, 0x41, 0xa2, 0xcd, 0x69, 0xdf, 0x3d, 0xcb,
+			0x64, 0x94, 0x54, 0xb2, 0xed, 0xc1, 0x1c, 0x31,
+			0xe3, 0x26, 0xcb, 0x71, 0xe6, 0x98, 0xb2, 0x56,
+			0x74, 0x30, 0xa9, 0x15, 0x98, 0x9d, 0xb3, 0x07,
+			0xcc, 0xa8, 0xcc, 0x6f, 0x42, 0xb0, 0x9d, 0x2b,
+		},
+	},
+	{
+		.data_len = 65,
+		.digest = {
+			0x85, 0x1f, 0xbc, 0x5e, 0x2a, 0x00, 0x7d, 0xc2,
+			0x21, 0x4c, 0x28, 0x14, 0xc5, 0xd8, 0x0c, 0xe8,
+			0x55, 0xa5, 0xa0, 0x77, 0xda, 0x8f, 0xce, 0xd4,
+			0xf0, 0xcb, 0x30, 0xb8, 0x9c, 0x47, 0xe1, 0x33,
+			0x92, 0x18, 0xc5, 0x1f, 0xf2, 0xef, 0xb5, 0xe5,
+			0xbc, 0x63, 0xa6, 0xe5, 0x9a, 0xc9, 0xcc, 0xf1,
+		},
+	},
+	{
+		.data_len = 127,
+		.digest = {
+			0x26, 0xd2, 0x4c, 0xb6, 0xce, 0xd8, 0x22, 0x2b,
+			0x44, 0x10, 0x6f, 0x59, 0xf7, 0x0d, 0xb9, 0x3f,
+			0x7d, 0x29, 0x75, 0xf1, 0x71, 0xb2, 0x71, 0x23,
+			0xef, 0x68, 0xb7, 0x25, 0xae, 0xb8, 0x45, 0xf8,
+			0xa3, 0xb2, 0x2d, 0x7a, 0x83, 0x0a, 0x05, 0x61,
+			0xbc, 0x73, 0xf1, 0xf9, 0xba, 0xfb, 0x3d, 0xc2,
+		},
+	},
+	{
+		.data_len = 128,
+		.digest = {
+			0x7c, 0xe5, 0x7f, 0x5e, 0xea, 0xd9, 0x7e, 0x54,
+			0x14, 0x30, 0x6f, 0x37, 0x02, 0x71, 0x0f, 0xf1,
+			0x14, 0x16, 0xfa, 0xeb, 0x6e, 0x1e, 0xf0, 0xbe,
+			0x10, 0xed, 0x01, 0xbf, 0xa0, 0x9d, 0xcb, 0x07,
+			0x5f, 0x8b, 0x7f, 0x44, 0xe1, 0xd9, 0x13, 0xf0,
+			0x29, 0xa2, 0x54, 0x32, 0xd9, 0xb0, 0x69, 0x69,
+		},
+	},
+	{
+		.data_len = 129,
+		.digest = {
+			0xc5, 0x54, 0x1f, 0xcb, 0x9d, 0x8f, 0xdf, 0xbf,
+			0xab, 0x55, 0x92, 0x1d, 0x3b, 0x93, 0x79, 0x26,
+			0xdf, 0xba, 0x9a, 0x28, 0xff, 0xa0, 0x6c, 0xae,
+			0x7b, 0x53, 0x8d, 0xfa, 0xef, 0x35, 0x88, 0x19,
+			0x16, 0xb8, 0x72, 0x86, 0x76, 0x2a, 0xf5, 0xe6,
+			0xec, 0xb2, 0xd7, 0xd4, 0xbe, 0x1a, 0xe4, 0x9f,
+		},
+	},
+	{
+		.data_len = 256,
+		.digest = {
+			0x74, 0x9d, 0x77, 0xfb, 0xe8, 0x0f, 0x0c, 0x2d,
+			0x86, 0x0d, 0x49, 0xea, 0x2b, 0xd0, 0x13, 0xd1,
+			0xe8, 0xb8, 0xe1, 0xa3, 0x7b, 0x48, 0xab, 0x6a,
+			0x21, 0x2b, 0x4c, 0x48, 0x32, 0xb5, 0xdc, 0x31,
+			0x7f, 0xd0, 0x32, 0x67, 0x9a, 0xc0, 0x85, 0x53,
+			0xef, 0xe9, 0xfb, 0xe1, 0x8b, 0xd8, 0xcc, 0xc2,
+		},
+	},
+	{
+		.data_len = 511,
+		.digest = {
+			0x7b, 0xa9, 0xde, 0xa3, 0x07, 0x5c, 0x4c, 0xaa,
+			0x31, 0xc6, 0x9e, 0x55, 0xd4, 0x3f, 0x52, 0xdd,
+			0xde, 0x36, 0x70, 0x96, 0x59, 0x6e, 0x90, 0x78,
+			0x4c, 0x6a, 0x27, 0xde, 0x83, 0x84, 0xc3, 0x35,
+			0x53, 0x76, 0x1d, 0xbf, 0x83, 0x64, 0xcf, 0xf2,
+			0xb0, 0x3e, 0x07, 0x27, 0xe4, 0x25, 0x6c, 0x56,
+		},
+	},
+	{
+		.data_len = 513,
+		.digest = {
+			0x53, 0x50, 0xf7, 0x3b, 0x86, 0x1d, 0x7a, 0xe2,
+			0x5d, 0x9b, 0x71, 0xfa, 0x25, 0x23, 0x5a, 0xfe,
+			0x8c, 0xb9, 0xac, 0x8a, 0x9d, 0x6c, 0x99, 0xbc,
+			0x01, 0x9e, 0xa0, 0xd6, 0x3c, 0x03, 0x46, 0x21,
+			0xb6, 0xd0, 0xb0, 0xb3, 0x23, 0x23, 0x58, 0xf1,
+			0xea, 0x4e, 0xf2, 0x1a, 0x2f, 0x14, 0x2b, 0x5a,
+		},
+	},
+	{
+		.data_len = 1000,
+		.digest = {
+			0x06, 0x03, 0xb3, 0xba, 0x14, 0xe0, 0x28, 0x07,
+			0xd5, 0x15, 0x97, 0x1f, 0x87, 0xef, 0x80, 0xba,
+			0x48, 0x03, 0xb6, 0xc5, 0x47, 0xca, 0x8c, 0x95,
+			0xed, 0x95, 0xfd, 0x27, 0xb6, 0x83, 0xda, 0x6d,
+			0xa7, 0xb2, 0x1a, 0xd2, 0xb5, 0x89, 0xbb, 0xb4,
+			0x00, 0xbc, 0x86, 0x54, 0x7d, 0x5a, 0x91, 0x63,
+		},
+	},
+	{
+		.data_len = 3333,
+		.digest = {
+			0xd3, 0xe0, 0x6e, 0x7d, 0x80, 0x08, 0x53, 0x07,
+			0x8c, 0x0f, 0xc2, 0xce, 0x9f, 0x09, 0x86, 0x31,
+			0x28, 0x24, 0x3c, 0x3e, 0x2d, 0x36, 0xb4, 0x28,
+			0xc7, 0x1b, 0x70, 0xf9, 0x35, 0x9b, 0x10, 0xfa,
+			0xc8, 0x5e, 0x2b, 0x32, 0x7f, 0x65, 0xd2, 0x68,
+			0xb2, 0x84, 0x90, 0xf6, 0xc8, 0x6e, 0xb8, 0xdb,
+		},
+	},
+	{
+		.data_len = 4096,
+		.digest = {
+			0x39, 0xeb, 0xc4, 0xb3, 0x08, 0xe2, 0xdd, 0xf3,
+			0x9f, 0x5e, 0x44, 0x93, 0x63, 0x8b, 0x39, 0x57,
+			0xd7, 0xe8, 0x7e, 0x3d, 0x74, 0xf8, 0xf6, 0xab,
+			0xfe, 0x74, 0x51, 0xe4, 0x1b, 0x4a, 0x23, 0xbc,
+			0x69, 0xfc, 0xbb, 0xa7, 0x71, 0xa7, 0x86, 0x24,
+			0xcc, 0x85, 0x70, 0xf2, 0x31, 0x0d, 0x47, 0xc0,
+		},
+	},
+	{
+		.data_len = 4128,
+		.digest = {
+			0x23, 0xc3, 0x97, 0x06, 0x79, 0xbe, 0x8a, 0xe9,
+			0x1f, 0x1a, 0x43, 0xad, 0xe6, 0x76, 0x23, 0x13,
+			0x64, 0xae, 0xda, 0xe7, 0x8b, 0x88, 0x96, 0xb6,
+			0xa9, 0x1a, 0xb7, 0x80, 0x8e, 0x1c, 0x94, 0x98,
+			0x09, 0x08, 0xdb, 0x8e, 0x4d, 0x0a, 0x09, 0x65,
+			0xe5, 0x21, 0x1c, 0xd9, 0xab, 0x64, 0xbb, 0xea,
+		},
+	},
+	{
+		.data_len = 4160,
+		.digest = {
+			0x4f, 0x4a, 0x88, 0x9f, 0x40, 0x89, 0xfe, 0xb6,
+			0xda, 0x9d, 0xcd, 0xa5, 0x27, 0xd2, 0x29, 0x71,
+			0x58, 0x60, 0xd4, 0x55, 0xfe, 0x92, 0xcd, 0x51,
+			0x8b, 0xec, 0x3b, 0xd3, 0xd1, 0x3e, 0x8d, 0x36,
+			0x7b, 0xb1, 0x41, 0xef, 0xec, 0x9d, 0xdf, 0xcd,
+			0x4e, 0xde, 0x5a, 0xe5, 0xe5, 0x16, 0x14, 0x54,
+		},
+	},
+	{
+		.data_len = 4224,
+		.digest = {
+			0xb5, 0xa5, 0x3e, 0x86, 0x39, 0x20, 0x49, 0x4c,
+			0xcd, 0xb6, 0xdd, 0x03, 0xfe, 0x36, 0x6e, 0xa6,
+			0xfc, 0xff, 0x19, 0x33, 0x0c, 0x52, 0xea, 0x37,
+			0x94, 0xda, 0x5b, 0x27, 0xd1, 0x99, 0x5a, 0x89,
+			0x40, 0x78, 0xfa, 0x96, 0xb9, 0x2f, 0xa0, 0x48,
+			0xc9, 0xf8, 0x5c, 0xf0, 0x95, 0xf4, 0xea, 0x61,
+		},
+	},
+	{
+		.data_len = 16384,
+		.digest = {
+			0x6f, 0x48, 0x6f, 0x21, 0xb9, 0xc1, 0xcc, 0x92,
+			0x4e, 0xed, 0x6b, 0xef, 0x51, 0x88, 0xdf, 0xfd,
+			0xcb, 0x3d, 0x44, 0x9c, 0x37, 0x85, 0xb4, 0xc5,
+			0xeb, 0x60, 0x55, 0x58, 0x01, 0x47, 0xbf, 0x75,
+			0x9b, 0xa8, 0x82, 0x8c, 0xec, 0xe8, 0x0e, 0x58,
+			0xc1, 0x26, 0xa2, 0x45, 0x87, 0x3e, 0xfb, 0x8d,
+		},
+	},
+};
+
+static const struct {
+	size_t data_len;
+	size_t key_len;
+	u8 mac[SHA384_DIGEST_SIZE];
+} hmac_sha384_testvecs[] = {
+	{
+		.data_len = 0,
+		.key_len = 0,
+		.mac = {
+			0x6c, 0x1f, 0x2e, 0xe9, 0x38, 0xfa, 0xd2, 0xe2,
+			0x4b, 0xd9, 0x12, 0x98, 0x47, 0x43, 0x82, 0xca,
+			0x21, 0x8c, 0x75, 0xdb, 0x3d, 0x83, 0xe1, 0x14,
+			0xb3, 0xd4, 0x36, 0x77, 0x76, 0xd1, 0x4d, 0x35,
+			0x51, 0x28, 0x9e, 0x75, 0xe8, 0x20, 0x9c, 0xd4,
+			0xb7, 0x92, 0x30, 0x28, 0x40, 0x23, 0x4a, 0xdc,
+		},
+	},
+	{
+		.data_len = 1,
+		.key_len = 1,
+		.mac = {
+			0xe5, 0x20, 0x5e, 0xd4, 0x0a, 0xd8, 0x37, 0xff,
+			0xf9, 0x0e, 0x2b, 0xf2, 0xca, 0x15, 0x65, 0xec,
+			0xb3, 0xfb, 0x14, 0xa1, 0xc3, 0xdc, 0x9e, 0xa0,
+			0x96, 0x99, 0xeb, 0x18, 0x24, 0x90, 0x42, 0xef,
+			0x63, 0x3c, 0x38, 0xd3, 0x19, 0x6b, 0x7f, 0xef,
+			0x07, 0xb3, 0xb8, 0xb0, 0x43, 0x5f, 0xef, 0xed,
+		},
+	},
+	{
+		.data_len = 2,
+		.key_len = 31,
+		.mac = {
+			0x47, 0x08, 0x60, 0x37, 0xe9, 0x47, 0x0d, 0x56,
+			0xa9, 0x81, 0xa1, 0xdf, 0x05, 0x1e, 0x41, 0x4e,
+			0x7f, 0xf9, 0x51, 0xb3, 0x47, 0x7e, 0x04, 0x4f,
+			0x0a, 0x05, 0x13, 0x6e, 0xd8, 0x4e, 0x6d, 0x98,
+			0x91, 0x89, 0xe1, 0xdc, 0x7f, 0x23, 0x03, 0x2e,
+			0x47, 0x9e, 0x7c, 0xe0, 0x68, 0x08, 0xd2, 0x57,
+		},
+	},
+	{
+		.data_len = 3,
+		.key_len = 32,
+		.mac = {
+			0xb9, 0x83, 0xdc, 0x7c, 0xb2, 0x48, 0x04, 0xc7,
+			0xdf, 0x9f, 0x8b, 0xbe, 0x17, 0x80, 0xc5, 0x13,
+			0x24, 0x10, 0x1c, 0xf1, 0x38, 0x75, 0x87, 0xe6,
+			0x3a, 0x2e, 0xa2, 0xed, 0x33, 0xdb, 0xfc, 0xd7,
+			0x0c, 0x8e, 0x89, 0x92, 0x14, 0x19, 0xef, 0x43,
+			0xef, 0x6b, 0xc7, 0xc5, 0x4d, 0x3f, 0xa4, 0x41,
+		},
+	},
+	{
+		.data_len = 16,
+		.key_len = 33,
+		.mac = {
+			0xee, 0x3b, 0x6b, 0x7f, 0xec, 0xe1, 0xc4, 0x8f,
+			0x01, 0x91, 0xc9, 0x1a, 0x18, 0xb3, 0x0f, 0x34,
+			0xad, 0xe5, 0x1f, 0x51, 0x9a, 0x0b, 0xec, 0xa3,
+			0xc1, 0x0e, 0xf7, 0x7e, 0xb5, 0xd5, 0xe6, 0x22,
+			0x44, 0x23, 0x85, 0x2c, 0xe0, 0xb6, 0x81, 0xac,
+			0x7b, 0x41, 0x49, 0x18, 0x92, 0x0a, 0xd5, 0xc1,
+		},
+	},
+	{
+		.data_len = 32,
+		.key_len = 64,
+		.mac = {
+			0x4d, 0x1f, 0xd0, 0x53, 0x5e, 0x04, 0x2b, 0xd6,
+			0xfd, 0xd6, 0xa2, 0xed, 0xa2, 0x49, 0x36, 0xbf,
+			0x44, 0x8e, 0x42, 0x1c, 0x8a, 0xde, 0x44, 0xbb,
+			0x43, 0x84, 0xec, 0x70, 0xbb, 0x2d, 0xd3, 0x66,
+			0x51, 0xc0, 0xed, 0xd1, 0xcd, 0x5b, 0x11, 0xf2,
+			0x1c, 0xe6, 0x7d, 0xe9, 0xcd, 0xab, 0xff, 0x02,
+		},
+	},
+	{
+		.data_len = 48,
+		.key_len = 65,
+		.mac = {
+			0x12, 0xfc, 0x9f, 0x95, 0xcd, 0x88, 0xed, 0x8a,
+			0x6a, 0x87, 0x36, 0x45, 0x63, 0xb9, 0xc8, 0x46,
+			0xf5, 0x06, 0x97, 0x24, 0x19, 0xc8, 0xfa, 0xfd,
+			0xcf, 0x2b, 0x78, 0x5d, 0x44, 0xf1, 0x82, 0xbf,
+			0x93, 0xea, 0x9c, 0x84, 0xe5, 0xba, 0x27, 0x21,
+			0x2f, 0x3b, 0xd0, 0xfe, 0x2c, 0x53, 0x72, 0x31,
+		},
+	},
+	{
+		.data_len = 49,
+		.key_len = 66,
+		.mac = {
+			0x8e, 0x8f, 0x3d, 0xd7, 0xe6, 0x14, 0x0c, 0xf2,
+			0xf6, 0x9a, 0x19, 0xda, 0x4c, 0xb2, 0xc4, 0x84,
+			0x63, 0x76, 0x5b, 0xae, 0x17, 0xe0, 0xdf, 0x92,
+			0x82, 0xcf, 0x85, 0xbd, 0xce, 0xde, 0x3b, 0x49,
+			0xfe, 0x0a, 0xfb, 0xdc, 0x9a, 0xc0, 0x9e, 0xc7,
+			0x4f, 0x2c, 0x0f, 0xd3, 0xb9, 0x82, 0x1a, 0xaa,
+		},
+	},
+	{
+		.data_len = 63,
+		.key_len = 127,
+		.mac = {
+			0xc9, 0x17, 0xbb, 0x8f, 0x4f, 0x13, 0xba, 0x99,
+			0x4e, 0x48, 0x6a, 0x23, 0x12, 0x61, 0x7b, 0xa0,
+			0x63, 0xcb, 0x47, 0xfd, 0xbd, 0xd3, 0xfd, 0x94,
+			0xe7, 0x0b, 0xec, 0x04, 0x44, 0x5a, 0xfe, 0xb0,
+			0x97, 0x5b, 0x80, 0x4c, 0x02, 0x5c, 0x92, 0x05,
+			0x45, 0xe6, 0xe3, 0x0d, 0x21, 0xa5, 0x9a, 0x11,
+		},
+	},
+	{
+		.data_len = 64,
+		.key_len = 128,
+		.mac = {
+			0xbf, 0x20, 0x44, 0xe1, 0x91, 0xcf, 0x2b, 0x53,
+			0xcb, 0xcb, 0x89, 0xc2, 0x1b, 0x8e, 0xcb, 0xb0,
+			0x12, 0xd2, 0x77, 0x21, 0x7e, 0x8f, 0x40, 0x0f,
+			0x1e, 0xa4, 0xe7, 0x38, 0x69, 0x0f, 0x58, 0xba,
+			0x42, 0x78, 0x57, 0x4e, 0x7a, 0xf0, 0xb0, 0xf2,
+			0xe0, 0x17, 0x17, 0xcf, 0xee, 0x26, 0x53, 0x81,
+		},
+	},
+	{
+		.data_len = 65,
+		.key_len = 129,
+		.mac = {
+			0x44, 0xe7, 0x53, 0x94, 0xaa, 0x33, 0xb0, 0xde,
+			0x8e, 0xef, 0x85, 0x19, 0x69, 0x1e, 0xba, 0x69,
+			0x7f, 0xe1, 0x17, 0xc3, 0x91, 0xd6, 0x7b, 0x07,
+			0x61, 0xed, 0x81, 0x4c, 0x01, 0x65, 0x36, 0xbd,
+			0x7d, 0x4f, 0x70, 0xd7, 0x0d, 0xb8, 0xfc, 0xaf,
+			0x48, 0x1c, 0x96, 0x37, 0xf9, 0xc8, 0x72, 0x00,
+		},
+	},
+	{
+		.data_len = 127,
+		.key_len = 1000,
+		.mac = {
+			0x98, 0x11, 0x57, 0xfe, 0xa5, 0xd0, 0xed, 0x5e,
+			0xc5, 0x7e, 0xb3, 0x53, 0x9d, 0x12, 0x38, 0x41,
+			0x0a, 0x78, 0x75, 0xd4, 0x0f, 0xa6, 0x9f, 0x05,
+			0xd3, 0x2e, 0xcd, 0xad, 0x78, 0xea, 0x09, 0xdc,
+			0xdc, 0x2b, 0x56, 0x41, 0xb1, 0x5a, 0x6b, 0xd8,
+			0x3e, 0xe7, 0xac, 0x01, 0x4b, 0xb8, 0x52, 0x42,
+		},
+	},
+	{
+		.data_len = 128,
+		.key_len = 1024,
+		.mac = {
+			0xaa, 0x48, 0xa9, 0x1a, 0x47, 0xbf, 0x87, 0xec,
+			0x9e, 0xe6, 0x0f, 0x98, 0x2a, 0xb0, 0xa7, 0x84,
+			0x9a, 0x87, 0x5c, 0x75, 0x7e, 0xb5, 0xf1, 0x0a,
+			0x01, 0x20, 0x75, 0xfd, 0xbf, 0xb8, 0x59, 0xad,
+			0x1d, 0xa6, 0x59, 0x2c, 0xf2, 0x5e, 0xfd, 0xdc,
+			0x3c, 0x39, 0x4c, 0xcd, 0x0a, 0x5f, 0xb0, 0x1f,
+		},
+	},
+	{
+		.data_len = 129,
+		.key_len = 0,
+		.mac = {
+			0x0a, 0xa9, 0x08, 0xdf, 0x29, 0xc4, 0x9e, 0xb3,
+			0x80, 0x32, 0xab, 0xf5, 0x61, 0xb2, 0xdf, 0x31,
+			0xc7, 0x7b, 0xb6, 0xb6, 0x30, 0x45, 0x85, 0x6b,
+			0x76, 0xbc, 0x83, 0xfd, 0x94, 0xe5, 0x91, 0x33,
+			0x40, 0x01, 0x2d, 0xcf, 0x22, 0x27, 0x35, 0x5e,
+			0x25, 0xac, 0xfe, 0x14, 0xb4, 0xec, 0x13, 0xa7,
+		},
+	},
+	{
+		.data_len = 256,
+		.key_len = 1,
+		.mac = {
+			0x0d, 0x94, 0xcc, 0xcd, 0xbd, 0x89, 0xdc, 0xb4,
+			0xcf, 0x93, 0x02, 0x8c, 0x1d, 0x37, 0xbd, 0x00,
+			0xa4, 0x9c, 0x24, 0xb2, 0xf7, 0xa5, 0xbf, 0x97,
+			0x5a, 0x9b, 0x27, 0xc2, 0x28, 0xcf, 0xce, 0x3e,
+			0x8d, 0xa0, 0x14, 0x03, 0x64, 0xc2, 0x80, 0xec,
+			0x09, 0xcb, 0x57, 0x81, 0x2f, 0x70, 0x15, 0x1f,
+		},
+	},
+	{
+		.data_len = 511,
+		.key_len = 31,
+		.mac = {
+			0xb7, 0x4b, 0x98, 0x94, 0x29, 0xfd, 0x21, 0xba,
+			0x99, 0xc4, 0x36, 0x2b, 0x8d, 0x71, 0xa5, 0x15,
+			0xd0, 0x2f, 0xc2, 0x4d, 0x15, 0x33, 0xa2, 0x52,
+			0x58, 0x74, 0xe7, 0x40, 0x5e, 0x75, 0x32, 0x70,
+			0x64, 0x7d, 0xce, 0x13, 0xf2, 0x01, 0x38, 0x71,
+			0x0e, 0x8d, 0xea, 0x8b, 0x78, 0x23, 0x65, 0x28,
+		},
+	},
+	{
+		.data_len = 513,
+		.key_len = 32,
+		.mac = {
+			0xba, 0xc4, 0x7a, 0xf3, 0x62, 0xfc, 0x56, 0x8b,
+			0x77, 0xde, 0x56, 0x64, 0x51, 0x0d, 0xaa, 0x50,
+			0x7c, 0x77, 0xbc, 0xd4, 0x44, 0x78, 0x0e, 0xae,
+			0x8a, 0xa2, 0x52, 0x7b, 0x3b, 0x87, 0x5f, 0x66,
+			0xf9, 0x28, 0x6a, 0x0a, 0xd6, 0xbf, 0x40, 0xcf,
+			0xa3, 0xb0, 0x70, 0x60, 0xb1, 0x36, 0x4d, 0x3b,
+		},
+	},
+	{
+		.data_len = 1000,
+		.key_len = 33,
+		.mac = {
+			0xf7, 0x54, 0x6b, 0x0d, 0x52, 0x46, 0x95, 0x1b,
+			0xb2, 0xc1, 0xd9, 0x89, 0x8c, 0xdf, 0x56, 0xfc,
+			0x05, 0xd5, 0x1c, 0x0a, 0x60, 0xef, 0x06, 0xfa,
+			0x40, 0x18, 0xf7, 0xa3, 0xdb, 0x5e, 0xcb, 0x94,
+			0xa7, 0x8f, 0x6f, 0x01, 0x8d, 0x40, 0x83, 0x1e,
+			0x32, 0x22, 0xa5, 0xa6, 0x83, 0xb7, 0x57, 0x9e,
+		},
+	},
+	{
+		.data_len = 3333,
+		.key_len = 64,
+		.mac = {
+			0x46, 0x1f, 0x32, 0xf7, 0x8e, 0x21, 0x52, 0x70,
+			0xe6, 0x45, 0xa4, 0xb5, 0x13, 0x92, 0xbe, 0x5e,
+			0x5b, 0x9e, 0xa8, 0x9a, 0x22, 0x3a, 0x49, 0xbb,
+			0xc5, 0xab, 0xfb, 0x05, 0xed, 0x13, 0xcb, 0xe2,
+			0x71, 0xc1, 0x22, 0xca, 0x3b, 0x65, 0x08, 0xb3,
+			0x9c, 0x1a, 0x03, 0xd0, 0x8e, 0xf8, 0xf0, 0x8b,
+		},
+	},
+	{
+		.data_len = 4096,
+		.key_len = 65,
+		.mac = {
+			0xb4, 0x0d, 0x90, 0x01, 0x69, 0x2b, 0xc8, 0xab,
+			0x6b, 0xe9, 0x8c, 0xa5, 0xa9, 0x46, 0xc0, 0x90,
+			0x84, 0xec, 0x6d, 0x6b, 0x64, 0x88, 0x66, 0x55,
+			0x61, 0x04, 0x2d, 0xd8, 0x30, 0x9a, 0x2f, 0x3b,
+			0x3d, 0xa3, 0x11, 0x50, 0xcc, 0x6a, 0xe4, 0xb2,
+			0x41, 0x18, 0xd7, 0x70, 0x57, 0x01, 0x67, 0x1c,
+		},
+	},
+	{
+		.data_len = 4128,
+		.key_len = 66,
+		.mac = {
+			0xbd, 0x68, 0x84, 0xea, 0x22, 0xbf, 0xe2, 0x0e,
+			0x86, 0x61, 0x5e, 0x58, 0x38, 0xfd, 0xce, 0x91,
+			0x3a, 0x67, 0xda, 0x2b, 0xce, 0x71, 0xaf, 0xbc,
+			0xf2, 0x75, 0xa5, 0xa8, 0xa2, 0xe2, 0x45, 0x12,
+			0xab, 0x67, 0x3d, 0x4e, 0x1c, 0x42, 0xe1, 0x5d,
+			0x6c, 0xb1, 0xd2, 0xb0, 0x16, 0xd5, 0x5c, 0xaf,
+		},
+	},
+	{
+		.data_len = 4160,
+		.key_len = 127,
+		.mac = {
+			0x91, 0xe1, 0x89, 0x46, 0x28, 0x01, 0xe1, 0xd3,
+			0x21, 0x12, 0xda, 0x6e, 0xe0, 0x17, 0x14, 0xd0,
+			0x07, 0x5a, 0x9f, 0xca, 0xad, 0x6a, 0x6b, 0x89,
+			0xf3, 0x6e, 0x21, 0x92, 0x52, 0x18, 0x21, 0x9d,
+			0xc6, 0xe6, 0x5d, 0xca, 0xc3, 0x4d, 0xed, 0xe7,
+			0xb9, 0x51, 0x51, 0x13, 0x12, 0xff, 0x73, 0x91,
+		},
+	},
+	{
+		.data_len = 4224,
+		.key_len = 128,
+		.mac = {
+			0x15, 0x8f, 0xae, 0x57, 0xa2, 0x69, 0xe0, 0xb7,
+			0x15, 0xb2, 0xd9, 0x33, 0xfd, 0x62, 0x5d, 0xc9,
+			0x38, 0xad, 0xc0, 0xbc, 0x9c, 0xd4, 0x8f, 0xed,
+			0x93, 0x2d, 0x66, 0x6b, 0x57, 0x26, 0xda, 0xdc,
+			0x4b, 0x14, 0x00, 0x82, 0x0d, 0x1a, 0x27, 0x37,
+			0xa6, 0x91, 0x61, 0x04, 0x20, 0xc9, 0x6b, 0x61,
+		},
+	},
+	{
+		.data_len = 16384,
+		.key_len = 129,
+		.mac = {
+			0x65, 0x25, 0x4f, 0xfc, 0x9b, 0x4d, 0xe5, 0xd7,
+			0x2c, 0xb7, 0xb1, 0x2f, 0xf9, 0xb7, 0x7b, 0x98,
+			0x80, 0x45, 0x23, 0xdc, 0x0b, 0xd1, 0x76, 0xc1,
+			0x81, 0xfd, 0x89, 0x08, 0x96, 0x9a, 0x35, 0xbd,
+			0x0c, 0x7c, 0x0e, 0x26, 0xab, 0xa4, 0x03, 0x55,
+			0x4d, 0x3a, 0xc0, 0x0a, 0x10, 0x45, 0x1a, 0x46,
+		},
+	},
+};
diff --git a/lib/crypto/tests/sha384_kunit.c b/lib/crypto/tests/sha384_kunit.c
new file mode 100644
index 0000000000000..54c33dd3430d9
--- /dev/null
+++ b/lib/crypto/tests/sha384_kunit.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2025 Google LLC
+ */
+#include <crypto/sha2.h>
+#include "sha384-testvecs.h"
+
+#define HASH sha384
+#define HASH_CTX sha384_ctx
+#define HASH_SIZE SHA384_DIGEST_SIZE
+#define HASH_INIT sha384_init
+#define HASH_UPDATE sha384_update
+#define HASH_FINAL sha384_final
+#define HASH_TESTVECS sha384_testvecs
+#define HMAC_KEY hmac_sha384_key
+#define HMAC_CTX hmac_sha384_ctx
+#define HMAC_SETKEY hmac_sha384_preparekey
+#define HMAC_INIT hmac_sha384_init
+#define HMAC_UPDATE hmac_sha384_update
+#define HMAC_FINAL hmac_sha384_final
+#define HMAC hmac_sha384
+#define HMAC_USINGRAWKEY hmac_sha384_usingrawkey
+#define HMAC_TESTVECS hmac_sha384_testvecs
+#include "hash-test-template.h"
+
+static struct kunit_case hash_test_cases[] = {
+	KUNIT_CASE(test_hash_test_vectors),
+	KUNIT_CASE(test_hash_incremental_updates),
+	KUNIT_CASE(test_hash_buffer_overruns),
+	KUNIT_CASE(test_hash_overlaps),
+	KUNIT_CASE(test_hash_alignment_consistency),
+	KUNIT_CASE(test_hash_interrupt_context),
+	KUNIT_CASE(test_hash_ctx_zeroization),
+	KUNIT_CASE(test_hmac),
+	KUNIT_CASE(benchmark_hash),
+	{},
+};
+
+static struct kunit_suite hash_test_suite = {
+	.name = "sha384",
+	.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-384 and HMAC-SHA384");
+MODULE_LICENSE("GPL");
diff --git a/lib/crypto/tests/sha512-testvecs.h b/lib/crypto/tests/sha512-testvecs.h
new file mode 100644
index 0000000000000..d91e11fd6879e
--- /dev/null
+++ b/lib/crypto/tests/sha512-testvecs.h
@@ -0,0 +1,662 @@
+/* This file was generated by: ./scripts/crypto/gen-hash-testvecs.py sha512 */
+
+static const struct {
+	size_t data_len;
+	u8 digest[SHA512_DIGEST_SIZE];
+} sha512_testvecs[] = {
+	{
+		.data_len = 0,
+		.digest = {
+			0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
+			0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
+			0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
+			0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
+			0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
+			0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
+			0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
+			0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e,
+		},
+	},
+	{
+		.data_len = 1,
+		.digest = {
+			0x12, 0xf2, 0xb6, 0xec, 0x84, 0xa0, 0x8e, 0xcf,
+			0x0d, 0xec, 0x17, 0xfd, 0x1f, 0x91, 0x15, 0x69,
+			0xd2, 0xb9, 0x89, 0xff, 0x89, 0x9d, 0xd9, 0x0b,
+			0x7a, 0x0f, 0x82, 0x94, 0x57, 0x5b, 0xf3, 0x08,
+			0x42, 0x45, 0x23, 0x08, 0x44, 0x54, 0x35, 0x36,
+			0xed, 0x4b, 0xb3, 0xa5, 0xbf, 0x17, 0xc1, 0x3c,
+			0xdd, 0x25, 0x4a, 0x30, 0x64, 0xed, 0x66, 0x06,
+			0x72, 0x05, 0xc2, 0x71, 0x5a, 0x6c, 0xd0, 0x75,
+		},
+	},
+	{
+		.data_len = 2,
+		.digest = {
+			0x01, 0x37, 0x97, 0xcc, 0x0a, 0xcb, 0x61, 0xa4,
+			0x93, 0x26, 0x36, 0x4b, 0xd2, 0x27, 0xea, 0xaf,
+			0xda, 0xfa, 0x8f, 0x86, 0x12, 0x99, 0x7b, 0xc8,
+			0x94, 0xa9, 0x1c, 0x70, 0x3f, 0x43, 0xf3, 0x9a,
+			0x02, 0xc5, 0x0d, 0x8e, 0x01, 0xf8, 0x3a, 0xa6,
+			0xec, 0xaa, 0xc5, 0xc7, 0x9d, 0x3d, 0x7f, 0x9d,
+			0x47, 0x0e, 0x58, 0x2d, 0x9a, 0x2d, 0x51, 0x1d,
+			0xc3, 0x77, 0xb2, 0x7f, 0x69, 0x9a, 0xc3, 0x50,
+		},
+	},
+	{
+		.data_len = 3,
+		.digest = {
+			0xd4, 0xa3, 0xc2, 0x50, 0xa0, 0x33, 0xc6, 0xe4,
+			0x50, 0x08, 0xea, 0xc9, 0xb8, 0x35, 0x55, 0x34,
+			0x61, 0xb8, 0x2e, 0xa2, 0xe5, 0xdc, 0x04, 0x70,
+			0x99, 0x86, 0x5f, 0xee, 0x2e, 0x1e, 0xd4, 0x40,
+			0xf8, 0x88, 0x01, 0x84, 0x97, 0x16, 0x6a, 0xd3,
+			0x0a, 0xb4, 0xe2, 0x34, 0xca, 0x1f, 0xfc, 0x6b,
+			0x61, 0xf3, 0x7f, 0x72, 0xfa, 0x8d, 0x22, 0xcf,
+			0x7f, 0x2d, 0x87, 0x9d, 0xbb, 0x59, 0xac, 0x53,
+		},
+	},
+	{
+		.data_len = 16,
+		.digest = {
+			0x3b, 0xae, 0x66, 0x48, 0x0f, 0x35, 0x3c, 0xcd,
+			0x92, 0xa9, 0xb6, 0xb9, 0xfe, 0x19, 0x90, 0x92,
+			0x52, 0xa5, 0x02, 0xd1, 0x89, 0xcf, 0x98, 0x86,
+			0x29, 0x28, 0xab, 0xc4, 0x9e, 0xcc, 0x75, 0x38,
+			0x95, 0xa7, 0x59, 0x43, 0xef, 0x8c, 0x3a, 0xeb,
+			0x40, 0xa3, 0xbe, 0x2b, 0x75, 0x0d, 0xfd, 0xc3,
+			0xaf, 0x69, 0x08, 0xad, 0x9f, 0xc9, 0xf4, 0x96,
+			0xa9, 0xc2, 0x2b, 0x1b, 0x66, 0x6f, 0x1d, 0x28,
+		},
+	},
+	{
+		.data_len = 32,
+		.digest = {
+			0x9c, 0xfb, 0x3c, 0x40, 0xd5, 0x3b, 0xc4, 0xff,
+			0x07, 0xa7, 0xf0, 0x24, 0xb7, 0xd6, 0x5e, 0x12,
+			0x5b, 0x85, 0xb5, 0xa5, 0xe0, 0x82, 0xa6, 0xda,
+			0x30, 0x13, 0x2f, 0x1a, 0xe3, 0xd0, 0x55, 0xcb,
+			0x14, 0x19, 0xe2, 0x09, 0x91, 0x96, 0x26, 0xf9,
+			0x38, 0xd7, 0xfa, 0x4a, 0xfb, 0x2f, 0x6f, 0xc0,
+			0xf4, 0x95, 0xc3, 0x40, 0xf6, 0xdb, 0xe7, 0xc2,
+			0x79, 0x23, 0xa4, 0x20, 0x96, 0x3a, 0x00, 0xbb,
+		},
+	},
+	{
+		.data_len = 48,
+		.digest = {
+			0x92, 0x1a, 0x21, 0x06, 0x6e, 0x08, 0x84, 0x09,
+			0x23, 0x8d, 0x63, 0xec, 0xd6, 0x72, 0xd3, 0x21,
+			0x51, 0xe8, 0x65, 0x94, 0xf8, 0x1f, 0x5f, 0xa7,
+			0xab, 0x6b, 0xae, 0x1c, 0x2c, 0xaf, 0xf9, 0x0c,
+			0x7c, 0x5a, 0x74, 0x1d, 0x90, 0x26, 0x4a, 0xc3,
+			0xa1, 0x60, 0xf4, 0x1d, 0xd5, 0x3c, 0x86, 0xe8,
+			0x00, 0xb3, 0x99, 0x27, 0xb8, 0x9d, 0x3e, 0x17,
+			0x32, 0x5a, 0x34, 0x3e, 0xc2, 0xb2, 0x6e, 0xbd,
+		},
+	},
+	{
+		.data_len = 49,
+		.digest = {
+			0x5a, 0x1f, 0x40, 0x5f, 0xee, 0xf2, 0xdd, 0x67,
+			0x01, 0xcb, 0x26, 0x58, 0xf5, 0x1b, 0xe8, 0x7e,
+			0xeb, 0x7d, 0x9d, 0xef, 0xd3, 0x55, 0xd6, 0x89,
+			0x2e, 0xfc, 0x14, 0xe2, 0x98, 0x4c, 0x31, 0xaa,
+			0x69, 0x00, 0xf9, 0x4e, 0xb0, 0x75, 0x1b, 0x71,
+			0x93, 0x60, 0xdf, 0xa1, 0xaf, 0xba, 0xc2, 0xd3,
+			0x6a, 0x22, 0xa0, 0xff, 0xb5, 0x66, 0x15, 0x66,
+			0xd2, 0x24, 0x9a, 0x7e, 0xe4, 0xe5, 0x84, 0xdb,
+		},
+	},
+	{
+		.data_len = 63,
+		.digest = {
+			0x32, 0xbd, 0xcf, 0x72, 0xa9, 0x74, 0x87, 0xe6,
+			0x2a, 0x53, 0x7e, 0x6d, 0xac, 0xc2, 0xdd, 0x2c,
+			0x87, 0xb3, 0xf7, 0x90, 0x29, 0xc9, 0x16, 0x59,
+			0xd2, 0x7e, 0x6e, 0x84, 0x1d, 0xa6, 0xaf, 0x3c,
+			0xca, 0xd6, 0x1a, 0x24, 0xa4, 0xcd, 0x59, 0x44,
+			0x20, 0xd7, 0xd2, 0x5b, 0x97, 0xda, 0xd5, 0xa9,
+			0x23, 0xb1, 0xa4, 0x60, 0xb8, 0x05, 0x98, 0xdc,
+			0xef, 0x89, 0x81, 0xe3, 0x3a, 0xf9, 0x24, 0x37,
+		},
+	},
+	{
+		.data_len = 64,
+		.digest = {
+			0x96, 0x3a, 0x1a, 0xdd, 0x1b, 0xeb, 0x1a, 0x55,
+			0x24, 0x52, 0x3d, 0xec, 0x9d, 0x52, 0x2e, 0xa6,
+			0xfe, 0x81, 0xd6, 0x98, 0xac, 0xcc, 0x60, 0x56,
+			0x04, 0x9d, 0xa3, 0xf3, 0x56, 0x05, 0xe4, 0x8a,
+			0x61, 0xaf, 0x6f, 0x6e, 0x8e, 0x75, 0x67, 0x3a,
+			0xd2, 0xb0, 0x85, 0x2d, 0x17, 0xd2, 0x86, 0x8c,
+			0x50, 0x4b, 0xdd, 0xef, 0x35, 0x00, 0xde, 0x29,
+			0x3d, 0x4b, 0x04, 0x12, 0x8a, 0x81, 0xe2, 0xcc,
+		},
+	},
+	{
+		.data_len = 65,
+		.digest = {
+			0x9c, 0x6e, 0xf0, 0x6f, 0x71, 0x77, 0xd5, 0xd0,
+			0xbb, 0x70, 0x1f, 0xcb, 0xbd, 0xd3, 0xfe, 0x23,
+			0x71, 0x78, 0xad, 0x3a, 0xd2, 0x1e, 0x34, 0xf4,
+			0x6d, 0xb4, 0xa2, 0x0a, 0x24, 0xcb, 0xe1, 0x99,
+			0x07, 0xd0, 0x79, 0x8f, 0x7e, 0x69, 0x31, 0x68,
+			0x29, 0xb5, 0x85, 0x82, 0x67, 0xdc, 0x4a, 0x8d,
+			0x44, 0x04, 0x02, 0xc0, 0xfb, 0xd2, 0x19, 0x66,
+			0x1e, 0x25, 0x8b, 0xd2, 0x5a, 0x59, 0x68, 0xc0,
+		},
+	},
+	{
+		.data_len = 127,
+		.digest = {
+			0xb8, 0x8f, 0xa8, 0x29, 0x4d, 0xcf, 0x5f, 0x73,
+			0x3c, 0x55, 0x43, 0xd9, 0x1c, 0xbc, 0x0c, 0x17,
+			0x75, 0x0b, 0xc7, 0xb1, 0x1d, 0x9f, 0x7b, 0x2f,
+			0x4c, 0x3d, 0x2a, 0x71, 0xfb, 0x1b, 0x0e, 0xca,
+			0x4e, 0x96, 0xa0, 0x95, 0xee, 0xf4, 0x93, 0x76,
+			0x36, 0xfb, 0x5d, 0xd3, 0x46, 0xc4, 0x1d, 0x41,
+			0x32, 0x92, 0x9d, 0xed, 0xdb, 0x7f, 0xfa, 0xb3,
+			0x91, 0x61, 0x3e, 0xd6, 0xb2, 0xca, 0x8d, 0x81,
+		},
+	},
+	{
+		.data_len = 128,
+		.digest = {
+			0x54, 0xac, 0x1a, 0xa1, 0xa6, 0xa3, 0x47, 0x2a,
+			0x5a, 0xac, 0x1a, 0x3a, 0x4b, 0xa1, 0x11, 0x08,
+			0xa7, 0x90, 0xec, 0x52, 0xcb, 0xaf, 0x68, 0x41,
+			0x38, 0x44, 0x53, 0x94, 0x93, 0x30, 0xaf, 0x3a,
+			0xec, 0x99, 0x3a, 0x7d, 0x2a, 0xd5, 0xb6, 0x05,
+			0xf5, 0xa6, 0xbb, 0x9b, 0x82, 0xc2, 0xbd, 0x98,
+			0x28, 0x62, 0x98, 0x3e, 0xe4, 0x27, 0x9b, 0xaa,
+			0xce, 0x0a, 0x6f, 0xab, 0x1b, 0x16, 0xf3, 0xdd,
+		},
+	},
+	{
+		.data_len = 129,
+		.digest = {
+			0x04, 0x37, 0x60, 0xbc, 0xb3, 0xb1, 0xc6, 0x2d,
+			0x42, 0xc5, 0xd7, 0x7e, 0xd9, 0x86, 0x82, 0xe0,
+			0xf4, 0x62, 0xad, 0x75, 0x68, 0x0b, 0xc7, 0xa8,
+			0xd6, 0x9a, 0x76, 0xe5, 0x29, 0xb8, 0x37, 0x30,
+			0x0f, 0xc0, 0xbc, 0x81, 0x94, 0x7c, 0x13, 0xf4,
+			0x9c, 0x27, 0xbc, 0x59, 0xa1, 0x70, 0x6a, 0x87,
+			0x20, 0x12, 0x0a, 0x2a, 0x62, 0x5e, 0x6f, 0xca,
+			0x91, 0x6b, 0x34, 0x7e, 0x4c, 0x0d, 0xf0, 0x6c,
+		},
+	},
+	{
+		.data_len = 256,
+		.digest = {
+			0x4b, 0x7c, 0x1f, 0x53, 0x52, 0xcc, 0x30, 0xed,
+			0x91, 0x44, 0x6f, 0x0d, 0xb5, 0x41, 0x79, 0x99,
+			0xaf, 0x82, 0x65, 0x52, 0x03, 0xf8, 0x55, 0x74,
+			0x7c, 0xd9, 0x41, 0xd6, 0xe8, 0x91, 0xa4, 0x85,
+			0xcb, 0x0a, 0x60, 0x08, 0x76, 0x07, 0x60, 0x99,
+			0x89, 0x76, 0xba, 0x84, 0xbd, 0x0b, 0xf2, 0xb3,
+			0xdc, 0xf3, 0x33, 0xd1, 0x9b, 0x0b, 0x2e, 0x5d,
+			0xf6, 0x9d, 0x0f, 0x67, 0xf4, 0x86, 0xb3, 0xd5,
+		},
+	},
+	{
+		.data_len = 511,
+		.digest = {
+			0x7d, 0x83, 0x78, 0x6a, 0x5d, 0x52, 0x42, 0x2a,
+			0xb1, 0x97, 0xc6, 0x62, 0xa2, 0x2a, 0x7c, 0x8b,
+			0xcd, 0x4f, 0xa4, 0x86, 0x19, 0xa4, 0x5b, 0x1d,
+			0xc7, 0x6f, 0x2f, 0x9c, 0x03, 0xc3, 0x45, 0x2e,
+			0xa7, 0x8e, 0x38, 0xf2, 0x57, 0x55, 0x89, 0x47,
+			0xed, 0xeb, 0x81, 0xe2, 0xe0, 0x55, 0x9f, 0xe6,
+			0xca, 0x03, 0x59, 0xd3, 0xd4, 0xba, 0xc9, 0x2d,
+			0xaf, 0xbb, 0x62, 0x2e, 0xe6, 0x89, 0xe4, 0x11,
+		},
+	},
+	{
+		.data_len = 513,
+		.digest = {
+			0xe9, 0x14, 0xe7, 0x01, 0xd0, 0x81, 0x09, 0x51,
+			0x78, 0x1c, 0x8e, 0x6c, 0x00, 0xd3, 0x28, 0xa0,
+			0x2a, 0x7b, 0xd6, 0x25, 0xca, 0xd0, 0xf9, 0xb8,
+			0xd8, 0xcf, 0xd0, 0xb7, 0x48, 0x25, 0xb7, 0x6a,
+			0x53, 0x8e, 0xf8, 0x52, 0x9c, 0x1f, 0x7d, 0xae,
+			0x4c, 0x22, 0xd5, 0x9d, 0xf0, 0xaf, 0x98, 0x91,
+			0x19, 0x1f, 0x99, 0xbd, 0xa6, 0xc2, 0x0f, 0x05,
+			0xa5, 0x9f, 0x3e, 0x87, 0xed, 0xc3, 0xab, 0x92,
+		},
+	},
+	{
+		.data_len = 1000,
+		.digest = {
+			0x2e, 0xf4, 0x72, 0xd2, 0xd9, 0x4a, 0xd5, 0xf9,
+			0x20, 0x03, 0x4a, 0xad, 0xed, 0xa9, 0x1b, 0x64,
+			0x73, 0x38, 0xc6, 0x30, 0xa8, 0x7f, 0xf9, 0x3b,
+			0x8c, 0xbc, 0xa1, 0x2d, 0x22, 0x7b, 0x84, 0x37,
+			0xf5, 0xba, 0xee, 0xf0, 0x80, 0x9d, 0xe3, 0x82,
+			0xbd, 0x07, 0x68, 0x15, 0x01, 0x22, 0xf6, 0x88,
+			0x07, 0x0b, 0xfd, 0xb7, 0xb1, 0xc0, 0x68, 0x4b,
+			0x8d, 0x05, 0xec, 0xfb, 0xcd, 0xde, 0xa4, 0x2a,
+		},
+	},
+	{
+		.data_len = 3333,
+		.digest = {
+			0x73, 0xe3, 0xe5, 0x87, 0x01, 0x0a, 0x29, 0x4d,
+			0xad, 0x92, 0x67, 0x64, 0xc7, 0x71, 0x0b, 0x22,
+			0x80, 0x8a, 0x6e, 0x8b, 0x20, 0x73, 0xb2, 0xd7,
+			0x98, 0x20, 0x35, 0x42, 0x42, 0x5d, 0x85, 0x12,
+			0xb0, 0x06, 0x69, 0x63, 0x5f, 0x5b, 0xe7, 0x63,
+			0x6f, 0xe6, 0x18, 0xa6, 0xc1, 0xa6, 0xae, 0x27,
+			0xa7, 0x6a, 0x73, 0x6b, 0x27, 0xd5, 0x47, 0xe1,
+			0xa2, 0x7d, 0xe4, 0x0d, 0xbd, 0x23, 0x7b, 0x7a,
+		},
+	},
+	{
+		.data_len = 4096,
+		.digest = {
+			0x11, 0x5b, 0x77, 0x36, 0x6b, 0x3b, 0xe4, 0x42,
+			0xe4, 0x92, 0x23, 0xcb, 0x0c, 0x06, 0xff, 0xb7,
+			0x0c, 0x71, 0x64, 0xd9, 0x8a, 0x57, 0x75, 0x7b,
+			0xa2, 0xd2, 0x17, 0x19, 0xbb, 0xb5, 0x3c, 0xb3,
+			0x5f, 0xae, 0x35, 0x75, 0x8e, 0xa8, 0x97, 0x43,
+			0xce, 0xfe, 0x41, 0x84, 0xfe, 0xcb, 0x18, 0x70,
+			0x68, 0x2e, 0x16, 0x19, 0xd5, 0x10, 0x0d, 0x2f,
+			0x61, 0x87, 0x79, 0xee, 0x5f, 0x24, 0xdd, 0x76,
+		},
+	},
+	{
+		.data_len = 4128,
+		.digest = {
+			0x9e, 0x96, 0xe1, 0x0a, 0xb2, 0xd5, 0xba, 0xcf,
+			0x27, 0xba, 0x6f, 0x85, 0xe9, 0xbf, 0x96, 0xb9,
+			0x5a, 0x00, 0x00, 0x06, 0xdc, 0xb7, 0xaf, 0x0a,
+			0x8f, 0x1d, 0x31, 0xf6, 0xce, 0xc3, 0x50, 0x2e,
+			0x61, 0x3a, 0x8b, 0x28, 0xaf, 0xb2, 0x50, 0x0d,
+			0x00, 0x98, 0x02, 0x11, 0x6b, 0xfa, 0x51, 0xc1,
+			0xde, 0xe1, 0x34, 0x9f, 0xda, 0x11, 0x63, 0xfa,
+			0x0a, 0xa0, 0xa2, 0x67, 0x39, 0xeb, 0x9b, 0xf1,
+		},
+	},
+	{
+		.data_len = 4160,
+		.digest = {
+			0x46, 0x4e, 0x81, 0xd1, 0x08, 0x2a, 0x46, 0x12,
+			0x4e, 0xae, 0x1f, 0x5d, 0x57, 0xe5, 0x19, 0xbc,
+			0x76, 0x38, 0xb6, 0xa7, 0xe3, 0x72, 0x6d, 0xaf,
+			0x80, 0x3b, 0xd0, 0xbc, 0x06, 0xe8, 0xab, 0xab,
+			0x86, 0x4b, 0x0b, 0x7a, 0x61, 0xa6, 0x13, 0xff,
+			0x64, 0x47, 0x89, 0xb7, 0x63, 0x8a, 0xa5, 0x4c,
+			0x9f, 0x52, 0x70, 0xeb, 0x21, 0xe5, 0x2d, 0xe9,
+			0xe7, 0xab, 0x1c, 0x0e, 0x74, 0xf5, 0x72, 0xec,
+		},
+	},
+	{
+		.data_len = 4224,
+		.digest = {
+			0xfa, 0x6e, 0xff, 0x3c, 0xc1, 0x98, 0x49, 0x42,
+			0x34, 0x67, 0xd4, 0xd3, 0xfa, 0xae, 0x27, 0xe4,
+			0x77, 0x11, 0x84, 0xd2, 0x57, 0x99, 0xf8, 0xfd,
+			0x41, 0x50, 0x84, 0x80, 0x7f, 0xf7, 0xb2, 0xd3,
+			0x88, 0x21, 0x9c, 0xe8, 0xb9, 0x05, 0xd3, 0x48,
+			0x64, 0xc5, 0xb7, 0x29, 0xd9, 0x21, 0x17, 0xad,
+			0x89, 0x9c, 0x79, 0x55, 0x51, 0x0b, 0x96, 0x3e,
+			0x10, 0x40, 0xe1, 0xdd, 0x7b, 0x39, 0x40, 0x86,
+		},
+	},
+	{
+		.data_len = 16384,
+		.digest = {
+			0x41, 0xb3, 0xd2, 0x93, 0xcd, 0x79, 0x84, 0xc2,
+			0xf5, 0xea, 0xf3, 0xb3, 0x94, 0x23, 0xaa, 0x76,
+			0x87, 0x5f, 0xe3, 0xd2, 0x03, 0xd8, 0x00, 0xbb,
+			0xa1, 0x55, 0xe4, 0xcb, 0x16, 0x04, 0x5b, 0xdf,
+			0xf8, 0xd2, 0x63, 0x51, 0x02, 0x22, 0xc6, 0x0f,
+			0x98, 0x2b, 0x12, 0x52, 0x25, 0x64, 0x93, 0xd9,
+			0xab, 0xe9, 0x4d, 0x16, 0x4b, 0xf6, 0x09, 0x83,
+			0x5c, 0x63, 0x1c, 0x41, 0x19, 0xf6, 0x76, 0xe3,
+		},
+	},
+};
+
+static const struct {
+	size_t data_len;
+	size_t key_len;
+	u8 mac[SHA512_DIGEST_SIZE];
+} hmac_sha512_testvecs[] = {
+	{
+		.data_len = 0,
+		.key_len = 0,
+		.mac = {
+			0xb9, 0x36, 0xce, 0xe8, 0x6c, 0x9f, 0x87, 0xaa,
+			0x5d, 0x3c, 0x6f, 0x2e, 0x84, 0xcb, 0x5a, 0x42,
+			0x39, 0xa5, 0xfe, 0x50, 0x48, 0x0a, 0x6e, 0xc6,
+			0x6b, 0x70, 0xab, 0x5b, 0x1f, 0x4a, 0xc6, 0x73,
+			0x0c, 0x6c, 0x51, 0x54, 0x21, 0xb3, 0x27, 0xec,
+			0x1d, 0x69, 0x40, 0x2e, 0x53, 0xdf, 0xb4, 0x9a,
+			0xd7, 0x38, 0x1e, 0xb0, 0x67, 0xb3, 0x38, 0xfd,
+			0x7b, 0x0c, 0xb2, 0x22, 0x47, 0x22, 0x5d, 0x47,
+		},
+	},
+	{
+		.data_len = 1,
+		.key_len = 1,
+		.mac = {
+			0x1b, 0xee, 0x4e, 0x7f, 0x67, 0xb3, 0x40, 0x78,
+			0xd6, 0x68, 0x16, 0xf9, 0x84, 0xf1, 0xcf, 0x0e,
+			0xca, 0x51, 0x26, 0xb4, 0x50, 0x6d, 0xa9, 0xe4,
+			0x78, 0x1b, 0xac, 0x7c, 0xe2, 0xe1, 0x5b, 0x75,
+			0x85, 0xb8, 0xe3, 0xfa, 0x9a, 0x8d, 0x30, 0x46,
+			0x78, 0x0c, 0x86, 0xc6, 0x72, 0x2b, 0xb9, 0xac,
+			0xda, 0xe4, 0x37, 0x00, 0x8f, 0xad, 0x69, 0xf7,
+			0xb7, 0x3a, 0x25, 0xcb, 0x3a, 0x24, 0xe3, 0x8e,
+		},
+	},
+	{
+		.data_len = 2,
+		.key_len = 31,
+		.mac = {
+			0x39, 0xb9, 0xad, 0xca, 0xe2, 0xf1, 0x2f, 0x29,
+			0x4c, 0x52, 0x55, 0x7f, 0x0c, 0xe0, 0x6f, 0x90,
+			0x10, 0x4e, 0xe1, 0x2b, 0x08, 0x9c, 0x13, 0x9a,
+			0x09, 0xb2, 0x0f, 0x26, 0x26, 0xa9, 0x41, 0x54,
+			0x06, 0xa0, 0x8f, 0x81, 0xba, 0x22, 0xae, 0x01,
+			0xf8, 0x3b, 0x50, 0x46, 0x46, 0xf6, 0x8a, 0xc4,
+			0x17, 0x84, 0xf4, 0x8c, 0x4e, 0x40, 0xa2, 0x26,
+			0x3e, 0x5b, 0x81, 0x42, 0xef, 0xee, 0xb9, 0xdb,
+		},
+	},
+	{
+		.data_len = 3,
+		.key_len = 32,
+		.mac = {
+			0x90, 0x82, 0xb5, 0x56, 0xb1, 0x0b, 0x23, 0x38,
+			0xb4, 0x26, 0x99, 0x7a, 0x4e, 0x3e, 0x3a, 0x0b,
+			0x36, 0x0a, 0x03, 0xc9, 0x79, 0xba, 0x37, 0x8f,
+			0xab, 0x42, 0x6f, 0x51, 0x5f, 0x8e, 0x75, 0x0d,
+			0x7e, 0xd5, 0x2b, 0xa7, 0x0b, 0x53, 0xe7, 0xab,
+			0x95, 0x8a, 0x01, 0x80, 0x8a, 0x55, 0x28, 0x30,
+			0x2f, 0x4f, 0xef, 0x7e, 0x60, 0xe2, 0xe5, 0xf2,
+			0x52, 0xc7, 0xae, 0xf2, 0xe4, 0x96, 0x16, 0xf2,
+		},
+	},
+	{
+		.data_len = 16,
+		.key_len = 33,
+		.mac = {
+			0x51, 0x34, 0xa4, 0xe8, 0x53, 0xab, 0xf3, 0xa4,
+			0x78, 0x78, 0xff, 0xbe, 0xaa, 0x8f, 0xf0, 0xad,
+			0xb9, 0x6d, 0x87, 0x7d, 0x43, 0x76, 0x60, 0x71,
+			0x10, 0xbc, 0x7b, 0x99, 0x48, 0xc8, 0xf4, 0x78,
+			0xe5, 0xd0, 0x28, 0x06, 0x75, 0x60, 0xa0, 0xbd,
+			0xd5, 0xdc, 0xb6, 0x74, 0x7f, 0x2e, 0x4b, 0xd8,
+			0xc9, 0x58, 0x64, 0xe2, 0x40, 0xf0, 0xe8, 0xaf,
+			0x2e, 0x4b, 0x2f, 0xe8, 0xa6, 0x29, 0xc4, 0xcf,
+		},
+	},
+	{
+		.data_len = 32,
+		.key_len = 64,
+		.mac = {
+			0x08, 0x7e, 0xc1, 0x64, 0xe4, 0xa7, 0xe2, 0xb7,
+			0x32, 0x86, 0xd8, 0x68, 0x96, 0x20, 0x6c, 0x88,
+			0x62, 0x8f, 0xe4, 0x93, 0xd4, 0x18, 0x11, 0xce,
+			0x2d, 0x58, 0xaa, 0x3b, 0xa0, 0xd7, 0x19, 0x67,
+			0xb4, 0x5d, 0x43, 0x0d, 0x98, 0x09, 0x75, 0x73,
+			0xbf, 0xb3, 0xa4, 0x68, 0x84, 0x47, 0x14, 0x65,
+			0x11, 0xa8, 0xc6, 0x65, 0x19, 0x53, 0x31, 0x96,
+			0x4e, 0x51, 0x42, 0x50, 0x76, 0x3a, 0xa3, 0x03,
+		},
+	},
+	{
+		.data_len = 48,
+		.key_len = 65,
+		.mac = {
+			0x29, 0xd3, 0x6d, 0x5f, 0x4f, 0x3e, 0x99, 0xa7,
+			0x70, 0x9e, 0xe8, 0xfb, 0x26, 0xbd, 0xcb, 0xff,
+			0x45, 0xa2, 0x77, 0x4a, 0x5d, 0xaa, 0xd0, 0xa6,
+			0xc5, 0xaf, 0xca, 0xda, 0xbc, 0x93, 0x5f, 0xd2,
+			0x5d, 0x9d, 0x71, 0xb1, 0x5f, 0x92, 0x66, 0xc0,
+			0xe8, 0x62, 0x69, 0x86, 0x1d, 0xb4, 0xcd, 0x53,
+			0x3e, 0xf4, 0x51, 0xbc, 0x32, 0x65, 0x06, 0x6c,
+			0x71, 0x2a, 0x12, 0xcc, 0x04, 0x10, 0x44, 0x1d,
+		},
+	},
+	{
+		.data_len = 49,
+		.key_len = 66,
+		.mac = {
+			0x2f, 0xb9, 0x24, 0x49, 0x5c, 0x68, 0x92, 0x3e,
+			0xfd, 0x3a, 0x47, 0x96, 0xb0, 0x76, 0xab, 0x3e,
+			0x19, 0xb4, 0x64, 0xcf, 0x3a, 0x83, 0x18, 0xf7,
+			0xb4, 0xa1, 0xb7, 0xcb, 0xd4, 0xea, 0x4b, 0x33,
+			0x68, 0x5f, 0x7a, 0x29, 0xa8, 0x08, 0x3d, 0x64,
+			0x09, 0x7a, 0x8e, 0xe1, 0x6f, 0xbb, 0x22, 0xba,
+			0xd9, 0xec, 0xd8, 0x46, 0xd2, 0x8e, 0xd8, 0xf6,
+			0xf8, 0x39, 0x55, 0x36, 0xe4, 0x8d, 0x7a, 0xb6,
+		},
+	},
+	{
+		.data_len = 63,
+		.key_len = 127,
+		.mac = {
+			0xf7, 0x10, 0xdc, 0xc9, 0x08, 0xca, 0x65, 0x98,
+			0xb5, 0xa5, 0x04, 0x1b, 0xce, 0x0f, 0xe6, 0x13,
+			0x55, 0x93, 0x3b, 0x73, 0xc9, 0x83, 0xb2, 0x99,
+			0x0a, 0xd6, 0xbb, 0x75, 0x92, 0x46, 0x96, 0xa0,
+			0x28, 0x8f, 0xf0, 0xb0, 0x0c, 0x43, 0xcc, 0x45,
+			0x77, 0xc9, 0xda, 0x0a, 0x63, 0x45, 0x4e, 0xc0,
+			0x59, 0x53, 0xba, 0xbe, 0xbc, 0x56, 0x6c, 0xee,
+			0x7a, 0x1e, 0x54, 0xd1, 0x6b, 0xc0, 0xe8, 0x58,
+		},
+	},
+	{
+		.data_len = 64,
+		.key_len = 128,
+		.mac = {
+			0x3b, 0x7d, 0x49, 0x7b, 0x8e, 0x67, 0x2f, 0xe1,
+			0x71, 0xd9, 0x3f, 0xbd, 0x61, 0xd1, 0x51, 0x4b,
+			0xd7, 0xa8, 0x6d, 0x27, 0x94, 0x9c, 0x55, 0x87,
+			0x51, 0xaa, 0xce, 0xbc, 0x0e, 0x13, 0x38, 0x85,
+			0x80, 0x20, 0x9a, 0x86, 0x7c, 0x6f, 0x6d, 0x40,
+			0xf9, 0xff, 0xde, 0x17, 0x38, 0x40, 0xe3, 0xc3,
+			0xf2, 0x58, 0xd4, 0xf8, 0x0d, 0x2f, 0x8c, 0x1e,
+			0xcd, 0x27, 0xac, 0x87, 0xd9, 0x47, 0x25, 0x52,
+		},
+	},
+	{
+		.data_len = 65,
+		.key_len = 129,
+		.mac = {
+			0x74, 0xac, 0x10, 0x6b, 0x4d, 0x68, 0xbb, 0x6c,
+			0xc8, 0x14, 0x23, 0xd9, 0xfa, 0xd1, 0xbe, 0x40,
+			0xac, 0x85, 0x8c, 0xcd, 0x75, 0xbf, 0x4e, 0x51,
+			0xe7, 0x72, 0x6e, 0x64, 0xb1, 0x36, 0x97, 0xee,
+			0xc3, 0x1c, 0xdc, 0x8a, 0x07, 0x79, 0xc6, 0xac,
+			0x4d, 0x2b, 0x53, 0xca, 0x91, 0xac, 0xa4, 0x85,
+			0x7f, 0x08, 0x6c, 0x2c, 0x7a, 0xa8, 0x5c, 0xb3,
+			0x28, 0x5f, 0x3c, 0xf1, 0x26, 0x6a, 0x2a, 0xaf,
+		},
+	},
+	{
+		.data_len = 127,
+		.key_len = 1000,
+		.mac = {
+			0x68, 0xb9, 0x3b, 0x1c, 0x35, 0x75, 0x84, 0xe7,
+			0x00, 0xcb, 0x23, 0xa6, 0x40, 0xb2, 0x4b, 0x2c,
+			0x39, 0x63, 0x61, 0xf1, 0x71, 0x57, 0xd4, 0xd8,
+			0xa3, 0xdd, 0xcb, 0xca, 0x7e, 0x7d, 0x14, 0xf7,
+			0x85, 0xbe, 0xc6, 0xce, 0x51, 0x55, 0x60, 0xe0,
+			0x84, 0x3e, 0xda, 0xec, 0x39, 0x19, 0x82, 0xc1,
+			0x3e, 0xac, 0x0c, 0x5c, 0x9a, 0x40, 0x5e, 0xa2,
+			0xfa, 0x4e, 0xe2, 0x65, 0xc3, 0x17, 0x7d, 0x60,
+		},
+	},
+	{
+		.data_len = 128,
+		.key_len = 1024,
+		.mac = {
+			0x76, 0xe0, 0x17, 0x27, 0x0a, 0xed, 0xfa, 0xfb,
+			0x51, 0xc7, 0x52, 0x19, 0xbe, 0xbe, 0xe3, 0x1a,
+			0x28, 0xc0, 0x28, 0xe0, 0x0c, 0x94, 0xb6, 0x3a,
+			0x50, 0x06, 0x78, 0x5f, 0x04, 0x2a, 0x98, 0x19,
+			0x96, 0xb6, 0x98, 0xc7, 0x26, 0x50, 0x60, 0xd0,
+			0x52, 0x3f, 0x48, 0xc0, 0x06, 0x2d, 0xf4, 0xcc,
+			0xe9, 0x62, 0x5e, 0x12, 0xff, 0x4e, 0x8f, 0x41,
+			0x48, 0xe6, 0x92, 0xac, 0x84, 0x82, 0x12, 0x92,
+		},
+	},
+	{
+		.data_len = 129,
+		.key_len = 0,
+		.mac = {
+			0x9e, 0xe3, 0x94, 0xcb, 0x6d, 0x88, 0x3a, 0x47,
+			0xc4, 0xdd, 0xdb, 0xf0, 0x38, 0x01, 0x22, 0x4c,
+			0xcc, 0x5f, 0x2f, 0x73, 0xf6, 0x0d, 0xa9, 0xf2,
+			0x29, 0xbe, 0xc9, 0x37, 0xeb, 0x5c, 0xb0, 0x90,
+			0x86, 0x0a, 0x86, 0x48, 0xff, 0xf7, 0xd7, 0xd8,
+			0x4d, 0x6e, 0xbf, 0x72, 0xa6, 0x67, 0xee, 0xf7,
+			0x9d, 0x29, 0x96, 0x02, 0x4e, 0x17, 0x8a, 0x32,
+			0x1e, 0x59, 0xeb, 0xfb, 0xd6, 0xd7, 0xaa, 0x7d,
+		},
+	},
+	{
+		.data_len = 256,
+		.key_len = 1,
+		.mac = {
+			0x07, 0x2e, 0xcc, 0x0e, 0xd3, 0xd4, 0xf2, 0xbc,
+			0xb1, 0xd1, 0x57, 0x66, 0x06, 0xce, 0x64, 0xd4,
+			0x0a, 0x62, 0xd4, 0x84, 0x5c, 0x88, 0x27, 0xa1,
+			0x5c, 0x0d, 0xb5, 0x1e, 0xf4, 0x3e, 0x79, 0x6a,
+			0x6e, 0x50, 0x8f, 0x39, 0xe6, 0x8b, 0xed, 0x9b,
+			0x0d, 0xe4, 0x32, 0xd6, 0x72, 0xfd, 0x17, 0x33,
+			0x92, 0xb6, 0x88, 0xfd, 0xe0, 0xfb, 0x85, 0x39,
+			0x27, 0xc7, 0x96, 0xad, 0x8a, 0x68, 0xf7, 0xde,
+		},
+	},
+	{
+		.data_len = 511,
+		.key_len = 31,
+		.mac = {
+			0xc2, 0xef, 0x28, 0xbd, 0xf6, 0x30, 0x74, 0xed,
+			0xfd, 0x2e, 0x52, 0x30, 0xf3, 0xcb, 0x42, 0x75,
+			0x58, 0x35, 0x2c, 0xad, 0x2a, 0x5b, 0x73, 0xa3,
+			0xe0, 0x18, 0x0b, 0x96, 0x7e, 0x07, 0xce, 0x1e,
+			0xf1, 0xe3, 0x08, 0x31, 0x6f, 0x18, 0x79, 0xa0,
+			0x5e, 0xbc, 0xad, 0x15, 0xce, 0x32, 0xef, 0x78,
+			0x1c, 0x3e, 0x83, 0xb6, 0xa0, 0x41, 0xf0, 0x26,
+			0xdd, 0xe2, 0x7d, 0xec, 0x99, 0x4a, 0x73, 0xe2,
+		},
+	},
+	{
+		.data_len = 513,
+		.key_len = 32,
+		.mac = {
+			0x11, 0x35, 0x64, 0x72, 0x68, 0x9b, 0xd3, 0xd8,
+			0x09, 0x54, 0x99, 0x32, 0x63, 0x6c, 0x45, 0x13,
+			0x70, 0x71, 0x34, 0xd3, 0x56, 0x9c, 0xbd, 0x10,
+			0x8f, 0x33, 0xbe, 0xe8, 0x60, 0x14, 0x59, 0x8b,
+			0x23, 0xee, 0xeb, 0xc8, 0x72, 0xfe, 0x1b, 0x88,
+			0x9e, 0xd7, 0xf3, 0x6c, 0xd8, 0xe9, 0x73, 0xd0,
+			0xfe, 0xa2, 0x9a, 0xc8, 0xb1, 0xf7, 0x65, 0x48,
+			0xd0, 0x53, 0x31, 0x82, 0x04, 0xd5, 0x9d, 0x44,
+		},
+	},
+	{
+		.data_len = 1000,
+		.key_len = 33,
+		.mac = {
+			0x02, 0x25, 0xf7, 0x45, 0x56, 0xd1, 0x99, 0xf2,
+			0xfb, 0x9b, 0x8c, 0x64, 0xac, 0x85, 0x6c, 0x6c,
+			0x4b, 0x2e, 0x03, 0x0d, 0x78, 0x2d, 0xa4, 0x89,
+			0x7e, 0x2e, 0x32, 0x7a, 0xce, 0x4f, 0x0d, 0xdb,
+			0x54, 0xf2, 0xb3, 0x01, 0x9f, 0xc4, 0x61, 0x9e,
+			0xa8, 0xb3, 0x72, 0xa9, 0x65, 0x37, 0xfa, 0xb3,
+			0x57, 0xce, 0x41, 0xb1, 0x7c, 0xb9, 0x08, 0xab,
+			0xfd, 0x0a, 0xdf, 0xc0, 0x07, 0xd9, 0xaa, 0x19,
+		},
+	},
+	{
+		.data_len = 3333,
+		.key_len = 64,
+		.mac = {
+			0x22, 0xfe, 0x0d, 0xae, 0x67, 0x4f, 0xfb, 0x5d,
+			0xa9, 0x89, 0xf7, 0xa4, 0xc6, 0xf2, 0xb2, 0xf0,
+			0x7f, 0xfd, 0xa5, 0x69, 0xb2, 0x7f, 0xa4, 0xd7,
+			0x9b, 0xbf, 0xca, 0xd9, 0x22, 0xd3, 0xca, 0x9f,
+			0x22, 0x6e, 0x49, 0xbe, 0xf3, 0x38, 0xad, 0x47,
+			0xc9, 0xfb, 0x58, 0x72, 0xc2, 0x0e, 0xc8, 0xca,
+			0xcf, 0xc5, 0x49, 0xdb, 0xa7, 0xbe, 0x80, 0x69,
+			0x58, 0xd8, 0x35, 0x7a, 0xf8, 0x33, 0x13, 0x29,
+		},
+	},
+	{
+		.data_len = 4096,
+		.key_len = 65,
+		.mac = {
+			0xc4, 0x3b, 0x53, 0xe6, 0x98, 0x8c, 0xed, 0xca,
+			0x5e, 0xb3, 0xac, 0xa1, 0x6e, 0xda, 0xb7, 0x25,
+			0x94, 0x53, 0xad, 0xf5, 0x72, 0xa5, 0xd6, 0xd3,
+			0x35, 0xce, 0x4a, 0xd9, 0x86, 0x9c, 0x8d, 0x28,
+			0x4a, 0xfb, 0x2b, 0x04, 0x23, 0xd1, 0xe9, 0x03,
+			0xfa, 0xf6, 0x60, 0x31, 0x85, 0x62, 0x48, 0x54,
+			0x1e, 0x2d, 0xd2, 0x9f, 0xfb, 0xeb, 0xf6, 0x1c,
+			0xc7, 0x72, 0x8d, 0x2a, 0x95, 0x38, 0xf0, 0x12,
+		},
+	},
+	{
+		.data_len = 4128,
+		.key_len = 66,
+		.mac = {
+			0xf1, 0x1c, 0x03, 0xbb, 0x96, 0x3e, 0xe3, 0x42,
+			0x6e, 0xcf, 0x6b, 0xed, 0x72, 0xc3, 0xf8, 0x9d,
+			0xb9, 0x65, 0x03, 0xc0, 0xaf, 0x97, 0x3e, 0x8e,
+			0x0f, 0x6b, 0x85, 0x59, 0xb7, 0x2b, 0x03, 0x9d,
+			0x0c, 0x6b, 0xa6, 0x36, 0x84, 0xb1, 0x79, 0x02,
+			0x12, 0x31, 0x66, 0x75, 0xb9, 0xa4, 0x7c, 0x61,
+			0xce, 0xbf, 0x6e, 0x13, 0x40, 0xd2, 0x52, 0xc2,
+			0xe1, 0x3c, 0xee, 0x58, 0xf6, 0xb4, 0x7e, 0x51,
+		},
+	},
+	{
+		.data_len = 4160,
+		.key_len = 127,
+		.mac = {
+			0xb9, 0x05, 0x0a, 0xf6, 0x43, 0x3a, 0xc1, 0xf5,
+			0xd7, 0x37, 0x8a, 0xaf, 0x05, 0x5f, 0x7e, 0x9f,
+			0x59, 0xaf, 0xa7, 0x2b, 0x91, 0x47, 0x91, 0x5b,
+			0xeb, 0xca, 0xab, 0x25, 0x66, 0x0c, 0x06, 0x13,
+			0x23, 0x29, 0x18, 0x5c, 0x34, 0x66, 0x8b, 0x40,
+			0x0e, 0x05, 0x0f, 0x31, 0x97, 0x24, 0x53, 0x60,
+			0xba, 0x98, 0x7b, 0x85, 0xd6, 0x8b, 0xef, 0x99,
+			0xb6, 0x49, 0x00, 0x1a, 0xb9, 0xef, 0x1b, 0xeb,
+		},
+	},
+	{
+		.data_len = 4224,
+		.key_len = 128,
+		.mac = {
+			0x66, 0x52, 0x8d, 0xd1, 0x45, 0x3e, 0xde, 0x65,
+			0x57, 0xc2, 0x45, 0x08, 0x2c, 0xe2, 0xcd, 0xb0,
+			0xe5, 0x26, 0x04, 0x4c, 0x42, 0xac, 0x44, 0x25,
+			0x59, 0x63, 0x42, 0x3c, 0xfe, 0x9b, 0xcd, 0xe0,
+			0xf6, 0x8d, 0x59, 0x1b, 0x1c, 0xa0, 0xde, 0x67,
+			0xb2, 0x3b, 0x4b, 0xec, 0x7b, 0x00, 0x67, 0xa9,
+			0x3a, 0x69, 0x2e, 0x6d, 0x59, 0x4e, 0x2b, 0x87,
+			0x9a, 0x90, 0x66, 0xab, 0x12, 0xc4, 0x90, 0x23,
+		},
+	},
+	{
+		.data_len = 16384,
+		.key_len = 129,
+		.mac = {
+			0x9e, 0x4e, 0xad, 0x30, 0xc4, 0xf1, 0x48, 0xf8,
+			0x9d, 0x1d, 0x01, 0x4f, 0xa2, 0xf2, 0x12, 0x08,
+			0x8f, 0xca, 0xc3, 0x31, 0x6c, 0x51, 0xe1, 0xc4,
+			0x46, 0x75, 0x78, 0x83, 0xbe, 0x29, 0x66, 0xb7,
+			0x7b, 0x91, 0x09, 0xc5, 0xb3, 0xd7, 0xc7, 0x78,
+			0xc3, 0x48, 0x63, 0x2f, 0x15, 0x7b, 0xe3, 0x7c,
+			0xe5, 0x45, 0x7b, 0xd3, 0x8f, 0xf6, 0x2b, 0x4b,
+			0x93, 0x72, 0xe9, 0x01, 0xf8, 0xe3, 0xfa, 0x2b,
+		},
+	},
+};
diff --git a/lib/crypto/tests/sha512_kunit.c b/lib/crypto/tests/sha512_kunit.c
new file mode 100644
index 0000000000000..8a93b86c36657
--- /dev/null
+++ b/lib/crypto/tests/sha512_kunit.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2025 Google LLC
+ */
+#include <crypto/sha2.h>
+#include "sha512-testvecs.h"
+
+#define HASH sha512
+#define HASH_CTX sha512_ctx
+#define HASH_SIZE SHA512_DIGEST_SIZE
+#define HASH_INIT sha512_init
+#define HASH_UPDATE sha512_update
+#define HASH_FINAL sha512_final
+#define HASH_TESTVECS sha512_testvecs
+#define HMAC_KEY hmac_sha512_key
+#define HMAC_CTX hmac_sha512_ctx
+#define HMAC_SETKEY hmac_sha512_preparekey
+#define HMAC_INIT hmac_sha512_init
+#define HMAC_UPDATE hmac_sha512_update
+#define HMAC_FINAL hmac_sha512_final
+#define HMAC hmac_sha512
+#define HMAC_USINGRAWKEY hmac_sha512_usingrawkey
+#define HMAC_TESTVECS hmac_sha512_testvecs
+#include "hash-test-template.h"
+
+static struct kunit_case hash_test_cases[] = {
+	KUNIT_CASE(test_hash_test_vectors),
+	KUNIT_CASE(test_hash_incremental_updates),
+	KUNIT_CASE(test_hash_buffer_overruns),
+	KUNIT_CASE(test_hash_overlaps),
+	KUNIT_CASE(test_hash_alignment_consistency),
+	KUNIT_CASE(test_hash_interrupt_context),
+	KUNIT_CASE(test_hash_ctx_zeroization),
+	KUNIT_CASE(test_hmac),
+	KUNIT_CASE(benchmark_hash),
+	{},
+};
+
+static struct kunit_suite hash_test_suite = {
+	.name = "sha512",
+	.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/scripts/crypto/gen-hash-testvecs.py b/scripts/crypto/gen-hash-testvecs.py
new file mode 100755
index 0000000000000..9e4baa9201579
--- /dev/null
+++ b/scripts/crypto/gen-hash-testvecs.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Script that generates test vectors for the given cryptographic hash function.
+#
+# Copyright 2025 Google LLC
+
+import hashlib
+import hmac
+import sys
+
+DATA_LENS = [0, 1, 2, 3, 16, 32, 48, 49, 63, 64, 65, 127, 128, 129, 256, 511, 513,
+             1000, 3333, 4096, 4128, 4160, 4224, 16384]
+KEY_LENS = [0, 1, 31, 32, 33, 64, 65, 66, 127, 128, 129, 1000, 1024]
+
+# Generate the given number of random bytes, using the length itself as the seed
+# for a simple random number generator.  The test uses the same seed and random
+# number generator to reconstruct the data, so it doesn't have to be explicitly
+# included in the test vector (as long as all test vectors use random data).
+def rand_bytes(length):
+    seed = length
+    out = []
+    for _ in range(length):
+        seed = (seed * 25214903917 + 11) % 2**48
+        out.append((seed >> 16) % 256)
+    return bytes(out)
+
+def gen_unkeyed_testvecs(alg):
+    print('')
+    print('static const struct {')
+    print('\tsize_t data_len;')
+    print(f'\tu8 digest[{alg.upper()}_DIGEST_SIZE];')
+    print(f'}} {alg}_testvecs[] = {{')
+    for data_len in DATA_LENS:
+        data = rand_bytes(data_len)
+        h = hashlib.new(alg)
+        h.update(data)
+        digest = h.digest()
+
+        print('\t{')
+        print(f'\t\t.data_len = {data_len},')
+        print('\t\t.digest = {')
+        for i in range(0, len(digest), 8):
+            line = '\t\t\t' + ''.join(f'0x{b:02x}, ' for b in digest[i:i+8])
+            print(f'{line.rstrip()}')
+        print('\t\t},')
+        print('\t},')
+    print('};')
+
+def gen_hmac_testvecs(alg):
+    print('')
+    print('static const struct {')
+    print('\tsize_t data_len;')
+    print('\tsize_t key_len;')
+    print(f'\tu8 mac[{alg.upper()}_DIGEST_SIZE];')
+    print(f'}} hmac_{alg}_testvecs[] = {{')
+    for (i, data_len) in enumerate(DATA_LENS):
+        key_len = KEY_LENS[i % len(KEY_LENS)]
+        data = rand_bytes(data_len)
+        key = rand_bytes(key_len)
+        mac = hmac.digest(key, data, alg)
+
+        print('\t{')
+        print(f'\t\t.data_len = {data_len},')
+        print(f'\t\t.key_len = {key_len},')
+        print('\t\t.mac = {')
+        for i in range(0, len(mac), 8):
+            line = '\t\t\t' + ''.join(f'0x{b:02x}, ' for b in mac[i:i+8])
+            print(f'{line.rstrip()}')
+        print('\t\t},')
+        print('\t},')
+    print('};')
+
+if len(sys.argv) != 2:
+    sys.stderr.write('Usage: gen-hash-testvecs.py ALGORITHM\n')
+    sys.stderr.write('ALGORITHM may be any supported by Python hashlib.\n')
+    sys.stderr.write('Example: gen-hash-testvecs.py sha512\n')
+    sys.exit(1)
+
+alg = sys.argv[1]
+print(f'/* This file was generated by: {sys.argv[0]} {" ".join(sys.argv[1:])} */')
+gen_unkeyed_testvecs(alg)
+gen_hmac_testvecs(alg)
-- 
2.50.0


  reply	other threads:[~2025-06-30 16:24 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-30 16:20 [PATCH v3 0/2] KUnit tests for SHA-2 library functions Eric Biggers
2025-06-30 16:20 ` Eric Biggers [this message]
2025-06-30 16:20 ` [PATCH v3 2/2] lib/crypto: sha256: Add KUnit tests for SHA-224 and SHA-256 Eric Biggers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250630162014.6463-2-ebiggers@kernel.org \
    --to=ebiggers@kernel.org \
    --cc=Jason@zx2c4.com \
    --cc=ardb@kernel.org \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.