From 2dd3fffe18577baa9619623e627adacefd51fca9 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 26 Mar 2014 23:12:56 +0000 Subject: [PATCH] [crypto] Add pubkey_match() to check for matching public/private key pairs Signed-off-by: Michael Brown --- src/crypto/rsa.c | 157 ++++++++++++++++++++++++++------------ src/include/ipxe/crypto.h | 18 +++++ 2 files changed, 128 insertions(+), 47 deletions(-) diff --git a/src/crypto/rsa.c b/src/crypto/rsa.c index 1a5cf6cd5..0ab7b2ad3 100644 --- a/src/crypto/rsa.c +++ b/src/crypto/rsa.c @@ -202,13 +202,11 @@ static int rsa_alloc ( struct rsa_context *context, size_t modulus_len, /** * Parse RSA integer * - * @v context RSA context * @v integer Integer to fill in * @v raw ASN.1 cursor * @ret rc Return status code */ -static int rsa_parse_integer ( struct rsa_context *context, - struct asn1_cursor *integer, +static int rsa_parse_integer ( struct asn1_cursor *integer, const struct asn1_cursor *raw ) { /* Enter integer */ @@ -223,12 +221,72 @@ static int rsa_parse_integer ( struct rsa_context *context, } /* Fail if cursor or integer are invalid */ - if ( ! integer->len ) { - DBGC ( context, "RSA %p invalid integer:\n", context ); - DBGC_HDA ( context, 0, raw->data, raw->len ); + if ( ! integer->len ) return -EINVAL; + + return 0; +} + +/** + * Parse RSA modulus and exponent + * + * @v modulus Modulus to fill in + * @v exponent Exponent to fill in + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int rsa_parse_mod_exp ( struct asn1_cursor *modulus, + struct asn1_cursor *exponent, + const struct asn1_cursor *raw ) { + struct asn1_bit_string bits; + struct asn1_cursor cursor; + int is_private; + int rc; + + /* Enter subjectPublicKeyInfo/RSAPrivateKey */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Determine key format */ + if ( asn1_type ( &cursor ) == ASN1_INTEGER ) { + + /* Private key */ + is_private = 1; + + /* Skip version */ + asn1_skip_any ( &cursor ); + + } else { + + /* Public key */ + is_private = 0; + + /* Skip algorithm */ + asn1_skip ( &cursor, ASN1_SEQUENCE ); + + /* Enter subjectPublicKey */ + if ( ( rc = asn1_integral_bit_string ( &cursor, &bits ) ) != 0 ) + return rc; + cursor.data = bits.data; + cursor.len = bits.len; + + /* Enter RSAPublicKey */ + asn1_enter ( &cursor, ASN1_SEQUENCE ); } + /* Extract modulus */ + if ( ( rc = rsa_parse_integer ( modulus, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Skip public exponent, if applicable */ + if ( is_private ) + asn1_skip ( &cursor, ASN1_INTEGER ); + + /* Extract publicExponent/privateExponent */ + if ( ( rc = rsa_parse_integer ( exponent, &cursor ) ) != 0 ) + return rc; + return 0; } @@ -242,11 +300,9 @@ static int rsa_parse_integer ( struct rsa_context *context, */ static int rsa_init ( void *ctx, const void *key, size_t key_len ) { struct rsa_context *context = ctx; - struct asn1_bit_string bits; struct asn1_cursor modulus; struct asn1_cursor exponent; struct asn1_cursor cursor; - int is_private; int rc; /* Initialise context */ @@ -256,47 +312,13 @@ static int rsa_init ( void *ctx, const void *key, size_t key_len ) { cursor.data = key; cursor.len = key_len; - /* Enter subjectPublicKeyInfo/RSAPrivateKey */ - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Determine key format */ - if ( asn1_type ( &cursor ) == ASN1_INTEGER ) { - /* Private key */ - is_private = 1; - - /* Skip version */ - asn1_skip_any ( &cursor ); - - } else { - /* Public key */ - is_private = 0; - - /* Skip algorithm */ - asn1_skip ( &cursor, ASN1_SEQUENCE ); - - /* Enter subjectPublicKey */ - if ( ( rc = asn1_integral_bit_string ( &cursor, &bits ) ) != 0 ) - goto err_parse; - cursor.data = bits.data; - cursor.len = bits.len; - - /* Enter RSAPublicKey */ - asn1_enter ( &cursor, ASN1_SEQUENCE ); + /* Parse modulus and exponent */ + if ( ( rc = rsa_parse_mod_exp ( &modulus, &exponent, &cursor ) ) != 0 ){ + DBGC ( context, "RSA %p invalid modulus/exponent:\n", context ); + DBGC_HDA ( context, 0, cursor.data, cursor.len ); + goto err_parse; } - /* Extract modulus */ - if ( ( rc = rsa_parse_integer ( context, &modulus, &cursor ) ) != 0 ) - goto err_parse; - asn1_skip_any ( &cursor ); - - /* Skip public exponent, if applicable */ - if ( is_private ) - asn1_skip ( &cursor, ASN1_INTEGER ); - - /* Extract publicExponent/privateExponent */ - if ( ( rc = rsa_parse_integer ( context, &exponent, &cursor ) ) != 0 ) - goto err_parse; - DBGC ( context, "RSA %p modulus:\n", context ); DBGC_HDA ( context, 0, modulus.data, modulus.len ); DBGC ( context, "RSA %p exponent:\n", context ); @@ -628,6 +650,46 @@ static void rsa_final ( void *ctx ) { rsa_free ( context ); } +/** + * Check for matching RSA public/private key pair + * + * @v private_key Private key + * @v private_key_len Private key length + * @v public_key Public key + * @v public_key_len Public key length + * @ret rc Return status code + */ +static int rsa_match ( const void *private_key, size_t private_key_len, + const void *public_key, size_t public_key_len ) { + struct asn1_cursor private_modulus; + struct asn1_cursor private_exponent; + struct asn1_cursor private_cursor; + struct asn1_cursor public_modulus; + struct asn1_cursor public_exponent; + struct asn1_cursor public_cursor; + int rc; + + /* Initialise cursors */ + private_cursor.data = private_key; + private_cursor.len = private_key_len; + public_cursor.data = public_key; + public_cursor.len = public_key_len; + + /* Parse moduli and exponents */ + if ( ( rc = rsa_parse_mod_exp ( &private_modulus, &private_exponent, + &private_cursor ) ) != 0 ) + return rc; + if ( ( rc = rsa_parse_mod_exp ( &public_modulus, &public_exponent, + &public_cursor ) ) != 0 ) + return rc; + + /* Compare moduli */ + if ( asn1_compare ( &private_modulus, &public_modulus ) != 0 ) + return -ENOTTY; + + return 0; +} + /** RSA public-key algorithm */ struct pubkey_algorithm rsa_algorithm = { .name = "rsa", @@ -639,4 +701,5 @@ struct pubkey_algorithm rsa_algorithm = { .sign = rsa_sign, .verify = rsa_verify, .final = rsa_final, + .match = rsa_match, }; diff --git a/src/include/ipxe/crypto.h b/src/include/ipxe/crypto.h index d7d42b66c..3eda5ec6e 100644 --- a/src/include/ipxe/crypto.h +++ b/src/include/ipxe/crypto.h @@ -157,6 +157,16 @@ struct pubkey_algorithm { * @v ctx Context */ void ( * final ) ( void *ctx ); + /** Check that public key matches private key + * + * @v private_key Private key + * @v private_key_len Private key length + * @v public_key Public key + * @v public_key_len Public key length + * @ret rc Return status code + */ + int ( * match ) ( const void *private_key, size_t private_key_len, + const void *public_key, size_t public_key_len ); }; static inline void digest_init ( struct digest_algorithm *digest, @@ -245,6 +255,14 @@ static inline void pubkey_final ( struct pubkey_algorithm *pubkey, void *ctx ) { pubkey->final ( ctx ); } +static inline int pubkey_match ( struct pubkey_algorithm *pubkey, + const void *private_key, + size_t private_key_len, const void *public_key, + size_t public_key_len ) { + return pubkey->match ( private_key, private_key_len, public_key, + public_key_len ); +} + extern struct digest_algorithm digest_null; extern struct cipher_algorithm cipher_null; extern struct pubkey_algorithm pubkey_null;