aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2022-10-11 13:47:06 +0100
committerMichael Brown <mcb30@ipxe.org>2022-10-11 14:37:12 +0100
commit028aac99a397f591de6cc6f6f2b4763f55aa8962 (patch)
treee42ad5ba0e477d3614519125aa3a1252dae4ae20
parent1a7317e7d46f134f21244f6d272f90648beda4e7 (diff)
downloadipxe-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.h13
-rw-r--r--src/net/tls.c40
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 );