Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib/crypto: tests: Migrate Curve25519 self-test to KUnit

Move the Curve25519 test from an ad-hoc self-test to a KUnit test.

Generally keep the same test logic for now, just translated to KUnit.
There's one exception, which is that I dropped the incomplete test of
curve25519_generic(). The approach I'm taking to cover the different
implementations with the KUnit tests is to just rely on booting kernels
in QEMU with different '-cpu' options, rather than try to make the tests
(incompletely) test multiple implementations on one CPU. This way, both
the test and the library API are simpler.

This commit makes the file lib/crypto/curve25519.c no longer needed, as
its only purpose was to call the self-test. However, keep it for now,
since a later commit will add code to it again.

Temporarily omit the default value of CRYPTO_SELFTESTS that the other
lib/crypto/ KUnit tests have. It would cause a recursive kconfig
dependency, since the Curve25519 code is still entangled with CRYPTO. A
later commit will fix that.

Link: https://lore.kernel.org/r/20250906213523.84915-8-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>

+52 -37
-2
include/crypto/curve25519.h
··· 28 28 void curve25519_base_arch(u8 pub[CURVE25519_KEY_SIZE], 29 29 const u8 secret[CURVE25519_KEY_SIZE]); 30 30 31 - bool curve25519_selftest(void); 32 - 33 31 static inline 34 32 bool __must_check curve25519(u8 mypublic[CURVE25519_KEY_SIZE], 35 33 const u8 secret[CURVE25519_KEY_SIZE],
-1
lib/crypto/Makefile
··· 87 87 88 88 obj-$(CONFIG_CRYPTO_LIB_CURVE25519) += libcurve25519.o 89 89 libcurve25519-y += curve25519.o 90 - libcurve25519-$(CONFIG_CRYPTO_SELFTESTS) += curve25519-selftest.o 91 90 92 91 obj-$(CONFIG_CRYPTO_LIB_DES) += libdes.o 93 92 libdes-y := des.o
+42 -31
lib/crypto/curve25519-selftest.c lib/crypto/tests/curve25519_kunit.c
··· 4 4 */ 5 5 6 6 #include <crypto/curve25519.h> 7 + #include <kunit/test.h> 7 8 8 9 struct curve25519_test_vector { 9 10 u8 private[CURVE25519_KEY_SIZE]; ··· 12 11 u8 result[CURVE25519_KEY_SIZE]; 13 12 bool valid; 14 13 }; 15 - static const struct curve25519_test_vector curve25519_test_vectors[] __initconst = { 14 + static const struct curve25519_test_vector curve25519_test_vectors[] = { 16 15 { 17 16 .private = { 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 18 17 0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, ··· 1281 1280 } 1282 1281 }; 1283 1282 1284 - bool __init curve25519_selftest(void) 1283 + static void test_curve25519(struct kunit *test) 1285 1284 { 1286 - bool success = true, ret, ret2; 1287 - size_t i = 0, j; 1288 - u8 in[CURVE25519_KEY_SIZE]; 1289 - u8 out[CURVE25519_KEY_SIZE], out2[CURVE25519_KEY_SIZE], 1290 - out3[CURVE25519_KEY_SIZE]; 1285 + for (size_t i = 0; i < ARRAY_SIZE(curve25519_test_vectors); ++i) { 1286 + const struct curve25519_test_vector *vec = 1287 + &curve25519_test_vectors[i]; 1288 + u8 out[CURVE25519_KEY_SIZE] = {}; 1289 + bool ret; 1291 1290 1292 - for (i = 0; i < ARRAY_SIZE(curve25519_test_vectors); ++i) { 1293 - memset(out, 0, CURVE25519_KEY_SIZE); 1294 - ret = curve25519(out, curve25519_test_vectors[i].private, 1295 - curve25519_test_vectors[i].public); 1296 - if (ret != curve25519_test_vectors[i].valid || 1297 - memcmp(out, curve25519_test_vectors[i].result, 1298 - CURVE25519_KEY_SIZE)) { 1299 - pr_err("curve25519 self-test %zu: FAIL\n", i + 1); 1300 - success = false; 1301 - } 1291 + ret = curve25519(out, vec->private, vec->public); 1292 + KUNIT_EXPECT_EQ_MSG(test, ret, vec->valid, 1293 + "Wrong return value with test vector %zu", 1294 + i); 1295 + KUNIT_EXPECT_MEMEQ_MSG(test, out, vec->result, sizeof(out), 1296 + "Wrong output with test vector %zu", i); 1302 1297 } 1298 + } 1303 1299 1304 - for (i = 0; i < 5; ++i) { 1300 + static void test_curve25519_basepoint(struct kunit *test) 1301 + { 1302 + for (size_t i = 0; i < 5; ++i) { 1303 + u8 in[CURVE25519_KEY_SIZE]; 1304 + u8 out[CURVE25519_KEY_SIZE]; 1305 + u8 out2[CURVE25519_KEY_SIZE]; 1306 + bool ret, ret2; 1307 + 1305 1308 get_random_bytes(in, sizeof(in)); 1306 1309 ret = curve25519_generate_public(out, in); 1307 1310 ret2 = curve25519(out2, in, (u8[CURVE25519_KEY_SIZE]){ 9 }); 1308 - curve25519_generic(out3, in, (u8[CURVE25519_KEY_SIZE]){ 9 }); 1309 - if (ret != ret2 || 1310 - memcmp(out, out2, CURVE25519_KEY_SIZE) || 1311 - memcmp(out, out3, CURVE25519_KEY_SIZE)) { 1312 - pr_err("curve25519 basepoint self-test %zu: FAIL: input - 0x", 1313 - i + 1); 1314 - for (j = CURVE25519_KEY_SIZE; j-- > 0;) 1315 - printk(KERN_CONT "%02x", in[j]); 1316 - printk(KERN_CONT "\n"); 1317 - success = false; 1318 - } 1311 + KUNIT_EXPECT_EQ_MSG(test, ret, ret2, 1312 + "in=%*phN", CURVE25519_KEY_SIZE, in); 1313 + KUNIT_EXPECT_MEMEQ_MSG(test, out, out2, CURVE25519_KEY_SIZE, 1314 + "in=%*phN", CURVE25519_KEY_SIZE, in); 1319 1315 } 1320 - 1321 - return success; 1322 1316 } 1317 + 1318 + static struct kunit_case curve25519_test_cases[] = { 1319 + KUNIT_CASE(test_curve25519), 1320 + KUNIT_CASE(test_curve25519_basepoint), 1321 + {}, 1322 + }; 1323 + 1324 + static struct kunit_suite curve25519_test_suite = { 1325 + .name = "curve25519", 1326 + .test_cases = curve25519_test_cases, 1327 + }; 1328 + kunit_test_suite(curve25519_test_suite); 1329 + 1330 + MODULE_DESCRIPTION("KUnit tests for Curve25519"); 1331 + MODULE_LICENSE("GPL");
-3
lib/crypto/curve25519.c
··· 15 15 16 16 static int __init curve25519_init(void) 17 17 { 18 - if (IS_ENABLED(CONFIG_CRYPTO_SELFTESTS) && 19 - WARN_ON(!curve25519_selftest())) 20 - return -ENODEV; 21 18 return 0; 22 19 } 23 20
+9
lib/crypto/tests/Kconfig
··· 10 10 help 11 11 KUnit tests for the BLAKE2s cryptographic hash function. 12 12 13 + config CRYPTO_LIB_CURVE25519_KUNIT_TEST 14 + tristate "KUnit tests for Curve25519" if !KUNIT_ALL_TESTS 15 + depends on KUNIT 16 + default KUNIT_ALL_TESTS 17 + select CRYPTO_LIB_BENCHMARK_VISIBLE 18 + select CRYPTO_LIB_CURVE25519 19 + help 20 + KUnit tests for the Curve25519 Diffie-Hellman function. 21 + 13 22 config CRYPTO_LIB_MD5_KUNIT_TEST 14 23 tristate "KUnit tests for MD5" if !KUNIT_ALL_TESTS 15 24 depends on KUNIT
+1
lib/crypto/tests/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-or-later 2 2 3 3 obj-$(CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST) += blake2s_kunit.o 4 + obj-$(CONFIG_CRYPTO_LIB_CURVE25519_KUNIT_TEST) += curve25519_kunit.o 4 5 obj-$(CONFIG_CRYPTO_LIB_MD5_KUNIT_TEST) += md5_kunit.o 5 6 obj-$(CONFIG_CRYPTO_LIB_POLY1305_KUNIT_TEST) += poly1305_kunit.o 6 7 obj-$(CONFIG_CRYPTO_LIB_SHA1_KUNIT_TEST) += sha1_kunit.o