diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index f53385995..725b156d5 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -169,6 +169,37 @@ /** Invalid value in SSL config */ #define MBEDTLS_ERR_SSL_BAD_CONFIG -0x5E80 +/* + * TLS 1.3 NamedGroup values + * + * From RF 8446 + * enum { + * // Elliptic Curve Groups (ECDHE) + * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), + * x25519(0x001D), x448(0x001E), + * // Finite Field Groups (DHE) + * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), + * ffdhe6144(0x0103), ffdhe8192(0x0104), + * // Reserved Code Points + * ffdhe_private_use(0x01FC..0x01FF), + * ecdhe_private_use(0xFE00..0xFEFF), + * (0xFFFF) + * } NamedGroup; + * + */ +/* Elliptic Curve Groups (ECDHE) */ +#define MBEDTLS_SSL_TLS13_NAMED_GROUP_SECP256R1 0x0017 +#define MBEDTLS_SSL_TLS13_NAMED_GROUP_SECP384R1 0x0018 +#define MBEDTLS_SSL_TLS13_NAMED_GROUP_SECP521R1 0x0019 +#define MBEDTLS_SSL_TLS13_NAMED_GROUP_X25519 0x001D +#define MBEDTLS_SSL_TLS13_NAMED_GROUP_X448 0x001E +/* Finite Field Groups (DHE) */ +#define MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE2048 0x0100 +#define MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE3072 0x0101 +#define MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE4096 0x0102 +#define MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE6144 0x0103 +#define MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE8192 0x0104 + /* * TLS 1.3 Key Exchange Modes * diff --git a/library/ecdh.c b/library/ecdh.c index 9dfa86806..b72bd1fe0 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -32,6 +32,8 @@ #include "mbedtls/platform_util.h" #include "mbedtls/error.h" +#include "ecdh_misc.h" + #include /* Parameter validation macros based on platform_util.h */ @@ -726,4 +728,84 @@ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, #endif } +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + +static int ecdh_tls13_make_params_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, int point_format, unsigned char *buf, size_t blen, + int ( *f_rng )( void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) + return( ret ); + + ret = mbedtls_ecp_point_write_binary( &ctx->grp, &ctx->Q, point_format, + olen, buf, blen ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_ecdh_tls13_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int ( *f_rng )( void *, unsigned char *, size_t ), + void *p_rng ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ctx-> restart_enabled ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_tls13_make_params_internal( ctx, olen, ctx->point_format, + buf, blen, f_rng, p_rng ) ); +#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_make_params_internal( &ctx->ctx.mbed_ecdh, olen, + ctx->point_format, buf, blen, + f_rng, p_rng ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +/* + * Setup context without Everest + */ +int mbedtls_ecdh_setup_no_everest( mbedtls_ecdh_context *ctx, + mbedtls_ecp_group_id grp_id ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_setup_internal( ctx, grp_id ) ); +#else + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; + ctx->grp_id = grp_id; + ecdh_init_internal( &ctx->ctx.mbed_ecdh ); + return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) ); +#endif +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + #endif /* MBEDTLS_ECDH_C */ diff --git a/library/ecdh_misc.h b/library/ecdh_misc.h new file mode 100644 index 000000000..d1342f8b9 --- /dev/null +++ b/library/ecdh_misc.h @@ -0,0 +1,51 @@ +/** + * \file ecdh_misc.h + * + * \brief Internal functions shared by the ECDH module + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 ( the "License" ); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#if !defined(MBEDTLS_ECDH_MISC_H) +#define MBEDTLS_ECDH_MISC_H + +#include "mbedtls/ecdh.h" +#include "mbedtls/ecp.h" + +#if defined(MBEDTLS_ECDH_C) + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + +/* + * Setup context without Everest + */ +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 + */ +int mbedtls_ecdh_tls13_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int ( *f_rng )( void *, unsigned char *, size_t ), + void *p_rng ); + + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + +#endif /* MBEDTLS_ECDH_C */ + +#endif /* !MBEDTLS_ECDH_MISC_H */ diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 7035c278c..c338d79ee 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -649,6 +649,16 @@ struct mbedtls_ssl_handshake_params void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); mbedtls_ssl_tls_prf_cb *tls_prf; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + uint16_t offered_group_id; /* The NamedGroup value for the group + * that is being used for ephemeral + * key exchange. + * + * On the client: Defaults to the first + * entry in the client's group list, + * but can be overwritten by the HRR. */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + mbedtls_ssl_ciphersuite_t const *ciphersuite_info; size_t pmslen; /*!< premaster length */ @@ -1348,6 +1358,49 @@ void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl ); void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight ); #endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + +/* + * Helper functions around key exchange modes. + */ +static inline unsigned mbedtls_ssl_conf_tls13_check_kex_modes( mbedtls_ssl_context *ssl, + int kex_mode_mask ) +{ + return( ( ssl->conf->tls13_kex_modes & kex_mode_mask ) != 0 ); +} + +static inline int mbedtls_ssl_conf_tls13_psk_enabled( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK ) ); +} + +static inline int mbedtls_ssl_conf_tls13_psk_ephemeral_enabled( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK_EPHEMERAL ) ); +} + +static inline int mbedtls_ssl_conf_tls13_ephemeral_enabled( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_EPHEMERAL ) ); +} + +static inline int mbedtls_ssl_conf_tls13_some_ephemeral_enabled( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_EPHEMERAL_ALL ) ); +} + +static inline int mbedtls_ssl_conf_tls13_some_psk_enabled( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK_ALL ) ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + /** * ssl utils functions for checking configuration. */ @@ -1396,6 +1449,24 @@ static inline int mbedtls_ssl_conf_is_hybrid_tls12_tls13( const mbedtls_ssl_conf #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) +/* + * Helper functions for NamedGroup. + */ +static inline int mbedtls_ssl_tls13_named_group_is_ecdhe( uint16_t named_group ) +{ + return( named_group == MBEDTLS_SSL_TLS13_NAMED_GROUP_SECP256R1 || + named_group == MBEDTLS_SSL_TLS13_NAMED_GROUP_SECP384R1 || + named_group == MBEDTLS_SSL_TLS13_NAMED_GROUP_SECP521R1 || + named_group == MBEDTLS_SSL_TLS13_NAMED_GROUP_X25519 || + named_group == MBEDTLS_SSL_TLS13_NAMED_GROUP_X448 ); +} + +static inline int mbedtls_ssl_tls13_named_group_is_dhe( uint16_t named_group ) +{ + return( named_group >= MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE2048 && + named_group <= MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE8192 ); +} + static inline void mbedtls_ssl_handshake_set_state( mbedtls_ssl_context *ssl, mbedtls_ssl_states state ) { @@ -1430,6 +1501,7 @@ int mbedtls_ssl_tls13_write_sig_alg_ext( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *olen); + #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 41c7a4d14..13e932c45 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -27,8 +27,11 @@ #include +#include "mbedtls/debug.h" +#include "mbedtls/error.h" + #include "ssl_misc.h" -#include +#include "ecdh_misc.h" #define CLIENT_HELLO_RANDOM_LEN 32 @@ -52,13 +55,11 @@ static int ssl_tls13_write_supported_versions_ext( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported versions extension" ) ); - /* - * Check space for extension header. - * - * extension_type 2 - * extension_data_length 2 - * version_length 1 - * versions 2 + /* Check if we have space to write the extension: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - versions_length (1 byte ) + * - versions (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR( p, end, 7 ); @@ -93,35 +94,366 @@ static int ssl_tls13_write_supported_versions_ext( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* + * Functions for writing supported_groups extension. + * + * Stucture of supported_groups: + * enum { + * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), + * x25519(0x001D), x448(0x001E), + * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), + * ffdhe6144(0x0103), ffdhe8192(0x0104), + * ffdhe_private_use(0x01FC..0x01FF), + * ecdhe_private_use(0xFE00..0xFEFF), + * (0xFFFF) + * } NamedGroup; + * struct { + * NamedGroup named_group_list<2..2^16-1>; + * } NamedGroupList; + */ +#if defined(MBEDTLS_ECDH_C) +/* + * In versions of TLS prior to TLS 1.3, this extension was named + * 'elliptic_curves' and only contained elliptic curve groups. + */ +static int ssl_tls13_write_named_group_list_ecdhe( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->curve_list == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for ( const mbedtls_ecp_group_id *grp_id = ssl->conf->curve_list; + *grp_id != MBEDTLS_ECP_DP_NONE; + grp_id++ ) + { + const mbedtls_ecp_curve_info *info; + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); + if( info == NULL ) + continue; + + if( !mbedtls_ssl_tls13_named_group_is_ecdhe( info->tls_id ) ) + continue; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2); + MBEDTLS_PUT_UINT16_BE( info->tls_id, p, 0 ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "NamedGroup: %s ( %x )", + mbedtls_ecp_curve_info_from_tls_id( info->tls_id )->name, + info->tls_id ) ); + } + + *olen = p - buf; + + return( 0 ); +} +#else +static int ssl_tls13_write_named_group_list_ecdhe( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *olen ) +{ + ((void) ssl); + ((void) buf); + ((void) end); + *olen = 0; + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_ECDH_C */ + +static int ssl_tls13_write_named_group_list_dhe( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *olen ) +{ + ((void) ssl); + ((void) buf); + ((void) end); + *olen = 0; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "write_named_group_dhe is not implemented" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} + static int ssl_tls13_write_supported_groups_ext( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *olen ) { - ((void) ssl); - ((void) buf); - ((void) end); - ((void) olen); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + unsigned char *p = buf ; + unsigned char *named_group_list_ptr; /* Start of named_group_list */ + size_t named_group_list_len; /* Length of named_group_list */ + size_t output_len = 0; + int ret_ecdhe, ret_dhe; + + *olen = 0; + + if( !mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_groups extension" ) ); + + /* Check if we have space for header and length fields: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - named_group_list_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); + p += 6; + + named_group_list_ptr = p; + ret_ecdhe = ssl_tls13_write_named_group_list_ecdhe( ssl, p, end, &output_len ); + if( ret_ecdhe != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_write_named_group_list_ecdhe", ret_ecdhe ); + } + p += output_len; + + ret_dhe = ssl_tls13_write_named_group_list_dhe( ssl, p, end, &output_len ); + if( ret_dhe != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_write_named_group_list_dhe", ret_dhe ); + } + p += output_len; + + /* Both ECDHE and DHE failed. */ + if( ret_ecdhe != 0 && ret_dhe != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Both ECDHE and DHE groups are fail. " ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Length of named_group_list*/ + named_group_list_len = p - named_group_list_ptr; + if( named_group_list_len == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "No group available." ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Write extension_type */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_GROUPS, buf, 0 ); + /* Write extension_data_length */ + MBEDTLS_PUT_UINT16_BE( named_group_list_len + 2, buf, 2 ); + /* Write length of named_group_list */ + MBEDTLS_PUT_UINT16_BE( named_group_list_len, buf, 4 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "Supported groups extension", buf + 4, named_group_list_len + 2 ); + + *olen = p - buf; + + ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SUPPORTED_GROUPS; + + return( 0 ); } -static int ssl_tls13_write_key_shares_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - unsigned char *end, - size_t *olen ) +/* + * Functions for writing key_share extension. + */ +#if defined(MBEDTLS_ECDH_C) +static int ssl_tls13_generate_and_write_ecdh_key_exchange( + mbedtls_ssl_context *ssl, + uint16_t named_group, + unsigned char *buf, + unsigned char *end, + size_t *olen ) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_tls_id( named_group ); + + if( curve_info == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "offer curve %s", curve_info->name ) ); + + if( ( ret = mbedtls_ecdh_setup_no_everest( &ssl->handshake->ecdh_ctx, + curve_info->grp_id ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_setup_no_everest", ret ); + return( ret ); + } + + ret = mbedtls_ecdh_tls13_make_params( &ssl->handshake->ecdh_ctx, olen, + buf, end - buf, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_tls13_make_params", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C */ + +static int ssl_tls13_get_default_group_id( mbedtls_ssl_context *ssl, + uint16_t *group_id ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + +#if defined(MBEDTLS_ECDH_C) + /* Pick first available ECDHE group compatible with TLS 1.3 */ + if( ssl->conf->curve_list == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for ( const mbedtls_ecp_group_id *grp_id = ssl->conf->curve_list; + *grp_id != MBEDTLS_ECP_DP_NONE; + grp_id++ ) + { + const mbedtls_ecp_curve_info *info; + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); + if( info != NULL && + mbedtls_ssl_tls13_named_group_is_ecdhe( info->tls_id ) ) + { + *group_id = info->tls_id; + return( 0 ); + } + } +#else ((void) ssl); - ((void) buf); - ((void) end); - ((void) olen); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + ((void) group_id); +#endif /* MBEDTLS_ECDH_C */ + + /* + * Add DHE named groups here. + * Pick first available DHE group compatible with TLS 1.3 + */ + + return( ret ); +} + +/* + * ssl_tls13_write_key_share_ext + * + * Structure of key_share extension in ClientHello: + * + * struct { + * NamedGroup group; + * opaque key_exchange<1..2^16-1>; + * } KeyShareEntry; + * struct { + * KeyShareEntry client_shares<0..2^16-1>; + * } KeyShareClientHello; + */ +static int ssl_tls13_write_key_share_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + unsigned char *client_shares_ptr; /* Start of client_shares */ + size_t client_shares_len; /* Length of client_shares */ + uint16_t group_id; + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + *olen = 0; + + if( !mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) ) + return( 0 ); + + /* Check if we have space for header and length fields: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - client_shares_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); + p += 6; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello: adding key share extension" ) ); + + /* HRR could already have requested something else. */ + group_id = ssl->handshake->offered_group_id; + if( !mbedtls_ssl_tls13_named_group_is_ecdhe( group_id ) && + !mbedtls_ssl_tls13_named_group_is_dhe( group_id ) ) + { + MBEDTLS_SSL_PROC_CHK( ssl_tls13_get_default_group_id( ssl, + &group_id ) ); + } + + /* + * Dispatch to type-specific key generation function. + * + * So far, we're only supporting ECDHE. With the introduction + * of PQC KEMs, we'll want to have multiple branches, one per + * type of KEM, and dispatch to the corresponding crypto. And + * only one key share entry is allowed. + */ + client_shares_ptr = p; +#if defined(MBEDTLS_ECDH_C) + if( mbedtls_ssl_tls13_named_group_is_ecdhe( group_id ) ) + { + /* Pointer to group */ + unsigned char *group_ptr = p; + /* Length of key_exchange */ + size_t key_exchange_len; + + /* Check there is space for header of KeyShareEntry + * - group (2 bytes) + * - key_exchange_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + p += 4; + ret = ssl_tls13_generate_and_write_ecdh_key_exchange( ssl, group_id, + p, end, + &key_exchange_len ); + p += key_exchange_len; + if( ret != 0 ) + return( ret ); + + /* Write group */ + MBEDTLS_PUT_UINT16_BE( group_id, group_ptr, 0 ); + /* Write key_exchange_length */ + MBEDTLS_PUT_UINT16_BE( key_exchange_len, group_ptr, 2 ); + } + else +#endif /* MBEDTLS_ECDH_C */ + if( 0 /* other KEMs? */ ) + { + /* Do something */ + } + else + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + /* Length of client_shares */ + client_shares_len = p - client_shares_ptr; + if( client_shares_len == 0) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "No key share defined." ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + /* Write extension_type */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0 ); + /* Write extension_data_length */ + MBEDTLS_PUT_UINT16_BE( client_shares_len + 2, buf, 2 ); + /* Write client_shares_length */ + MBEDTLS_PUT_UINT16_BE( client_shares_len, buf, 4 ); + + /* Update offered_group_id field */ + ssl->handshake->offered_group_id = group_id; + + /* Output the total length of key_share extension. */ + *olen = p - buf; + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, key_share extension", buf, *olen ); + + ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_KEY_SHARE; + +cleanup: + + return( ret ); } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ -/* - * Functions for writing ClientHello message. - */ /* Write cipher_suites * CipherSuite cipher_suites<2..2^16-2>; */ @@ -311,7 +643,7 @@ static int ssl_tls13_write_client_hello_body( mbedtls_ssl_context *ssl, * 3) Or, in case all ciphers are supported ( which includes #1 and #2 * from above ) */ - ret = ssl_tls13_write_key_shares_ext( ssl, p, end, &output_len ); + ret = ssl_tls13_write_key_share_ext( ssl, p, end, &output_len ); if( ret != 0 ) return( ret ); p += output_len; @@ -340,7 +672,7 @@ static int ssl_tls13_write_client_hello_body( mbedtls_ssl_context *ssl, return( 0 ); } -static int ssl_tls13_finalize_client_hello( mbedtls_ssl_context* ssl ) +static int ssl_tls13_finalize_client_hello( mbedtls_ssl_context *ssl ) { mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_HELLO ); return( 0 ); diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index ca4c16713..5c20f2928 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -24,6 +24,7 @@ #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) #include "mbedtls/error.h" +#include "mbedtls/debug.h" #include "ssl_misc.h" @@ -99,17 +100,70 @@ void mbedtls_ssl_tls13_add_hs_hdr_to_checksum( mbedtls_ssl_context *ssl, * * Only if we handle at least one key exchange that needs signatures. */ - int mbedtls_ssl_tls13_write_sig_alg_ext( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *olen ) { - ((void) ssl); - ((void) buf); - ((void) end); - ((void) olen); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + unsigned char *p = buf; + unsigned char *supported_sig_alg_ptr; /* Start of supported_signature_algorithms */ + size_t supported_sig_alg_len = 0; /* Length of supported_signature_algorithms */ + + *olen = 0; + + /* Skip the extension on the client if all allowed key exchanges + * are PSK-based. */ +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + !mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) ) + { + return( 0 ); + } +#endif /* MBEDTLS_SSL_CLI_C */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding signature_algorithms extension" ) ); + + /* Check if we have space for header and length field: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - supported_signature_algorithms_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); + p += 6; + + /* + * Write supported_signature_algorithms + */ + supported_sig_alg_ptr = p; + for( const uint16_t *sig_alg = ssl->conf->tls13_sig_algs; + *sig_alg != MBEDTLS_TLS13_SIG_NONE; sig_alg++ ) + { + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + MBEDTLS_PUT_UINT16_BE( *sig_alg, p, 0 ); + p += 2; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "signature scheme [%x]", *sig_alg ) ); + } + + /* Length of supported_signature_algorithms */ + supported_sig_alg_len = p - supported_sig_alg_ptr; + if( supported_sig_alg_len == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "No signature algorithms defined." ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Write extension_type */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SIG_ALG, buf, 0 ); + /* Write extension_data_length */ + MBEDTLS_PUT_UINT16_BE( supported_sig_alg_len + 2, buf, 2 ); + /* Write length of supported_signature_algorithms */ + MBEDTLS_PUT_UINT16_BE( supported_sig_alg_len, buf, 4 ); + + /* Output the total length of signature algorithms extension. */ + *olen = p - buf; + + ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SIG_ALG; + return( 0 ); } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 9944a853f..8c88b6353 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -2565,6 +2565,8 @@ component_test_tls13_experimental () { make msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL enabled, without padding" make test + msg "ssl-opt.sh (TLS 1.3 experimental)" + if_build_succeeded tests/ssl-opt.sh } component_test_tls13_experimental_with_padding () { @@ -2579,6 +2581,31 @@ component_test_tls13_experimental_with_padding () { if_build_succeeded tests/ssl-opt.sh } +component_test_tls13_experimental_with_ecp_restartable () { + msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL enabled, with ecp_restartable" + scripts/config.py set MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL + scripts/config.py set MBEDTLS_ECP_RESTARTABLE + CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . + make + msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL enabled, with ecp_restartable" + make test + msg "ssl-opt.sh (TLS 1.3 experimental)" + if_build_succeeded tests/ssl-opt.sh +} + +component_test_tls13_experimental_with_everest () { + msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL enabled, with Everest" + scripts/config.py set MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL + scripts/config.py set MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED + scripts/config.py unset MBEDTLS_ECP_RESTARTABLE + CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . + make + msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL enabled, with Everest" + make test + msg "ssl-opt.sh (TLS 1.3 experimental)" + if_build_succeeded tests/ssl-opt.sh +} + component_build_mingw () { msg "build: Windows cross build - mingw64, make (Link Library)" # ~ 30s make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 lib programs diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 3e199e288..39499d441 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1322,6 +1322,11 @@ if [ -n "${OPENSSL_LEGACY:-}" ]; then O_LEGACY_CLI="$O_LEGACY_CLI -connect localhost:+SRV_PORT" fi +if [ -n "${OPENSSL_NEXT:-}" ]; then + O_NEXT_SRV="$O_NEXT_SRV -accept $SRV_PORT" + O_NEXT_CLI="$O_NEXT_CLI -connect localhost:+SRV_PORT" +fi + if [ -n "${GNUTLS_NEXT_SERV:-}" ]; then G_NEXT_SRV="$G_NEXT_SRV -p $SRV_PORT" fi @@ -8661,6 +8666,24 @@ run_test "TLS1.3: handshake dispatch test: tls1_3 only" \ -s "SSL - The requested feature is not available" \ -c "SSL - The requested feature is not available" +requires_openssl_tls1_3 +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL +run_test "TLS1.3: Test client hello msg work - openssl" \ + "$O_NEXT_SRV -tls1_3 -msg" \ + "$P_CLI min_version=tls1_3 max_version=tls1_3" \ + 1 \ + -c "SSL - The requested feature is not available" \ + -s "ServerHello" + +requires_gnutls_tls1_3 +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL +run_test "TLS1.3: Test client hello msg work - gnutls" \ + "$G_NEXT_SRV --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 --debug=4" \ + "$P_CLI min_version=tls1_3 max_version=tls1_3" \ + 1 \ + -c "SSL - The requested feature is not available" \ + -s "SERVER HELLO was queued" + # Test heap memory usage after handshake requires_config_enabled MBEDTLS_MEMORY_DEBUG requires_config_enabled MBEDTLS_MEMORY_BUFFER_ALLOC_C