]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Add pubkey_match() to check for matching public/private key pairs
authorMichael Brown <mcb30@ipxe.org>
Wed, 26 Mar 2014 23:12:56 +0000 (23:12 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 27 Mar 2014 00:30:47 +0000 (00:30 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/rsa.c
src/include/ipxe/crypto.h

index 1a5cf6cd51f1aa116f328125e933976d740ba7e0..0ab7b2ad34017e4991a042ce4db14d53f7250c27 100644 (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,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,
 };
index d7d42b66c3278cae0e0528290754672796151e99..3eda5ec6ee83e48f9697ba914be17c3896a11bdc 100644 (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;