david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[crypto] Add pubkey_match() to check for matching public/private key pairs

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2014-03-26 23:12:56 +00:00
parent c27b3c7c33
commit 2dd3fffe18
2 changed files with 128 additions and 47 deletions

View File

@ -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,
};

View File

@ -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;