diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 6c3d7fdb49..df7f170d3a 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -99,6 +99,7 @@ set(src_tls net_sockets.c ssl_cache.c ssl_ciphersuites.c + ssl_client.c ssl_cookie.c ssl_msg.c ssl_ticket.c diff --git a/library/Makefile b/library/Makefile index d49d20cbcb..d267e05b4a 100644 --- a/library/Makefile +++ b/library/Makefile @@ -168,6 +168,7 @@ OBJS_TLS= \ net_sockets.o \ ssl_cache.o \ ssl_ciphersuites.o \ + ssl_client.o \ ssl_cookie.o \ ssl_msg.o \ ssl_ticket.o \ diff --git a/library/ssl_client.c b/library/ssl_client.c new file mode 100644 index 0000000000..a6a0abefae --- /dev/null +++ b/library/ssl_client.c @@ -0,0 +1,412 @@ +/* + * TLS 1.2 and 1.3 client-side functions + * + * 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. + * + * This file is part of mbed TLS ( https://tls.mbed.org ) + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_CLI_C) +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + +#include + +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform.h" + +#include "ssl_client.h" +#include "ssl_misc.h" +#include "ecdh_misc.h" +#include "ssl_tls13_keys.h" +#include "ssl_debug_helpers.h" + +#if defined(MBEDTLS_SSL_ALPN) +/* + * ssl_tls13_write_alpn_ext() + * + * Structure of the application_layer_protocol_negotiation extension in + * ClientHello: + * + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + * + */ +static int ssl_tls13_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *out_len ) +{ + unsigned char *p = buf; + + *out_len = 0; + + if( ssl->conf->alpn_list == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); + + + /* Check we have enough space for the extension type (2 bytes), the + * extension length (2 bytes) and the protocol_name_list length (2 bytes). + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ALPN, p, 0 ); + /* Skip writing extension and list length for now */ + p += 6; + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + for( const char **cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + { + /* + * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of + * protocol names is less than 255. + */ + size_t protocol_name_len = strlen( *cur ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 + protocol_name_len ); + *p++ = (unsigned char)protocol_name_len; + memcpy( p, *cur, protocol_name_len ); + p += protocol_name_len; + } + + *out_len = p - buf; + + /* List length = *out_len - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ + MBEDTLS_PUT_UINT16_BE( *out_len - 6, buf, 4 ); + + /* Extension length = *out_len - 2 (ext_type) - 2 (ext_len) */ + MBEDTLS_PUT_UINT16_BE( *out_len - 4, buf, 2 ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +/* Write cipher_suites + * CipherSuite cipher_suites<2..2^16-2>; + */ +static int ssl_tls13_write_client_hello_cipher_suites( + mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) +{ + unsigned char *p = buf; + const int *ciphersuite_list; + unsigned char *cipher_suites; /* Start of the cipher_suites list */ + size_t cipher_suites_len; + + *out_len = 0 ; + + /* + * Ciphersuite list + * + * This is a list of the symmetric cipher options supported by + * the client, specifically the record protection algorithm + * ( including secret key length ) and a hash to be used with + * HKDF, in descending order of client preference. + */ + ciphersuite_list = ssl->conf->ciphersuite_list; + + /* Check there is space for the cipher suite list length (2 bytes). */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + p += 2; + + /* Write cipher_suites */ + cipher_suites = p; + for ( size_t i = 0; ciphersuite_list[i] != 0; i++ ) + { + int cipher_suite = ciphersuite_list[i]; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( cipher_suite ); + if( ciphersuite_info == NULL ) + continue; + if( !( MBEDTLS_SSL_MINOR_VERSION_4 >= ciphersuite_info->min_minor_ver && + MBEDTLS_SSL_MINOR_VERSION_4 <= ciphersuite_info->max_minor_ver ) ) + continue; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x, %s", + (unsigned int) cipher_suite, + ciphersuite_info->name ) ); + + /* Check there is space for the cipher suite identifier (2 bytes). */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + MBEDTLS_PUT_UINT16_BE( cipher_suite, p, 0 ); + p += 2; + } + + /* Write the cipher_suites length in number of bytes */ + cipher_suites_len = p - cipher_suites; + MBEDTLS_PUT_UINT16_BE( cipher_suites_len, buf, 0 ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, got %" MBEDTLS_PRINTF_SIZET " cipher suites", + cipher_suites_len/2 ) ); + + /* Output the total length of cipher_suites field. */ + *out_len = p - buf; + + return( 0 ); +} + +/* + * Structure of ClientHello message: + * + * struct { + * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 + * Random random; + * opaque legacy_session_id<0..32>; + * CipherSuite cipher_suites<2..2^16-2>; + * opaque legacy_compression_methods<1..2^8-1>; + * Extension extensions<8..2^16-1>; + * } ClientHello; + */ +static int ssl_tls13_write_client_hello_body( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) +{ + + int ret; + unsigned char *p_extensions_len; /* Pointer to extensions length */ + size_t output_len; /* Length of buffer used by function */ + size_t extensions_len; /* Length of the list of extensions*/ + + /* Buffer management */ + unsigned char *p = buf; + + *out_len = 0; + + /* No validation needed here. It has been done by ssl_conf_check() */ + ssl->major_ver = ssl->conf->min_major_ver; + ssl->minor_ver = ssl->conf->min_minor_ver; + + /* + * Write legacy_version + * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 + * + * For TLS 1.3 we use the legacy version number {0x03, 0x03} + * instead of the true version number. + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + MBEDTLS_PUT_UINT16_BE( 0x0303, p, 0 ); + p += 2; + + /* Write the random bytes ( random ).*/ + 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, MBEDTLS_CLIENT_HELLO_RANDOM_LEN ); + p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN; + + /* + * Write legacy_session_id + * + * Versions of TLS before TLS 1.3 supported a "session resumption" feature + * which has been merged with pre-shared keys in this version. A client + * which has a cached session ID set by a pre-TLS 1.3 server SHOULD set + * this field to that value. In compatibility mode, this field MUST be + * non-empty, so a client not offering a pre-TLS 1.3 session MUST generate + * a new 32-byte value. This value need not be random but SHOULD be + * unpredictable to avoid implementations fixating on a specific value + * ( also known as ossification ). Otherwise, it MUST be set as a zero-length + * vector ( i.e., a zero-valued single byte length field ). + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + MBEDTLS_SSL_CHK_BUF_PTR( p, end, ssl->session_negotiate->id_len + 1 ); + *p++ = (unsigned char)ssl->session_negotiate->id_len; + memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + p += ssl->session_negotiate->id_len; + + MBEDTLS_SSL_DEBUG_BUF( 3, "session id", ssl->session_negotiate->id, + ssl->session_negotiate->id_len ); +#else + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 ); + *p++ = 0; /* session id length set to zero */ +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + + /* Write cipher_suites */ + ret = ssl_tls13_write_client_hello_cipher_suites( ssl, p, end, &output_len ); + if( ret != 0 ) + return( ret ); + p += output_len; + + /* Write legacy_compression_methods + * + * For every TLS 1.3 ClientHello, this vector MUST contain exactly + * one byte set to zero, which corresponds to the 'null' compression + * method in prior versions of TLS. + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + *p++ = 1; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + + /* Write extensions */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* Keeping track of the included extensions */ + ssl->handshake->extensions_present = MBEDTLS_SSL_EXT_NONE; +#endif + + /* First write extensions, then the total length */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + p_extensions_len = p; + p += 2; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + ret = mbedtls_ssl_tls13_write_client_hello_exts( ssl, p, end, &output_len ); + if( ret != 0 ) + return( ret ); + p += output_len; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + ret = ssl_tls13_write_alpn_ext( ssl, p, end, &output_len ); + if( ret != 0 ) + return( ret ); + p += output_len; +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + if( mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) ) + { + ret = mbedtls_ssl_write_supported_groups_ext( ssl, p, end, &output_len ); + if( ret != 0 ) + return( ret ); + p += output_len; + } + + if( mbedtls_ssl_conf_tls13_ephemeral_enabled( ssl ) ) + { + ret = mbedtls_ssl_write_sig_alg_ext( ssl, p, end, &output_len ); + if( ret != 0 ) + return( ret ); + p += output_len; + } +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /* Write server name extension */ + ret = mbedtls_ssl_write_hostname_ext( ssl, p, end, &output_len ); + if( ret != 0 ) + return( ret ); + p += output_len; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + + /* Add more extensions here */ + + /* Write the length of the list of extensions. */ + extensions_len = p - p_extensions_len - 2; + MBEDTLS_PUT_UINT16_BE( extensions_len, p_extensions_len, 0 ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %" MBEDTLS_PRINTF_SIZET , + extensions_len ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", p_extensions_len, extensions_len ); + + *out_len = p - buf; + return( 0 ); +} + +static int ssl_tls13_prepare_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided" ) ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, + ssl->handshake->randbytes, + MBEDTLS_CLIENT_HELLO_RANDOM_LEN ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + /* + * Create a session identifier for the purpose of middlebox compatibility + * only if one has not been created already. + */ + if( ssl->session_negotiate->id_len == 0 ) + { + /* Creating a session id with 32 byte length */ + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, + ssl->session_negotiate->id, 32 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "creating session id failed", ret ); + return( ret ); + } + ssl->session_negotiate->id_len = 32; + } +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + + return( 0 ); +} + +/* + * Write ClientHello handshake message. + * Handler for MBEDTLS_SSL_CLIENT_HELLO + */ +int mbedtls_ssl_write_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); + + MBEDTLS_SSL_PROC_CHK( ssl_tls13_prepare_client_hello( ssl ) ); + + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, + &buf, &buf_len ) ); + + MBEDTLS_SSL_PROC_CHK( ssl_tls13_write_client_hello_body( ssl, buf, + buf + buf_len, + &msg_len ) ); + + mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, + buf, msg_len ); + + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_finish_handshake_msg( ssl, + buf_len, + msg_len ) ); + + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_HELLO ); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); + return ret; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 || MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_CLI_C */ diff --git a/library/ssl_client.h b/library/ssl_client.h new file mode 100644 index 0000000000..8e0c21634b --- /dev/null +++ b/library/ssl_client.h @@ -0,0 +1,33 @@ +/** + * TLS 1.2 and 1.3 client-side functions + * + * 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. + */ + +#ifndef MBEDTLS_SSL_CLIENT_H +#define MBEDTLS_SSL_CLIENT_H + +#include "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) +#include "ssl_misc.h" +#endif + +#include + +int mbedtls_ssl_write_client_hello( mbedtls_ssl_context *ssl ); + +#endif /* MBEDTLS_SSL_CLIENT_H */ diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 6329e0d5e5..4731020c2a 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -1652,6 +1652,20 @@ int mbedtls_ssl_tls13_process_finished_message( mbedtls_ssl_context *ssl ); int mbedtls_ssl_tls13_write_finished_message( mbedtls_ssl_context *ssl ); void mbedtls_ssl_tls13_handshake_wrapup( mbedtls_ssl_context *ssl ); +/** + * \brief Given an SSL context and its associated configuration, write the TLS + * 1.3 specific extensions of the ClientHello message. + * + * \param[in] ssl SSL context + * \param[in] buf Base address of the buffer where to write the extensions + * \param[in] end End address of the buffer where to write the extensions + * \param[out] out_len Length of the data written into the buffer \p buf + */ +int mbedtls_ssl_tls13_write_client_hello_exts( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ); + /** * \brief TLS 1.3 client side state machine entry * diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 9f22e1dcc6..88cd22ad4b 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -31,6 +31,7 @@ #include "ssl_misc.h" #include "ecdh_misc.h" +#include "ssl_client.h" #include "ssl_tls13_keys.h" #include "ssl_debug_helpers.h" @@ -112,74 +113,6 @@ static int ssl_tls13_parse_supported_versions_ext( mbedtls_ssl_context *ssl, } #if defined(MBEDTLS_SSL_ALPN) -/* - * ssl_tls13_write_alpn_ext() - * - * Structure of the application_layer_protocol_negotiation extension in - * ClientHello: - * - * opaque ProtocolName<1..2^8-1>; - * - * struct { - * ProtocolName protocol_name_list<2..2^16-1> - * } ProtocolNameList; - * - */ -static int ssl_tls13_write_alpn_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - const unsigned char *end, - size_t *out_len ) -{ - unsigned char *p = buf; - - *out_len = 0; - - if( ssl->conf->alpn_list == NULL ) - return( 0 ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); - - - /* Check we have enough space for the extension type (2 bytes), the - * extension length (2 bytes) and the protocol_name_list length (2 bytes). - */ - MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); - MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ALPN, p, 0 ); - /* Skip writing extension and list length for now */ - p += 6; - - /* - * opaque ProtocolName<1..2^8-1>; - * - * struct { - * ProtocolName protocol_name_list<2..2^16-1> - * } ProtocolNameList; - */ - for( const char **cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) - { - /* - * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of - * protocol names is less than 255. - */ - size_t protocol_name_len = strlen( *cur ); - - MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 + protocol_name_len ); - *p++ = (unsigned char)protocol_name_len; - memcpy( p, *cur, protocol_name_len ); - p += protocol_name_len; - } - - *out_len = p - buf; - - /* List length = *out_len - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ - MBEDTLS_PUT_UINT16_BE( *out_len - 6, buf, 4 ); - - /* Extension length = *out_len - 2 (ext_type) - 2 (ext_len) */ - MBEDTLS_PUT_UINT16_BE( *out_len - 4, buf, 2 ); - - return( 0 ); -} - static int ssl_tls13_parse_alpn_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { @@ -738,77 +671,10 @@ static int ssl_tls13_write_cookie_ext( mbedtls_ssl_context *ssl, return( 0 ); } -/* Write cipher_suites - * CipherSuite cipher_suites<2..2^16-2>; - */ -static int ssl_tls13_write_client_hello_cipher_suites( - mbedtls_ssl_context *ssl, - unsigned char *buf, - unsigned char *end, - size_t *out_len ) -{ - unsigned char *p = buf; - const int *ciphersuite_list; - unsigned char *cipher_suites; /* Start of the cipher_suites list */ - size_t cipher_suites_len; - - *out_len = 0 ; - - /* - * Ciphersuite list - * - * This is a list of the symmetric cipher options supported by - * the client, specifically the record protection algorithm - * ( including secret key length ) and a hash to be used with - * HKDF, in descending order of client preference. - */ - ciphersuite_list = ssl->conf->ciphersuite_list; - - /* Check there is space for the cipher suite list length (2 bytes). */ - MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); - p += 2; - - /* Write cipher_suites */ - cipher_suites = p; - for ( size_t i = 0; ciphersuite_list[i] != 0; i++ ) - { - int cipher_suite = ciphersuite_list[i]; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - - ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( cipher_suite ); - if( ciphersuite_info == NULL ) - continue; - if( !( MBEDTLS_SSL_MINOR_VERSION_4 >= ciphersuite_info->min_minor_ver && - MBEDTLS_SSL_MINOR_VERSION_4 <= ciphersuite_info->max_minor_ver ) ) - continue; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x, %s", - (unsigned int) cipher_suite, - ciphersuite_info->name ) ); - - /* Check there is space for the cipher suite identifier (2 bytes). */ - MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); - MBEDTLS_PUT_UINT16_BE( cipher_suite, p, 0 ); - p += 2; - } - - /* Write the cipher_suites length in number of bytes */ - cipher_suites_len = p - cipher_suites; - MBEDTLS_PUT_UINT16_BE( cipher_suites_len, buf, 0 ); - MBEDTLS_SSL_DEBUG_MSG( 3, - ( "client hello, got %" MBEDTLS_PRINTF_SIZET " cipher suites", - cipher_suites_len/2 ) ); - - /* Output the total length of cipher_suites field. */ - *out_len = p - buf; - - return( 0 ); -} - -static int ssl_tls13_write_client_hello_exts( mbedtls_ssl_context *ssl, - unsigned char *buf, - unsigned char *end, - size_t *out_len ) +int mbedtls_ssl_tls13_write_client_hello_exts( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; @@ -848,241 +714,6 @@ static int ssl_tls13_write_client_hello_exts( mbedtls_ssl_context *ssl, return( 0 ); } -/* - * Structure of ClientHello message: - * - * struct { - * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 - * Random random; - * opaque legacy_session_id<0..32>; - * CipherSuite cipher_suites<2..2^16-2>; - * opaque legacy_compression_methods<1..2^8-1>; - * Extension extensions<8..2^16-1>; - * } ClientHello; - */ -static int ssl_tls13_write_client_hello_body( mbedtls_ssl_context *ssl, - unsigned char *buf, - unsigned char *end, - size_t *out_len ) -{ - - int ret; - unsigned char *p_extensions_len; /* Pointer to extensions length */ - size_t output_len; /* Length of buffer used by function */ - size_t extensions_len; /* Length of the list of extensions*/ - - /* Buffer management */ - unsigned char *p = buf; - - *out_len = 0; - - /* No validation needed here. It has been done by ssl_conf_check() */ - ssl->major_ver = ssl->conf->min_major_ver; - ssl->minor_ver = ssl->conf->min_minor_ver; - - /* - * Write legacy_version - * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 - * - * For TLS 1.3 we use the legacy version number {0x03, 0x03} - * instead of the true version number. - */ - MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); - MBEDTLS_PUT_UINT16_BE( 0x0303, p, 0 ); - p += 2; - - /* Write the random bytes ( random ).*/ - 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, MBEDTLS_CLIENT_HELLO_RANDOM_LEN ); - p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN; - - /* - * Write legacy_session_id - * - * Versions of TLS before TLS 1.3 supported a "session resumption" feature - * which has been merged with pre-shared keys in this version. A client - * which has a cached session ID set by a pre-TLS 1.3 server SHOULD set - * this field to that value. In compatibility mode, this field MUST be - * non-empty, so a client not offering a pre-TLS 1.3 session MUST generate - * a new 32-byte value. This value need not be random but SHOULD be - * unpredictable to avoid implementations fixating on a specific value - * ( also known as ossification ). Otherwise, it MUST be set as a zero-length - * vector ( i.e., a zero-valued single byte length field ). - */ -#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) - MBEDTLS_SSL_CHK_BUF_PTR( p, end, ssl->session_negotiate->id_len + 1 ); - *p++ = (unsigned char)ssl->session_negotiate->id_len; - memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); - p += ssl->session_negotiate->id_len; - - MBEDTLS_SSL_DEBUG_BUF( 3, "session id", ssl->session_negotiate->id, - ssl->session_negotiate->id_len ); -#else - MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 ); - *p++ = 0; /* session id length set to zero */ -#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ - - /* Write cipher_suites */ - ret = ssl_tls13_write_client_hello_cipher_suites( ssl, p, end, &output_len ); - if( ret != 0 ) - return( ret ); - p += output_len; - - /* Write legacy_compression_methods - * - * For every TLS 1.3 ClientHello, this vector MUST contain exactly - * one byte set to zero, which corresponds to the 'null' compression - * method in prior versions of TLS. - */ - MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); - *p++ = 1; - *p++ = MBEDTLS_SSL_COMPRESS_NULL; - - /* Write extensions */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_3) - /* Keeping track of the included extensions */ - ssl->handshake->extensions_present = MBEDTLS_SSL_EXT_NONE; -#endif - - /* First write extensions, then the total length */ - MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); - p_extensions_len = p; - p += 2; - -#if defined(MBEDTLS_SSL_PROTO_TLS1_3) - ret = ssl_tls13_write_client_hello_exts( ssl, p, end, &output_len ); - if( ret != 0 ) - return( ret ); - p += output_len; -#endif - -#if defined(MBEDTLS_SSL_ALPN) - ret = ssl_tls13_write_alpn_ext( ssl, p, end, &output_len ); - if( ret != 0 ) - return( ret ); - p += output_len; -#endif /* MBEDTLS_SSL_ALPN */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_3) -#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) - if( mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) ) - { - ret = mbedtls_ssl_write_supported_groups_ext( ssl, p, end, &output_len ); - if( ret != 0 ) - return( ret ); - p += output_len; - } - - if( mbedtls_ssl_conf_tls13_ephemeral_enabled( ssl ) ) - { - ret = mbedtls_ssl_write_sig_alg_ext( ssl, p, end, &output_len ); - if( ret != 0 ) - return( ret ); - p += output_len; - } -#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - /* Write server name extension */ - ret = mbedtls_ssl_write_hostname_ext( ssl, p, end, &output_len ); - if( ret != 0 ) - return( ret ); - p += output_len; -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - - /* Add more extensions here */ - - /* Write the length of the list of extensions. */ - extensions_len = p - p_extensions_len - 2; - MBEDTLS_PUT_UINT16_BE( extensions_len, p_extensions_len, 0 ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %" MBEDTLS_PRINTF_SIZET , - extensions_len ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", p_extensions_len, extensions_len ); - - *out_len = p - buf; - return( 0 ); -} - -static int ssl_tls13_prepare_client_hello( mbedtls_ssl_context *ssl ) -{ - int ret; - - if( ssl->conf->f_rng == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided" ) ); - return( MBEDTLS_ERR_SSL_NO_RNG ); - } - - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, - ssl->handshake->randbytes, - MBEDTLS_CLIENT_HELLO_RANDOM_LEN ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); - return( ret ); - } - -#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) - /* - * Create a session identifier for the purpose of middlebox compatibility - * only if one has not been created already. - */ - if( ssl->session_negotiate->id_len == 0 ) - { - /* Creating a session id with 32 byte length */ - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, - ssl->session_negotiate->id, 32 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "creating session id failed", ret ); - return( ret ); - } - ssl->session_negotiate->id_len = 32; - } -#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ - - return( 0 ); -} - -/* - * Write ClientHello handshake message. - * Handler for MBEDTLS_SSL_CLIENT_HELLO - */ -static int ssl_tls13_write_client_hello( mbedtls_ssl_context *ssl ) -{ - int ret = 0; - unsigned char *buf; - size_t buf_len, msg_len; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); - - MBEDTLS_SSL_PROC_CHK( ssl_tls13_prepare_client_hello( ssl ) ); - - MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_start_handshake_msg( - ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, - &buf, &buf_len ) ); - - MBEDTLS_SSL_PROC_CHK( ssl_tls13_write_client_hello_body( ssl, buf, - buf + buf_len, - &msg_len ) ); - - mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, - buf, msg_len ); - - MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_finish_handshake_msg( ssl, - buf_len, - msg_len ) ); - - mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_HELLO ); - -cleanup: - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); - return ret; -} - /* * Functions for parsing and processing Server Hello */ @@ -2246,7 +1877,7 @@ int mbedtls_ssl_tls13_handshake_client_step( mbedtls_ssl_context *ssl ) */ case MBEDTLS_SSL_HELLO_REQUEST: case MBEDTLS_SSL_CLIENT_HELLO: - ret = ssl_tls13_write_client_hello( ssl ); + ret = mbedtls_ssl_write_client_hello( ssl ); break; case MBEDTLS_SSL_SERVER_HELLO: