From 090c8842a797af0835c1a6e2ff82e28a3d45a457 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Jun 2026 14:28:22 +0200 Subject: [PATCH 01/16] include: ssl: add a typedef for unused data in mbedtls_ssl_config and mbedtls_ssl_context Add mbedtls_ssl_unused_data_t type instead of embedding the union inside both structures. Signed-off-by: Valerio Setti --- include/mbedtls/ssl.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index d272a9a894..348ee04fd1 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1728,6 +1728,17 @@ struct mbedtls_ssl_config { #endif }; +/* + * Warning: whenever a change is applied to "mbedtls_ssl_context" please re-run + * the script "tests/scripts/generate_ssl_session_reset_check.py". + * Please note that this script has some limitation that should be considered + * when modifing "mbedtls_ssl_context": + * - Parsed structure must start with struct "mbedtls_ssl_context {" + * (not "typedef struct {"). + * - It must end with "}}" in column 0. + * - Must not contain "#else" or "#elif" conditionals. + * - Must not contain nested struct/union/enum definitions. + */ struct mbedtls_ssl_context { const mbedtls_ssl_config *MBEDTLS_PRIVATE(conf); /*!< configuration information */ From b4eb39217b21fa9e1885a8919a8244875c7e0d84 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Jun 2026 14:37:41 +0200 Subject: [PATCH 02/16] tests: ssl: split ssl_helpers between public and internal functions Move functions in "ssl_helpers.h" that depend on internal headers to "ssl_helpers_internal.h". This allows to include "ssl_helpers.h" also in programs (which do not have access to internal headers). Signed-off-by: Valerio Setti --- tests/include/test/ssl_helpers.h | 93 --------------- tests/include/test/ssl_helpers_internal.h | 112 +++++++++++++++++++ tests/src/test_helpers/ssl_helpers.c | 2 + tests/suites/test_suite_ssl.function | 1 + tests/suites/test_suite_ssl_decrypt.function | 1 + 5 files changed, 116 insertions(+), 93 deletions(-) create mode 100644 tests/include/test/ssl_helpers_internal.h diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h index 56cc8c06ce..f0071f9449 100644 --- a/tests/include/test/ssl_helpers.h +++ b/tests/include/test/ssl_helpers.h @@ -16,12 +16,10 @@ #include #include -#include #include #include #if defined(MBEDTLS_SSL_TLS_C) -#include #include #include @@ -31,11 +29,6 @@ #include "mbedtls/ssl_cache.h" #endif -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ - psa_to_ssl_errors, \ - psa_generic_status_to_mbedtls) -#endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #if defined(MBEDTLS_SSL_HAVE_AES) @@ -104,13 +97,6 @@ #define MBEDTLS_TEST_HAS_ADDITIONAL_HASH #endif -enum { -#define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \ - tls13_label_ ## name, - MBEDTLS_SSL_TLS1_3_LABEL_LIST -#undef MBEDTLS_SSL_TLS1_3_LABEL -}; - #if defined(MBEDTLS_SSL_ALPN) #define MBEDTLS_TEST_MAX_ALPN_LIST_SIZE 10 #endif @@ -556,68 +542,6 @@ int mbedtls_test_move_handshake_to_state(mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ -/* - * Helper function setting up inverse record transformations - * using given cipher, hash, EtM mode, authentication tag length, - * and version. - */ -#define CHK(x) \ - do \ - { \ - if (!(x)) \ - { \ - ret = -1; \ - goto cleanup; \ - } \ - } while (0) - -#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX -#define SSL_CID_LEN_MIN MBEDTLS_SSL_CID_IN_LEN_MAX -#else -#define SSL_CID_LEN_MIN MBEDTLS_SSL_CID_OUT_LEN_MAX -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_SSL_HAVE_CBC) && defined(MBEDTLS_SSL_HAVE_AES) -int mbedtls_test_psa_cipher_encrypt_helper(mbedtls_ssl_transform *transform, - const unsigned char *iv, - size_t iv_len, - const unsigned char *input, - size_t ilen, - unsigned char *output, - size_t *olen); -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_HAVE_CBC && - MBEDTLS_SSL_HAVE_AES */ - -int mbedtls_test_ssl_build_transforms(mbedtls_ssl_transform *t_in, - mbedtls_ssl_transform *t_out, - int cipher_type, int hash_id, - int etm, int tag_mode, - mbedtls_ssl_protocol_version tls_version, - size_t cid0_len, - size_t cid1_len); - -#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) -/** - * \param[in,out] record The record to prepare. - * It must contain the data to MAC at offset - * `record->data_offset`, of length - * `record->data_length`. - * On success, write the MAC immediately - * after the data and increment - * `record->data_length` accordingly. - * \param[in,out] transform_out The out transform, typically prepared by - * mbedtls_test_ssl_build_transforms(). - * Its HMAC context may be used. Other than that - * it is treated as an input parameter. - * - * \return 0 on success, an `MBEDTLS_ERR_xxx` error code - * or -1 on error. - */ -int mbedtls_test_ssl_prepare_record_mac(mbedtls_record *record, - mbedtls_ssl_transform *transform_out); -#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ - /* * Populate a session structure for serialization tests. * Choose dummy values, mostly non-0 to distinguish from the init default. @@ -674,23 +598,6 @@ void mbedtls_test_ssl_perform_handshake( mbedtls_test_handshake_test_options *options); #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ -#if defined(MBEDTLS_TEST_HOOKS) -/* - * Tweak vector lengths in a TLS 1.3 Certificate message - * - * \param[in] buf Buffer containing the Certificate message to tweak - * \param[in]]out] end End of the buffer to parse - * \param tweak Tweak identifier (from 1 to the number of tweaks). - * \param[out] expected_result Error code expected from the parsing function - * \param[out] args Arguments of the MBEDTLS_SSL_CHK_BUF_READ_PTR call that - * is expected to fail. All zeroes if no - * MBEDTLS_SSL_CHK_BUF_READ_PTR failure is expected. - */ -int mbedtls_test_tweak_tls13_certificate_msg_vector_len( - unsigned char *buf, unsigned char **end, int tweak, - int *expected_result, mbedtls_ssl_chk_buf_ptr_args *args); -#endif /* MBEDTLS_TEST_HOOKS */ - #if defined(MBEDTLS_SSL_SESSION_TICKETS) int mbedtls_test_ticket_write( void *p_ticket, const mbedtls_ssl_session *session, diff --git a/tests/include/test/ssl_helpers_internal.h b/tests/include/test/ssl_helpers_internal.h new file mode 100644 index 0000000000..8df1d98df8 --- /dev/null +++ b/tests/include/test/ssl_helpers_internal.h @@ -0,0 +1,112 @@ +/** \file ssl_helpers.h + * + * \brief This file contains helper functions for TLS that rely on private + * headers. + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef SSL_HELPERS_INTERNAL_H +#define SSL_HELPERS_INTERNAL_H + +#if defined(MBEDTLS_SSL_TLS_C) +#include + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_ssl_errors, \ + psa_generic_status_to_mbedtls) +#endif + +enum { +#define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \ + tls13_label_ ## name, + MBEDTLS_SSL_TLS1_3_LABEL_LIST +#undef MBEDTLS_SSL_TLS1_3_LABEL +}; + +/* + * Helper function setting up inverse record transformations + * using given cipher, hash, EtM mode, authentication tag length, + * and version. + */ +#define CHK(x) \ + do \ + { \ + if (!(x)) \ + { \ + ret = -1; \ + goto cleanup; \ + } \ + } while (0) + +#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX +#define SSL_CID_LEN_MIN MBEDTLS_SSL_CID_IN_LEN_MAX +#else +#define SSL_CID_LEN_MIN MBEDTLS_SSL_CID_OUT_LEN_MAX +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_SSL_HAVE_CBC) && defined(MBEDTLS_SSL_HAVE_AES) +int mbedtls_test_psa_cipher_encrypt_helper(mbedtls_ssl_transform *transform, + const unsigned char *iv, + size_t iv_len, + const unsigned char *input, + size_t ilen, + unsigned char *output, + size_t *olen); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_HAVE_CBC && + MBEDTLS_SSL_HAVE_AES */ + +int mbedtls_test_ssl_build_transforms(mbedtls_ssl_transform *t_in, + mbedtls_ssl_transform *t_out, + int cipher_type, int hash_id, + int etm, int tag_mode, + mbedtls_ssl_protocol_version tls_version, + size_t cid0_len, + size_t cid1_len); + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) +/** + * \param[in,out] record The record to prepare. + * It must contain the data to MAC at offset + * `record->data_offset`, of length + * `record->data_length`. + * On success, write the MAC immediately + * after the data and increment + * `record->data_length` accordingly. + * \param[in,out] transform_out The out transform, typically prepared by + * mbedtls_test_ssl_build_transforms(). + * Its HMAC context may be used. Other than that + * it is treated as an input parameter. + * + * \return 0 on success, an `MBEDTLS_ERR_xxx` error code + * or -1 on error. + */ +int mbedtls_test_ssl_prepare_record_mac(mbedtls_record *record, + mbedtls_ssl_transform *transform_out); +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + +#if defined(MBEDTLS_TEST_HOOKS) +/* + * Tweak vector lengths in a TLS 1.3 Certificate message + * + * \param[in] buf Buffer containing the Certificate message to tweak + * \param[in]]out] end End of the buffer to parse + * \param tweak Tweak identifier (from 1 to the number of tweaks). + * \param[out] expected_result Error code expected from the parsing function + * \param[out] args Arguments of the MBEDTLS_SSL_CHK_BUF_READ_PTR call that + * is expected to fail. All zeroes if no + * MBEDTLS_SSL_CHK_BUF_READ_PTR failure is expected. + */ +int mbedtls_test_tweak_tls13_certificate_msg_vector_len( + unsigned char *buf, unsigned char **end, int tweak, + int *expected_result, mbedtls_ssl_chk_buf_ptr_args *args); +#endif /* MBEDTLS_TEST_HOOKS */ + +#endif /* MBEDTLS_SSL_TLS_C */ + +#endif /* SSL_HELPERS_INTERNAL_H */ diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c index fb798ac73e..3cf0fc3cfa 100644 --- a/tests/src/test_helpers/ssl_helpers.c +++ b/tests/src/test_helpers/ssl_helpers.c @@ -9,6 +9,8 @@ */ #include +#include +#include #include "mbedtls/psa_util.h" #if defined(MBEDTLS_SSL_TLS_C) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 6cba78e2fa..1042a69ab3 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff --git a/tests/suites/test_suite_ssl_decrypt.function b/tests/suites/test_suite_ssl_decrypt.function index 2d75a29bc5..c7e86ed49e 100644 --- a/tests/suites/test_suite_ssl_decrypt.function +++ b/tests/suites/test_suite_ssl_decrypt.function @@ -5,6 +5,7 @@ #include #include #include +#include /* END_HEADER */ From 066f0f98a8062b9427074536d0243da999b37570 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Jun 2026 14:39:15 +0200 Subject: [PATCH 03/16] tests: scripts: add generate_ssl_session_reset_check.py Togethere with the framework counterpart ('ssl_session_reset_check.py') this script is used to automatically generate the function 'mbedtls_test_ssl_check_context_after_session_reset()'. The goal of this function is to verify that 'mbedtls_ssl_session_reset()' properly handled (reset or keep) all the fields of the 'mbedtls_ssl_context' structure. Signed-off-by: Valerio Setti --- .../generate_ssl_session_reset_check.py | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100755 tests/scripts/generate_ssl_session_reset_check.py diff --git a/tests/scripts/generate_ssl_session_reset_check.py b/tests/scripts/generate_ssl_session_reset_check.py new file mode 100755 index 0000000000..fa67134ca4 --- /dev/null +++ b/tests/scripts/generate_ssl_session_reset_check.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +"""Generate test code to validate mbedtls_ssl_session_reset(). +""" + +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + +import scripts_path # pylint: disable=unused-import +from mbedtls_framework import ssl_session_reset_check + +RULES = { + # Fields that are reset + 'state': ssl_session_reset_check.ResetBehavior.RESET, + 'renego_status': ssl_session_reset_check.ResetBehavior.RESET, + 'renego_records_seen': ssl_session_reset_check.ResetBehavior.RESET, + 'early_data_state': ssl_session_reset_check.ResetBehavior.RESET, + 'badmac_seen': ssl_session_reset_check.ResetBehavior.RESET, + 'session_in': ssl_session_reset_check.ResetBehavior.RESET, + 'session_out': ssl_session_reset_check.ResetBehavior.RESET, + 'session': ssl_session_reset_check.ResetBehavior.RESET, + 'transform_in': ssl_session_reset_check.ResetBehavior.RESET, + 'transform_out': ssl_session_reset_check.ResetBehavior.RESET, + 'transform': ssl_session_reset_check.ResetBehavior.RESET, + 'transform_application': ssl_session_reset_check.ResetBehavior.RESET, + 'in_offt': ssl_session_reset_check.ResetBehavior.RESET, + 'in_msgtype': ssl_session_reset_check.ResetBehavior.RESET, + 'in_msglen': ssl_session_reset_check.ResetBehavior.RESET, + 'in_left': ssl_session_reset_check.ResetBehavior.RESET, + 'in_epoch': ssl_session_reset_check.ResetBehavior.RESET, + 'next_record_offset': ssl_session_reset_check.ResetBehavior.RESET, + 'in_window_top': ssl_session_reset_check.ResetBehavior.RESET, + 'in_window': ssl_session_reset_check.ResetBehavior.RESET, + 'in_hslen': ssl_session_reset_check.ResetBehavior.RESET, + 'in_hsfraglen': ssl_session_reset_check.ResetBehavior.RESET, + 'nb_zero': ssl_session_reset_check.ResetBehavior.RESET, + 'keep_current_message': ssl_session_reset_check.ResetBehavior.RESET, + 'in_fatal_alert_recv': ssl_session_reset_check.ResetBehavior.RESET, + 'in_fatal_alert_type': ssl_session_reset_check.ResetBehavior.RESET, + 'send_alert': ssl_session_reset_check.ResetBehavior.RESET, + 'alert_type': ssl_session_reset_check.ResetBehavior.RESET, + 'alert_reason': ssl_session_reset_check.ResetBehavior.RESET, + 'discard_early_data_record': ssl_session_reset_check.ResetBehavior.RESET, + 'total_early_data_size': ssl_session_reset_check.ResetBehavior.RESET, + 'out_msgtype': ssl_session_reset_check.ResetBehavior.RESET, + 'out_msglen': ssl_session_reset_check.ResetBehavior.RESET, + 'out_left': ssl_session_reset_check.ResetBehavior.RESET, + 'cur_out_ctr': ssl_session_reset_check.ResetBehavior.RESET, + 'alpn_chosen': ssl_session_reset_check.ResetBehavior.RESET, + 'dtls_srtp_info': ssl_session_reset_check.ResetBehavior.RESET, + 'cli_id': ssl_session_reset_check.ResetBehavior.RESET, + 'cli_id_len': ssl_session_reset_check.ResetBehavior.RESET, + 'secure_renegotiation': ssl_session_reset_check.ResetBehavior.RESET, + 'verify_data_len': ssl_session_reset_check.ResetBehavior.RESET, + 'own_verify_data': ssl_session_reset_check.ResetBehavior.RESET, + 'peer_verify_data': ssl_session_reset_check.ResetBehavior.RESET, + + # Fields that are preserved during reset + 'conf': ssl_session_reset_check.ResetBehavior.KEEP, + 'f_vrfy': ssl_session_reset_check.ResetBehavior.KEEP, + 'p_vrfy': ssl_session_reset_check.ResetBehavior.KEEP, + 'f_send': ssl_session_reset_check.ResetBehavior.KEEP, + 'f_recv': ssl_session_reset_check.ResetBehavior.KEEP, + 'f_recv_timeout': ssl_session_reset_check.ResetBehavior.KEEP, + 'p_bio': ssl_session_reset_check.ResetBehavior.KEEP, + 'p_timer': ssl_session_reset_check.ResetBehavior.KEEP, + 'f_set_timer': ssl_session_reset_check.ResetBehavior.KEEP, + 'f_get_timer': ssl_session_reset_check.ResetBehavior.KEEP, + 'disable_datagram_packing': ssl_session_reset_check.ResetBehavior.KEEP, + 'mtu': ssl_session_reset_check.ResetBehavior.KEEP, + 'hostname': ssl_session_reset_check.ResetBehavior.KEEP, + 'own_cid': ssl_session_reset_check.ResetBehavior.KEEP, + 'own_cid_len': ssl_session_reset_check.ResetBehavior.KEEP, + 'negotiate_cid': ssl_session_reset_check.ResetBehavior.KEEP, + 'f_export_keys': ssl_session_reset_check.ResetBehavior.KEEP, + 'p_export_keys': ssl_session_reset_check.ResetBehavior.KEEP, + + # Fields which are intentionally not checked. + 'unused': ssl_session_reset_check.ResetBehavior.IGNORE, + + # Pointers which might be reallocated during reset + 'in_buf': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'in_ctr': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'in_hdr': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'in_cid': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'in_len': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'in_iv': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'in_msg': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'out_buf': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'out_ctr': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'out_hdr': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'out_cid': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'out_len': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'out_iv': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'out_msg': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'session_negotiate': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'handshake': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'transform_negotiate': ssl_session_reset_check.ResetBehavior.REALLOCATE, + + # Fields with custom check rules. Rules must be defined in the + # SPECIAL_BEHAVIORS dictionary below. + 'flags': ssl_session_reset_check.ResetBehavior.SPECIAL, + 'tls_version': ssl_session_reset_check.ResetBehavior.SPECIAL, + 'user_data': ssl_session_reset_check.ResetBehavior.SPECIAL, + 'in_buf_len': ssl_session_reset_check.ResetBehavior.SPECIAL, + 'out_buf_len': ssl_session_reset_check.ResetBehavior.SPECIAL, +} + +SPECIAL_BEHAVIORS = { + 'flags': ['TEST_EQUAL((after->flags & ~(MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)), ' + 'initial.flags)', + 'TEST_EQUAL((before->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION), ' + + '(after->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION));'], + 'tls_version': ['TEST_ASSERT(after->tls_version == after->conf->max_tls_version);'], + 'user_data': ['TEST_ASSERT(before->user_data.n == after->user_data.n);'], + 'in_buf_len': ['TEST_ASSERT(after->in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);'], + 'out_buf_len': ['TEST_ASSERT(after->out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);'], +} + +NAMED_STRUCTURES = [ + 'dtls_srtp_info', +] + +FIELDS_INFO = ssl_session_reset_check.FieldsInfo(RULES, + SPECIAL_BEHAVIORS, + NAMED_STRUCTURES) + +if __name__ == '__main__': + ssl_session_reset_check.main(FIELDS_INFO) From 056883674423c24ed7913f6e55ecb9d19c04e1fe Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Jun 2026 14:49:38 +0200 Subject: [PATCH 04/16] tests: add prototype and implementation of mbedtls_test_ssl_check_context_after_session_reset Ideally the implementation shouldn't be checked in git, but for the time being there is no support in building source code for tests from the binary folder, so it's accepted as a temporary solution. Signed-off-by: Valerio Setti --- tests/include/test/ssl_helpers.h | 17 +++ tests/src/ssl_context_reset_verifier.c | 190 +++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 tests/src/ssl_context_reset_verifier.c diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h index f0071f9449..7b06298d1b 100644 --- a/tests/include/test/ssl_helpers.h +++ b/tests/include/test/ssl_helpers.h @@ -651,6 +651,23 @@ int mbedtls_test_get_tls13_ticket( &psa_type, &psa_bits), \ PSA_ERROR_NOT_SUPPORTED); +/** + * Verify that mbedtls_ssl_session_reset() properly managed fields of the + * mbedtls_ssl_context structure. The expected action on reset depends on the + * specific field. + * + * Note: the code is automatically generated from the python script + * "tests/scripts/generate_ssl_session_reset_check.py". + * + * \param[in] before The SSL context before mbedtls_ssl_session_reset() + * is called on it. This is used for fields that + * should be kept untouched during the reset. + * \param[in] after The SSL context after mbedtls_ssl_session_reset() + * is called on it. + */ +int mbedtls_test_ssl_check_context_after_session_reset(const mbedtls_ssl_context *before, + const mbedtls_ssl_context *after); + #endif /* MBEDTLS_SSL_TLS_C */ #endif /* SSL_HELPERS_H */ diff --git a/tests/src/ssl_context_reset_verifier.c b/tests/src/ssl_context_reset_verifier.c new file mode 100644 index 0000000000..2f106e9067 --- /dev/null +++ b/tests/src/ssl_context_reset_verifier.c @@ -0,0 +1,190 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +/* + * The following function was automatically generated through the script + * ./tests/scripts/generate_ssl_session_reset_check.py. + */ + +#include +#include +#include "mbedtls/psa_util.h" +#include + +#include + +#if defined(MBEDTLS_SSL_TLS_C) + +int mbedtls_test_ssl_check_context_after_session_reset(const mbedtls_ssl_context *before, + const mbedtls_ssl_context *after) +{ + mbedtls_ssl_context initial; + int ret = -1; + + /* Create a freshly initialized SSL context*/ + memset(&initial, 0, sizeof(initial)); + mbedtls_ssl_init(&initial); + TEST_EQUAL(mbedtls_ssl_setup(&initial, after->conf), 0); + + /* *INDENT-OFF* */ + TEST_ASSERT(before->conf == after->conf); + TEST_ASSERT(after->state == initial.state); + TEST_EQUAL((after->flags & ~(MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)), initial.flags) + TEST_EQUAL((before->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION), (after->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + TEST_ASSERT(after->renego_status == initial.renego_status); +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + TEST_ASSERT(after->renego_records_seen == initial.renego_records_seen); +#endif + TEST_ASSERT(after->tls_version == after->conf->max_tls_version); +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) + TEST_ASSERT(after->early_data_state == initial.early_data_state); +#endif + TEST_ASSERT(after->badmac_seen == initial.badmac_seen); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + TEST_ASSERT(before->f_vrfy == after->f_vrfy); +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) + TEST_ASSERT(before->p_vrfy == after->p_vrfy); +#endif + TEST_ASSERT(before->f_send == after->f_send); + TEST_ASSERT(before->f_recv == after->f_recv); + TEST_ASSERT(before->f_recv_timeout == after->f_recv_timeout); + TEST_ASSERT(before->p_bio == after->p_bio); + TEST_ASSERT(after->session_in == initial.session_in); + TEST_ASSERT(after->session_out == initial.session_out); + TEST_ASSERT(after->session == initial.session); + TEST_ASSERT(after->session_negotiate != NULL); + TEST_ASSERT(after->handshake != NULL); + TEST_ASSERT(after->transform_in == initial.transform_in); + TEST_ASSERT(after->transform_out == initial.transform_out); + TEST_ASSERT(after->transform == initial.transform); +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + TEST_ASSERT(after->transform_negotiate != NULL); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + TEST_ASSERT(after->transform_application == initial.transform_application); +#endif + TEST_ASSERT(before->p_timer == after->p_timer); + TEST_ASSERT(before->f_set_timer == after->f_set_timer); + TEST_ASSERT(before->f_get_timer == after->f_get_timer); + TEST_ASSERT(after->in_buf != NULL); + TEST_ASSERT(after->in_ctr != NULL); + TEST_ASSERT(after->in_hdr != NULL); +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + TEST_ASSERT(after->in_cid != NULL); +#endif + TEST_ASSERT(after->in_len != NULL); + TEST_ASSERT(after->in_iv != NULL); + TEST_ASSERT(after->in_msg != NULL); + TEST_ASSERT(after->in_offt == initial.in_offt); + TEST_ASSERT(after->in_msgtype == initial.in_msgtype); + TEST_ASSERT(after->in_msglen == initial.in_msglen); + TEST_ASSERT(after->in_left == initial.in_left); +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + TEST_ASSERT(after->in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN); +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) + TEST_ASSERT(after->in_epoch == initial.in_epoch); +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) + TEST_ASSERT(after->next_record_offset == initial.next_record_offset); +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + TEST_ASSERT(after->in_window_top == initial.in_window_top); +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + TEST_ASSERT(after->in_window == initial.in_window); +#endif + TEST_ASSERT(after->in_hslen == initial.in_hslen); + TEST_ASSERT(after->in_hsfraglen == initial.in_hsfraglen); + TEST_ASSERT(after->nb_zero == initial.nb_zero); + TEST_ASSERT(after->keep_current_message == initial.keep_current_message); + TEST_ASSERT(after->in_fatal_alert_recv == initial.in_fatal_alert_recv); + TEST_ASSERT(after->in_fatal_alert_type == initial.in_fatal_alert_type); + TEST_ASSERT(after->send_alert == initial.send_alert); + TEST_ASSERT(after->alert_type == initial.alert_type); + TEST_ASSERT(after->alert_reason == initial.alert_reason); +#if defined(MBEDTLS_SSL_PROTO_DTLS) + TEST_EQUAL(before->disable_datagram_packing, after->disable_datagram_packing); +#endif +#if defined(MBEDTLS_SSL_EARLY_DATA) + +#if defined(MBEDTLS_SSL_SRV_C) + TEST_ASSERT(after->discard_early_data_record == initial.discard_early_data_record); +#endif +#endif +#if defined(MBEDTLS_SSL_EARLY_DATA) + TEST_ASSERT(after->total_early_data_size == initial.total_early_data_size); +#endif + TEST_ASSERT(after->out_buf != NULL); + TEST_ASSERT(after->out_ctr != NULL); + TEST_ASSERT(after->out_hdr != NULL); +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + TEST_ASSERT(after->out_cid != NULL); +#endif + TEST_ASSERT(after->out_len != NULL); + TEST_ASSERT(after->out_iv != NULL); + TEST_ASSERT(after->out_msg != NULL); + TEST_ASSERT(after->out_msgtype == initial.out_msgtype); + TEST_ASSERT(after->out_msglen == initial.out_msglen); + TEST_ASSERT(after->out_left == initial.out_left); +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + TEST_ASSERT(after->out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN); +#endif + TEST_MEMORY_COMPARE(after->cur_out_ctr, sizeof(after->cur_out_ctr), initial.cur_out_ctr, sizeof(initial.cur_out_ctr)); +#if defined(MBEDTLS_SSL_PROTO_DTLS) + TEST_EQUAL(before->mtu, after->mtu); +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) + TEST_ASSERT(before->hostname == after->hostname); +#endif +#if defined(MBEDTLS_SSL_ALPN) + TEST_ASSERT(after->alpn_chosen == initial.alpn_chosen); +#endif +#if defined(MBEDTLS_SSL_DTLS_SRTP) + TEST_MEMORY_COMPARE(&(after->dtls_srtp_info), sizeof(after->dtls_srtp_info), &(initial.dtls_srtp_info), sizeof(initial.dtls_srtp_info)); +#endif +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + TEST_ASSERT(after->cli_id == initial.cli_id); +#endif +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + TEST_ASSERT(after->cli_id_len == initial.cli_id_len); +#endif + TEST_ASSERT(after->secure_renegotiation == initial.secure_renegotiation); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + TEST_ASSERT(after->verify_data_len == initial.verify_data_len); +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + TEST_MEMORY_COMPARE(after->own_verify_data, sizeof(after->own_verify_data), initial.own_verify_data, sizeof(initial.own_verify_data)); +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + TEST_MEMORY_COMPARE(after->peer_verify_data, sizeof(after->peer_verify_data), initial.peer_verify_data, sizeof(initial.peer_verify_data)); +#endif +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + TEST_MEMORY_COMPARE(before->own_cid, sizeof(before->own_cid), after->own_cid, sizeof(after->own_cid)); +#endif +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + TEST_EQUAL(before->own_cid_len, after->own_cid_len); +#endif +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + TEST_EQUAL(before->negotiate_cid, after->negotiate_cid); +#endif + TEST_ASSERT(before->f_export_keys == after->f_export_keys); + TEST_ASSERT(before->p_export_keys == after->p_export_keys); + TEST_ASSERT(before->user_data.n == after->user_data.n); + /* unused is ignored */ + /* *INDENT-ON* */ + + ret = 0; + +exit: + mbedtls_ssl_free(&initial); + + return ret; +} + +#endif /* MBEDTLS_SSL_TLS_C */ From c2568cb96b5dc9bd2e526c90d05b9ce652e90702 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Jun 2026 14:51:24 +0200 Subject: [PATCH 05/16] tests|programs: call check_context_after_session_reset whenever mbedtls_ssl_session_reset Call mbedtls_test_ssl_check_context_after_session_reset both in programs (ssl_client2 and ssl_server2) and tests to ensure that the SSL context has been properly handled when mbedtls_ssl_session_reset was called. Signed-off-by: Valerio Setti --- programs/ssl/ssl_client2.c | 11 +++++++++++ programs/ssl/ssl_server2.c | 10 ++++++++++ tests/src/test_helpers/ssl_helpers.c | 10 ++++++++++ 3 files changed, 31 insertions(+) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index f8747d89fd..24b7c0c441 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -27,6 +27,8 @@ int main(void) } #else /* !MBEDTLS_SSL_TEST_IMPOSSIBLE && MBEDTLS_SSL_CLI_C */ +#include "test/ssl_helpers.h" + /* Size of memory to be allocated for the heap, when using the library's memory * management and MBEDTLS_MEMORY_BUFFER_ALLOC_C is enabled. */ #define MEMORY_HEAP_SIZE 120000 @@ -2894,12 +2896,21 @@ send_request: memset(peer_crt_info, 0, sizeof(peer_crt_info)); #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + /* Dump the SSL context before resetting it. This will be used below + * to check if the reset function worked properly. */ + mbedtls_ssl_context ssl_before = ssl; if ((ret = mbedtls_ssl_session_reset(&ssl)) != 0) { mbedtls_printf(" failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n", (unsigned int) -ret); goto exit; } + if (mbedtls_test_ssl_check_context_after_session_reset(&ssl_before, &ssl) != 0) { + mbedtls_printf( + " failed\n ! mbedtls_ssl_session_reset didn't properly reset ssl context\n\n"); + goto exit; + } + while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 5cbd7de006..813e25f158 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -57,6 +57,8 @@ int main(void) #include "test/psa_crypto_helpers.h" #endif +#include "test/ssl_helpers.h" + #include "mbedtls/pk.h" #include "mbedtls/dhm.h" @@ -3372,7 +3374,15 @@ reset: mbedtls_net_free(&client_fd); + /* Dump the SSL context before resetting it. This will be used below + * to check if the reset function worked properly. */ + mbedtls_ssl_context ssl_before = ssl; mbedtls_ssl_session_reset(&ssl); + if (mbedtls_test_ssl_check_context_after_session_reset(&ssl_before, &ssl) != 0) { + mbedtls_printf( + " failed\n ! mbedtls_ssl_session_reset didn't properly reset ssl context\n\n"); + goto exit; + } /* * 3. Wait until a client connects diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c index 3cf0fc3cfa..527c69d761 100644 --- a/tests/src/test_helpers/ssl_helpers.c +++ b/tests/src/test_helpers/ssl_helpers.c @@ -934,6 +934,16 @@ void mbedtls_test_ssl_endpoint_free( { test_ssl_endpoint_certificate_free(ep); + mbedtls_ssl_context ssl_before; + + /* Dump the SSL context before resetting it */ + memcpy(&ssl_before, &(ep->ssl), sizeof(mbedtls_ssl_context)); + + mbedtls_ssl_session_reset(&(ep->ssl)); + + /* Check that required fields were properly reset */ + mbedtls_test_ssl_check_context_after_session_reset(&ssl_before, &(ep->ssl)); + mbedtls_ssl_free(&(ep->ssl)); mbedtls_ssl_config_free(&(ep->conf)); From d36dedc03334888adfd4fe2769997690a72ae79b Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 23 Jun 2026 22:37:54 +0200 Subject: [PATCH 06/16] tests: generate_ssl_session_reset_check: add missing semicolon in generated file Signed-off-by: Valerio Setti --- tests/scripts/generate_ssl_session_reset_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/scripts/generate_ssl_session_reset_check.py b/tests/scripts/generate_ssl_session_reset_check.py index fa67134ca4..303f27e251 100755 --- a/tests/scripts/generate_ssl_session_reset_check.py +++ b/tests/scripts/generate_ssl_session_reset_check.py @@ -107,7 +107,7 @@ RULES = { SPECIAL_BEHAVIORS = { 'flags': ['TEST_EQUAL((after->flags & ~(MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)), ' - 'initial.flags)', + 'initial.flags);', 'TEST_EQUAL((before->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION), ' + '(after->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION));'], 'tls_version': ['TEST_ASSERT(after->tls_version == after->conf->max_tls_version);'], From 40f82abadbca6a177a2fcdf9f547d5a803bf41dc Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 23 Jun 2026 22:38:41 +0200 Subject: [PATCH 07/16] tests: ssl_context_reset_verifier: add missing semicolon in generated file Signed-off-by: Valerio Setti --- tests/src/ssl_context_reset_verifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/ssl_context_reset_verifier.c b/tests/src/ssl_context_reset_verifier.c index 2f106e9067..a0fda308ec 100644 --- a/tests/src/ssl_context_reset_verifier.c +++ b/tests/src/ssl_context_reset_verifier.c @@ -31,7 +31,7 @@ int mbedtls_test_ssl_check_context_after_session_reset(const mbedtls_ssl_context /* *INDENT-OFF* */ TEST_ASSERT(before->conf == after->conf); TEST_ASSERT(after->state == initial.state); - TEST_EQUAL((after->flags & ~(MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)), initial.flags) + TEST_EQUAL((after->flags & ~(MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)), initial.flags); TEST_EQUAL((before->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION), (after->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)); #if defined(MBEDTLS_SSL_RENEGOTIATION) TEST_ASSERT(after->renego_status == initial.renego_status); From 778a0546a5b39d00491668217ee274809cee50fa Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 23 Jun 2026 22:39:41 +0200 Subject: [PATCH 08/16] tests: ssl_helpers: fix documentation of mbedtls_test_ssl_check_context_after_session_reset Signed-off-by: Valerio Setti --- tests/include/test/ssl_helpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h index 7b06298d1b..3592015cb9 100644 --- a/tests/include/test/ssl_helpers.h +++ b/tests/include/test/ssl_helpers.h @@ -663,7 +663,7 @@ int mbedtls_test_get_tls13_ticket( * is called on it. This is used for fields that * should be kept untouched during the reset. * \param[in] after The SSL context after mbedtls_ssl_session_reset() - * is called on it. + * has been called on it. */ int mbedtls_test_ssl_check_context_after_session_reset(const mbedtls_ssl_context *before, const mbedtls_ssl_context *after); From 96423d43d00bf3121e5bc66b56f1579f88e7e8fc Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 23 Jun 2026 22:49:11 +0200 Subject: [PATCH 09/16] tests: generate_ssl_session_reset_check: order rules as fields in the struct Signed-off-by: Valerio Setti --- .../generate_ssl_session_reset_check.py | 80 ++++++++----------- 1 file changed, 35 insertions(+), 45 deletions(-) diff --git a/tests/scripts/generate_ssl_session_reset_check.py b/tests/scripts/generate_ssl_session_reset_check.py index 303f27e251..96a5d3b078 100755 --- a/tests/scripts/generate_ssl_session_reset_check.py +++ b/tests/scripts/generate_ssl_session_reset_check.py @@ -9,23 +9,45 @@ import scripts_path # pylint: disable=unused-import from mbedtls_framework import ssl_session_reset_check RULES = { - # Fields that are reset + 'conf': ssl_session_reset_check.ResetBehavior.KEEP, 'state': ssl_session_reset_check.ResetBehavior.RESET, + 'flags': ssl_session_reset_check.ResetBehavior.SPECIAL, 'renego_status': ssl_session_reset_check.ResetBehavior.RESET, 'renego_records_seen': ssl_session_reset_check.ResetBehavior.RESET, + 'tls_version': ssl_session_reset_check.ResetBehavior.SPECIAL, 'early_data_state': ssl_session_reset_check.ResetBehavior.RESET, 'badmac_seen': ssl_session_reset_check.ResetBehavior.RESET, + 'f_vrfy': ssl_session_reset_check.ResetBehavior.KEEP, + 'p_vrfy': ssl_session_reset_check.ResetBehavior.KEEP, + 'f_send': ssl_session_reset_check.ResetBehavior.KEEP, + 'f_recv': ssl_session_reset_check.ResetBehavior.KEEP, + 'f_recv_timeout': ssl_session_reset_check.ResetBehavior.KEEP, + 'p_bio': ssl_session_reset_check.ResetBehavior.KEEP, 'session_in': ssl_session_reset_check.ResetBehavior.RESET, 'session_out': ssl_session_reset_check.ResetBehavior.RESET, 'session': ssl_session_reset_check.ResetBehavior.RESET, + 'session_negotiate': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'handshake': ssl_session_reset_check.ResetBehavior.REALLOCATE, 'transform_in': ssl_session_reset_check.ResetBehavior.RESET, 'transform_out': ssl_session_reset_check.ResetBehavior.RESET, 'transform': ssl_session_reset_check.ResetBehavior.RESET, + 'transform_negotiate': ssl_session_reset_check.ResetBehavior.REALLOCATE, 'transform_application': ssl_session_reset_check.ResetBehavior.RESET, + 'p_timer': ssl_session_reset_check.ResetBehavior.KEEP, + 'f_set_timer': ssl_session_reset_check.ResetBehavior.KEEP, + 'f_get_timer': ssl_session_reset_check.ResetBehavior.KEEP, + 'in_buf': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'in_ctr': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'in_hdr': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'in_cid': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'in_len': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'in_iv': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'in_msg': ssl_session_reset_check.ResetBehavior.REALLOCATE, 'in_offt': ssl_session_reset_check.ResetBehavior.RESET, 'in_msgtype': ssl_session_reset_check.ResetBehavior.RESET, 'in_msglen': ssl_session_reset_check.ResetBehavior.RESET, 'in_left': ssl_session_reset_check.ResetBehavior.RESET, + 'in_buf_len': ssl_session_reset_check.ResetBehavior.SPECIAL, 'in_epoch': ssl_session_reset_check.ResetBehavior.RESET, 'next_record_offset': ssl_session_reset_check.ResetBehavior.RESET, 'in_window_top': ssl_session_reset_check.ResetBehavior.RESET, @@ -39,12 +61,23 @@ RULES = { 'send_alert': ssl_session_reset_check.ResetBehavior.RESET, 'alert_type': ssl_session_reset_check.ResetBehavior.RESET, 'alert_reason': ssl_session_reset_check.ResetBehavior.RESET, + 'disable_datagram_packing': ssl_session_reset_check.ResetBehavior.KEEP, 'discard_early_data_record': ssl_session_reset_check.ResetBehavior.RESET, 'total_early_data_size': ssl_session_reset_check.ResetBehavior.RESET, + 'out_buf': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'out_ctr': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'out_hdr': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'out_cid': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'out_len': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'out_iv': ssl_session_reset_check.ResetBehavior.REALLOCATE, + 'out_msg': ssl_session_reset_check.ResetBehavior.REALLOCATE, 'out_msgtype': ssl_session_reset_check.ResetBehavior.RESET, 'out_msglen': ssl_session_reset_check.ResetBehavior.RESET, 'out_left': ssl_session_reset_check.ResetBehavior.RESET, + 'out_buf_len': ssl_session_reset_check.ResetBehavior.SPECIAL, 'cur_out_ctr': ssl_session_reset_check.ResetBehavior.RESET, + 'mtu': ssl_session_reset_check.ResetBehavior.KEEP, + 'hostname': ssl_session_reset_check.ResetBehavior.KEEP, 'alpn_chosen': ssl_session_reset_check.ResetBehavior.RESET, 'dtls_srtp_info': ssl_session_reset_check.ResetBehavior.RESET, 'cli_id': ssl_session_reset_check.ResetBehavior.RESET, @@ -53,56 +86,13 @@ RULES = { 'verify_data_len': ssl_session_reset_check.ResetBehavior.RESET, 'own_verify_data': ssl_session_reset_check.ResetBehavior.RESET, 'peer_verify_data': ssl_session_reset_check.ResetBehavior.RESET, - - # Fields that are preserved during reset - 'conf': ssl_session_reset_check.ResetBehavior.KEEP, - 'f_vrfy': ssl_session_reset_check.ResetBehavior.KEEP, - 'p_vrfy': ssl_session_reset_check.ResetBehavior.KEEP, - 'f_send': ssl_session_reset_check.ResetBehavior.KEEP, - 'f_recv': ssl_session_reset_check.ResetBehavior.KEEP, - 'f_recv_timeout': ssl_session_reset_check.ResetBehavior.KEEP, - 'p_bio': ssl_session_reset_check.ResetBehavior.KEEP, - 'p_timer': ssl_session_reset_check.ResetBehavior.KEEP, - 'f_set_timer': ssl_session_reset_check.ResetBehavior.KEEP, - 'f_get_timer': ssl_session_reset_check.ResetBehavior.KEEP, - 'disable_datagram_packing': ssl_session_reset_check.ResetBehavior.KEEP, - 'mtu': ssl_session_reset_check.ResetBehavior.KEEP, - 'hostname': ssl_session_reset_check.ResetBehavior.KEEP, 'own_cid': ssl_session_reset_check.ResetBehavior.KEEP, 'own_cid_len': ssl_session_reset_check.ResetBehavior.KEEP, 'negotiate_cid': ssl_session_reset_check.ResetBehavior.KEEP, 'f_export_keys': ssl_session_reset_check.ResetBehavior.KEEP, 'p_export_keys': ssl_session_reset_check.ResetBehavior.KEEP, - - # Fields which are intentionally not checked. - 'unused': ssl_session_reset_check.ResetBehavior.IGNORE, - - # Pointers which might be reallocated during reset - 'in_buf': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'in_ctr': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'in_hdr': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'in_cid': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'in_len': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'in_iv': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'in_msg': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'out_buf': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'out_ctr': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'out_hdr': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'out_cid': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'out_len': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'out_iv': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'out_msg': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'session_negotiate': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'handshake': ssl_session_reset_check.ResetBehavior.REALLOCATE, - 'transform_negotiate': ssl_session_reset_check.ResetBehavior.REALLOCATE, - - # Fields with custom check rules. Rules must be defined in the - # SPECIAL_BEHAVIORS dictionary below. - 'flags': ssl_session_reset_check.ResetBehavior.SPECIAL, - 'tls_version': ssl_session_reset_check.ResetBehavior.SPECIAL, 'user_data': ssl_session_reset_check.ResetBehavior.SPECIAL, - 'in_buf_len': ssl_session_reset_check.ResetBehavior.SPECIAL, - 'out_buf_len': ssl_session_reset_check.ResetBehavior.SPECIAL, + 'unused': ssl_session_reset_check.ResetBehavior.IGNORE, } SPECIAL_BEHAVIORS = { From eb9fd867451fe82dc3a4b9e07406deeb077aea3d Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 23 Jun 2026 23:34:01 +0200 Subject: [PATCH 10/16] tests: generate_ssl_session_reset_check: pacify pylint Signed-off-by: Valerio Setti --- tests/scripts/generate_ssl_session_reset_check.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/scripts/generate_ssl_session_reset_check.py b/tests/scripts/generate_ssl_session_reset_check.py index 96a5d3b078..78e0b6921f 100755 --- a/tests/scripts/generate_ssl_session_reset_check.py +++ b/tests/scripts/generate_ssl_session_reset_check.py @@ -96,7 +96,7 @@ RULES = { } SPECIAL_BEHAVIORS = { - 'flags': ['TEST_EQUAL((after->flags & ~(MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)), ' + 'flags': ['TEST_EQUAL((after->flags & ~(MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)), ' + 'initial.flags);', 'TEST_EQUAL((before->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION), ' + '(after->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION));'], @@ -106,9 +106,9 @@ SPECIAL_BEHAVIORS = { 'out_buf_len': ['TEST_ASSERT(after->out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);'], } -NAMED_STRUCTURES = [ +NAMED_STRUCTURES = frozenset([ 'dtls_srtp_info', -] +]) FIELDS_INFO = ssl_session_reset_check.FieldsInfo(RULES, SPECIAL_BEHAVIORS, From 2c35acc231d8b00e1a974df6764167d939e6f6c4 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 24 Jun 2026 09:04:15 +0200 Subject: [PATCH 11/16] tests: generate_ssl_session_reset_check: remove trailing whitespace Signed-off-by: Valerio Setti --- tests/scripts/generate_ssl_session_reset_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/scripts/generate_ssl_session_reset_check.py b/tests/scripts/generate_ssl_session_reset_check.py index 78e0b6921f..8e26d9ee1a 100755 --- a/tests/scripts/generate_ssl_session_reset_check.py +++ b/tests/scripts/generate_ssl_session_reset_check.py @@ -106,7 +106,7 @@ SPECIAL_BEHAVIORS = { 'out_buf_len': ['TEST_ASSERT(after->out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);'], } -NAMED_STRUCTURES = frozenset([ +NAMED_STRUCTURES = frozenset([ 'dtls_srtp_info', ]) From 9c2ef6a4da84bd0e6a9d79c97613b1fd4c807acb Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 24 Jun 2026 15:37:00 +0200 Subject: [PATCH 12/16] tests: ssl_helpers: run ssl_context reset check only when the SSL context is setup Signed-off-by: Valerio Setti --- tests/src/test_helpers/ssl_helpers.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c index 527c69d761..ba42da9b6e 100644 --- a/tests/src/test_helpers/ssl_helpers.c +++ b/tests/src/test_helpers/ssl_helpers.c @@ -934,16 +934,17 @@ void mbedtls_test_ssl_endpoint_free( { test_ssl_endpoint_certificate_free(ep); - mbedtls_ssl_context ssl_before; + // mbedtls_ssl_session_reset() requires the SSL to be setup. + if (ep->ssl.conf != NULL) { + mbedtls_ssl_context ssl_before; - /* Dump the SSL context before resetting it */ - memcpy(&ssl_before, &(ep->ssl), sizeof(mbedtls_ssl_context)); - - mbedtls_ssl_session_reset(&(ep->ssl)); - - /* Check that required fields were properly reset */ - mbedtls_test_ssl_check_context_after_session_reset(&ssl_before, &(ep->ssl)); + /* Dump the SSL context before resetting it */ + memcpy(&ssl_before, &(ep->ssl), sizeof(mbedtls_ssl_context)); + mbedtls_ssl_session_reset(&(ep->ssl)); + /* Check that required fields were properly reset */ + mbedtls_test_ssl_check_context_after_session_reset(&ssl_before, &(ep->ssl)); + } mbedtls_ssl_free(&(ep->ssl)); mbedtls_ssl_config_free(&(ep->conf)); From 41ada48936d1ea1f54c1a1aa12a1ecb31bda4802 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 24 Jun 2026 16:45:43 +0200 Subject: [PATCH 13/16] tests: generate_ssl_session_reset_check: adjust rules for 3.6 branch Signed-off-by: Valerio Setti --- tests/scripts/generate_ssl_session_reset_check.py | 11 +---------- tests/src/ssl_context_reset_verifier.c | 8 +------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/tests/scripts/generate_ssl_session_reset_check.py b/tests/scripts/generate_ssl_session_reset_check.py index 8e26d9ee1a..51ec077b0d 100755 --- a/tests/scripts/generate_ssl_session_reset_check.py +++ b/tests/scripts/generate_ssl_session_reset_check.py @@ -11,12 +11,11 @@ from mbedtls_framework import ssl_session_reset_check RULES = { 'conf': ssl_session_reset_check.ResetBehavior.KEEP, 'state': ssl_session_reset_check.ResetBehavior.RESET, - 'flags': ssl_session_reset_check.ResetBehavior.SPECIAL, 'renego_status': ssl_session_reset_check.ResetBehavior.RESET, 'renego_records_seen': ssl_session_reset_check.ResetBehavior.RESET, 'tls_version': ssl_session_reset_check.ResetBehavior.SPECIAL, 'early_data_state': ssl_session_reset_check.ResetBehavior.RESET, - 'badmac_seen': ssl_session_reset_check.ResetBehavior.RESET, + 'badmac_seen_or_in_hsfraglen': ssl_session_reset_check.ResetBehavior.RESET, 'f_vrfy': ssl_session_reset_check.ResetBehavior.KEEP, 'p_vrfy': ssl_session_reset_check.ResetBehavior.KEEP, 'f_send': ssl_session_reset_check.ResetBehavior.KEEP, @@ -53,11 +52,8 @@ RULES = { 'in_window_top': ssl_session_reset_check.ResetBehavior.RESET, 'in_window': ssl_session_reset_check.ResetBehavior.RESET, 'in_hslen': ssl_session_reset_check.ResetBehavior.RESET, - 'in_hsfraglen': ssl_session_reset_check.ResetBehavior.RESET, 'nb_zero': ssl_session_reset_check.ResetBehavior.RESET, 'keep_current_message': ssl_session_reset_check.ResetBehavior.RESET, - 'in_fatal_alert_recv': ssl_session_reset_check.ResetBehavior.RESET, - 'in_fatal_alert_type': ssl_session_reset_check.ResetBehavior.RESET, 'send_alert': ssl_session_reset_check.ResetBehavior.RESET, 'alert_type': ssl_session_reset_check.ResetBehavior.RESET, 'alert_reason': ssl_session_reset_check.ResetBehavior.RESET, @@ -92,14 +88,9 @@ RULES = { 'f_export_keys': ssl_session_reset_check.ResetBehavior.KEEP, 'p_export_keys': ssl_session_reset_check.ResetBehavior.KEEP, 'user_data': ssl_session_reset_check.ResetBehavior.SPECIAL, - 'unused': ssl_session_reset_check.ResetBehavior.IGNORE, } SPECIAL_BEHAVIORS = { - 'flags': ['TEST_EQUAL((after->flags & ~(MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)), ' + - 'initial.flags);', - 'TEST_EQUAL((before->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION), ' + - '(after->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION));'], 'tls_version': ['TEST_ASSERT(after->tls_version == after->conf->max_tls_version);'], 'user_data': ['TEST_ASSERT(before->user_data.n == after->user_data.n);'], 'in_buf_len': ['TEST_ASSERT(after->in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);'], diff --git a/tests/src/ssl_context_reset_verifier.c b/tests/src/ssl_context_reset_verifier.c index a0fda308ec..662b20beb0 100644 --- a/tests/src/ssl_context_reset_verifier.c +++ b/tests/src/ssl_context_reset_verifier.c @@ -31,8 +31,6 @@ int mbedtls_test_ssl_check_context_after_session_reset(const mbedtls_ssl_context /* *INDENT-OFF* */ TEST_ASSERT(before->conf == after->conf); TEST_ASSERT(after->state == initial.state); - TEST_EQUAL((after->flags & ~(MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)), initial.flags); - TEST_EQUAL((before->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION), (after->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)); #if defined(MBEDTLS_SSL_RENEGOTIATION) TEST_ASSERT(after->renego_status == initial.renego_status); #endif @@ -43,7 +41,7 @@ int mbedtls_test_ssl_check_context_after_session_reset(const mbedtls_ssl_context #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) TEST_ASSERT(after->early_data_state == initial.early_data_state); #endif - TEST_ASSERT(after->badmac_seen == initial.badmac_seen); + TEST_ASSERT(after->badmac_seen_or_in_hsfraglen == initial.badmac_seen_or_in_hsfraglen); #if defined(MBEDTLS_X509_CRT_PARSE_C) TEST_ASSERT(before->f_vrfy == after->f_vrfy); #endif @@ -100,11 +98,8 @@ int mbedtls_test_ssl_check_context_after_session_reset(const mbedtls_ssl_context TEST_ASSERT(after->in_window == initial.in_window); #endif TEST_ASSERT(after->in_hslen == initial.in_hslen); - TEST_ASSERT(after->in_hsfraglen == initial.in_hsfraglen); TEST_ASSERT(after->nb_zero == initial.nb_zero); TEST_ASSERT(after->keep_current_message == initial.keep_current_message); - TEST_ASSERT(after->in_fatal_alert_recv == initial.in_fatal_alert_recv); - TEST_ASSERT(after->in_fatal_alert_type == initial.in_fatal_alert_type); TEST_ASSERT(after->send_alert == initial.send_alert); TEST_ASSERT(after->alert_type == initial.alert_type); TEST_ASSERT(after->alert_reason == initial.alert_reason); @@ -176,7 +171,6 @@ int mbedtls_test_ssl_check_context_after_session_reset(const mbedtls_ssl_context TEST_ASSERT(before->f_export_keys == after->f_export_keys); TEST_ASSERT(before->p_export_keys == after->p_export_keys); TEST_ASSERT(before->user_data.n == after->user_data.n); - /* unused is ignored */ /* *INDENT-ON* */ ret = 0; From 7902021aebe7ac079906ef85c935199f2ac3859d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 25 Jun 2026 11:07:59 +0200 Subject: [PATCH 14/16] Move context verifier to a better place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In terms of CMake, we want it to be part of the mbedtls_test_helpers object collection, which as the name does not suggest, is actually for SSL, and not part of mbedtls_test which is generic. The easiest way to achieve that is to move the source file to test_helpers which again as the name does not reflect is for SSL. Then we just need ssl_server2 and ssl_client2 to link to mbedtls_test_helpers. Signed-off-by: Manuel Pégourié-Gonnard --- programs/ssl/CMakeLists.txt | 1 + tests/src/{ => test_helpers}/ssl_context_reset_verifier.c | 0 2 files changed, 1 insertion(+) rename tests/src/{ => test_helpers}/ssl_context_reset_verifier.c (100%) diff --git a/programs/ssl/CMakeLists.txt b/programs/ssl/CMakeLists.txt index 4e954f07ef..0088ba0f16 100644 --- a/programs/ssl/CMakeLists.txt +++ b/programs/ssl/CMakeLists.txt @@ -34,6 +34,7 @@ foreach(exe IN LISTS executables) set(extra_sources "") if(exe STREQUAL "ssl_client2" OR exe STREQUAL "ssl_server2") list(APPEND extra_sources + $ ssl_test_lib.c ${MBEDTLS_FRAMEWORK_DIR}/tests/programs/query_config.h ${CMAKE_CURRENT_BINARY_DIR}/../test/query_config.c) diff --git a/tests/src/ssl_context_reset_verifier.c b/tests/src/test_helpers/ssl_context_reset_verifier.c similarity index 100% rename from tests/src/ssl_context_reset_verifier.c rename to tests/src/test_helpers/ssl_context_reset_verifier.c From a16f9fa50328414c3e4a83add66d0a6e6cb56c9c Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 26 Jun 2026 14:43:45 +0200 Subject: [PATCH 15/16] Use a list for test source directories No change to the output except some reordering of elements in a list. Signed-off-by: Gilles Peskine --- scripts/generate_visualc_files.pl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts/generate_visualc_files.pl b/scripts/generate_visualc_files.pl index 9f28cddffb..d778e83c85 100755 --- a/scripts/generate_visualc_files.pl +++ b/scripts/generate_visualc_files.pl @@ -26,12 +26,14 @@ my $framework_programs_dir = 'framework/tests/programs'; my $mbedtls_header_dir = 'include/mbedtls'; my $psa_header_dir = 'include/psa'; my $source_dir = 'library'; -my $tls_test_source_dir = 'tests/src'; my $tls_test_header_dir = 'tests/include/test'; -my $test_source_dir = 'framework/tests/src'; +my @test_source_dirs = qw( + framework/tests/src + framework/tests/src/drivers + tests/src +); my $test_header_dir = 'framework/tests/include/test'; my $test_drivers_header_dir = 'framework/tests/include/test/drivers'; -my $test_drivers_source_dir = 'framework/tests/src/drivers'; my @thirdparty_header_dirs = qw( 3rdparty/everest/include/everest @@ -101,16 +103,16 @@ EOT exit( main() ); sub check_dirs { - foreach my $d (@thirdparty_header_dirs, @thirdparty_source_dirs) { + foreach my $d ( + @thirdparty_header_dirs, @thirdparty_source_dirs, + @test_source_dirs, + ) { if (not (-d $d)) { return 0; } } return -d $vsx_dir && -d $mbedtls_header_dir && -d $psa_header_dir && -d $source_dir - && -d $test_source_dir - && -d $tls_test_source_dir - && -d $test_drivers_source_dir && -d $test_header_dir && -d $tls_test_header_dir && -d $test_drivers_header_dir @@ -283,10 +285,8 @@ sub main { my @headers = (map { <$_/*.h> } @header_dirs); my @source_dirs = ( $source_dir, - $test_source_dir, - $tls_test_source_dir, - $test_drivers_source_dir, @thirdparty_source_dirs, + @test_source_dirs, ); my @sources = (map { <$_/*.c> } @source_dirs); From 6be594ffca8f32ae2b74683a336e422faa64f144 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 26 Jun 2026 14:44:30 +0200 Subject: [PATCH 16/16] Expose tests/src/test_helpers Make SSL test helper code potentially available to sample programs. This is notably useful for `ssl_client2` and `ssl_server2`, which may reasonably use some test helper code even in the default configuration. Signed-off-by: Gilles Peskine --- scripts/generate_visualc_files.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/generate_visualc_files.pl b/scripts/generate_visualc_files.pl index d778e83c85..561ba12de4 100755 --- a/scripts/generate_visualc_files.pl +++ b/scripts/generate_visualc_files.pl @@ -31,6 +31,7 @@ my @test_source_dirs = qw( framework/tests/src framework/tests/src/drivers tests/src + tests/src/test_helpers ); my $test_header_dir = 'framework/tests/include/test'; my $test_drivers_header_dir = 'framework/tests/include/test/drivers';