]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[tls] Generate pre-master secret at point of sending ClientKeyExchange
authorMichael Brown <mcb30@ipxe.org>
Tue, 11 Oct 2022 12:47:06 +0000 (13:47 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 11 Oct 2022 13:37:12 +0000 (14:37 +0100)
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>
src/include/ipxe/tls.h
src/net/tls.c

index 8b03579cc6c10c4f6e289b2068a7398bcba95c8e..65608970a5757d40a20c4c1c284e0c1328fafe23 100644 (file)
@@ -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 */
index 89ed6fceb75ab8ff70f54f270fc06a9bf0d22956..4fb5b179e85621779d8d2319c78b632149a22963 100644 (file)
@@ -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 ),
@@ -1211,6 +1213,10 @@ static int tls_send_client_key_exchange ( struct tls_connection *tls ) {
        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 {
+               uint16_t version;
+               uint8_t random[46];
+       } __attribute__ (( packed )) pre_master_secret;
        struct {
                uint32_t type_length;
                uint16_t encrypted_pre_master_secret_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 );