diff --git a/library/ecdh.c b/library/ecdh.c index b72bd1fe0..ddd4ef545 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -806,6 +806,60 @@ int mbedtls_ecdh_setup_no_everest( mbedtls_ecdh_context *ctx, #endif } +static int ecdh_tls13_read_public_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char *buf, + size_t buf_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + size_t data_len; + + if( buf_len < 3 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + data_len = MBEDTLS_GET_UINT16_BE( p, 0 ); + p += 2; + + if( data_len < 1 || data_len != ( buf_len - 2 ) ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_point_read_binary( &ctx->grp, + &ctx->Qp, p, data_len ) ) != 0) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Parse and import the client's TLS 1.3 public value + */ +int mbedtls_ecdh_tls13_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, + size_t buf_len ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_tls13_read_public_internal( ctx, buf, buf_len ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_tls13_read_public_internal( &ctx->ctx.mbed_ecdh, + buf, buf_len ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ #endif /* MBEDTLS_ECDH_C */ diff --git a/library/ecdh_misc.h b/library/ecdh_misc.h index d1342f8b9..d0f338a83 100644 --- a/library/ecdh_misc.h +++ b/library/ecdh_misc.h @@ -36,13 +36,19 @@ int mbedtls_ecdh_setup_no_everest( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id ); /* - * TLS 1.3 version of mbedtls_ecdh_make_params in ecdh.h + * TLS 1.3 version of mbedtls_ecdh_make_params */ int mbedtls_ecdh_tls13_make_params( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, + unsigned char *buf, size_t buf_len, int ( *f_rng )( void *, unsigned char *, size_t ), void *p_rng ); +/* + * TLS 1.3 version of mbedtls_ecdh_read_public + */ +int mbedtls_ecdh_tls13_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, + size_t buf_len ); #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 9041c51d2..66fb26c62 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -307,9 +307,10 @@ + ( MBEDTLS_SSL_CID_OUT_LEN_MAX ) ) #endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) #define MBEDTLS_TLS1_3_MD_MAX_SIZE MBEDTLS_MD_MAX_SIZE -#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + +#define MBEDTLS_CLIENT_HELLO_RANDOM_LEN 32 +#define MBEDTLS_SERVER_HELLO_RANDOM_LEN 32 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /** @@ -508,6 +509,27 @@ struct mbedtls_ssl_key_set }; typedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set; +typedef struct +{ + unsigned char binder_key [ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; + unsigned char client_early_traffic_secret [ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; + unsigned char early_exporter_master_secret[ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; +} mbedtls_ssl_tls1_3_early_secrets; + +typedef struct +{ + unsigned char client_handshake_traffic_secret[ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; + unsigned char server_handshake_traffic_secret[ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; +} mbedtls_ssl_tls1_3_handshake_secrets; + +typedef struct +{ + unsigned char client_application_traffic_secret_N[ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; + unsigned char server_application_traffic_secret_N[ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; + unsigned char exporter_master_secret [ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; + unsigned char resumption_master_secret [ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; +} mbedtls_ssl_tls1_3_application_secrets; + /* * This structure contains the parameters only needed during handshake. */ @@ -696,7 +718,9 @@ struct mbedtls_ssl_handshake_params size_t pmslen; /*!< premaster length */ - unsigned char randbytes[64]; /*!< random bytes */ + unsigned char randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN + + MBEDTLS_SERVER_HELLO_RANDOM_LEN]; + /*!< random bytes */ unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; /*!< premaster secret */ @@ -715,6 +739,8 @@ struct mbedtls_ssl_handshake_params unsigned char handshake[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char app [MBEDTLS_TLS1_3_MD_MAX_SIZE]; } tls1_3_master_secrets; + + mbedtls_ssl_tls1_3_handshake_secrets tls13_hs_secrets; #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) @@ -859,7 +885,9 @@ struct mbedtls_ssl_transform /* We need the Hello random bytes in order to re-derive keys from the * Master Secret and other session info, * see ssl_tls12_populate_transform() */ - unsigned char randbytes[64]; /*!< ServerHello.random+ClientHello.random */ + unsigned char randbytes[MBEDTLS_SERVER_HELLO_RANDOM_LEN + + MBEDTLS_CLIENT_HELLO_RANDOM_LEN]; + /*!< ServerHello.random+ClientHello.random */ #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ }; diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 633bb8da2..979db3144 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -29,11 +29,11 @@ #include "mbedtls/debug.h" #include "mbedtls/error.h" +#include "mbedtls/platform.h" #include "ssl_misc.h" #include "ecdh_misc.h" - -#define CLIENT_HELLO_RANDOM_LEN 32 +#include "ssl_tls13_keys.h" /* Write extensions */ @@ -92,6 +92,26 @@ static int ssl_tls13_write_supported_versions_ext( mbedtls_ssl_context *ssl, return( 0 ); } +static int ssl_tls13_parse_supported_versions_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end ) +{ + ((void) ssl); + + MBEDTLS_SSL_CHK_BUF_READ_PTR( buf, end, 2); + if( buf[0] != MBEDTLS_SSL_MAJOR_VERSION_3 || + buf[1] != MBEDTLS_SSL_MINOR_VERSION_4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unexpected version" ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + return( 0 ); +} + #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* @@ -452,6 +472,127 @@ cleanup: return( ret ); } +#if defined(MBEDTLS_ECDH_C) + +static int ssl_tls13_check_ecdh_params( const mbedtls_ssl_context *ssl ) +{ + const mbedtls_ecp_curve_info *curve_info; + mbedtls_ecp_group_id grp_id; +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + grp_id = ssl->handshake->ecdh_ctx.grp.id; +#else + grp_id = ssl->handshake->ecdh_ctx.grp_id; +#endif + + curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id ); + if( curve_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); + + if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 ) + return( -1 ); + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + return( 0 ); +} + +static int ssl_tls13_read_public_ecdhe_share( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t buf_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_ecdh_tls13_read_public( &ssl->handshake->ecdh_ctx, + buf, buf_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_tls13_read_public" ), ret ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + if( ssl_tls13_check_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ssl_tls13_check_ecdh_params() failed!" ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C */ + +/* + * ssl_tls13_parse_key_share_ext() + * Parse key_share extension in Server Hello + * + * struct { + * KeyShareEntry server_share; + * } KeyShareServerHello; + * struct { + * NamedGroup group; + * opaque key_exchange<1..2^16-1>; + * } KeyShareEntry; + */ +static int ssl_tls13_parse_key_share_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + uint16_t group, offered_group; + + /* ... + * NamedGroup group; (2 bytes) + * ... + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 ); + group = MBEDTLS_GET_UINT16_BE( p, 0 ); + p += 2; + + /* Check that the chosen group matches the one we offered. */ + offered_group = ssl->handshake->offered_group_id; + if( offered_group != group ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "Invalid server key share, our group %u, their group %u", + (unsigned) offered_group, (unsigned) group ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + +#if defined(MBEDTLS_ECDH_C) + if( mbedtls_ssl_tls13_named_group_is_ecdhe( group ) ) + { + /* Complete ECDHE key agreement */ + ret = ssl_tls13_read_public_ecdhe_share( ssl, p, end - p ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_ECDH_C */ + if( 0 /* other KEMs? */ ) + { + /* Do something */ + } + else + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_KEY_SHARE; + return( ret ); +} + #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ /* Write cipher_suites @@ -565,11 +706,11 @@ static int ssl_tls13_write_client_hello_body( mbedtls_ssl_context *ssl, p += 2; /* Write the random bytes ( random ).*/ - MBEDTLS_SSL_CHK_BUF_PTR( p, end, CLIENT_HELLO_RANDOM_LEN ); - memcpy( p, ssl->handshake->randbytes, CLIENT_HELLO_RANDOM_LEN ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, MBEDTLS_CLIENT_HELLO_RANDOM_LEN ); + memcpy( p, ssl->handshake->randbytes, MBEDTLS_CLIENT_HELLO_RANDOM_LEN ); MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", - p, CLIENT_HELLO_RANDOM_LEN ); - p += CLIENT_HELLO_RANDOM_LEN; + p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN ); + p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN; /* * Write legacy_session_id @@ -690,7 +831,7 @@ static int ssl_tls13_prepare_client_hello( mbedtls_ssl_context *ssl ) if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->handshake->randbytes, - CLIENT_HELLO_RANDOM_LEN ) ) != 0 ) + MBEDTLS_CLIENT_HELLO_RANDOM_LEN ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); return( ret ); @@ -738,13 +879,519 @@ cleanup: } /* + * Functions for parsing and processing Server Hello + */ +/* Returns a negative value on failure, and otherwise + * - SSL_SERVER_HELLO_COORDINATE_HELLO or + * - SSL_SERVER_HELLO_COORDINATE_HRR + * to indicate which message is expected and to be parsed next. */ +#define SSL_SERVER_HELLO_COORDINATE_HELLO 0 +#define SSL_SERVER_HELLO_COORDINATE_HRR 1 +static int ssl_server_hello_is_hrr( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end ) +{ + static const unsigned char magic_hrr_string[MBEDTLS_SERVER_HELLO_RANDOM_LEN] = + { 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, + 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, + 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, + 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33 ,0x9C }; + + /* Check whether this message is a HelloRetryRequest ( HRR ) message. + * + * Server Hello and HRR are only distinguished by Random set to the + * special value of the SHA-256 of "HelloRetryRequest". + * + * struct { + * ProtocolVersion legacy_version = 0x0303; + * Random random; + * opaque legacy_session_id_echo<0..32>; + * CipherSuite cipher_suite; + * uint8 legacy_compression_method = 0; + * Extension extensions<6..2^16-1>; + * } ServerHello; + * + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( buf, end, 2 + sizeof( magic_hrr_string ) ); + + if( memcmp( buf + 2, magic_hrr_string, sizeof( magic_hrr_string ) ) == 0 ) + { + return( SSL_SERVER_HELLO_COORDINATE_HRR ); + } + + return( SSL_SERVER_HELLO_COORDINATE_HELLO ); +} + +/* Fetch and preprocess + * Returns a negative value on failure, and otherwise + * - SSL_SERVER_HELLO_COORDINATE_HELLO or + * - SSL_SERVER_HELLO_COORDINATE_HRR + */ +static int ssl_tls13_server_hello_coordinate( mbedtls_ssl_context *ssl, + unsigned char **buf, + size_t *buf_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_read_record( ssl, 0 ) ); + + if( ( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) || + ( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unexpected message" ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, + MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + *buf = ssl->in_msg + 4; + *buf_len = ssl->in_hslen - 4; + + ret = ssl_server_hello_is_hrr( ssl, *buf, *buf + *buf_len ); + switch( ret ) + { + case SSL_SERVER_HELLO_COORDINATE_HELLO: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received ServerHello message" ) ); + break; + case SSL_SERVER_HELLO_COORDINATE_HRR: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received HelloRetryRequest message" ) ); + break; + } + +cleanup: + + return( ret ); +} + +static int ssl_tls13_check_server_hello_session_id_echo( mbedtls_ssl_context *ssl, + const unsigned char **buf, + const unsigned char *end ) +{ + const unsigned char *p = *buf; + size_t legacy_session_id_echo_len; + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 1 ); + legacy_session_id_echo_len = *p++ ; + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, legacy_session_id_echo_len ); + + /* legacy_session_id_echo */ + if( ssl->session_negotiate->id_len != legacy_session_id_echo_len || + memcmp( ssl->session_negotiate->id, p , legacy_session_id_echo_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "Expected Session ID", + ssl->session_negotiate->id, + ssl->session_negotiate->id_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Received Session ID", p, + legacy_session_id_echo_len ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + p += legacy_session_id_echo_len; + *buf = p; + + MBEDTLS_SSL_DEBUG_BUF( 3, "Session ID", ssl->session_negotiate->id, + ssl->session_negotiate->id_len ); + return( 0 ); +} + +static int ssl_tls13_cipher_suite_is_offered( mbedtls_ssl_context *ssl, + int cipher_suite ) +{ + const int *ciphersuite_list = ssl->conf->ciphersuite_list; + + /* Check whether we have offered this ciphersuite */ + for ( size_t i = 0; ciphersuite_list[i] != 0; i++ ) + { + if( ciphersuite_list[i] == cipher_suite ) + { + return( 1 ); + } + } + return( 0 ); +} + +/* Parse ServerHello message and configure context + * + * struct { + * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 + * Random random; + * opaque legacy_session_id_echo<0..32>; + * CipherSuite cipher_suite; + * uint8 legacy_compression_method = 0; + * Extension extensions<6..2^16-1>; + * } ServerHello; + */ +static int ssl_tls13_parse_server_hello( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + size_t extensions_len; + const unsigned char *extensions_end; + uint16_t cipher_suite; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + /* + * Check there is space for minimal fields + * + * - legacy_version ( 2 bytes) + * - random (MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes) + * - legacy_session_id_echo ( 1 byte ), minimum size + * - cipher_suite ( 2 bytes) + * - legacy_compression_method ( 1 byte ) + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 6 ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "server hello", p, end - p ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", p, 2 ); + + /* ... + * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 + * ... + * with ProtocolVersion defined as: + * uint16 ProtocolVersion; + */ + if( !( p[0] == MBEDTLS_SSL_MAJOR_VERSION_3 && + p[1] == MBEDTLS_SSL_MINOR_VERSION_3 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Unsupported version of TLS." ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, + MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION ); + } + p += 2; + + /* ... + * Random random; + * ... + * with Random defined as: + * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN]; + */ + memcpy( &ssl->handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], p, + MBEDTLS_SERVER_HELLO_RANDOM_LEN ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", + p, MBEDTLS_SERVER_HELLO_RANDOM_LEN ); + p += MBEDTLS_SERVER_HELLO_RANDOM_LEN; + + /* ... + * opaque legacy_session_id_echo<0..32>; + * ... + */ + if( ssl_tls13_check_server_hello_session_id_echo( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + /* ... + * CipherSuite cipher_suite; + * ... + * with CipherSuite defined as: + * uint8 CipherSuite[2]; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 ); + cipher_suite = MBEDTLS_GET_UINT16_BE( p, 0 ); + p += 2; + + + /* + * Check whether this ciphersuite is supported and offered. + * Via the force_ciphersuite version we may have instructed the client + * to use a different ciphersuite. + */ + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( cipher_suite ); + if( ciphersuite_info == NULL || + ssl_tls13_cipher_suite_is_offered( ssl, cipher_suite ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite(%04x) not found or not offered", + cipher_suite ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + + /* Configure ciphersuites */ + mbedtls_ssl_optimize_checksum( ssl, ciphersuite_info ); + + ssl->handshake->ciphersuite_info = ciphersuite_info; + ssl->session_negotiate->ciphersuite = cipher_suite; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: ( %04x ) - %s", + cipher_suite, ciphersuite_info->name ) ); + +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = time( NULL ); +#endif /* MBEDTLS_HAVE_TIME */ + + /* ... + * uint8 legacy_compression_method = 0; + * ... + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 1 ); + if( p[0] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad legacy compression method" ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + p++; + + /* ... + * Extension extensions<6..2^16-1>; + * ... + * struct { + * ExtensionType extension_type; (2 bytes) + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 ); + extensions_len = MBEDTLS_GET_UINT16_BE( p, 0 ); + p += 2; + + /* Check extensions do not go beyond the buffer of data. */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, extensions_len ); + extensions_end = p + extensions_len; + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello extensions", p, extensions_len ); + + while( p < extensions_end ) + { + unsigned int extension_type; + size_t extension_data_len; + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, 4 ); + extension_type = MBEDTLS_GET_UINT16_BE( p, 0 ); + extension_data_len = MBEDTLS_GET_UINT16_BE( p, 2 ); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, extension_data_len ); + + switch( extension_type ) + { + case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found supported_versions extension" ) ); + + ret = ssl_tls13_parse_supported_versions_ext( ssl, + p, + p + extension_data_len ); + if( ret != 0 ) + return( ret ); + break; + + case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found pre_shared_key extension." ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "pre_shared_key:Not supported yet" ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, + MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + return( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + case MBEDTLS_TLS_EXT_KEY_SHARE: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found key_shares extension" ) ); + if( ( ret = ssl_tls13_parse_key_share_ext( ssl, + p, p + extension_data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, + "ssl_tls13_parse_key_share_ext", + ret ); + return( ret ); + } + break; +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + + default: + MBEDTLS_SSL_DEBUG_MSG( + 3, + ( "unknown extension found: %u ( ignoring )", + extension_type ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, + MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + return( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + } + + p += extension_data_len; + } + + return( 0 ); +} + +static int ssl_tls13_finalize_server_hello( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_key_set traffic_keys; + mbedtls_ssl_transform *transform_handshake = NULL; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Determine the key exchange mode: + * 1) If both the pre_shared_key and key_share extensions were received + * then the key exchange mode is PSK with EPHEMERAL. + * 2) If only the pre_shared_key extension was received then the key + * exchange mode is PSK-only. + * 3) If only the key_share extension was received then the key + * exchange mode is EPHEMERAL-only. + */ + switch( handshake->extensions_present & + ( MBEDTLS_SSL_EXT_PRE_SHARED_KEY | MBEDTLS_SSL_EXT_KEY_SHARE ) ) + { + /* Only the pre_shared_key extension was received */ + case MBEDTLS_SSL_EXT_PRE_SHARED_KEY: + handshake->tls1_3_kex_modes = MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK; + break; + + /* Only the key_share extension was received */ + case MBEDTLS_SSL_EXT_KEY_SHARE: + handshake->tls1_3_kex_modes = MBEDTLS_SSL_TLS13_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->tls1_3_kex_modes = MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; + break; + + /* Neither pre_shared_key nor key_share extension was received */ + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Unknown key exchange." ) ); + ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + goto cleanup; + } + + /* Start the TLS 1.3 key schedule: Set the PSK and derive early secret. + * + * TODO: We don't have to do this in case we offered 0-RTT and the + * server accepted it. In this case, we could skip generating + * the early secret. */ + ret = mbedtls_ssl_tls1_3_key_schedule_stage_early( ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_key_schedule_stage_early_data", + ret ); + goto cleanup; + } + + /* Compute handshake secret */ + ret = mbedtls_ssl_tls13_key_schedule_stage_handshake( ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_derive_master_secret", ret ); + goto cleanup; + } + + /* Next evolution in key schedule: Establish handshake secret and + * key material. */ + ret = mbedtls_ssl_tls13_generate_handshake_keys( ssl, &traffic_keys ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_generate_handshake_keys", + ret ); + goto cleanup; + } + + transform_handshake = mbedtls_calloc( 1, sizeof( mbedtls_ssl_transform ) ); + if( transform_handshake == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto cleanup; + } + + ret = mbedtls_ssl_tls13_populate_transform( transform_handshake, + ssl->conf->endpoint, + ssl->session_negotiate->ciphersuite, + &traffic_keys, + ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_populate_transform", ret ); + goto cleanup; + } + + handshake->transform_handshake = transform_handshake; + mbedtls_ssl_set_inbound_transform( ssl, transform_handshake ); + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to handshake keys for inbound traffic" ) ); + ssl->session_in = ssl->session_negotiate; + + /* + * State machine update + */ + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS ); + +cleanup: + + mbedtls_platform_zeroize( &traffic_keys, sizeof( traffic_keys ) ); + if( ret != 0 ) + { + mbedtls_free( transform_handshake ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + return( ret ); +} + +/* + * Wait and parse ServerHello handshake message. * Handler for MBEDTLS_SSL_SERVER_HELLO */ static int ssl_tls1_3_process_server_hello( mbedtls_ssl_context *ssl ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) ); - mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS ); - return( 0 ); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> %s", __func__ ) ); + + /* Coordination step + * - Fetch record + * - Make sure it's either a ServerHello or a HRR. + * - Switch processing routine in case of HRR + */ + ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + ssl->handshake->extensions_present = MBEDTLS_SSL_EXT_NONE; + + ret = ssl_tls13_server_hello_coordinate( ssl, &buf, &buf_len ); + /* Parsing step + * We know what message to expect by now and call + * the respective parsing function. + */ + if( ret == SSL_SERVER_HELLO_COORDINATE_HELLO ) + { + MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_server_hello( ssl, buf, + buf + buf_len ) ); + + mbedtls_ssl_tls1_3_add_hs_msg_to_checksum( ssl, + MBEDTLS_SSL_HS_SERVER_HELLO, + buf, buf_len ); + + MBEDTLS_SSL_PROC_CHK( ssl_tls13_finalize_server_hello( ssl ) ); + } + else if( ret == SSL_SERVER_HELLO_COORDINATE_HRR ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "HRR not supported" ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE , + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + +cleanup: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= %s", __func__ ) ); + return( ret ); } /* diff --git a/library/ssl_tls13_keys.c b/library/ssl_tls13_keys.c index b07c1c3b9..96f531079 100644 --- a/library/ssl_tls13_keys.c +++ b/library/ssl_tls13_keys.c @@ -826,17 +826,18 @@ int mbedtls_ssl_tls1_3_key_schedule_stage_early( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_type; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; - if( ssl->handshake->ciphersuite_info == NULL ) + if( handshake->ciphersuite_info == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher suite info not found" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - md_type = ssl->handshake->ciphersuite_info->mac; + md_type = handshake->ciphersuite_info->mac; ret = mbedtls_ssl_tls1_3_evolve_secret( md_type, NULL, NULL, 0, - ssl->handshake->tls1_3_master_secrets.early ); + handshake->tls1_3_master_secrets.early ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_evolve_secret", ret ); @@ -846,4 +847,185 @@ int mbedtls_ssl_tls1_3_key_schedule_stage_early( mbedtls_ssl_context *ssl ) return( 0 ); } +/* mbedtls_ssl_tls13_generate_handshake_keys() generates keys necessary for + * protecting the handshake messages, as described in Section 7 of TLS 1.3. */ +int mbedtls_ssl_tls13_generate_handshake_keys( mbedtls_ssl_context *ssl, + mbedtls_ssl_key_set *traffic_keys ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_type_t md_type; + mbedtls_md_info_t const *md_info; + size_t md_size; + + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + + mbedtls_cipher_info_t const *cipher_info; + size_t keylen, ivlen; + + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info; + mbedtls_ssl_tls1_3_handshake_secrets *tls13_hs_secrets = &handshake->tls13_hs_secrets; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_tls13_generate_handshake_keys" ) ); + + cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher ); + keylen = cipher_info->key_bitlen >> 3; + ivlen = cipher_info->iv_size; + + md_type = ciphersuite_info->mac; + md_info = mbedtls_md_info_from_type( md_type ); + md_size = mbedtls_md_get_size( md_info ); + + ret = mbedtls_ssl_get_handshake_transcript( ssl, md_type, + transcript, + sizeof( transcript ), + &transcript_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, + "mbedtls_ssl_get_handshake_transcript", + ret ); + return( ret ); + } + + ret = mbedtls_ssl_tls1_3_derive_handshake_secrets( md_type, + handshake->tls1_3_master_secrets.handshake, + transcript, transcript_len, tls13_hs_secrets ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_derive_handshake_secrets", + ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "Client handshake traffic secret", + tls13_hs_secrets->client_handshake_traffic_secret, + md_size ); + MBEDTLS_SSL_DEBUG_BUF( 4, "Server handshake traffic secret", + tls13_hs_secrets->server_handshake_traffic_secret, + md_size ); + + /* + * Export client handshake traffic secret + */ + if( ssl->f_export_keys != NULL ) + { + ssl->f_export_keys( ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS13_CLIENT_HANDSHAKE_TRAFFIC_SECRET, + tls13_hs_secrets->client_handshake_traffic_secret, + md_size, + handshake->randbytes + 32, + handshake->randbytes, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */ ); + + ssl->f_export_keys( ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS13_SERVER_HANDSHAKE_TRAFFIC_SECRET, + tls13_hs_secrets->server_handshake_traffic_secret, + md_size, + handshake->randbytes + 32, + handshake->randbytes, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */ ); + } + + ret = mbedtls_ssl_tls1_3_make_traffic_keys( md_type, + tls13_hs_secrets->client_handshake_traffic_secret, + tls13_hs_secrets->server_handshake_traffic_secret, + md_size, keylen, ivlen, traffic_keys ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_make_traffic_keys", ret ); + goto exit; + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "client_handshake write_key", + traffic_keys->client_write_key, + traffic_keys->key_len); + + MBEDTLS_SSL_DEBUG_BUF( 4, "server_handshake write_key", + traffic_keys->server_write_key, + traffic_keys->key_len); + + MBEDTLS_SSL_DEBUG_BUF( 4, "client_handshake write_iv", + traffic_keys->client_write_iv, + traffic_keys->iv_len); + + MBEDTLS_SSL_DEBUG_BUF( 4, "server_handshake write_iv", + traffic_keys->server_write_iv, + traffic_keys->iv_len); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_tls13_generate_handshake_keys" ) ); + +exit: + + return( ret ); +} + +int mbedtls_ssl_tls13_key_schedule_stage_handshake( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + mbedtls_md_type_t const md_type = handshake->ciphersuite_info->mac; + size_t ephemeral_len = 0; + unsigned char ecdhe[MBEDTLS_ECP_MAX_BYTES]; +#if defined(MBEDTLS_DEBUG_C) + mbedtls_md_info_t const * const md_info = mbedtls_md_info_from_type( md_type ); + size_t const md_size = mbedtls_md_get_size( md_info ); +#endif /* MBEDTLS_DEBUG_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) + /* + * Compute ECDHE secret used to compute the handshake secret from which + * client_handshake_traffic_secret and server_handshake_traffic_secret + * are derived in the handshake secret derivation stage. + */ + if( mbedtls_ssl_tls1_3_ephemeral_enabled( ssl ) ) + { + if( mbedtls_ssl_tls13_named_group_is_ecdhe( handshake->offered_group_id ) ) + { +#if defined(MBEDTLS_ECDH_C) + ret = mbedtls_ecdh_calc_secret( &handshake->ecdh_ctx, + &ephemeral_len, ecdhe, sizeof( ecdhe ), + ssl->conf->f_rng, + ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( ret ); + } +#endif /* MBEDTLS_ECDH_C */ + } + else if( mbedtls_ssl_tls13_named_group_is_dhe( handshake->offered_group_id ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHE not supported." ) ); + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } + } +#else + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */ + + /* + * Compute the Handshake Secret + */ + ret = mbedtls_ssl_tls1_3_evolve_secret( md_type, + handshake->tls1_3_master_secrets.early, + ecdhe, ephemeral_len, + handshake->tls1_3_master_secrets.handshake ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_evolve_secret", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "Handshake secret", + handshake->tls1_3_master_secrets.handshake, md_size ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) + mbedtls_platform_zeroize( ecdhe, sizeof( ecdhe ) ); +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */ + return( 0 ); +} + #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ diff --git a/library/ssl_tls13_keys.h b/library/ssl_tls13_keys.h index 866aae911..384f433b5 100644 --- a/library/ssl_tls13_keys.h +++ b/library/ssl_tls13_keys.h @@ -70,27 +70,6 @@ extern const struct mbedtls_ssl_tls1_3_labels_struct mbedtls_ssl_tls1_3_labels; #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN \ MBEDTLS_MD_MAX_SIZE -typedef struct -{ - unsigned char binder_key [ MBEDTLS_MD_MAX_SIZE ]; - unsigned char client_early_traffic_secret [ MBEDTLS_MD_MAX_SIZE ]; - unsigned char early_exporter_master_secret[ MBEDTLS_MD_MAX_SIZE ]; -} mbedtls_ssl_tls1_3_early_secrets; - -typedef struct -{ - unsigned char client_handshake_traffic_secret[ MBEDTLS_MD_MAX_SIZE ]; - unsigned char server_handshake_traffic_secret[ MBEDTLS_MD_MAX_SIZE ]; -} mbedtls_ssl_tls1_3_handshake_secrets; - -typedef struct -{ - unsigned char client_application_traffic_secret_N[ MBEDTLS_MD_MAX_SIZE ]; - unsigned char server_application_traffic_secret_N[ MBEDTLS_MD_MAX_SIZE ]; - unsigned char exporter_master_secret [ MBEDTLS_MD_MAX_SIZE ]; - unsigned char resumption_master_secret [ MBEDTLS_MD_MAX_SIZE ]; -} mbedtls_ssl_tls1_3_application_secrets; - /* Maximum desired length for expanded key material generated * by HKDF-Expand-Label. * @@ -553,4 +532,37 @@ int mbedtls_ssl_tls13_populate_transform( mbedtls_ssl_transform *transform, */ int mbedtls_ssl_tls1_3_key_schedule_stage_early( mbedtls_ssl_context *ssl ); +/** + * \brief Transition into handshake stage of TLS 1.3 key schedule. + * + * The TLS 1.3 key schedule can be viewed as a simple state machine + * with states Initial -> Early -> Handshake -> Application, and + * this function represents the Early -> Handshake transition. + * + * In the handshake stage, mbedtls_ssl_tls13_generate_handshake_keys() + * can be used to derive the handshake traffic keys. + * + * \param ssl The SSL context to operate on. This must be in key schedule + * stage \c Early. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_key_schedule_stage_handshake( mbedtls_ssl_context *ssl ); + +/** + * \brief Compute TLS 1.3 handshake traffic keys. + * + * \param ssl The SSL context to operate on. This must be in + * key schedule stage \c Handshake, see + * mbedtls_ssl_tls13_key_schedule_stage_handshake(). + * \param traffic_keys The address at which to store the handshake traffic key + * keys. This must be writable but may be uninitialized. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_generate_handshake_keys( mbedtls_ssl_context *ssl, + mbedtls_ssl_key_set *traffic_keys ); + #endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */ diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index d66c57a5c..8fbe67739 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -8806,9 +8806,10 @@ run_test "TLS1.3: handshake dispatch test: tls1_3 only" \ requires_openssl_tls1_3 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL +requires_config_disabled MBEDTLS_USE_PSA_CRYPTO run_test "TLS1.3: Test client hello msg work - openssl" \ "$O_NEXT_SRV -tls1_3 -msg" \ - "$P_CLI debug_level=2 min_version=tls1_3 max_version=tls1_3" \ + "$P_CLI debug_level=3 min_version=tls1_3 max_version=tls1_3" \ 1 \ -c "SSL - The requested feature is not available" \ -s "ServerHello" \ @@ -8823,13 +8824,18 @@ run_test "TLS1.3: Test client hello msg work - openssl" \ -c "tls1_3 client state: 20" \ -c "tls1_3 client state: 11" \ -c "tls1_3 client state: 14" \ - -c "tls1_3 client state: 15" + -c "tls1_3 client state: 15" \ + -c "<= ssl_tls1_3_process_server_hello" \ + -c "server hello, chosen ciphersuite: ( 1301 ) - TLS1-3-AES-128-GCM-SHA256" \ + -c "ECDH curve: x25519" \ + -c "=> ssl_tls1_3_process_server_hello" requires_gnutls_tls1_3 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL +requires_config_disabled MBEDTLS_USE_PSA_CRYPTO run_test "TLS1.3: Test client hello msg work - gnutls" \ "$G_NEXT_SRV --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 --debug=4" \ - "$P_CLI debug_level=2 min_version=tls1_3 max_version=tls1_3" \ + "$P_CLI debug_level=3 min_version=tls1_3 max_version=tls1_3" \ 1 \ -c "SSL - The requested feature is not available" \ -s "SERVER HELLO was queued" \ @@ -8844,7 +8850,12 @@ run_test "TLS1.3: Test client hello msg work - gnutls" \ -c "tls1_3 client state: 20" \ -c "tls1_3 client state: 11" \ -c "tls1_3 client state: 14" \ - -c "tls1_3 client state: 15" + -c "tls1_3 client state: 15" \ + -c "<= ssl_tls1_3_process_server_hello" \ + -c "server hello, chosen ciphersuite: ( 1301 ) - TLS1-3-AES-128-GCM-SHA256" \ + -c "ECDH curve: x25519" \ + -c "=> ssl_tls1_3_process_server_hello" + # Test heap memory usage after handshake requires_config_enabled MBEDTLS_MEMORY_DEBUG