diff --git a/src/include/ipxe/tls.h b/src/include/ipxe/tls.h index 3b46543bb..658a008f8 100644 --- a/src/include/ipxe/tls.h +++ b/src/include/ipxe/tls.h @@ -134,6 +134,9 @@ struct tls_header { /* TLS signature algorithms extension */ #define TLS_SIGNATURE_ALGORITHMS 13 +/* TLS extended master secret extension */ +#define TLS_EXTENDED_MASTER_SECRET 23 + /* TLS session ticket extension */ #define TLS_SESSION_TICKET 35 @@ -452,6 +455,8 @@ struct tls_connection { uint8_t *handshake_ctx; /** Secure renegotiation flag */ int secure_renegotiation; + /** Extended master secret flag */ + int extended_master_secret; /** Verification data */ struct tls_verify_data verify; diff --git a/src/net/tls.c b/src/net/tls.c index cc463214f..8f91da018 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -200,6 +200,7 @@ static int tls_send_plaintext ( struct tls_connection *tls, unsigned int type, const void *data, size_t len ); static void tls_clear_cipher ( struct tls_connection *tls, struct tls_cipherspec *cipherspec ); +static void tls_verify_handshake ( struct tls_connection *tls, void *out ); /****************************************************************************** * @@ -637,21 +638,43 @@ static void tls_prf ( struct tls_connection *tls, const void *secret, static void tls_generate_master_secret ( struct tls_connection *tls, const void *pre_master_secret, size_t pre_master_secret_len ) { + struct digest_algorithm *digest = tls->handshake_digest; + uint8_t digest_out[ digest->digestsize ]; - DBGC ( tls, "TLS %p pre-master-secret:\n", tls ); + /* Generate handshake digest */ + tls_verify_handshake ( tls, digest_out ); + + /* Show inputs */ + DBGC ( tls, "TLS %p pre-master secret:\n", tls ); 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 ) ); + DBGC ( tls, "TLS %p session hash:\n", tls ); + DBGC_HD ( tls, digest_out, sizeof ( digest_out ) ); - 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 ), - &tls->server.random, sizeof ( tls->server.random ) ); + /* Generate master secret */ + if ( tls->extended_master_secret ) { + tls_prf_label ( tls, pre_master_secret, pre_master_secret_len, + &tls->master_secret, + sizeof ( tls->master_secret ), + "extended master secret", + digest_out, sizeof ( digest_out ) ); + } else { + 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 ), + &tls->server.random, + sizeof ( tls->server.random ) ); + } - DBGC ( tls, "TLS %p generated master secret:\n", tls ); + /* Show output */ + DBGC ( tls, "TLS %p generated %smaster secret:\n", tls, + ( tls->extended_master_secret ? "extended ": "" ) ); DBGC_HD ( tls, &tls->master_secret, sizeof ( tls->master_secret ) ); } @@ -1195,12 +1218,17 @@ static int tls_client_hello ( struct tls_connection *tls, uint16_t code[TLS_NUM_NAMED_CURVES]; } __attribute__ (( packed )) data; } __attribute__ (( packed )) *named_curve_ext; + struct { + uint16_t type; + uint16_t len; + } __attribute__ (( packed )) *extended_master_secret_ext; struct { typeof ( *server_name_ext ) server_name; typeof ( *max_fragment_length_ext ) max_fragment_length; typeof ( *signature_algorithms_ext ) signature_algorithms; typeof ( *renegotiation_info_ext ) renegotiation_info; typeof ( *session_ticket_ext ) session_ticket; + typeof ( *extended_master_secret_ext ) extended_master_secret; typeof ( *named_curve_ext ) named_curve[TLS_NUM_NAMED_CURVES ? 1 : 0]; } __attribute__ (( packed )) *extensions; @@ -1286,6 +1314,12 @@ static int tls_client_hello ( struct tls_connection *tls, memcpy ( session_ticket_ext->data.data, session->ticket, sizeof ( session_ticket_ext->data.data ) ); + /* Construct extended master secret extension */ + extended_master_secret_ext = &extensions->extended_master_secret; + extended_master_secret_ext->type + = htons ( TLS_EXTENDED_MASTER_SECRET ); + extended_master_secret_ext->len = 0; + /* Construct named curves extension, if applicable */ if ( sizeof ( extensions->named_curve ) ) { named_curve_ext = &extensions->named_curve[0]; @@ -2091,6 +2125,9 @@ static int tls_new_server_hello ( struct tls_connection *tls, uint8_t len; uint8_t data[0]; } __attribute__ (( packed )) *reneg = NULL; + const struct { + uint8_t data[0]; + } __attribute__ (( packed )) *ems = NULL; uint16_t version; size_t exts_len; size_t ext_len; @@ -2155,6 +2192,9 @@ static int tls_new_server_hello ( struct tls_connection *tls, return -EINVAL_HELLO; } break; + case htons ( TLS_EXTENDED_MASTER_SECRET ) : + ems = ( ( void * ) ext->data ); + break; } } } @@ -2188,6 +2228,9 @@ static int tls_new_server_hello ( struct tls_connection *tls, memcpy ( &tls->server.random, &hello_a->random, sizeof ( tls->server.random ) ); + /* Handle extended master secret */ + tls->extended_master_secret = ( !! ems ); + /* Check session ID */ if ( hello_a->session_id_len && ( hello_a->session_id_len == tls->session_id_len ) &&