]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[test] Use mock random data for public key self-tests
authorMichael Brown <mcb30@ipxe.org>
Wed, 6 May 2026 20:43:44 +0000 (21:43 +0100)
committerMichael Brown <mcb30@ipxe.org>
Wed, 6 May 2026 20:43:44 +0000 (21:43 +0100)
Make the public key self-tests fully deterministic by temporarily
overriding the function used to obtain random data for RSA encryption.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/rsa.c
src/include/ipxe/rsa.h
src/tests/ecdsa_test.c
src/tests/pubkey_test.c
src/tests/pubkey_test.h
src/tests/rsa_test.c

index be055d8815199b37f74f9c2c1fec2054ef7cf57a..c0a56acd3d38cf87c1e59476b1886a9bb8fba801 100644 (file)
@@ -70,6 +70,9 @@ struct rsa_context {
        void *tmp;
 };
 
+/** Generate random data */
+int ( * rsa_get_random ) ( void *data, size_t len ) = get_random_nz;
+
 /**
  * Identify RSA prefix
  *
@@ -331,7 +334,7 @@ static int rsa_encrypt ( const struct asn1_cursor *key,
        encoded = temp;
        encoded[0] = 0x00;
        encoded[1] = 0x02;
-       if ( ( rc = get_random_nz ( &encoded[2], random_nz_len ) ) != 0 ) {
+       if ( ( rc = rsa_get_random ( &encoded[2], random_nz_len ) ) != 0 ) {
                DBGC ( &context, "RSA %p could not generate random data: %s\n",
                       &context, strerror ( rc ) );
                goto err_random;
@@ -339,6 +342,8 @@ static int rsa_encrypt ( const struct asn1_cursor *key,
        encoded[ 2 + random_nz_len ] = 0x00;
        memcpy ( &encoded[ context.max_len - plaintext->len ],
                 plaintext->data, plaintext->len );
+       DBGC ( &context, "RSA %p encoded:\n", &context );
+       DBGC_HDA ( &context, 0, encoded, context.max_len );
 
        /* Create space for ciphertext */
        if ( ( rc = asn1_grow ( ciphertext, context.max_len ) ) != 0 )
@@ -404,6 +409,8 @@ static int rsa_decrypt ( const struct asn1_cursor *key,
        temp = context.input0;
        encoded = temp;
        rsa_cipher ( &context, ciphertext->data, encoded );
+       DBGC ( &context, "RSA %p encoded:\n", &context );
+       DBGC_HDA ( &context, 0, encoded, context.max_len );
 
        /* Parse the message */
        end = ( encoded + context.max_len );
index c5ae919ae7ac34a19f2864824823467806e77dac..289743c40d1ab5b4a9cfef5fcce5fde7fa3812e0 100644 (file)
@@ -58,4 +58,6 @@ struct rsa_digestinfo_prefix {
 
 extern struct pubkey_algorithm rsa_algorithm;
 
+extern int ( * rsa_get_random ) ( void *data, size_t len );
+
 #endif /* _IPXE_RSA_H */
index 0ea039b1f6583f6125287ecc70d08fab74840b6d..007ee12c1be42d6eb4223b346409c3d0574bfe5d 100644 (file)
@@ -67,6 +67,7 @@ PUBKEY_SIGN_TEST ( p256_hw_test, &ecdsa_algorithm,
                 0x59, 0xd5, 0xdc, 0x3d, 0xb8, 0x13, 0x8f, 0x90, 0x26, 0xfc,
                 0xf5, 0xce, 0xcb, 0xf9, 0x68, 0x91, 0x59, 0x87, 0xc6, 0x7d,
                 0x2a ),
+       RANDOM(),
        PLAINTEXT ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c,
                    0x64, 0x0a ),
        &sha256_algorithm,
@@ -104,6 +105,7 @@ PUBKEY_SIGN_TEST ( p256_hw_sha512_test, &ecdsa_algorithm,
                 0x59, 0xd5, 0xdc, 0x3d, 0xb8, 0x13, 0x8f, 0x90, 0x26, 0xfc,
                 0xf5, 0xce, 0xcb, 0xf9, 0x68, 0x91, 0x59, 0x87, 0xc6, 0x7d,
                 0x2a ),
+       RANDOM(),
        PLAINTEXT ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c,
                    0x64, 0x0a ),
        &sha512_algorithm,
@@ -142,6 +144,7 @@ PUBKEY_SIGN_TEST ( p256_random_test, &ecdsa_algorithm,
                 0x59, 0xd5, 0xdc, 0x3d, 0xb8, 0x13, 0x8f, 0x90, 0x26, 0xfc,
                 0xf5, 0xce, 0xcb, 0xf9, 0x68, 0x91, 0x59, 0x87, 0xc6, 0x7d,
                 0x2a ),
+       RANDOM(),
        PLAINTEXT ( 0xe0, 0xf0, 0x1b, 0xd1, 0x95, 0xe0, 0x4b, 0xd1, 0xf7, 0x4a,
                    0x18, 0xca, 0x60, 0x02, 0x29, 0xc1, 0x58, 0x03, 0xf8, 0xc2,
                    0x3c, 0x0f, 0x86, 0x55, 0xc5, 0x22, 0x88, 0x7e, 0x1f, 0x6c,
@@ -211,6 +214,7 @@ PUBKEY_SIGN_TEST ( p384_random_test, &ecdsa_algorithm,
                 0x84, 0x01, 0x52, 0x28, 0xb8, 0x18, 0xb0, 0xcc, 0x33, 0x9c,
                 0x44, 0x98, 0xa3, 0x59, 0x92, 0x36, 0xe3, 0x46, 0x72, 0xa8,
                 0x86, 0xec, 0x69, 0x24, 0x29, 0x29, 0xc0, 0xca, 0x2b, 0x40 ),
+       RANDOM(),
        PLAINTEXT ( 0xe0, 0xf0, 0x1b, 0xd1, 0x95, 0xe0, 0x4b, 0xd1, 0xf7, 0x4a,
                    0x18, 0xca, 0x60, 0x02, 0x29, 0xc1, 0x58, 0x03, 0xf8, 0xc2,
                    0x3c, 0x0f, 0x86, 0x55, 0xc5, 0x22, 0x88, 0x7e, 0x1f, 0x6c,
index b94ed90ff18921870ca63375bc52868885ff6140..130af02f209aaeb6e52e4d1bd65a409c89474761 100644 (file)
@@ -40,6 +40,34 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/test.h>
 #include "pubkey_test.h"
 
+/** Random data input */
+static const uint8_t *pubkey_random;
+
+/** Length of random data input */
+static size_t pubkey_random_len;
+
+/**
+ * Get random data input
+ *
+ * @v data             Output buffer
+ * @v len              Length of output buffer
+ * @ret rc             Return status code
+ */
+int pubkey_test_get_random ( void *data, size_t len ) {
+
+       /* Sanity check */
+       assert ( len <= pubkey_random_len );
+
+       /* Return random data */
+       memcpy ( data, pubkey_random, len );
+
+       /* Consume random data */
+       pubkey_random += len;
+       pubkey_random_len -= len;
+
+       return 0;
+}
+
 /**
  * Report public key encryption and decryption test result
  *
@@ -57,6 +85,18 @@ void pubkey_okx ( struct pubkey_test *test, const char *file,
        okx ( pubkey_match ( pubkey, &test->private, &test->public ) == 0,
              file, line );
 
+       /* Test encrypting with public key to obtain known ciphertext */
+       ciphertext.data = NULL;
+       ciphertext.len = 0;
+       pubkey_random = test->random;
+       pubkey_random_len = test->random_len;
+       okx ( pubkey_encrypt ( pubkey, &test->public, &test->plaintext,
+                              &ciphertext ) == 0, file, line );
+       okx ( pubkey_random_len == 0, file, line );
+       okx ( asn1_compare ( asn1_built ( &ciphertext ),
+                            &test->ciphertext ) == 0, file, line );
+       free ( ciphertext.data );
+
        /* Test decrypting with private key to obtain known plaintext */
        plaintext.data = NULL;
        plaintext.len = 0;
@@ -71,8 +111,11 @@ void pubkey_okx ( struct pubkey_test *test, const char *file,
        ciphertext.len = 0;
        plaintext.data = NULL;
        plaintext.len = 0;
+       pubkey_random = test->random;
+       pubkey_random_len = test->random_len;
        okx ( pubkey_encrypt ( pubkey, &test->private, &test->plaintext,
                               &ciphertext ) == 0, file, line );
+       okx ( pubkey_random_len == 0, file, line );
        okx ( pubkey_decrypt ( pubkey, &test->public,
                               asn1_built ( &ciphertext ),
                               &plaintext ) == 0, file, line );
@@ -86,8 +129,11 @@ void pubkey_okx ( struct pubkey_test *test, const char *file,
        ciphertext.len = 0;
        plaintext.data = NULL;
        plaintext.len = 0;
+       pubkey_random = test->random;
+       pubkey_random_len = test->random_len;
        okx ( pubkey_encrypt ( pubkey, &test->public, &test->plaintext,
                               &ciphertext ) == 0, file, line );
+       okx ( pubkey_random_len == 0, file, line );
        okx ( pubkey_decrypt ( pubkey, &test->private,
                               asn1_built ( &ciphertext ),
                               &plaintext ) == 0, file, line );
@@ -140,8 +186,11 @@ void pubkey_sign_okx ( struct pubkey_sign_test *test, const char *file,
                              &cursor ) == 0, file, line );
 
        /* Test signing using private key */
+       pubkey_random = test->random;
+       pubkey_random_len = test->random_len;
        okx ( pubkey_sign ( pubkey, &test->private, digest, digestout,
                            &builder ) == 0, file, line );
+       okx ( pubkey_random_len == 0, file, line );
        okx ( builder.len != 0, file, line );
        okx ( asn1_compare ( asn1_built ( &builder ), &test->signature ) == 0,
              file, line );
index 33b301a6ec3cf6dd9d0b778e9955407ae462a24c..f6c952d3fe687ecadbbf0ac4d3809fcfa8ec06be 100644 (file)
@@ -15,14 +15,13 @@ struct pubkey_test {
        const struct asn1_cursor private;
        /** Public key */
        const struct asn1_cursor public;
+       /** Random data input */
+       const void *random;
+       /** Random data input length */
+       size_t random_len;
        /** Plaintext */
        const struct asn1_cursor plaintext;
-       /** Ciphertext
-        *
-        * Note that the encryption process may include some random
-        * padding, so a given plaintext will encrypt to multiple
-        * different ciphertexts.
-        */
+       /** Ciphertext */
        const struct asn1_cursor ciphertext;
 };
 
@@ -34,6 +33,10 @@ struct pubkey_sign_test {
        const struct asn1_cursor private;
        /** Public key */
        const struct asn1_cursor public;
+       /** Random data input */
+       const void *random;
+       /** Random data input length */
+       size_t random_len;
        /** Plaintext */
        const void *plaintext;
        /** Plaintext length */
@@ -50,6 +53,9 @@ struct pubkey_sign_test {
 /** Define inline public key data */
 #define PUBLIC(...) { __VA_ARGS__ }
 
+/** Define inline random data */
+#define RANDOM(...) { __VA_ARGS__ }
+
 /** Define inline plaintext data */
 #define PLAINTEXT(...) { __VA_ARGS__ }
 
@@ -66,14 +72,16 @@ struct pubkey_sign_test {
  * @v PUBKEY           Public-key algorithm
  * @v PRIVATE          Private key
  * @v PUBLIC           Public key
+ * @v RANDOM           Random data
  * @v PLAINTEXT                Plaintext
  * @v CIPHERTEXT       Ciphertext
  * @ret test           Encryption and decryption test
  */
-#define PUBKEY_TEST( name, PUBKEY, PRIVATE, PUBLIC, PLAINTEXT,         \
-                          CIPHERTEXT )                                 \
+#define PUBKEY_TEST( name, PUBKEY, PRIVATE, PUBLIC, RANDOM, PLAINTEXT, \
+                    CIPHERTEXT )                                       \
        static const uint8_t name ## _private[] = PRIVATE;              \
        static const uint8_t name ## _public[] = PUBLIC;                \
+       static const uint8_t name ## _random[] = RANDOM;                \
        static const uint8_t name ## _plaintext[] = PLAINTEXT;          \
        static const uint8_t name ## _ciphertext[] = CIPHERTEXT;        \
        static struct pubkey_test name = {                              \
@@ -86,6 +94,8 @@ struct pubkey_sign_test {
                        .data = name ## _public,                        \
                        .len = sizeof ( name ## _public ),              \
                },                                                      \
+               .random = name ## _random,                              \
+               .random_len = sizeof ( name ## _random ),               \
                .plaintext = {                                          \
                        .data = name ## _plaintext,                     \
                        .len = sizeof ( name ## _plaintext ),           \
@@ -103,15 +113,17 @@ struct pubkey_sign_test {
  * @v PUBKEY           Public-key algorithm
  * @v PRIVATE          Private key
  * @v PUBLIC           Public key
+ * @v RANDOM           Random data
  * @v PLAINTEXT                Plaintext
  * @v DIGEST           Digest algorithm
  * @v SIGNATURE                Signature
  * @ret test           Signature test
  */
-#define PUBKEY_SIGN_TEST( name, PUBKEY, PRIVATE, PUBLIC, PLAINTEXT,    \
-                         DIGEST, SIGNATURE )                           \
+#define PUBKEY_SIGN_TEST( name, PUBKEY, PRIVATE, PUBLIC, RANDOM,       \
+                         PLAINTEXT, DIGEST, SIGNATURE )                \
        static const uint8_t name ## _private[] = PRIVATE;              \
        static const uint8_t name ## _public[] = PUBLIC;                \
+       static const uint8_t name ## _random[] = RANDOM;                \
        static const uint8_t name ## _plaintext[] = PLAINTEXT;          \
        static const uint8_t name ## _signature[] = SIGNATURE;          \
        static struct pubkey_sign_test name = {                         \
@@ -124,6 +136,8 @@ struct pubkey_sign_test {
                        .data = name ## _public,                        \
                        .len = sizeof ( name ## _public ),              \
                },                                                      \
+               .random = name ## _random,                              \
+               .random_len = sizeof ( name ## _random ),               \
                .plaintext = name ## _plaintext,                        \
                .plaintext_len = sizeof ( name ## _plaintext ),         \
                .digest = DIGEST,                                       \
@@ -133,6 +147,7 @@ struct pubkey_sign_test {
                },                                                      \
        }
 
+extern int pubkey_test_get_random ( void *data, size_t len );
 extern void pubkey_okx ( struct pubkey_test *test,
                         const char *file, unsigned int line );
 extern void pubkey_sign_okx ( struct pubkey_sign_test *test,
index 13160934aa4052e8475a18fa98dd78ef9952a428..871c8461f85bb99cdf41e540f831e93ffa732109 100644 (file)
@@ -87,6 +87,11 @@ PUBKEY_TEST ( hw_test, &rsa_algorithm,
                 0x04, 0xf2, 0x82, 0xc4, 0x7b, 0x6a, 0x3e, 0xec, 0x53, 0x7a,
                 0xe3, 0x4e, 0xa8, 0xc9, 0xf9, 0x1f, 0x2a, 0x13, 0x0d, 0x02,
                 0x03, 0x01, 0x00, 0x01 ),
+       RANDOM ( 0x87, 0x90, 0xdf, 0x03, 0x31, 0x20, 0x31, 0x63, 0x86, 0x30,
+                0xb9, 0xb1, 0x99, 0x5e, 0xf8, 0x2b, 0xb7, 0x6b, 0x62, 0x56,
+                0x8c, 0x2b, 0x88, 0xa1, 0x5b, 0x1e, 0x37, 0xaa, 0x12, 0xa6,
+                0xf6, 0xe8, 0x3a, 0x41, 0x91, 0x70, 0x24, 0x3f, 0x89, 0x9b,
+                0x6e, 0x81, 0x63, 0x8c, 0xe1, 0x63, 0x93, 0x19, 0x49 ),
        PLAINTEXT ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c,
                    0x64, 0x0a ),
        CIPHERTEXT ( 0x39, 0xff, 0x5c, 0x54, 0x65, 0x3e, 0x6a, 0xab, 0xc0, 0x62,
@@ -144,6 +149,11 @@ PUBKEY_TEST ( hw_test_pkcs8, &rsa_algorithm,
                 0x04, 0xf2, 0x82, 0xc4, 0x7b, 0x6a, 0x3e, 0xec, 0x53, 0x7a,
                 0xe3, 0x4e, 0xa8, 0xc9, 0xf9, 0x1f, 0x2a, 0x13, 0x0d, 0x02,
                 0x03, 0x01, 0x00, 0x01 ),
+       RANDOM ( 0x87, 0x90, 0xdf, 0x03, 0x31, 0x20, 0x31, 0x63, 0x86, 0x30,
+                0xb9, 0xb1, 0x99, 0x5e, 0xf8, 0x2b, 0xb7, 0x6b, 0x62, 0x56,
+                0x8c, 0x2b, 0x88, 0xa1, 0x5b, 0x1e, 0x37, 0xaa, 0x12, 0xa6,
+                0xf6, 0xe8, 0x3a, 0x41, 0x91, 0x70, 0x24, 0x3f, 0x89, 0x9b,
+                0x6e, 0x81, 0x63, 0x8c, 0xe1, 0x63, 0x93, 0x19, 0x49 ),
        PLAINTEXT ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c,
                    0x64, 0x0a ),
        CIPHERTEXT ( 0x39, 0xff, 0x5c, 0x54, 0x65, 0x3e, 0x6a, 0xab, 0xc0, 0x62,
@@ -198,6 +208,7 @@ PUBKEY_SIGN_TEST ( md5_test, &rsa_algorithm,
                 0xf5, 0xb0, 0x63, 0xa0, 0x84, 0xc0, 0xaf, 0x4e, 0xbe, 0x6a,
                 0xd3, 0x84, 0x3f, 0xec, 0x42, 0x17, 0xe9, 0x25, 0xe1, 0x02,
                 0x03, 0x01, 0x00, 0x01 ),
+       RANDOM(),
        PLAINTEXT ( 0x9d, 0x5b, 0x46, 0x42, 0x27, 0xc0, 0xf1, 0x4b, 0xe5, 0x9e,
                    0xd3, 0x10, 0xa1, 0xeb, 0x16, 0xc3, 0xc6, 0x8f, 0x1a, 0x18,
                    0x86, 0xc3, 0x92, 0x15, 0x2d, 0x65, 0xa0, 0x40, 0xe1, 0x3e,
@@ -271,6 +282,7 @@ PUBKEY_SIGN_TEST ( sha1_test, &rsa_algorithm,
                 0x24, 0x81, 0x4b, 0x4d, 0x48, 0x5a, 0xd2, 0x29, 0x14, 0xeb,
                 0x38, 0xdd, 0x3e, 0xb5, 0x57, 0x45, 0x9b, 0xed, 0x33, 0x02,
                 0x03, 0x01, 0x00, 0x01 ),
+       RANDOM(),
        PLAINTEXT ( 0xf7, 0x42, 0x01, 0x57, 0x6b, 0x70, 0xcc, 0x4a, 0xdc, 0xed,
                    0x12, 0x83, 0x3f, 0xef, 0x27, 0xc1, 0x3c, 0x85, 0xdd, 0x5e,
                    0x0a, 0x34, 0x98, 0xf9, 0x21, 0xd3, 0x24, 0x2a, 0x5a, 0xb2,
@@ -344,6 +356,7 @@ PUBKEY_SIGN_TEST ( sha256_test, &rsa_algorithm,
                 0x35, 0x88, 0x3f, 0xde, 0xa2, 0xce, 0x46, 0x94, 0x30, 0xa9,
                 0x76, 0xee, 0x25, 0xc5, 0x5d, 0xa6, 0xa6, 0x3a, 0xa5, 0x02,
                 0x03, 0x01, 0x00, 0x01 ),
+       RANDOM(),
        PLAINTEXT ( 0x60, 0xe7, 0xba, 0x9d, 0x5a, 0xe3, 0x2d, 0xfa, 0x5f, 0x47,
                    0xdb, 0x93, 0x24, 0x2c, 0xc4, 0xe2, 0x61, 0xf3, 0x89, 0x4d,
                    0x67, 0xad, 0xc8, 0xae, 0xf8, 0xe2, 0xfb, 0x52, 0x0f, 0x8d,
@@ -378,12 +391,21 @@ PUBKEY_SIGN_TEST ( sha256_test, &rsa_algorithm,
  *
  */
 static void rsa_test_exec ( void ) {
+       int ( * saved_get_random ) ( void *data, size_t len );
 
+       /* Temporarily override rsa_get_random() */
+       saved_get_random = rsa_get_random;
+       rsa_get_random = pubkey_test_get_random;
+
+       /* Run tests */
        pubkey_ok ( &hw_test );
        pubkey_ok ( &hw_test_pkcs8 );
        pubkey_sign_ok ( &md5_test );
        pubkey_sign_ok ( &sha1_test );
        pubkey_sign_ok ( &sha256_test );
+
+       /* Restore rsa_get_random() */
+       rsa_get_random = saved_get_random;
 }
 
 /** RSA self-test */