From 2dd3fffe18577baa9619623e627adacefd51fca9 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 26 Mar 2014 23:12:56 +0000 Subject: [crypto] Add pubkey_match() to check for matching public/private key pairs Signed-off-by: Michael Brown --- src/crypto/rsa.c | 115 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 89 insertions(+), 26 deletions(-) (limited to 'src/crypto') diff --git a/src/crypto/rsa.c b/src/crypto/rsa.c index 1a5cf6cd..0ab7b2ad 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,44 +221,35 @@ 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; } /** - * Initialise RSA cipher + * Parse RSA modulus and exponent * - * @v ctx RSA context - * @v key Key - * @v key_len Length of key + * @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_init ( void *ctx, const void *key, size_t key_len ) { - struct rsa_context *context = ctx; +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 modulus; - struct asn1_cursor exponent; struct asn1_cursor cursor; int is_private; int rc; - /* Initialise context */ - memset ( context, 0, sizeof ( *context ) ); - - /* Initialise cursor */ - cursor.data = key; - cursor.len = key_len; - /* 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; @@ -268,6 +257,7 @@ static int rsa_init ( void *ctx, const void *key, size_t key_len ) { asn1_skip_any ( &cursor ); } else { + /* Public key */ is_private = 0; @@ -276,7 +266,7 @@ static int rsa_init ( void *ctx, const void *key, size_t key_len ) { /* Enter subjectPublicKey */ if ( ( rc = asn1_integral_bit_string ( &cursor, &bits ) ) != 0 ) - goto err_parse; + return rc; cursor.data = bits.data; cursor.len = bits.len; @@ -285,8 +275,8 @@ static int rsa_init ( void *ctx, const void *key, size_t key_len ) { } /* Extract modulus */ - if ( ( rc = rsa_parse_integer ( context, &modulus, &cursor ) ) != 0 ) - goto err_parse; + if ( ( rc = rsa_parse_integer ( modulus, &cursor ) ) != 0 ) + return rc; asn1_skip_any ( &cursor ); /* Skip public exponent, if applicable */ @@ -294,8 +284,40 @@ static int rsa_init ( void *ctx, const void *key, size_t key_len ) { asn1_skip ( &cursor, ASN1_INTEGER ); /* Extract publicExponent/privateExponent */ - if ( ( rc = rsa_parse_integer ( context, &exponent, &cursor ) ) != 0 ) + if ( ( rc = rsa_parse_integer ( exponent, &cursor ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Initialise RSA cipher + * + * @v ctx RSA context + * @v key Key + * @v key_len Length of key + * @ret rc Return status code + */ +static int rsa_init ( void *ctx, const void *key, size_t key_len ) { + struct rsa_context *context = ctx; + struct asn1_cursor modulus; + struct asn1_cursor exponent; + struct asn1_cursor cursor; + int rc; + + /* Initialise context */ + memset ( context, 0, sizeof ( *context ) ); + + /* Initialise cursor */ + cursor.data = key; + cursor.len = key_len; + + /* 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; + } DBGC ( context, "RSA %p modulus:\n", context ); DBGC_HDA ( context, 0, modulus.data, modulus.len ); @@ -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, }; -- cgit v1.2.3-55-g7522