diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 4a9c1c72e3e3..401795f9d742 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -939,6 +939,9 @@ struct mbedtls_ssl_handshake_params 1 -- MBEDTLS_SSL_EARLY_DATA_ENABLED (for use early data) */ int early_data; +#if defined(MBEDTLS_SSL_SRV_C) + int skip_failed_decryption; +#endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_ZERO_RTT */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/library/ssl_msg.c b/library/ssl_msg.c index b5ee52255e50..3db70247dcb7 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -4114,10 +4114,21 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, return( ret ); } - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - update_hs_digest == 1 ) + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) { - mbedtls_ssl_update_handshake_status( ssl ); + if( update_hs_digest == 1) + mbedtls_ssl_update_handshake_status( ssl ); + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_ZERO_RTT) + if( ssl->handshake != NULL && + ssl->handshake->skip_failed_decryption != 0 && + ssl->transform_in != NULL ) + { + /* Record deprotected successfully */ + ssl->handshake->skip_failed_decryption = 0; + MBEDTLS_SSL_DEBUG_MSG( 4, ( "disabling skip_failed_decryption" ) ); + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_ZERO_RTT */ } } else @@ -4711,6 +4722,41 @@ static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_PROTO_DTLS */ +/* + * RFC 8446: + * "If the client attempts a 0-RTT handshake but the server + * rejects it, the server will generally not have the 0-RTT record + * protection keys and must instead use trial decryption (either with + * the 1-RTT handshake keys or by looking for a cleartext ClientHello in + * the case of a HelloRetryRequest) to find the first non-0-RTT message." + */ +#if defined(MBEDTLS_SSL_SRV_C) +static int ssl_should_drop_record( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_ZERO_RTT) && !defined(MBEDTLS_SSL_USE_MPS) + if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER || ssl->handshake == NULL ) + return( 0 ); + + /* + * Drop record iff: + * 1. Client indicated early data use (skip_failed_decryption). + * 2. Server does not have early data enabled (skip_failed_decryption). + * 3. First non-0-RTT record has not yet been found (skip_failed_decryption). + * 4. 1-RTT handshake keys are in use. + */ + if( ssl->handshake->skip_failed_decryption == 1 && + ssl->transform_in == ssl->handshake->transform_handshake ) + { + return( 1 ); + } + +#endif /* MBEDTLS_ZERO_RTT && !MBEDTLS_SSL_USE_MPS */ + ((void) ssl); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_C */ + static int ssl_get_next_record( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -4879,15 +4925,25 @@ static int ssl_get_next_record( mbedtls_ssl_context *ssl ) else #endif { - /* Error out (and send alert) on invalid records */ -#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) { +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->handshake != NULL && + ssl_should_drop_record( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid record (mac), dropping 0-RTT message" ) ); + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + + /* Error out (and send alert) on invalid records */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); +#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ } -#endif + return( ret ); } } diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index 51d6f1a13f82..2e6ebf735ba4 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -2130,6 +2130,7 @@ int mbedtls_ssl_tls13_write_early_data_ext( mbedtls_ssl_context *ssl, { MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write early_data extension" ) ); ssl->handshake->early_data = MBEDTLS_SSL_EARLY_DATA_OFF; + ssl->handshake->skip_failed_decryption = 1; return( 0 ); } } diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index 3126f687ba25..8da0b260a14f 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -2754,6 +2754,9 @@ static int ssl_tls13_client_hello_postprocess( mbedtls_ssl_context *ssl, int ret = 0; #if defined(MBEDTLS_ZERO_RTT) mbedtls_ssl_key_set traffic_keys; + + if( ssl->handshake->hello_retry_requests_sent == 1 ) + ssl->handshake->skip_failed_decryption = 0; #endif /* MBEDTLS_ZERO_RTT */ if( ssl->handshake->hello_retry_requests_sent == 0 && diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 20a89808dbd0..ef94cd7806a5 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -2188,6 +2188,19 @@ run_test "TLS 1.3, TLS1-3-AES-256-GCM-SHA384, ext PSK, early data status - no 0 \ -c "early data status = 0" \ +# test early data status - rejected +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_config_enabled MBEDTLS_DEBUG_C +requires_config_enabled MBEDTLS_SSL_SRV_C +requires_config_enabled MBEDTLS_SSL_CLI_C +requires_config_enabled MBEDTLS_ZERO_RTT +requires_config_disabled MBEDTLS_SSL_USE_MPS +run_test "TLS 1.3, TLS1-3-AES-256-GCM-SHA384, ext PSK, early data status - rejected" \ + "$P_SRV nbio=2 debug_level=5 force_version=tls13 early_data=0 tls13_kex_modes=psk psk=010203 psk_identity=0a0b0c" \ + "$P_CLI nbio=2 debug_level=5 force_version=tls13 force_ciphersuite=TLS1-3-AES-256-GCM-SHA384 tls13_kex_modes=psk early_data=1 psk=010203 psk_identity=0a0b0c" \ + 0 \ + -c "early data status = 1" \ + # test early data status - accepted requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 requires_config_enabled MBEDTLS_DEBUG_C