]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[tls] Use iPXE native RSA algorithm
authorMichael Brown <mcb30@ipxe.org>
Sun, 18 Mar 2012 14:44:53 +0000 (14:44 +0000)
committerMichael Brown <mcb30@ipxe.org>
Sun, 18 Mar 2012 14:44:53 +0000 (14:44 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/x509.c
src/include/ipxe/tls.h
src/include/ipxe/x509.h
src/net/tls.c

index c09c5ebd5267aa887508625f341181f7ee6d318f..a13b671a59d21a9be2ad570996a313189dd2e571 100644 (file)
@@ -33,161 +33,33 @@ FILE_LICENCE ( GPL2_OR_LATER );
  * documented in RFC2313.
  */
 
-/** Object Identifier for "rsaEncryption" (1.2.840.113549.1.1.1) */
-static const uint8_t oid_rsa_encryption[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
-                                             0x0d, 0x01, 0x01, 0x01 };
-
 /**
- * Identify X.509 certificate public key
+ * Identify X.509 certificate RSA public key
  *
  * @v certificate      Certificate
- * @v algorithm                Public key algorithm to fill in
- * @v pubkey           Public key value to fill in
+ * @v rsa              RSA public key to fill in
  * @ret rc             Return status code
  */
-static int x509_public_key ( const struct asn1_cursor *certificate,
-                            struct asn1_cursor *algorithm,
-                            struct asn1_cursor *pubkey ) {
-       struct asn1_cursor cursor;
+int x509_rsa_public_key ( const struct asn1_cursor *certificate,
+                         struct x509_rsa_public_key *key ) {
+       struct asn1_cursor *cursor = &key->raw;
        int rc;
 
        /* Locate subjectPublicKeyInfo */
-       memcpy ( &cursor, certificate, sizeof ( cursor ) );
-       rc = ( asn1_enter ( &cursor, ASN1_SEQUENCE ), /* Certificate */
-              asn1_enter ( &cursor, ASN1_SEQUENCE ), /* tbsCertificate */
-              asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG(0) ),/*version*/
-              asn1_skip ( &cursor, ASN1_INTEGER ), /* serialNumber */
-              asn1_skip ( &cursor, ASN1_SEQUENCE ), /* signature */
-              asn1_skip ( &cursor, ASN1_SEQUENCE ), /* issuer */
-              asn1_skip ( &cursor, ASN1_SEQUENCE ), /* validity */
-              asn1_skip ( &cursor, ASN1_SEQUENCE ), /* name */
-              asn1_enter ( &cursor, ASN1_SEQUENCE )/* subjectPublicKeyInfo*/);
+       memcpy ( cursor, certificate, sizeof ( *cursor ) );
+       rc = ( asn1_enter ( cursor, ASN1_SEQUENCE ), /* Certificate */
+              asn1_enter ( cursor, ASN1_SEQUENCE ), /* tbsCertificate */
+              asn1_skip_if_exists ( cursor, ASN1_EXPLICIT_TAG(0) ),/*version*/
+              asn1_skip ( cursor, ASN1_INTEGER ), /* serialNumber */
+              asn1_skip ( cursor, ASN1_SEQUENCE ), /* signature */
+              asn1_skip ( cursor, ASN1_SEQUENCE ), /* issuer */
+              asn1_skip ( cursor, ASN1_SEQUENCE ), /* validity */
+              asn1_skip ( cursor, ASN1_SEQUENCE ) /* name */ );
        if ( rc != 0 ) {
                DBG ( "Cannot locate subjectPublicKeyInfo in:\n" );
                DBG_HDA ( 0, certificate->data, certificate->len );
                return rc;
        }
 
-       /* Locate algorithm */
-       memcpy ( algorithm, &cursor, sizeof ( *algorithm ) );
-       rc = ( asn1_enter ( algorithm, ASN1_SEQUENCE ) /* algorithm */ );
-       if ( rc != 0 ) {
-               DBG ( "Cannot locate algorithm in:\n" );
-               DBG_HDA ( 0, certificate->data, certificate->len );
-               return rc;
-       }
-
-       /* Locate subjectPublicKey */
-       memcpy ( pubkey, &cursor, sizeof ( *pubkey ) );
-       rc = ( asn1_skip ( pubkey, ASN1_SEQUENCE ), /* algorithm */
-              asn1_enter ( pubkey, ASN1_BIT_STRING ) /* subjectPublicKey*/ );
-       if ( rc != 0 ) {
-               DBG ( "Cannot locate subjectPublicKey in:\n" );
-               DBG_HDA ( 0, certificate->data, certificate->len );
-               return rc;
-       }
-
-       return 0;
-}
-
-/**
- * Identify X.509 certificate RSA modulus and public exponent
- *
- * @v certificate      Certificate
- * @v rsa              RSA public key to fill in
- * @ret rc             Return status code
- *
- * The caller is responsible for eventually calling
- * x509_free_rsa_public_key() to free the storage allocated to hold
- * the RSA modulus and exponent.
- */
-int x509_rsa_public_key ( const struct asn1_cursor *certificate,
-                         struct x509_rsa_public_key *rsa_pubkey ) {
-       struct asn1_cursor algorithm;
-       struct asn1_cursor pubkey;
-       struct asn1_cursor modulus;
-       struct asn1_cursor exponent;
-       int rc;
-
-       /* First, extract the public key algorithm and key data */
-       if ( ( rc = x509_public_key ( certificate, &algorithm,
-                                     &pubkey ) ) != 0 )
-               return rc;
-
-       /* Check that algorithm is RSA */
-       rc = ( asn1_enter ( &algorithm, ASN1_OID ) /* algorithm */ );
-       if ( rc != 0 ) {
-               DBG ( "Cannot locate algorithm:\n" );
-               DBG_HDA ( 0, certificate->data, certificate->len );
-       return rc;
-       }
-       if ( ( algorithm.len != sizeof ( oid_rsa_encryption ) ) ||
-            ( memcmp ( algorithm.data, &oid_rsa_encryption,
-                       sizeof ( oid_rsa_encryption ) ) != 0 ) ) {
-               DBG ( "algorithm is not rsaEncryption in:\n" );
-               DBG_HDA ( 0, certificate->data, certificate->len );
-               return -ENOTSUP;
-       }
-
-       /* Check that public key is a byte string, i.e. that the
-        * "unused bits" byte contains zero.
-        */
-       if ( ( pubkey.len < 1 ) ||
-            ( ( *( uint8_t * ) pubkey.data ) != 0 ) ) {
-               DBG ( "subjectPublicKey is not a byte string in:\n" );
-               DBG_HDA ( 0, certificate->data, certificate->len );
-               return -ENOTSUP;
-       }
-       pubkey.data++;
-       pubkey.len--;
-
-       /* Pick out the modulus and exponent */
-       rc = ( asn1_enter ( &pubkey, ASN1_SEQUENCE ) /* RSAPublicKey */ );
-       if ( rc != 0 ) {
-               DBG ( "Cannot locate RSAPublicKey in:\n" );
-               DBG_HDA ( 0, certificate->data, certificate->len );
-               return -ENOTSUP;
-       }
-       memcpy ( &modulus, &pubkey, sizeof ( modulus ) );
-       rc = ( asn1_enter ( &modulus, ASN1_INTEGER ) /* modulus */ );
-       if ( rc != 0 ) {
-               DBG ( "Cannot locate modulus in:\n" );
-               DBG_HDA ( 0, certificate->data, certificate->len );
-               return -ENOTSUP;
-       }
-       if ( modulus.len && ( ! *( ( uint8_t * ) modulus.data ) ) ) {
-               /* Skip positive sign byte */
-               modulus.data++;
-               modulus.len--;
-       }
-       memcpy ( &exponent, &pubkey, sizeof ( exponent ) );
-       rc = ( asn1_skip ( &exponent, ASN1_INTEGER ), /* modulus */
-              asn1_enter ( &exponent, ASN1_INTEGER ) /* publicExponent */ );
-       if ( rc != 0 ) {
-               DBG ( "Cannot locate publicExponent in:\n" );
-               DBG_HDA ( 0, certificate->data, certificate->len );
-               return -ENOTSUP;
-       }
-       if ( exponent.len && ( ! *( ( uint8_t * ) exponent.data ) ) ) {
-               /* Skip positive sign byte */
-               exponent.data++;
-               exponent.len--;
-       }
-
-       /* Allocate space and copy out modulus and exponent */
-       rsa_pubkey->modulus = malloc ( modulus.len + exponent.len );
-       if ( ! rsa_pubkey->modulus )
-               return -ENOMEM;
-       rsa_pubkey->exponent = ( rsa_pubkey->modulus + modulus.len );
-       memcpy ( rsa_pubkey->modulus, modulus.data, modulus.len );
-       rsa_pubkey->modulus_len = modulus.len;
-       memcpy ( rsa_pubkey->exponent, exponent.data, exponent.len );
-       rsa_pubkey->exponent_len = exponent.len;
-
-       DBG2 ( "RSA modulus:\n" );
-       DBG2_HDA ( 0, rsa_pubkey->modulus, rsa_pubkey->modulus_len );
-       DBG2 ( "RSA exponent:\n" );
-       DBG2_HDA ( 0, rsa_pubkey->exponent, rsa_pubkey->exponent_len );
-
        return 0;
 }
index 804e1a1fb8035e30fe201911c4ec2cafd7987769..a2504f19cb22a006d85e24dff0ef918fb1d43212 100644 (file)
@@ -182,9 +182,6 @@ struct tls_session {
        /** SHA256 context for handshake verification */
        uint8_t handshake_sha256_ctx[SHA256_CTX_SIZE];
 
-       /** Hack: server RSA public key */
-       struct x509_rsa_public_key rsa;
-
        /** TX sequence number */
        uint64_t tx_seq;
        /** TX pending transmissions */
index 2ea21aa9cffd9fb36d22484499b0712f5b6175c3..f8cffabdb30054eaef607438d7df8fb163347bda 100644 (file)
@@ -11,31 +11,14 @@ FILE_LICENCE ( GPL2_OR_LATER );
 
 #include <stdint.h>
 #include <stdlib.h>
-
-struct asn1_cursor;
+#include <ipxe/asn1.h>
 
 /** An X.509 RSA public key */
 struct x509_rsa_public_key {
-       /** Modulus */
-       uint8_t *modulus;
-       /** Modulus length */
-       size_t modulus_len;
-       /** Exponent */
-       uint8_t *exponent;
-       /** Exponent length */
-       size_t exponent_len;
+       /** Raw public key */
+       struct asn1_cursor raw;
 };
 
-/**
- * Free X.509 RSA public key
- *
- * @v rsa_pubkey       RSA public key
- */
-static inline void
-x509_free_rsa_public_key ( struct x509_rsa_public_key *rsa_pubkey ) {
-       free ( rsa_pubkey->modulus );
-}
-
 extern int x509_rsa_public_key ( const struct asn1_cursor *certificate,
                                 struct x509_rsa_public_key *rsa_pubkey );
 
index dfd19a0a40b691bc2d28930a8ed695a9e7a89341..7ec5745ffb745db6e9d23e7a51417ad705a78368 100644 (file)
@@ -39,7 +39,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/iobuf.h>
 #include <ipxe/xfer.h>
 #include <ipxe/open.h>
-#include <ipxe/asn1.h>
 #include <ipxe/x509.h>
 #include <ipxe/rbg.h>
 #include <ipxe/tls.h>
@@ -90,7 +89,6 @@ static void free_tls ( struct refcnt *refcnt ) {
        tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
        tls_clear_cipher ( tls, &tls->rx_cipherspec );
        tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
-       x509_free_rsa_public_key ( &tls->rsa );
        free ( tls->rx_data );
 
        /* Free TLS structure itself */
@@ -437,28 +435,28 @@ struct tls_cipher_suite tls_cipher_suites[] = {
        {
                .code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA256 ),
                .key_len = ( 256 / 8 ),
-               .pubkey = &pubkey_null, /* FIXME */
+               .pubkey = &rsa_algorithm,
                .cipher = &aes_cbc_algorithm,
                .digest = &sha256_algorithm,
        },
        {
                .code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA256 ),
                .key_len = ( 128 / 8 ),
-               .pubkey = &pubkey_null, /* FIXME */
+               .pubkey = &rsa_algorithm,
                .cipher = &aes_cbc_algorithm,
                .digest = &sha256_algorithm,
        },
        {
                .code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA ),
                .key_len = ( 256 / 8 ),
-               .pubkey = &pubkey_null, /* FIXME */
+               .pubkey = &rsa_algorithm,
                .cipher = &aes_cbc_algorithm,
                .digest = &sha1_algorithm,
        },
        {
                .code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA ),
                .key_len = ( 128 / 8 ),
-               .pubkey = &pubkey_null, /* FIXME */
+               .pubkey = &rsa_algorithm,
                .cipher = &aes_cbc_algorithm,
                .digest = &sha1_algorithm,
        },
@@ -496,6 +494,11 @@ tls_find_cipher_suite ( unsigned int cipher_suite ) {
  */
 static void tls_clear_cipher ( struct tls_session *tls __unused,
                               struct tls_cipherspec *cipherspec ) {
+
+       if ( cipherspec->suite ) {
+               pubkey_final ( cipherspec->suite->pubkey,
+                              cipherspec->pubkey_ctx );
+       }
        free ( cipherspec->dynamic );
        memset ( cipherspec, 0, sizeof ( cipherspec ) );
        cipherspec->suite = &tls_cipher_suite_null;
@@ -523,13 +526,12 @@ static int tls_set_cipher ( struct tls_session *tls,
        
        /* Allocate dynamic storage */
        total = ( pubkey->ctxsize + 2 * cipher->ctxsize + digest->digestsize );
-       dynamic = malloc ( total );
+       dynamic = zalloc ( total );
        if ( ! dynamic ) {
                DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto "
                       "context\n", tls, total );
                return -ENOMEM;
        }
-       memset ( dynamic, 0, total );
 
        /* Assign storage */
        cipherspec->dynamic = dynamic;
@@ -793,37 +795,38 @@ static int tls_send_certificate ( struct tls_session *tls ) {
  * @ret rc             Return status code
  */
 static int tls_send_client_key_exchange ( struct tls_session *tls ) {
-       /* FIXME: Hack alert */
-       RSA_CTX *rsa_ctx = NULL;
-       RSA_pub_key_new ( &rsa_ctx, tls->rsa.modulus, tls->rsa.modulus_len,
-                         tls->rsa.exponent, tls->rsa.exponent_len );
+       struct tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
+       struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
+       size_t max_len = pubkey_max_len ( pubkey, cipherspec->pubkey_ctx );
        struct {
                uint32_t type_length;
                uint16_t encrypted_pre_master_secret_len;
-               uint8_t encrypted_pre_master_secret[rsa_ctx->num_octets];
+               uint8_t encrypted_pre_master_secret[max_len];
        } __attribute__ (( packed )) key_xchg;
+       size_t unused;
+       int len;
+       int rc;
 
+       /* Encrypt pre-master secret using server's public key */
        memset ( &key_xchg, 0, sizeof ( key_xchg ) );
-       key_xchg.type_length = ( cpu_to_le32 ( TLS_CLIENT_KEY_EXCHANGE ) |
-                                htonl ( sizeof ( key_xchg ) -
-                                        sizeof ( key_xchg.type_length ) ) );
-       key_xchg.encrypted_pre_master_secret_len
-               = htons ( sizeof ( key_xchg.encrypted_pre_master_secret ) );
-
-       /* FIXME: Hack alert */
-       DBGC ( tls, "RSA encrypting plaintext, modulus, exponent:\n" );
-       DBGC_HD ( tls, &tls->pre_master_secret,
-                 sizeof ( tls->pre_master_secret ) );
-       DBGC_HD ( tls, tls->rsa.modulus, tls->rsa.modulus_len );
-       DBGC_HD ( tls, tls->rsa.exponent, tls->rsa.exponent_len );
-       RSA_encrypt ( rsa_ctx, ( const uint8_t * ) &tls->pre_master_secret,
-                     sizeof ( tls->pre_master_secret ),
-                     key_xchg.encrypted_pre_master_secret, 0 );
-       DBGC ( tls, "RSA encrypt done.  Ciphertext:\n" );
-       DBGC_HD ( tls, &key_xchg.encrypted_pre_master_secret,
-                 sizeof ( key_xchg.encrypted_pre_master_secret ) );
-       RSA_free ( rsa_ctx );
-
+       len = pubkey_encrypt ( pubkey, cipherspec->pubkey_ctx,
+                              &tls->pre_master_secret,
+                              sizeof ( tls->pre_master_secret ),
+                              key_xchg.encrypted_pre_master_secret );
+       if ( len < 0 ) {
+               rc = len;
+               DBGC ( tls, "TLS %p could not encrypt pre-master secret: %s\n",
+                      tls, strerror ( rc ) );
+               return rc;
+       }
+       unused = ( max_len - len );
+       key_xchg.type_length =
+               ( cpu_to_le32 ( TLS_CLIENT_KEY_EXCHANGE ) |
+                 htonl ( sizeof ( key_xchg ) -
+                         sizeof ( key_xchg.type_length ) - unused ) );
+       key_xchg.encrypted_pre_master_secret_len =
+               htons ( sizeof ( key_xchg.encrypted_pre_master_secret ) -
+                       unused );
 
        return tls_send_handshake ( tls, &key_xchg, sizeof ( key_xchg ) );
 }
@@ -1021,7 +1024,10 @@ static int tls_new_certificate ( struct tls_session *tls,
                  ( ( void * ) certificate->certificates );
        size_t elements_len = tls_uint24 ( certificate->length );
        const void *end = ( certificate->certificates + elements_len );
+       struct tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
+       struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
        struct asn1_cursor cursor;
+       struct x509_rsa_public_key key;
        int rc;
 
        /* Sanity check */
@@ -1044,12 +1050,20 @@ static int tls_new_certificate ( struct tls_session *tls,
                }
 
                // HACK
-               if ( ( rc = x509_rsa_public_key ( &cursor,
-                                                 &tls->rsa ) ) != 0 ) {
-                       DBGC ( tls, "TLS %p cannot determine RSA public key: "
-                              "%s\n", tls, strerror ( rc ) );
+               if ( ( rc = x509_rsa_public_key ( &cursor, &key ) ) != 0 ) {
+                       DBGC ( tls, "TLS %p cannot parse public key: %s\n",
+                              tls, strerror ( rc ) );
+                       return rc;
+               }
+
+               /* Initialise public key algorithm */
+               if ( ( rc = pubkey_init ( pubkey, cipherspec->pubkey_ctx,
+                                         key.raw.data, key.raw.len ) ) != 0){
+                       DBGC ( tls, "TLS %p cannot initialise public key: %s\n",
+                              tls, strerror ( rc ) );
                        return rc;
                }
+
                return 0;
 
                element = ( cursor.data + cursor.len );