diff options
author | Michael Brown | 2014-03-27 00:12:56 +0100 |
---|---|---|
committer | Michael Brown | 2014-03-27 01:30:47 +0100 |
commit | 2dd3fffe18577baa9619623e627adacefd51fca9 (patch) | |
tree | fc9d2ac7a3e355846328d2570588f31849c43cdd | |
parent | [build] Add dependency of generated files upon Makefile (diff) | |
download | ipxe-2dd3fffe18577baa9619623e627adacefd51fca9.tar.gz ipxe-2dd3fffe18577baa9619623e627adacefd51fca9.tar.xz ipxe-2dd3fffe18577baa9619623e627adacefd51fca9.zip |
[crypto] Add pubkey_match() to check for matching public/private key pairs
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/crypto/rsa.c | 115 | ||||
-rw-r--r-- | src/include/ipxe/crypto.h | 18 |
2 files changed, 107 insertions, 26 deletions
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, }; diff --git a/src/include/ipxe/crypto.h b/src/include/ipxe/crypto.h index d7d42b66..3eda5ec6 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; |