Align ciphersuite with overwrite.

Selected ciphersuite MUST be same with ciphsersuite of PSK.
Overwrite the old ciphersuite with the one of PSK.

Signed-off-by: Jerry Yu <jerry.h.yu@arm.com>
This commit is contained in:
Jerry Yu 2022-08-21 17:27:16 +08:00
parent 01e42d2d4c
commit 5725f1cf3a

View file

@ -106,8 +106,10 @@ MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_offered_psks_check_identity_match(
mbedtls_ssl_context *ssl,
const unsigned char *identity,
size_t identity_len )
size_t identity_len,
int *psk_type )
{
*psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL;
/* Check identity with external configured function */
if( ssl->conf->f_psk != NULL )
{
@ -137,12 +139,11 @@ MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_offered_psks_check_binder_match( mbedtls_ssl_context *ssl,
const unsigned char *binder,
size_t binder_len,
mbedtls_md_type_t *psk_alg )
int psk_type,
mbedtls_md_type_t psk_alg )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int psk_type;
mbedtls_md_type_t md_alg;
psa_algorithm_t psa_md_alg;
unsigned char transcript[PSA_HASH_MAX_SIZE];
size_t transcript_len;
@ -150,22 +151,9 @@ static int ssl_tls13_offered_psks_check_binder_match( mbedtls_ssl_context *ssl,
size_t psk_len;
unsigned char server_computed_binder[PSA_HASH_MAX_SIZE];
*psk_alg = MBEDTLS_MD_NONE;
psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL;
switch( binder_len )
{
case 32:
md_alg = MBEDTLS_MD_SHA256;
break;
case 48:
md_alg = MBEDTLS_MD_SHA384;
break;
default:
return( MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
}
psa_md_alg = mbedtls_psa_translate_md( md_alg );
psa_md_alg = mbedtls_psa_translate_md( psk_alg );
/* Get current state of handshake transcript. */
ret = mbedtls_ssl_get_handshake_transcript( ssl, md_alg,
ret = mbedtls_ssl_get_handshake_transcript( ssl, psk_alg,
transcript, sizeof( transcript ),
&transcript_len );
if( ret != 0 )
@ -194,7 +182,6 @@ static int ssl_tls13_offered_psks_check_binder_match( mbedtls_ssl_context *ssl,
if( mbedtls_ct_memcmp( server_computed_binder, binder, binder_len ) == 0 )
{
*psk_alg = md_alg;
return( SSL_TLS1_3_OFFERED_PSK_MATCH );
}
@ -203,6 +190,70 @@ static int ssl_tls13_offered_psks_check_binder_match( mbedtls_ssl_context *ssl,
return( SSL_TLS1_3_OFFERED_PSK_NOT_MATCH );
}
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_psk_external_check_ciphersuites( mbedtls_ssl_context *ssl,
const unsigned char *buf,
const unsigned char *end,
size_t binder_len,
uint16_t *selected_cipher_suite )
{
mbedtls_md_type_t psk_alg;
*selected_cipher_suite = 0;
switch( binder_len )
{
#if defined(MBEDTLS_SHA256_C)
case 32:
psk_alg = MBEDTLS_MD_SHA256;
break;
#endif
#if defined(MBEDTLS_SHA384_C)
case 48:
psk_alg = MBEDTLS_MD_SHA384;
break;
#endif
default:
return( MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
}
/*
* Search for a matching ciphersuite
*/
for ( const unsigned char *p = buf ; p < end ; p += 2 )
{
uint16_t cipher_suite;
const mbedtls_ssl_ciphersuite_t* ciphersuite_info;
MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 );
cipher_suite = MBEDTLS_GET_UINT16_BE( p, 0 );
if( ! mbedtls_ssl_tls13_cipher_suite_is_offered( ssl, cipher_suite ) )
continue;
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( cipher_suite );
if( ( mbedtls_ssl_validate_ciphersuite(
ssl, ciphersuite_info, ssl->tls_version,
ssl->tls_version ) != 0 ) )
{
continue;
}
/* MAC of selected ciphersuite MUST be same with PSK binder if exist.
* Otherwise, client should reject.
*/
if( psk_alg != MBEDTLS_MD_NONE && psk_alg != ciphersuite_info->mac )
continue;
*selected_cipher_suite = cipher_suite;
MBEDTLS_SSL_DEBUG_MSG( 5, ( "PSK matched ciphersuite: %04x - %s",
cipher_suite,
ciphersuite_info->name ) );
return( 0 );
}
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
/* Parser for pre_shared_key extension in client hello
* struct {
* opaque identity<1..2^16-1>;
@ -227,7 +278,8 @@ MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_parse_pre_shared_key_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
const unsigned char *end,
mbedtls_md_type_t *psk_alg )
const unsigned char *ciphersuites,
const unsigned char *ciphersuites_end )
{
const unsigned char *identities = buf;
const unsigned char *p_identity_len;
@ -240,8 +292,6 @@ static int ssl_tls13_parse_pre_shared_key_ext( mbedtls_ssl_context *ssl,
int matched_identity = -1;
int identity_id = -1;
*psk_alg = MBEDTLS_MD_NONE;
MBEDTLS_SSL_DEBUG_BUF( 3, "pre_shared_key extension", buf, end - buf );
/* identities_len 2 bytes
@ -272,7 +322,9 @@ static int ssl_tls13_parse_pre_shared_key_ext( mbedtls_ssl_context *ssl,
const unsigned char *binder;
size_t binder_len;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t alg;
int psk_type;
uint16_t cipher_suite;
const mbedtls_ssl_ciphersuite_t* ciphersuite_info;
MBEDTLS_SSL_CHK_BUF_READ_PTR( p_identity_len, identities_end, 2 + 1 + 4 );
identity_len = MBEDTLS_GET_UINT16_BE( p_identity_len, 0 );
@ -291,12 +343,34 @@ static int ssl_tls13_parse_pre_shared_key_ext( mbedtls_ssl_context *ssl,
continue;
ret = ssl_tls13_offered_psks_check_identity_match(
ssl, identity, identity_len );
ssl, identity, identity_len, &psk_type );
if( ret != SSL_TLS1_3_OFFERED_PSK_MATCH )
continue;
if( psk_type == MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL )
{
ret = ssl_tls13_psk_external_check_ciphersuites(
ssl, ciphersuites, ciphersuites_end,
binder_len, &cipher_suite );
if( ret < 0 )
{
/* See below, no cipher_suite available, abort handshake */
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR,
MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
return( ret );
}
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( cipher_suite );
}
else
{
MBEDTLS_SSL_DEBUG_MSG( 4, ( "`psk_type = %d` not support yet",
psk_type ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
}
ret = ssl_tls13_offered_psks_check_binder_match(
ssl, binder, binder_len, &alg );
ssl, binder, binder_len, psk_type, ciphersuite_info->mac );
/* For the security rationale, handshake should be abort when binder
* value mismatch. See RFC 8446 section 4.2.11.2 and appendix E.6. */
if( ret != SSL_TLS1_3_OFFERED_PSK_MATCH )
@ -311,7 +385,16 @@ static int ssl_tls13_parse_pre_shared_key_ext( mbedtls_ssl_context *ssl,
}
matched_identity = identity_id;
*psk_alg = alg;
/* Update handshake parameters */
if( psk_type == MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL )
{
ssl->session_negotiate->ciphersuite = cipher_suite;
ssl->handshake->ciphersuite_info = ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "overwrite ciphersuite: %04x - %s",
cipher_suite,
ciphersuite_info->name ) );
}
}
if( p_identity_len != identities_end || p_binder_len != binders_end )
@ -915,7 +998,6 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *p = buf;
size_t legacy_session_id_len;
const unsigned char *cipher_suites;
size_t cipher_suites_len;
const unsigned char *cipher_suites_end;
size_t extensions_len;
@ -923,9 +1005,9 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
int hrr_required = 0;
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
const unsigned char *cipher_suites;
const unsigned char *pre_shared_key_ext_start = NULL;
const unsigned char *pre_shared_key_ext_end = NULL;
mbedtls_md_type_t psk_alg = MBEDTLS_MD_NONE;
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
ssl->handshake->extensions_present = MBEDTLS_SSL_EXT_NONE;
@ -1033,26 +1115,48 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
* with CipherSuite defined as:
* uint8 CipherSuite[2];
*/
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
cipher_suites = p;
#endif
cipher_suites_end = p + cipher_suites_len;
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
p, cipher_suites_len );
#if defined(MBEDTLS_DEBUG_C)
/*
* Search for a matching ciphersuite
*/
for ( ; p < cipher_suites_end; p += 2 )
{
uint16_t cipher_suite;
const mbedtls_ssl_ciphersuite_t* ciphersuite_info;
MBEDTLS_SSL_CHK_BUF_READ_PTR( p, cipher_suites_end, 2 );
cipher_suite = MBEDTLS_GET_UINT16_BE( p, 0 );
if( ! mbedtls_ssl_tls13_cipher_suite_is_offered( ssl, cipher_suite ) )
continue;
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( cipher_suite );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello, received ciphersuite: %04x - %s",
if( ( mbedtls_ssl_validate_ciphersuite(
ssl, ciphersuite_info, ssl->tls_version,
ssl->tls_version ) != 0 ) )
{
continue;
}
ssl->session_negotiate->ciphersuite = cipher_suite;
ssl->handshake->ciphersuite_info = ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %04x - %s",
cipher_suite,
ciphersuite_info == NULL ?
"Unkown": ciphersuite_info->name ) );
ciphersuite_info->name ) );
}
if( ssl->handshake->ciphersuite_info == NULL )
{
MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
return ( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
}
#else /* MBEDTLS_DEBUG_C */
p = cipher_suites_end;
#endif /* !MBEDTLS_DEBUG_C */
/* ...
* opaque legacy_compression_methods<1..2^8-1>;
@ -1301,7 +1405,8 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
ret = ssl_tls13_parse_pre_shared_key_ext( ssl,
pre_shared_key_ext_start,
pre_shared_key_ext_end,
&psk_alg );
cipher_suites,
cipher_suites_end );
if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY )
{
ssl->handshake->extensions_present &= ~MBEDTLS_SSL_EXT_PRE_SHARED_KEY;
@ -1319,51 +1424,6 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
ssl->handshake->update_checksum( ssl, buf, p - buf );
}
/*
* Search for a matching ciphersuite
*/
for ( const unsigned char * p_chiper_suite = cipher_suites ;
p_chiper_suite < cipher_suites_end; p_chiper_suite += 2 )
{
uint16_t cipher_suite;
const mbedtls_ssl_ciphersuite_t* ciphersuite_info;
MBEDTLS_SSL_CHK_BUF_READ_PTR( p_chiper_suite, cipher_suites_end, 2 );
cipher_suite = MBEDTLS_GET_UINT16_BE( p_chiper_suite, 0 );
if( ! mbedtls_ssl_tls13_cipher_suite_is_offered( ssl, cipher_suite ) )
continue;
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( cipher_suite );
if( ( mbedtls_ssl_validate_ciphersuite(
ssl, ciphersuite_info, ssl->tls_version,
ssl->tls_version ) != 0 ) )
{
continue;
}
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
/* MAC of selected ciphersuite MUST be same with PSK binder if exist.
* Otherwise, client should reject.
*/
if( psk_alg != MBEDTLS_MD_NONE && psk_alg != ciphersuite_info->mac )
continue;
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
ssl->session_negotiate->ciphersuite = cipher_suite;
ssl->handshake->ciphersuite_info = ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %04x - %s",
cipher_suite,
ciphersuite_info->name ) );
}
if( ssl->handshake->ciphersuite_info == NULL )
{
MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
return ( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
}
ret = ssl_tls13_determine_key_exchange_mode( ssl );
if( ret < 0 )
return( ret );