diff --git a/docs/architecture/tls13-experimental.md b/docs/architecture/tls13-experimental.md index bcf3e34f9..3db16e0a6 100644 --- a/docs/architecture/tls13-experimental.md +++ b/docs/architecture/tls13-experimental.md @@ -38,3 +38,12 @@ together with their level of testing: - The HKDF key derivation function on which the TLS 1.3 key schedule is based, is already present as an independent module controlled by `MBEDTLS_HKDF_C` independently of the development of the TLS 1.3 prototype. + +- The TLS 1.3-specific HKDF-based key derivation functions (see RFC 8446): + * HKDF-Expand-Label + * Derive-Secret + - Secret evolution + * The traffic {Key,IV} generation from secret + Those functions are implemented in `library/ssl_tls13_keys.c` and + tested in `test_suite_ssl` using test vectors from RFC 8448 and + https://tls13.ulfheim.net/. diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h index 014786ad5..8827e0b79 100644 --- a/include/mbedtls/cipher.h +++ b/include/mbedtls/cipher.h @@ -227,10 +227,30 @@ enum { }; /** Maximum length of any IV, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * This should be kept in sync with MBEDTLS_SSL_MAX_IV_LENGTH defined + * in ssl_internal.h. */ #define MBEDTLS_MAX_IV_LENGTH 16 + /** Maximum block size of any cipher, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined + * in ssl_internal.h. */ #define MBEDTLS_MAX_BLOCK_LENGTH 16 +/** Maximum key length, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * For now, only check whether XTS is enabled which uses 64 Byte keys, + * and use 32 Bytes as an upper bound for the maximum key length otherwise. + * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined + * in ssl_internal.h, which however deliberately ignores the case of XTS + * since the latter isn't used in SSL/TLS. */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +#define MBEDTLS_MAX_KEY_LENGTH 64 +#else +#define MBEDTLS_MAX_KEY_LENGTH 32 +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + /** * Base cipher information (opaque struct). */ diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index b3d53d34a..7b78c7310 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -378,6 +378,49 @@ typedef int mbedtls_ssl_tls_prf_cb( const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen ); + +/* cipher.h exports the maximum IV, key and block length from + * all ciphers enabled in the config, regardless of whether those + * ciphers are actually usable in SSL/TLS. Notably, XTS is enabled + * in the default configuration and uses 64 Byte keys, but it is + * not used for record protection in SSL/TLS. + * + * In order to prevent unnecessary inflation of key structures, + * we introduce SSL-specific variants of the max-{key,block,IV} + * macros here which are meant to only take those ciphers into + * account which can be negotiated in SSL/TLS. + * + * Since the current definitions of MBEDTLS_MAX_{KEY|BLOCK|IV}_LENGTH + * in cipher.h are rough overapproximations of the real maxima, here + * we content ourselves with replicating those overapproximations + * for the maximum block and IV length, and excluding XTS from the + * computation of the maximum key length. */ +#define MBEDTLS_SSL_MAX_BLOCK_LENGTH 16 +#define MBEDTLS_SSL_MAX_IV_LENGTH 16 +#define MBEDTLS_SSL_MAX_KEY_LENGTH 32 + +/** + * \brief The data structure holding the cryptographic material (key and IV) + * used for record protection in TLS 1.3. + */ +struct mbedtls_ssl_key_set +{ + /*! The key for client->server records. */ + unsigned char client_write_key[ MBEDTLS_SSL_MAX_KEY_LENGTH ]; + /*! The key for server->client records. */ + unsigned char server_write_key[ MBEDTLS_SSL_MAX_KEY_LENGTH ]; + /*! The IV for client->server records. */ + unsigned char client_write_iv[ MBEDTLS_SSL_MAX_IV_LENGTH ]; + /*! The IV for server->client records. */ + unsigned char server_write_iv[ MBEDTLS_SSL_MAX_IV_LENGTH ]; + + size_t key_len; /*!< The length of client_write_key and + * server_write_key, in Bytes. */ + size_t iv_len; /*!< The length of client_write_iv and + * server_write_iv, in Bytes. */ +}; +typedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set; + /* * This structure contains the parameters only needed during handshake. */ diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 91ac8bc7e..4444b984e 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -104,6 +104,7 @@ set(src_tls ssl_srv.c ssl_ticket.c ssl_tls.c + ssl_tls13_keys.c ) if(CMAKE_COMPILER_IS_GNUCC) diff --git a/library/Makefile b/library/Makefile index c7d4a0615..a6db9b3e6 100644 --- a/library/Makefile +++ b/library/Makefile @@ -163,6 +163,7 @@ OBJS_TLS= \ ssl_srv.o \ ssl_ticket.o \ ssl_tls.o \ + ssl_tls13_keys.o \ # This line is intentionally left blank .SILENT: diff --git a/library/ssl_tls13_keys.c b/library/ssl_tls13_keys.c new file mode 100644 index 000000000..c39e0322b --- /dev/null +++ b/library/ssl_tls13_keys.c @@ -0,0 +1,349 @@ +/* + * TLS 1.3 key schedule + * + * 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. + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + +#include "mbedtls/hkdf.h" +#include "mbedtls/ssl_internal.h" +#include "ssl_tls13_keys.h" + +#include +#include + +#define MBEDTLS_SSL_TLS1_3_LABEL( name, string ) \ + .name = string, + +struct mbedtls_ssl_tls1_3_labels_struct const mbedtls_ssl_tls1_3_labels = +{ + /* This seems to work in C, despite the string literal being one + * character too long due to the 0-termination. */ + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; + +#undef MBEDTLS_SSL_TLS1_3_LABEL + +/* + * This function creates a HkdfLabel structure used in the TLS 1.3 key schedule. + * + * The HkdfLabel is specified in RFC 8446 as follows: + * + * struct HkdfLabel { + * uint16 length; // Length of expanded key material + * opaque label<7..255>; // Always prefixed by "tls13 " + * opaque context<0..255>; // Usually a communication transcript hash + * }; + * + * Parameters: + * - desired_length: Length of expanded key material + * Even though the standard allows expansion to up to + * 2**16 Bytes, TLS 1.3 never uses expansion to more than + * 255 Bytes, so we require `desired_length` to be at most + * 255. This allows us to save a few Bytes of code by + * hardcoding the writing of the high bytes. + * - (label, llen): label + label length, without "tls13 " prefix + * The label length MUST be less than or equal to + * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN + * It is the caller's responsibility to ensure this. + * All (label, label length) pairs used in TLS 1.3 + * can be obtained via MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(). + * - (ctx, clen): context + context length + * The context length MUST be less than or equal to + * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN + * It is the caller's responsibility to ensure this. + * - dst: Target buffer for HkdfLabel structure, + * This MUST be a writable buffer of size + * at least SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN Bytes. + * - dlen: Pointer at which to store the actual length of + * the HkdfLabel structure on success. + */ + +static const char tls1_3_label_prefix[6] = "tls13 "; + +#define SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( label_len, context_len ) \ + ( 2 /* expansion length */ \ + + 1 /* label length */ \ + + label_len \ + + 1 /* context length */ \ + + context_len ) + +#define SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN \ + SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( \ + sizeof(tls1_3_label_prefix) + \ + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN, \ + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN ) + +static void ssl_tls1_3_hkdf_encode_label( + size_t desired_length, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + unsigned char *dst, size_t *dlen ) +{ + size_t total_label_len = + sizeof(tls1_3_label_prefix) + llen; + size_t total_hkdf_lbl_len = + SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( total_label_len, clen ); + + unsigned char *p = dst; + + /* Add the size of the expanded key material. + * We're hardcoding the high byte to 0 here assuming that we never use + * TLS 1.3 HKDF key expansion to more than 255 Bytes. */ +#if MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN > 255 +#error "The implementation of ssl_tls1_3_hkdf_encode_label() is not fit for the \ + value of MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN" +#endif + + *p++ = 0; + *p++ = (unsigned char)( ( desired_length >> 0 ) & 0xFF ); + + /* Add label incl. prefix */ + *p++ = (unsigned char)( total_label_len & 0xFF ); + memcpy( p, tls1_3_label_prefix, sizeof(tls1_3_label_prefix) ); + p += sizeof(tls1_3_label_prefix); + memcpy( p, label, llen ); + p += llen; + + /* Add context value */ + *p++ = (unsigned char)( clen & 0xFF ); + if( clen != 0 ) + memcpy( p, ctx, clen ); + + /* Return total length to the caller. */ + *dlen = total_hkdf_lbl_len; +} + +int mbedtls_ssl_tls1_3_hkdf_expand_label( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t slen, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + unsigned char *buf, size_t blen ) +{ + const mbedtls_md_info_t *md; + unsigned char hkdf_label[ SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN ]; + size_t hkdf_label_len; + + if( llen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN ) + { + /* Should never happen since this is an internal + * function, and we know statically which labels + * are allowed. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( clen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN ) + { + /* Should not happen, as above. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( blen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN ) + { + /* Should not happen, as above. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + md = mbedtls_md_info_from_type( hash_alg ); + if( md == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl_tls1_3_hkdf_encode_label( blen, + label, llen, + ctx, clen, + hkdf_label, + &hkdf_label_len ); + + return( mbedtls_hkdf_expand( md, + secret, slen, + hkdf_label, hkdf_label_len, + buf, blen ) ); +} + +/* + * The traffic keying material is generated from the following inputs: + * + * - One secret value per sender. + * - A purpose value indicating the specific value being generated + * - The desired lengths of key and IV. + * + * The expansion itself is based on HKDF: + * + * [sender]_write_key = HKDF-Expand-Label( Secret, "key", "", key_length ) + * [sender]_write_iv = HKDF-Expand-Label( Secret, "iv" , "", iv_length ) + * + * [sender] denotes the sending side and the Secret value is provided + * by the function caller. Note that we generate server and client side + * keys in a single function call. + */ +int mbedtls_ssl_tls1_3_make_traffic_keys( + mbedtls_md_type_t hash_alg, + const unsigned char *client_secret, + const unsigned char *server_secret, + size_t slen, size_t key_len, size_t iv_len, + mbedtls_ssl_key_set *keys ) +{ + int ret = 0; + + ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + client_secret, slen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ), + NULL, 0, + keys->client_write_key, key_len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + server_secret, slen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ), + NULL, 0, + keys->server_write_key, key_len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + client_secret, slen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ), + NULL, 0, + keys->client_write_iv, iv_len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + server_secret, slen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ), + NULL, 0, + keys->server_write_iv, iv_len ); + if( ret != 0 ) + return( ret ); + + keys->key_len = key_len; + keys->iv_len = iv_len; + + return( 0 ); +} + +int mbedtls_ssl_tls1_3_derive_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t slen, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + int ctx_hashed, + unsigned char *dstbuf, size_t buflen ) +{ + int ret; + unsigned char hashed_context[ MBEDTLS_MD_MAX_SIZE ]; + + const mbedtls_md_info_t *md; + md = mbedtls_md_info_from_type( hash_alg ); + if( md == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ctx_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED ) + { + ret = mbedtls_md( md, ctx, clen, hashed_context ); + if( ret != 0 ) + return( ret ); + clen = mbedtls_md_get_size( md ); + } + else + { + if( clen > sizeof(hashed_context) ) + { + /* This should never happen since this function is internal + * and the code sets `ctx_hashed` correctly. + * Let's double-check nonetheless to not run at the risk + * of getting a stack overflow. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( hashed_context, ctx, clen ); + } + + return( mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + secret, slen, + label, llen, + hashed_context, clen, + dstbuf, buflen ) ); +} + +int mbedtls_ssl_tls1_3_evolve_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret_old, + const unsigned char *input, size_t input_len, + unsigned char *secret_new ) +{ + int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + size_t hlen, ilen; + unsigned char tmp_secret[ MBEDTLS_MD_MAX_SIZE ] = { 0 }; + unsigned char tmp_input [ MBEDTLS_MD_MAX_SIZE ] = { 0 }; + + const mbedtls_md_info_t *md; + md = mbedtls_md_info_from_type( hash_alg ); + if( md == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md ); + + /* For non-initial runs, call Derive-Secret( ., "derived", "") + * on the old secret. */ + if( secret_old != NULL ) + { + ret = mbedtls_ssl_tls1_3_derive_secret( + hash_alg, + secret_old, hlen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( derived ), + NULL, 0, /* context */ + MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, + tmp_secret, hlen ); + if( ret != 0 ) + goto cleanup; + } + + if( input != NULL ) + { + memcpy( tmp_input, input, input_len ); + ilen = input_len; + } + else + { + ilen = hlen; + } + + /* HKDF-Extract takes a salt and input key material. + * The salt is the old secret, and the input key material + * is the input secret (PSK / ECDHE). */ + ret = mbedtls_hkdf_extract( md, + tmp_secret, hlen, + tmp_input, ilen, + secret_new ); + if( ret != 0 ) + goto cleanup; + + ret = 0; + + cleanup: + + mbedtls_platform_zeroize( tmp_secret, sizeof(tmp_secret) ); + mbedtls_platform_zeroize( tmp_input, sizeof(tmp_input) ); + return( ret ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ diff --git a/library/ssl_tls13_keys.h b/library/ssl_tls13_keys.h new file mode 100644 index 000000000..7089049ce --- /dev/null +++ b/library/ssl_tls13_keys.h @@ -0,0 +1,274 @@ +/* + * TLS 1.3 key schedule + * + * 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_SSL_TLS1_3_KEYS_H) +#define MBEDTLS_SSL_TLS1_3_KEYS_H + +/* This requires MBEDTLS_SSL_TLS1_3_LABEL( idx, name, string ) to be defined at + * the point of use. See e.g. the definition of mbedtls_ssl_tls1_3_labels_union + * below. */ +#define MBEDTLS_SSL_TLS1_3_LABEL_LIST \ + MBEDTLS_SSL_TLS1_3_LABEL( finished , "finished" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( resumption , "resumption" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( traffic_upd , "traffic upd" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( exporter , "exporter" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( key , "key" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( iv , "iv" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( c_hs_traffic, "c hs traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( c_ap_traffic, "c ap traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( c_e_traffic , "c e traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( s_hs_traffic, "s hs traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( s_ap_traffic, "s ap traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( s_e_traffic , "s e traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( e_exp_master, "e exp master" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( res_master , "res master" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( exp_master , "exp master" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( ext_binder , "ext binder" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( res_binder , "res binder" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( derived , "derived" ) + +#define MBEDTLS_SSL_TLS1_3_LABEL( name, string ) \ + const unsigned char name [ sizeof(string) - 1 ]; + +union mbedtls_ssl_tls1_3_labels_union +{ + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; +struct mbedtls_ssl_tls1_3_labels_struct +{ + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; +#undef MBEDTLS_SSL_TLS1_3_LABEL + +extern const struct mbedtls_ssl_tls1_3_labels_struct mbedtls_ssl_tls1_3_labels; + +#define MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( LABEL ) \ + mbedtls_ssl_tls1_3_labels.LABEL, \ + sizeof(mbedtls_ssl_tls1_3_labels.LABEL) + +#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN \ + sizeof( union mbedtls_ssl_tls1_3_labels_union ) + +/* The maximum length of HKDF contexts used in the TLS 1.3 standard. + * Since contexts are always hashes of message transcripts, this can + * be approximated from above by the maximum hash size. */ +#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN \ + MBEDTLS_MD_MAX_SIZE + +/* Maximum desired length for expanded key material generated + * by HKDF-Expand-Label. + * + * Warning: If this ever needs to be increased, the implementation + * ssl_tls1_3_hkdf_encode_label() in ssl_tls13_keys.c needs to be + * adjusted since it currently assumes that HKDF key expansion + * is never used with more than 255 Bytes of output. */ +#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN 255 + +/** + * \brief The \c HKDF-Expand-Label function from + * the TLS 1.3 standard RFC 8446. + * + * + * HKDF-Expand-Label( Secret, Label, Context, Length ) = + * HKDF-Expand( Secret, HkdfLabel, Length ) + * + * + * \param hash_alg The identifier for the hash algorithm to use. + * \param secret The \c Secret argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length \p slen Bytes. + * \param slen The length of \p secret in Bytes. + * \param label The \c Label argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length \p llen Bytes. + * \param llen The length of \p label in Bytes. + * \param ctx The \c Context argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length \p clen Bytes. + * \param clen The length of \p context in Bytes. + * \param buf The destination buffer to hold the expanded secret. + * This must be a writable buffer of length \p blen Bytes. + * \param blen The desired size of the expanded secret in Bytes. + * + * \returns \c 0 on success. + * \return A negative error code on failure. + */ + +int mbedtls_ssl_tls1_3_hkdf_expand_label( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t slen, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function is part of the TLS 1.3 key schedule. + * It extracts key and IV for the actual client/server traffic + * from the client/server traffic secrets. + * + * From RFC 8446: + * + * + * [sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length) + * [sender]_write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length)* + * + * + * \param hash_alg The identifier for the hash algorithm to be used + * for the HKDF-based expansion of the secret. + * \param client_secret The client traffic secret. + * This must be a readable buffer of size \p slen Bytes + * \param server_secret The server traffic secret. + * This must be a readable buffer of size \p slen Bytes + * \param slen Length of the secrets \p client_secret and + * \p server_secret in Bytes. + * \param key_len The desired length of the key to be extracted in Bytes. + * \param iv_len The desired length of the IV to be extracted in Bytes. + * \param keys The address of the structure holding the generated + * keys and IVs. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ + +int mbedtls_ssl_tls1_3_make_traffic_keys( + mbedtls_md_type_t hash_alg, + const unsigned char *client_secret, + const unsigned char *server_secret, + size_t slen, size_t key_len, size_t iv_len, + mbedtls_ssl_key_set *keys ); + + +#define MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED 0 +#define MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED 1 + +/** + * \brief The \c Derive-Secret function from the TLS 1.3 standard RFC 8446. + * + * + * Derive-Secret( Secret, Label, Messages ) = + * HKDF-Expand-Label( Secret, Label, + * Hash( Messages ), + * Hash.Length ) ) + * + * + * \param hash_alg The identifier for the hash function used for the + * applications of HKDF. + * \param secret The \c Secret argument to the \c Derive-Secret function. + * This must be a readable buffer of length \p slen Bytes. + * \param slen The length of \p secret in Bytes. + * \param label The \c Label argument to the \c Derive-Secret function. + * This must be a readable buffer of length \p llen Bytes. + * \param llen The length of \p label in Bytes. + * \param ctx The hash of the \c Messages argument to the + * \c Derive-Secret function, or the \c Messages argument + * itself, depending on \p context_already_hashed. + * \param clen The length of \p hash. + * \param ctx_hashed This indicates whether the \p ctx contains the hash of + * the \c Messages argument in the application of the + * \c Derive-Secret function + * (value MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED), or whether + * it is the content of \c Messages itself, in which case + * the function takes care of the hashing + * (value MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED). + * \param dstbuf The target buffer to write the output of + * \c Derive-Secret to. This must be a writable buffer of + * size \p buflen Bytes. + * \param buflen The length of \p dstbuf in Bytes. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls1_3_derive_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t slen, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + int ctx_hashed, + unsigned char *dstbuf, size_t buflen ); + +/** + * \brief Compute the next secret in the TLS 1.3 key schedule + * + * The TLS 1.3 key schedule proceeds as follows to compute + * the three main secrets during the handshake: The early + * secret for early data, the handshake secret for all + * other encrypted handshake messages, and the master + * secret for all application traffic. + * + * + * 0 + * | + * v + * PSK -> HKDF-Extract = Early Secret + * | + * v + * Derive-Secret( ., "derived", "" ) + * | + * v + * (EC)DHE -> HKDF-Extract = Handshake Secret + * | + * v + * Derive-Secret( ., "derived", "" ) + * | + * v + * 0 -> HKDF-Extract = Master Secret + * + * + * Each of the three secrets in turn is the basis for further + * key derivations, such as the derivation of traffic keys and IVs; + * see e.g. mbedtls_ssl_tls1_3_make_traffic_keys(). + * + * This function implements one step in this evolution of secrets: + * + * + * old_secret + * | + * v + * Derive-Secret( ., "derived", "" ) + * | + * v + * input -> HKDF-Extract = new_secret + * + * + * \param hash_alg The identifier for the hash function used for the + * applications of HKDF. + * \param secret_old The address of the buffer holding the old secret + * on function entry. If not \c NULL, this must be a + * readable buffer whose size matches the output size + * of the hash function represented by \p hash_alg. + * If \c NULL, an all \c 0 array will be used instead. + * \param input The address of the buffer holding the additional + * input for the key derivation (e.g., the PSK or the + * ephemeral (EC)DH secret). If not \c NULL, this must be + * a readable buffer whose size \p input_len Bytes. + * If \c NULL, an all \c 0 array will be used instead. + * \param input_len The length of \p input in Bytes. + * \param secret_new The address of the buffer holding the new secret + * on function exit. This must be a writable buffer + * whose size matches the output size of the hash + * function represented by \p hash_alg. + * This may be the same as \p secret_old. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ + +int mbedtls_ssl_tls1_3_evolve_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret_old, + const unsigned char *input, size_t input_len, + unsigned char *secret_new ); + +#endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */ diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 1b7919104..6e653ffc2 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -10398,6 +10398,132 @@ Decrypt CBC !EtM, 3DES SHA384 trunc, padlen=255 depends_on:MBEDTLS_DES_C:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384 ssl_decrypt_non_etm_cbc:MBEDTLS_CIPHER_DES_EDE3_CBC:MBEDTLS_MD_SHA384:1:255 +SSL TLS 1.3 Key schedule: Secret evolution #1 +# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/) +# Initial secret to Early Secret +depends_on:MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL +ssl_tls1_3_key_evolution:MBEDTLS_MD_SHA256:"":"":"33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a" + +SSL TLS 1.3 Key schedule: Secret evolution #2 +# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/) +# Early secret to Handshake Secret +ssl_tls1_3_key_evolution:MBEDTLS_MD_SHA256:"33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a":"df4a291baa1eb7cfa6934b29b474baad2697e29f1f920dcc77c8a0a088447624":"fb9fc80689b3a5d02c33243bf69a1b1b20705588a794304a6e7120155edf149a" + +SSL TLS 1.3 Key schedule: Secret evolution #3 +# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/) +# Handshake secret to Master Secret +ssl_tls1_3_key_evolution:MBEDTLS_MD_SHA256:"fb9fc80689b3a5d02c33243bf69a1b1b20705588a794304a6e7120155edf149a":"":"7f2882bb9b9a46265941653e9c2f19067118151e21d12e57a7b6aca1f8150c8d" + +SSL TLS 1.3 Key schedule: HKDF Expand Label #1 +# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/) +# Server handshake traffic secret -> Server traffic key +# HKDF-Expand-Label(server_handshake_secret, "key", "", 16) +ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"a2067265e7f0652a923d5d72ab0467c46132eeb968b6a32d311c805868548814":tls1_3_label_key:"":16:"844780a7acad9f980fa25c114e43402a" + +SSL TLS 1.3 Key schedule: HKDF Expand Label #2 +# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/) +# Server handshake traffic secret -> Server traffic IV +# HKDF-Expand-Label(server_handshake_secret, "iv", "", 12) +ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"a2067265e7f0652a923d5d72ab0467c46132eeb968b6a32d311c805868548814":tls1_3_label_iv:"":12:"4c042ddc120a38d1417fc815" + +SSL TLS 1.3 Key schedule: HKDF Expand Label #3 +# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/) +# Client handshake traffic secret -> Client traffic key +# HKDF-Expand-Label(client_handshake_secret, "key", "", 16) +ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"ff0e5b965291c608c1e8cd267eefc0afcc5e98a2786373f0db47b04786d72aea":tls1_3_label_key:"":16:"7154f314e6be7dc008df2c832baa1d39" + +SSL TLS 1.3 Key schedule: HKDF Expand Label #4 +# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/) +# Client handshake traffic secret -> Client traffic IV +# HKDF-Expand-Label(client_handshake_secret, "iv", "", 12) +ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"ff0e5b965291c608c1e8cd267eefc0afcc5e98a2786373f0db47b04786d72aea":tls1_3_label_iv:"":12:"71abc2cae4c699d47c600268" + +SSL TLS 1.3 Key schedule: HKDF Expand Label #5 (RFC 8448) +# Vector from RFC 8448 +# Server handshake traffic secret -> Server traffic IV +# HKDF-Expand-Label(server_handshake_secret, "iv", "", 12) +ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"b67b7d690cc16c4e75e54213cb2d37b4e9c912bcded9105d42befd59d391ad38":tls1_3_label_iv:"":12:"5d313eb2671276ee13000b30" + +SSL TLS 1.3 Key schedule: HKDF Expand Label #6 (RFC 8448) +# Vector from RFC 8448 +# Server handshake traffic secret -> Server traffic Key +# HKDF-Expand-Label(server_handshake_secret, "key", "", 16) +ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"b67b7d690cc16c4e75e54213cb2d37b4e9c912bcded9105d42befd59d391ad38":tls1_3_label_key:"":16:"3fce516009c21727d0f2e4e86ee403bc" + +SSL TLS 1.3 Key schedule: HKDF Expand Label #7 (RFC 8448) +# Vector from RFC 8448 +# Client handshake traffic secret -> Client traffic IV +# HKDF-Expand-Label(client_handshake_secret, "iv", "", 12) +ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"b3eddb126e067f35a780b3abf45e2d8f3b1a950738f52e9600746a0e27a55a21":tls1_3_label_iv:"":12:"5bd3c71b836e0b76bb73265f" + +SSL TLS 1.3 Key schedule: HKDF Expand Label #8 (RFC 8448) +# Vector from RFC 8448 +# Client handshake traffic secret -> Client traffic Key +# HKDF-Expand-Label(client_handshake_secret, "key", "", 16) +ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"b3eddb126e067f35a780b3abf45e2d8f3b1a950738f52e9600746a0e27a55a21":tls1_3_label_key:"":16:"dbfaa693d1762c5b666af5d950258d01" + +SSL TLS 1.3 Key schedule: HKDF Expand Label #9 (RFC 8448) +# Calculation of finished_key +ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"2faac08f851d35fea3604fcb4de82dc62c9b164a70974d0462e27f1ab278700f":tls1_3_label_finished:"":32:"5ace394c26980d581243f627d1150ae27e37fa52364e0a7f20ac686d09cd0e8e" + +SSL TLS 1.3 Key schedule: HKDF Expand Label #10 (RFC 8448) +# Calculation of resumption key +ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"7df235f2031d2a051287d02b0241b0bfdaf86cc856231f2d5aba46c434ec196c":tls1_3_label_resumption:"0000":32:"4ecd0eb6ec3b4d87f5d6028f922ca4c5851a277fd41311c9e62d2c9492e1c4f3" + +SSL TLS 1.3 Key schedule: Traffic key generation #1 +# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/) +# Client/Server handshake traffic secrets -> Client/Server traffic {Key,IV} +ssl_tls1_3_traffic_key_generation:MBEDTLS_MD_SHA256:"a2067265e7f0652a923d5d72ab0467c46132eeb968b6a32d311c805868548814":"ff0e5b965291c608c1e8cd267eefc0afcc5e98a2786373f0db47b04786d72aea":12:16:"844780a7acad9f980fa25c114e43402a":"4c042ddc120a38d1417fc815":"7154f314e6be7dc008df2c832baa1d39":"71abc2cae4c699d47c600268" + +SSL TLS 1.3 Key schedule: Traffic key generation #2 (RFC 8448) +# Vector RFC 8448 +# Client/Server handshake traffic secrets -> Client/Server traffic {Key,IV} +ssl_tls1_3_traffic_key_generation:MBEDTLS_MD_SHA256:"a2067265e7f0652a923d5d72ab0467c46132eeb968b6a32d311c805868548814":"ff0e5b965291c608c1e8cd267eefc0afcc5e98a2786373f0db47b04786d72aea":12:16:"844780a7acad9f980fa25c114e43402a":"4c042ddc120a38d1417fc815":"7154f314e6be7dc008df2c832baa1d39":"71abc2cae4c699d47c600268" + +SSL TLS 1.3 Key schedule: Derive-Secret( ., "derived", "") +# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/) +# Derive-Secret( Early-Secret, "derived", "") +# Tests the case where context isn't yet hashed (empty string here, +# but still needs to be hashed) +ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a":tls1_3_label_derived:"":32:MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED:"6f2615a108c702c5678f54fc9dbab69716c076189c48250cebeac3576c3611ba" + +SSL TLS 1.3 Key schedule: Derive-Secret( ., "s ap traffic", hash) #1 +# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/) +# Derive-Secret( MasterSecret, "s ap traffic", hash) +# Tests the case where context is already hashed +ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"7f2882bb9b9a46265941653e9c2f19067118151e21d12e57a7b6aca1f8150c8d":tls1_3_label_s_ap_traffic:"22844b930e5e0a59a09d5ac35fc032fc91163b193874a265236e568077378d8b":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"3fc35ea70693069a277956afa23b8f4543ce68ac595f2aace05cd7a1c92023d5" + +SSL TLS 1.3 Key schedule: Derive-Secret( ., "c e traffic", hash) +# Vector from RFC 8448 +ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"9b2188e9b2fc6d64d71dc329900e20bb41915000f678aa839cbb797cb7d8332c":tls1_3_label_c_e_traffic:"08ad0fa05d7c7233b1775ba2ff9f4c5b8b59276b7f227f13a976245f5d960913":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"3fbbe6a60deb66c30a32795aba0eff7eaa10105586e7be5c09678d63b6caab62" + +SSL TLS 1.3 Key schedule: Derive-Secret( ., "e exp master", hash) +# Vector from RFC 8448 +ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"9b2188e9b2fc6d64d71dc329900e20bb41915000f678aa839cbb797cb7d8332c":tls1_3_label_e_exp_master:"08ad0fa05d7c7233b1775ba2ff9f4c5b8b59276b7f227f13a976245f5d960913":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"b2026866610937d7423e5be90862ccf24c0e6091186d34f812089ff5be2ef7df" + +SSL TLS 1.3 Key schedule: Derive-Secret( ., "c hs traffic", hash) +# Vector from RFC 8448 +ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"005cb112fd8eb4ccc623bb88a07c64b3ede1605363fc7d0df8c7ce4ff0fb4ae6":tls1_3_label_c_hs_traffic:"f736cb34fe25e701551bee6fd24c1cc7102a7daf9405cb15d97aafe16f757d03"::32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"2faac08f851d35fea3604fcb4de82dc62c9b164a70974d0462e27f1ab278700f" + +SSL TLS 1.3 Key schedule: Derive-Secret( ., "s hs traffic", hash) +# Vector from RFC 8448 +ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"005cb112fd8eb4ccc623bb88a07c64b3ede1605363fc7d0df8c7ce4ff0fb4ae6":tls1_3_label_s_hs_traffic:"f736cb34fe25e701551bee6fd24c1cc7102a7daf9405cb15d97aafe16f757d03":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"fe927ae271312e8bf0275b581c54eef020450dc4ecffaa05a1a35d27518e7803" + +SSL TLS 1.3 Key schedule: Derive-Secret( ., "c ap traffic", hash) +# Vector from RFC 8448 +ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"e2d32d4ed66dd37897a0e80c84107503ce58bf8aad4cb55a5002d77ecb890ece":tls1_3_label_c_ap_traffic:"b0aeffc46a2cfe33114e6fd7d51f9f04b1ca3c497dab08934a774a9d9ad7dbf3":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"2abbf2b8e381d23dbebe1dd2a7d16a8bf484cb4950d23fb7fb7fa8547062d9a1" + +SSL TLS 1.3 Key schedule: Derive-Secret( ., "s ap traffic", hash) #2 +# Vector from RFC 8448 +ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"e2d32d4ed66dd37897a0e80c84107503ce58bf8aad4cb55a5002d77ecb890ece":tls1_3_label_s_ap_traffic:"b0aeffc46a2cfe33114e6fd7d51f9f04b1ca3c497dab08934a774a9d9ad7dbf3":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"cc21f1bf8feb7dd5fa505bd9c4b468a9984d554a993dc49e6d285598fb672691" + +SSL TLS 1.3 Key schedule: Derive-Secret( ., "exp master", hash) +# Vector from RFC 8448 +ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"e2d32d4ed66dd37897a0e80c84107503ce58bf8aad4cb55a5002d77ecb890ece":tls1_3_label_exp_master:"b0aeffc46a2cfe33114e6fd7d51f9f04b1ca3c497dab08934a774a9d9ad7dbf3":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"3fd93d4ffddc98e64b14dd107aedf8ee4add23f4510f58a4592d0b201bee56b4" + +SSL TLS 1.3 Key schedule: Derive-Secret( ., "res master", hash) +# Vector from RFC 8448 +ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"e2d32d4ed66dd37897a0e80c84107503ce58bf8aad4cb55a5002d77ecb890ece":tls1_3_label_res_master:"c3c122e0bd907a4a3ff6112d8fd53dbf89c773d9552e8b6b9d56d361b3a97bf6":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"5e95bdf1f89005ea2e9aa0ba85e728e3c19c5fe0c699e3f5bee59faebd0b5406" SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_NONE ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_NONE:"":"":"test tls_prf label":"":MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 7c4f865e9..9fcf36729 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6,11 +6,20 @@ #include #include #include +#include #include #include +enum +{ +#define MBEDTLS_SSL_TLS1_3_LABEL( name, string ) \ + tls1_3_label_ ## name, +MBEDTLS_SSL_TLS1_3_LABEL_LIST +#undef MBEDTLS_SSL_TLS1_3_LABEL +}; + typedef struct log_pattern { const char *pattern; @@ -3669,6 +3678,150 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ +void ssl_tls1_3_hkdf_expand_label( int hash_alg, + data_t *secret, + int label_idx, + data_t *ctx, + int desired_length, + data_t *expected ) +{ + unsigned char dst[ 100 ]; + + unsigned char const *lbl = NULL; + size_t lbl_len; +#define MBEDTLS_SSL_TLS1_3_LABEL( name, string ) \ + if( label_idx == (int) tls1_3_label_ ## name ) \ + { \ + lbl = mbedtls_ssl_tls1_3_labels.name; \ + lbl_len = sizeof( mbedtls_ssl_tls1_3_labels.name ); \ + } +MBEDTLS_SSL_TLS1_3_LABEL_LIST +#undef MBEDTLS_SSL_TLS1_3_LABEL + TEST_ASSERT( lbl != NULL ); + + /* Check sanity of test parameters. */ + TEST_ASSERT( (size_t) desired_length <= sizeof(dst) ); + TEST_ASSERT( (size_t) desired_length == expected->len ); + + TEST_ASSERT( mbedtls_ssl_tls1_3_hkdf_expand_label( + (mbedtls_md_type_t) hash_alg, + secret->x, secret->len, + lbl, lbl_len, + ctx->x, ctx->len, + dst, desired_length ) == 0 ); + + ASSERT_COMPARE( dst, (size_t) desired_length, + expected->x, (size_t) expected->len ); +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ +void ssl_tls1_3_traffic_key_generation( int hash_alg, + data_t *server_secret, + data_t *client_secret, + int desired_iv_len, + int desired_key_len, + data_t *expected_server_write_key, + data_t *expected_server_write_iv, + data_t *expected_client_write_key, + data_t *expected_client_write_iv ) +{ + mbedtls_ssl_key_set keys; + + /* Check sanity of test parameters. */ + TEST_ASSERT( client_secret->len == server_secret->len ); + TEST_ASSERT( expected_client_write_iv->len == expected_server_write_iv->len && + expected_client_write_iv->len == (size_t) desired_iv_len ); + TEST_ASSERT( expected_client_write_key->len == expected_server_write_key->len && + expected_client_write_key->len == (size_t) desired_key_len ); + + TEST_ASSERT( mbedtls_ssl_tls1_3_make_traffic_keys( + (mbedtls_md_type_t) hash_alg, + client_secret->x, + server_secret->x, + client_secret->len /* == server_secret->len */, + desired_key_len, desired_iv_len, + &keys ) == 0 ); + + ASSERT_COMPARE( keys.client_write_key, + keys.key_len, + expected_client_write_key->x, + (size_t) desired_key_len ); + ASSERT_COMPARE( keys.server_write_key, + keys.key_len, + expected_server_write_key->x, + (size_t) desired_key_len ); + ASSERT_COMPARE( keys.client_write_iv, + keys.iv_len, + expected_client_write_iv->x, + (size_t) desired_iv_len ); + ASSERT_COMPARE( keys.server_write_iv, + keys.iv_len, + expected_server_write_iv->x, + (size_t) desired_iv_len ); +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ +void ssl_tls1_3_derive_secret( int hash_alg, + data_t *secret, + int label_idx, + data_t *ctx, + int desired_length, + int already_hashed, + data_t *expected ) +{ + unsigned char dst[ 100 ]; + + unsigned char const *lbl = NULL; + size_t lbl_len; +#define MBEDTLS_SSL_TLS1_3_LABEL( name, string ) \ + if( label_idx == (int) tls1_3_label_ ## name ) \ + { \ + lbl = mbedtls_ssl_tls1_3_labels.name; \ + lbl_len = sizeof( mbedtls_ssl_tls1_3_labels.name ); \ + } +MBEDTLS_SSL_TLS1_3_LABEL_LIST +#undef MBEDTLS_SSL_TLS1_3_LABEL + TEST_ASSERT( lbl != NULL ); + + /* Check sanity of test parameters. */ + TEST_ASSERT( (size_t) desired_length <= sizeof(dst) ); + TEST_ASSERT( (size_t) desired_length == expected->len ); + + TEST_ASSERT( mbedtls_ssl_tls1_3_derive_secret( + (mbedtls_md_type_t) hash_alg, + secret->x, secret->len, + lbl, lbl_len, + ctx->x, ctx->len, + already_hashed, + dst, desired_length ) == 0 ); + + ASSERT_COMPARE( dst, desired_length, + expected->x, desired_length ); +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ +void ssl_tls1_3_key_evolution( int hash_alg, + data_t *secret, + data_t *input, + data_t *expected ) +{ + unsigned char secret_new[ MBEDTLS_MD_MAX_SIZE ]; + + TEST_ASSERT( mbedtls_ssl_tls1_3_evolve_secret( + (mbedtls_md_type_t) hash_alg, + secret->len ? secret->x : NULL, + input->len ? input->x : NULL, input->len, + secret_new ) == 0 ); + + ASSERT_COMPARE( secret_new, (size_t) expected->len, + expected->x, (size_t) expected->len ); +} +/* END_CASE */ + /* BEGIN_CASE */ void ssl_tls_prf( int type, data_t * secret, data_t * random, char *label, data_t *result_hex_str, int exp_ret ) diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj index db8ec3389..b243b73ae 100644 --- a/visualc/VS2010/mbedTLS.vcxproj +++ b/visualc/VS2010/mbedTLS.vcxproj @@ -252,6 +252,7 @@ + @@ -331,6 +332,7 @@ +