mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-08-01 10:06:53 +03:00
Merge pull request #6167 from yuhaoth/pr/finalize-tls13-session-tickets
This commit is contained in:
@ -2457,16 +2457,6 @@ int mbedtls_ssl_check_dtls_clihlo_cookie(
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
|
||||
/* Check if we have any PSK to offer, returns 0 if PSK is available.
|
||||
* Assign the psk and ticket if pointers are present.
|
||||
*/
|
||||
MBEDTLS_CHECK_RETURN_CRITICAL
|
||||
int mbedtls_ssl_get_psk_to_offer(
|
||||
const mbedtls_ssl_context *ssl,
|
||||
int *psk_type,
|
||||
const unsigned char **psk, size_t *psk_len,
|
||||
const unsigned char **psk_identity, size_t *psk_identity_len );
|
||||
|
||||
/**
|
||||
* \brief Given an SSL context and its associated configuration, write the TLS
|
||||
* 1.3 specific Pre-Shared key extension.
|
||||
|
@ -664,10 +664,59 @@ static int ssl_tls13_write_psk_key_exchange_modes_ext( mbedtls_ssl_context *ssl,
|
||||
ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_PSK_KEY_EXCHANGE_MODES;
|
||||
return ( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
|
||||
|
||||
/* Check if we have any PSK to offer, returns 0 if a PSK is available. */
|
||||
MBEDTLS_CHECK_RETURN_CRITICAL
|
||||
static int ssl_tls13_get_psk_to_offer(
|
||||
const mbedtls_ssl_context *ssl,
|
||||
int *psk_type,
|
||||
const unsigned char **psk, size_t *psk_len,
|
||||
const unsigned char **psk_identity, size_t *psk_identity_len )
|
||||
{
|
||||
*psk = NULL;
|
||||
*psk_len = 0;
|
||||
*psk_identity = NULL;
|
||||
*psk_identity_len = 0;
|
||||
*psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL;
|
||||
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||
/* Check if a ticket has been configured. */
|
||||
if( ssl->session_negotiate != NULL &&
|
||||
ssl->session_negotiate->ticket != NULL )
|
||||
{
|
||||
#if defined(MBEDTLS_HAVE_TIME)
|
||||
mbedtls_time_t now = mbedtls_time( NULL );
|
||||
if( ssl->session_negotiate->ticket_received <= now &&
|
||||
(uint64_t)( now - ssl->session_negotiate->ticket_received )
|
||||
<= ssl->session_negotiate->ticket_lifetime )
|
||||
{
|
||||
*psk_type = MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION;
|
||||
*psk = ssl->session_negotiate->resumption_key;
|
||||
*psk_len = ssl->session_negotiate->resumption_key_len;
|
||||
*psk_identity = ssl->session_negotiate->ticket;
|
||||
*psk_identity_len = ssl->session_negotiate->ticket_len;
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_HAVE_TIME */
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket expired" ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check if an external PSK has been configured. */
|
||||
if( ssl->conf->psk != NULL )
|
||||
{
|
||||
*psk = ssl->conf->psk;
|
||||
*psk_len = ssl->conf->psk_len;
|
||||
*psk_identity = ssl->conf->psk_identity;
|
||||
*psk_identity_len = ssl->conf->psk_identity_len;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
return( MBEDTLS_ERR_ERROR_GENERIC_ERROR );
|
||||
}
|
||||
|
||||
/*
|
||||
* mbedtls_ssl_tls13_write_pre_shared_key_ext() structure:
|
||||
* mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext() structure:
|
||||
*
|
||||
* struct {
|
||||
* opaque identity<1..2^16-1>;
|
||||
@ -689,9 +738,6 @@ static int ssl_tls13_write_psk_key_exchange_modes_ext( mbedtls_ssl_context *ssl,
|
||||
* } PreSharedKeyExtension;
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
|
||||
|
||||
int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext(
|
||||
mbedtls_ssl_context *ssl,
|
||||
unsigned char *buf, unsigned char *end,
|
||||
@ -725,9 +771,8 @@ int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext(
|
||||
* configured, offer that.
|
||||
* - Otherwise, skip the PSK extension.
|
||||
*/
|
||||
|
||||
if( mbedtls_ssl_get_psk_to_offer( ssl, &psk_type, &psk, &psk_len,
|
||||
&psk_identity, &psk_identity_len ) != 0 )
|
||||
if( ssl_tls13_get_psk_to_offer( ssl, &psk_type, &psk, &psk_len,
|
||||
&psk_identity, &psk_identity_len ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip pre_shared_key extensions" ) );
|
||||
return( 0 );
|
||||
@ -757,6 +802,26 @@ int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext(
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||
if( psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION )
|
||||
{
|
||||
#if defined(MBEDTLS_HAVE_TIME)
|
||||
mbedtls_time_t now = mbedtls_time( NULL );
|
||||
|
||||
obfuscated_ticket_age =
|
||||
( (uint32_t)( now - ssl->session_negotiate->ticket_received ) * 1000 )
|
||||
+ ssl->session_negotiate->ticket_age_add;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "write_identities_of_pre_shared_key_ext: "
|
||||
"should never happen" ) );
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
|
||||
|
||||
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(
|
||||
ssl->session_negotiate->ciphersuite );
|
||||
@ -831,8 +896,8 @@ int mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext(
|
||||
unsigned char transcript[MBEDTLS_MD_MAX_SIZE];
|
||||
size_t transcript_len;
|
||||
|
||||
if( mbedtls_ssl_get_psk_to_offer( ssl, &psk_type, &psk, &psk_len,
|
||||
&psk_identity, &psk_identity_len ) != 0 )
|
||||
if( ssl_tls13_get_psk_to_offer( ssl, &psk_type, &psk, &psk_len,
|
||||
&psk_identity, &psk_identity_len ) != 0 )
|
||||
{
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
@ -1266,15 +1331,15 @@ static int ssl_tls13_parse_server_pre_shared_key_ext( mbedtls_ssl_context *ssl,
|
||||
size_t psk_len;
|
||||
const unsigned char *psk_identity;
|
||||
size_t psk_identity_len;
|
||||
|
||||
int psk_type;
|
||||
|
||||
/* Check which PSK we've offered.
|
||||
*
|
||||
* NOTE: Ultimately, we want to offer multiple PSKs, and in this
|
||||
* case, we need to iterate over them here.
|
||||
*/
|
||||
if( mbedtls_ssl_get_psk_to_offer( ssl, NULL, &psk, &psk_len,
|
||||
&psk_identity, &psk_identity_len ) != 0 )
|
||||
if( ssl_tls13_get_psk_to_offer( ssl, &psk_type, &psk, &psk_len,
|
||||
&psk_identity, &psk_identity_len ) != 0 )
|
||||
{
|
||||
/* If we haven't offered a PSK, the server must not send
|
||||
* a PSK identity extension. */
|
||||
@ -1622,16 +1687,19 @@ static int ssl_tls13_postprocess_server_hello( mbedtls_ssl_context *ssl )
|
||||
/* Only the pre_shared_key extension was received */
|
||||
case MBEDTLS_SSL_EXT_PRE_SHARED_KEY:
|
||||
handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "key exchange mode: psk" ) );
|
||||
break;
|
||||
|
||||
/* Only the key_share extension was received */
|
||||
case MBEDTLS_SSL_EXT_KEY_SHARE:
|
||||
handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL;
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "key exchange mode: ephemeral" ) );
|
||||
break;
|
||||
|
||||
/* Both the pre_shared_key and key_share extensions were received */
|
||||
case ( MBEDTLS_SSL_EXT_PRE_SHARED_KEY | MBEDTLS_SSL_EXT_KEY_SHARE ):
|
||||
handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "key exchange mode: psk_ephemeral" ) );
|
||||
break;
|
||||
|
||||
/* Neither pre_shared_key nor key_share extension was received */
|
||||
@ -1819,7 +1887,12 @@ static int ssl_tls13_parse_encrypted_extensions( mbedtls_ssl_context *ssl,
|
||||
*/
|
||||
switch( extension_type )
|
||||
{
|
||||
case MBEDTLS_TLS_EXT_SERVERNAME:
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found server_name extension" ) );
|
||||
|
||||
/* The server_name extension should be an empty extension */
|
||||
|
||||
break;
|
||||
case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS:
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extensions supported groups" ) );
|
||||
break;
|
||||
@ -2237,11 +2310,11 @@ static int ssl_tls13_write_client_finished( mbedtls_ssl_context *ssl )
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
ret = mbedtls_ssl_tls13_generate_resumption_master_secret( ssl );
|
||||
ret = mbedtls_ssl_tls13_compute_resumption_master_secret( ssl );
|
||||
if( ret != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1,
|
||||
"mbedtls_ssl_tls13_generate_resumption_master_secret ", ret );
|
||||
"mbedtls_ssl_tls13_compute_resumption_master_secret ", ret );
|
||||
return ( ret );
|
||||
}
|
||||
|
||||
@ -2405,6 +2478,9 @@ static int ssl_tls13_parse_new_session_ticket( mbedtls_ssl_context *ssl,
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/* session has been updated, allow export */
|
||||
session->exported = 0;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
@ -1504,41 +1504,4 @@ int mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
|
||||
}
|
||||
#endif /* MBEDTLS_ECDH_C */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
|
||||
/* Check if we have any PSK to offer, returns 0 if PSK is available.
|
||||
* Assign the psk and ticket if pointers are present.
|
||||
*/
|
||||
int mbedtls_ssl_get_psk_to_offer(
|
||||
const mbedtls_ssl_context *ssl,
|
||||
int *psk_type,
|
||||
const unsigned char **psk, size_t *psk_len,
|
||||
const unsigned char **psk_identity, size_t *psk_identity_len )
|
||||
{
|
||||
int ptrs_present = 0;
|
||||
|
||||
if( psk_type != NULL && psk != NULL && psk_len != NULL &&
|
||||
psk_identity != NULL && psk_identity_len != NULL )
|
||||
{
|
||||
ptrs_present = 1;
|
||||
}
|
||||
|
||||
/* Check if an external PSK has been configured. */
|
||||
if( ssl->conf->psk != NULL )
|
||||
{
|
||||
if( ptrs_present )
|
||||
{
|
||||
*psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL;
|
||||
*psk = ssl->conf->psk;
|
||||
*psk_len = ssl->conf->psk_len;
|
||||
*psk_identity = ssl->conf->psk_identity;
|
||||
*psk_identity_len = ssl->conf->psk_identity_len;
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
|
||||
|
||||
#endif /* MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_PROTO_TLS1_3 */
|
||||
|
@ -1504,12 +1504,43 @@ cleanup:
|
||||
return( ret );
|
||||
}
|
||||
|
||||
int mbedtls_ssl_tls13_generate_resumption_master_secret(
|
||||
mbedtls_ssl_context *ssl )
|
||||
int mbedtls_ssl_tls13_compute_resumption_master_secret( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
mbedtls_md_type_t md_type;
|
||||
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
|
||||
unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
|
||||
size_t transcript_len;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2,
|
||||
( "=> mbedtls_ssl_tls13_compute_resumption_master_secret" ) );
|
||||
|
||||
md_type = handshake->ciphersuite_info->mac;
|
||||
|
||||
ret = mbedtls_ssl_get_handshake_transcript( ssl, md_type,
|
||||
transcript, sizeof( transcript ),
|
||||
&transcript_len );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
ret = mbedtls_ssl_tls13_derive_resumption_master_secret(
|
||||
mbedtls_psa_translate_md( md_type ),
|
||||
handshake->tls13_master_secrets.app,
|
||||
transcript, transcript_len,
|
||||
&ssl->session_negotiate->app_secrets );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
/* Erase master secrets */
|
||||
mbedtls_platform_zeroize( &ssl->handshake->tls13_master_secrets,
|
||||
sizeof( ssl->handshake->tls13_master_secrets ) );
|
||||
mbedtls_platform_zeroize( &handshake->tls13_master_secrets,
|
||||
sizeof( handshake->tls13_master_secrets ) );
|
||||
|
||||
MBEDTLS_SSL_DEBUG_BUF( 4, "Resumption master secret",
|
||||
ssl->session_negotiate->app_secrets.resumption_master_secret,
|
||||
PSA_HASH_LENGTH( mbedtls_psa_translate_md( md_type ) ) ) ;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2,
|
||||
( "<= mbedtls_ssl_tls13_compute_resumption_master_secret" ) );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
@ -636,8 +636,7 @@ int mbedtls_ssl_tls13_generate_application_keys(
|
||||
* \returns A negative error code on failure.
|
||||
*/
|
||||
MBEDTLS_CHECK_RETURN_CRITICAL
|
||||
int mbedtls_ssl_tls13_generate_resumption_master_secret(
|
||||
mbedtls_ssl_context *ssl );
|
||||
int mbedtls_ssl_tls13_compute_resumption_master_secret( mbedtls_ssl_context *ssl );
|
||||
|
||||
/**
|
||||
* \brief Calculate the verify_data value for the client or server TLS 1.3
|
||||
|
@ -121,14 +121,170 @@ static int ssl_tls13_parse_key_exchange_modes_ext( mbedtls_ssl_context *ssl,
|
||||
|
||||
#define SSL_TLS1_3_OFFERED_PSK_NOT_MATCH 1
|
||||
#define SSL_TLS1_3_OFFERED_PSK_MATCH 0
|
||||
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||
|
||||
MBEDTLS_CHECK_RETURN_CRITICAL
|
||||
static int ssl_tls13_offered_psks_check_identity_match_ticket(
|
||||
mbedtls_ssl_context *ssl,
|
||||
const unsigned char *identity,
|
||||
size_t identity_len,
|
||||
uint32_t obfuscated_ticket_age,
|
||||
mbedtls_ssl_session *session )
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
unsigned char *ticket_buffer;
|
||||
#if defined(MBEDTLS_HAVE_TIME)
|
||||
mbedtls_time_t now;
|
||||
uint64_t age_in_s;
|
||||
int64_t age_diff_in_ms;
|
||||
#endif
|
||||
|
||||
((void) obfuscated_ticket_age);
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> check_identity_match_ticket" ) );
|
||||
|
||||
/* Ticket parser is not configured, Skip */
|
||||
if( ssl->conf->f_ticket_parse == NULL || identity_len == 0 )
|
||||
return( 0 );
|
||||
|
||||
/* We create a copy of the encrypted ticket since the ticket parsing
|
||||
* function is allowed to use its input buffer as an output buffer
|
||||
* (in-place decryption). We do, however, need the original buffer for
|
||||
* computing the PSK binder value.
|
||||
*/
|
||||
ticket_buffer = mbedtls_calloc( 1, identity_len );
|
||||
if( ticket_buffer == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
|
||||
return ( MBEDTLS_ERR_SSL_ALLOC_FAILED );
|
||||
}
|
||||
memcpy( ticket_buffer, identity, identity_len );
|
||||
|
||||
if( ( ret = ssl->conf->f_ticket_parse( ssl->conf->p_ticket,
|
||||
session,
|
||||
ticket_buffer, identity_len ) ) != 0 )
|
||||
{
|
||||
if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is not authentic" ) );
|
||||
else if( ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED )
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is expired" ) );
|
||||
else
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "ticket_parse", ret );
|
||||
}
|
||||
|
||||
/* We delete the temporary buffer */
|
||||
mbedtls_free( ticket_buffer );
|
||||
|
||||
if( ret != 0 )
|
||||
goto exit;
|
||||
|
||||
ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
|
||||
#if defined(MBEDTLS_HAVE_TIME)
|
||||
now = mbedtls_time( NULL );
|
||||
|
||||
if( now < session->start )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG(
|
||||
3, ( "Ticket expired: now=%" MBEDTLS_PRINTF_LONGLONG
|
||||
", start=%" MBEDTLS_PRINTF_LONGLONG,
|
||||
(long long)now, (long long)session->start ) );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
age_in_s = (uint64_t)( now - session->start );
|
||||
|
||||
/* RFC 8446 section 4.6.1
|
||||
*
|
||||
* Servers MUST NOT use any value greater than 604800 seconds (7 days).
|
||||
*
|
||||
* RFC 8446 section 4.2.11.1
|
||||
*
|
||||
* Clients MUST NOT attempt to use tickets which have ages greater than
|
||||
* the "ticket_lifetime" value which was provided with the ticket.
|
||||
*
|
||||
* For time being, the age MUST be less than 604800 seconds (7 days).
|
||||
*/
|
||||
if( age_in_s > 604800 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG(
|
||||
3, ( "Ticket expired: Ticket age exceed limitation ticket_age=%lu",
|
||||
(long unsigned int)age_in_s ) );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* RFC 8446 section 4.2.10
|
||||
*
|
||||
* For PSKs provisioned via NewSessionTicket, a server MUST validate that
|
||||
* the ticket age for the selected PSK identity (computed by subtracting
|
||||
* ticket_age_add from PskIdentity.obfuscated_ticket_age modulo 2^32) is
|
||||
* within a small tolerance of the time since the ticket was issued.
|
||||
*
|
||||
* NOTE: When `now == session->start`, `age_diff_in_ms` may be negative
|
||||
* as the age units are different on the server (s) and in the
|
||||
* client (ms) side. Add a -1000 ms tolerance window to take this
|
||||
* into account.
|
||||
*/
|
||||
age_diff_in_ms = age_in_s * 1000;
|
||||
age_diff_in_ms -= ( obfuscated_ticket_age - session->ticket_age_add );
|
||||
if( age_diff_in_ms <= -1000 ||
|
||||
age_diff_in_ms > MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG(
|
||||
3, ( "Ticket expired: Ticket age outside tolerance window "
|
||||
"( diff=%d )", (int)age_diff_in_ms ) );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
#endif /* MBEDTLS_HAVE_TIME */
|
||||
|
||||
exit:
|
||||
if( ret != 0 )
|
||||
mbedtls_ssl_session_free( session );
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= check_identity_match_ticket" ) );
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
|
||||
|
||||
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,
|
||||
int *psk_type )
|
||||
uint32_t obfuscated_ticket_age,
|
||||
int *psk_type,
|
||||
mbedtls_ssl_session *session )
|
||||
{
|
||||
((void) session);
|
||||
((void) obfuscated_ticket_age);
|
||||
*psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_BUF( 4, "identity", identity, identity_len );
|
||||
ssl->handshake->resume = 0;
|
||||
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||
if( ssl_tls13_offered_psks_check_identity_match_ticket(
|
||||
ssl, identity, identity_len, obfuscated_ticket_age,
|
||||
session ) == SSL_TLS1_3_OFFERED_PSK_MATCH )
|
||||
{
|
||||
ssl->handshake->resume = 1;
|
||||
*psk_type = MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION;
|
||||
mbedtls_ssl_set_hs_psk( ssl,
|
||||
session->resumption_key,
|
||||
session->resumption_key_len );
|
||||
|
||||
MBEDTLS_SSL_DEBUG_BUF( 4, "Ticket-resumed PSK:",
|
||||
session->resumption_key,
|
||||
session->resumption_key_len );
|
||||
MBEDTLS_SSL_DEBUG_MSG( 4, ( "ticket: obfuscated_ticket_age: %u",
|
||||
(unsigned)obfuscated_ticket_age ) );
|
||||
return( SSL_TLS1_3_OFFERED_PSK_MATCH );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
|
||||
|
||||
/* Check identity with external configured function */
|
||||
if( ssl->conf->f_psk != NULL )
|
||||
{
|
||||
@ -256,6 +412,7 @@ static int ssl_tls13_select_ciphersuite_for_psk(
|
||||
return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||
MBEDTLS_CHECK_RETURN_CRITICAL
|
||||
static int ssl_tls13_select_ciphersuite_for_resumption(
|
||||
mbedtls_ssl_context *ssl,
|
||||
@ -265,15 +422,46 @@ static int ssl_tls13_select_ciphersuite_for_resumption(
|
||||
uint16_t *selected_ciphersuite,
|
||||
const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info )
|
||||
{
|
||||
((void) ssl);
|
||||
((void) session);
|
||||
((void) cipher_suites);
|
||||
((void) cipher_suites_end);
|
||||
|
||||
*selected_ciphersuite = 0;
|
||||
*selected_ciphersuite_info = NULL;
|
||||
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
|
||||
for( const unsigned char *p = cipher_suites; p < cipher_suites_end; p += 2 )
|
||||
{
|
||||
uint16_t cipher_suite = MBEDTLS_GET_UINT16_BE( p, 0 );
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
|
||||
|
||||
if( cipher_suite != session->ciphersuite )
|
||||
continue;
|
||||
|
||||
ciphersuite_info = ssl_tls13_validate_peer_ciphersuite( ssl,
|
||||
cipher_suite );
|
||||
if( ciphersuite_info == NULL )
|
||||
continue;
|
||||
|
||||
*selected_ciphersuite = cipher_suite;
|
||||
*selected_ciphersuite_info = ciphersuite_info;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
|
||||
}
|
||||
|
||||
MBEDTLS_CHECK_RETURN_CRITICAL
|
||||
static int ssl_tls13_session_copy_ticket( mbedtls_ssl_session *dst,
|
||||
const mbedtls_ssl_session *src )
|
||||
{
|
||||
dst->ticket_age_add = src->ticket_age_add;
|
||||
dst->ticket_flags = src->ticket_flags;
|
||||
dst->resumption_key_len = src->resumption_key_len;
|
||||
if( src->resumption_key_len == 0 )
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
memcpy( dst->resumption_key, src->resumption_key, src->resumption_key_len );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
|
||||
|
||||
/* Parser for pre_shared_key extension in client hello
|
||||
* struct {
|
||||
* opaque identity<1..2^16-1>;
|
||||
@ -343,17 +531,23 @@ static int ssl_tls13_parse_pre_shared_key_ext( mbedtls_ssl_context *ssl,
|
||||
{
|
||||
const unsigned char *identity;
|
||||
size_t identity_len;
|
||||
uint32_t obfuscated_ticket_age;
|
||||
const unsigned char *binder;
|
||||
size_t binder_len;
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
int psk_type;
|
||||
uint16_t cipher_suite;
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||
mbedtls_ssl_session session;
|
||||
mbedtls_ssl_session_init( &session );
|
||||
#endif
|
||||
|
||||
MBEDTLS_SSL_CHK_BUF_READ_PTR( p_identity_len, identities_end, 2 + 1 + 4 );
|
||||
identity_len = MBEDTLS_GET_UINT16_BE( p_identity_len, 0 );
|
||||
identity = p_identity_len + 2;
|
||||
MBEDTLS_SSL_CHK_BUF_READ_PTR( identity, identities_end, identity_len + 4 );
|
||||
obfuscated_ticket_age = MBEDTLS_GET_UINT32_BE( identity , identity_len );
|
||||
p_identity_len += identity_len + 6;
|
||||
|
||||
MBEDTLS_SSL_CHK_BUF_READ_PTR( p_binder_len, binders_end, 1 + 32 );
|
||||
@ -367,7 +561,8 @@ 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, &psk_type );
|
||||
ssl, identity, identity_len, obfuscated_ticket_age,
|
||||
&psk_type, &session );
|
||||
if( ret != SSL_TLS1_3_OFFERED_PSK_MATCH )
|
||||
continue;
|
||||
|
||||
@ -380,9 +575,15 @@ static int ssl_tls13_parse_pre_shared_key_ext( mbedtls_ssl_context *ssl,
|
||||
&cipher_suite, &ciphersuite_info );
|
||||
break;
|
||||
case MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION:
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||
ret = ssl_tls13_select_ciphersuite_for_resumption(
|
||||
ssl, ciphersuites, ciphersuites_end, NULL,
|
||||
ssl, ciphersuites, ciphersuites_end, &session,
|
||||
&cipher_suite, &ciphersuite_info );
|
||||
if( ret != 0 )
|
||||
mbedtls_ssl_session_free( &session );
|
||||
#else
|
||||
ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
@ -406,6 +607,9 @@ static int ssl_tls13_parse_pre_shared_key_ext( mbedtls_ssl_context *ssl,
|
||||
/* For security reasons, the handshake should be aborted when we
|
||||
* fail to validate a binder value. See RFC 8446 section 4.2.11.2
|
||||
* and appendix E.6. */
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||
mbedtls_ssl_session_free( &session );
|
||||
#endif
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Invalid binder." ) );
|
||||
MBEDTLS_SSL_DEBUG_RET( 1,
|
||||
"ssl_tls13_offered_psks_check_binder_match" , ret );
|
||||
@ -418,11 +622,20 @@ static int ssl_tls13_parse_pre_shared_key_ext( mbedtls_ssl_context *ssl,
|
||||
matched_identity = identity_id;
|
||||
|
||||
/* Update handshake parameters */
|
||||
ssl->session_negotiate->ciphersuite = cipher_suite;
|
||||
ssl->handshake->ciphersuite_info = ciphersuite_info;
|
||||
ssl->session_negotiate->ciphersuite = cipher_suite;
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "overwrite ciphersuite: %04x - %s",
|
||||
cipher_suite, ciphersuite_info->name ) );
|
||||
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||
if( psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION )
|
||||
{
|
||||
ret = ssl_tls13_session_copy_ticket( ssl->session_negotiate,
|
||||
&session );
|
||||
mbedtls_ssl_session_free( &session );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
|
||||
}
|
||||
|
||||
if( p_identity_len != identities_end || p_binder_len != binders_end )
|
||||
@ -2366,11 +2579,11 @@ static int ssl_tls13_process_client_finished( mbedtls_ssl_context *ssl )
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
ret = mbedtls_ssl_tls13_generate_resumption_master_secret( ssl );
|
||||
ret = mbedtls_ssl_tls13_compute_resumption_master_secret( ssl );
|
||||
if( ret != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1,
|
||||
"mbedtls_ssl_tls13_generate_resumption_master_secret ", ret );
|
||||
"mbedtls_ssl_tls13_compute_resumption_master_secret", ret );
|
||||
}
|
||||
|
||||
mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP );
|
||||
|
Reference in New Issue
Block a user