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 for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260114153138.4896-2-dengler@linux.ibm.com>
Date: Wed, 14 Jan 2026 16:31:38 +0100
From: Holger Dengler <dengler@...ux.ibm.com>
To: Eric Biggers <ebiggers@...nel.org>
Cc: Ard Biesheuvel <ardb@...nel.org>, "Jason A . Donenfeld" <Jason@...c4.com>,
        Herbert Xu <herbert@...dor.apana.org.au>,
        Harald Freudenberger <freude@...ux.ibm.com>,
        linux-kernel@...r.kernel.org, linux-crypto@...r.kernel.org,
        Holger Dengler <dengler@...ux.ibm.com>
Subject: [RFC PATCH 1/1] lib/crypto: tests: Add KUnit tests for AES

Add a KUnit test suite for AES library functions, including KAT and
benchmarks.

Signed-off-by: Holger Dengler <dengler@...ux.ibm.com>
---
 lib/crypto/tests/Kconfig        |  12 ++++
 lib/crypto/tests/Makefile       |   1 +
 lib/crypto/tests/aes-testvecs.h |  78 ++++++++++++++++++++++
 lib/crypto/tests/aes_kunit.c    | 115 ++++++++++++++++++++++++++++++++
 4 files changed, 206 insertions(+)
 create mode 100644 lib/crypto/tests/aes-testvecs.h
 create mode 100644 lib/crypto/tests/aes_kunit.c

diff --git a/lib/crypto/tests/Kconfig b/lib/crypto/tests/Kconfig
index 4970463ea0aa..f34e79093275 100644
--- a/lib/crypto/tests/Kconfig
+++ b/lib/crypto/tests/Kconfig
@@ -118,6 +118,18 @@ config CRYPTO_LIB_SHA3_KUNIT_TEST
 	  including SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE128 and
 	  SHAKE256.
 
+config CRYPTO_LIB_AES_KUNIT_TEST
+	tristate "KUnit tests for AES" if !KUNIT_ALL_TESTS
+	depends on KUNIT
+	default KUNIT_ALL_TESTS || CRYPTO_SELFTESTS
+	select CRYPTO_LIB_BENCHMARK_VISIBLE
+	select CRYPTO_LIB_AES
+	help
+	  KUnit tests for the AES library functions, including known answer
+	  tests and benchmarks for encrypt/decrypt with all key sizes. The
+	  test suite does not contain any key generation test, nor any error
+	  cases.
+
 config CRYPTO_LIB_BENCHMARK_VISIBLE
 	bool
 
diff --git a/lib/crypto/tests/Makefile b/lib/crypto/tests/Makefile
index f4262379f56c..72234e965cdc 100644
--- a/lib/crypto/tests/Makefile
+++ b/lib/crypto/tests/Makefile
@@ -12,3 +12,4 @@ 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_kunit.o
+obj-$(CONFIG_CRYPTO_LIB_AES_KUNIT_TEST) += aes_kunit.o
diff --git a/lib/crypto/tests/aes-testvecs.h b/lib/crypto/tests/aes-testvecs.h
new file mode 100644
index 000000000000..2bfa646ff2e5
--- /dev/null
+++ b/lib/crypto/tests/aes-testvecs.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _AES_TESTVECS_H
+#define _AES_TESTVECS_H
+
+#include <crypto/aes.h>
+
+struct buf {
+	size_t blen;
+	u8 b[];
+};
+
+struct kat {
+	u8 plain[AES_BLOCK_SIZE];
+	u8 cipher[AES_BLOCK_SIZE];
+	struct {
+		size_t len;
+		u8 b[32];
+	} key;
+};
+
+static const struct kat AES128_KAT = {
+	.plain = {
+		0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+		0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+	},
+	.cipher = {
+		0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60,
+		0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97,
+	},
+	.key = {
+		.len = 16,
+		.b = {
+			0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+			0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
+		},
+	},
+};
+
+static const struct kat AES192_KAT = {
+	.plain = {
+		0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+		0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+	},
+	.cipher = {
+		0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f,
+		0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc,
+	},
+	.key = {
+		.len = 24,
+		.b = {
+			0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
+			0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+			0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b,
+		},
+	},
+};
+
+static const struct kat AES256_KAT = {
+	.plain = {
+		0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+		0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+	},
+	.cipher = {
+		0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c,
+		0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8,
+	},
+	.key = {
+		.len = 32,
+		.b = {
+			0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+			0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+			0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+			0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4,
+		},
+	},
+};
+
+#endif /* _AES_TESTVECS_H */
diff --git a/lib/crypto/tests/aes_kunit.c b/lib/crypto/tests/aes_kunit.c
new file mode 100644
index 000000000000..057ddc3a1b1f
--- /dev/null
+++ b/lib/crypto/tests/aes_kunit.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <kunit/test.h>
+
+#include "aes-testvecs.h"
+
+#define AES_KAT(bits, func, from, to)				\
+static void aes##bits##_kat_##func(struct kunit *test)		\
+{								\
+	const u8 *in = AES##bits##_KAT.from;			\
+	u8 out[AES_BLOCK_SIZE];					\
+	struct aes_key aes_key;					\
+								\
+	if (aes_preparekey(&aes_key, AES##bits##_KAT.key.b,	\
+			   AES##bits##_KAT.key.len))		\
+		kunit_skip(test, "no key");			\
+								\
+	aes_##func(&aes_key, out, in);				\
+	KUNIT_ASSERT_MEMEQ(test, out, AES##bits##_KAT.to,	\
+			   sizeof(out));			\
+}
+
+#define KB		(1024)
+#define MB		(KB * KB)
+#define NS_PER_SEC	(1000000000ULL)
+
+#define AES_BENCHMARK(bits)					\
+static void aes##bits##_benchmark(struct kunit *test)		\
+{								\
+	const size_t num_iters = 10000000;			\
+	const u8 *cipher = AES##bits##_KAT.cipher;		\
+	const u8 *plain = AES##bits##_KAT.plain;		\
+	u8 out[AES_BLOCK_SIZE];					\
+	struct aes_key aes_key;					\
+	u64 t_enc, t_dec;					\
+								\
+	if (!IS_ENABLED(CONFIG_CRYPTO_LIB_BENCHMARK))		\
+		kunit_skip(test, "not enabled");		\
+								\
+	if (aes_preparekey(&aes_key, AES##bits##_KAT.key.b,	\
+			   AES##bits##_KAT.key.len))		\
+		kunit_skip(test, "no key");			\
+								\
+	/* warm-up enc */					\
+	for (size_t i = 0; i < 1000; i++)			\
+		aes_encrypt(&aes_key, out, plain);		\
+								\
+	preempt_disable();					\
+	t_enc = ktime_get_ns();					\
+								\
+	for (size_t i = 0; i < num_iters; i++)			\
+		aes_encrypt(&aes_key, out, plain);		\
+								\
+	t_enc = ktime_get_ns() - t_enc;				\
+	preempt_enable();					\
+								\
+	/* warm-up dec */					\
+	for (size_t i = 0; i < 1000; i++)			\
+		aes_decrypt(&aes_key, out, cipher);		\
+								\
+	preempt_disable();					\
+	t_dec = ktime_get_ns();					\
+								\
+	for (size_t i = 0; i < num_iters; i++)			\
+		aes_decrypt(&aes_key, out, cipher);		\
+								\
+	t_dec = ktime_get_ns() - t_dec;				\
+	preempt_enable();					\
+								\
+	kunit_info(test, "enc (iter. %zu, duration %lluns)",	\
+		   num_iters, t_enc);				\
+	kunit_info(test, "enc (len=%zu): %llu MB/s",		\
+		   (size_t)AES_BLOCK_SIZE,			\
+		   div64_u64((u64)AES_BLOCK_SIZE * num_iters * NS_PER_SEC, \
+			     (t_enc ?: 1) * MB));		\
+								\
+	kunit_info(test, "dec (iter. %zu, duration %lluns)",	\
+		   num_iters, t_dec);				\
+	kunit_info(test, "dec (len=%zu): %llu MB/s",		\
+		   (size_t)AES_BLOCK_SIZE,			\
+		   div64_u64((u64)AES_BLOCK_SIZE * num_iters * NS_PER_SEC, \
+			     (t_dec ?: 1) * MB));		\
+}
+
+AES_KAT(128, encrypt, plain, cipher);
+AES_KAT(192, encrypt, plain, cipher);
+AES_KAT(256, encrypt, plain, cipher);
+AES_KAT(128, decrypt, cipher, plain);
+AES_KAT(192, decrypt, cipher, plain);
+AES_KAT(256, decrypt, cipher, plain);
+AES_BENCHMARK(128);
+AES_BENCHMARK(192);
+AES_BENCHMARK(256);
+
+static struct kunit_case aes_test_cases[] = {
+	KUNIT_CASE(aes128_kat_encrypt),
+	KUNIT_CASE(aes128_kat_decrypt),
+	KUNIT_CASE(aes192_kat_encrypt),
+	KUNIT_CASE(aes192_kat_decrypt),
+	KUNIT_CASE(aes256_kat_encrypt),
+	KUNIT_CASE(aes256_kat_decrypt),
+	KUNIT_CASE(aes128_benchmark),
+	KUNIT_CASE(aes192_benchmark),
+	KUNIT_CASE(aes256_benchmark),
+	{},
+};
+
+static struct kunit_suite aes_test_suite = {
+	.name = "aes",
+	.test_cases = aes_test_cases,
+};
+
+kunit_test_suite(aes_test_suite);
+
+MODULE_DESCRIPTION("KUnit tests and benchmark aes library");
+MODULE_LICENSE("GPL");
-- 
2.51.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ