summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/crypto/rsa.c115
-rw-r--r--src/include/ipxe/crypto.h18
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;