]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[test] Generalise public-key algorithm tests and use okx()
authorMichael Brown <mcb30@ipxe.org>
Sun, 18 Aug 2024 19:01:08 +0000 (20:01 +0100)
committerMichael Brown <mcb30@ipxe.org>
Sun, 18 Aug 2024 22:51:43 +0000 (23:51 +0100)
Generalise the existing support for performing RSA public-key
encryption, decryption, signature, and verification tests, and update
the code to use okx() for neater reporting of test results.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/tests/pubkey_test.c [new file with mode: 0644]
src/tests/pubkey_test.h
src/tests/rsa_test.c

diff --git a/src/tests/pubkey_test.c b/src/tests/pubkey_test.c
new file mode 100644 (file)
index 0000000..9396251
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/** @file
+ *
+ * Public key self-tests
+ *
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ipxe/crypto.h>
+#include <ipxe/test.h>
+#include "pubkey_test.h"
+
+/**
+ * Report public key encryption and decryption test result
+ *
+ * @v test             Public key encryption and decryption test
+ * @v file             Test code file
+ * @v line             Test code line
+ */
+void pubkey_okx ( struct pubkey_test *test, const char *file,
+                 unsigned int line ) {
+       struct pubkey_algorithm *pubkey = test->pubkey;
+       uint8_t private_ctx[pubkey->ctxsize];
+       uint8_t public_ctx[pubkey->ctxsize];
+       size_t max_len;
+
+       /* Initialize contexts */
+       okx ( pubkey_init ( pubkey, private_ctx, &test->private ) == 0,
+             file, line );
+       okx ( pubkey_init ( pubkey, public_ctx, &test->public ) == 0,
+             file, line );
+       max_len = pubkey_max_len ( pubkey, private_ctx );
+
+       /* Test decrypting with private key to obtain known plaintext */
+       {
+               uint8_t decrypted[max_len];
+               int decrypted_len;
+
+               decrypted_len = pubkey_decrypt ( pubkey, private_ctx,
+                                                test->ciphertext,
+                                                test->ciphertext_len,
+                                                decrypted );
+               okx ( decrypted_len == ( ( int ) test->plaintext_len ),
+                     file, line );
+               okx ( memcmp ( decrypted, test->plaintext,
+                              test->plaintext_len ) == 0, file, line );
+       }
+
+       /* Test encrypting with private key and decrypting with public key */
+       {
+               uint8_t encrypted[max_len];
+               uint8_t decrypted[max_len];
+               int encrypted_len;
+               int decrypted_len;
+
+               encrypted_len = pubkey_encrypt ( pubkey, private_ctx,
+                                                test->plaintext,
+                                                test->plaintext_len,
+                                                encrypted );
+               okx ( encrypted_len >= 0, file, line );
+               decrypted_len = pubkey_decrypt ( pubkey, public_ctx,
+                                                encrypted, encrypted_len,
+                                                decrypted );
+               okx ( decrypted_len == ( ( int ) test->plaintext_len ),
+                     file, line );
+               okx ( memcmp ( decrypted, test->plaintext,
+                              test->plaintext_len ) == 0, file, line );
+       }
+
+       /* Test encrypting with public key and decrypting with private key */
+       {
+               uint8_t encrypted[max_len];
+               uint8_t decrypted[max_len];
+               int encrypted_len;
+               int decrypted_len;
+
+               encrypted_len = pubkey_encrypt ( pubkey, public_ctx,
+                                                test->plaintext,
+                                                test->plaintext_len,
+                                                encrypted );
+               okx ( encrypted_len >= 0, file, line );
+               decrypted_len = pubkey_decrypt ( pubkey, private_ctx,
+                                                encrypted, encrypted_len,
+                                                decrypted );
+               okx ( decrypted_len == ( ( int ) test->plaintext_len ),
+                     file, line );
+               okx ( memcmp ( decrypted, test->plaintext,
+                              test->plaintext_len ) == 0, file, line );
+       }
+
+       /* Free contexts */
+       pubkey_final ( pubkey, public_ctx );
+       pubkey_final ( pubkey, private_ctx );
+}
+
+/**
+ * Report public key signature test result
+ *
+ * @v test             Public key signature test
+ * @v file             Test code file
+ * @v line             Test code line
+ */
+void pubkey_sign_okx ( struct pubkey_sign_test *test, const char *file,
+                      unsigned int line ) {
+       struct pubkey_algorithm *pubkey = test->pubkey;
+       struct digest_algorithm *digest = test->digest;
+       uint8_t private_ctx[pubkey->ctxsize];
+       uint8_t public_ctx[pubkey->ctxsize];
+       uint8_t digestctx[digest->ctxsize ];
+       uint8_t digestout[digest->digestsize];
+       size_t max_len;
+
+       /* Initialize contexts */
+       okx ( pubkey_init ( pubkey, private_ctx, &test->private ) == 0,
+             file, line );
+       okx ( pubkey_init ( pubkey, public_ctx, &test->public ) == 0,
+             file, line );
+       max_len = pubkey_max_len ( pubkey, private_ctx );
+
+       /* Construct digest over plaintext */
+       digest_init ( digest, digestctx );
+       digest_update ( digest, digestctx, test->plaintext,
+                       test->plaintext_len );
+       digest_final ( digest, digestctx, digestout );
+
+       /* Test signing using private key */
+       {
+               uint8_t signature[max_len];
+               int signature_len;
+
+               signature_len = pubkey_sign ( pubkey, private_ctx, digest,
+                                             digestout, signature );
+               okx ( signature_len == ( ( int ) test->signature_len ),
+                     file, line );
+               okx ( memcmp ( signature, test->signature,
+                              test->signature_len ) == 0, file, line );
+       }
+
+       /* Test verification using public key */
+       okx ( pubkey_verify ( pubkey, public_ctx, digest, digestout,
+                             test->signature, test->signature_len ) == 0,
+             file, line );
+
+       /* Test verification failure of modified signature */
+       {
+               uint8_t bad[test->signature_len];
+
+               memcpy ( bad, test->signature, test->signature_len );
+               bad[ test->signature_len / 2 ] ^= 0x40;
+               okx ( pubkey_verify ( pubkey, public_ctx, digest, digestout,
+                                     bad, sizeof ( bad ) ) != 0, file, line );
+       }
+
+       /* Free contexts */
+       pubkey_final ( pubkey, public_ctx );
+       pubkey_final ( pubkey, private_ctx );
+}
index 214992238dd127282a681120acc837ee5e1c4b9b..20bb94355c8298469df819b5e9255e734253b66b 100644 (file)
@@ -7,160 +7,151 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/crypto.h>
 #include <ipxe/test.h>
 
-/**
- * Report public key decryption test result
- *
- * @v pubkey           Public key algorithm
- * @v key              Key
- * @v ciphertext       Ciphertext
- * @v ciphertext_len   Ciphertext length
- * @v expected         Expected plaintext
- * @v expected_len     Expected plaintext length
- */
-#define pubkey_decrypt_ok( pubkey, key, ciphertext, ciphertext_len,    \
-                          expected, expected_len ) do {                \
-       uint8_t ctx[ (pubkey)->ctxsize ];                               \
-                                                                       \
-       ok ( pubkey_init ( (pubkey), ctx, (key) ) == 0 );               \
-       {                                                               \
-               size_t max_len = pubkey_max_len ( (pubkey), ctx );      \
-               uint8_t decrypted[ max_len ];                           \
-               int decrypted_len;                                      \
-                                                                       \
-               decrypted_len = pubkey_decrypt ( (pubkey), ctx,         \
-                                                (ciphertext),          \
-                                                (ciphertext_len),      \
-                                                decrypted );           \
-               ok ( decrypted_len == ( ( int ) (expected_len) ) );     \
-               ok ( memcmp ( decrypted, (expected),                    \
-                             (expected_len) ) == 0 );                  \
-       }                                                               \
-       pubkey_final ( (pubkey), ctx );                                 \
-       } while ( 0 )
+/** A public-key encryption and decryption test */
+struct pubkey_test {
+       /** Public-key algorithm */
+       struct pubkey_algorithm *pubkey;
+       /** Private key */
+       const struct asn1_cursor private;
+       /** Public key */
+       const struct asn1_cursor public;
+       /** Plaintext */
+       const void *plaintext;
+       /** Length of plaintext */
+       size_t plaintext_len;
+       /** Ciphertext
+        *
+        * Note that the encryption process may include some random
+        * padding, so a given plaintext will encrypt to multiple
+        * different ciphertexts.
+        */
+       const void *ciphertext;
+       /** Length of ciphertext */
+       size_t ciphertext_len;
+};
+
+/** A public-key signature test */
+struct pubkey_sign_test {
+       /** Public-key algorithm */
+       struct pubkey_algorithm *pubkey;
+       /** Private key */
+       const struct asn1_cursor private;
+       /** Public key */
+       const struct asn1_cursor public;
+       /** Plaintext */
+       const void *plaintext;
+       /** Plaintext length */
+       size_t plaintext_len;
+       /** Signature algorithm */
+       struct digest_algorithm *digest;
+       /** Signature */
+       const void *signature;
+       /** Signature length */
+       size_t signature_len;
+};
+
+/** Define inline private key data */
+#define PRIVATE(...) { __VA_ARGS__ }
+
+/** Define inline public key data */
+#define PUBLIC(...) { __VA_ARGS__ }
+
+/** Define inline plaintext data */
+#define PLAINTEXT(...) { __VA_ARGS__ }
+
+/** Define inline ciphertext data */
+#define CIPHERTEXT(...) { __VA_ARGS__ }
+
+/** Define inline signature data */
+#define SIGNATURE(...) { __VA_ARGS__ }
 
 /**
- * Report public key encryption and decryption test result
+ * Define a public-key encryption and decryption test
  *
- * @v pubkey           Public key algorithm
- * @v encrypt_key      Encryption key
- * @v decrypt_key      Decryption key
- * @v plaintext                Plaintext
- * @v plaintext_len    Plaintext length
+ * @v name             Test name
+ * @v PUBKEY           Public-key algorithm
+ * @v PRIVATE          Private key
+ * @v PUBLIC           Public key
+ * @v PLAINTEXT                Plaintext
+ * @v CIPHERTEXT       Ciphertext
+ * @ret test           Encryption and decryption test
  */
-#define pubkey_encrypt_ok( pubkey, encrypt_key, decrypt_key, plaintext,        \
-                          plaintext_len ) do {                         \
-       uint8_t ctx[ (pubkey)->ctxsize ];                               \
-                                                                       \
-       ok ( pubkey_init ( (pubkey), ctx, (encrypt_key) ) == 0 );       \
-       {                                                               \
-               size_t max_len = pubkey_max_len ( (pubkey), ctx );      \
-               uint8_t encrypted[ max_len ];                           \
-               int encrypted_len;                                      \
-                                                                       \
-               encrypted_len = pubkey_encrypt ( (pubkey), ctx,         \
-                                                (plaintext),           \
-                                                (plaintext_len),       \
-                                                encrypted );           \
-               ok ( encrypted_len >= 0 );                              \
-               pubkey_decrypt_ok ( (pubkey), (decrypt_key),            \
-                                   encrypted, encrypted_len,           \
-                                   (plaintext), (plaintext_len) );     \
-       }                                                               \
-       pubkey_final ( (pubkey), ctx );                                 \
-       } while ( 0 )
+#define PUBKEY_TEST( name, PUBKEY, PRIVATE, PUBLIC, PLAINTEXT,         \
+                          CIPHERTEXT )                                 \
+       static const uint8_t name ## _private[] = PRIVATE;              \
+       static const uint8_t name ## _public[] = PUBLIC;                \
+       static const uint8_t name ## _plaintext[] = PLAINTEXT;          \
+       static const uint8_t name ## _ciphertext[] = CIPHERTEXT;        \
+       static struct pubkey_test name = {                              \
+               .pubkey = PUBKEY,                                       \
+               .private = {                                            \
+                       .data = name ## _private,                       \
+                       .len = sizeof ( name ## _private ),             \
+               },                                                      \
+               .public = {                                             \
+                       .data = name ## _public,                        \
+                       .len = sizeof ( name ## _public ),              \
+               },                                                      \
+               .plaintext = name ## _plaintext,                        \
+               .plaintext_len = sizeof ( name ## _plaintext ),         \
+               .ciphertext = name ## _ciphertext,                      \
+               .ciphertext_len = sizeof ( name ## _ciphertext ),       \
+       }
 
 /**
- * Report public key signature test result
+ * Define a public-key signature test
  *
- * @v pubkey           Public key algorithm
- * @v key              Key
- * @v digest           Digest algorithm
- * @v plaintext                Plaintext
- * @v plaintext_len    Plaintext length
- * @v expected         Expected signature
- * @v expected_len     Expected signature length
+ * @v name             Test name
+ * @v PUBKEY           Public-key algorithm
+ * @v PRIVATE          Private key
+ * @v PUBLIC           Public key
+ * @v PLAINTEXT                Plaintext
+ * @v DIGEST           Digest algorithm
+ * @v SIGNATURE                Signature
+ * @ret test           Signature test
  */
-#define pubkey_sign_ok( pubkey, key, digest, plaintext,        plaintext_len,  \
-                       expected, expected_len ) do {                   \
-       uint8_t ctx[ (pubkey)->ctxsize ];                               \
-       uint8_t digestctx[ (digest)->ctxsize ];                         \
-       uint8_t digestout[ (digest)->digestsize ];                      \
-                                                                       \
-       digest_init ( (digest), digestctx );                            \
-       digest_update ( (digest), digestctx, (plaintext),               \
-                       (plaintext_len) );                              \
-       digest_final ( (digest), digestctx, digestout );                \
-                                                                       \
-       ok ( pubkey_init ( (pubkey), ctx, (key) ) == 0 );               \
-       {                                                               \
-               size_t max_len = pubkey_max_len ( (pubkey), ctx );      \
-               uint8_t signature[ max_len ];                           \
-               int signature_len;                                      \
-                                                                       \
-               signature_len = pubkey_sign ( (pubkey), ctx, (digest),  \
-                                             digestout, signature );   \
-               ok ( signature_len == ( ( int ) (expected_len) ) );     \
-               ok ( memcmp ( signature, (expected),                    \
-                             (expected_len) ) == 0 );                  \
-       }                                                               \
-       pubkey_final ( (pubkey), ctx );                                 \
-       } while ( 0 )
+#define PUBKEY_SIGN_TEST( name, PUBKEY, PRIVATE, PUBLIC, PLAINTEXT,    \
+                         DIGEST, SIGNATURE )                           \
+       static const uint8_t name ## _private[] = PRIVATE;              \
+       static const uint8_t name ## _public[] = PUBLIC;                \
+       static const uint8_t name ## _plaintext[] = PLAINTEXT;          \
+       static const uint8_t name ## _signature[] = SIGNATURE;          \
+       static struct pubkey_sign_test name = {                         \
+               .pubkey = PUBKEY,                                       \
+               .private = {                                            \
+                       .data = name ## _private,                       \
+                       .len = sizeof ( name ## _private ),             \
+               },                                                      \
+               .public = {                                             \
+                       .data = name ## _public,                        \
+                       .len = sizeof ( name ## _public ),              \
+               },                                                      \
+               .plaintext = name ## _plaintext,                        \
+               .plaintext_len = sizeof ( name ## _plaintext ),         \
+               .digest = DIGEST,                                       \
+               .signature = name ## _signature,                        \
+               .signature_len = sizeof ( name ## _signature ),         \
+       }
+
+extern void pubkey_okx ( struct pubkey_test *test,
+                        const char *file, unsigned int line );
+extern void pubkey_sign_okx ( struct pubkey_sign_test *test,
+                             const char *file, unsigned int line );
 
 /**
- * Report public key verification test result
+ * Report a public key encryption and decryption test result
  *
- * @v pubkey           Public key algorithm
- * @v key              Key
- * @v digest           Digest algorithm
- * @v plaintext                Plaintext
- * @v plaintext_len    Plaintext length
- * @v signature                Signature
- * @v signature_len    Signature length
+ * @v test             Public key encryption and decryption test
  */
-#define pubkey_verify_ok( pubkey, key, digest, plaintext,              \
-                         plaintext_len, signature, signature_len ) do {\
-       uint8_t ctx[ (pubkey)->ctxsize ];                               \
-       uint8_t digestctx[ (digest)->ctxsize ];                         \
-       uint8_t digestout[ (digest)->digestsize ];                      \
-                                                                       \
-       digest_init ( (digest), digestctx );                            \
-       digest_update ( (digest), digestctx, (plaintext),               \
-                       (plaintext_len) );                              \
-       digest_final ( (digest), digestctx, digestout );                \
-                                                                       \
-       ok ( pubkey_init ( (pubkey), ctx, (key) ) == 0 );               \
-       ok ( pubkey_verify ( (pubkey), ctx, (digest), digestout,        \
-                            (signature), (signature_len) ) == 0 );     \
-       pubkey_final ( (pubkey), ctx );                                 \
-       } while ( 0 )
+#define pubkey_ok( test ) \
+       pubkey_okx ( test, __FILE__, __LINE__ )
 
 /**
- * Report public key verification test result
+ * Report a public key signature test result
  *
- * @v pubkey           Public key algorithm
- * @v key              Key
- * @v digest           Digest algorithm
- * @v plaintext                Plaintext
- * @v plaintext_len    Plaintext length
- * @v signature                Signature
- * @v signature_len    Signature length
+ * @v test             Public key signature test
  */
-#define pubkey_verify_fail_ok( pubkey, key, digest, plaintext,         \
-                              plaintext_len, signature,                \
-                              signature_len ) do {                     \
-       uint8_t ctx[ (pubkey)->ctxsize ];                               \
-       uint8_t digestctx[ (digest)->ctxsize ];                         \
-       uint8_t digestout[ (digest)->digestsize ];                      \
-                                                                       \
-       digest_init ( (digest), digestctx );                            \
-       digest_update ( (digest), digestctx, (plaintext),               \
-                       (plaintext_len) );                              \
-       digest_final ( (digest), digestctx, digestout );                \
-                                                                       \
-       ok ( pubkey_init ( (pubkey), ctx, (key) ) == 0 );               \
-       ok ( pubkey_verify ( (pubkey), ctx, (digest), digestout,        \
-                            (signature), (signature_len) ) != 0 );     \
-       pubkey_final ( (pubkey), ctx );                                 \
-       } while ( 0 )
+#define pubkey_sign_ok( test ) \
+       pubkey_sign_okx ( test, __FILE__, __LINE__ )
 
 #endif /* _PUBKEY_TEST_H */
index b1d522bc00ade34fcdf2a83bb04866701d482803..13160934aa4052e8475a18fa98dd78ef9952a428 100644 (file)
@@ -43,165 +43,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/test.h>
 #include "pubkey_test.h"
 
-/** Define inline private key data */
-#define PRIVATE(...) { __VA_ARGS__ }
-
-/** Define inline public key data */
-#define PUBLIC(...) { __VA_ARGS__ }
-
-/** Define inline plaintext data */
-#define PLAINTEXT(...) { __VA_ARGS__ }
-
-/** Define inline ciphertext data */
-#define CIPHERTEXT(...) { __VA_ARGS__ }
-
-/** Define inline signature data */
-#define SIGNATURE(...) { __VA_ARGS__ }
-
-/** An RSA encryption and decryption self-test */
-struct rsa_encrypt_decrypt_test {
-       /** Private key */
-       const struct asn1_cursor private;
-       /** Public key */
-       const struct asn1_cursor public;
-       /** Plaintext */
-       const void *plaintext;
-       /** Plaintext length */
-       size_t plaintext_len;
-       /** Ciphertext
-        *
-        * Note that the encryption process includes some random
-        * padding, so a given plaintext will encrypt to multiple
-        * different ciphertexts.
-        */
-       const void *ciphertext;
-       /** Ciphertext length */
-       size_t ciphertext_len;
-};
-
-/**
- * Define an RSA encryption and decryption test
- *
- * @v name             Test name
- * @v PRIVATE          Private key
- * @v PUBLIC           Public key
- * @v PLAINTEXT                Plaintext
- * @v CIPHERTEXT       Ciphertext
- * @ret test           Encryption and decryption test
- */
-#define RSA_ENCRYPT_DECRYPT_TEST( name, PRIVATE, PUBLIC, PLAINTEXT,    \
-                                 CIPHERTEXT )                          \
-       static const uint8_t name ## _private[] = PRIVATE;              \
-       static const uint8_t name ## _public[] = PUBLIC;                \
-       static const uint8_t name ## _plaintext[] = PLAINTEXT;          \
-       static const uint8_t name ## _ciphertext[] = CIPHERTEXT;        \
-       static struct rsa_encrypt_decrypt_test name = {                 \
-               .private = {                                            \
-                       .data = name ## _private,                       \
-                       .len = sizeof ( name ## _private ),             \
-               },                                                      \
-               .public = {                                             \
-                       .data = name ## _public,                        \
-                       .len = sizeof ( name ## _public ),              \
-               },                                                      \
-               .plaintext = name ## _plaintext,                        \
-               .plaintext_len = sizeof ( name ## _plaintext ),         \
-               .ciphertext = name ## _ciphertext,                      \
-               .ciphertext_len = sizeof ( name ## _ciphertext ),       \
-       }
-
-/** An RSA signature self-test */
-struct rsa_signature_test {
-       /** Private key */
-       const struct asn1_cursor private;
-       /** Public key */
-       const struct asn1_cursor public;
-       /** Plaintext */
-       const void *plaintext;
-       /** Plaintext length */
-       size_t plaintext_len;
-       /** Signature algorithm */
-       struct asn1_algorithm *algorithm;
-       /** Signature */
-       const void *signature;
-       /** Signature length */
-       size_t signature_len;
-};
-
-/**
- * Define an RSA signature test
- *
- * @v name             Test name
- * @v PRIVATE          Private key
- * @v PUBLIC           Public key
- * @v PLAINTEXT                Plaintext
- * @v ALGORITHM                Signature algorithm
- * @v SIGNATURE                Signature
- * @ret test           Signature test
- */
-#define RSA_SIGNATURE_TEST( name, PRIVATE, PUBLIC, PLAINTEXT,          \
-                           ALGORITHM, SIGNATURE )                      \
-       static const uint8_t name ## _private[] = PRIVATE;              \
-       static const uint8_t name ## _public[] = PUBLIC;                \
-       static const uint8_t name ## _plaintext[] = PLAINTEXT;          \
-       static const uint8_t name ## _signature[] = SIGNATURE;          \
-       static struct rsa_signature_test name = {                       \
-               .private = {                                            \
-                       .data = name ## _private,                       \
-                       .len = sizeof ( name ## _private ),             \
-               },                                                      \
-               .public = {                                             \
-                       .data = name ## _public,                        \
-                       .len = sizeof ( name ## _public ),              \
-               },                                                      \
-               .plaintext = name ## _plaintext,                        \
-               .plaintext_len = sizeof ( name ## _plaintext ),         \
-               .algorithm = ALGORITHM,                                 \
-               .signature = name ## _signature,                        \
-               .signature_len = sizeof ( name ## _signature ),         \
-       }
-
-/**
- * Report RSA encryption and decryption test result
- *
- * @v test             RSA encryption and decryption test
- */
-#define rsa_encrypt_decrypt_ok( test ) do {                            \
-       pubkey_decrypt_ok ( &rsa_algorithm, &(test)->private,           \
-                           (test)->ciphertext, (test)->ciphertext_len, \
-                           (test)->plaintext,  (test)->plaintext_len );\
-       pubkey_encrypt_ok ( &rsa_algorithm, &(test)->private,           \
-                           &(test)->public, (test)->plaintext,         \
-                           (test)->plaintext_len );                    \
-       pubkey_encrypt_ok ( &rsa_algorithm, &(test)->public,            \
-                           &(test)->private, (test)->plaintext,        \
-                           (test)->plaintext_len );                    \
-       } while ( 0 )
-
-
-/**
- * Report RSA signature test result
- *
- * @v test             RSA signature test
- */
-#define rsa_signature_ok( test ) do {                                  \
-       struct digest_algorithm *digest = (test)->algorithm->digest;    \
-       uint8_t bad_signature[ (test)->signature_len ];                 \
-       pubkey_sign_ok ( &rsa_algorithm, &(test)->private, digest,      \
-                        (test)->plaintext, (test)->plaintext_len,      \
-                        (test)->signature, (test)->signature_len );    \
-       pubkey_verify_ok ( &rsa_algorithm, &(test)->public, digest,     \
-                          (test)->plaintext, (test)->plaintext_len,    \
-                          (test)->signature, (test)->signature_len );  \
-       memset ( bad_signature, 0, sizeof ( bad_signature ) );          \
-       pubkey_verify_fail_ok ( &rsa_algorithm, &(test)->public,        \
-                               digest, (test)->plaintext,              \
-                               (test)->plaintext_len, bad_signature,   \
-                               sizeof ( bad_signature ) );             \
-       } while ( 0 )
-
 /** "Hello world" encryption and decryption test (traditional PKCS#1 key) */
-RSA_ENCRYPT_DECRYPT_TEST ( hw_test,
+PUBKEY_TEST ( hw_test, &rsa_algorithm,
        PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
                  0xd2, 0xf1, 0x04, 0x67, 0xf6, 0x2c, 0x96, 0x07, 0xa6, 0xbd,
                  0x85, 0xac, 0xc1, 0x17, 0x5d, 0xe8, 0xf0, 0x93, 0x94, 0x0c,
@@ -255,7 +98,7 @@ RSA_ENCRYPT_DECRYPT_TEST ( hw_test,
                     0x38, 0x43, 0xf9, 0x41 ) );
 
 /** "Hello world" encryption and decryption test (PKCS#8 key) */
-RSA_ENCRYPT_DECRYPT_TEST ( hw_test_pkcs8,
+PUBKEY_TEST ( hw_test_pkcs8, &rsa_algorithm,
        PRIVATE ( 0x30, 0x82, 0x01, 0x55, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06,
                  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
                  0x05, 0x00, 0x04, 0x82, 0x01, 0x3f, 0x30, 0x82, 0x01, 0x3b,
@@ -312,7 +155,7 @@ RSA_ENCRYPT_DECRYPT_TEST ( hw_test_pkcs8,
                     0x38, 0x43, 0xf9, 0x41 ) );
 
 /** Random message MD5 signature test */
-RSA_SIGNATURE_TEST ( md5_test,
+PUBKEY_SIGN_TEST ( md5_test, &rsa_algorithm,
        PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
                  0xf9, 0x3f, 0x78, 0x44, 0xe2, 0x0e, 0x25, 0xf1, 0x0e, 0x94,
                  0xcd, 0xca, 0x6f, 0x9e, 0xea, 0x6d, 0xdf, 0xcd, 0xa0, 0x7c,
@@ -375,7 +218,7 @@ RSA_SIGNATURE_TEST ( md5_test,
                    0xf2, 0x8d, 0xfc, 0xfc, 0x37, 0xf7, 0xc7, 0x6d, 0x6c, 0xd8,
                    0x24, 0x0c, 0x6a, 0xec, 0x82, 0x5c, 0x72, 0xf1, 0xfc, 0x05,
                    0xed, 0x8e, 0xe8, 0xd9, 0x8b, 0x8b, 0x67, 0x02, 0x95 ),
-       &md5_with_rsa_encryption_algorithm,
+       &md5_algorithm,
        SIGNATURE ( 0xdb, 0x56, 0x3d, 0xea, 0xae, 0x81, 0x4b, 0x3b, 0x2e, 0x8e,
                    0xb8, 0xee, 0x13, 0x61, 0xc6, 0xe7, 0xd7, 0x50, 0xcd, 0x0d,
                    0x34, 0x3a, 0xfe, 0x9a, 0x8d, 0xf8, 0xfb, 0xd6, 0x7e, 0xbd,
@@ -385,7 +228,7 @@ RSA_SIGNATURE_TEST ( md5_test,
                    0xac, 0x45, 0x00, 0xa8 ) );
 
 /** Random message SHA-1 signature test */
-RSA_SIGNATURE_TEST ( sha1_test,
+PUBKEY_SIGN_TEST ( sha1_test, &rsa_algorithm,
        PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
                  0xe0, 0x3a, 0x8d, 0x35, 0xe1, 0x92, 0x2f, 0xea, 0x0d, 0x82,
                  0x60, 0x2e, 0xb6, 0x0b, 0x02, 0xd3, 0xf4, 0x39, 0xfb, 0x06,
@@ -448,7 +291,7 @@ RSA_SIGNATURE_TEST ( sha1_test,
                    0x30, 0x91, 0x1c, 0xaa, 0x6c, 0x24, 0x42, 0x1b, 0x1a, 0xba,
                    0x30, 0x40, 0x49, 0x83, 0xd9, 0xd7, 0x66, 0x7e, 0x5c, 0x1a,
                    0x4b, 0x7f, 0xa6, 0x8e, 0x8a, 0xd6, 0x0c, 0x65, 0x75 ),
-       &sha1_with_rsa_encryption_algorithm,
+       &sha1_algorithm,
        SIGNATURE ( 0xa5, 0x5a, 0x8a, 0x67, 0x81, 0x76, 0x7e, 0xad, 0x99, 0x22,
                    0xf1, 0x47, 0x64, 0xd2, 0xfb, 0x81, 0x45, 0xeb, 0x85, 0x56,
                    0xf8, 0x7d, 0xb8, 0xec, 0x41, 0x17, 0x84, 0xf7, 0x2b, 0xbb,
@@ -458,7 +301,7 @@ RSA_SIGNATURE_TEST ( sha1_test,
                    0x0e, 0x3d, 0x80, 0x80 ) );
 
 /** Random message SHA-256 signature test */
-RSA_SIGNATURE_TEST ( sha256_test,
+PUBKEY_SIGN_TEST ( sha256_test, &rsa_algorithm,
        PRIVATE ( 0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
                  0xa5, 0xe9, 0xdb, 0xa9, 0x1a, 0x6e, 0xd6, 0x4c, 0x25, 0x50,
                  0xfe, 0x61, 0x77, 0x08, 0x7a, 0x80, 0x36, 0xcb, 0x88, 0x49,
@@ -521,7 +364,7 @@ RSA_SIGNATURE_TEST ( sha256_test,
                    0x91, 0x71, 0xd6, 0x2d, 0xa1, 0xae, 0x81, 0x0c, 0xed, 0x54,
                    0x48, 0x79, 0x8a, 0x78, 0x05, 0x74, 0x4d, 0x4f, 0xf0, 0xe0,
                    0x3c, 0x41, 0x5c, 0x04, 0x0b, 0x68, 0x57, 0xc5, 0xd6 ),
-       &sha256_with_rsa_encryption_algorithm,
+       &sha256_algorithm,
        SIGNATURE ( 0x02, 0x2e, 0xc5, 0x2a, 0x2b, 0x7f, 0xb4, 0x80, 0xca, 0x9d,
                    0x96, 0x5b, 0xaf, 0x1f, 0x72, 0x5b, 0x6e, 0xf1, 0x69, 0x7f,
                    0x4d, 0x41, 0xd5, 0x9f, 0x00, 0xdc, 0x47, 0xf4, 0x68, 0x8f,
@@ -536,11 +379,11 @@ RSA_SIGNATURE_TEST ( sha256_test,
  */
 static void rsa_test_exec ( void ) {
 
-       rsa_encrypt_decrypt_ok ( &hw_test );
-       rsa_encrypt_decrypt_ok ( &hw_test_pkcs8 );
-       rsa_signature_ok ( &md5_test );
-       rsa_signature_ok ( &sha1_test );
-       rsa_signature_ok ( &sha256_test );
+       pubkey_ok ( &hw_test );
+       pubkey_ok ( &hw_test_pkcs8 );
+       pubkey_sign_ok ( &md5_test );
+       pubkey_sign_ok ( &sha1_test );
+       pubkey_sign_ok ( &sha256_test );
 }
 
 /** RSA self-test */
@@ -548,3 +391,9 @@ struct self_test rsa_test __self_test = {
        .name = "rsa",
        .exec = rsa_test_exec,
 };
+
+/* Drag in required ASN.1 OID-identified algorithms */
+REQUIRING_SYMBOL ( rsa_test );
+REQUIRE_OBJECT ( rsa_md5 );
+REQUIRE_OBJECT ( rsa_sha1 );
+REQUIRE_OBJECT ( rsa_sha256 );