]> www.infradead.org Git - users/hch/misc.git/commitdiff
lib/crypto: tests: Migrate Curve25519 self-test to KUnit
authorEric Biggers <ebiggers@kernel.org>
Sat, 6 Sep 2025 21:35:18 +0000 (14:35 -0700)
committerEric Biggers <ebiggers@kernel.org>
Sat, 6 Sep 2025 23:32:19 +0000 (16:32 -0700)
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>
include/crypto/curve25519.h
lib/crypto/Makefile
lib/crypto/curve25519.c
lib/crypto/tests/Kconfig
lib/crypto/tests/Makefile
lib/crypto/tests/curve25519_kunit.c [moved from lib/crypto/curve25519-selftest.c with 97% similarity]

index ece6a9b5fafc883e3f8e698eb9fb9c0f053de1cc..4e6dc840b1592c53cb38b3687a2ff3b55fa8364f 100644 (file)
@@ -28,8 +28,6 @@ void curve25519_arch(u8 out[CURVE25519_KEY_SIZE],
 void curve25519_base_arch(u8 pub[CURVE25519_KEY_SIZE],
                          const u8 secret[CURVE25519_KEY_SIZE]);
 
-bool curve25519_selftest(void);
-
 static inline
 bool __must_check curve25519(u8 mypublic[CURVE25519_KEY_SIZE],
                             const u8 secret[CURVE25519_KEY_SIZE],
index ad27c5bf99e11cb429c2f9ffb1ebf13178a5c425..6c3be971ace096a3cdc72d0dd688e1531121c97e 100644 (file)
@@ -87,7 +87,6 @@ endif
 
 obj-$(CONFIG_CRYPTO_LIB_CURVE25519)            += libcurve25519.o
 libcurve25519-y                                        += curve25519.o
-libcurve25519-$(CONFIG_CRYPTO_SELFTESTS)       += curve25519-selftest.o
 
 obj-$(CONFIG_CRYPTO_LIB_DES)                   += libdes.o
 libdes-y                                       := des.o
index 6850b76a80c9e3a1e7e56facfe572e4e79318ba7..25f16777865bfcc9b2a7fdc2d5547a18a12882c6 100644 (file)
@@ -15,9 +15,6 @@
 
 static int __init curve25519_init(void)
 {
-       if (IS_ENABLED(CONFIG_CRYPTO_SELFTESTS) &&
-           WARN_ON(!curve25519_selftest()))
-               return -ENODEV;
        return 0;
 }
 
index fd341aa12f1579f38f7c64e79283c6b7693e1cfe..eaca60d3e0a3641bf9c94f7675fc52844adc0da4 100644 (file)
@@ -10,6 +10,15 @@ config CRYPTO_LIB_BLAKE2S_KUNIT_TEST
        help
          KUnit tests for the BLAKE2s cryptographic hash function.
 
+config CRYPTO_LIB_CURVE25519_KUNIT_TEST
+       tristate "KUnit tests for Curve25519" if !KUNIT_ALL_TESTS
+       depends on KUNIT
+       default KUNIT_ALL_TESTS
+       select CRYPTO_LIB_BENCHMARK_VISIBLE
+       select CRYPTO_LIB_CURVE25519
+       help
+         KUnit tests for the Curve25519 Diffie-Hellman function.
+
 config CRYPTO_LIB_MD5_KUNIT_TEST
        tristate "KUnit tests for MD5" if !KUNIT_ALL_TESTS
        depends on KUNIT
index be7de929af2cc768340cb6addf9c4077f4fa6322..a71fad19922baa3723d1eafa90fd257548808571 100644 (file)
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 
 obj-$(CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST) += blake2s_kunit.o
+obj-$(CONFIG_CRYPTO_LIB_CURVE25519_KUNIT_TEST) += curve25519_kunit.o
 obj-$(CONFIG_CRYPTO_LIB_MD5_KUNIT_TEST) += md5_kunit.o
 obj-$(CONFIG_CRYPTO_LIB_POLY1305_KUNIT_TEST) += poly1305_kunit.o
 obj-$(CONFIG_CRYPTO_LIB_SHA1_KUNIT_TEST) += sha1_kunit.o
similarity index 97%
rename from lib/crypto/curve25519-selftest.c
rename to lib/crypto/tests/curve25519_kunit.c
index c85e85381e7884302e7d495b3519cceae3440cf7..68eab75d40dcd5fbfb27e0ed6f79c6c3832e6aea 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <crypto/curve25519.h>
+#include <kunit/test.h>
 
 struct curve25519_test_vector {
        u8 private[CURVE25519_KEY_SIZE];
@@ -11,7 +12,7 @@ struct curve25519_test_vector {
        u8 result[CURVE25519_KEY_SIZE];
        bool valid;
 };
-static const struct curve25519_test_vector curve25519_test_vectors[] __initconst = {
+static const struct curve25519_test_vector curve25519_test_vectors[] = {
        {
                .private = { 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d,
                             0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45,
@@ -1280,42 +1281,52 @@ static const struct curve25519_test_vector curve25519_test_vectors[] __initconst
        }
 };
 
-bool __init curve25519_selftest(void)
+static void test_curve25519(struct kunit *test)
 {
-       bool success = true, ret, ret2;
-       size_t i = 0, j;
-       u8 in[CURVE25519_KEY_SIZE];
-       u8 out[CURVE25519_KEY_SIZE], out2[CURVE25519_KEY_SIZE],
-          out3[CURVE25519_KEY_SIZE];
+       for (size_t i = 0; i < ARRAY_SIZE(curve25519_test_vectors); ++i) {
+               const struct curve25519_test_vector *vec =
+                       &curve25519_test_vectors[i];
+               u8 out[CURVE25519_KEY_SIZE] = {};
+               bool ret;
 
-       for (i = 0; i < ARRAY_SIZE(curve25519_test_vectors); ++i) {
-               memset(out, 0, CURVE25519_KEY_SIZE);
-               ret = curve25519(out, curve25519_test_vectors[i].private,
-                                curve25519_test_vectors[i].public);
-               if (ret != curve25519_test_vectors[i].valid ||
-                   memcmp(out, curve25519_test_vectors[i].result,
-                          CURVE25519_KEY_SIZE)) {
-                       pr_err("curve25519 self-test %zu: FAIL\n", i + 1);
-                       success = false;
-               }
+               ret = curve25519(out, vec->private, vec->public);
+               KUNIT_EXPECT_EQ_MSG(test, ret, vec->valid,
+                                   "Wrong return value with test vector %zu",
+                                   i);
+               KUNIT_EXPECT_MEMEQ_MSG(test, out, vec->result, sizeof(out),
+                                      "Wrong output with test vector %zu", i);
        }
+}
+
+static void test_curve25519_basepoint(struct kunit *test)
+{
+       for (size_t i = 0; i < 5; ++i) {
+               u8 in[CURVE25519_KEY_SIZE];
+               u8 out[CURVE25519_KEY_SIZE];
+               u8 out2[CURVE25519_KEY_SIZE];
+               bool ret, ret2;
 
-       for (i = 0; i < 5; ++i) {
                get_random_bytes(in, sizeof(in));
                ret = curve25519_generate_public(out, in);
                ret2 = curve25519(out2, in, (u8[CURVE25519_KEY_SIZE]){ 9 });
-               curve25519_generic(out3, in, (u8[CURVE25519_KEY_SIZE]){ 9 });
-               if (ret != ret2 ||
-                   memcmp(out, out2, CURVE25519_KEY_SIZE) ||
-                   memcmp(out, out3, CURVE25519_KEY_SIZE)) {
-                       pr_err("curve25519 basepoint self-test %zu: FAIL: input - 0x",
-                              i + 1);
-                       for (j = CURVE25519_KEY_SIZE; j-- > 0;)
-                               printk(KERN_CONT "%02x", in[j]);
-                       printk(KERN_CONT "\n");
-                       success = false;
-               }
+               KUNIT_EXPECT_EQ_MSG(test, ret, ret2,
+                                   "in=%*phN", CURVE25519_KEY_SIZE, in);
+               KUNIT_EXPECT_MEMEQ_MSG(test, out, out2, CURVE25519_KEY_SIZE,
+                                      "in=%*phN", CURVE25519_KEY_SIZE, in);
        }
-
-       return success;
 }
+
+static struct kunit_case curve25519_test_cases[] = {
+       KUNIT_CASE(test_curve25519),
+       KUNIT_CASE(test_curve25519_basepoint),
+       {},
+};
+
+static struct kunit_suite curve25519_test_suite = {
+       .name = "curve25519",
+       .test_cases = curve25519_test_cases,
+};
+kunit_test_suite(curve25519_test_suite);
+
+MODULE_DESCRIPTION("KUnit tests for Curve25519");
+MODULE_LICENSE("GPL");