[test] Use mock random data for public key self-tests

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>
This commit is contained in:
Michael Brown
2026-05-06 21:43:44 +01:00
parent ae8defc279
commit 7fe8b7fde4
6 changed files with 110 additions and 11 deletions
+8 -1
View 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 );
+2
View 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 */
+4
View 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,
+49
View 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 );
+25 -10
View 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,
+22
View 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 */