mirror of https://github.com/ipxe/ipxe.git
[crypto] Add pubkey_match() to check for matching public/private key pairs
Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/17/head
parent
c27b3c7c33
commit
2dd3fffe18
155
src/crypto/rsa.c
155
src/crypto/rsa.c
|
@ -202,13 +202,11 @@ static int rsa_alloc ( struct rsa_context *context, size_t modulus_len,
|
||||||
/**
|
/**
|
||||||
* Parse RSA integer
|
* Parse RSA integer
|
||||||
*
|
*
|
||||||
* @v context RSA context
|
|
||||||
* @v integer Integer to fill in
|
* @v integer Integer to fill in
|
||||||
* @v raw ASN.1 cursor
|
* @v raw ASN.1 cursor
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int rsa_parse_integer ( struct rsa_context *context,
|
static int rsa_parse_integer ( struct asn1_cursor *integer,
|
||||||
struct asn1_cursor *integer,
|
|
||||||
const struct asn1_cursor *raw ) {
|
const struct asn1_cursor *raw ) {
|
||||||
|
|
||||||
/* Enter integer */
|
/* Enter integer */
|
||||||
|
@ -223,12 +221,72 @@ static int rsa_parse_integer ( struct rsa_context *context,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fail if cursor or integer are invalid */
|
/* Fail if cursor or integer are invalid */
|
||||||
if ( ! integer->len ) {
|
if ( ! integer->len )
|
||||||
DBGC ( context, "RSA %p invalid integer:\n", context );
|
|
||||||
DBGC_HDA ( context, 0, raw->data, raw->len );
|
|
||||||
return -EINVAL;
|
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;
|
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 ) {
|
static int rsa_init ( void *ctx, const void *key, size_t key_len ) {
|
||||||
struct rsa_context *context = ctx;
|
struct rsa_context *context = ctx;
|
||||||
struct asn1_bit_string bits;
|
|
||||||
struct asn1_cursor modulus;
|
struct asn1_cursor modulus;
|
||||||
struct asn1_cursor exponent;
|
struct asn1_cursor exponent;
|
||||||
struct asn1_cursor cursor;
|
struct asn1_cursor cursor;
|
||||||
int is_private;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Initialise context */
|
/* Initialise context */
|
||||||
|
@ -256,47 +312,13 @@ static int rsa_init ( void *ctx, const void *key, size_t key_len ) {
|
||||||
cursor.data = key;
|
cursor.data = key;
|
||||||
cursor.len = key_len;
|
cursor.len = key_len;
|
||||||
|
|
||||||
/* Enter subjectPublicKeyInfo/RSAPrivateKey */
|
/* Parse modulus and exponent */
|
||||||
asn1_enter ( &cursor, ASN1_SEQUENCE );
|
if ( ( rc = rsa_parse_mod_exp ( &modulus, &exponent, &cursor ) ) != 0 ){
|
||||||
|
DBGC ( context, "RSA %p invalid modulus/exponent:\n", context );
|
||||||
/* Determine key format */
|
DBGC_HDA ( context, 0, cursor.data, cursor.len );
|
||||||
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;
|
goto err_parse;
|
||||||
cursor.data = bits.data;
|
|
||||||
cursor.len = bits.len;
|
|
||||||
|
|
||||||
/* Enter RSAPublicKey */
|
|
||||||
asn1_enter ( &cursor, ASN1_SEQUENCE );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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 ( context, "RSA %p modulus:\n", context );
|
||||||
DBGC_HDA ( context, 0, modulus.data, modulus.len );
|
DBGC_HDA ( context, 0, modulus.data, modulus.len );
|
||||||
DBGC ( context, "RSA %p exponent:\n", context );
|
DBGC ( context, "RSA %p exponent:\n", context );
|
||||||
|
@ -628,6 +650,46 @@ static void rsa_final ( void *ctx ) {
|
||||||
rsa_free ( context );
|
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 */
|
/** RSA public-key algorithm */
|
||||||
struct pubkey_algorithm rsa_algorithm = {
|
struct pubkey_algorithm rsa_algorithm = {
|
||||||
.name = "rsa",
|
.name = "rsa",
|
||||||
|
@ -639,4 +701,5 @@ struct pubkey_algorithm rsa_algorithm = {
|
||||||
.sign = rsa_sign,
|
.sign = rsa_sign,
|
||||||
.verify = rsa_verify,
|
.verify = rsa_verify,
|
||||||
.final = rsa_final,
|
.final = rsa_final,
|
||||||
|
.match = rsa_match,
|
||||||
};
|
};
|
||||||
|
|
|
@ -157,6 +157,16 @@ struct pubkey_algorithm {
|
||||||
* @v ctx Context
|
* @v ctx Context
|
||||||
*/
|
*/
|
||||||
void ( * final ) ( void *ctx );
|
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,
|
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 );
|
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 digest_algorithm digest_null;
|
||||||
extern struct cipher_algorithm cipher_null;
|
extern struct cipher_algorithm cipher_null;
|
||||||
extern struct pubkey_algorithm pubkey_null;
|
extern struct pubkey_algorithm pubkey_null;
|
||||||
|
|
Loading…
Reference in New Issue