Merge pull request #6167 from yuhaoth/pr/finalize-tls13-session-tickets

This commit is contained in:
Ronald Cron 2022-09-18 21:18:13 +02:00 committed by GitHub
commit be0224aef3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 484 additions and 146 deletions

View file

@ -1549,6 +1549,26 @@
*/
//#define MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
/**
* \def MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE
*
* Maximum time difference in milliseconds tolerated between the age of a
* ticket from the server and client point of view.
* From the client point of view, the age of a ticket is the time difference
* between the time when the client proposes to the server to use the ticket
* (time of writing of the Pre-Shared Key Extension including the ticket) and
* the time the client received the ticket from the server.
* From the server point of view, the age of a ticket is the time difference
* between the time when the server receives a proposition from the client
* to use the ticket and the time when the ticket was created by the server.
* The server age is expected to be always greater than the client one and
* MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE defines the
* maximum difference tolerated for the server to accept the ticket.
* This is not used in TLS 1.2.
*
*/
#define MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE 6000
/**
* \def MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH
*

View file

@ -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.

View file

@ -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,8 +771,7 @@ 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,
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" ) );
@ -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,7 +896,7 @@ 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,
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,14 +1331,14 @@ 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,
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
@ -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 );
}

View file

@ -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 */

View file

@ -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 );
}

View file

@ -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

View file

@ -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 );

View file

@ -657,6 +657,58 @@ int report_cid_usage( mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
static int ssl_save_session_serialize( mbedtls_ssl_context *ssl,
unsigned char **session_data,
size_t *session_data_len )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ssl_session exported_session;
/* free any previously saved data */
if( *session_data != NULL )
{
mbedtls_platform_zeroize( *session_data, *session_data_len );
mbedtls_free( *session_data );
*session_data = NULL;
*session_data_len = 0;
}
mbedtls_ssl_session_init( &exported_session );
ret = mbedtls_ssl_get_session( ssl, &exported_session );
if( ret != 0 )
{
mbedtls_printf(
"failed\n ! mbedtls_ssl_get_session() returned -%#02x\n",
(unsigned) -ret );
goto exit;
}
/* get size of the buffer needed */
mbedtls_ssl_session_save( &exported_session, NULL, 0, session_data_len );
*session_data = mbedtls_calloc( 1, *session_data_len );
if( *session_data == NULL )
{
mbedtls_printf( " failed\n ! alloc %u bytes for session data\n",
(unsigned) *session_data_len );
ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
goto exit;
}
/* actually save session data */
if( ( ret = mbedtls_ssl_session_save( &exported_session,
*session_data, *session_data_len,
session_data_len ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_session_saved returned -0x%04x\n\n",
(unsigned int) -ret );
goto exit;
}
exit:
mbedtls_ssl_session_free( &exported_session );
return( ret );
}
int main( int argc, char *argv[] )
{
int ret = 0, len, tail_len, i, written, frags, retry_left;
@ -2360,57 +2412,21 @@ int main( int argc, char *argv[] )
}
}
#endif /* MBEDTLS_SSL_DTLS_SRTP */
if( opt.reconnect != 0 )
if( opt.reconnect != 0 && ssl.tls_version != MBEDTLS_SSL_VERSION_TLS1_3 )
{
mbedtls_printf(" . Saving session for reuse..." );
fflush( stdout );
if( opt.reco_mode == 1 )
{
mbedtls_ssl_session exported_session;
/* free any previously saved data */
if( session_data != NULL )
if( ( ret = ssl_save_session_serialize( &ssl,
&session_data, &session_data_len ) ) != 0 )
{
mbedtls_platform_zeroize( session_data, session_data_len );
mbedtls_free( session_data );
session_data = NULL;
}
mbedtls_ssl_session_init( &exported_session );
ret = mbedtls_ssl_get_session( &ssl, &exported_session );
if( ret != 0 )
{
mbedtls_printf(
"failed\n ! mbedtls_ssl_get_session() returned -%#02x\n",
(unsigned) -ret );
goto exit;
}
/* get size of the buffer needed */
mbedtls_ssl_session_save( &exported_session, NULL, 0, &session_data_len );
session_data = mbedtls_calloc( 1, session_data_len );
if( session_data == NULL )
{
mbedtls_printf( " failed\n ! alloc %u bytes for session data\n",
(unsigned) session_data_len );
mbedtls_ssl_session_free( &exported_session );
ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
goto exit;
}
/* actually save session data */
if( ( ret = mbedtls_ssl_session_save( &exported_session,
session_data, session_data_len,
&session_data_len ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_session_saved returned -0x%04x\n\n",
mbedtls_printf( " failed\n ! ssl_save_session_serialize returned -0x%04x\n\n",
(unsigned int) -ret );
mbedtls_ssl_session_free( &exported_session );
goto exit;
}
mbedtls_ssl_session_free( &exported_session );
}
else
{
@ -2700,6 +2716,40 @@ send_request:
/* We were waiting for application data but got
* a NewSessionTicket instead. */
mbedtls_printf( " got new session ticket.\n" );
if( opt.reconnect != 0 )
{
mbedtls_printf(" . Saving session for reuse..." );
fflush( stdout );
if( opt.reco_mode == 1 )
{
if( ( ret = ssl_save_session_serialize( &ssl,
&session_data, &session_data_len ) ) != 0 )
{
mbedtls_printf( " failed\n ! ssl_save_session_serialize returned -0x%04x\n\n",
(unsigned int) -ret );
goto exit;
}
}
else
{
if( ( ret = mbedtls_ssl_get_session( &ssl, &saved_session ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_get_session returned -0x%x\n\n",
(unsigned int) -ret );
goto exit;
}
}
mbedtls_printf( " ok\n" );
if( opt.reco_mode == 1 )
{
mbedtls_printf( " [ Saved %u bytes of session data]\n",
(unsigned) session_data_len );
}
}
continue;
#endif /* MBEDTLS_SSL_SESSION_TICKETS */

View file

@ -12096,7 +12096,7 @@ requires_config_enabled MBEDTLS_SSL_CLI_C
run_test "TLS 1.3, default suite, PSK" \
"$P_SRV nbio=2 debug_level=5 force_version=tls13 psk=010203 psk_identity=0a0b0c tls13_kex_modes=psk" \
"$P_CLI nbio=2 debug_level=5 force_version=tls13 psk=010203 psk_identity=0a0b0c tls13_kex_modes=psk" \
1 \
0 \
-c "=> write client hello" \
-c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
-c "client hello, adding psk_key_exchange_modes extension" \
@ -12111,7 +12111,7 @@ requires_config_enabled MBEDTLS_SSL_CLI_C
run_test "TLS 1.3, default suite, PSK - openssl" \
"$O_NEXT_SRV -msg -debug -tls1_3 -psk_identity 0a0b0c -psk 010203 -allow_no_dhe_kex -nocert" \
"$P_CLI debug_level=4 psk=010203 psk_identity=0a0b0c tls13_kex_modes=psk" \
1 \
0 \
-c "=> write client hello" \
-c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
-c "client hello, adding psk_key_exchange_modes extension" \
@ -12756,13 +12756,13 @@ requires_config_enabled MBEDTLS_DEBUG_C
requires_config_enabled MBEDTLS_SSL_CLI_C
requires_config_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
run_test "TLS 1.3: NewSessionTicket: Basic check, m->O" \
"$O_NEXT_SRV -msg -tls1_3 -no_resume_ephemeral -no_cache " \
"$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
"$O_NEXT_SRV -msg -tls1_3 -no_resume_ephemeral -no_cache --num_tickets 4" \
"$P_CLI debug_level=1 reco_mode=1 reconnect=1" \
0 \
-c "Protocol is TLSv1.3" \
-c "MBEDTLS_SSL_NEW_SESSION_TICKET" \
-c "got new session ticket." \
-c "Saving session for reuse... ok" \
-c "Reconnecting with saved session" \
-c "HTTP/1.0 200 ok"
requires_gnutls_tls1_3
@ -12771,27 +12771,15 @@ requires_config_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
requires_config_enabled MBEDTLS_DEBUG_C
requires_config_enabled MBEDTLS_SSL_CLI_C
run_test "TLS 1.3: NewSessionTicket: Basic check, m->G" \
"$G_NEXT_SRV --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+PSK --disable-client-cert" \
"$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
"$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+PSK --disable-client-cert" \
"$P_CLI debug_level=1 reco_mode=1 reconnect=1" \
0 \
-c "Protocol is TLSv1.3" \
-c "MBEDTLS_SSL_NEW_SESSION_TICKET" \
-c "got new session ticket." \
-c "Saving session for reuse... ok" \
-c "HTTP/1.0 200 OK"
requires_openssl_tls1_3
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
requires_config_enabled MBEDTLS_SSL_SRV_C
requires_config_enabled MBEDTLS_DEBUG_C
run_test "TLS 1.3: NewSessionTicket: Basic check, O->m" \
"$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=1" \
"$O_NEXT_CLI -msg -debug -tls1_3 -no_middlebox" \
0 \
-s "=> write NewSessionTicket msg" \
-s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET" \
-s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH"
-c "Reconnecting with saved session" \
-c "HTTP/1.0 200 OK" \
-s "This is a resumed session"
requires_gnutls_tls1_3
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
@ -12800,12 +12788,16 @@ requires_config_enabled MBEDTLS_SSL_SRV_C
requires_config_enabled MBEDTLS_DEBUG_C
run_test "TLS 1.3: NewSessionTicket: Basic check, G->m" \
"$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=1" \
"$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:%DISABLE_TLS13_COMPAT_MODE -V" \
"$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:%DISABLE_TLS13_COMPAT_MODE -V -r" \
0 \
-c "Connecting again- trying to resume previous session" \
-c "NEW SESSION TICKET (4) was received" \
-s "=> write NewSessionTicket msg" \
-s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET" \
-s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH" \
-c "NEW SESSION TICKET (4) was received"
-s "key exchange mode: ephemeral" \
-s "key exchange mode: psk_ephemeral" \
-s "found pre_shared_key extension"
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
@ -12817,13 +12809,17 @@ run_test "TLS 1.3: NewSessionTicket: Basic check, m->m" \
"$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
0 \
-c "Protocol is TLSv1.3" \
-c "MBEDTLS_SSL_NEW_SESSION_TICKET" \
-c "got new session ticket." \
-c "Saving session for reuse... ok" \
-c "Reconnecting with saved session" \
-c "HTTP/1.0 200 OK" \
-s "=> write NewSessionTicket msg" \
-s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET" \
-s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH"
-s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH" \
-s "key exchange mode: ephemeral" \
-s "key exchange mode: psk_ephemeral" \
-s "found pre_shared_key extension"
requires_openssl_tls1_3
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2