mirror of
https://github.com/ipxe/ipxe
synced 2026-02-14 02:31:26 +03:00
[test] Generalise public-key algorithm tests and use okx()
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>
This commit is contained in:
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user