[tls] Record ServerKeyExchange record, if provided

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>
pull/785/head
Michael Brown 2022-10-11 13:49:57 +01:00
parent 028aac99a3
commit 80c45c5c71
2 changed files with 40 additions and 0 deletions

View File

@ -310,6 +310,10 @@ struct tls_connection {
uint8_t server_random[32]; uint8_t server_random[32];
/** Client random bytes */ /** Client random bytes */
struct tls_client_random client_random; 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 */ /** MD5+SHA1 context for handshake verification */
uint8_t handshake_md5_sha1_ctx[MD5_SHA1_CTX_SIZE]; uint8_t handshake_md5_sha1_ctx[MD5_SHA1_CTX_SIZE];
/** SHA256 context for handshake verification */ /** SHA256 context for handshake verification */

View 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->tx_cipherspec_pending );
tls_clear_cipher ( tls, &tls->rx_cipherspec ); tls_clear_cipher ( tls, &tls->rx_cipherspec );
tls_clear_cipher ( tls, &tls->rx_cipherspec_pending ); tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
free ( tls->server_key );
list_for_each_entry_safe ( iobuf, tmp, &tls->rx_data, list ) { list_for_each_entry_safe ( iobuf, tmp, &tls->rx_data, list ) {
list_del ( &iobuf->list ); list_del ( &iobuf->list );
free_iob ( iobuf ); free_iob ( iobuf );
@ -1867,6 +1868,37 @@ static int tls_new_certificate ( struct tls_connection *tls,
return 0; 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 * Receive new Certificate Request handshake record
* *
@ -2100,6 +2132,10 @@ static int tls_new_handshake ( struct tls_connection *tls,
case TLS_CERTIFICATE: case TLS_CERTIFICATE:
rc = tls_new_certificate ( tls, payload, payload_len ); rc = tls_new_certificate ( tls, payload, payload_len );
break; break;
case TLS_SERVER_KEY_EXCHANGE:
rc = tls_new_server_key_exchange ( tls, payload,
payload_len );
break;
case TLS_CERTIFICATE_REQUEST: case TLS_CERTIFICATE_REQUEST:
rc = tls_new_certificate_request ( tls, payload, rc = tls_new_certificate_request ( tls, payload,
payload_len ); payload_len );