diff options
author | Michael Brown <mcb30@ipxe.org> | 2012-03-18 14:44:53 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2012-03-18 14:44:53 +0000 |
commit | dc87161c300e01fa5a6cca11af7fad22ea6cded9 (patch) | |
tree | 477e4be1e0e2db75f414a5bf34703a311da8e404 | |
parent | 7fb064470f8a7128daab3ed52e954f4269214f75 (diff) | |
download | ipxe-dc87161c300e01fa5a6cca11af7fad22ea6cded9.tar.gz |
[tls] Use iPXE native RSA algorithm
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/crypto/x509.c | 156 | ||||
-rw-r--r-- | src/include/ipxe/tls.h | 3 | ||||
-rw-r--r-- | src/include/ipxe/x509.h | 23 | ||||
-rw-r--r-- | src/net/tls.c | 88 |
4 files changed, 68 insertions, 202 deletions
diff --git a/src/crypto/x509.c b/src/crypto/x509.c index c09c5ebd5..a13b671a5 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -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; } diff --git a/src/include/ipxe/tls.h b/src/include/ipxe/tls.h index 804e1a1fb..a2504f19c 100644 --- a/src/include/ipxe/tls.h +++ b/src/include/ipxe/tls.h @@ -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 */ diff --git a/src/include/ipxe/x509.h b/src/include/ipxe/x509.h index 2ea21aa9c..f8cffabdb 100644 --- a/src/include/ipxe/x509.h +++ b/src/include/ipxe/x509.h @@ -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 ); diff --git a/src/net/tls.c b/src/net/tls.c index dfd19a0a4..7ec5745ff 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -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 ); |