summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2024-01-30 16:23:39 +0100
committerMichael Brown2024-01-30 17:06:45 +0100
commit8e2469c861fd25ac4956ca6b3bc3ed4ab8d74308 (patch)
tree53de0c185a7f45304ce51ca22791aa16f3f975bc
parent[tls] Generate key material after sending ClientKeyExchange (diff)
downloadipxe-8e2469c861fd25ac4956ca6b3bc3ed4ab8d74308.tar.gz
ipxe-8e2469c861fd25ac4956ca6b3bc3ed4ab8d74308.tar.xz
ipxe-8e2469c861fd25ac4956ca6b3bc3ed4ab8d74308.zip
[tls] Split out Diffie-Hellman parameter signature verification
DHE and ECDHE use essentially the same mechanism for verifying the signature over the Diffie-Hellman parameters, though the format of the parameters is different between the two methods. Split out the verification of the parameter signature so that it may be shared between the DHE and ECDHE key exchange algorithms. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/net/tls.c101
1 files changed, 62 insertions, 39 deletions
diff --git a/src/net/tls.c b/src/net/tls.c
index da16889f..66ab1e9c 100644
--- a/src/net/tls.c
+++ b/src/net/tls.c
@@ -1394,21 +1394,18 @@ struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm = {
};
/**
- * Transmit Client Key Exchange record using DHE key exchange
+ * Verify Diffie-Hellman parameter signature
*
* @v tls TLS connection
+ * @v param_len Diffie-Hellman parameter length
* @ret rc Return status code
*/
-static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
+static int tls_verify_dh_params ( struct tls_connection *tls,
+ size_t param_len ) {
struct tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
struct pubkey_algorithm *pubkey;
struct digest_algorithm *digest;
int use_sig_hash = tls_version ( tls, TLS_VERSION_TLS_1_2 );
- uint8_t private[ sizeof ( tls->client_random.random ) ];
- const struct {
- uint16_t len;
- uint8_t data[0];
- } __attribute__ (( packed )) *dh_val[3];
const struct {
struct tls_signature_hash_id sig_hash[use_sig_hash];
uint16_t signature_len;
@@ -1416,29 +1413,14 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
} __attribute__ (( packed )) *sig;
const void *data;
size_t remaining;
- size_t frag_len;
- unsigned int i;
int rc;
- /* Parse ServerKeyExchange */
- data = tls->server_key;
- remaining = tls->server_key_len;
- for ( i = 0 ; i < ( sizeof ( dh_val ) / sizeof ( dh_val[0] ) ) ; i++ ){
- dh_val[i] = data;
- if ( ( sizeof ( *dh_val[i] ) > remaining ) ||
- ( ntohs ( dh_val[i]->len ) > ( remaining -
- sizeof ( *dh_val[i] ) ) )){
- DBGC ( tls, "TLS %p received underlength "
- "ServerKeyExchange\n", tls );
- DBGC_HDA ( tls, 0, tls->server_key,
- tls->server_key_len );
- rc = -EINVAL_KEY_EXCHANGE;
- goto err_header;
- }
- frag_len = ( sizeof ( *dh_val[i] ) + ntohs ( dh_val[i]->len ));
- data += frag_len;
- remaining -= frag_len;
- }
+ /* Signature follows parameters */
+ assert ( param_len <= tls->server_key_len );
+ data = ( tls->server_key + param_len );
+ remaining = ( tls->server_key_len - param_len );
+
+ /* Parse signature from ServerKeyExchange */
sig = data;
if ( ( sizeof ( *sig ) > remaining ) ||
( ntohs ( sig->signature_len ) > ( remaining -
@@ -1446,8 +1428,7 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
tls );
DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
- rc = -EINVAL_KEY_EXCHANGE;
- goto err_header;
+ return -EINVAL_KEY_EXCHANGE;
}
/* Identify signature and hash algorithm */
@@ -1457,15 +1438,13 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
if ( ( ! pubkey ) || ( ! digest ) ) {
DBGC ( tls, "TLS %p ServerKeyExchange unsupported "
"signature and hash algorithm\n", tls );
- rc = -ENOTSUP_SIG_HASH;
- goto err_sig_hash;
+ return -ENOTSUP_SIG_HASH;
}
if ( pubkey != cipherspec->suite->pubkey ) {
DBGC ( tls, "TLS %p ServerKeyExchange incorrect "
"signature algorithm %s (expected %s)\n", tls,
pubkey->name, cipherspec->suite->pubkey->name );
- rc = -EPERM_KEY_EXCHANGE;
- goto err_sig_hash;
+ return -EPERM_KEY_EXCHANGE;
}
} else {
pubkey = cipherspec->suite->pubkey;
@@ -1485,8 +1464,7 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
sizeof ( tls->client_random ) );
digest_update ( digest, ctx, tls->server_random,
sizeof ( tls->server_random ) );
- digest_update ( digest, ctx, tls->server_key,
- ( tls->server_key_len - remaining ) );
+ digest_update ( digest, ctx, tls->server_key, param_len );
digest_final ( digest, ctx, hash );
/* Verify signature */
@@ -1497,11 +1475,57 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
"verification\n", tls );
DBGC_HDA ( tls, 0, tls->server_key,
tls->server_key_len );
- rc = -EPERM_KEY_EXCHANGE;
- goto err_verify;
+ return -EPERM_KEY_EXCHANGE;
}
}
+ return 0;
+}
+
+/**
+ * Transmit Client Key Exchange record using DHE key exchange
+ *
+ * @v tls TLS connection
+ * @ret rc Return status code
+ */
+static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
+ uint8_t private[ sizeof ( tls->client_random.random ) ];
+ const struct {
+ uint16_t len;
+ uint8_t data[0];
+ } __attribute__ (( packed )) *dh_val[3];
+ const void *data;
+ size_t remaining;
+ size_t frag_len;
+ size_t param_len;
+ unsigned int i;
+ int rc;
+
+ /* Parse ServerKeyExchange */
+ data = tls->server_key;
+ remaining = tls->server_key_len;
+ for ( i = 0 ; i < ( sizeof ( dh_val ) / sizeof ( dh_val[0] ) ) ; i++ ){
+ dh_val[i] = data;
+ if ( ( sizeof ( *dh_val[i] ) > remaining ) ||
+ ( ntohs ( dh_val[i]->len ) > ( remaining -
+ sizeof ( *dh_val[i] ) ) )){
+ DBGC ( tls, "TLS %p received underlength "
+ "ServerKeyExchange\n", tls );
+ DBGC_HDA ( tls, 0, tls->server_key,
+ tls->server_key_len );
+ rc = -EINVAL_KEY_EXCHANGE;
+ goto err_header;
+ }
+ frag_len = ( sizeof ( *dh_val[i] ) + ntohs ( dh_val[i]->len ));
+ data += frag_len;
+ remaining -= frag_len;
+ }
+ param_len = ( tls->server_key_len - remaining );
+
+ /* Verify parameter signature */
+ if ( ( rc = tls_verify_dh_params ( tls, param_len ) ) != 0 )
+ goto err_verify;
+
/* Generate Diffie-Hellman private key */
if ( ( rc = tls_generate_random ( tls, private,
sizeof ( private ) ) ) != 0 ) {
@@ -1573,7 +1597,6 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
err_alloc:
err_random:
err_verify:
- err_sig_hash:
err_header:
return rc;
}