diff options
author | Michael Brown <mcb30@ipxe.org> | 2022-10-11 13:47:06 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2022-10-11 14:37:12 +0100 |
commit | 028aac99a397f591de6cc6f6f2b4763f55aa8962 (patch) | |
tree | e42ad5ba0e477d3614519125aa3a1252dae4ae20 | |
parent | 1a7317e7d46f134f21244f6d272f90648beda4e7 (diff) | |
download | ipxe-028aac99a397f591de6cc6f6f2b4763f55aa8962.zip ipxe-028aac99a397f591de6cc6f6f2b4763f55aa8962.tar.gz ipxe-028aac99a397f591de6cc6f6f2b4763f55aa8962.tar.bz2 |
[tls] Generate pre-master secret at point of sending ClientKeyExchange
The pre-master secret is currently constructed at the time of
instantiating the TLS connection. This precludes the use of key
exchange mechanisms such as Ephemeral Diffie-Hellman (DHE), which
require a ServerKeyExchange message to exchange additional key
material before the pre-master secret can be constructed.
Allow for the use of such cipher suites by deferring generation of the
master secret until the point of sending the ClientKeyExchange
message.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/include/ipxe/tls.h | 13 | ||||
-rw-r--r-- | src/net/tls.c | 40 |
2 files changed, 27 insertions, 26 deletions
diff --git a/src/include/ipxe/tls.h b/src/include/ipxe/tls.h index 8b03579..6560897 100644 --- a/src/include/ipxe/tls.h +++ b/src/include/ipxe/tls.h @@ -48,6 +48,9 @@ struct tls_header { /** TLS version 1.2 */ #define TLS_VERSION_TLS_1_2 0x0303 +/** Maximum supported TLS version */ +#define TLS_VERSION_MAX TLS_VERSION_TLS_1_2 + /** Change cipher content type */ #define TLS_TYPE_CHANGE_CIPHER 20 @@ -209,14 +212,6 @@ struct tls_signature_hash_algorithm { #define __tls_sig_hash_algorithm \ __table_entry ( TLS_SIG_HASH_ALGORITHMS, 01 ) -/** TLS pre-master secret */ -struct tls_pre_master_secret { - /** TLS version */ - uint16_t version; - /** Random data */ - uint8_t random[46]; -} __attribute__ (( packed )); - /** TLS client random data */ struct tls_client_random { /** GMT Unix time */ @@ -309,8 +304,6 @@ struct tls_connection { struct tls_cipherspec rx_cipherspec; /** Next RX cipher specification */ struct tls_cipherspec rx_cipherspec_pending; - /** Premaster secret */ - struct tls_pre_master_secret pre_master_secret; /** Master secret */ uint8_t master_secret[48]; /** Server random bytes */ diff --git a/src/net/tls.c b/src/net/tls.c index 89ed6fc..4fb5b17 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -616,21 +616,23 @@ static void tls_prf ( struct tls_connection *tls, const void *secret, * Generate master secret * * @v tls TLS connection + * @v pre_master_secret Pre-master secret + * @v pre_master_secret_len Length of pre-master secret * - * The pre-master secret and the client and server random values must - * already be known. + * The client and server random values must already be known. */ -static void tls_generate_master_secret ( struct tls_connection *tls ) { +static void tls_generate_master_secret ( struct tls_connection *tls, + const void *pre_master_secret, + size_t pre_master_secret_len ) { + DBGC ( tls, "TLS %p pre-master-secret:\n", tls ); - DBGC_HD ( tls, &tls->pre_master_secret, - sizeof ( tls->pre_master_secret ) ); + DBGC_HD ( tls, pre_master_secret, pre_master_secret_len ); DBGC ( tls, "TLS %p client random bytes:\n", tls ); DBGC_HD ( tls, &tls->client_random, sizeof ( tls->client_random ) ); DBGC ( tls, "TLS %p server random bytes:\n", tls ); DBGC_HD ( tls, &tls->server_random, sizeof ( tls->server_random ) ); - tls_prf_label ( tls, &tls->pre_master_secret, - sizeof ( tls->pre_master_secret ), + tls_prf_label ( tls, pre_master_secret, pre_master_secret_len, &tls->master_secret, sizeof ( tls->master_secret ), "master secret", &tls->client_random, sizeof ( tls->client_random ), @@ -1212,6 +1214,10 @@ static int tls_send_client_key_exchange ( struct tls_connection *tls ) { struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey; size_t max_len = pubkey_max_len ( pubkey, cipherspec->pubkey_ctx ); struct { + uint16_t version; + uint8_t random[46]; + } __attribute__ (( packed )) pre_master_secret; + struct { uint32_t type_length; uint16_t encrypted_pre_master_secret_len; uint8_t encrypted_pre_master_secret[max_len]; @@ -1220,8 +1226,16 @@ static int tls_send_client_key_exchange ( struct tls_connection *tls ) { int len; int rc; + /* Generate pre-master secret */ + pre_master_secret.version = htons ( TLS_VERSION_MAX ); + if ( ( rc = tls_generate_random ( tls, &pre_master_secret.random, + ( sizeof ( pre_master_secret.random ) ) ) ) != 0 ) { + return rc; + } + /* Generate master secret */ - tls_generate_master_secret ( tls ); + tls_generate_master_secret ( tls, &pre_master_secret, + sizeof ( pre_master_secret ) ); /* Generate keys */ if ( ( rc = tls_generate_keys ( tls ) ) != 0 ) { @@ -1233,8 +1247,7 @@ static int tls_send_client_key_exchange ( struct tls_connection *tls ) { /* Encrypt pre-master secret using server's public key */ memset ( &key_xchg, 0, sizeof ( key_xchg ) ); len = pubkey_encrypt ( pubkey, cipherspec->pubkey_ctx, - &tls->pre_master_secret, - sizeof ( tls->pre_master_secret ), + &pre_master_secret, sizeof ( pre_master_secret ), key_xchg.encrypted_pre_master_secret ); if ( len < 0 ) { rc = len; @@ -3173,7 +3186,7 @@ int add_tls ( struct interface *xfer, const char *name, &tls->refcnt ); tls->key = privkey_get ( key ? key : &private_key ); tls->root = x509_root_get ( root ? root : &root_certificates ); - tls->version = TLS_VERSION_TLS_1_2; + tls->version = TLS_VERSION_MAX; tls_clear_cipher ( tls, &tls->tx_cipherspec ); tls_clear_cipher ( tls, &tls->tx_cipherspec_pending ); tls_clear_cipher ( tls, &tls->rx_cipherspec ); @@ -3186,11 +3199,6 @@ int add_tls ( struct interface *xfer, const char *name, ( sizeof ( tls->client_random.random ) ) ) ) != 0 ) { goto err_random; } - tls->pre_master_secret.version = htons ( tls->version ); - if ( ( rc = tls_generate_random ( tls, &tls->pre_master_secret.random, - ( sizeof ( tls->pre_master_secret.random ) ) ) ) != 0 ) { - goto err_random; - } if ( ( rc = tls_session ( tls, name ) ) != 0 ) goto err_session; list_add_tail ( &tls->list, &tls->session->conn ); |