diff --git a/src/crypto/rsa.c b/src/crypto/rsa.c index be055d881..c0a56acd3 100644 --- a/src/crypto/rsa.c +++ b/src/crypto/rsa.c @@ -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 ); diff --git a/src/include/ipxe/rsa.h b/src/include/ipxe/rsa.h index c5ae919ae..289743c40 100644 --- a/src/include/ipxe/rsa.h +++ b/src/include/ipxe/rsa.h @@ -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 */ diff --git a/src/tests/ecdsa_test.c b/src/tests/ecdsa_test.c index 0ea039b1f..007ee12c1 100644 --- a/src/tests/ecdsa_test.c +++ b/src/tests/ecdsa_test.c @@ -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, diff --git a/src/tests/pubkey_test.c b/src/tests/pubkey_test.c index b94ed90ff..130af02f2 100644 --- a/src/tests/pubkey_test.c +++ b/src/tests/pubkey_test.c @@ -40,6 +40,34 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #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 ); diff --git a/src/tests/pubkey_test.h b/src/tests/pubkey_test.h index 33b301a6e..f6c952d3f 100644 --- a/src/tests/pubkey_test.h +++ b/src/tests/pubkey_test.h @@ -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, diff --git a/src/tests/rsa_test.c b/src/tests/rsa_test.c index 13160934a..871c8461f 100644 --- a/src/tests/rsa_test.c +++ b/src/tests/rsa_test.c @@ -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 */