mirror of https://github.com/ipxe/ipxe.git
[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>pull/785/head
parent
1a7317e7d4
commit
028aac99a3
|
@ -48,6 +48,9 @@ struct tls_header {
|
||||||
/** TLS version 1.2 */
|
/** TLS version 1.2 */
|
||||||
#define TLS_VERSION_TLS_1_2 0x0303
|
#define TLS_VERSION_TLS_1_2 0x0303
|
||||||
|
|
||||||
|
/** Maximum supported TLS version */
|
||||||
|
#define TLS_VERSION_MAX TLS_VERSION_TLS_1_2
|
||||||
|
|
||||||
/** Change cipher content type */
|
/** Change cipher content type */
|
||||||
#define TLS_TYPE_CHANGE_CIPHER 20
|
#define TLS_TYPE_CHANGE_CIPHER 20
|
||||||
|
|
||||||
|
@ -209,14 +212,6 @@ struct tls_signature_hash_algorithm {
|
||||||
#define __tls_sig_hash_algorithm \
|
#define __tls_sig_hash_algorithm \
|
||||||
__table_entry ( TLS_SIG_HASH_ALGORITHMS, 01 )
|
__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 */
|
/** TLS client random data */
|
||||||
struct tls_client_random {
|
struct tls_client_random {
|
||||||
/** GMT Unix time */
|
/** GMT Unix time */
|
||||||
|
@ -309,8 +304,6 @@ struct tls_connection {
|
||||||
struct tls_cipherspec rx_cipherspec;
|
struct tls_cipherspec rx_cipherspec;
|
||||||
/** Next RX cipher specification */
|
/** Next RX cipher specification */
|
||||||
struct tls_cipherspec rx_cipherspec_pending;
|
struct tls_cipherspec rx_cipherspec_pending;
|
||||||
/** Premaster secret */
|
|
||||||
struct tls_pre_master_secret pre_master_secret;
|
|
||||||
/** Master secret */
|
/** Master secret */
|
||||||
uint8_t master_secret[48];
|
uint8_t master_secret[48];
|
||||||
/** Server random bytes */
|
/** Server random bytes */
|
||||||
|
|
|
@ -616,21 +616,23 @@ static void tls_prf ( struct tls_connection *tls, const void *secret,
|
||||||
* Generate master secret
|
* Generate master secret
|
||||||
*
|
*
|
||||||
* @v tls TLS connection
|
* @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
|
* The client and server random values must already be known.
|
||||||
* 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 ( tls, "TLS %p pre-master-secret:\n", tls );
|
||||||
DBGC_HD ( tls, &tls->pre_master_secret,
|
DBGC_HD ( tls, pre_master_secret, pre_master_secret_len );
|
||||||
sizeof ( tls->pre_master_secret ) );
|
|
||||||
DBGC ( tls, "TLS %p client random bytes:\n", tls );
|
DBGC ( tls, "TLS %p client random bytes:\n", tls );
|
||||||
DBGC_HD ( tls, &tls->client_random, sizeof ( tls->client_random ) );
|
DBGC_HD ( tls, &tls->client_random, sizeof ( tls->client_random ) );
|
||||||
DBGC ( tls, "TLS %p server random bytes:\n", tls );
|
DBGC ( tls, "TLS %p server random bytes:\n", tls );
|
||||||
DBGC_HD ( tls, &tls->server_random, sizeof ( tls->server_random ) );
|
DBGC_HD ( tls, &tls->server_random, sizeof ( tls->server_random ) );
|
||||||
|
|
||||||
tls_prf_label ( tls, &tls->pre_master_secret,
|
tls_prf_label ( tls, pre_master_secret, pre_master_secret_len,
|
||||||
sizeof ( tls->pre_master_secret ),
|
|
||||||
&tls->master_secret, sizeof ( tls->master_secret ),
|
&tls->master_secret, sizeof ( tls->master_secret ),
|
||||||
"master secret",
|
"master secret",
|
||||||
&tls->client_random, sizeof ( tls->client_random ),
|
&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 tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
|
||||||
struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
|
struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
|
||||||
size_t max_len = pubkey_max_len ( pubkey, cipherspec->pubkey_ctx );
|
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 {
|
struct {
|
||||||
uint32_t type_length;
|
uint32_t type_length;
|
||||||
uint16_t encrypted_pre_master_secret_len;
|
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 len;
|
||||||
int rc;
|
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 */
|
/* Generate master secret */
|
||||||
tls_generate_master_secret ( tls );
|
tls_generate_master_secret ( tls, &pre_master_secret,
|
||||||
|
sizeof ( pre_master_secret ) );
|
||||||
|
|
||||||
/* Generate keys */
|
/* Generate keys */
|
||||||
if ( ( rc = tls_generate_keys ( tls ) ) != 0 ) {
|
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 */
|
/* Encrypt pre-master secret using server's public key */
|
||||||
memset ( &key_xchg, 0, sizeof ( key_xchg ) );
|
memset ( &key_xchg, 0, sizeof ( key_xchg ) );
|
||||||
len = pubkey_encrypt ( pubkey, cipherspec->pubkey_ctx,
|
len = pubkey_encrypt ( pubkey, cipherspec->pubkey_ctx,
|
||||||
&tls->pre_master_secret,
|
&pre_master_secret, sizeof ( pre_master_secret ),
|
||||||
sizeof ( tls->pre_master_secret ),
|
|
||||||
key_xchg.encrypted_pre_master_secret );
|
key_xchg.encrypted_pre_master_secret );
|
||||||
if ( len < 0 ) {
|
if ( len < 0 ) {
|
||||||
rc = len;
|
rc = len;
|
||||||
|
@ -3173,7 +3186,7 @@ int add_tls ( struct interface *xfer, const char *name,
|
||||||
&tls->refcnt );
|
&tls->refcnt );
|
||||||
tls->key = privkey_get ( key ? key : &private_key );
|
tls->key = privkey_get ( key ? key : &private_key );
|
||||||
tls->root = x509_root_get ( root ? root : &root_certificates );
|
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 );
|
||||||
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 );
|
||||||
|
@ -3186,11 +3199,6 @@ int add_tls ( struct interface *xfer, const char *name,
|
||||||
( sizeof ( tls->client_random.random ) ) ) ) != 0 ) {
|
( sizeof ( tls->client_random.random ) ) ) ) != 0 ) {
|
||||||
goto err_random;
|
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 )
|
if ( ( rc = tls_session ( tls, name ) ) != 0 )
|
||||||
goto err_session;
|
goto err_session;
|
||||||
list_add_tail ( &tls->list, &tls->session->conn );
|
list_add_tail ( &tls->list, &tls->session->conn );
|
||||||
|
|
Loading…
Reference in New Issue