ssl_tls13_client: Add downgrade attack protection

Signed-off-by: Ronald Cron <ronald.cron@arm.com>
This commit is contained in:
Ronald Cron 2022-04-05 11:04:20 +02:00
parent 217d699d85
commit fd6193c285

View File

@ -711,6 +711,7 @@ int mbedtls_ssl_tls13_write_client_hello_exts( mbedtls_ssl_context *ssl,
/*
* Functions for parsing and processing Server Hello
*/
/**
* \brief Detect if the ServerHello contains a supported_versions extension
* or not.
@ -792,6 +793,36 @@ static int ssl_tls13_is_supported_versions_ext_present(
return( 0 );
}
/* Returns a negative value on failure, and otherwise
* - 1 if the last eight bytes of the ServerHello random bytes indicate that
* the server is TLS 1.3 capable but negotiating TLS 1.2 or below.
* - 0 otherwise
*/
static int ssl_tls13_is_downgrade_negotiation( mbedtls_ssl_context *ssl,
const unsigned char *buf,
const unsigned char *end )
{
/* First seven bytes of the magic downgrade strings, see RFC 8446 4.1.3 */
static const unsigned char magic_downgrade_string[] =
{ 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44 };
const unsigned char *last_eight_bytes_of_random;
unsigned char last_byte_of_random;
MBEDTLS_SSL_CHK_BUF_READ_PTR( buf, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 2 );
last_eight_bytes_of_random = buf + 2 + MBEDTLS_SERVER_HELLO_RANDOM_LEN - 8;
if( memcmp( last_eight_bytes_of_random,
magic_downgrade_string,
sizeof( magic_downgrade_string ) ) == 0 )
{
last_byte_of_random = last_eight_bytes_of_random[7];
return( last_byte_of_random == 0 ||
last_byte_of_random == 1 );
}
return( 0 );
}
/* Returns a negative value on failure, and otherwise
* - SSL_SERVER_HELLO_COORDINATE_HELLO or
* - SSL_SERVER_HELLO_COORDINATE_HRR
@ -846,20 +877,27 @@ static int ssl_tls13_server_hello_coordinate( mbedtls_ssl_context *ssl,
size_t *buf_len )
{
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_PROC_CHK_NEG( ssl_tls13_is_supported_versions_ext_present(
ssl, *buf, *buf + *buf_len ) );
ssl, *buf, end ) );
if( ret == 0 )
{
/* If the supported versions extension is not present but we were
* expecting it, abort the handshake. Otherwise, switch to TLS 1.2
* handshake.
MBEDTLS_SSL_PROC_CHK_NEG(
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
* . the server responded it is TLS 1.3 capable but negotiating a lower
* 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 )
if( ssl->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 );
@ -881,7 +919,7 @@ static int ssl_tls13_server_hello_coordinate( mbedtls_ssl_context *ssl,
return( SSL_SERVER_HELLO_COORDINATE_TLS1_2 );
}
ret = ssl_server_hello_is_hrr( ssl, *buf, *buf + *buf_len );
ret = ssl_server_hello_is_hrr( ssl, *buf, end );
switch( ret )
{
case SSL_SERVER_HELLO_COORDINATE_HELLO: