]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[tls] Record ServerKeyExchange record, if provided
authorMichael Brown <mcb30@ipxe.org>
Tue, 11 Oct 2022 12:49:57 +0000 (13:49 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 11 Oct 2022 13:37:12 +0000 (14:37 +0100)
Accept and record the ServerKeyExchange record, which is required for
key exchange mechanisms such as Ephemeral Diffie-Hellman (DHE).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/tls.h
src/net/tls.c

index 65608970a5757d40a20c4c1c284e0c1328fafe23..672cfbd7e961e052d7bf9bbdda2a374dd66e3afb 100644 (file)
@@ -310,6 +310,10 @@ struct tls_connection {
        uint8_t server_random[32];
        /** Client random bytes */
        struct tls_client_random client_random;
+       /** Server Key Exchange record (if any) */
+       void *server_key;
+       /** Server Key Exchange record length */
+       size_t server_key_len;
        /** MD5+SHA1 context for handshake verification */
        uint8_t handshake_md5_sha1_ctx[MD5_SHA1_CTX_SIZE];
        /** SHA256 context for handshake verification */
index 4fb5b179e85621779d8d2319c78b632149a22963..a1ffcacd7ed5a63ed39344ea578c7d5c2eae00ca 100644 (file)
@@ -377,6 +377,7 @@ 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 );
+       free ( tls->server_key );
        list_for_each_entry_safe ( iobuf, tmp, &tls->rx_data, list ) {
                list_del ( &iobuf->list );
                free_iob ( iobuf );
@@ -1867,6 +1868,37 @@ static int tls_new_certificate ( struct tls_connection *tls,
        return 0;
 }
 
+/**
+ * Receive new Server Key Exchange handshake record
+ *
+ * @v tls              TLS connection
+ * @v data             Plaintext handshake record
+ * @v len              Length of plaintext handshake record
+ * @ret rc             Return status code
+ */
+static int tls_new_server_key_exchange ( struct tls_connection *tls,
+                                        const void *data, size_t len ) {
+
+       /* Free any existing server key exchange record */
+       free ( tls->server_key );
+       tls->server_key_len = 0;
+
+       /* Allocate copy of server key exchange record */
+       tls->server_key = malloc ( len );
+       if ( ! tls->server_key )
+               return -ENOMEM;
+
+       /* Store copy of server key exchange record for later
+        * processing.  We cannot verify the signature at this point
+        * since the certificate validation will not yet have
+        * completed.
+        */
+       memcpy ( tls->server_key, data, len );
+       tls->server_key_len = len;
+
+       return 0;
+}
+
 /**
  * Receive new Certificate Request handshake record
  *
@@ -2100,6 +2132,10 @@ static int tls_new_handshake ( struct tls_connection *tls,
                case TLS_CERTIFICATE:
                        rc = tls_new_certificate ( tls, payload, payload_len );
                        break;
+               case TLS_SERVER_KEY_EXCHANGE:
+                       rc = tls_new_server_key_exchange ( tls, payload,
+                                                          payload_len );
+                       break;
                case TLS_CERTIFICATE_REQUEST:
                        rc = tls_new_certificate_request ( tls, payload,
                                                           payload_len );