1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-07-29 11:41:15 +03:00

Merge pull request #5908 from ronald-cron-arm/tls13-fixes-doc

TLS 1.3: Fixes and add documentation
Validated by the internal CI, no need to wait for the Open CI.
This commit is contained in:
Ronald Cron
2022-06-28 12:16:17 +02:00
committed by GitHub
5 changed files with 201 additions and 142 deletions

View File

@ -121,11 +121,12 @@ static int ssl_tls13_parse_supported_versions_ext( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_SSL_ALPN)
static int ssl_tls13_parse_alpn_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
const unsigned char *buf, size_t len )
{
size_t list_len, name_len;
const unsigned char *p = buf;
const unsigned char *end = buf + len;
size_t protocol_name_list_len, protocol_name_len;
const unsigned char *protocol_name_list_end;
/* If we didn't send it, the server shouldn't send it */
if( ssl->conf->alpn_list == NULL )
@ -141,21 +142,22 @@ static int ssl_tls13_parse_alpn_ext( mbedtls_ssl_context *ssl,
* the "ProtocolNameList" MUST contain exactly one "ProtocolName"
*/
/* Min length is 2 ( list_len ) + 1 ( name_len ) + 1 ( name ) */
MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 4 );
list_len = MBEDTLS_GET_UINT16_BE( p, 0 );
MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 );
protocol_name_list_len = MBEDTLS_GET_UINT16_BE( p, 0 );
p += 2;
MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, list_len );
name_len = *p++;
MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, list_len - 1 );
MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, protocol_name_list_len );
protocol_name_list_end = p + protocol_name_list_len;
MBEDTLS_SSL_CHK_BUF_READ_PTR( p, protocol_name_list_end, 1 );
protocol_name_len = *p++;
/* Check that the server chosen protocol was in our list and save it */
for ( const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++ )
MBEDTLS_SSL_CHK_BUF_READ_PTR( p, protocol_name_list_end, protocol_name_len );
for( const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++ )
{
if( name_len == strlen( *alpn ) &&
memcmp( buf + 3, *alpn, name_len ) == 0 )
if( protocol_name_len == strlen( *alpn ) &&
memcmp( p, *alpn, protocol_name_len ) == 0 )
{
ssl->alpn_chosen = *alpn;
return( 0 );
@ -667,6 +669,7 @@ static int ssl_tls13_is_supported_versions_ext_present(
* - cipher_suite 2 bytes
* - legacy_compression_method 1 byte
*/
MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, legacy_session_id_echo_len + 4 );
p += legacy_session_id_echo_len + 4;
/* Case of no extension */
@ -740,12 +743,12 @@ static int ssl_tls13_is_downgrade_negotiation( mbedtls_ssl_context *ssl,
}
/* Returns a negative value on failure, and otherwise
* - SSL_SERVER_HELLO_COORDINATE_HELLO or
* - SSL_SERVER_HELLO_COORDINATE_HRR
* - SSL_SERVER_HELLO or
* - SSL_SERVER_HELLO_HRR
* to indicate which message is expected and to be parsed next.
*/
#define SSL_SERVER_HELLO_COORDINATE_HELLO 0
#define SSL_SERVER_HELLO_COORDINATE_HRR 1
#define SSL_SERVER_HELLO 0
#define SSL_SERVER_HELLO_HRR 1
static int ssl_server_hello_is_hrr( mbedtls_ssl_context *ssl,
const unsigned char *buf,
const unsigned char *end )
@ -772,37 +775,32 @@ static int ssl_server_hello_is_hrr( mbedtls_ssl_context *ssl,
if( memcmp( buf + 2, mbedtls_ssl_tls13_hello_retry_request_magic,
sizeof( mbedtls_ssl_tls13_hello_retry_request_magic ) ) == 0 )
{
return( SSL_SERVER_HELLO_COORDINATE_HRR );
return( SSL_SERVER_HELLO_HRR );
}
return( SSL_SERVER_HELLO_COORDINATE_HELLO );
return( SSL_SERVER_HELLO );
}
/* Fetch and preprocess
/*
* Returns a negative value on failure, and otherwise
* - SSL_SERVER_HELLO_COORDINATE_HELLO or
* - SSL_SERVER_HELLO_COORDINATE_HRR or
* - SSL_SERVER_HELLO_COORDINATE_TLS1_2
* - SSL_SERVER_HELLO or
* - SSL_SERVER_HELLO_HRR or
* - SSL_SERVER_HELLO_TLS1_2
*/
#define SSL_SERVER_HELLO_COORDINATE_TLS1_2 2
static int ssl_tls13_server_hello_coordinate( mbedtls_ssl_context *ssl,
unsigned char **buf,
size_t *buf_len )
#define SSL_SERVER_HELLO_TLS1_2 2
static int ssl_tls13_preprocess_server_hello( mbedtls_ssl_context *ssl,
const unsigned char *buf,
const unsigned char *end )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *end;
MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( ssl,
MBEDTLS_SSL_HS_SERVER_HELLO,
buf, buf_len ) );
end = *buf + *buf_len;
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
MBEDTLS_SSL_PROC_CHK_NEG( ssl_tls13_is_supported_versions_ext_present(
ssl, *buf, end ) );
ssl, buf, end ) );
if( ret == 0 )
{
MBEDTLS_SSL_PROC_CHK_NEG(
ssl_tls13_is_downgrade_negotiation( ssl, *buf, end ) );
ssl_tls13_is_downgrade_negotiation( ssl, buf, end ) );
/* If the server is negotiating TLS 1.2 or below and:
* . we did not propose TLS 1.2 or
@ -810,7 +808,7 @@ static int ssl_tls13_server_hello_coordinate( mbedtls_ssl_context *ssl,
* version of the protocol and thus we are under downgrade attack
* abort the handshake with an "illegal parameter" alert.
*/
if( ssl->handshake->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 || ret )
if( handshake->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 || ret )
{
MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
@ -820,7 +818,7 @@ static int ssl_tls13_server_hello_coordinate( mbedtls_ssl_context *ssl,
ssl->keep_current_message = 1;
ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_SERVER_HELLO,
*buf, *buf_len );
buf, (size_t)(end - buf) );
if( mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) )
{
@ -829,23 +827,25 @@ static int ssl_tls13_server_hello_coordinate( mbedtls_ssl_context *ssl,
return( ret );
}
return( SSL_SERVER_HELLO_COORDINATE_TLS1_2 );
return( SSL_SERVER_HELLO_TLS1_2 );
}
ret = ssl_server_hello_is_hrr( ssl, *buf, end );
handshake->extensions_present = MBEDTLS_SSL_EXT_NONE;
ret = ssl_server_hello_is_hrr( ssl, buf, end );
switch( ret )
{
case SSL_SERVER_HELLO_COORDINATE_HELLO:
case SSL_SERVER_HELLO:
MBEDTLS_SSL_DEBUG_MSG( 2, ( "received ServerHello message" ) );
break;
case SSL_SERVER_HELLO_COORDINATE_HRR:
case SSL_SERVER_HELLO_HRR:
MBEDTLS_SSL_DEBUG_MSG( 2, ( "received HelloRetryRequest message" ) );
/* If a client receives a second
* HelloRetryRequest in the same connection (i.e., where the ClientHello
* was itself in response to a HelloRetryRequest), it MUST abort the
* handshake with an "unexpected_message" alert.
*/
if( ssl->handshake->hello_retry_request_count > 0 )
if( handshake->hello_retry_request_count > 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Multiple HRRs received" ) );
MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
@ -868,7 +868,7 @@ static int ssl_tls13_server_hello_coordinate( mbedtls_ssl_context *ssl,
return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
}
ssl->handshake->hello_retry_request_count++;
handshake->hello_retry_request_count++;
break;
}
@ -1247,11 +1247,6 @@ static int ssl_tls13_postprocess_server_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to handshake keys for inbound traffic" ) );
ssl->session_in = ssl->session_negotiate;
/*
* State machine update
*/
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS );
cleanup:
if( ret != 0 )
{
@ -1267,17 +1262,6 @@ static int ssl_tls13_postprocess_hrr( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
/* If not offering early data, the client sends a dummy CCS record
* immediately before its second flight. This may either be before
* its second ClientHello or before its encrypted handshake flight.
*/
mbedtls_ssl_handshake_set_state( ssl,
MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO );
#else
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_HELLO );
#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
mbedtls_ssl_session_reset_msg_layer( ssl, 0 );
/*
@ -1306,20 +1290,17 @@ static int ssl_tls13_process_server_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> %s", __func__ ) );
/* Coordination step
* - Fetch record
* - Make sure it's either a ServerHello or a HRR.
* - Switch processing routine in case of HRR
*/
ssl->handshake->extensions_present = MBEDTLS_SSL_EXT_NONE;
MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( ssl,
MBEDTLS_SSL_HS_SERVER_HELLO,
&buf, &buf_len ) );
ret = ssl_tls13_server_hello_coordinate( ssl, &buf, &buf_len );
ret = ssl_tls13_preprocess_server_hello( ssl, buf, buf + buf_len );
if( ret < 0 )
goto cleanup;
else
is_hrr = ( ret == SSL_SERVER_HELLO_COORDINATE_HRR );
is_hrr = ( ret == SSL_SERVER_HELLO_HRR );
if( ret == SSL_SERVER_HELLO_COORDINATE_TLS1_2 )
if( ret == SSL_SERVER_HELLO_TLS1_2 )
{
ret = 0;
goto cleanup;
@ -1335,9 +1316,24 @@ static int ssl_tls13_process_server_hello( mbedtls_ssl_context *ssl )
buf, buf_len );
if( is_hrr )
{
MBEDTLS_SSL_PROC_CHK( ssl_tls13_postprocess_hrr( ssl ) );
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
/* If not offering early data, the client sends a dummy CCS record
* immediately before its second flight. This may either be before
* its second ClientHello or before its encrypted handshake flight.
*/
mbedtls_ssl_handshake_set_state( ssl,
MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO );
#else
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_HELLO );
#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
}
else
{
MBEDTLS_SSL_PROC_CHK( ssl_tls13_postprocess_server_hello( ssl ) );
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS );
}
cleanup:
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= %s ( %s )", __func__,
@ -1347,56 +1343,13 @@ cleanup:
/*
*
* EncryptedExtensions message
* Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS
*
* The EncryptedExtensions message contains any extensions which
* should be protected, i.e., any which are not needed to establish
* the cryptographic context.
*/
/*
* Overview
*/
/* Main entry point; orchestrates the other functions */
static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl );
static int ssl_tls13_parse_encrypted_extensions( mbedtls_ssl_context *ssl,
const unsigned char *buf,
const unsigned char *end );
static int ssl_tls13_postprocess_encrypted_extensions( mbedtls_ssl_context *ssl );
/*
* Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS
*/
static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl )
{
int ret;
unsigned char *buf;
size_t buf_len;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse encrypted extensions" ) );
MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( ssl,
MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
&buf, &buf_len ) );
/* Process the message contents */
MBEDTLS_SSL_PROC_CHK(
ssl_tls13_parse_encrypted_extensions( ssl, buf, buf + buf_len ) );
mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
buf, buf_len );
MBEDTLS_SSL_PROC_CHK( ssl_tls13_postprocess_encrypted_extensions( ssl ) );
cleanup:
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse encrypted extensions" ) );
return( ret );
}
/* Parse EncryptedExtensions message
* struct {
* Extension extensions<0..2^16-1>;
@ -1416,8 +1369,8 @@ static int ssl_tls13_parse_encrypted_extensions( mbedtls_ssl_context *ssl,
p += 2;
MBEDTLS_SSL_DEBUG_BUF( 3, "encrypted extensions", p, extensions_len );
extensions_end = p + extensions_len;
MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, extensions_len );
extensions_end = p + extensions_len;
while( p < extensions_end )
{
@ -1483,8 +1436,25 @@ static int ssl_tls13_parse_encrypted_extensions( mbedtls_ssl_context *ssl,
return( ret );
}
static int ssl_tls13_postprocess_encrypted_extensions( mbedtls_ssl_context *ssl )
static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl )
{
int ret;
unsigned char *buf;
size_t buf_len;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse encrypted extensions" ) );
MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( ssl,
MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
&buf, &buf_len ) );
/* Process the message contents */
MBEDTLS_SSL_PROC_CHK(
ssl_tls13_parse_encrypted_extensions( ssl, buf, buf + buf_len ) );
mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
buf, buf_len );
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
if( mbedtls_ssl_tls13_some_psk_enabled( ssl ) )
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED );
@ -1494,12 +1464,16 @@ static int ssl_tls13_postprocess_encrypted_extensions( mbedtls_ssl_context *ssl
((void) ssl);
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED );
#endif
return( 0 );
cleanup:
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse encrypted extensions" ) );
return( ret );
}
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
/*
*
* STATE HANDLING: CertificateRequest
*
*/

View File

@ -812,7 +812,7 @@ static int ssl_tls13_write_certificate_body( mbedtls_ssl_context *ssl,
/* Currently, we don't have any certificate extensions defined.
* Hence, we are sending an empty extension with length zero.
*/
MBEDTLS_PUT_UINT24_BE( 0, p, 0 );
MBEDTLS_PUT_UINT16_BE( 0, p, 0 );
p += 2;
}
@ -1437,12 +1437,12 @@ int mbedtls_ssl_tls13_read_public_ecdhe_share( mbedtls_ssl_context *ssl,
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
/* Get size of the TLS opaque key_exchange field of the KeyShareEntry struct. */
MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 );
uint16_t peerkey_len = MBEDTLS_GET_UINT16_BE( p, 0 );
p += 2;
/* Check if key size is consistent with given buffer length. */
MBEDTLS_SSL_CHK_BUF_PTR( p, end, peerkey_len );
MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, peerkey_len );
/* Store peer's ECDH public key. */
memcpy( handshake->ecdh_psa_peerkey, p, peerkey_len );

View File

@ -1095,7 +1095,7 @@ static int ssl_tls13_write_hrr_key_share_ext( mbedtls_ssl_context *ssl,
* - extension_data_length (2 bytes)
* - selected_group (2 bytes)
*/
MBEDTLS_SSL_CHK_BUF_READ_PTR( buf, end, 6 );
MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 6 );
MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0 );
MBEDTLS_PUT_UINT16_BE( 2, buf, 2 );
@ -1307,8 +1307,7 @@ cleanup:
/*
* Handler for MBEDTLS_SSL_HELLO_RETRY_REQUEST
*/
static int ssl_tls13_write_hello_retry_request_coordinate(
mbedtls_ssl_context *ssl )
static int ssl_tls13_prepare_hello_retry_request( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ssl->handshake->hello_retry_request_count > 0 )
@ -1342,7 +1341,7 @@ static int ssl_tls13_write_hello_retry_request( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello retry request" ) );
MBEDTLS_SSL_PROC_CHK( ssl_tls13_write_hello_retry_request_coordinate( ssl ) );
MBEDTLS_SSL_PROC_CHK( ssl_tls13_prepare_hello_retry_request( ssl ) );
MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_start_handshake_msg(
ssl, MBEDTLS_SSL_HS_SERVER_HELLO,
@ -1636,19 +1635,18 @@ static int ssl_tls13_write_server_finished( mbedtls_ssl_context *ssl )
return( ret );
}
if( ssl->handshake->certificate_request_sent )
{
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE );
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to handshake keys for inbound traffic" ) );
mbedtls_ssl_set_inbound_transform( ssl, ssl->handshake->transform_handshake );
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to handshake keys for inbound traffic" ) );
mbedtls_ssl_set_inbound_transform( ssl, ssl->handshake->transform_handshake );
}
if( ssl->handshake->certificate_request_sent )
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE );
else
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "skip parse certificate" ) );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "skip parse certificate verify" ) );
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_FINISHED );
}
return( 0 );
}
@ -1659,12 +1657,6 @@ static int ssl_tls13_process_client_finished( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ! ssl->handshake->certificate_request_sent )
{
MBEDTLS_SSL_DEBUG_MSG( 1,
( "Switch to handshake traffic keys for inbound traffic" ) );
mbedtls_ssl_set_inbound_transform( ssl, ssl->handshake->transform_handshake );
}
ret = mbedtls_ssl_tls13_process_finished_message( ssl );
if( ret != 0 )
return( ret );