From 902762039334c91813ab9e9ba8ccef5356e819e4 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Tue, 21 Apr 2026 16:46:31 +0100 Subject: [PATCH 001/168] tls13_client: fix HRR selected_group validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reject HRR selected_group unless it matches the client’s original supported_groups and is locally supported, so unadvertised groups are not accepted in the second ClientHello. Signed-off-by: Minos Galanakis --- library/ssl_tls13_client.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index b7b075cc97..167861e33a 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -404,14 +404,18 @@ static int ssl_tls13_parse_hrr_key_share_ext(mbedtls_ssl_context *ssl, * then the client MUST abort the handshake with an "illegal_parameter" alert. */ for (; *group_list != 0; group_list++) { + if (*group_list != selected_group) { + continue; + } #if defined(PSA_WANT_ALG_ECDH) if (mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) { - if ((mbedtls_ssl_get_psa_curve_info_from_tls_id( - *group_list, NULL, NULL) == PSA_ERROR_NOT_SUPPORTED) || - *group_list != selected_group) { - found = 1; - break; + if (mbedtls_ssl_get_psa_curve_info_from_tls_id( + *group_list, NULL, NULL) == PSA_ERROR_NOT_SUPPORTED) { + continue; } + /* Found only if psa_curve is supported and group_list == selected_group */ + found = 1; + break; } #endif /* PSA_WANT_ALG_ECDH */ #if defined(PSA_WANT_ALG_FFDH) From a9a838574748885daa01136fc56eb5fd26456b48 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Thu, 23 Apr 2026 13:53:40 +0100 Subject: [PATCH 002/168] test_suite_ssl: Introduced hrr_reject_unadvertised_group Signed-off-by: Minos Galanakis --- tests/suites/test_suite_ssl.data | 3 ++ tests/suites/test_suite_ssl.function | 77 ++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 6b9c73f11e..154f568d3b 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3347,6 +3347,9 @@ cookie_parsing:"16fefd0000000000000000002F010000de000000000000011efefd7b72727272 TLS 1.3 srv Certificate msg - wrong vector lengths tls13_server_certificate_msg_invalid_vector_len +TLS 1.3 cli rejects HRR selected_group not in original supported_groups +hrr_reject_unadvertised_group + EC-JPAKE set password depends_on:MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED ssl_ecjpake_set_password:0 diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index d27d959232..82bb2e1db1 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -3995,6 +3995,83 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_ECDH:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384 */ +void hrr_reject_unadvertised_group(void) +{ + int ret = -1; + + mbedtls_test_ssl_endpoint client_ep, server_ep; + mbedtls_test_handshake_test_options client_options, server_options; + + uint16_t offered_group_before_hrr_parse = 0; + uint16_t offered_group_after_hrr_parse = 0; + + /* Group order is intentional: client offers secp256r1 first, while server only + * accepts secp384r1. This prevents immediate group agreement and forces HRR. */ + uint16_t client_group_list[] = { + MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, + MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, + MBEDTLS_SSL_IANA_TLS_GROUP_NONE + }; + uint16_t server_group_list[] = { MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, + MBEDTLS_SSL_IANA_TLS_GROUP_NONE }; + + memset(&client_ep, 0, sizeof(client_ep)); + memset(&server_ep, 0, sizeof(server_ep)); + + mbedtls_test_init_handshake_options(&client_options); + mbedtls_test_init_handshake_options(&server_options); + MD_OR_USE_PSA_INIT(); + + client_options.pk_alg = MBEDTLS_PK_ECDSA; + client_options.client_min_version = MBEDTLS_SSL_VERSION_TLS1_3; + client_options.client_max_version = MBEDTLS_SSL_VERSION_TLS1_3; + client_options.group_list = client_group_list; + + server_options.pk_alg = MBEDTLS_PK_ECDSA; + server_options.server_min_version = MBEDTLS_SSL_VERSION_TLS1_3; + server_options.server_max_version = MBEDTLS_SSL_VERSION_TLS1_3; + server_options.group_list = server_group_list; + + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, + &client_options), 0); + + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, + &server_options), 0); + + TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket), + &(server_ep.socket), 4096), 0); + + ret = mbedtls_test_move_handshake_to_state( + &(server_ep.ssl), &(client_ep.ssl), + MBEDTLS_SSL_HELLO_RETRY_REQUEST); + TEST_EQUAL(ret, 0); + + server_ep.ssl.handshake->hrr_selected_group = MBEDTLS_SSL_IANA_TLS_GROUP_X25519; + TEST_EQUAL(mbedtls_ssl_handshake_step(&(server_ep.ssl)), 0); + + /* Push the HRR with unadvertised group into the wire*/ + TEST_EQUAL(mbedtls_ssl_flush_output(&(server_ep.ssl)), 0); + + offered_group_before_hrr_parse = client_ep.ssl.handshake->offered_group_id; + + /* Client should reject malformed selected_group with illegal_parameter. */ + TEST_EQUAL(mbedtls_ssl_handshake_step(&(client_ep.ssl)), MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + + /* The server send a non advertised group during HRR. Client shouldnt accept it as offered_group_id */ + offered_group_after_hrr_parse = client_ep.ssl.handshake->offered_group_id; + TEST_EQUAL(offered_group_after_hrr_parse, offered_group_before_hrr_parse); + + +exit: + mbedtls_test_ssl_endpoint_free(&client_ep); + mbedtls_test_ssl_endpoint_free(&server_ep); + mbedtls_test_free_handshake_options(&client_options); + mbedtls_test_free_handshake_options(&server_options); + MD_OR_USE_PSA_DONE(); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ void ssl_ecjpake_set_password(int use_opaque_arg) { From 465d6e9669a24ff7fe1a018fafe0e9f44aa4a48b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Sat, 11 Apr 2026 17:10:14 +0200 Subject: [PATCH 003/168] Fix ssl_tls13_prepare_new_session_ticket returning 1 on an RNG failure Signed-off-by: Gilles Peskine --- .../ssl_tls13_prepare_new_session_ticket-psa_get_random.txt | 5 +++++ library/ssl_tls13_server.c | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 ChangeLog.d/ssl_tls13_prepare_new_session_ticket-psa_get_random.txt diff --git a/ChangeLog.d/ssl_tls13_prepare_new_session_ticket-psa_get_random.txt b/ChangeLog.d/ssl_tls13_prepare_new_session_ticket-psa_get_random.txt new file mode 100644 index 0000000000..0fc8b0aa85 --- /dev/null +++ b/ChangeLog.d/ssl_tls13_prepare_new_session_ticket-psa_get_random.txt @@ -0,0 +1,5 @@ +Security + * Fix a bug where mbedtls_ssl_read() and mbedtls_ssl_write() could return + 1 instead of an error code if the random generator fails if a server + calls these functions before the end of a TLS 1.3 handshake. + Reported by Mohammad Seet (mhdsait101). CVE-2026-40294 diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index dc7c776830..37fdf79ee3 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -3183,8 +3183,9 @@ static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl, #endif /* Generate ticket_age_add */ - if ((ret = psa_generate_random((unsigned char *) &session->ticket_age_add, - sizeof(session->ticket_age_add)) != 0)) { + ret = psa_generate_random((unsigned char *) &session->ticket_age_add, + sizeof(session->ticket_age_add)); + if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "generate_ticket_age_add", ret); return ret; } From 89a06061183f297ff5c9652745752fe7de53a15e Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Mon, 27 Apr 2026 12:25:32 +0100 Subject: [PATCH 004/168] Adjusted dependecies for hrr_reject_unadvertised_group Signed-off-by: Minos Galanakis --- tests/suites/test_suite_ssl.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 82bb2e1db1..aa36e36b75 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -3995,7 +3995,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_ECDH:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384 */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA_ANY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384 */ void hrr_reject_unadvertised_group(void) { int ret = -1; From 08e3e3f81e6c5703c3afcbfcb47c600a2b10afcb Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 11 May 2026 15:22:09 +0100 Subject: [PATCH 005/168] Add fix for OOB key exchange error Signed-off-by: Ben Taylor --- library/ssl_tls12_client.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c index a0170d51f6..d32fea18c1 100644 --- a/library/ssl_tls12_client.c +++ b/library/ssl_tls12_client.c @@ -1885,6 +1885,8 @@ start_processing: * However since we only support secp256r1 for now, we check only * that TLS ID here */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 3); + uint16_t read_tls_id = MBEDTLS_GET_UINT16_BE(p, 1); uint16_t exp_tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( MBEDTLS_ECP_DP_SECP256R1); From 5936ba523da2efbb4674f585662cfa9cef8dc449 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Tue, 12 May 2026 14:59:18 +0100 Subject: [PATCH 006/168] Added ChangeLog Signed-off-by: Minos Galanakis --- ChangeLog.d/tls13-hrr-selected-group.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 ChangeLog.d/tls13-hrr-selected-group.txt diff --git a/ChangeLog.d/tls13-hrr-selected-group.txt b/ChangeLog.d/tls13-hrr-selected-group.txt new file mode 100644 index 0000000000..20d7a18fbd --- /dev/null +++ b/ChangeLog.d/tls13-hrr-selected-group.txt @@ -0,0 +1,5 @@ +Security + * Fix TLS 1.3 clients to reject a HelloRetryRequest whose selected group was + not advertised in the original ClientHello. Reported by + Din Asotić / Xiangdong Li, Beijing University of Posts and + Telecommunications (BUPT) From ea9dc9c396a883aa08851eda9381a42ab6d0f9e4 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Tue, 12 May 2026 14:41:06 +0100 Subject: [PATCH 007/168] Add ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/oob-key-exchange-restricted.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 ChangeLog.d/oob-key-exchange-restricted.txt diff --git a/ChangeLog.d/oob-key-exchange-restricted.txt b/ChangeLog.d/oob-key-exchange-restricted.txt new file mode 100644 index 0000000000..794e294272 --- /dev/null +++ b/ChangeLog.d/oob-key-exchange-restricted.txt @@ -0,0 +1,3 @@ +Bugfix + * Fix an out-of-bounds read in TLS 1.2 ECJPAKE ServerKeyExchange parsing. + Fixes #1590. From 848ddaaedb4133ab34f473b76bf330ecec774b47 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Wed, 13 May 2026 11:33:40 +0100 Subject: [PATCH 008/168] test_suite_ssl: doc fixes Signed-off-by: Minos Galanakis --- tests/suites/test_suite_ssl.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index aa36e36b75..91040203d5 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4058,7 +4058,7 @@ void hrr_reject_unadvertised_group(void) /* Client should reject malformed selected_group with illegal_parameter. */ TEST_EQUAL(mbedtls_ssl_handshake_step(&(client_ep.ssl)), MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); - /* The server send a non advertised group during HRR. Client shouldnt accept it as offered_group_id */ + /* The server sends a non-advertised group during HRR. Client shouldn't accept it as offered_group_id */ offered_group_after_hrr_parse = client_ep.ssl.handshake->offered_group_id; TEST_EQUAL(offered_group_after_hrr_parse, offered_group_before_hrr_parse); From a3ae8be611dc31792d80c266664ff093e2070dc4 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Fri, 15 May 2026 11:44:18 +0200 Subject: [PATCH 009/168] ssl: improve documentation of mbedtls_ssl_conf_sig_algs() Clarify that the 'sig_algs' set through this function are only enforced during the key exchange and that 'mbedtls_ssl_conf_cert_profile()' should instead be used to enforce the same algorithms when verifying certificates. Signed-off-by: Valerio Setti --- include/mbedtls/ssl.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 3a69df5466..2a6d98ab1c 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3411,7 +3411,7 @@ int mbedtls_ssl_conf_cid(mbedtls_ssl_config *conf, size_t len, * * \note The restrictions are enforced for all certificates in the * chain. However, signatures in the handshake are not covered - * by this setting but by \b mbedtls_ssl_conf_sig_algs(). + * by this setting but by \c mbedtls_ssl_conf_sig_algs(). * * \param conf SSL configuration * \param profile Profile to use @@ -3899,7 +3899,12 @@ void mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf, #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) /** - * \brief Configure allowed signature algorithms for use in TLS + * \brief Configure allowed signature algorithms for use in TLS key + * exchange. + * + * \note This only covers signature algorithms used in the key + * exchange. To also enforce restrictions in certificate verification + * refer to \c mbedtls_ssl_conf_cert_profile(). * * \param conf The SSL configuration to use. * \param sig_algs List of allowed IANA values for TLS 1.3 signature algorithms, From c53e78796a10da69b8f7feb668628bfa4d3168fb Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 18 May 2026 11:08:23 +0200 Subject: [PATCH 010/168] changelog: add note about issue 1569 resolution Signed-off-by: Valerio Setti --- ChangeLog.d/security-issue1569.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ChangeLog.d/security-issue1569.txt diff --git a/ChangeLog.d/security-issue1569.txt b/ChangeLog.d/security-issue1569.txt new file mode 100644 index 0000000000..320947ec90 --- /dev/null +++ b/ChangeLog.d/security-issue1569.txt @@ -0,0 +1,4 @@ +Security + * Improved documentation of mbedtls_ssl_conf_sig_algs() to emphasize that + this function only set signature algorithms that are enforced during + TLS key exchange and not only on certificate verification. From 147ad72669797947bef12a0bdbe5dec0ed805c58 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 19 May 2026 12:37:30 +0200 Subject: [PATCH 011/168] changelog: fix typos Signed-off-by: Valerio Setti --- ChangeLog.d/security-issue1569.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog.d/security-issue1569.txt b/ChangeLog.d/security-issue1569.txt index 320947ec90..c7d3ca0782 100644 --- a/ChangeLog.d/security-issue1569.txt +++ b/ChangeLog.d/security-issue1569.txt @@ -1,4 +1,4 @@ Security * Improved documentation of mbedtls_ssl_conf_sig_algs() to emphasize that - this function only set signature algorithms that are enforced during - TLS key exchange and not only on certificate verification. + this function only sets signature algorithms that are enforced during + TLS key exchange and not on certificate verification. From 7a232d0822ad20da952fff4f3b3cf4f5b5e3b149 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Tue, 19 May 2026 17:31:47 +0100 Subject: [PATCH 012/168] sll_client: align TLS 1.3 supported_groups filtering with PSA curve support Signed-off-by: Minos Galanakis --- library/ssl_client.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/ssl_client.c b/library/ssl_client.c index 6fe6dd8fe6..7f0bb7d937 100644 --- a/library/ssl_client.c +++ b/library/ssl_client.c @@ -208,6 +208,9 @@ static int ssl_write_alpn_ext(mbedtls_ssl_context *ssl, * generalization of the TLS 1.2 supported elliptic curves extension. They both * share the same extension identifier. * + * If the TLS 1.3 logic for selecting proposed groups changes, the TLS 1.3 + * group filtering in this function must be kept in sync. + * */ #define SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG 1 #define SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG 2 @@ -251,8 +254,8 @@ static int ssl_write_supported_groups_ext(mbedtls_ssl_context *ssl, if (flags & SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG) { #if defined(PSA_WANT_ALG_ECDH) if (mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list) && - (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) != - MBEDTLS_ECP_DP_NONE)) { + mbedtls_ssl_get_psa_curve_info_from_tls_id( + *group_list, NULL, NULL) == PSA_SUCCESS) { propose_group = 1; } #endif From 3d3de630dbc297378c4ae471531c3a60b4b1c2c9 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Tue, 19 May 2026 17:36:12 +0100 Subject: [PATCH 013/168] test_suite_ssl: Renamed hrr_reject_selecting_unoffered_group Signed-off-by: Minos Galanakis --- tests/suites/test_suite_ssl.data | 4 ++-- tests/suites/test_suite_ssl.function | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 154f568d3b..8d762bc801 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3347,8 +3347,8 @@ cookie_parsing:"16fefd0000000000000000002F010000de000000000000011efefd7b72727272 TLS 1.3 srv Certificate msg - wrong vector lengths tls13_server_certificate_msg_invalid_vector_len -TLS 1.3 cli rejects HRR selected_group not in original supported_groups -hrr_reject_unadvertised_group +TLS 1.3 cli rejects HRR selecting an un-offered group +reject_hrr_selecting_unoffered_group EC-JPAKE set password depends_on:MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 91040203d5..3d53cbb414 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -3996,7 +3996,7 @@ exit: /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA_ANY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384 */ -void hrr_reject_unadvertised_group(void) +void reject_hrr_selecting_unoffered_group(void) { int ret = -1; From 95ad8b45ed23f17a28e39ae4aa6819cc6e5fa0c7 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Tue, 19 May 2026 22:12:05 +0100 Subject: [PATCH 014/168] test_suite_ssl: Restructured reject_hrr_selecting_unoffered_group Signed-off-by: Minos Galanakis --- tests/suites/test_suite_ssl.function | 75 ++++++++++++++++++---------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 3d53cbb414..7547b60ebb 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4002,9 +4002,7 @@ void reject_hrr_selecting_unoffered_group(void) mbedtls_test_ssl_endpoint client_ep, server_ep; mbedtls_test_handshake_test_options client_options, server_options; - - uint16_t offered_group_before_hrr_parse = 0; - uint16_t offered_group_after_hrr_parse = 0; + mbedtls_test_ssl_log_pattern cli_pattern = { .pattern = "Invalid key share in HRR" }; /* Group order is intentional: client offers secp256r1 first, while server only * accepts secp384r1. This prevents immediate group agreement and forces HRR. */ @@ -4027,47 +4025,72 @@ void reject_hrr_selecting_unoffered_group(void) client_options.client_min_version = MBEDTLS_SSL_VERSION_TLS1_3; client_options.client_max_version = MBEDTLS_SSL_VERSION_TLS1_3; client_options.group_list = client_group_list; + client_options.cli_log_obj = &cli_pattern; + client_options.cli_log_fun = mbedtls_test_ssl_log_analyzer; + mbedtls_debug_set_threshold(1); server_options.pk_alg = MBEDTLS_PK_ECDSA; server_options.server_min_version = MBEDTLS_SSL_VERSION_TLS1_3; server_options.server_max_version = MBEDTLS_SSL_VERSION_TLS1_3; server_options.group_list = server_group_list; - TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, - &client_options), 0); + for (int round = 0; round < 2; round++) { + int select_unoffered_group = (round != 0); + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client_ep, + MBEDTLS_SSL_IS_CLIENT, + &client_options), 0); - TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, - &server_options), 0); + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server_ep, + MBEDTLS_SSL_IS_SERVER, + &server_options), 0); - TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket), - &(server_ep.socket), 4096), 0); + TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket), + &(server_ep.socket), 4096), 0); - ret = mbedtls_test_move_handshake_to_state( - &(server_ep.ssl), &(client_ep.ssl), - MBEDTLS_SSL_HELLO_RETRY_REQUEST); - TEST_EQUAL(ret, 0); + ret = mbedtls_test_move_handshake_to_state( + &(server_ep.ssl), &(client_ep.ssl), + MBEDTLS_SSL_HELLO_RETRY_REQUEST); + TEST_EQUAL(ret, 0); + TEST_EQUAL(client_ep.ssl.handshake->offered_group_id, + MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1); - server_ep.ssl.handshake->hrr_selected_group = MBEDTLS_SSL_IANA_TLS_GROUP_X25519; - TEST_EQUAL(mbedtls_ssl_handshake_step(&(server_ep.ssl)), 0); + if (!select_unoffered_group) { + TEST_EQUAL(server_ep.ssl.handshake->hrr_selected_group, + MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1); + } else { + server_ep.ssl.handshake->hrr_selected_group = MBEDTLS_SSL_IANA_TLS_GROUP_X25519; + } - /* Push the HRR with unadvertised group into the wire*/ - TEST_EQUAL(mbedtls_ssl_flush_output(&(server_ep.ssl)), 0); - - offered_group_before_hrr_parse = client_ep.ssl.handshake->offered_group_id; - - /* Client should reject malformed selected_group with illegal_parameter. */ - TEST_EQUAL(mbedtls_ssl_handshake_step(&(client_ep.ssl)), MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); - - /* The server sends a non-advertised group during HRR. Client shouldn't accept it as offered_group_id */ - offered_group_after_hrr_parse = client_ep.ssl.handshake->offered_group_id; - TEST_EQUAL(offered_group_after_hrr_parse, offered_group_before_hrr_parse); + /* Write and send the HRR */ + TEST_EQUAL(mbedtls_ssl_handshake_step(&(server_ep.ssl)), 0); + TEST_EQUAL(mbedtls_ssl_flush_output(&(server_ep.ssl)), 0); + if (!select_unoffered_group) { + /* Valid HRR, the client accepts the group MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 + * and goes ahead with the handshake. + */ + TEST_EQUAL(mbedtls_ssl_handshake_step(&(client_ep.ssl)), 0); + TEST_ASSERT(client_ep.ssl.state != MBEDTLS_SSL_SERVER_HELLO); + TEST_EQUAL(cli_pattern.counter, 0); + } else { + /* Invalid HRR selecting MBEDTLS_SSL_IANA_TLS_GROUP_X25519 group. + * The client rejects it and aborts the handshake. + */ + TEST_EQUAL(mbedtls_ssl_handshake_step(&(client_ep.ssl)), + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + TEST_EQUAL(cli_pattern.counter, 1); + } + mbedtls_test_ssl_endpoint_free(&client_ep); + mbedtls_test_ssl_endpoint_free(&server_ep); + } exit: mbedtls_test_ssl_endpoint_free(&client_ep); mbedtls_test_ssl_endpoint_free(&server_ep); mbedtls_test_free_handshake_options(&client_options); mbedtls_test_free_handshake_options(&server_options); + mbedtls_debug_set_threshold(0); MD_OR_USE_PSA_DONE(); } /* END_CASE */ From 84667a048f2d9d85402c8f8c75b90c8a169a0c3e Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Wed, 20 May 2026 12:25:42 +0100 Subject: [PATCH 015/168] test_suite_ssl: Added MBEDTLS_DEBUG_C guards to logs Signed-off-by: Minos Galanakis --- tests/suites/test_suite_ssl.function | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 7547b60ebb..0c176f1224 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4002,7 +4002,9 @@ void reject_hrr_selecting_unoffered_group(void) mbedtls_test_ssl_endpoint client_ep, server_ep; mbedtls_test_handshake_test_options client_options, server_options; +#if defined(MBEDTLS_DEBUG_C) mbedtls_test_ssl_log_pattern cli_pattern = { .pattern = "Invalid key share in HRR" }; +#endif /* MBEDTLS_DEBUG_C */ /* Group order is intentional: client offers secp256r1 first, while server only * accepts secp384r1. This prevents immediate group agreement and forces HRR. */ @@ -4025,9 +4027,11 @@ void reject_hrr_selecting_unoffered_group(void) client_options.client_min_version = MBEDTLS_SSL_VERSION_TLS1_3; client_options.client_max_version = MBEDTLS_SSL_VERSION_TLS1_3; client_options.group_list = client_group_list; +#if defined(MBEDTLS_DEBUG_C) client_options.cli_log_obj = &cli_pattern; client_options.cli_log_fun = mbedtls_test_ssl_log_analyzer; mbedtls_debug_set_threshold(1); +#endif /* MBEDTLS_DEBUG_C */ server_options.pk_alg = MBEDTLS_PK_ECDSA; server_options.server_min_version = MBEDTLS_SSL_VERSION_TLS1_3; @@ -4071,7 +4075,9 @@ void reject_hrr_selecting_unoffered_group(void) */ TEST_EQUAL(mbedtls_ssl_handshake_step(&(client_ep.ssl)), 0); TEST_ASSERT(client_ep.ssl.state != MBEDTLS_SSL_SERVER_HELLO); +#if defined(MBEDTLS_DEBUG_C) TEST_EQUAL(cli_pattern.counter, 0); +#endif /* MBEDTLS_DEBUG_C */ } else { /* Invalid HRR selecting MBEDTLS_SSL_IANA_TLS_GROUP_X25519 group. * The client rejects it and aborts the handshake. @@ -4079,7 +4085,9 @@ void reject_hrr_selecting_unoffered_group(void) TEST_EQUAL(mbedtls_ssl_handshake_step(&(client_ep.ssl)), MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); +#if defined(MBEDTLS_DEBUG_C) TEST_EQUAL(cli_pattern.counter, 1); +#endif /* MBEDTLS_DEBUG_C */ } mbedtls_test_ssl_endpoint_free(&client_ep); mbedtls_test_ssl_endpoint_free(&server_ep); @@ -4090,7 +4098,9 @@ exit: mbedtls_test_ssl_endpoint_free(&server_ep); mbedtls_test_free_handshake_options(&client_options); mbedtls_test_free_handshake_options(&server_options); +#if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold(0); +#endif /* MBEDTLS_DEBUG_C */ MD_OR_USE_PSA_DONE(); } /* END_CASE */ From e2a6f05640528b1eff715824f3d931b81e7c911d Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Tue, 26 May 2026 10:17:11 +0100 Subject: [PATCH 016/168] ssl_write_supported_groups_ext: Updated documentation Signed-off-by: Minos Galanakis --- library/ssl_client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/ssl_client.c b/library/ssl_client.c index 7f0bb7d937..354fe9b72b 100644 --- a/library/ssl_client.c +++ b/library/ssl_client.c @@ -209,7 +209,8 @@ static int ssl_write_alpn_ext(mbedtls_ssl_context *ssl, * share the same extension identifier. * * If the TLS 1.3 logic for selecting proposed groups changes, the TLS 1.3 - * group filtering in this function must be kept in sync. + * group filtering in the function `ssl_tls13_parse_hrr_key_share_ext()` must + * be updated accordingly. * */ #define SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG 1 From 22dccc1d83ca3edee9e91861d57fa53a4c67760e Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 8 May 2026 12:22:12 +0200 Subject: [PATCH 017/168] Update framework with test certificate with basicConstraints overflow Signed-off-by: Gilles Peskine --- framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework b/framework index e92a819966..e0f6275eff 160000 --- a/framework +++ b/framework @@ -1 +1 @@ -Subproject commit e92a81996656d82941a9afce843453c57e1d51f5 +Subproject commit e0f6275eff2e45e295fdd6b6877de4cbdaddae83 From 6c8ae1ea48ffa29d5401171244737eb0bc7f4d9c Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 6 May 2026 22:29:22 +0200 Subject: [PATCH 018/168] Fix lax basicConstraints parsing When parsing the basicConstraints extension, reject junk after the SEQUENCE inside the extension (which is probably benign), and reject a SEQUENCE that extends beyond the extension (could be very dangerous). Add a non-regression test where a certificate that is technically malformed, but accepted as a leaf certificate by OpenSSL and other X.509 implementations, to be accepted as a CA certificate by Mbed TLS. Signed-off-by: Gilles Peskine --- ChangeLog.d/x509-crt-parse-basicConstraints.txt | 7 +++++++ library/x509_crt.c | 7 +++++++ tests/suites/test_suite_x509parse.data | 8 ++++++++ 3 files changed, 22 insertions(+) create mode 100644 ChangeLog.d/x509-crt-parse-basicConstraints.txt diff --git a/ChangeLog.d/x509-crt-parse-basicConstraints.txt b/ChangeLog.d/x509-crt-parse-basicConstraints.txt new file mode 100644 index 0000000000..c5b25f114b --- /dev/null +++ b/ChangeLog.d/x509-crt-parse-basicConstraints.txt @@ -0,0 +1,7 @@ +Security + * Fix a bug in the X.509 certificate parser that caused some inputs + with a malformed basicConstraints extension to be accepted. This + could have dangerous results, in particular causing some certificates + to be parsed as CA certificates when other X.509 implementations would + parse them as end-entity certificates. Reported by Mohammad Seet + (mhdsait101). CVE-2026-TODO diff --git a/library/x509_crt.c b/library/x509_crt.c index 3232760ea2..637ce7f336 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -515,6 +515,13 @@ static int x509_get_basic_constraints(unsigned char **p, return 0; } + if ((size_t) (end - *p) != len) { + /* Reject junk after the SEQUENCE inside the extension (which is + * probably benign), and reject a SEQUENCE that extends beyond + * the extension (could be very dangerous). */ + return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; + } + if ((ret = mbedtls_asn1_get_bool(p, end, ca_istrue)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { ret = mbedtls_asn1_get_int(p, end, ca_istrue); diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 5e91df9107..4f479fb30d 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -2052,6 +2052,14 @@ X509 CRT ASN1 (TBSCertificate v3, inv CertificatePolicies, policy qualifier leng depends_on:PSA_HAVE_ALG_SOME_RSA_VERIFY:PSA_WANT_ALG_SHA_256 x509parse_crt:"3081b030819aa0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092a864886f70d01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a314301230100603551d200409300730050601003001300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_OUT_OF_DATA) +X509 CRT ASN1: basicConstraints overflow would make CA=1 (bad signature) +depends_on:MBEDTLS_PK_CAN_ECDSA_SOME:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_MD_CAN_SHA256 +mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-constraints-sequence-overflow.badsign.crt":MBEDTLS_ERR_X509_INVALID_EXTENSIONS:0 + +X509 CRT ASN1: basicConstraints overflow would make CA=1 (good self signature) +depends_on:MBEDTLS_PK_CAN_ECDSA_SOME:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_MD_CAN_SHA256 +mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-constraints-sequence-overflow.selfsigned.crt":MBEDTLS_ERR_X509_INVALID_EXTENSIONS:0 + X509 CRT ASN1 (TBS, inv extBasicConstraint, no pathlen length) depends_on:PSA_HAVE_ALG_SOME_RSA_VERIFY:PSA_WANT_ALG_SHA_256 x509parse_crt:"3081b030819aa0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a314301230100603551d130101010406300402010102300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_OUT_OF_DATA) From b05434c1b1df14cb3b2ce52dd1200c3ba9f9b198 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 May 2026 16:32:09 +0200 Subject: [PATCH 019/168] Improve changelog wording Signed-off-by: Gilles Peskine --- .../ssl_tls13_prepare_new_session_ticket-psa_get_random.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog.d/ssl_tls13_prepare_new_session_ticket-psa_get_random.txt b/ChangeLog.d/ssl_tls13_prepare_new_session_ticket-psa_get_random.txt index 0fc8b0aa85..b020546b12 100644 --- a/ChangeLog.d/ssl_tls13_prepare_new_session_ticket-psa_get_random.txt +++ b/ChangeLog.d/ssl_tls13_prepare_new_session_ticket-psa_get_random.txt @@ -1,5 +1,5 @@ Security * Fix a bug where mbedtls_ssl_read() and mbedtls_ssl_write() could return - 1 instead of an error code if the random generator fails if a server - calls these functions before the end of a TLS 1.3 handshake. + 1 instead of an error code if the random generator failed when a server + called these functions before the end of a TLS 1.3 handshake. Reported by Mohammad Seet (mhdsait101). CVE-2026-40294 From baf449db7e31f031ed5def0fecf417122f72d3ee Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Fri, 1 May 2026 10:23:02 +0100 Subject: [PATCH 020/168] Added fix for Integer overflow using a large ECDHE Identity Signed-off-by: Ben Taylor --- library/ssl_tls12_client.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c index c101ccd91e..cbdffe88ad 100644 --- a/library/ssl_tls12_client.c +++ b/library/ssl_tls12_client.c @@ -2470,11 +2470,16 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) /* uint16 to store content length */ const size_t content_len_size = 2; + const size_t ecpoint_len_size = 1; + const size_t ecpoint_max_len = + PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(handshake->xxdh_psa_type, + handshake->xxdh_psa_bits); header_len = 4; - if (header_len + content_len_size + ssl->conf->psk_identity_len - > MBEDTLS_SSL_OUT_CONTENT_LEN) { + if (ecpoint_max_len > MBEDTLS_SSL_OUT_CONTENT_LEN - ecpoint_len_size || + header_len + content_len_size + ssl->conf->psk_identity_len + > MBEDTLS_SSL_OUT_CONTENT_LEN - ecpoint_len_size - ecpoint_max_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("psk identity too long or SSL buffer too short")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; From e71e49e634ba49b2b630f268bc8f0dd392751ec3 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Fri, 1 May 2026 10:26:49 +0100 Subject: [PATCH 021/168] Add ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/ecdh-psk-integer-overflow.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 ChangeLog.d/ecdh-psk-integer-overflow.txt diff --git a/ChangeLog.d/ecdh-psk-integer-overflow.txt b/ChangeLog.d/ecdh-psk-integer-overflow.txt new file mode 100644 index 0000000000..0c84914a45 --- /dev/null +++ b/ChangeLog.d/ecdh-psk-integer-overflow.txt @@ -0,0 +1,2 @@ +Bugfix + * Add fix for ecdh-psk integer overflow with large identity. From c058818451833a748da112e3b8129fd299480ceb Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Wed, 3 Jun 2026 08:26:17 +0100 Subject: [PATCH 022/168] Improve ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/ecdh-psk-integer-overflow.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog.d/ecdh-psk-integer-overflow.txt b/ChangeLog.d/ecdh-psk-integer-overflow.txt index 0c84914a45..c1b7f6affa 100644 --- a/ChangeLog.d/ecdh-psk-integer-overflow.txt +++ b/ChangeLog.d/ecdh-psk-integer-overflow.txt @@ -1,2 +1,2 @@ -Bugfix - * Add fix for ecdh-psk integer overflow with large identity. +Security + * Fix a remote buffer overflow in (D)TLS with ECDHE-PSK cipher suites when CBC is disabled. From c567299ee6bade9547a97d3ad1dcd5f3bd98ea6f Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Wed, 3 Jun 2026 09:44:12 +0100 Subject: [PATCH 023/168] Add in tests for ECDHE-PSK integer overflow Signed-off-by: Ben Taylor --- tests/ssl-opt.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 4a4ee4d1ef..9ab566944d 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -8382,6 +8382,37 @@ run_test "extKeyUsage cli-auth 1.3: codeSign -> fail (hard)" \ -s "Processing of the Certificate handshake message failed" # MBEDTLS_X509_BADCERT_EXT_KEY_USAGE -> MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT +# Miscellaneous PSK-related tests + +psk_identity_max_minus_10=a$(printf "%$((MAX_OUT_LEN - 11))s" z | tr ' ' .) + +run_test "Large PSK identity (MBEDTLS_SSL_OUT_CONTENT_LEN - 7)" \ + "$P_SRV debug_level=3 \ + psk_identity=${psk_identity_max_minus_10}987 psk=73776f726466697368" \ + "$P_CLI force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256 debug_level=3 \ + psk_identity=${psk_identity_max_minus_10}987 psk=73776f726466697368" \ + 1 \ + -s "! mbedtls_ssl_handshake returned" \ + -c "! mbedtls_ssl_handshake returned" + +run_test "Large PSK identity (MBEDTLS_SSL_OUT_CONTENT_LEN - 6)" \ + "$P_SRV debug_level=3 \ + psk_identity=${psk_identity_max_minus_10}9876 psk=73776f726466697368" \ + "$P_CLI force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256 debug_level=3 \ + psk_identity=${psk_identity_max_minus_10}9876 psk=73776f726466697368" \ + 1 \ + -s "! mbedtls_ssl_handshake returned" \ + -c "! mbedtls_ssl_handshake returned" + +run_test "Large PSK identity (MBEDTLS_SSL_OUT_CONTENT_LEN - 5)" \ + "$P_SRV debug_level=3 \ + psk_identity=${psk_identity_max_minus_10}98765 psk=73776f726466697368" \ + "$P_CLI force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256 debug_level=3 \ + psk_identity=${psk_identity_max_minus_10}98765 psk=73776f726466697368" \ + 1 \ + -s "! mbedtls_ssl_handshake returned" \ + -c "! mbedtls_ssl_handshake returned" + # Tests for PSK callback run_test "PSK callback: psk, no callback" \ From 0501e447cc19ed06b69daea5e17585e1294030cd Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Wed, 3 Jun 2026 10:38:21 +0100 Subject: [PATCH 024/168] Correct style of ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/ecdh-psk-integer-overflow.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog.d/ecdh-psk-integer-overflow.txt b/ChangeLog.d/ecdh-psk-integer-overflow.txt index c1b7f6affa..7d4b452275 100644 --- a/ChangeLog.d/ecdh-psk-integer-overflow.txt +++ b/ChangeLog.d/ecdh-psk-integer-overflow.txt @@ -1,2 +1,3 @@ Security - * Fix a remote buffer overflow in (D)TLS with ECDHE-PSK cipher suites when CBC is disabled. + * Fix a remote buffer overflow in (D)TLS with ECDHE-PSK cipher suites when + CBC is disabled. From ab2a7d5a3472f39190344f754e6cee5039fcba50 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 4 Jun 2026 14:20:18 +0100 Subject: [PATCH 025/168] Add reported by and CVE placeholder Signed-off-by: Ben Taylor --- ChangeLog.d/ecdh-psk-integer-overflow.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/ecdh-psk-integer-overflow.txt b/ChangeLog.d/ecdh-psk-integer-overflow.txt index 7d4b452275..8693dde60e 100644 --- a/ChangeLog.d/ecdh-psk-integer-overflow.txt +++ b/ChangeLog.d/ecdh-psk-integer-overflow.txt @@ -1,3 +1,3 @@ Security * Fix a remote buffer overflow in (D)TLS with ECDHE-PSK cipher suites when - CBC is disabled. + CBC is disabled. Reported by Karnakar Reddy. CVE-ID-TODO From a7c0d833547449868f12e40d22bc9e6cb6b24ec5 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Fri, 5 Jun 2026 10:22:49 +0100 Subject: [PATCH 026/168] Add improvements to ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/oob-key-exchange-restricted.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog.d/oob-key-exchange-restricted.txt b/ChangeLog.d/oob-key-exchange-restricted.txt index 794e294272..a0e698c077 100644 --- a/ChangeLog.d/oob-key-exchange-restricted.txt +++ b/ChangeLog.d/oob-key-exchange-restricted.txt @@ -1,3 +1,3 @@ -Bugfix +Security * Fix an out-of-bounds read in TLS 1.2 ECJPAKE ServerKeyExchange parsing. - Fixes #1590. + Reported-by Biniam Demissie From cc794d85013313040e678b5e63333c6426123e78 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 7 May 2026 20:29:11 +0200 Subject: [PATCH 027/168] Tighten CSR extensionRequest bounds Don't allow parts of a compound (SEQUENCE or SET) to go beyond the containing compound. The inline CSR regression test is derived from the existing "X509 CSR ASN.1 (OK)" DER test vector. In the extensionRequest attribute, the original well-formed fragment is: a029 3027 06092a864886f70d01090e 311a 3018 ... where 31 1a is the SET containing the Extensions sequence and 30 18 is the contained Extensions sequence. The malformed test changes only the SET length byte, from 1a to 19: a029 3027 06092a864886f70d01090e 3119 3018 ... The attribute SEQUENCE length and the inner Extensions sequence length are left unchanged. This makes the SET one byte too short for its containing attribute, so the parser must reject it with MBEDTLS_ERR_ASN1_LENGTH_MISMATCH instead of parsing the trailing byte as data outside the SET. There is no known security impact, just some risk reduction. Signed-off-by: Gilles Peskine --- .../x509-csr-extension-request-bounds.txt | 3 +++ library/x509_csr.c | 18 +++++++++++++++--- tests/suites/test_suite_x509parse.data | 12 ++++++++---- 3 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 ChangeLog.d/x509-csr-extension-request-bounds.txt diff --git a/ChangeLog.d/x509-csr-extension-request-bounds.txt b/ChangeLog.d/x509-csr-extension-request-bounds.txt new file mode 100644 index 0000000000..dfc706703c --- /dev/null +++ b/ChangeLog.d/x509-csr-extension-request-bounds.txt @@ -0,0 +1,3 @@ +Bugfix + * Reject malformed X.509 CSRs where the extensionRequest attribute + wrappers do not exactly contain the requested extensions. diff --git a/library/x509_csr.c b/library/x509_csr.c index 3e8e407b26..45b7b8f9ac 100644 --- a/library/x509_csr.c +++ b/library/x509_csr.c @@ -227,18 +227,30 @@ static int x509_csr_parse_attributes(mbedtls_x509_csr *csr, /* Check that this is an extension-request attribute */ if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, &attr_oid) == 0) { - if ((ret = mbedtls_asn1_get_tag(p, end, &len, + if ((ret = mbedtls_asn1_get_tag(p, end_attr_data, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } - if ((ret = mbedtls_asn1_get_tag(p, end, &len, + const unsigned char *end_set = *p + len; + if (end_set != end_attr_data) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + if ((ret = mbedtls_asn1_get_tag(p, end_set, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } - if ((ret = x509_csr_parse_extensions(csr, p, *p + len, cb, p_ctx)) != 0) { + const unsigned char *end_exts = *p + len; + if (end_exts != end_set) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + if ((ret = x509_csr_parse_extensions(csr, p, end_exts, cb, p_ctx)) != 0) { return ret; } diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 4f479fb30d..bb91cd1788 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -2955,6 +2955,10 @@ X509 CSR ASN.1 (OK) depends_on:PSA_HAVE_ALG_SOME_ECDSA:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_1:!MBEDTLS_X509_REMOVE_INFO mbedtls_x509_csr_parse:"308201183081bf0201003034310b3009060355040613024e4c3111300f060355040a1308506f6c617253534c31123010060355040313096c6f63616c686f73743059301306072a8648ce3d020106082a8648ce3d0301070342000437cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f768225962924ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edffa029302706092a864886f70d01090e311a301830090603551d1304023000300b0603551d0f0404030205e0300906072a8648ce3d04010349003046022100b49fd8c8f77abfa871908dfbe684a08a793d0f490a43d86fcf2086e4f24bb0c2022100f829d5ccd3742369299e6294394717c4b723a0f68b44e831b6e6c3bcabf97243":"CSR version \: 1\nsubject name \: C=NL, O=PolarSSL, CN=localhost\nsigned using \: ECDSA with SHA1\nEC key size \: 256 bits\n\nkey usage \: Digital Signature, Non Repudiation, Key Encipherment\n":0 +X509 CSR ASN.1 (extensionRequest SET length too short) +depends_on:MBEDTLS_PK_CAN_ECDSA_SOME:MBEDTLS_ECP_HAVE_SECP256R1 +mbedtls_x509_csr_parse:"308201183081bf0201003034310b3009060355040613024e4c3111300f060355040a1308506f6c617253534c31123010060355040313096c6f63616c686f73743059301306072a8648ce3d020106082a8648ce3d0301070342000437cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f768225962924ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edffa029302706092a864886f70d01090e3119301830090603551d1304023000300b0603551d0f0404030205e0300906072a8648ce3d04010349003046022100b49fd8c8f77abfa871908dfbe684a08a793d0f490a43d86fcf2086e4f24bb0c2022100f829d5ccd3742369299e6294394717c4b723a0f68b44e831b6e6c3bcabf97243":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS+MBEDTLS_ERR_ASN1_LENGTH_MISMATCH + X509 CSR ASN.1 (Unsupported critical extension, critical=true) depends_on:PSA_HAVE_ALG_SOME_ECDSA:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:!MBEDTLS_X509_REMOVE_INFO mbedtls_x509_csr_parse:"308201233081cb02010030413119301706035504030c1053656c66207369676e65642074657374310b300906035504061302444531173015060355040a0c0e41757468437274444220546573743059301306072a8648ce3d020106082a8648ce3d03010703420004c11ebb9951848a436ca2c8a73382f24bbb6c28a92e401d4889b0c361f377b92a8b0497ff2f5a5f6057ae85f704ab1850bef075914f68ed3aeb15a1ff1ebc0dc6a028302606092a864886f70d01090e311930173015060b2b0601040183890c8622020101ff0403010101300a06082a8648ce3d040302034700304402200c4108fd098525993d3fd5b113f0a1ead8750852baf55a2f8e670a22cabc0ba1022034db93a0fcb993912adcf2ea8cb4b66389af30e264d43c0daea03255e45d2ccc":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) @@ -3090,17 +3094,17 @@ X509 CSR ASN.1 (attributes: invalid len (len > data)) depends_on:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_SOME_RSA_VERIFY mbedtls_x509_csr_parse_file:"../framework/data_files/parse_input/test_csr_v3_all_malformed_attributes_len1.csr.der":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_OUT_OF_DATA) -X509 CSR ASN.1 (attributes: invalid len (len < data)) +X509 CSR ASN.1 (attributes: extensionRequest SET extends past attribute) depends_on:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_SOME_RSA_VERIFY -mbedtls_x509_csr_parse_file:"../framework/data_files/parse_input/test_csr_v3_all_malformed_attributes_len2.csr.der":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) +mbedtls_x509_csr_parse_file:"../framework/data_files/parse_input/test_csr_v3_all_malformed_attributes_len2.csr.der":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_OUT_OF_DATA) X509 CSR ASN.1 (attributes: extension request invalid len (len > data)) depends_on:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_SOME_RSA_VERIFY mbedtls_x509_csr_parse_file:"../framework/data_files/parse_input/test_csr_v3_all_malformed_attributes_extension_request_sequence_len1.csr.der":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_OUT_OF_DATA) -X509 CSR ASN.1 (attributes: extension request invalid len (len < data)) +X509 CSR ASN.1 (attributes: extensionRequest sequence shorter than SET) depends_on:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_SOME_RSA_VERIFY -mbedtls_x509_csr_parse_file:"../framework/data_files/parse_input/test_csr_v3_all_malformed_attributes_extension_request_sequence_len2.csr.der":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_OUT_OF_DATA) +mbedtls_x509_csr_parse_file:"../framework/data_files/parse_input/test_csr_v3_all_malformed_attributes_extension_request_sequence_len2.csr.der":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) X509 CSR ASN.1 (extensions: invalid sequence tag) depends_on:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_SOME_RSA_VERIFY From eb051b501a1ed2d772cc26eccb20e54cf15e2b11 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 7 May 2026 20:59:00 +0200 Subject: [PATCH 028/168] Remove unreachable CSR extensionRequest check It is now unreachable because: - end_set == end_attr_data is enforced at library/x509_csr.c:236. - end_exts == end_set is enforced at library/x509_csr.c:248. - x509_csr_parse_extensions() only returns success if *p == end_exts, enforced at library/x509_csr.c:188. So after a successful x509_csr_parse_extensions() call, *p == end_exts == end_set == end_attr_data. The condition at line 257 cannot be true. Signed-off-by: Gilles Peskine --- library/x509_csr.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/library/x509_csr.c b/library/x509_csr.c index 45b7b8f9ac..28a4560c43 100644 --- a/library/x509_csr.c +++ b/library/x509_csr.c @@ -253,11 +253,8 @@ static int x509_csr_parse_attributes(mbedtls_x509_csr *csr, if ((ret = x509_csr_parse_extensions(csr, p, end_exts, cb, p_ctx)) != 0) { return ret; } - - if (*p != end_attr_data) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } + /* x509_csr_parse_extensions() guarantees *p == end_exts + * on success */ } *p = end_attr_data; From 5cc6fb22c63ecf946920bce3d5185baf03ab9559 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 12 May 2026 17:14:02 +0200 Subject: [PATCH 029/168] basicConstraints pathLenConstraint tests: use standard cA type In test cases for pathLenConstraint parsing in a basicConstraints extension of an X.509 certificate, use the standard type for the leading cA field, namely BOOLEAN. The test data was encoding that field as INTEGER, which was accepted as a deviation from the standard since XySSL 0.9. Signed-off-by: Gilles Peskine --- tests/suites/test_suite_x509parse.data | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index bb91cd1788..ff4ecaedc1 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -2062,7 +2062,7 @@ mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-c X509 CRT ASN1 (TBS, inv extBasicConstraint, no pathlen length) depends_on:PSA_HAVE_ALG_SOME_RSA_VERIFY:PSA_WANT_ALG_SHA_256 -x509parse_crt:"3081b030819aa0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a314301230100603551d130101010406300402010102300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_OUT_OF_DATA) +x509parse_crt:"3081b030819aa0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a314301230100603551d13010101040630040101ff02300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_OUT_OF_DATA) X509 CRT ASN1 (inv extBasicConstraint, pathlen is INT_MAX) depends_on:PSA_HAVE_ALG_SOME_RSA_VERIFY:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_SHA_1 @@ -2074,19 +2074,19 @@ mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server1_pathlen X509 CRT ASN1 (TBS, inv extBasicConstraint, pathlen inv length encoding) depends_on:PSA_HAVE_ALG_SOME_RSA_VERIFY:PSA_WANT_ALG_SHA_256 -x509parse_crt:"3081b130819ba0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a315301330110603551d13010101040730050201010285300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_LENGTH) +x509parse_crt:"3081b130819ba0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a315301330110603551d13010101040730050101ff0285300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_LENGTH) X509 CRT ASN1 (TBS, inv extBasicConstraint, pathlen length out of bounds) depends_on:PSA_HAVE_ALG_SOME_RSA_VERIFY:PSA_WANT_ALG_SHA_256 -x509parse_crt:"3081b130819ba0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a315301330110603551d13010101040730050201010201300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_OUT_OF_DATA) +x509parse_crt:"3081b130819ba0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a315301330110603551d13010101040730050101ff0201300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_OUT_OF_DATA) X509 CRT ASN1 (TBS, inv extBasicConstraint, pathlen empty) depends_on:PSA_HAVE_ALG_SOME_RSA_VERIFY:PSA_WANT_ALG_SHA_256 -x509parse_crt:"3081b130819ba0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a315301330110603551d13010101040730050201010200300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_LENGTH) +x509parse_crt:"3081b130819ba0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a315301330110603551d13010101040730050101ff0200300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_LENGTH) X509 CRT ASN1 (TBS, inv extBasicConstraint, pathlen length mismatch) depends_on:PSA_HAVE_ALG_SOME_RSA_VERIFY:PSA_WANT_ALG_SHA_256 -x509parse_crt:"3081b430819ea0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a318301630140603551d13010101040a30080201010201010500300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) +x509parse_crt:"3081b430819ea0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a318301630140603551d13010101040a30080101ff0201010500300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) X509 CRT ASN1 (TBS, inv v3Ext, ExtKeyUsage bad second tag) depends_on:PSA_HAVE_ALG_SOME_RSA_VERIFY:PSA_WANT_ALG_SHA_256 From 0d6060d644903b84dffc12378f4d8322fa4e0af5 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 12 May 2026 17:06:18 +0200 Subject: [PATCH 030/168] Stop accepting basicConstraints with only pathLenConstraint In an X.509 certificate, a basicConstraints extension where the cA field (BOOLEAN) is omitted but the pathLenConstraint field (INTEGER )is present is syntactically valid, but RFC 5280 states that CAs MUST NOT emit such a certificate. Historically, since XySSL 0.9 in 2008, if a basicConstraints extension started with an INTEGER field, we interpreted that field as a cA value. This was a deliberate change: > Fixed x509_get_ext() to accept some rare certificates (like > www.openssl.org:443) which have an INTEGER instead of a BOOLEAN for > Extension::BasicConstraints::cA. However, 18 years later, this does not seem to be relevant, and the details seem to have been lost. Furthermore, major implementations follow RFC 5280 and interpret `SEQUENCE { INTEGER n }` with cA being set to its default value (FALSE) and pathLenConstraint set to `n`. This means that such a certificate with n != 0 would be interpreted as a CA certificate in Mbed TLS but as a leaf certificate elsewhere, which is dangerous. Since CAs are not supposed to emit such certificates, stop accepting them altogether. Signed-off-by: Gilles Peskine --- library/x509_crt.c | 26 +++++++++++++++----------- tests/suites/test_suite_x509parse.data | 8 ++++++++ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index 637ce7f336..093d733c1c 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -512,6 +512,7 @@ static int x509_get_basic_constraints(unsigned char **p, } if (*p == end) { + /* Empty basicConstraints: valid, not a CA. */ return 0; } @@ -523,18 +524,21 @@ static int x509_get_basic_constraints(unsigned char **p, } if ((ret = mbedtls_asn1_get_bool(p, end, ca_istrue)) != 0) { - if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - ret = mbedtls_asn1_get_int(p, end, ca_istrue); - } - - if (ret != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - if (*ca_istrue != 0) { - *ca_istrue = 1; - } + /* If the SEQUENCE starts with an INTEGER and not a BOOLEAN, + * according to RFC 5280, it's syntactically valid, but it's + * something that a CA MUST NOT produce. So we reject it. + * + * Note: historically, from XySSL 0.9 to Mbed TLS 3.6.6/4.1.0, + * `SEQUENCE { INTEGER n }` was interpreted as cA=FALSE if n == 0 + * and cA=TRUE if n != 0. This was dangerous since + * `SEQUENCE { INTEGER n }` should be parsed as cA=FALSE + * according to RFC 5280, so we stopped doing it. + */ + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } + /* `SEQUENCE { BOOLEAN FALSE }` is not DER since default-value fields + * must be omitted in DER. But it seems harmless, and Mbed TLS has + * always accepted it, so we continue to accept it. */ if (*p == end) { return 0; diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index ff4ecaedc1..a2e3e9c67e 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -2060,6 +2060,14 @@ X509 CRT ASN1: basicConstraints overflow would make CA=1 (good self signature) depends_on:MBEDTLS_PK_CAN_ECDSA_SOME:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_MD_CAN_SHA256 mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-constraints-sequence-overflow.selfsigned.crt":MBEDTLS_ERR_X509_INVALID_EXTENSIONS:0 +X509 CRT ASN1: basicConstraints: no cA but pathLenConstraint (bad signature) +depends_on:MBEDTLS_PK_CAN_ECDSA_SOME:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_MD_CAN_SHA256 +mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-constraints-integer-first.badsign.crt":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG):0 + +X509 CRT ASN1: basicConstraints: no cA but pathLenConstraint (good self signature) +depends_on:MBEDTLS_PK_CAN_ECDSA_SOME:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_MD_CAN_SHA256 +mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-constraints-integer-first.selfsigned.crt":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG):0 + X509 CRT ASN1 (TBS, inv extBasicConstraint, no pathlen length) depends_on:PSA_HAVE_ALG_SOME_RSA_VERIFY:PSA_WANT_ALG_SHA_256 x509parse_crt:"3081b030819aa0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a314301230100603551d13010101040630040101ff02300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_OUT_OF_DATA) From 045cede1b88195ab9ed0e3458aef9bdab48d4882 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 12 May 2026 17:21:48 +0200 Subject: [PATCH 031/168] basicConstraints with leading INTEGER field: document the behavior change Announce the security fix together with the overflow fix, since the two bugs are pretty much indistinguishable from a black-box perspective, despite being due to independent problems in the code. Signed-off-by: Gilles Peskine --- ChangeLog.d/x509-crt-parse-basicConstraints.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog.d/x509-crt-parse-basicConstraints.txt b/ChangeLog.d/x509-crt-parse-basicConstraints.txt index c5b25f114b..4fd450e18e 100644 --- a/ChangeLog.d/x509-crt-parse-basicConstraints.txt +++ b/ChangeLog.d/x509-crt-parse-basicConstraints.txt @@ -1,7 +1,15 @@ Security - * Fix a bug in the X.509 certificate parser that caused some inputs + * Fix two bugs in the X.509 certificate parser that caused some inputs with a malformed basicConstraints extension to be accepted. This could have dangerous results, in particular causing some certificates to be parsed as CA certificates when other X.509 implementations would parse them as end-entity certificates. Reported by Mohammad Seet (mhdsait101). CVE-2026-TODO + +Changes + * X.509 certificates with a basicConstraints extension starting with an + INTEGER field are no longer accepted. According to RFC 5280, such + certificates are syntactically valid and the first field is the + pathLenConstraint value, but certificate authorities must not emit such + certificates. Mbed TLS interpreted it as a cA value, which was nonstandard + and dangerous. From f624adff2ec306b63fc2d604b6c97ae2a647129b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 27 May 2026 12:29:51 +0200 Subject: [PATCH 032/168] Switch to MBEDTLS_ERROR_ADD for combining X509 and ASN1 error codes Since Mbed TLS 4.0, this is just the low-level error code. But keep the combination for uniformity with the rest of the file, and to reduce the differences with the 3.6 branch. Signed-off-by: Gilles Peskine --- tests/suites/test_suite_x509parse.data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index a2e3e9c67e..d0314753bf 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -2965,7 +2965,7 @@ mbedtls_x509_csr_parse:"308201183081bf0201003034310b3009060355040613024e4c311130 X509 CSR ASN.1 (extensionRequest SET length too short) depends_on:MBEDTLS_PK_CAN_ECDSA_SOME:MBEDTLS_ECP_HAVE_SECP256R1 -mbedtls_x509_csr_parse:"308201183081bf0201003034310b3009060355040613024e4c3111300f060355040a1308506f6c617253534c31123010060355040313096c6f63616c686f73743059301306072a8648ce3d020106082a8648ce3d0301070342000437cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f768225962924ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edffa029302706092a864886f70d01090e3119301830090603551d1304023000300b0603551d0f0404030205e0300906072a8648ce3d04010349003046022100b49fd8c8f77abfa871908dfbe684a08a793d0f490a43d86fcf2086e4f24bb0c2022100f829d5ccd3742369299e6294394717c4b723a0f68b44e831b6e6c3bcabf97243":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS+MBEDTLS_ERR_ASN1_LENGTH_MISMATCH +mbedtls_x509_csr_parse:"308201183081bf0201003034310b3009060355040613024e4c3111300f060355040a1308506f6c617253534c31123010060355040313096c6f63616c686f73743059301306072a8648ce3d020106082a8648ce3d0301070342000437cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f768225962924ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edffa029302706092a864886f70d01090e3119301830090603551d1304023000300b0603551d0f0404030205e0300906072a8648ce3d04010349003046022100b49fd8c8f77abfa871908dfbe684a08a793d0f490a43d86fcf2086e4f24bb0c2022100f829d5ccd3742369299e6294394717c4b723a0f68b44e831b6e6c3bcabf97243":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) X509 CSR ASN.1 (Unsupported critical extension, critical=true) depends_on:PSA_HAVE_ALG_SOME_ECDSA:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:!MBEDTLS_X509_REMOVE_INFO From 402592db1d6b2763ee433a4169748b57adce7f7f Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 27 May 2026 15:44:01 +0200 Subject: [PATCH 033/168] Update dependencies in forward port from 3.6 Signed-off-by: Gilles Peskine --- tests/suites/test_suite_x509parse.data | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index d0314753bf..63f4c0daa9 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -2053,19 +2053,19 @@ depends_on:PSA_HAVE_ALG_SOME_RSA_VERIFY:PSA_WANT_ALG_SHA_256 x509parse_crt:"3081b030819aa0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092a864886f70d01010105000319003016021100ffffffffffffffffffffffffffffffff020103a100a200a314301230100603551d200409300730050601003001300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_OUT_OF_DATA) X509 CRT ASN1: basicConstraints overflow would make CA=1 (bad signature) -depends_on:MBEDTLS_PK_CAN_ECDSA_SOME:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_MD_CAN_SHA256 +depends_on:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-constraints-sequence-overflow.badsign.crt":MBEDTLS_ERR_X509_INVALID_EXTENSIONS:0 X509 CRT ASN1: basicConstraints overflow would make CA=1 (good self signature) -depends_on:MBEDTLS_PK_CAN_ECDSA_SOME:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_MD_CAN_SHA256 +depends_on:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-constraints-sequence-overflow.selfsigned.crt":MBEDTLS_ERR_X509_INVALID_EXTENSIONS:0 X509 CRT ASN1: basicConstraints: no cA but pathLenConstraint (bad signature) -depends_on:MBEDTLS_PK_CAN_ECDSA_SOME:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_MD_CAN_SHA256 +depends_on:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-constraints-integer-first.badsign.crt":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG):0 X509 CRT ASN1: basicConstraints: no cA but pathLenConstraint (good self signature) -depends_on:MBEDTLS_PK_CAN_ECDSA_SOME:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_MD_CAN_SHA256 +depends_on:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-constraints-integer-first.selfsigned.crt":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG):0 X509 CRT ASN1 (TBS, inv extBasicConstraint, no pathlen length) @@ -2964,7 +2964,7 @@ depends_on:PSA_HAVE_ALG_SOME_ECDSA:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_1:! mbedtls_x509_csr_parse:"308201183081bf0201003034310b3009060355040613024e4c3111300f060355040a1308506f6c617253534c31123010060355040313096c6f63616c686f73743059301306072a8648ce3d020106082a8648ce3d0301070342000437cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f768225962924ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edffa029302706092a864886f70d01090e311a301830090603551d1304023000300b0603551d0f0404030205e0300906072a8648ce3d04010349003046022100b49fd8c8f77abfa871908dfbe684a08a793d0f490a43d86fcf2086e4f24bb0c2022100f829d5ccd3742369299e6294394717c4b723a0f68b44e831b6e6c3bcabf97243":"CSR version \: 1\nsubject name \: C=NL, O=PolarSSL, CN=localhost\nsigned using \: ECDSA with SHA1\nEC key size \: 256 bits\n\nkey usage \: Digital Signature, Non Repudiation, Key Encipherment\n":0 X509 CSR ASN.1 (extensionRequest SET length too short) -depends_on:MBEDTLS_PK_CAN_ECDSA_SOME:MBEDTLS_ECP_HAVE_SECP256R1 +depends_on:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_WANT_ECC_SECP_R1_256 mbedtls_x509_csr_parse:"308201183081bf0201003034310b3009060355040613024e4c3111300f060355040a1308506f6c617253534c31123010060355040313096c6f63616c686f73743059301306072a8648ce3d020106082a8648ce3d0301070342000437cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f768225962924ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edffa029302706092a864886f70d01090e3119301830090603551d1304023000300b0603551d0f0404030205e0300906072a8648ce3d04010349003046022100b49fd8c8f77abfa871908dfbe684a08a793d0f490a43d86fcf2086e4f24bb0c2022100f829d5ccd3742369299e6294394717c4b723a0f68b44e831b6e6c3bcabf97243":"":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) X509 CSR ASN.1 (Unsupported critical extension, critical=true) From ca89089968098aa8798281878c5fc4fe0df9194b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 Jun 2026 18:23:42 +0200 Subject: [PATCH 034/168] Add attribution for the second bug Signed-off-by: Gilles Peskine --- ChangeLog.d/x509-crt-parse-basicConstraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/x509-crt-parse-basicConstraints.txt b/ChangeLog.d/x509-crt-parse-basicConstraints.txt index 4fd450e18e..30ee25a785 100644 --- a/ChangeLog.d/x509-crt-parse-basicConstraints.txt +++ b/ChangeLog.d/x509-crt-parse-basicConstraints.txt @@ -4,7 +4,7 @@ Security could have dangerous results, in particular causing some certificates to be parsed as CA certificates when other X.509 implementations would parse them as end-entity certificates. Reported by Mohammad Seet - (mhdsait101). CVE-2026-TODO + (mhdsait101) and Pablo Ruiz García. CVE-2026-TODO Changes * X.509 certificates with a basicConstraints extension starting with an From e94a7a2d228956f6c929e1d8b3758dd95fb8acb5 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 Jun 2026 18:24:04 +0200 Subject: [PATCH 035/168] Add CVE-ID Signed-off-by: Gilles Peskine --- ChangeLog.d/x509-crt-parse-basicConstraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/x509-crt-parse-basicConstraints.txt b/ChangeLog.d/x509-crt-parse-basicConstraints.txt index 30ee25a785..a67f992ab5 100644 --- a/ChangeLog.d/x509-crt-parse-basicConstraints.txt +++ b/ChangeLog.d/x509-crt-parse-basicConstraints.txt @@ -4,7 +4,7 @@ Security could have dangerous results, in particular causing some certificates to be parsed as CA certificates when other X.509 implementations would parse them as end-entity certificates. Reported by Mohammad Seet - (mhdsait101) and Pablo Ruiz García. CVE-2026-TODO + (mhdsait101) and Pablo Ruiz García. CVE-2026-49300 Changes * X.509 certificates with a basicConstraints extension starting with an From 4b32430d3c0123654ad6f6fbb208e955c24579ec Mon Sep 17 00:00:00 2001 From: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> Date: Mon, 8 Jun 2026 15:13:02 +0100 Subject: [PATCH 036/168] Improve the wording of the ChangeLog Co-authored-by: Ronald Cron Signed-off-by: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> --- ChangeLog.d/oob-key-exchange-restricted.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/oob-key-exchange-restricted.txt b/ChangeLog.d/oob-key-exchange-restricted.txt index a0e698c077..a4bfe738b2 100644 --- a/ChangeLog.d/oob-key-exchange-restricted.txt +++ b/ChangeLog.d/oob-key-exchange-restricted.txt @@ -1,3 +1,3 @@ Security - * Fix an out-of-bounds read in TLS 1.2 ECJPAKE ServerKeyExchange parsing. + * Fix an out-of-bounds read when parsing TLS 1.2 ECJPAKE ServerKeyExchange messages. Reported-by Biniam Demissie From 5e04a328403e760e821fe4365bad02a14d6f8f22 Mon Sep 17 00:00:00 2001 From: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> Date: Mon, 8 Jun 2026 15:13:37 +0100 Subject: [PATCH 037/168] Add CVE to ChangeLog Co-authored-by: Ronald Cron Signed-off-by: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> --- ChangeLog.d/oob-key-exchange-restricted.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog.d/oob-key-exchange-restricted.txt b/ChangeLog.d/oob-key-exchange-restricted.txt index a4bfe738b2..62e613648b 100644 --- a/ChangeLog.d/oob-key-exchange-restricted.txt +++ b/ChangeLog.d/oob-key-exchange-restricted.txt @@ -1,3 +1,4 @@ Security * Fix an out-of-bounds read when parsing TLS 1.2 ECJPAKE ServerKeyExchange messages. - Reported-by Biniam Demissie + Reported-by Biniam Demissie. + CVE-2026-50588 From f5675fd06442dbf9d11dfdd78a5d99657de8b12f Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 7 May 2026 17:23:55 +0100 Subject: [PATCH 038/168] Add test for leak Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.data | 4 ++ tests/suites/test_suite_ssl.function | 91 ++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 881d502ed5..f21fb55bcc 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3549,3 +3549,7 @@ send_invalid_sig_alg:MBEDTLS_SSL_SIG_ECDSA:MBEDTLS_SSL_HASH_SHA512:0 Negative Test: Server using sig_alg not offered by the client - ECDSA with SHA512 depends_on:MBEDTLS_CAN_HANDLE_ECDSA_TEST_KEY:MBEDTLS_CAN_HANDLE_ECDSA_CLIENT_TEST_KEY:PSA_WANT_ALG_SHA_512 send_invalid_sig_alg:MBEDTLS_SSL_SIG_ECDSA:MBEDTLS_SSL_HASH_SHA512:MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER + +TLS 1.2 NewSessionTicket: failing ticket callback leaves lifetime unset +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY +write_new_session_ticket_mem diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 39457c9047..a93904a2b6 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -25,6 +25,36 @@ #define TEST_EARLY_DATA_NO_INITIAL_ALPN 6 #define TEST_EARLY_DATA_NO_LATER_ALPN 7 +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) && \ + defined(PSA_HAVE_ALG_SOME_RSA_SIGN) && \ + defined(PSA_WANT_ECC_SECP_R1_384) && \ + defined(PSA_WANT_ALG_SHA_256) && \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ + defined(MBEDTLS_CAN_HANDLE_RSA_TEST_KEY) +static int failing_ticket_write_unset_lifetime( + void *p_ticket, const mbedtls_ssl_session *session, + unsigned char *start, const unsigned char *end, + size_t *tlen, uint32_t *lifetime) +{ + ((void) p_ticket); + ((void) session); + ((void) start); + ((void) end); + ((void) tlen); + ((void) lifetime); + + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_SESSION_TICKETS && + MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SRV_C && + MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED && + PSA_HAVE_ALG_SOME_RSA_SIGN && PSA_WANT_ECC_SECP_R1_384 && + PSA_WANT_ALG_SHA_256 && PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY && + MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */ + #if (!defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \ defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) && \ defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_DEBUG_C) && \ @@ -6350,3 +6380,64 @@ exit: PSA_DONE(); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */ +void write_new_session_ticket_mem() +{ + enum { BUFFSIZE = 1024 }; + mbedtls_test_ssl_endpoint server_ep, client_ep; + mbedtls_test_handshake_test_options options; + int ret = -1; + + memset(&server_ep, 0, sizeof(server_ep)); + memset(&client_ep, 0, sizeof(client_ep)); + mbedtls_test_init_handshake_options(&options); + + options.pk_alg = MBEDTLS_PK_RSA; + options.client_min_version = MBEDTLS_SSL_VERSION_TLS1_2; + options.client_max_version = MBEDTLS_SSL_VERSION_TLS1_2; + options.server_min_version = MBEDTLS_SSL_VERSION_TLS1_2; + options.server_max_version = MBEDTLS_SSL_VERSION_TLS1_2; + + MD_OR_USE_PSA_INIT(); + + ret = mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, + &options); + TEST_EQUAL(ret, 0); + + mbedtls_ssl_conf_session_tickets_cb(&server_ep.conf, + failing_ticket_write_unset_lifetime, + mbedtls_test_ticket_parse, + NULL); + + ret = mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, + &options); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_mock_socket_connect(&(server_ep.socket), + &(client_ep.socket), + BUFFSIZE); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_move_handshake_to_state(&(server_ep.ssl), + &(client_ep.ssl), + MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC); + TEST_EQUAL(ret, 0); + + ret = mbedtls_ssl_handshake_step(&(server_ep.ssl)); + TEST_EQUAL(ret, 0); + +#if defined(MBEDTLS_TEST_HAVE_MSAN) + { + volatile unsigned char lifetime_byte = server_ep.ssl.out_msg[4]; + TEST_ASSERT(lifetime_byte != 0xff); + } +#endif + +exit: + mbedtls_test_ssl_endpoint_free(&client_ep); + mbedtls_test_ssl_endpoint_free(&server_ep); + mbedtls_test_free_handshake_options(&options); + MD_OR_USE_PSA_DONE(); +} +/* END_CASE */ From a5c2e02198433b4808c500bd8f5e77bd07d82bf1 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 7 May 2026 17:24:50 +0100 Subject: [PATCH 039/168] Add fix for leak Signed-off-by: Ben Taylor --- library/ssl_tls12_server.c | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index 884c8fd4a4..a1fa442b7a 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -3396,6 +3396,7 @@ static int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl) &tlen, &lifetime)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_ticket_write", ret); tlen = 0; + lifetime = 0; } MBEDTLS_PUT_UINT32_BE(lifetime, ssl->out_msg, 4); From 38185e2308d201d7dfd05aa0032636440bdd1bfa Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 1 Jun 2026 14:56:20 +0100 Subject: [PATCH 040/168] Improve robustness of tlen and lifetime variables Signed-off-by: Ben Taylor --- library/ssl_tls12_server.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index a1fa442b7a..328e25aafc 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -3367,8 +3367,8 @@ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t tlen; - uint32_t lifetime; + size_t tlen = 0; + uint32_t lifetime = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write new session ticket")); @@ -3395,8 +3395,6 @@ static int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl) ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, &tlen, &lifetime)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_ticket_write", ret); - tlen = 0; - lifetime = 0; } MBEDTLS_PUT_UINT32_BE(lifetime, ssl->out_msg, 4); From 33c55a90e323620dbe67f0074668af8484c74960 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 8 Jun 2026 15:32:26 +0100 Subject: [PATCH 041/168] Improve test of non-initilisation of lifetime Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.function | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index a93904a2b6..34c4d89e00 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6427,12 +6427,13 @@ void write_new_session_ticket_mem() ret = mbedtls_ssl_handshake_step(&(server_ep.ssl)); TEST_EQUAL(ret, 0); -#if defined(MBEDTLS_TEST_HAVE_MSAN) - { - volatile unsigned char lifetime_byte = server_ep.ssl.out_msg[4]; - TEST_ASSERT(lifetime_byte != 0xff); - } -#endif + /* Force a read of the lifetime value from the outgoing message. + * This is a non-regression test for a bug where the lifetime was set from + * uninitialized memory. + * The read here causes MSan and Valgrind to complain if the bug isn't fixed. + */ + volatile unsigned char lifetime = MBEDTLS_GET_UINT32_BE(server_ep.ssl.out_msg + 4); + (void) lifetime; exit: mbedtls_test_ssl_endpoint_free(&client_ep); From 0c62b498bdc54cf56ed4b4198d766e76edf9153a Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 8 Jun 2026 15:46:00 +0100 Subject: [PATCH 042/168] Add ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/fix-info-leak-in-ssl.txt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 ChangeLog.d/fix-info-leak-in-ssl.txt diff --git a/ChangeLog.d/fix-info-leak-in-ssl.txt b/ChangeLog.d/fix-info-leak-in-ssl.txt new file mode 100644 index 0000000000..2a0309fc40 --- /dev/null +++ b/ChangeLog.d/fix-info-leak-in-ssl.txt @@ -0,0 +1,6 @@ +Security + * Fix a potential information disclosure in TLS 1.2 servers using session + tickets. If the session ticket write callback failed without setting the + lifetime output parameter, Mbed TLS could send 4 bytes of uninitialized + stack memory to the peer in the NewSessionTicket message. Fixes #1570. + Reported by James Love. CVE-2026-50586. From 911b9b67dbf335f79253c2b66acc9767e34b3105 Mon Sep 17 00:00:00 2001 From: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> Date: Mon, 8 Jun 2026 15:48:14 +0100 Subject: [PATCH 043/168] Add CVE ID to ChangeLog Co-authored-by: Gilles Peskine Signed-off-by: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> --- ChangeLog.d/ecdh-psk-integer-overflow.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/ecdh-psk-integer-overflow.txt b/ChangeLog.d/ecdh-psk-integer-overflow.txt index 8693dde60e..47dfd428de 100644 --- a/ChangeLog.d/ecdh-psk-integer-overflow.txt +++ b/ChangeLog.d/ecdh-psk-integer-overflow.txt @@ -1,3 +1,3 @@ Security * Fix a remote buffer overflow in (D)TLS with ECDHE-PSK cipher suites when - CBC is disabled. Reported by Karnakar Reddy. CVE-ID-TODO + CBC is disabled. Reported by Karnakar Reddy. CVE-2026-50580 From cecb4c21628d62290b4d1498ebd43ea8ee75fa53 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Wed, 10 Jun 2026 08:21:05 +0100 Subject: [PATCH 044/168] Correct ChangeLog style Signed-off-by: Ben Taylor --- ChangeLog.d/oob-key-exchange-restricted.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog.d/oob-key-exchange-restricted.txt b/ChangeLog.d/oob-key-exchange-restricted.txt index 62e613648b..6a250644b9 100644 --- a/ChangeLog.d/oob-key-exchange-restricted.txt +++ b/ChangeLog.d/oob-key-exchange-restricted.txt @@ -1,4 +1,4 @@ Security - * Fix an out-of-bounds read when parsing TLS 1.2 ECJPAKE ServerKeyExchange messages. - Reported-by Biniam Demissie. + * Fix an out-of-bounds read when parsing TLS 1.2 ECJPAKE ServerKeyExchange + messages. Reported-by Biniam Demissie. CVE-2026-50588 From 273c9b38b78da06244bd685dd7073e599f10eb9e Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Wed, 10 Jun 2026 08:38:36 +0100 Subject: [PATCH 045/168] Correct syntax of MBEDTLS_GET_UINT32_BE in write_new_session_ticket_mem Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 34c4d89e00..d6a7ea8e27 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6432,7 +6432,7 @@ void write_new_session_ticket_mem() * uninitialized memory. * The read here causes MSan and Valgrind to complain if the bug isn't fixed. */ - volatile unsigned char lifetime = MBEDTLS_GET_UINT32_BE(server_ep.ssl.out_msg + 4); + volatile uint32_t lifetime = MBEDTLS_GET_UINT32_BE(server_ep.ssl.out_msg, 4); (void) lifetime; exit: From 1aa125454601ef3492c285d2122518ac3fa3b6c2 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Wed, 10 Jun 2026 14:15:48 +0100 Subject: [PATCH 046/168] Fix style issue Signed-off-by: Ben Taylor --- ChangeLog.d/oob-key-exchange-restricted.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/oob-key-exchange-restricted.txt b/ChangeLog.d/oob-key-exchange-restricted.txt index 6a250644b9..2e48ce0fec 100644 --- a/ChangeLog.d/oob-key-exchange-restricted.txt +++ b/ChangeLog.d/oob-key-exchange-restricted.txt @@ -1,4 +1,4 @@ Security - * Fix an out-of-bounds read when parsing TLS 1.2 ECJPAKE ServerKeyExchange + * Fix an out-of-bounds read when parsing TLS 1.2 ECJPAKE ServerKeyExchange messages. Reported-by Biniam Demissie. CVE-2026-50588 From 67e696b430716f95ed714f2c1404681697251438 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 30 Apr 2026 13:09:10 +0100 Subject: [PATCH 047/168] Add fix for stale pointer after mbedtls_pkcs7_free Signed-off-by: Ben Taylor --- library/pkcs7.c | 2 +- tests/suites/test_suite_pkcs7.data | 4 ++ tests/suites/test_suite_pkcs7.function | 59 ++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/library/pkcs7.c b/library/pkcs7.c index 2cc7812bf0..e345d4b980 100644 --- a/library/pkcs7.c +++ b/library/pkcs7.c @@ -766,7 +766,7 @@ void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7) mbedtls_free(signer_prev); } - pkcs7->raw.p = NULL; + mbedtls_platform_zeroize(pkcs7, sizeof(*pkcs7)); } #endif diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data index 3e3f7f1d7d..7e220fc2e6 100644 --- a/tests/suites/test_suite_pkcs7.data +++ b/tests/suites/test_suite_pkcs7.data @@ -14,6 +14,10 @@ PKCS7 Signed Data Parse with zero signers depends_on:PSA_WANT_ALG_SHA_256 pkcs7_parse:"../framework/data_files/pkcs7_data_no_signers.der":MBEDTLS_PKCS7_SIGNED_DATA +PKCS7 Signed Data Parse reused object after multiple signers +depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY +pkcs7_parse_reuse:"../framework/data_files/pkcs7_data_multiple_signed.der":"../framework/data_files/pkcs7_data_no_signers.der":MBEDTLS_PKCS7_SIGNED_DATA + PKCS7 Signed Data Parse Fail with multiple certs #4 depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY pkcs7_parse:"../framework/data_files/pkcs7_data_multiple_certs_signed.der":MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE diff --git a/tests/suites/test_suite_pkcs7.function b/tests/suites/test_suite_pkcs7.function index 9eccabab22..4e60a99bc7 100644 --- a/tests/suites/test_suite_pkcs7.function +++ b/tests/suites/test_suite_pkcs7.function @@ -25,8 +25,33 @@ static int pkcs7_parse_buffer(unsigned char *pkcs7_buf, int buflen) mbedtls_pkcs7_init(&pkcs7); res = mbedtls_pkcs7_parse_der(&pkcs7, pkcs7_buf, buflen); mbedtls_pkcs7_free(&pkcs7); + return res; } + +# ifdef MBEDTLS_FS_IO +static int pkcs7_parse_buffers_reuse(unsigned char *first_buf, int first_len, + unsigned char *second_buf, int second_len) +{ + int res; + mbedtls_pkcs7 pkcs7; + + mbedtls_pkcs7_init(&pkcs7); + + res = mbedtls_pkcs7_parse_der(&pkcs7, first_buf, first_len); + if (res != MBEDTLS_PKCS7_SIGNED_DATA) { + goto exit; + } + + mbedtls_pkcs7_free(&pkcs7); + + res = mbedtls_pkcs7_parse_der(&pkcs7, second_buf, second_len); + +exit: + mbedtls_pkcs7_free(&pkcs7); + return res; +} +#endif /* END_SUITE_HELPERS */ /* BEGIN_CASE */ @@ -71,6 +96,40 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */ +void pkcs7_parse_reuse(char *first_pkcs7_file, char *second_pkcs7_file, + int res_expect) +{ + unsigned char *first_pkcs7_buf = NULL; + unsigned char *second_pkcs7_buf = NULL; + size_t first_buflen; + size_t second_buflen; + int res; + + /* PKCS7 uses X509 which itself relies on PK under the hood and the latter + * can use PSA to store keys and perform operations so psa_crypto_init() + * must be called before. */ + USE_PSA_INIT(); + + res = mbedtls_pk_load_file(first_pkcs7_file, &first_pkcs7_buf, + &first_buflen); + TEST_EQUAL(res, 0); + + res = mbedtls_pk_load_file(second_pkcs7_file, &second_pkcs7_buf, + &second_buflen); + TEST_EQUAL(res, 0); + + res = pkcs7_parse_buffers_reuse(first_pkcs7_buf, first_buflen, + second_pkcs7_buf, second_buflen); + TEST_EQUAL(res, res_expect); + +exit: + mbedtls_free(first_pkcs7_buf); + mbedtls_free(second_pkcs7_buf); + USE_PSA_DONE(); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:PSA_HAVE_ALG_SOME_RSA_VERIFY */ void pkcs7_verify(char *pkcs7_file, char *crt_files, From e9ec4ce3caf7e21f877d4dd6d733b858bc56df75 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 30 Apr 2026 13:14:27 +0100 Subject: [PATCH 048/168] Add ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/pkcs-free-stale-pointers.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 ChangeLog.d/pkcs-free-stale-pointers.txt diff --git a/ChangeLog.d/pkcs-free-stale-pointers.txt b/ChangeLog.d/pkcs-free-stale-pointers.txt new file mode 100644 index 0000000000..04ba823217 --- /dev/null +++ b/ChangeLog.d/pkcs-free-stale-pointers.txt @@ -0,0 +1,2 @@ +Bugfix + * Add fix for stale pointer after mbedtls_pkcs7_free. From f60f5ba85cda59545442af29b59fdee9ed6af83d Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Tue, 2 Jun 2026 15:32:54 +0100 Subject: [PATCH 049/168] Remove redundant function from pkcs7_parse_reuse Signed-off-by: Ben Taylor --- tests/suites/test_suite_pkcs7.function | 49 +++++++++----------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/tests/suites/test_suite_pkcs7.function b/tests/suites/test_suite_pkcs7.function index 4e60a99bc7..cdf221524e 100644 --- a/tests/suites/test_suite_pkcs7.function +++ b/tests/suites/test_suite_pkcs7.function @@ -29,29 +29,6 @@ static int pkcs7_parse_buffer(unsigned char *pkcs7_buf, int buflen) return res; } -# ifdef MBEDTLS_FS_IO -static int pkcs7_parse_buffers_reuse(unsigned char *first_buf, int first_len, - unsigned char *second_buf, int second_len) -{ - int res; - mbedtls_pkcs7 pkcs7; - - mbedtls_pkcs7_init(&pkcs7); - - res = mbedtls_pkcs7_parse_der(&pkcs7, first_buf, first_len); - if (res != MBEDTLS_PKCS7_SIGNED_DATA) { - goto exit; - } - - mbedtls_pkcs7_free(&pkcs7); - - res = mbedtls_pkcs7_parse_der(&pkcs7, second_buf, second_len); - -exit: - mbedtls_pkcs7_free(&pkcs7); - return res; -} -#endif /* END_SUITE_HELPERS */ /* BEGIN_CASE */ @@ -102,30 +79,36 @@ void pkcs7_parse_reuse(char *first_pkcs7_file, char *second_pkcs7_file, { unsigned char *first_pkcs7_buf = NULL; unsigned char *second_pkcs7_buf = NULL; + mbedtls_pkcs7 pkcs7; size_t first_buflen; size_t second_buflen; - int res; /* PKCS7 uses X509 which itself relies on PK under the hood and the latter * can use PSA to store keys and perform operations so psa_crypto_init() * must be called before. */ USE_PSA_INIT(); - res = mbedtls_pk_load_file(first_pkcs7_file, &first_pkcs7_buf, - &first_buflen); - TEST_EQUAL(res, 0); + mbedtls_pkcs7_init(&pkcs7); - res = mbedtls_pk_load_file(second_pkcs7_file, &second_pkcs7_buf, - &second_buflen); - TEST_EQUAL(res, 0); + TEST_EQUAL(mbedtls_pk_load_file(first_pkcs7_file, &first_pkcs7_buf, + &first_buflen), 0); - res = pkcs7_parse_buffers_reuse(first_pkcs7_buf, first_buflen, - second_pkcs7_buf, second_buflen); - TEST_EQUAL(res, res_expect); + TEST_EQUAL(mbedtls_pk_load_file(second_pkcs7_file, &second_pkcs7_buf, + &second_buflen), 0); + + TEST_EQUAL(mbedtls_pkcs7_parse_der(&pkcs7, first_pkcs7_buf, + first_buflen), + MBEDTLS_PKCS7_SIGNED_DATA); + + mbedtls_pkcs7_free(&pkcs7); + TEST_EQUAL(mbedtls_pkcs7_parse_der(&pkcs7, second_pkcs7_buf, + second_buflen), + res_expect); exit: mbedtls_free(first_pkcs7_buf); mbedtls_free(second_pkcs7_buf); + mbedtls_pkcs7_free(&pkcs7); USE_PSA_DONE(); } /* END_CASE */ From 62162e6e4d08ddcc6805975cc39e59f69e0c9775 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Tue, 2 Jun 2026 15:34:40 +0100 Subject: [PATCH 050/168] Fix style issues Signed-off-by: Ben Taylor --- tests/suites/test_suite_pkcs7.function | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_pkcs7.function b/tests/suites/test_suite_pkcs7.function index cdf221524e..3fccbaceaf 100644 --- a/tests/suites/test_suite_pkcs7.function +++ b/tests/suites/test_suite_pkcs7.function @@ -91,18 +91,18 @@ void pkcs7_parse_reuse(char *first_pkcs7_file, char *second_pkcs7_file, mbedtls_pkcs7_init(&pkcs7); TEST_EQUAL(mbedtls_pk_load_file(first_pkcs7_file, &first_pkcs7_buf, - &first_buflen), 0); + &first_buflen), 0); TEST_EQUAL(mbedtls_pk_load_file(second_pkcs7_file, &second_pkcs7_buf, - &second_buflen), 0); + &second_buflen), 0); TEST_EQUAL(mbedtls_pkcs7_parse_der(&pkcs7, first_pkcs7_buf, - first_buflen), + first_buflen), MBEDTLS_PKCS7_SIGNED_DATA); mbedtls_pkcs7_free(&pkcs7); TEST_EQUAL(mbedtls_pkcs7_parse_der(&pkcs7, second_pkcs7_buf, - second_buflen), + second_buflen), res_expect); exit: From 4e797c14e0ae62c31f7ae5996dd27888642d11a3 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Tue, 2 Jun 2026 15:35:08 +0100 Subject: [PATCH 051/168] Update ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/pkcs-free-stale-pointers.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ChangeLog.d/pkcs-free-stale-pointers.txt b/ChangeLog.d/pkcs-free-stale-pointers.txt index 04ba823217..e283557b15 100644 --- a/ChangeLog.d/pkcs-free-stale-pointers.txt +++ b/ChangeLog.d/pkcs-free-stale-pointers.txt @@ -1,2 +1,4 @@ -Bugfix - * Add fix for stale pointer after mbedtls_pkcs7_free. +Security + * Fix a use-after-free/double-free risk in mbedtls_pkcs7_free() when reusing an mbedtls_pkcs7 context + across parse -> free -> parse -> free cycles. The function now clears the signer list after freeing it, + ensuring stale signed_data.signers.next pointers cannot be walked by a later free operation. From 64435904480332b9dd7249b73385853720b6a5da Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Tue, 2 Jun 2026 15:38:02 +0100 Subject: [PATCH 052/168] Update ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/pkcs-free-stale-pointers.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/pkcs-free-stale-pointers.txt b/ChangeLog.d/pkcs-free-stale-pointers.txt index e283557b15..72c673fac6 100644 --- a/ChangeLog.d/pkcs-free-stale-pointers.txt +++ b/ChangeLog.d/pkcs-free-stale-pointers.txt @@ -1,4 +1,4 @@ Security * Fix a use-after-free/double-free risk in mbedtls_pkcs7_free() when reusing an mbedtls_pkcs7 context - across parse -> free -> parse -> free cycles. The function now clears the signer list after freeing it, + across parse -> free -> parse -> free cycles. The function now resets the context after freeing it, ensuring stale signed_data.signers.next pointers cannot be walked by a later free operation. From 84966c1bda07dd01e38786b2caa9b7453a5adb95 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Tue, 2 Jun 2026 15:47:08 +0100 Subject: [PATCH 053/168] Add further testing Signed-off-by: Ben Taylor --- tests/suites/test_suite_pkcs7.data | 8 ++++++ tests/suites/test_suite_pkcs7.function | 35 ++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data index 7e220fc2e6..88dc5f27ef 100644 --- a/tests/suites/test_suite_pkcs7.data +++ b/tests/suites/test_suite_pkcs7.data @@ -18,6 +18,14 @@ PKCS7 Signed Data Parse reused object after multiple signers depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY pkcs7_parse_reuse:"../framework/data_files/pkcs7_data_multiple_signed.der":"../framework/data_files/pkcs7_data_no_signers.der":MBEDTLS_PKCS7_SIGNED_DATA +PKCS7 Signed Data Parse reused object from multiple signers to one signer +depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY +pkcs7_parse_reuse:"../framework/data_files/pkcs7_data_multiple_signed.der":"../framework/data_files/pkcs7_data_cert_signed_sha256.der":MBEDTLS_PKCS7_SIGNED_DATA + +PKCS7 Signed Data Parse free resets context after multiple signers +depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY +pkcs7_parse_free_resets_context:"../framework/data_files/pkcs7_data_multiple_signed.der":MBEDTLS_PKCS7_SIGNED_DATA + PKCS7 Signed Data Parse Fail with multiple certs #4 depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY pkcs7_parse:"../framework/data_files/pkcs7_data_multiple_certs_signed.der":MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE diff --git a/tests/suites/test_suite_pkcs7.function b/tests/suites/test_suite_pkcs7.function index 3fccbaceaf..f6068879f8 100644 --- a/tests/suites/test_suite_pkcs7.function +++ b/tests/suites/test_suite_pkcs7.function @@ -83,13 +83,13 @@ void pkcs7_parse_reuse(char *first_pkcs7_file, char *second_pkcs7_file, size_t first_buflen; size_t second_buflen; + mbedtls_pkcs7_init(&pkcs7); + /* PKCS7 uses X509 which itself relies on PK under the hood and the latter * can use PSA to store keys and perform operations so psa_crypto_init() * must be called before. */ USE_PSA_INIT(); - mbedtls_pkcs7_init(&pkcs7); - TEST_EQUAL(mbedtls_pk_load_file(first_pkcs7_file, &first_pkcs7_buf, &first_buflen), 0); @@ -113,6 +113,37 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */ +void pkcs7_parse_free_resets_context(char *pkcs7_file, int res_expect) +{ + unsigned char *pkcs7_buf = NULL; + mbedtls_pkcs7 pkcs7; + size_t buflen; + + mbedtls_pkcs7_init(&pkcs7); + + /* PKCS7 uses X509 which itself relies on PK under the hood and the latter + * can use PSA to store keys and perform operations so psa_crypto_init() + * must be called before. */ + USE_PSA_INIT(); + + TEST_EQUAL(mbedtls_pk_load_file(pkcs7_file, &pkcs7_buf, &buflen), 0); + + TEST_EQUAL(mbedtls_pkcs7_parse_der(&pkcs7, pkcs7_buf, buflen), + res_expect); + + mbedtls_pkcs7_free(&pkcs7); + + TEST_ASSERT(pkcs7.raw.p == NULL); + TEST_ASSERT(pkcs7.signed_data.signers.next == NULL); + +exit: + mbedtls_pkcs7_free(&pkcs7); + mbedtls_free(pkcs7_buf); + USE_PSA_DONE(); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:PSA_HAVE_ALG_SOME_RSA_VERIFY */ void pkcs7_verify(char *pkcs7_file, char *crt_files, From 351419f1ff82f148e142bd9bdbfc2a3fa3b7f5ee Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Wed, 3 Jun 2026 08:03:06 +0100 Subject: [PATCH 054/168] Correct changelog style Signed-off-by: Ben Taylor --- ChangeLog.d/pkcs-free-stale-pointers.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ChangeLog.d/pkcs-free-stale-pointers.txt b/ChangeLog.d/pkcs-free-stale-pointers.txt index 72c673fac6..68811c056c 100644 --- a/ChangeLog.d/pkcs-free-stale-pointers.txt +++ b/ChangeLog.d/pkcs-free-stale-pointers.txt @@ -1,4 +1,6 @@ Security - * Fix a use-after-free/double-free risk in mbedtls_pkcs7_free() when reusing an mbedtls_pkcs7 context - across parse -> free -> parse -> free cycles. The function now resets the context after freeing it, - ensuring stale signed_data.signers.next pointers cannot be walked by a later free operation. + * Fix a use-after-free/double-free risk in mbedtls_pkcs7_free() when reusing + an mbedtls_pkcs7 context across parse -> free -> parse -> free cycles. The + function now resets the context after freeing it, ensuring stale + signed_data.signers.next pointers cannot be walked by a later free + operation. From 74555884cc72bf8aa6b74a0a09bb2a3a68741806 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Wed, 3 Jun 2026 10:24:27 +0100 Subject: [PATCH 055/168] Remove whitespace in ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/pkcs-free-stale-pointers.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/pkcs-free-stale-pointers.txt b/ChangeLog.d/pkcs-free-stale-pointers.txt index 68811c056c..b56a62cc57 100644 --- a/ChangeLog.d/pkcs-free-stale-pointers.txt +++ b/ChangeLog.d/pkcs-free-stale-pointers.txt @@ -1,6 +1,6 @@ Security * Fix a use-after-free/double-free risk in mbedtls_pkcs7_free() when reusing an mbedtls_pkcs7 context across parse -> free -> parse -> free cycles. The - function now resets the context after freeing it, ensuring stale + function now resets the context after freeing it, ensuring stale signed_data.signers.next pointers cannot be walked by a later free operation. From a798b5804ef8571bcfd6609019758014325162c4 Mon Sep 17 00:00:00 2001 From: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> Date: Mon, 8 Jun 2026 15:49:42 +0100 Subject: [PATCH 056/168] Add CVE ID to ChangeLog Co-authored-by: Gilles Peskine Signed-off-by: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> --- ChangeLog.d/pkcs-free-stale-pointers.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/pkcs-free-stale-pointers.txt b/ChangeLog.d/pkcs-free-stale-pointers.txt index b56a62cc57..2c29fed5ef 100644 --- a/ChangeLog.d/pkcs-free-stale-pointers.txt +++ b/ChangeLog.d/pkcs-free-stale-pointers.txt @@ -3,4 +3,4 @@ Security an mbedtls_pkcs7 context across parse -> free -> parse -> free cycles. The function now resets the context after freeing it, ensuring stale signed_data.signers.next pointers cannot be walked by a later free - operation. + operation. CVE-2026-50579 From 10afc1ed5c8e9c47caf1ad8ee6241fd99e43f945 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Wed, 10 Jun 2026 10:17:48 +0100 Subject: [PATCH 057/168] Remove pkcs7_parse_free_resets_context as it duplicates pkcs7_parse_reuse Signed-off-by: Ben Taylor --- tests/suites/test_suite_pkcs7.data | 4 ---- tests/suites/test_suite_pkcs7.function | 31 -------------------------- 2 files changed, 35 deletions(-) diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data index 88dc5f27ef..57f71841e2 100644 --- a/tests/suites/test_suite_pkcs7.data +++ b/tests/suites/test_suite_pkcs7.data @@ -22,10 +22,6 @@ PKCS7 Signed Data Parse reused object from multiple signers to one signer depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY pkcs7_parse_reuse:"../framework/data_files/pkcs7_data_multiple_signed.der":"../framework/data_files/pkcs7_data_cert_signed_sha256.der":MBEDTLS_PKCS7_SIGNED_DATA -PKCS7 Signed Data Parse free resets context after multiple signers -depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY -pkcs7_parse_free_resets_context:"../framework/data_files/pkcs7_data_multiple_signed.der":MBEDTLS_PKCS7_SIGNED_DATA - PKCS7 Signed Data Parse Fail with multiple certs #4 depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY pkcs7_parse:"../framework/data_files/pkcs7_data_multiple_certs_signed.der":MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE diff --git a/tests/suites/test_suite_pkcs7.function b/tests/suites/test_suite_pkcs7.function index f6068879f8..09968f5ddf 100644 --- a/tests/suites/test_suite_pkcs7.function +++ b/tests/suites/test_suite_pkcs7.function @@ -113,37 +113,6 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */ -void pkcs7_parse_free_resets_context(char *pkcs7_file, int res_expect) -{ - unsigned char *pkcs7_buf = NULL; - mbedtls_pkcs7 pkcs7; - size_t buflen; - - mbedtls_pkcs7_init(&pkcs7); - - /* PKCS7 uses X509 which itself relies on PK under the hood and the latter - * can use PSA to store keys and perform operations so psa_crypto_init() - * must be called before. */ - USE_PSA_INIT(); - - TEST_EQUAL(mbedtls_pk_load_file(pkcs7_file, &pkcs7_buf, &buflen), 0); - - TEST_EQUAL(mbedtls_pkcs7_parse_der(&pkcs7, pkcs7_buf, buflen), - res_expect); - - mbedtls_pkcs7_free(&pkcs7); - - TEST_ASSERT(pkcs7.raw.p == NULL); - TEST_ASSERT(pkcs7.signed_data.signers.next == NULL); - -exit: - mbedtls_pkcs7_free(&pkcs7); - mbedtls_free(pkcs7_buf); - USE_PSA_DONE(); -} -/* END_CASE */ - /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:PSA_HAVE_ALG_SOME_RSA_VERIFY */ void pkcs7_verify(char *pkcs7_file, char *crt_files, From 377aa4eff16cd0aa5e7440a41de59847e3a789a0 Mon Sep 17 00:00:00 2001 From: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> Date: Mon, 15 Jun 2026 11:52:52 +0100 Subject: [PATCH 058/168] Add in the two additional checks that were dropped. Co-authored-by: Ronald Cron Signed-off-by: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> --- tests/suites/test_suite_pkcs7.function | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/suites/test_suite_pkcs7.function b/tests/suites/test_suite_pkcs7.function index 09968f5ddf..3bd7595b96 100644 --- a/tests/suites/test_suite_pkcs7.function +++ b/tests/suites/test_suite_pkcs7.function @@ -101,6 +101,8 @@ void pkcs7_parse_reuse(char *first_pkcs7_file, char *second_pkcs7_file, MBEDTLS_PKCS7_SIGNED_DATA); mbedtls_pkcs7_free(&pkcs7); + TEST_ASSERT(pkcs7.raw.p == NULL); + TEST_ASSERT(pkcs7.signed_data.signers.next == NULL); TEST_EQUAL(mbedtls_pkcs7_parse_der(&pkcs7, second_pkcs7_buf, second_buflen), res_expect); From e31c644041e1bdc021e1c28eb723cb770b4d31b0 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 16 Jun 2026 19:34:32 +0200 Subject: [PATCH 059/168] Credit independent report Signed-off-by: Gilles Peskine --- ChangeLog.d/x509-crt-parse-basicConstraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/x509-crt-parse-basicConstraints.txt b/ChangeLog.d/x509-crt-parse-basicConstraints.txt index a67f992ab5..251dc8f0fd 100644 --- a/ChangeLog.d/x509-crt-parse-basicConstraints.txt +++ b/ChangeLog.d/x509-crt-parse-basicConstraints.txt @@ -4,7 +4,7 @@ Security could have dangerous results, in particular causing some certificates to be parsed as CA certificates when other X.509 implementations would parse them as end-entity certificates. Reported by Mohammad Seet - (mhdsait101) and Pablo Ruiz García. CVE-2026-49300 + (mhdsait101), Pablo Ruiz García and NVIDIA Project Vanessa. CVE-2026-49300 Changes * X.509 certificates with a basicConstraints extension starting with an From 5374a4124bfd8d6fdedc72aa6ccb4ce67612cb4c Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 21 Apr 2026 09:26:07 +0200 Subject: [PATCH 060/168] Remove unnecessary dependency Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.function | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 39317cf3f9..8d8da35c09 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -2870,7 +2870,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:!MBEDTLS_SSL_PROTO_TLS1_3:PSA_WANT_ALG_SHA_256 */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256 */ void mbedtls_endpoint_sanity(int endpoint_type) { enum { BUFFSIZE = 1024 }; @@ -3106,7 +3106,7 @@ void app_data_tls(int mfl, int cli_msg_len, int srv_msg_len, } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:!MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_PROTO_TLS1_2:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_SSL_PROTO_DTLS:PSA_WANT_ALG_SHA_256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_SSL_PROTO_TLS1_2:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_SSL_PROTO_DTLS:PSA_WANT_ALG_SHA_256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */ void app_data_dtls(int mfl, int cli_msg_len, int srv_msg_len, int expected_cli_fragments, int expected_srv_fragments) @@ -3135,7 +3135,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:!MBEDTLS_SSL_PROTO_TLS1_3:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_DEBUG_C:MBEDTLS_SSL_MAX_FRAGMENT_LENGTH:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_ALG_SHA_384:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_DEBUG_C:MBEDTLS_SSL_MAX_FRAGMENT_LENGTH:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_ALG_SHA_384:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ void handshake_fragmentation(int mfl, int expected_srv_hs_fragmentation, int expected_cli_hs_fragmentation) @@ -3332,7 +3332,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:!MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_PROTO_TLS1_2:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SSL_RENEGOTIATION:PSA_WANT_ALG_SHA_256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_SSL_PROTO_TLS1_2:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SSL_RENEGOTIATION:PSA_WANT_ALG_SHA_256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */ void renegotiation(int legacy_renegotiation) { mbedtls_test_handshake_test_options options; From 639615337e0fe617effb897905ea78819d7c207c Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 5 Jun 2026 15:40:03 +0200 Subject: [PATCH 061/168] Add a missing dependency Needed by a test certificate. Signed-off-by: Gilles Peskine --- tests/suites/test_suite_ssl.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 8d8da35c09..97a70f997a 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -3135,7 +3135,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_DEBUG_C:MBEDTLS_SSL_MAX_FRAGMENT_LENGTH:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_ALG_SHA_384:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_DEBUG_C:MBEDTLS_SSL_MAX_FRAGMENT_LENGTH:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_SHA_384:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ void handshake_fragmentation(int mfl, int expected_srv_hs_fragmentation, int expected_cli_hs_fragmentation) From 21df158961b1d51f1adbb3bcf81c5d57532e9cbc Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 Jun 2026 15:43:18 +0200 Subject: [PATCH 062/168] Add some hooks in mbedtls_test_ssl_perform_handshake() Let test code customize the kitchen sink function `mbedtls_test_ssl_perform_handshake()` at a few points. Signed-off-by: Gilles Peskine --- tests/include/test/ssl_helpers.h | 32 ++++++++++++++++++++++++++++ tests/src/test_helpers/ssl_helpers.c | 17 +++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h index a653c9643e..467a27f342 100644 --- a/tests/include/test/ssl_helpers.h +++ b/tests/include/test/ssl_helpers.h @@ -117,6 +117,9 @@ enum { #define MBEDTLS_TEST_MAX_ALPN_LIST_SIZE 10 #endif +/* Forward declaration. Defined below. */ +struct mbedtls_test_ssl_endpoint; + typedef struct mbedtls_test_ssl_log_pattern { const char *pattern; size_t counter; @@ -147,6 +150,35 @@ typedef struct mbedtls_test_handshake_test_options { int expected_srv_fragments; int renegotiate; int legacy_renegotiation; + /** Hook that mbedtls_test_ssl_perform_handshake() runs just before + * the initial handshake. */ + void (*pre_handshake_fun)(struct mbedtls_test_ssl_endpoint *client, + struct mbedtls_test_ssl_endpoint *server, + void *param); + /** Value passed to ::pre_handshake_fun. */ + void *pre_handshake_param; + /** Hook that mbedtls_test_ssl_perform_handshake() runs after + * the initial handshake succeeds. */ + void (*post_handshake_fun)(struct mbedtls_test_ssl_endpoint *client, + struct mbedtls_test_ssl_endpoint *server, + void *param); + /** Value passed to ::post_handshake_fun. */ + void *post_handshake_param; + /** Hook that mbedtls_test_ssl_perform_handshake() runs after + * exchanging some data, before testing additional features such as + * serialization and renegotiation. */ + void (*post_data_fun)(struct mbedtls_test_ssl_endpoint *client, + struct mbedtls_test_ssl_endpoint *server, + void *param); + /** Value passed to ::post_data_fun. */ + void *post_data_param; + /** Hook that mbedtls_test_ssl_perform_handshake() runs after a successful + * connection, just before closing down. */ + void (*pre_shutdown_fun)(struct mbedtls_test_ssl_endpoint *client, + struct mbedtls_test_ssl_endpoint *server, + void *param); + /** Value passed to ::pre_shutdown_fun. */ + void *pre_shutdown_param; void *srv_log_obj; void *cli_log_obj; void (*srv_log_fun)(void *, int, const char *, int, const char *); diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c index db29413de6..08cfe252af 100644 --- a/tests/src/test_helpers/ssl_helpers.c +++ b/tests/src/test_helpers/ssl_helpers.c @@ -2282,6 +2282,10 @@ int mbedtls_test_ssl_perform_connection( expected_handshake_result = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } + if (options->pre_handshake_fun != NULL) { + options->pre_handshake_fun(client, server, options->pre_handshake_param); + } + TEST_EQUAL(mbedtls_test_move_handshake_to_state(&(client->ssl), &(server->ssl), MBEDTLS_SSL_HANDSHAKE_OVER), @@ -2313,6 +2317,10 @@ int mbedtls_test_ssl_perform_connection( options->expected_ciphersuite); } + if (options->post_handshake_fun != NULL) { + options->post_handshake_fun(client, server, options->post_handshake_param); + } + #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) if (options->resize_buffers != 0) { /* A server, when using DTLS, might delay a buffer resize to happen @@ -2339,6 +2347,11 @@ int mbedtls_test_ssl_perform_connection( options->expected_srv_fragments), 0); } + + if (options->post_data_fun != NULL) { + options->post_data_fun(client, server, options->post_data_param); + } + #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) if (options->serialize == 1) { TEST_ASSERT(test_serialization(options, client, server)); @@ -2396,6 +2409,10 @@ void mbedtls_test_ssl_perform_handshake( TEST_ASSERT(mbedtls_ssl_conf_get_user_data_p(&server->conf) == server); TEST_ASSERT(mbedtls_ssl_get_user_data_p(&server->ssl) == server); + if (options->pre_shutdown_fun != NULL) { + options->pre_shutdown_fun(client, server, options->pre_shutdown_param); + } + exit: mbedtls_test_ssl_endpoint_free(client); mbedtls_test_ssl_endpoint_free(server); From 3e76e77ee29fb7323bd5c293de9c58fc0d074d4b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 Jun 2026 15:44:08 +0200 Subject: [PATCH 063/168] Test DTLS renegotiation when badmac_seen_or_in_hsfraglen != 0 Non-regression test for a bug introduced with TLS handshake defragmentation support in Mbed TLS 3.6.3, whereby the confusion between the `badmac_seen` meaning and the `in_hsfraglen` meaning of `ssl->badmac_seen_or_in_hsfraglen` causes renegotiation to be processed incorrectly after receiving a message with a bad MAC. The bug doesn't affect Mbed TLS 4.0.0 and above, but it's still good to have more testing. Signed-off-by: Gilles Peskine --- tests/suites/test_suite_ssl.data | 12 +++++++++--- tests/suites/test_suite_ssl.function | 28 +++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 0c30c8987b..da975a5b0d 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -548,13 +548,19 @@ Sending app data via DTLS, without MFL and with fragmentation app_data_dtls:MBEDTLS_SSL_MAX_FRAG_LEN_NONE:16385:100000:0:0 DTLS renegotiation: no legacy renegotiation -renegotiation:MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION +renegotiation:MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION:-1 DTLS renegotiation: legacy renegotiation -renegotiation:MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION +renegotiation:MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION:-1 DTLS renegotiation: legacy break handshake -renegotiation:MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE +renegotiation:MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE:-1 + +DTLS renegotiation: after bad MAC on client +renegotiation:MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION:MBEDTLS_SSL_IS_CLIENT + +DTLS renegotiation: after bad MAC on server +renegotiation:MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION:MBEDTLS_SSL_IS_SERVER DTLS serialization with MFL=512 resize_buffers_serialize_mfl:MBEDTLS_SSL_MAX_FRAG_LEN_512 diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 97a70f997a..f5492ff53c 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -109,6 +109,30 @@ static void resize_buffers(int mfl, int renegotiation, int legacy_renegotiation, #define TEST_GCM_OR_CHACHAPOLY_ENABLED #endif +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(PSA_HAVE_ALG_SOME_RSA_SIGN) && \ + defined(PSA_WANT_ECC_SECP_R1_384) && \ + defined(MBEDTLS_SSL_PROTO_DTLS) && \ + defined(MBEDTLS_SSL_RENEGOTIATION) && \ + defined(PSA_WANT_ALG_SHA_256) && \ + defined(MBEDTLS_CAN_HANDLE_RSA_TEST_KEY) +static void simulate_badmac_seen_on(mbedtls_test_ssl_endpoint *client, + mbedtls_test_ssl_endpoint *server, + void *param) +{ + int on = *(int *) param; + switch (on) { + case MBEDTLS_SSL_IS_CLIENT: + client->ssl.badmac_seen = 1; + break; + case MBEDTLS_SSL_IS_SERVER: + server->ssl.badmac_seen = 1; + break; + } +} +#endif + typedef enum { RECOMBINE_NOMINAL, /* param: ignored */ RECOMBINE_SPLIT_FIRST, /* param: offset of split (<=0 means from end) */ @@ -3333,7 +3357,7 @@ exit: /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_SSL_PROTO_TLS1_2:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SSL_RENEGOTIATION:PSA_WANT_ALG_SHA_256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */ -void renegotiation(int legacy_renegotiation) +void renegotiation(int legacy_renegotiation, int badmac_seen_on) { mbedtls_test_handshake_test_options options; mbedtls_test_init_handshake_options(&options); @@ -3342,6 +3366,8 @@ void renegotiation(int legacy_renegotiation) options.legacy_renegotiation = legacy_renegotiation; options.dtls = 1; options.expected_negotiated_version = MBEDTLS_SSL_VERSION_TLS1_2; + options.post_data_fun = &simulate_badmac_seen_on; + options.post_data_param = &badmac_seen_on; mbedtls_test_ssl_perform_handshake(&options); From 2475c617cb81cd0d8f002e4660386d013f8a5e56 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 May 2026 10:54:32 +0200 Subject: [PATCH 064/168] Add udp_proxy options to delay an encrypted handshake message This can be used to simulate data messages received in the wrong epoch, or to cause a handshake message to be buffered. Signed-off-by: Gilles Peskine --- programs/test/udp_proxy.c | 50 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/programs/test/udp_proxy.c b/programs/test/udp_proxy.c index eab15feb38..7712a5f908 100644 --- a/programs/test/udp_proxy.c +++ b/programs/test/udp_proxy.c @@ -103,6 +103,12 @@ int main(void) " May be used multiple times, even for the same\n" \ " message, in which case the respective message\n" \ " gets delayed multiple times.\n" \ + " delay_encrypted_hs_cli=%%d default: 0 (don't delay)\n" \ + " delay the Nth encrypted handshake message from\n" \ + " client to server.\n" \ + " delay_encrypted_hs_srv=%%d default: 0 (don't delay)\n" \ + " delay the Nth encrypted handshake message from\n" \ + " server to client.\n" \ " delay_srv=%%s Handshake message from server that should be\n" \ " delayed. Possible values are 'HelloRequest',\n" \ " 'ServerHello', 'ServerHelloDone', 'Certificate'\n" \ @@ -148,6 +154,8 @@ static struct options { char *delay_srv[MAX_DELAYED_HS]; /* handshake types of messages from * server that should be delayed. */ uint8_t delay_srv_cnt; /* Number of entries in delay_srv. */ + int delay_encrypted_hs_cli; /* Delay Nth encrypted HS from client. */ + int delay_encrypted_hs_srv; /* Delay Nth encrypted HS from server. */ int drop; /* drop 1 packet in N (none if 0) */ int mtu; /* drop packets larger than this */ int bad_ad; /* inject corrupted ApplicationData record */ @@ -219,6 +227,16 @@ static void get_options(int argc, char *argv[]) if (opt.delay_ccs < 0 || opt.delay_ccs > 1) { exit_usage(p, q); } + } else if (strcmp(p, "delay_encrypted_hs_cli") == 0) { + opt.delay_encrypted_hs_cli = atoi(q); + if (opt.delay_encrypted_hs_cli < 0) { + exit_usage(p, q); + } + } else if (strcmp(p, "delay_encrypted_hs_srv") == 0) { + opt.delay_encrypted_hs_srv = atoi(q); + if (opt.delay_encrypted_hs_srv < 0) { + exit_usage(p, q); + } } else if (strcmp(p, "delay_cli") == 0 || strcmp(p, "delay_srv") == 0) { uint8_t *delay_cnt; @@ -664,6 +682,31 @@ static int send_delayed(void) static unsigned char held[2048] = { 0 }; #define HOLD_MAX 2 +static unsigned encrypted_hs_cli_seen; +static unsigned encrypted_hs_srv_seen; + +static int delay_encrypted_hs(const packet *p) +{ + unsigned *seen; + int delay_at; + + if (strcmp(p->type, "Encrypted handshake") != 0) { + return 0; + } + + if (strcmp(p->way, "S <- C") == 0) { + seen = &encrypted_hs_cli_seen; + delay_at = opt.delay_encrypted_hs_cli; + } else { + seen = &encrypted_hs_srv_seen; + delay_at = opt.delay_encrypted_hs_srv; + } + + ++*seen; + + return delay_at > 0 && *seen == (unsigned) delay_at; +} + static int handle_message(const char *way, mbedtls_net_context *dst, mbedtls_net_context *src) @@ -717,6 +760,11 @@ static int handle_message(const char *way, } } + if (delay_encrypted_hs(&cur)) { + delay_packet(&cur); + return 0; + } + /* do we want to drop, delay, or forward it? */ if ((opt.mtu != 0 && cur.len > (unsigned) opt.mtu) || @@ -851,6 +899,8 @@ accept: */ clear_pending(); memset(held, 0, sizeof(held)); + encrypted_hs_cli_seen = 0; + encrypted_hs_srv_seen = 0; nb_fds = client_fd.fd; if (nb_fds < server_fd.fd) { From 3d088c90c4a7ec824e7c472349eb856eea7a5c2d Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 May 2026 11:04:52 +0200 Subject: [PATCH 065/168] Add one-shot bad AD options to udp_proxy Signed-off-by: Gilles Peskine --- programs/test/udp_proxy.c | 51 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/programs/test/udp_proxy.c b/programs/test/udp_proxy.c index 7712a5f908..04c2e3a7e7 100644 --- a/programs/test/udp_proxy.c +++ b/programs/test/udp_proxy.c @@ -122,6 +122,12 @@ int main(void) " mtu=%%d default: 0 (unlimited)\n" \ " drop packets larger than N bytes\n" \ " bad_ad=0/1 default: 0 (don't add bad ApplicationData)\n" \ + " bad_ad_cli_once=%%d default: 0 (don't add bad ApplicationData)\n" \ + " add bad ApplicationData before the Nth\n" \ + " ApplicationData from client to server.\n" \ + " bad_ad_srv_once=%%d default: 0 (don't add bad ApplicationData)\n" \ + " add bad ApplicationData before the Nth\n" \ + " ApplicationData from server to client.\n" \ " bad_cid=%%d default: 0 (don't corrupt Connection IDs)\n" \ " duplicate 1:N packets containing a CID,\n" \ " modifying CID in first instance of the packet.\n" \ @@ -159,6 +165,8 @@ static struct options { int drop; /* drop 1 packet in N (none if 0) */ int mtu; /* drop packets larger than this */ int bad_ad; /* inject corrupted ApplicationData record */ + int bad_ad_cli_once; /* Inject corrupted Nth AD from client. */ + int bad_ad_srv_once; /* Inject corrupted Nth AD from server. */ unsigned bad_cid; /* inject corrupted CID record */ int protect_hvr; /* never drop or delay HelloVerifyRequest */ int protect_len; /* never drop/delay packet of the given size*/ @@ -289,6 +297,16 @@ static void get_options(int argc, char *argv[]) if (opt.bad_ad < 0 || opt.bad_ad > 1) { exit_usage(p, q); } + } else if (strcmp(p, "bad_ad_cli_once") == 0) { + opt.bad_ad_cli_once = atoi(q); + if (opt.bad_ad_cli_once < 0) { + exit_usage(p, q); + } + } else if (strcmp(p, "bad_ad_srv_once") == 0) { + opt.bad_ad_srv_once = atoi(q); + if (opt.bad_ad_srv_once < 0) { + exit_usage(p, q); + } } #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) else if (strcmp(p, "bad_cid") == 0) { @@ -546,6 +564,35 @@ typedef enum { static inject_clihlo_state_t inject_clihlo_state; static packet initial_clihlo; +static unsigned bad_ad_cli_seen; +static unsigned bad_ad_srv_seen; + +static int bad_ad_once(const packet *p) +{ + unsigned *seen; + int bad_ad_at; + + if (strcmp(p->type, "ApplicationData") != 0) { + return 0; + } + + if (strcmp(p->way, "S <- C") == 0) { + seen = &bad_ad_cli_seen; + bad_ad_at = opt.bad_ad_cli_once; + } else { + seen = &bad_ad_srv_seen; + bad_ad_at = opt.bad_ad_srv_once; + } + + if (bad_ad_at <= 0) { + return 0; + } + + ++*seen; + + return *seen == (unsigned) bad_ad_at; +} + static int send_packet(const packet *p, const char *why) { int ret; @@ -577,7 +624,7 @@ static int send_packet(const packet *p, const char *why) } /* insert corrupted ApplicationData record? */ - if (opt.bad_ad && + if ((bad_ad_once(p) || opt.bad_ad) && strcmp(p->type, "ApplicationData") == 0) { unsigned char buf[MAX_MSG_SIZE]; memcpy(buf, p->buf, p->len); @@ -901,6 +948,8 @@ accept: memset(held, 0, sizeof(held)); encrypted_hs_cli_seen = 0; encrypted_hs_srv_seen = 0; + bad_ad_cli_seen = 0; + bad_ad_srv_seen = 0; nb_fds = client_fd.fd; if (nb_fds < server_fd.fd) { From 259de57a85b39d120155e7c4788ab5fe532f7d8c Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 May 2026 14:03:49 +0200 Subject: [PATCH 066/168] Add badmac_limit option to ssl_client2 Signed-off-by: Gilles Peskine --- programs/ssl/ssl_client2.c | 15 ++++++++++++++- programs/ssl/ssl_server2.c | 7 ++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index fc00473cfc..26ea63db9b 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -86,6 +86,7 @@ int main(void) #define DFL_HS_TO_MIN 0 #define DFL_HS_TO_MAX 0 #define DFL_DTLS_MTU -1 +#define DFL_BADMAC_LIMIT -1 #define DFL_DGRAM_PACKING 1 #define DFL_FALLBACK -1 #define DFL_EXTENDED_MS -1 @@ -269,7 +270,8 @@ int main(void) " mtu=%%d default: (library default: unlimited)\n" \ " dgram_packing=%%d default: 1 (allowed)\n" \ " allow or forbid packing of multiple\n" \ - " records within a single datgram.\n" + " records within a single datagram.\n" \ + " badmac_limit=%%d default: (library default: disabled)\n" #else #define USAGE_DTLS "" #endif @@ -518,6 +520,7 @@ struct options { int dtls_mtu; /* UDP Maximum transport unit for DTLS */ int fallback; /* is this a fallback connection? */ int dgram_packing; /* allow/forbid datagram packing */ + int badmac_limit; /* Limit of records with bad MAC */ int extended_ms; /* negotiate extended master secret? */ int etm; /* negotiate encrypt then mac? */ int context_crt_cb; /* use context-specific CRT verify callback */ @@ -959,6 +962,7 @@ int main(int argc, char *argv[]) opt.extended_ms = DFL_EXTENDED_MS; opt.etm = DFL_ETM; opt.dgram_packing = DFL_DGRAM_PACKING; + opt.badmac_limit = DFL_BADMAC_LIMIT; opt.serialize = DFL_SERIALIZE; opt.context_file = DFL_CONTEXT_FILE; opt.eap_tls = DFL_EAP_TLS; @@ -1372,6 +1376,11 @@ usage: opt.dgram_packing != 1) { goto usage; } + } else if (strcmp(p, "badmac_limit") == 0) { + opt.badmac_limit = atoi(q); + if (opt.badmac_limit < 0) { + goto usage; + } } else if (strcmp(p, "recsplit") == 0) { opt.recsplit = atoi(q); if (opt.recsplit < 0 || opt.recsplit > 1) { @@ -1835,6 +1844,10 @@ usage: if (opt.dgram_packing != DFL_DGRAM_PACKING) { mbedtls_ssl_set_datagram_packing(&ssl, opt.dgram_packing); } + + if (opt.badmac_limit != DFL_BADMAC_LIMIT) { + mbedtls_ssl_conf_dtls_badmac_limit(&conf, opt.badmac_limit); + } #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 79cbad877d..541c6a6b43 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -367,9 +367,6 @@ int main(void) #define USAGE_ANTI_REPLAY "" #endif -#define USAGE_BADMAC_LIMIT \ - " badmac_limit=%%d default: (library default: disabled)\n" - #if defined(MBEDTLS_SSL_PROTO_DTLS) #define USAGE_DTLS \ " dtls=%%d default: 0 (TLS)\n" \ @@ -378,7 +375,8 @@ int main(void) " mtu=%%d default: (library default: unlimited)\n" \ " dgram_packing=%%d default: 1 (allowed)\n" \ " allow or forbid packing of multiple\n" \ - " records within a single datgram.\n" + " records within a single datagram.\n" \ + " badmac_limit=%%d default: (library default: disabled)\n" #else #define USAGE_DTLS "" #endif @@ -524,7 +522,6 @@ int main(void) USAGE_SRTP \ USAGE_COOKIES \ USAGE_ANTI_REPLAY \ - USAGE_BADMAC_LIMIT \ "\n" #define USAGE2 \ " auth_mode=%%s default: (library default: none)\n" \ From b1ba93460bad255ca28e383d9d1243499c0e212b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 May 2026 19:59:10 +0200 Subject: [PATCH 067/168] Check "refusing renegotiation" log in more renegotiation tests Signed-off-by: Gilles Peskine --- tests/ssl-opt.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 9ab566944d..ff855f2b91 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -5269,6 +5269,7 @@ run_test "Renegotiation: client-initiated, server-rejected" \ -c "=> renegotiate" \ -S "=> renegotiate" \ -S "write hello request" \ + -s "refusing renegotiation" \ -c "SSL - Unexpected message at ServerHello in renegotiation" \ -c "failed" @@ -5285,6 +5286,7 @@ run_test "Renegotiation: server-initiated, client-rejected, default" \ -C "=> renegotiate" \ -S "=> renegotiate" \ -s "write hello request" \ + -c "refusing renegotiation" \ -S "SSL - An unexpected message was received from our peer" \ -S "failed" @@ -5302,6 +5304,7 @@ run_test "Renegotiation: server-initiated, client-rejected, not enforced" \ -C "=> renegotiate" \ -S "=> renegotiate" \ -s "write hello request" \ + -c "refusing renegotiation" \ -S "SSL - An unexpected message was received from our peer" \ -S "failed" @@ -5320,6 +5323,7 @@ run_test "Renegotiation: server-initiated, client-rejected, delay 2" \ -C "=> renegotiate" \ -S "=> renegotiate" \ -s "write hello request" \ + -c "refusing renegotiation" \ -S "SSL - An unexpected message was received from our peer" \ -S "failed" @@ -5337,6 +5341,7 @@ run_test "Renegotiation: server-initiated, client-rejected, delay 0" \ -C "=> renegotiate" \ -S "=> renegotiate" \ -s "write hello request" \ + -c "refusing renegotiation" \ -s "SSL - An unexpected message was received from our peer" requires_config_enabled MBEDTLS_SSL_RENEGOTIATION @@ -5353,6 +5358,7 @@ run_test "Renegotiation: server-initiated, client-accepted, delay 0" \ -c "=> renegotiate" \ -s "=> renegotiate" \ -s "write hello request" \ + -C "refusing renegotiation" \ -S "SSL - An unexpected message was received from our peer" \ -S "failed" From ed39c7b3944939a8b6394278762b565cd61e53c2 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 May 2026 20:00:29 +0200 Subject: [PATCH 068/168] Add tests for renegotiation with badmac_seen=1 on the client After a message with a bad MAC (invalid application data record), try to renegotiate: * Test cases where renegotiation (nominal or delayed) is rejected. Nothing bad happens. * A test where renegotiation is misparsed and rejected. The subsequent parsing fails. * A test where the renegotiation request is delayed. This causes a heap buffer overflow in `ssl_buffer_message()`. Signed-off-by: Gilles Peskine --- tests/ssl-opt.sh | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index ff855f2b91..24cf101439 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -11806,6 +11806,86 @@ run_test "DTLS proxy: inject invalid AD record, badmac_limit 2, exchanges 2"\ -s "too many records with bad MAC" \ -s "Verification of the message MAC failed" +requires_config_enabled MBEDTLS_SSL_RENEGOTIATION +run_test "DTLS proxy: client: get invalid AD record then reject renego" \ + -p "$P_PXY bad_ad_srv_once=1" \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiate=1 renegotiation=1 exchanges=4 \ + badmac_limit=99 debug_level=3" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + exchanges=4 badmac_limit=99 debug_level=3" \ + 0 \ + -s "write hello request" \ + -c "refusing renegotiation" \ + -S "=> renegotiate" \ + -C "=> renegotiate" \ + -s "Extra-header:" \ + -c "HTTP/1.0 200 OK" \ + -c "discarding invalid record (mac)" \ + -C "too many records with bad MAC" \ + -C "Verification of the message MAC failed" \ + -C "Consume: waiting for more handshake fragments" + +requires_config_enabled MBEDTLS_SSL_RENEGOTIATION +run_test "DTLS proxy: client: get invalid AD record then accept renego" \ + -p "$P_PXY bad_ad_srv_once=1" \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiate=1 renegotiation=1 exchanges=4 \ + badmac_limit=99 debug_level=3" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiation=1 exchanges=4 badmac_limit=99 debug_level=3" \ + 0 \ + -s "=> renegotiate" \ + -c "=> renegotiate" \ + -s "Extra-header:" \ + -c "HTTP/1.0 200 OK" \ + -c "discarding invalid record (mac)" \ + -C "too many records with bad MAC" \ + -C "Verification of the message MAC failed" \ + -C "Consume: waiting for more handshake fragments" + +requires_config_enabled MBEDTLS_SSL_RENEGOTIATION +run_test "DTLS proxy: client: get invalid AD record then reject early renego" \ + -p "$P_PXY bad_ad_srv_once=1 delay_encrypted_hs_srv=3" \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiate=1 renegotiation=1 exchanges=4 \ + debug_level=3" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + exchanges=4 badmac_limit=99 debug_level=3" \ + 0 \ + -S "=> renegotiate" \ + -C "=> renegotiate" \ + -s "write hello request" \ + -c "refusing renegotiation" \ + -C "=> ssl_buffer_message" \ + -C "initialize reassembly, total length = 0" \ + -s "Extra-header:" \ + -c "HTTP/1.0 200 OK" \ + -c "discarding invalid record (mac)" \ + -C "too many records with bad MAC" \ + -C "Verification of the message MAC failed" \ + -C "Consume: waiting for more handshake fragments" + +requires_config_enabled MBEDTLS_SSL_RENEGOTIATION +run_test "DTLS proxy: client: get invalid AD record then accept early renego" \ + -p "$P_PXY bad_ad_srv_once=1 delay_encrypted_hs_srv=3" \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiate=1 renegotiation=1 exchanges=4 \ + debug_level=3" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiation=1 exchanges=4 badmac_limit=99 debug_level=3" \ + 0 \ + -s "=> renegotiate" \ + -c "=> renegotiate" \ + -c "=> ssl_buffer_message" \ + -C "initialize reassembly, total length = 0" \ + -s "Extra-header:" \ + -c "HTTP/1.0 200 OK" \ + -c "discarding invalid record (mac)" \ + -C "too many records with bad MAC" \ + -C "Verification of the message MAC failed" \ + -C "Consume: waiting for more handshake fragments" + requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS proxy: delay ChangeCipherSpec" \ -p "$P_PXY delay_ccs=1" \ From 05fa79dc43412eab2ad7862db0505995f57f114e Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 May 2026 20:52:38 +0200 Subject: [PATCH 069/168] Add renegotiate=2 option to ssl_client2 In `ssl_client2`, the existing option `renegotiate=1` causes the client to initiate renegotiation immediately after the initial handshake. Add a variant `renegotiate=2` that initiates renegotiation after one data exchange. Signed-off-by: Gilles Peskine --- programs/ssl/ssl_client2.c | 43 ++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 26ea63db9b..be1d2a8e2e 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -296,7 +296,7 @@ int main(void) #if defined(MBEDTLS_SSL_RENEGOTIATION) #define USAGE_RENEGO \ " renegotiation=%%d default: 0 (disabled)\n" \ - " renegotiate=%%d default: 0 (disabled)\n" \ + " renegotiate=%%d default: 0 (disabled), 1 immediately, 2 after first exchange\n" \ " renego_delay=%%d default: -2 (library default)\n" #else #define USAGE_RENEGO "" @@ -493,7 +493,7 @@ struct options { #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ int renegotiation; /* enable / disable renegotiation */ int allow_legacy; /* allow legacy renegotiation */ - int renegotiate; /* attempt renegotiation? */ + int renegotiate; /* attempt renegotiation? 1: before data, 2: after first exchange */ int renego_delay; /* delay before enforcing renegotiation */ int exchanges; /* number of data exchanges */ int min_version; /* minimum protocol version accepted */ @@ -1168,7 +1168,7 @@ usage: opt.renego_delay = (atoi(q)); } else if (strcmp(p, "renegotiate") == 0) { opt.renegotiate = atoi(q); - if (opt.renegotiate < 0 || opt.renegotiate > 1) { + if (opt.renegotiate < 0 || opt.renegotiate > 2) { goto usage; } } else if (strcmp(p, "exchanges") == 0) { @@ -2455,7 +2455,7 @@ usage: #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_RENEGOTIATION) - if (opt.renegotiate) { + if (opt.renegotiate == 1) { /* * Perform renegotiation (this must be done when the server is waiting * for input from our side). @@ -2830,6 +2830,41 @@ send_request: goto send_request; } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if (opt.renegotiate == 2) { + opt.renegotiate = 0; + + /* Perform renegotiation after the first data exchange. */ + mbedtls_printf(" . Performing renegotiation..."); + fflush(stdout); + while ((ret = mbedtls_ssl_renegotiate(&ssl)) != 0) { + if (ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) { + mbedtls_printf(" failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", + ret); + goto exit; + } + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) { + continue; + } +#endif + + /* For event-driven IO, wait for socket to become available */ + if (opt.event == 1 /* level triggered IO */) { +#if defined(MBEDTLS_TIMING_C) + idle(&server_fd, &timer, ret); +#else + idle(&server_fd, ret); +#endif + } + } + mbedtls_printf(" ok\n"); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + /* * 7c. Simulate serialize/deserialize and go back to data exchange */ From a4e7d2b11e1e1e3009478d5985ef49962d92bedc Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 May 2026 20:52:38 +0200 Subject: [PATCH 070/168] Add tests for renegotiation with badmac_seen=1 on the server Signed-off-by: Gilles Peskine --- tests/ssl-opt.sh | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 24cf101439..045879e2a2 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -11826,6 +11826,25 @@ run_test "DTLS proxy: client: get invalid AD record then reject renego" \ -C "Verification of the message MAC failed" \ -C "Consume: waiting for more handshake fragments" +requires_config_enabled MBEDTLS_SSL_RENEGOTIATION +run_test "DTLS proxy: server: get invalid AD record then reject renego (cli)" \ + -p "$P_PXY bad_ad_cli_once=1" \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiation=0 exchanges=4 \ + badmac_limit=99 debug_level=3" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiation=1 renegotiate=2 exchanges=4 badmac_limit=99 debug_level=3" \ + 1 \ + -s "discarding invalid record (mac)" \ + -c "=> renegotiate" \ + -S "=> renegotiate" \ + -s "refusing renegotiation" \ + -s "Extra-header:" \ + -c "HTTP/1.0 200 OK" \ + -S "too many records with bad MAC" \ + -S "Verification of the message MAC failed" \ + -S "Consume: waiting for more handshake fragments" + requires_config_enabled MBEDTLS_SSL_RENEGOTIATION run_test "DTLS proxy: client: get invalid AD record then accept renego" \ -p "$P_PXY bad_ad_srv_once=1" \ @@ -11844,6 +11863,42 @@ run_test "DTLS proxy: client: get invalid AD record then accept renego" \ -C "Verification of the message MAC failed" \ -C "Consume: waiting for more handshake fragments" +requires_config_enabled MBEDTLS_SSL_RENEGOTIATION +run_test "DTLS proxy: server: get invalid AD record then accept renego (srv)" \ + -p "$P_PXY bad_ad_cli_once=1" \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiate=1 renegotiation=1 exchanges=4 \ + badmac_limit=99 debug_level=3" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiation=1 exchanges=4 badmac_limit=99 debug_level=3" \ + 0 \ + -s "discarding invalid record (mac)" \ + -s "=> renegotiate" \ + -c "=> renegotiate" \ + -s "Extra-header:" \ + -c "HTTP/1.0 200 OK" \ + -S "too many records with bad MAC" \ + -S "Verification of the message MAC failed" \ + -S "Consume: waiting for more handshake fragments" + +requires_config_enabled MBEDTLS_SSL_RENEGOTIATION +run_test "DTLS proxy: server: get invalid AD record then accept renego (cli)" \ + -p "$P_PXY bad_ad_cli_once=1" \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiation=1 exchanges=4 \ + badmac_limit=99 debug_level=3" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiation=1 renegotiate=2 exchanges=4 badmac_limit=99 debug_level=3" \ + 0 \ + -s "discarding invalid record (mac)" \ + -c "=> renegotiate" \ + -s "=> renegotiate" \ + -s "Extra-header:" \ + -c "HTTP/1.0 200 OK" \ + -S "too many records with bad MAC" \ + -S "Verification of the message MAC failed" \ + -S "Consume: waiting for more handshake fragments" + requires_config_enabled MBEDTLS_SSL_RENEGOTIATION run_test "DTLS proxy: client: get invalid AD record then reject early renego" \ -p "$P_PXY bad_ad_srv_once=1 delay_encrypted_hs_srv=3" \ @@ -11886,6 +11941,43 @@ run_test "DTLS proxy: client: get invalid AD record then accept early renego" -C "Verification of the message MAC failed" \ -C "Consume: waiting for more handshake fragments" +requires_config_enabled MBEDTLS_SSL_RENEGOTIATION +run_test "DTLS proxy: server: get invalid AD record then reject early renego (cli)" \ + -p "$P_PXY bad_ad_cli_once=1 delay_encrypted_hs_cli=2" \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiation=0 exchanges=4 \ + badmac_limit=99 debug_level=3" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiation=1 renegotiate=2 exchanges=4 badmac_limit=99 debug_level=3" \ + 1 \ + -s "discarding invalid record (mac)" \ + -c "=> renegotiate" \ + -S "=> renegotiate" \ + -s "refusing renegotiation" \ + -s "Extra-header:" \ + -c "HTTP/1.0 200 OK" \ + -S "too many records with bad MAC" \ + -S "Verification of the message MAC failed" \ + -S "Consume: waiting for more handshake fragments" + +requires_config_enabled MBEDTLS_SSL_RENEGOTIATION +run_test "DTLS proxy: server: get invalid AD record then accept early renego (cli)" \ + -p "$P_PXY bad_ad_cli_once=1 delay_encrypted_hs_cli=2" \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiation=1 exchanges=4 \ + badmac_limit=99 debug_level=3" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ + renegotiation=1 renegotiate=2 exchanges=4 badmac_limit=99 debug_level=3" \ + 0 \ + -s "discarding invalid record (mac)" \ + -c "=> renegotiate" \ + -s "=> renegotiate" \ + -s "Extra-header:" \ + -c "HTTP/1.0 200 OK" \ + -S "too many records with bad MAC" \ + -S "Verification of the message MAC failed" \ + -S "Consume: waiting for more handshake fragments" + requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS proxy: delay ChangeCipherSpec" \ -p "$P_PXY delay_ccs=1" \ From 41ee1448ba07906825d05639a24db5ba6e17fa3a Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 15 Jun 2026 13:08:43 +0200 Subject: [PATCH 071/168] Add DTLS handshake test with badmac_seen=1 Add a test entry point for a handshake with a specially crafted context. This can be used for defense in depths for scenarios that we think can't happen, but might actually happen due to a bug, or due to a new feature that is insufficiently tested. This can also be a proxy for testing aspects of renegotiation or session resumption in circumstances that are hard to arrange. In this commit, use it to test a DTLS handshake with `ssl->badmac_seen` :(actually `ssl->badmac_seen_or_in_hsfraglen` in the 3.6 branch) set to a nonzero value. This can't happen, as far as I know (`badmac_seen` can only be nonzero during renegotiation, not during a nominal handshake or in session resumption). But it could happen, for example, if `mbedtls_ssl_session_reset()` failed to reset `badmac_seen`, as was the case in Mbed TLS 4.0.0 to 4.1.0. Signed-off-by: Gilles Peskine --- tests/suites/test_suite_ssl.data | 8 ++++ tests/suites/test_suite_ssl.function | 67 ++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index da975a5b0d..09da227dac 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -471,6 +471,14 @@ Handshake, select ECDHE-ECDSA-WITH-AES-256-CCM, opaque, bad usage depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_CCM:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH handshake_ciphersuite_select:"TLS-ECDHE-ECDSA-WITH-AES-256-CCM":MBEDTLS_PK_ECDSA:"":PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_NONE:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE:0 +Handshake: DTLS 1.2, badmac_seen on client +depends_on:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SSL_PROTO_TLS1_2 +handshake_with_forced_context:1:MBEDTLS_SSL_VERSION_TLS1_2:PRE_HANDSHAKE_BADMAC_SEEN:0 + +Handshake: DTLS 1.2, badmac_seen on server +depends_on:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SSL_PROTO_TLS1_2 +handshake_with_forced_context:1:MBEDTLS_SSL_VERSION_TLS1_2:0:PRE_HANDSHAKE_BADMAC_SEEN + Sending app data via TLS, MFL=512 without fragmentation depends_on:MBEDTLS_SSL_MAX_FRAGMENT_LENGTH app_data_tls:MBEDTLS_SSL_MAX_FRAG_LEN_512:400:512:1:1 diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index f5492ff53c..b4bdf37553 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -66,6 +66,39 @@ exit: } #endif +typedef enum { + PRE_HANDSHAKE_BADMAC_SEEN = 1u << 0, +} pre_handshake_tweaks_t; + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) && \ + defined(PSA_HAVE_ALG_SOME_RSA_SIGN) && \ + defined(PSA_WANT_ECC_SECP_R1_384) && \ + defined(PSA_WANT_ALG_SHA_256) && \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ + defined(MBEDTLS_CAN_HANDLE_RSA_TEST_KEY) +typedef struct { + uint32_t client; + uint32_t server; +} pre_handshake_tweak_spec_t; + +static void pre_handshake_tweak_context(mbedtls_ssl_context *ssl, + int tweaks) +{ + if (tweaks & PRE_HANDSHAKE_BADMAC_SEEN) { + ssl->badmac_seen = 1; + } +} + +static void pre_handshake_tweak_contexts(mbedtls_test_ssl_endpoint *client, + mbedtls_test_ssl_endpoint *server, + void *param) +{ + const pre_handshake_tweak_spec_t *tweaks = param; + pre_handshake_tweak_context(&client->ssl, tweaks->client); + pre_handshake_tweak_context(&server->ssl, tweaks->server); +} +#endif + #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ @@ -3089,6 +3122,40 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */ +/* Test a handshake in forced conditions. + * + * This can be used for defense in depths for scenarios that we think + * can't happen, but might actually happen due to a bug, or due to + * a new feature that is insufficiently tested. + * + * This can also be a proxy for testing aspects of renegotiation or + * session resumption in circumstances that are hard to arrange. + */ +void handshake_with_forced_context(int dtls, int version, + int client_tweaks, int server_tweaks) +{ + pre_handshake_tweak_spec_t tweaks = { client_tweaks, server_tweaks }; + + mbedtls_test_handshake_test_options options; + mbedtls_test_init_handshake_options(&options); + options.dtls = dtls; + options.client_min_version = version; + options.client_max_version = version; + options.expected_negotiated_version = version; + options.pre_handshake_fun = &pre_handshake_tweak_contexts; + options.pre_handshake_param = &tweaks; + + mbedtls_test_ssl_perform_handshake(&options); + + /* The goto below is used to avoid an "unused label" warning.*/ + goto exit; + +exit: + mbedtls_test_free_handshake_options(&options); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256 */ void app_data(int mfl, int cli_msg_len, int srv_msg_len, int expected_cli_fragments, From bba465154a9de990a8076193f8271b1b099163c9 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 15 Jun 2026 13:37:54 +0200 Subject: [PATCH 072/168] Don't pass badmac_limit when it would have no effect Only set `badmac_limit` on the side that actually receives a message with a bad MAC/tag (injected by the proxy). Signed-off-by: Gilles Peskine --- tests/ssl-opt.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 045879e2a2..ff620aca99 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -11811,7 +11811,7 @@ run_test "DTLS proxy: client: get invalid AD record then reject renego" \ -p "$P_PXY bad_ad_srv_once=1" \ "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ renegotiate=1 renegotiation=1 exchanges=4 \ - badmac_limit=99 debug_level=3" \ + debug_level=3" \ "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ exchanges=4 badmac_limit=99 debug_level=3" \ 0 \ @@ -11833,7 +11833,7 @@ run_test "DTLS proxy: server: get invalid AD record then reject renego (cli)" renegotiation=0 exchanges=4 \ badmac_limit=99 debug_level=3" \ "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ - renegotiation=1 renegotiate=2 exchanges=4 badmac_limit=99 debug_level=3" \ + renegotiation=1 renegotiate=2 exchanges=4 debug_level=3" \ 1 \ -s "discarding invalid record (mac)" \ -c "=> renegotiate" \ @@ -11850,7 +11850,7 @@ run_test "DTLS proxy: client: get invalid AD record then accept renego" \ -p "$P_PXY bad_ad_srv_once=1" \ "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ renegotiate=1 renegotiation=1 exchanges=4 \ - badmac_limit=99 debug_level=3" \ + debug_level=3" \ "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ renegotiation=1 exchanges=4 badmac_limit=99 debug_level=3" \ 0 \ @@ -11870,7 +11870,7 @@ run_test "DTLS proxy: server: get invalid AD record then accept renego (srv)" renegotiate=1 renegotiation=1 exchanges=4 \ badmac_limit=99 debug_level=3" \ "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ - renegotiation=1 exchanges=4 badmac_limit=99 debug_level=3" \ + renegotiation=1 exchanges=4 debug_level=3" \ 0 \ -s "discarding invalid record (mac)" \ -s "=> renegotiate" \ @@ -11888,7 +11888,7 @@ run_test "DTLS proxy: server: get invalid AD record then accept renego (cli)" renegotiation=1 exchanges=4 \ badmac_limit=99 debug_level=3" \ "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ - renegotiation=1 renegotiate=2 exchanges=4 badmac_limit=99 debug_level=3" \ + renegotiation=1 renegotiate=2 exchanges=4 debug_level=3" \ 0 \ -s "discarding invalid record (mac)" \ -c "=> renegotiate" \ @@ -11948,7 +11948,7 @@ run_test "DTLS proxy: server: get invalid AD record then reject early renego renegotiation=0 exchanges=4 \ badmac_limit=99 debug_level=3" \ "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ - renegotiation=1 renegotiate=2 exchanges=4 badmac_limit=99 debug_level=3" \ + renegotiation=1 renegotiate=2 exchanges=4 debug_level=3" \ 1 \ -s "discarding invalid record (mac)" \ -c "=> renegotiate" \ @@ -11967,7 +11967,7 @@ run_test "DTLS proxy: server: get invalid AD record then accept early renego renegotiation=1 exchanges=4 \ badmac_limit=99 debug_level=3" \ "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ - renegotiation=1 renegotiate=2 exchanges=4 badmac_limit=99 debug_level=3" \ + renegotiation=1 renegotiate=2 exchanges=4 debug_level=3" \ 0 \ -s "discarding invalid record (mac)" \ -c "=> renegotiate" \ From c2f9cf34161b3b4fc429ef3e9601f6e16f26600e Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 15 Jun 2026 13:58:49 +0200 Subject: [PATCH 073/168] Explain the "get invalid AD record .*renego" tests better Signed-off-by: Gilles Peskine --- programs/ssl/ssl_client2.c | 5 ++++- tests/ssl-opt.sh | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index be1d2a8e2e..9dc99c3e0b 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2832,9 +2832,12 @@ send_request: #if defined(MBEDTLS_SSL_RENEGOTIATION) if (opt.renegotiate == 2) { + /* Perform renegotiation after the first data exchange. + * This is a one-time thing, we won't renegotiate even if there are + * more data exchanges that cause a `goto send_request` later. + */ opt.renegotiate = 0; - /* Perform renegotiation after the first data exchange. */ mbedtls_printf(" . Performing renegotiation..."); fflush(stdout); while ((ret = mbedtls_ssl_renegotiate(&ssl)) != 0) { diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index ff620aca99..1657729be9 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -11806,6 +11806,14 @@ run_test "DTLS proxy: inject invalid AD record, badmac_limit 2, exchanges 2"\ -s "too many records with bad MAC" \ -s "Verification of the message MAC failed" +# The next few tests exercise renegotiation in DTLS when `ssl->badmac_seen != 0`. +# +# This seems unrelated, but was the location of a bug in Mbed TLS 3.6.3 to +# 3.6.6 (CVE-2026-50713) due to `ssl->badmac_seen` being unified with +# `ssl->in_hsfraglen` (to preserve the ABI when adding support for handshake +# defragmentation in TLS in 3.6.3), with some mistakes in using the unified +# field that were fixed in 3.6.7. + requires_config_enabled MBEDTLS_SSL_RENEGOTIATION run_test "DTLS proxy: client: get invalid AD record then reject renego" \ -p "$P_PXY bad_ad_srv_once=1" \ @@ -11899,6 +11907,15 @@ run_test "DTLS proxy: server: get invalid AD record then accept renego (cli)" -S "Verification of the message MAC failed" \ -S "Consume: waiting for more handshake fragments" +# The next few tests have "early renego". A DTLS handshake message is delayed +# past another handshake message. From the perspective of the recipient, +# this means that a DTLS handshake arrives early (its epoch number is still +# in the future) and needs to be queued. +# +# In Mbed TLS 3.6.3 through 3.6.6, due to the fields `ssl->badmac_seen` +# and `ssl->in_hsfraglen` being unified, the early message was parsed +# incorrectly, leading to heap corruption. + requires_config_enabled MBEDTLS_SSL_RENEGOTIATION run_test "DTLS proxy: client: get invalid AD record then reject early renego" \ -p "$P_PXY bad_ad_srv_once=1 delay_encrypted_hs_srv=3" \ @@ -11921,6 +11938,13 @@ run_test "DTLS proxy: client: get invalid AD record then reject early renego" -C "Verification of the message MAC failed" \ -C "Consume: waiting for more handshake fragments" +# Delay the third encrypted handshake message from the server: +# 1. Finished message of the initial handshake. +# 2. HelloRequest to request renegotiation. +# 3. ServerHello of renegotiation, delayed. +# 4. Subsequent handshake message, which the client receives and enqueues. +# +# In Mbed TLS 3.6.3 though 3.6.6, the processing of (4) caused heap corruption. requires_config_enabled MBEDTLS_SSL_RENEGOTIATION run_test "DTLS proxy: client: get invalid AD record then accept early renego" \ -p "$P_PXY bad_ad_srv_once=1 delay_encrypted_hs_srv=3" \ From 94370bc4e47f25ffe5a3202d8350bb5b88cfaafe Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 15 Jun 2026 18:22:11 +0200 Subject: [PATCH 074/168] Remove some test cases that are not really meaningful Remove the "srv" variant of "DTLS proxy: server: get invalid AD record then accept renego", where the server initiates the renegotiation process by sending a HelloRequest. The HelloRequest message is not relevant to this test. The first message of the actual renegotiation is the ClientHello message from the client, and the interesting part of the test happens when the client receives the server's response. Remove "DTLS proxy: server: get invalid AD record then accept early renego (cli)" and the corresponding "reject" control. This test case doesn't really do what it is advertised to do, and in particular does not lead to a call to `ssl_consume_current_message()` in the server. What happens is that the client sends a ClientHello message to start the renegotiation, then it blocks until the server has replied. So there is nothing to delay that ClientHello after:(unlike what happens in the corresponding client-side test, where the first flight of the renegotiation protocol contains multiple messages, so we can delay the first of these messages after the second one). What happens in practice is that the client times out, then resends its ClientHello, and the proxy sends the delayed ClientHello immediately after the resent one, which does not cause any interesting behavior in the server. Signed-off-by: Gilles Peskine --- tests/ssl-opt.sh | 59 ++---------------------------------------------- 1 file changed, 2 insertions(+), 57 deletions(-) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 1657729be9..e6ad70ee72 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -11835,7 +11835,7 @@ run_test "DTLS proxy: client: get invalid AD record then reject renego" \ -C "Consume: waiting for more handshake fragments" requires_config_enabled MBEDTLS_SSL_RENEGOTIATION -run_test "DTLS proxy: server: get invalid AD record then reject renego (cli)" \ +run_test "DTLS proxy: server: get invalid AD record then reject renego" \ -p "$P_PXY bad_ad_cli_once=1" \ "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ renegotiation=0 exchanges=4 \ @@ -11872,25 +11872,7 @@ run_test "DTLS proxy: client: get invalid AD record then accept renego" \ -C "Consume: waiting for more handshake fragments" requires_config_enabled MBEDTLS_SSL_RENEGOTIATION -run_test "DTLS proxy: server: get invalid AD record then accept renego (srv)" \ - -p "$P_PXY bad_ad_cli_once=1" \ - "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ - renegotiate=1 renegotiation=1 exchanges=4 \ - badmac_limit=99 debug_level=3" \ - "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ - renegotiation=1 exchanges=4 debug_level=3" \ - 0 \ - -s "discarding invalid record (mac)" \ - -s "=> renegotiate" \ - -c "=> renegotiate" \ - -s "Extra-header:" \ - -c "HTTP/1.0 200 OK" \ - -S "too many records with bad MAC" \ - -S "Verification of the message MAC failed" \ - -S "Consume: waiting for more handshake fragments" - -requires_config_enabled MBEDTLS_SSL_RENEGOTIATION -run_test "DTLS proxy: server: get invalid AD record then accept renego (cli)" \ +run_test "DTLS proxy: server: get invalid AD record then accept renego" \ -p "$P_PXY bad_ad_cli_once=1" \ "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ renegotiation=1 exchanges=4 \ @@ -11965,43 +11947,6 @@ run_test "DTLS proxy: client: get invalid AD record then accept early renego" -C "Verification of the message MAC failed" \ -C "Consume: waiting for more handshake fragments" -requires_config_enabled MBEDTLS_SSL_RENEGOTIATION -run_test "DTLS proxy: server: get invalid AD record then reject early renego (cli)" \ - -p "$P_PXY bad_ad_cli_once=1 delay_encrypted_hs_cli=2" \ - "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ - renegotiation=0 exchanges=4 \ - badmac_limit=99 debug_level=3" \ - "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ - renegotiation=1 renegotiate=2 exchanges=4 debug_level=3" \ - 1 \ - -s "discarding invalid record (mac)" \ - -c "=> renegotiate" \ - -S "=> renegotiate" \ - -s "refusing renegotiation" \ - -s "Extra-header:" \ - -c "HTTP/1.0 200 OK" \ - -S "too many records with bad MAC" \ - -S "Verification of the message MAC failed" \ - -S "Consume: waiting for more handshake fragments" - -requires_config_enabled MBEDTLS_SSL_RENEGOTIATION -run_test "DTLS proxy: server: get invalid AD record then accept early renego (cli)" \ - -p "$P_PXY bad_ad_cli_once=1 delay_encrypted_hs_cli=2" \ - "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \ - renegotiation=1 exchanges=4 \ - badmac_limit=99 debug_level=3" \ - "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \ - renegotiation=1 renegotiate=2 exchanges=4 debug_level=3" \ - 0 \ - -s "discarding invalid record (mac)" \ - -c "=> renegotiate" \ - -s "=> renegotiate" \ - -s "Extra-header:" \ - -c "HTTP/1.0 200 OK" \ - -S "too many records with bad MAC" \ - -S "Verification of the message MAC failed" \ - -S "Consume: waiting for more handshake fragments" - requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS proxy: delay ChangeCipherSpec" \ -p "$P_PXY delay_ccs=1" \ From 4e057619a95d17626ffeb5385e3b7838ab2d2da2 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Fri, 29 May 2026 18:01:16 +0200 Subject: [PATCH 075/168] x509_crt: remove old invalid comment ssl_preset_default_hashes was removed in f0cda410a4bca0f45f66bdbf0714cd0eb2ea4718 but the comment in 'x509_crt.c' wasn't updated. Signed-off-by: Valerio Setti --- library/x509_crt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index 093d733c1c..3938242298 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -87,8 +87,7 @@ typedef struct { * concerns. */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = { - /* Hashes from SHA-256 and above. Note that this selection - * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */ + /* Hashes from SHA-256 and above. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), From 24a184ad36df7575dfd2d069f7afb25d6813a690 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Fri, 29 May 2026 18:02:59 +0200 Subject: [PATCH 076/168] x509_crt: add SHA3 algs to mbedtls_x509_crt_profile_default Signed-off-by: Valerio Setti --- library/x509_crt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index 3938242298..e4fedb194a 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -90,7 +90,10 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = /* Hashes from SHA-256 and above. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA3_256) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA3_384) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA3_512), 0xFFFFFFF, /* Any PK alg */ #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) /* Curves at or above 128-bit security level. Note that this selection From 395bc86df8928dc188fae28d7b6512b61af0e9e2 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Fri, 29 May 2026 18:17:52 +0200 Subject: [PATCH 077/168] x509: make profile checking functions internally available Following functions - x509_profile_check_md_alg - x509_profile_check_pk_alg are made non-static and moved to x509_internal.h so that other library files can used them. Signed-off-by: Valerio Setti --- library/x509_crt.c | 26 +++++++++----------------- library/x509_internal.h | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index e4fedb194a..a6fcd1b4e6 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -167,12 +167,8 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none = (uint32_t) -1, }; -/* - * Check md_alg against profile - * Return 0 if md_alg is acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile, - mbedtls_md_type_t md_alg) +int mbedtls_x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile, + mbedtls_md_type_t md_alg) { if (md_alg == MBEDTLS_MD_NONE) { return -1; @@ -185,12 +181,8 @@ static int x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile, return -1; } -/* - * Check pk_alg against profile - * Return 0 if pk_alg is acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile, - mbedtls_pk_sigalg_t pk_alg) +int mbedtls_x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile, + mbedtls_pk_sigalg_t pk_alg) { if (pk_alg == MBEDTLS_PK_SIGALG_NONE) { return -1; @@ -2050,11 +2042,11 @@ static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, /* * Check if CRL is correctly signed by the trusted CA */ - if (x509_profile_check_md_alg(profile, crl_list->sig_md) != 0) { + if (mbedtls_x509_profile_check_md_alg(profile, crl_list->sig_md) != 0) { flags |= MBEDTLS_X509_BADCRL_BAD_MD; } - if (x509_profile_check_pk_alg(profile, crl_list->sig_pk) != 0) { + if (mbedtls_x509_profile_check_pk_alg(profile, crl_list->sig_pk) != 0) { flags |= MBEDTLS_X509_BADCRL_BAD_PK; } @@ -2563,11 +2555,11 @@ static int x509_crt_verify_chain( } /* Check signature algorithm: MD & PK algs */ - if (x509_profile_check_md_alg(profile, child->sig_md) != 0) { + if (mbedtls_x509_profile_check_md_alg(profile, child->sig_md) != 0) { *flags |= MBEDTLS_X509_BADCERT_BAD_MD; } - if (x509_profile_check_pk_alg(profile, child->sig_pk) != 0) { + if (mbedtls_x509_profile_check_pk_alg(profile, child->sig_pk) != 0) { *flags |= MBEDTLS_X509_BADCERT_BAD_PK; } @@ -3075,7 +3067,7 @@ static int x509_crt_verify_restartable_ca_cb(mbedtls_x509_crt *crt, /* Check the type and size of the key */ pk_type = mbedtls_pk_get_type(&crt->pk); - if (x509_profile_check_pk_alg(profile, (mbedtls_pk_sigalg_t) pk_type) != 0) { + if (mbedtls_x509_profile_check_pk_alg(profile, (mbedtls_pk_sigalg_t) pk_type) != 0) { ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; } diff --git a/library/x509_internal.h b/library/x509_internal.h index fcb996b19d..f68b6593bd 100644 --- a/library/x509_internal.h +++ b/library/x509_internal.h @@ -15,6 +15,7 @@ #include "mbedtls/private_access.h" #include "mbedtls/x509.h" +#include "mbedtls/x509_crt.h" #include "mbedtls/asn1.h" #include "pk_internal.h" // for a lot of things, including in SSL @@ -79,4 +80,18 @@ int mbedtls_x509_info_key_usage(char **buf, size_t *size, int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions, const mbedtls_x509_san_list *san_list); +/* + * Check md_alg against profile + * Return 0 if md_alg is acceptable for this profile, -1 otherwise + */ +int mbedtls_x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile, + mbedtls_md_type_t md_alg); + +/* + * Check pk_alg against profile + * Return 0 if pk_alg is acceptable for this profile, -1 otherwise + */ +int mbedtls_x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile, + mbedtls_pk_sigalg_t pk_alg); + #endif /* MBEDTLS_X509_INTERNAL_H */ From c25e7654ea6bb1e95743f0ae8e12b957a1cf67a6 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Fri, 29 May 2026 18:22:51 +0200 Subject: [PATCH 078/168] pkcs7: fail verification if MD alg or sig_alg are not secure Add a check on mbedtls_pkcs7_data_or_hash_verify() so that the verification fails if the MD alg specified in PKCS7 structure or the signature algorithm specified in the X.509 certificate are not in the list of secure algorithms (i.e. mbedtls_x509_crt_profile_default). Signed-off-by: Valerio Setti --- library/pkcs7.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/pkcs7.c b/library/pkcs7.c index 2cc7812bf0..1e952998cc 100644 --- a/library/pkcs7.c +++ b/library/pkcs7.c @@ -665,6 +665,14 @@ static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7, return ret; } + /* Ensure the MD alg from the PKCS#7 context and signature algorithm from + * the certificate belong to the list of secure algorithms + * (i.e. mbedtls_x509_crt_profile_default). */ + if (mbedtls_x509_profile_check_md_alg(&mbedtls_x509_crt_profile_default, md_alg) || + mbedtls_x509_profile_check_pk_alg(&mbedtls_x509_crt_profile_default, cert->sig_pk)) { + return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + } + md_info = mbedtls_md_info_from_type(md_alg); if (md_info == NULL) { return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; From 632c4fce0e7a39bb367163be2964b24e569c0e0b Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 10 Jun 2026 12:03:27 +0200 Subject: [PATCH 079/168] tests: pkcs7: adjust return code in SHA-1 based PKCS7 test Signed-off-by: Valerio Setti --- tests/suites/test_suite_pkcs7.data | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data index 3e3f7f1d7d..25659c2f29 100644 --- a/tests/suites/test_suite_pkcs7.data +++ b/tests/suites/test_suite_pkcs7.data @@ -86,9 +86,9 @@ PKCS7 Signed Data Verification Pass SHA256 #9.1 depends_on:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha256.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":MBEDTLS_MD_SHA256:0 -PKCS7 Signed Data Verification Pass SHA1 #10 +PKCS7 Signed Data Verification Fail SHA1 #10 depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY -pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha1.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:0 +pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha1.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:PSA_ERROR_INVALID_SIGNATURE PKCS7 Signed Data Verification Pass SHA512 #11 depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY From 394d8e6a6f6fe41663795d739c7e9e7804392a32 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 10 Jun 2026 16:44:36 +0200 Subject: [PATCH 080/168] changelog: add note for PKCS7 rejecting weak hash algorithms Signed-off-by: Valerio Setti --- ChangeLog.d/pkcs7-reject-weak-hashes.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 ChangeLog.d/pkcs7-reject-weak-hashes.txt diff --git a/ChangeLog.d/pkcs7-reject-weak-hashes.txt b/ChangeLog.d/pkcs7-reject-weak-hashes.txt new file mode 100644 index 0000000000..61cc03affe --- /dev/null +++ b/ChangeLog.d/pkcs7-reject-weak-hashes.txt @@ -0,0 +1,3 @@ +Security + * PKCS7 now rejects weak hash algorithms (RIPEMD160, MD5, SHA-1) on signature + verification. From 930b87a87ea99b828a0d0111cc0eb2c46dad37a3 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Thu, 11 Jun 2026 17:15:14 +0200 Subject: [PATCH 081/168] tests: pkcs7: add negative tests using MD5 and RIPEMD160 Signed-off-by: Valerio Setti --- tests/suites/test_suite_pkcs7.data | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data index 25659c2f29..301d95ed44 100644 --- a/tests/suites/test_suite_pkcs7.data +++ b/tests/suites/test_suite_pkcs7.data @@ -94,6 +94,14 @@ PKCS7 Signed Data Verification Pass SHA512 #11 depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha512.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:0 +PKCS7 Signed Data Verification Fail MD5 #12 +depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_MD5:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY +pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_md5.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:PSA_ERROR_INVALID_SIGNATURE + +PKCS7 Signed Data Verification Fail RIPEMD160 #13 +depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_RIPEMD160:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY +pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_ripemd160.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:PSA_ERROR_INVALID_SIGNATURE + PKCS7 Signed Data Verification Fail because of different certificate #12 depends_on:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha256.der":"../framework/data_files/pkcs7-rsa-sha256-2.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_RSA_VERIFY_FAILED From 45654b0246251afd681430c617391521fe93382b Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 15 Jun 2026 10:14:24 +0200 Subject: [PATCH 082/168] pkcs7: split MD/PK check in mbedtls_pkcs7_data_or_hash_verify Follow the default Mbed TLS coding style and ease debugging (i.e. placing of breakpoints). Signed-off-by: Valerio Setti --- library/pkcs7.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/pkcs7.c b/library/pkcs7.c index 1e952998cc..885ead6cb1 100644 --- a/library/pkcs7.c +++ b/library/pkcs7.c @@ -668,8 +668,12 @@ static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7, /* Ensure the MD alg from the PKCS#7 context and signature algorithm from * the certificate belong to the list of secure algorithms * (i.e. mbedtls_x509_crt_profile_default). */ - if (mbedtls_x509_profile_check_md_alg(&mbedtls_x509_crt_profile_default, md_alg) || - mbedtls_x509_profile_check_pk_alg(&mbedtls_x509_crt_profile_default, cert->sig_pk)) { + ret = mbedtls_x509_profile_check_md_alg(&mbedtls_x509_crt_profile_default, md_alg); + if (ret != 0) { + return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + } + ret = mbedtls_x509_profile_check_pk_alg(&mbedtls_x509_crt_profile_default, cert->sig_pk); + if (ret != 0) { return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; } From 64d8776ea9b49f278664b3d3db9ab5539e17ca10 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 15 Jun 2026 10:24:39 +0200 Subject: [PATCH 083/168] pkcs7: replace MBEDTLS_ERR_PKCS7_VERIFY_FAIL with MBEDTLS_ERR_PKCS7_VERIFY_FAIL This also updates test data. Signed-off-by: Valerio Setti --- library/pkcs7.c | 4 ++-- tests/suites/test_suite_pkcs7.data | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/pkcs7.c b/library/pkcs7.c index 885ead6cb1..365f7eac64 100644 --- a/library/pkcs7.c +++ b/library/pkcs7.c @@ -670,11 +670,11 @@ static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7, * (i.e. mbedtls_x509_crt_profile_default). */ ret = mbedtls_x509_profile_check_md_alg(&mbedtls_x509_crt_profile_default, md_alg); if (ret != 0) { - return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + return MBEDTLS_ERR_PKCS7_INVALID_ALG; } ret = mbedtls_x509_profile_check_pk_alg(&mbedtls_x509_crt_profile_default, cert->sig_pk); if (ret != 0) { - return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + return MBEDTLS_ERR_PKCS7_INVALID_ALG; } md_info = mbedtls_md_info_from_type(md_alg); diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data index 301d95ed44..0cd899fc27 100644 --- a/tests/suites/test_suite_pkcs7.data +++ b/tests/suites/test_suite_pkcs7.data @@ -88,7 +88,7 @@ pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha256.der":"../fra PKCS7 Signed Data Verification Fail SHA1 #10 depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY -pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha1.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:PSA_ERROR_INVALID_SIGNATURE +pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha1.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_PKCS7_INVALID_ALG PKCS7 Signed Data Verification Pass SHA512 #11 depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY @@ -96,11 +96,11 @@ pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha512.der":"../fra PKCS7 Signed Data Verification Fail MD5 #12 depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_MD5:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY -pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_md5.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:PSA_ERROR_INVALID_SIGNATURE +pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_md5.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_PKCS7_INVALID_ALG PKCS7 Signed Data Verification Fail RIPEMD160 #13 depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_RIPEMD160:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY -pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_ripemd160.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:PSA_ERROR_INVALID_SIGNATURE +pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_ripemd160.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_PKCS7_INVALID_ALG PKCS7 Signed Data Verification Fail because of different certificate #12 depends_on:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY From 00a2677b1eb0af2cb70c09678281560002c68665 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 15 Jun 2026 10:26:11 +0200 Subject: [PATCH 084/168] test_suite_pkcs7: adjust numbering of tests Some newly added tests had duplicate numbers with what was already there. This commit fixes the duplication problem. Signed-off-by: Valerio Setti --- tests/suites/test_suite_pkcs7.data | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data index 0cd899fc27..46d4078fc0 100644 --- a/tests/suites/test_suite_pkcs7.data +++ b/tests/suites/test_suite_pkcs7.data @@ -90,18 +90,18 @@ PKCS7 Signed Data Verification Fail SHA1 #10 depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha1.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_PKCS7_INVALID_ALG -PKCS7 Signed Data Verification Pass SHA512 #11 -depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY -pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha512.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:0 - -PKCS7 Signed Data Verification Fail MD5 #12 +PKCS7 Signed Data Verification Fail MD5 #10.1 depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_MD5:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_md5.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_PKCS7_INVALID_ALG -PKCS7 Signed Data Verification Fail RIPEMD160 #13 +PKCS7 Signed Data Verification Fail RIPEMD160 #10.2 depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_RIPEMD160:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_ripemd160.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_PKCS7_INVALID_ALG +PKCS7 Signed Data Verification Pass SHA512 #11 +depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY +pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha512.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:0 + PKCS7 Signed Data Verification Fail because of different certificate #12 depends_on:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha256.der":"../framework/data_files/pkcs7-rsa-sha256-2.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_RSA_VERIFY_FAILED From f065e47b18f14fbdb532eb09e2434c4d95c8094c Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 15 Jun 2026 10:34:22 +0200 Subject: [PATCH 085/168] changelog: update documentation for PKCS7 changes Signed-off-by: Valerio Setti --- ChangeLog.d/pkcs7-reject-weak-hashes.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog.d/pkcs7-reject-weak-hashes.txt b/ChangeLog.d/pkcs7-reject-weak-hashes.txt index 61cc03affe..a62cca9b96 100644 --- a/ChangeLog.d/pkcs7-reject-weak-hashes.txt +++ b/ChangeLog.d/pkcs7-reject-weak-hashes.txt @@ -1,3 +1,7 @@ Security - * PKCS7 now rejects weak hash algorithms (RIPEMD160, MD5, SHA-1) on signature - verification. + * PKCS7 now rejects weak hash algorithms (RIPEMD160, MD5, SHA-1, SHA-224, + SHA3-224) on signature verification. + +Features + * SHA3-256, SHA3-384 and SHA3-512 are now accepted in the default X.509 + certificate profile. From feb2c53009340a8c99083503c66b285a08302ea8 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 15 Jun 2026 10:49:56 +0200 Subject: [PATCH 086/168] pkcs7: update documentation adding a note about rejecting weak hash algs Signed-off-by: Valerio Setti --- include/mbedtls/pkcs7.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/mbedtls/pkcs7.h b/include/mbedtls/pkcs7.h index 957ca53d71..aa9764e19a 100644 --- a/include/mbedtls/pkcs7.h +++ b/include/mbedtls/pkcs7.h @@ -31,6 +31,10 @@ * assumed these fields are empty. * - The RFC allows for the signed Data type to contain contentInfo. This * implementation assumes the type is DATA and the content is empty. + * - The RFC doesn't put any constrain on the hash algorithm to be used, but + * this implementation rejects weak hash algorithms (i.e. RIPEMD160, MD5, + * SHA-1, SHA-224, SHA3-224). In general accepted hash and PK algorithms are + * the ones belonging to `mbedtls_x509_crt_profile_default`. */ #ifndef MBEDTLS_PKCS7_H @@ -190,6 +194,9 @@ int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf, * \note This function internally calculates the hash on the supplied * plain data for signature verification. * + * \note For limitation on the supported hash algorithms, please refer + * to the note at the top of this document. + * * \return 0 if the signature verifies, or a negative error code on failure. */ int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, @@ -219,6 +226,9 @@ int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, * \note This function is different from mbedtls_pkcs7_signed_data_verify() * in that it is directly passed the hash of the data. * + * \note For limitation on the supported hash algorithms, please refer + * to the note at the top of this document. + * * \return 0 if the signature verifies, or a negative error code on failure. */ int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7, From 869bd519fbac71d0e005b4c2935fc2ce14bc2799 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 16 Jun 2026 11:43:41 +0200 Subject: [PATCH 087/168] tests: pkcs7: adjust test dependencies Newly added tests for RIPEMD160 and MD5 still require SHA-256 for the certificate being used. SHA-1 is instead useless in this case. Signed-off-by: Valerio Setti --- tests/suites/test_suite_pkcs7.data | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data index 46d4078fc0..86dc4ed844 100644 --- a/tests/suites/test_suite_pkcs7.data +++ b/tests/suites/test_suite_pkcs7.data @@ -91,11 +91,11 @@ depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VER pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha1.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_PKCS7_INVALID_ALG PKCS7 Signed Data Verification Fail MD5 #10.1 -depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_MD5:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY +depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_md5.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_PKCS7_INVALID_ALG PKCS7 Signed Data Verification Fail RIPEMD160 #10.2 -depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_RIPEMD160:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY +depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_SHA_256:PSA_HAVE_ALG_RSA_PKCS1V15_VERIFY pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_ripemd160.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_PKCS7_INVALID_ALG PKCS7 Signed Data Verification Pass SHA512 #11 From f155d9fefd3d8cc59c7294ca1bcbed7715b0d9ae Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Thu, 11 Jun 2026 17:13:08 +0200 Subject: [PATCH 088/168] framework: update reference Signed-off-by: Valerio Setti --- framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework b/framework index e0f6275eff..d6dec17adf 160000 --- a/framework +++ b/framework @@ -1 +1 @@ -Subproject commit e0f6275eff2e45e295fdd6b6877de4cbdaddae83 +Subproject commit d6dec17adfb5bf283c6a7a5bb6c451ecdc0b8201 From de8a0d3fdb6e6b33fb6aa1883af9496e28fad3dc Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Mon, 22 Jun 2026 22:29:15 +0100 Subject: [PATCH 089/168] Added CVE Signed-off-by: Minos Galanakis --- ChangeLog.d/tls13-hrr-selected-group.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/tls13-hrr-selected-group.txt b/ChangeLog.d/tls13-hrr-selected-group.txt index 20d7a18fbd..c318b393fc 100644 --- a/ChangeLog.d/tls13-hrr-selected-group.txt +++ b/ChangeLog.d/tls13-hrr-selected-group.txt @@ -2,4 +2,4 @@ Security * Fix TLS 1.3 clients to reject a HelloRetryRequest whose selected group was not advertised in the original ClientHello. Reported by Din Asotić / Xiangdong Li, Beijing University of Posts and - Telecommunications (BUPT) + Telecommunications (BUPT). CVE-2026-25832 From 567a3a443d5029ef1e2ada99d290152dcbbf08c3 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Mon, 22 Jun 2026 22:32:25 +0100 Subject: [PATCH 090/168] Added attribution Signed-off-by: Minos Galanakis --- ChangeLog.d/tls13-hrr-selected-group.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ChangeLog.d/tls13-hrr-selected-group.txt b/ChangeLog.d/tls13-hrr-selected-group.txt index c318b393fc..4c338480f6 100644 --- a/ChangeLog.d/tls13-hrr-selected-group.txt +++ b/ChangeLog.d/tls13-hrr-selected-group.txt @@ -1,5 +1,7 @@ Security * Fix TLS 1.3 clients to reject a HelloRetryRequest whose selected group was - not advertised in the original ClientHello. Reported by + not advertised in the original ClientHello. Reported independently by Din Asotić / Xiangdong Li, Beijing University of Posts and - Telecommunications (BUPT). CVE-2026-25832 + Telecommunications (BUPT), and NVIDIA Project Vanessa. + CVE-2026-25832. + From 9063aca165efaa68c08f95159c4e84e0f17464a9 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 14 May 2026 11:27:05 +0100 Subject: [PATCH 091/168] ssl: propagate transcript-hash computation failures Signed-off-by: Ben Taylor --- library/ssl_tls.c | 1 + library/ssl_tls13_server.c | 1 + 2 files changed, 2 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index e8a44f834c..7ddaa12202 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -6297,6 +6297,7 @@ static int ssl_compute_master(mbedtls_ssl_handshake_params *handshake, ret = handshake->calc_verify(ssl, session_hash, &seed_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "calc_verify", ret); + return ret; } MBEDTLS_SSL_DEBUG_BUF(3, "session hash for extended master secret", diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index 37fdf79ee3..38f2fe9370 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -3077,6 +3077,7 @@ static int ssl_tls13_process_client_finished(mbedtls_ssl_context *ssl) if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_compute_resumption_master_secret", ret); + return ret; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP); From 5871216afc47bbafaadc71fa3f226061ffb82f6f Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 14 May 2026 11:27:15 +0100 Subject: [PATCH 092/168] tests: ssl: add regression tests for EMS/RMS error propagation Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.data | 6 + tests/suites/test_suite_ssl.function | 185 +++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 9bf4c1f0bf..ef6ac36909 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3378,6 +3378,12 @@ elliptic_curve_get_properties TLS 1.3 resume session with ticket tls13_resume_session_with_ticket +TLS 1.3 server propagates RMS computation error +tls13_server_propagates_rms_error + +TLS 1.2 server propagates EMS computation error +tls12_server_propagates_ems_error + TLS 1.3 read early data, early data accepted tls13_read_early_data:TEST_EARLY_DATA_ACCEPTED diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index cc73f49aaf..09cd48a525 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -55,6 +55,163 @@ static int failing_ticket_write_unset_lifetime( PSA_WANT_ALG_SHA_256 && PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY && MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */ +#if defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_DEBUG_C) && \ + defined(PSA_HAVE_ALG_SOME_RSA_SIGN) && \ + ((defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) && \ + defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) && \ + defined(MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE) && \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) && \ + defined(PSA_WANT_ALG_SHA_256) && \ + defined(PSA_WANT_ECC_SECP_R1_256) && \ + defined(PSA_WANT_ECC_SECP_R1_384) && \ + defined(PSA_HAVE_ALG_ECDSA_VERIFY) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS)) || \ + (defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) && \ + defined(PSA_WANT_ALG_SHA_256) && \ + defined(PSA_WANT_ECC_SECP_R1_384) && \ + defined(PSA_HAVE_ALG_ECDSA_VERIFY))) +typedef struct { + mbedtls_ssl_context *ssl; + const char *trigger; + int triggered; +} tls_abort_transcript_context; + +static void tls_abort_transcript(void *ctx, int level, + const char *file, int line, + const char *str) +{ + tls_abort_transcript_context *abort_ctx = ctx; + + (void) level; + (void) file; + (void) line; + + if (abort_ctx->triggered || abort_ctx->ssl == NULL || + abort_ctx->ssl->handshake == NULL || + abort_ctx->trigger == NULL || + strstr(str, abort_ctx->trigger) == NULL) { + return; + } + + abort_ctx->triggered = 1; + psa_hash_abort(&abort_ctx->ssl->handshake->fin_sha256_psa); +#if defined(PSA_WANT_ALG_SHA_384) + psa_hash_abort(&abort_ctx->ssl->handshake->fin_sha384_psa); +#endif +} + +static void tls_server_error(mbedtls_ssl_protocol_version tls_version, + const char *trigger, + int server_state, + int client_state) +{ + int ret = -1; + int max_steps = 100; + mbedtls_test_ssl_endpoint client_ep, server_ep; + mbedtls_test_handshake_test_options client_options; + mbedtls_test_handshake_test_options server_options; + tls_abort_transcript_context abort_ctx; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + unsigned char psk[] = "abcdefghijklmnop"; + data_t psk_data = { psk, sizeof(psk) - 1 }; +#endif + + memset(&client_ep, 0, sizeof(client_ep)); + memset(&server_ep, 0, sizeof(server_ep)); + memset(&abort_ctx, 0, sizeof(abort_ctx)); + mbedtls_test_init_handshake_options(&client_options); + mbedtls_test_init_handshake_options(&server_options); + + PSA_INIT(); + + client_options.client_min_version = tls_version; + client_options.client_max_version = tls_version; + server_options.server_min_version = tls_version; + server_options.server_max_version = tls_version; + + abort_ctx.trigger = trigger; + server_options.srv_log_obj = &abort_ctx; + server_options.srv_log_fun = tls_abort_transcript; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + client_options.psk_str = &psk_data; + } +#endif + + mbedtls_debug_set_threshold(4); + + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, + &client_options), 0); + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, + &server_options), 0); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) + if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + TEST_EQUAL(mbedtls_ssl_conf_psk(&server_ep.conf, psk, sizeof(psk) - 1, + (const unsigned char *) "foo", + strlen("foo")), 0); + mbedtls_ssl_conf_tls13_key_exchange_modes( + &client_ep.conf, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK); + mbedtls_ssl_conf_tls13_key_exchange_modes( + &server_ep.conf, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK); + mbedtls_ssl_conf_session_tickets_cb(&server_ep.conf, + mbedtls_test_ticket_write, + mbedtls_test_ticket_parse, + NULL); + } +#endif + + TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket), + &(server_ep.socket), 1024), 0); + + abort_ctx.ssl = &server_ep.ssl; + + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(server_ep.ssl), &(client_ep.ssl), + server_state), 0); + + TEST_EQUAL(mbedtls_ssl_flush_output(&(server_ep.ssl)), 0); + + TEST_EQUAL(server_ep.ssl.state, server_state); + + TEST_EQUAL(abort_ctx.triggered, 0); + + while (client_ep.ssl.state != client_state && + --max_steps >= 0) { + ret = mbedtls_ssl_handshake_step(&(client_ep.ssl)); + TEST_ASSERT(ret == 0 || ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE); + } + + TEST_ASSERT(max_steps >= 0); + + TEST_EQUAL(client_ep.ssl.state, client_state); + TEST_EQUAL(server_ep.ssl.state, server_state); + + TEST_EQUAL(abort_ctx.triggered, 0); + + ret = mbedtls_ssl_handshake_step(&(server_ep.ssl)); + TEST_ASSERT(abort_ctx.triggered); + TEST_ASSERT(ret != 0); + + TEST_EQUAL(server_ep.ssl.state, server_state); + +exit: + mbedtls_test_ssl_endpoint_free(&client_ep); + mbedtls_test_ssl_endpoint_free(&server_ep); + mbedtls_test_free_handshake_options(&client_options); + mbedtls_test_free_handshake_options(&server_options); + mbedtls_debug_set_threshold(0); + PSA_DONE(); +} +#endif + #if (!defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \ defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) && \ defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_DEBUG_C) && \ @@ -4358,6 +4515,34 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_DEBUG_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_HAVE_ALG_SOME_RSA_SIGN:MBEDTLS_SSL_SESSION_TICKETS */ +void tls13_server_propagates_rms_error() +{ + tls_server_error(MBEDTLS_SSL_VERSION_TLS1_3, + "<= parse finished message", + MBEDTLS_SSL_CLIENT_FINISHED, + MBEDTLS_SSL_FLUSH_BUFFERS); + goto exit; + +exit: + ; +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_DEBUG_C:MBEDTLS_SSL_EXTENDED_MASTER_SECRET:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_384:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_HAVE_ALG_SOME_RSA_SIGN:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ +void tls12_server_propagates_ems_error() +{ + tls_server_error(MBEDTLS_SSL_VERSION_TLS1_2, + "=> derive keys", + MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_VERIFY); + goto exit; + +exit: + ; +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_HAVE_ALG_ECDSA_VERIFY:MBEDTLS_SSL_SESSION_TICKETS */ void tls13_resume_session_with_ticket() { From ae6b06ce4c4685ea14b85502c3bb46e98d592c3c Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 15 May 2026 18:42:45 +0200 Subject: [PATCH 093/168] Improve dependencies and error handling Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.data | 6 +- tests/suites/test_suite_ssl.function | 215 +++++++++------------------ 2 files changed, 72 insertions(+), 149 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index ef6ac36909..c93ff542e9 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3379,10 +3379,12 @@ TLS 1.3 resume session with ticket tls13_resume_session_with_ticket TLS 1.3 server propagates RMS computation error -tls13_server_propagates_rms_error +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT +tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3:"<= parse finished message":MBEDTLS_SSL_CLIENT_FINISHED:MBEDTLS_SSL_FLUSH_BUFFERS TLS 1.2 server propagates EMS computation error -tls12_server_propagates_ems_error +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:MBEDTLS_SSL_CERTIFICATE_VERIFY TLS 1.3 read early data, early data accepted tls13_read_early_data:TEST_EARLY_DATA_ACCEPTED diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 09cd48a525..a68a6fcf3f 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -55,25 +55,11 @@ static int failing_ticket_write_unset_lifetime( PSA_WANT_ALG_SHA_256 && PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY && MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */ -#if defined(MBEDTLS_SSL_CLI_C) && \ - defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_DEBUG_C) && \ - defined(PSA_HAVE_ALG_SOME_RSA_SIGN) && \ - ((defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ +#if defined(MBEDTLS_SSL_TLS_C) && defined(MBEDTLS_DEBUG_C) && \ + defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) && \ - defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) && \ - defined(MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE) && \ - defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) && \ - defined(PSA_WANT_ALG_SHA_256) && \ - defined(PSA_WANT_ECC_SECP_R1_256) && \ - defined(PSA_WANT_ECC_SECP_R1_384) && \ - defined(PSA_HAVE_ALG_ECDSA_VERIFY) && \ - defined(MBEDTLS_SSL_SESSION_TICKETS)) || \ - (defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ - defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) && \ - defined(PSA_WANT_ALG_SHA_256) && \ - defined(PSA_WANT_ECC_SECP_R1_384) && \ - defined(PSA_HAVE_ALG_ECDSA_VERIFY))) + defined(MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP) && \ + defined(PSA_WANT_ALG_SHA_256) typedef struct { mbedtls_ssl_context *ssl; const char *trigger; @@ -103,113 +89,6 @@ static void tls_abort_transcript(void *ctx, int level, psa_hash_abort(&abort_ctx->ssl->handshake->fin_sha384_psa); #endif } - -static void tls_server_error(mbedtls_ssl_protocol_version tls_version, - const char *trigger, - int server_state, - int client_state) -{ - int ret = -1; - int max_steps = 100; - mbedtls_test_ssl_endpoint client_ep, server_ep; - mbedtls_test_handshake_test_options client_options; - mbedtls_test_handshake_test_options server_options; - tls_abort_transcript_context abort_ctx; - -#if defined(MBEDTLS_SSL_PROTO_TLS1_3) - unsigned char psk[] = "abcdefghijklmnop"; - data_t psk_data = { psk, sizeof(psk) - 1 }; -#endif - - memset(&client_ep, 0, sizeof(client_ep)); - memset(&server_ep, 0, sizeof(server_ep)); - memset(&abort_ctx, 0, sizeof(abort_ctx)); - mbedtls_test_init_handshake_options(&client_options); - mbedtls_test_init_handshake_options(&server_options); - - PSA_INIT(); - - client_options.client_min_version = tls_version; - client_options.client_max_version = tls_version; - server_options.server_min_version = tls_version; - server_options.server_max_version = tls_version; - - abort_ctx.trigger = trigger; - server_options.srv_log_obj = &abort_ctx; - server_options.srv_log_fun = tls_abort_transcript; - -#if defined(MBEDTLS_SSL_PROTO_TLS1_3) - if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { - client_options.psk_str = &psk_data; - } -#endif - - mbedtls_debug_set_threshold(4); - - TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, - &client_options), 0); - TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, - &server_options), 0); - -#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) - if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { - TEST_EQUAL(mbedtls_ssl_conf_psk(&server_ep.conf, psk, sizeof(psk) - 1, - (const unsigned char *) "foo", - strlen("foo")), 0); - mbedtls_ssl_conf_tls13_key_exchange_modes( - &client_ep.conf, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK); - mbedtls_ssl_conf_tls13_key_exchange_modes( - &server_ep.conf, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK); - mbedtls_ssl_conf_session_tickets_cb(&server_ep.conf, - mbedtls_test_ticket_write, - mbedtls_test_ticket_parse, - NULL); - } -#endif - - TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket), - &(server_ep.socket), 1024), 0); - - abort_ctx.ssl = &server_ep.ssl; - - TEST_EQUAL(mbedtls_test_move_handshake_to_state( - &(server_ep.ssl), &(client_ep.ssl), - server_state), 0); - - TEST_EQUAL(mbedtls_ssl_flush_output(&(server_ep.ssl)), 0); - - TEST_EQUAL(server_ep.ssl.state, server_state); - - TEST_EQUAL(abort_ctx.triggered, 0); - - while (client_ep.ssl.state != client_state && - --max_steps >= 0) { - ret = mbedtls_ssl_handshake_step(&(client_ep.ssl)); - TEST_ASSERT(ret == 0 || ret == MBEDTLS_ERR_SSL_WANT_READ || - ret == MBEDTLS_ERR_SSL_WANT_WRITE); - } - - TEST_ASSERT(max_steps >= 0); - - TEST_EQUAL(client_ep.ssl.state, client_state); - TEST_EQUAL(server_ep.ssl.state, server_state); - - TEST_EQUAL(abort_ctx.triggered, 0); - - ret = mbedtls_ssl_handshake_step(&(server_ep.ssl)); - TEST_ASSERT(abort_ctx.triggered); - TEST_ASSERT(ret != 0); - - TEST_EQUAL(server_ep.ssl.state, server_state); - -exit: - mbedtls_test_ssl_endpoint_free(&client_ep); - mbedtls_test_ssl_endpoint_free(&server_ep); - mbedtls_test_free_handshake_options(&client_options); - mbedtls_test_free_handshake_options(&server_options); - mbedtls_debug_set_threshold(0); - PSA_DONE(); -} #endif #if (!defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \ @@ -4515,31 +4394,73 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_DEBUG_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_HAVE_ALG_SOME_RSA_SIGN:MBEDTLS_SSL_SESSION_TICKETS */ -void tls13_server_propagates_rms_error() +/* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C:MBEDTLS_DEBUG_C:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP:PSA_WANT_ALG_SHA_256 */ +void tls_transcript_error_propagation(int endpoint, + int tls_version, + const char *trigger, + int server_state, + int client_state) { - tls_server_error(MBEDTLS_SSL_VERSION_TLS1_3, - "<= parse finished message", - MBEDTLS_SSL_CLIENT_FINISHED, - MBEDTLS_SSL_FLUSH_BUFFERS); - goto exit; + int ret = -1; + mbedtls_test_ssl_endpoint client_ep, server_ep; + mbedtls_test_handshake_test_options client_options; + mbedtls_test_handshake_test_options server_options; + tls_abort_transcript_context abort_ctx; + + mbedtls_test_init_handshake_options(&client_options); + mbedtls_test_init_handshake_options(&server_options); + memset(&abort_ctx, 0, sizeof(abort_ctx)); + + PSA_INIT(); + + client_options.client_min_version = tls_version; + client_options.client_max_version = tls_version; + server_options.server_min_version = tls_version; + server_options.server_max_version = tls_version; + + abort_ctx.trigger = trigger; + + if (endpoint == MBEDTLS_SSL_IS_CLIENT) { + client_options.cli_log_obj = &abort_ctx; + client_options.cli_log_fun = tls_abort_transcript; + } else { + server_options.srv_log_obj = &abort_ctx; + server_options.srv_log_fun = tls_abort_transcript; + } + + mbedtls_debug_set_threshold(4); + + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, + &client_options), 0); + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, + &server_options), 0); + + TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket), + &(server_ep.socket), 1024), 0); + + abort_ctx.ssl = &server_ep.ssl; + + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(server_ep.ssl), &(client_ep.ssl), + server_state), 0); + + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + client_state), 0); + + TEST_EQUAL(abort_ctx.triggered, 0); + + ret = mbedtls_ssl_handshake_step(&(server_ep.ssl)); + TEST_ASSERT(abort_ctx.triggered); + TEST_ASSERT(ret != 0); exit: - ; -} -/* END_CASE */ - -/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_DEBUG_C:MBEDTLS_SSL_EXTENDED_MASTER_SECRET:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_384:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_HAVE_ALG_SOME_RSA_SIGN:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ -void tls12_server_propagates_ems_error() -{ - tls_server_error(MBEDTLS_SSL_VERSION_TLS1_2, - "=> derive keys", - MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, - MBEDTLS_SSL_CERTIFICATE_VERIFY); - goto exit; - -exit: - ; + mbedtls_test_ssl_endpoint_free(&client_ep); + mbedtls_test_ssl_endpoint_free(&server_ep); + mbedtls_test_free_handshake_options(&client_options); + mbedtls_test_free_handshake_options(&server_options); + mbedtls_debug_set_threshold(0); + PSA_DONE(); } /* END_CASE */ From c7f07e92889377ec8ec7aa30d67ae846a6a5d22c Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Wed, 27 May 2026 07:56:31 +0100 Subject: [PATCH 094/168] Add ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/1583-1584-ssl-transcript-errors.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 ChangeLog.d/1583-1584-ssl-transcript-errors.txt diff --git a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt new file mode 100644 index 0000000000..921b40b11d --- /dev/null +++ b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt @@ -0,0 +1,5 @@ +Bugfix + * Fix a bug where errors during transcript-hash computation for TLS 1.2 + extended master secret and TLS 1.3 resumption master secret could be + ignored instead of causing the handshake to fail. Fixes #1583 and #1584. + From b35f87033178987542871d30069293343aa132b0 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 28 May 2026 15:07:08 +0100 Subject: [PATCH 095/168] Update ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/1583-1584-ssl-transcript-errors.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt index 921b40b11d..062a788788 100644 --- a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt +++ b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt @@ -1,5 +1,5 @@ -Bugfix +Security * Fix a bug where errors during transcript-hash computation for TLS 1.2 extended master secret and TLS 1.3 resumption master secret could be - ignored instead of causing the handshake to fail. Fixes #1583 and #1584. + ignored instead of causing the handshake to fail. From ceaa75b899c80ba4849fac7643279ba3fead0480 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 28 May 2026 15:18:19 +0100 Subject: [PATCH 096/168] Add security impact Signed-off-by: Ben Taylor --- ChangeLog.d/1583-1584-ssl-transcript-errors.txt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt index 062a788788..4b5db144c3 100644 --- a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt +++ b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt @@ -1,5 +1,12 @@ Security - * Fix a bug where errors during transcript-hash computation for TLS 1.2 - extended master secret and TLS 1.3 resumption master secret could be - ignored instead of causing the handshake to fail. - + * Fix a bug where transcript-hash computation errors during TLS 1.2 + extended master secret calculation could be ignored instead of causing the + handshake to fail. This could allow a handshake to continue with a master + secret that was not correctly bound to the handshake transcript, + undermining the security guarantees of the extended master secret + extension. + * Fix a bug where TLS 1.3 servers could ignore errors when computing the + resumption master secret instead of causing the handshake to fail. This + could allow a server to issue resumption tickets derived from an invalid + resumption secret, weakening authentication of future resumptions made + with those tickets. From e8f3c920eda967baf71788481c271c412ebbc9f0 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Fri, 29 May 2026 14:48:44 +0100 Subject: [PATCH 097/168] Improve layout of the code for debugging with breakpoints Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.function | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index a68a6fcf3f..569cb159d1 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -76,10 +76,19 @@ static void tls_abort_transcript(void *ctx, int level, (void) file; (void) line; - if (abort_ctx->triggered || abort_ctx->ssl == NULL || - abort_ctx->ssl->handshake == NULL || - abort_ctx->trigger == NULL || - strstr(str, abort_ctx->trigger) == NULL) { + if (abort_ctx->triggered){ + return; + } + if (abort_ctx->ssl == NULL) { + return; + } + if (abort_ctx->ssl->handshake == NULL) { + return; + } + if (abort_ctx->trigger == NULL) { + return; + } + if (strstr(str, abort_ctx->trigger) == NULL) { return; } From d137f35665b94b2fe8ea93b267294dbd863cf604 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Fri, 29 May 2026 15:09:34 +0100 Subject: [PATCH 098/168] Add additional guard for sha256 in tests Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.function | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 569cb159d1..2728ddc704 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -93,7 +93,9 @@ static void tls_abort_transcript(void *ctx, int level, } abort_ctx->triggered = 1; +#if defined(PSA_WANT_ALG_SHA_256) psa_hash_abort(&abort_ctx->ssl->handshake->fin_sha256_psa); +#endif #if defined(PSA_WANT_ALG_SHA_384) psa_hash_abort(&abort_ctx->ssl->handshake->fin_sha384_psa); #endif From 8e9e821ce8b001b1771db940f0dbec266c685b5a Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Fri, 29 May 2026 15:12:28 +0100 Subject: [PATCH 099/168] refactor initialisation in tls_transcript_error_propagation, so that the variables are initialised straight after they are declared Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.function | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 2728ddc704..5655be29d9 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4415,11 +4415,10 @@ void tls_transcript_error_propagation(int endpoint, int ret = -1; mbedtls_test_ssl_endpoint client_ep, server_ep; mbedtls_test_handshake_test_options client_options; - mbedtls_test_handshake_test_options server_options; - tls_abort_transcript_context abort_ctx; - mbedtls_test_init_handshake_options(&client_options); + mbedtls_test_handshake_test_options server_options; mbedtls_test_init_handshake_options(&server_options); + tls_abort_transcript_context abort_ctx; memset(&abort_ctx, 0, sizeof(abort_ctx)); PSA_INIT(); From c2a26a989f07ef4abd8a7de5269756a805bfc488 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 1 Jun 2026 07:43:48 +0100 Subject: [PATCH 100/168] Fixed code style Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 5655be29d9..8a99e93940 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -76,7 +76,7 @@ static void tls_abort_transcript(void *ctx, int level, (void) file; (void) line; - if (abort_ctx->triggered){ + if (abort_ctx->triggered) { return; } if (abort_ctx->ssl == NULL) { From 3565231081e263897619568f52b174d4ac9759ba Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 1 Jun 2026 07:59:06 +0100 Subject: [PATCH 101/168] Fix issues with hanging seed length Signed-off-by: Ben Taylor --- library/ssl_tls.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 7ddaa12202..86bed60fd8 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -6293,12 +6293,16 @@ static int ssl_compute_master(mbedtls_ssl_handshake_params *handshake, #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) if (handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) { lbl = "extended master secret"; - seed = session_hash; ret = handshake->calc_verify(ssl, session_hash, &seed_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "calc_verify", ret); return ret; } + if (seed_len > sizeof(session_hash)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad session hash length")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + seed = session_hash; MBEDTLS_SSL_DEBUG_BUF(3, "session hash for extended master secret", session_hash, seed_len); From ed70149de35ebc9f21bb9b4080830f37fe868882 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 1 Jun 2026 08:03:58 +0100 Subject: [PATCH 102/168] Add further documentation to tls_abort_transcript_context Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.function | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 8a99e93940..c377bcaace 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -61,6 +61,9 @@ static int failing_ticket_write_unset_lifetime( defined(MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP) && \ defined(PSA_WANT_ALG_SHA_256) typedef struct { + /* Context for tls_abort_transcript(). The debug callback watches for + * trigger in the SSL debug trace, then aborts this connection's transcript + * hash operation exactly once so the test can check error propagation. */ mbedtls_ssl_context *ssl; const char *trigger; int triggered; From e9779ccaa32f5e13713ba01adb05e2d1c811a6ce Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 1 Jun 2026 08:12:23 +0100 Subject: [PATCH 103/168] Add unsupported trigger check Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.function | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index c377bcaace..416af2141e 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -88,9 +88,6 @@ static void tls_abort_transcript(void *ctx, int level, if (abort_ctx->ssl->handshake == NULL) { return; } - if (abort_ctx->trigger == NULL) { - return; - } if (strstr(str, abort_ctx->trigger) == NULL) { return; } @@ -4432,6 +4429,7 @@ void tls_transcript_error_propagation(int endpoint, server_options.server_max_version = tls_version; abort_ctx.trigger = trigger; + TEST_ASSERT(abort_ctx.trigger != NULL); if (endpoint == MBEDTLS_SSL_IS_CLIENT) { client_options.cli_log_obj = &abort_ctx; From 1e098f3ae9a67122f728a845d1408057646c693c Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 1 Jun 2026 08:26:50 +0100 Subject: [PATCH 104/168] Add client tests for RMS computation error Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.data | 8 +++++++ tests/suites/test_suite_ssl.function | 32 ++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index c93ff542e9..3dba0df18b 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3382,10 +3382,18 @@ TLS 1.3 server propagates RMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3:"<= parse finished message":MBEDTLS_SSL_CLIENT_FINISHED:MBEDTLS_SSL_FLUSH_BUFFERS +TLS 1.3 client propagates RMS computation error +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT +tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3:"<= write finished message":MBEDTLS_SSL_CLIENT_FINISHED:MBEDTLS_SSL_CLIENT_FINISHED + TLS 1.2 server propagates EMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:MBEDTLS_SSL_CERTIFICATE_VERIFY +TLS 1.2 client propagates EMS computation error +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:MBEDTLS_SSL_CERTIFICATE_VERIFY + TLS 1.3 read early data, early data accepted tls13_read_early_data:TEST_EARLY_DATA_ACCEPTED diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 416af2141e..fbbce164a2 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4446,22 +4446,36 @@ void tls_transcript_error_propagation(int endpoint, TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, &server_options), 0); + /* Keep enough socket capacity for setup traffic so the final step below + * exercises the target state instead of only flushing previous messages. */ TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket), - &(server_ep.socket), 1024), 0); + &(server_ep.socket), 4096), 0); - abort_ctx.ssl = &server_ep.ssl; + if (endpoint == MBEDTLS_SSL_IS_CLIENT) { + /* Moving the client to its target state drives the server as needed. + * Moving the server afterwards can advance the client past that state. */ + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + client_state), 0); - TEST_EQUAL(mbedtls_test_move_handshake_to_state( - &(server_ep.ssl), &(client_ep.ssl), - server_state), 0); + abort_ctx.ssl = &client_ep.ssl; + } else { + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(server_ep.ssl), &(client_ep.ssl), + server_state), 0); - TEST_EQUAL(mbedtls_test_move_handshake_to_state( - &(client_ep.ssl), &(server_ep.ssl), - client_state), 0); + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + client_state), 0); + abort_ctx.ssl = &server_ep.ssl; + } + TEST_EQUAL(mbedtls_ssl_flush_output(abort_ctx.ssl), 0); + TEST_EQUAL(abort_ctx.ssl->state, + endpoint == MBEDTLS_SSL_IS_CLIENT ? client_state : server_state); TEST_EQUAL(abort_ctx.triggered, 0); - ret = mbedtls_ssl_handshake_step(&(server_ep.ssl)); + ret = mbedtls_ssl_handshake_step(abort_ctx.ssl); TEST_ASSERT(abort_ctx.triggered); TEST_ASSERT(ret != 0); From f6aeb4c8e40bd3d86da9363213d64e367b2017ad Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 1 Jun 2026 09:03:29 +0100 Subject: [PATCH 105/168] Add additional fix for return with error Signed-off-by: Ben Taylor --- library/ssl_tls13_client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 96d4d08ee0..ecdf507eab 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -2804,6 +2804,7 @@ static int ssl_tls13_parse_new_session_ticket_exts(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_parse_new_session_ticket_early_data_ext", ret); + return ret; } break; #endif /* MBEDTLS_SSL_EARLY_DATA */ From 48593c23a03a08a3dba4b42d3585e6b2c631caf8 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 1 Jun 2026 09:19:29 +0100 Subject: [PATCH 106/168] Add fix for missing return from ssl_write_ecjpake_kkpp_ext Signed-off-by: Ben Taylor --- library/ssl_tls12_server.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index 328e25aafc..5333d18c58 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -1746,7 +1746,7 @@ static void ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl, MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, +static int ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { @@ -1760,14 +1760,14 @@ static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, /* Skip costly computation if not needed */ if (ssl->handshake->ciphersuite_info->key_exchange != MBEDTLS_KEY_EXCHANGE_ECJPAKE) { - return; + return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, ecjpake kkpp extension")); if (end - p < 4) { MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small")); - return; + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0); @@ -1780,13 +1780,14 @@ static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); - return; + return ret; } MBEDTLS_PUT_UINT16_BE(kkpp_len, p, 0); p += 2; *olen = kkpp_len + 4; + return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ @@ -2169,7 +2170,10 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_ecjpake_kkpp_ext(ssl, p + 2 + ext_len, &olen); + if ((ret = ssl_write_ecjpake_kkpp_ext(ssl, p + 2 + ext_len, &olen)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_ecjpake_kkpp_ext", ret); + return ret; + } ext_len += olen; #endif From 1c68ca14fb3da7a70ff953bfbef13670344f4a3c Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 1 Jun 2026 14:48:09 +0100 Subject: [PATCH 107/168] Fix code style issues Signed-off-by: Ben Taylor --- library/ssl_tls12_server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index 5333d18c58..7ff2833121 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -1747,8 +1747,8 @@ static void ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl, #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) static int ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen) + unsigned char *buf, + size_t *olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; From 795eb3ee95da7d201cc194b34418f60cd58ae83a Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 4 Jun 2026 10:29:43 +0100 Subject: [PATCH 108/168] Add Reported by to ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/1583-1584-ssl-transcript-errors.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt index 4b5db144c3..75d6969501 100644 --- a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt +++ b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt @@ -10,3 +10,4 @@ Security could allow a server to issue resumption tickets derived from an invalid resumption secret, weakening authentication of future resumptions made with those tickets. + * Reported by jjfz123 / https://github.com/jjfz123 / https://www.linkedin.com/in/jjfdzcastro1/ From f487bd2e07db7292778dda24865ff071301fbf06 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 4 Jun 2026 10:32:03 +0100 Subject: [PATCH 109/168] Tidy up ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/1583-1584-ssl-transcript-errors.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt index 75d6969501..6d20d958b2 100644 --- a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt +++ b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt @@ -4,10 +4,10 @@ Security handshake to fail. This could allow a handshake to continue with a master secret that was not correctly bound to the handshake transcript, undermining the security guarantees of the extended master secret - extension. + extension. Reported by jjfz123 / https://github.com/jjfz123 / + https://www.linkedin.com/in/jjfdzcastro1/ * Fix a bug where TLS 1.3 servers could ignore errors when computing the resumption master secret instead of causing the handshake to fail. This could allow a server to issue resumption tickets derived from an invalid resumption secret, weakening authentication of future resumptions made with those tickets. - * Reported by jjfz123 / https://github.com/jjfz123 / https://www.linkedin.com/in/jjfdzcastro1/ From f63a0058d314e8793c4d88927071b4dc17ecfd35 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 4 Jun 2026 10:33:07 +0100 Subject: [PATCH 110/168] Remove check for NULL pointer Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.function | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index fbbce164a2..d0a7f25980 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4429,7 +4429,6 @@ void tls_transcript_error_propagation(int endpoint, server_options.server_max_version = tls_version; abort_ctx.trigger = trigger; - TEST_ASSERT(abort_ctx.trigger != NULL); if (endpoint == MBEDTLS_SSL_IS_CLIENT) { client_options.cli_log_obj = &abort_ctx; From d32397563e69cd3fbfb18608d62cc7a179aa15de Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 4 Jun 2026 12:12:00 +0100 Subject: [PATCH 111/168] Fix reporters in ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/1583-1584-ssl-transcript-errors.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt index 6d20d958b2..c8b6aa696c 100644 --- a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt +++ b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt @@ -4,10 +4,10 @@ Security handshake to fail. This could allow a handshake to continue with a master secret that was not correctly bound to the handshake transcript, undermining the security guarantees of the extended master secret - extension. Reported by jjfz123 / https://github.com/jjfz123 / - https://www.linkedin.com/in/jjfdzcastro1/ + extension. Report by Mathew Gretton-Dann * Fix a bug where TLS 1.3 servers could ignore errors when computing the resumption master secret instead of causing the handshake to fail. This could allow a server to issue resumption tickets derived from an invalid resumption secret, weakening authentication of future resumptions made - with those tickets. + with those tickets. Reported by jjfz123 / https://github.com/jjfz123 / + https://www.linkedin.com/in/jjfdzcastro1/ From 835226c59aa974452f55bebdb8555fd0f6e3aeca Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Fri, 5 Jun 2026 07:54:38 +0100 Subject: [PATCH 112/168] Update ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/1583-1584-ssl-transcript-errors.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt index c8b6aa696c..e21c52cfde 100644 --- a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt +++ b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt @@ -4,10 +4,9 @@ Security handshake to fail. This could allow a handshake to continue with a master secret that was not correctly bound to the handshake transcript, undermining the security guarantees of the extended master secret - extension. Report by Mathew Gretton-Dann + extension. Report by Mathew Gretton-Dann. * Fix a bug where TLS 1.3 servers could ignore errors when computing the resumption master secret instead of causing the handshake to fail. This could allow a server to issue resumption tickets derived from an invalid resumption secret, weakening authentication of future resumptions made - with those tickets. Reported by jjfz123 / https://github.com/jjfz123 / - https://www.linkedin.com/in/jjfdzcastro1/ + with those tickets. Reported by jjfz123. From 629df9f5fbd0bd1edc562f9309d1e252a96c59d6 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Fri, 5 Jun 2026 08:33:11 +0100 Subject: [PATCH 113/168] Improve testing Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.data | 22 ++-- tests/suites/test_suite_ssl.function | 150 +++++++++++++-------------- 2 files changed, 86 insertions(+), 86 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 3dba0df18b..24e9ae9033 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3378,21 +3378,21 @@ elliptic_curve_get_properties TLS 1.3 resume session with ticket tls13_resume_session_with_ticket -TLS 1.3 server propagates RMS computation error +TLS 1.3 server propagates RMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3:"<= parse finished message":MBEDTLS_SSL_CLIENT_FINISHED:MBEDTLS_SSL_FLUSH_BUFFERS - -TLS 1.3 client propagates RMS computation error + +TLS 1.3 client propagates RMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT -tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3:"<= write finished message":MBEDTLS_SSL_CLIENT_FINISHED:MBEDTLS_SSL_CLIENT_FINISHED - -TLS 1.2 server propagates EMS computation error -depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3:"<= write finished message":MBEDTLS_SSL_CLIENT_FINISHED:-1 + +TLS 1.2 server propagates EMS computation error +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:MBEDTLS_SSL_CERTIFICATE_VERIFY - -TLS 1.2 client propagates EMS computation error -depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED -tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:MBEDTLS_SSL_CERTIFICATE_VERIFY + +TLS 1.2 client propagates EMS computation error +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CERTIFICATE_VERIFY:-1 TLS 1.3 read early data, early data accepted tls13_read_early_data:TEST_EARLY_DATA_ACCEPTED diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index d0a7f25980..09b8ac8230 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4406,85 +4406,85 @@ exit: /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C:MBEDTLS_DEBUG_C:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP:PSA_WANT_ALG_SHA_256 */ -void tls_transcript_error_propagation(int endpoint, - int tls_version, - const char *trigger, - int server_state, - int client_state) -{ - int ret = -1; - mbedtls_test_ssl_endpoint client_ep, server_ep; - mbedtls_test_handshake_test_options client_options; - mbedtls_test_init_handshake_options(&client_options); - mbedtls_test_handshake_test_options server_options; - mbedtls_test_init_handshake_options(&server_options); - tls_abort_transcript_context abort_ctx; - memset(&abort_ctx, 0, sizeof(abort_ctx)); - - PSA_INIT(); - - client_options.client_min_version = tls_version; - client_options.client_max_version = tls_version; - server_options.server_min_version = tls_version; - server_options.server_max_version = tls_version; - - abort_ctx.trigger = trigger; - - if (endpoint == MBEDTLS_SSL_IS_CLIENT) { - client_options.cli_log_obj = &abort_ctx; - client_options.cli_log_fun = tls_abort_transcript; - } else { - server_options.srv_log_obj = &abort_ctx; - server_options.srv_log_fun = tls_abort_transcript; - } - - mbedtls_debug_set_threshold(4); - +void tls_transcript_error_propagation(int endpoint, + int tls_version, + const char *trigger, + int target_state, + int peer_target_state) +{ + int ret = -1; + mbedtls_test_ssl_endpoint client_ep, server_ep; + mbedtls_test_handshake_test_options client_options; + mbedtls_test_init_handshake_options(&client_options); + mbedtls_test_handshake_test_options server_options; + mbedtls_test_init_handshake_options(&server_options); + tls_abort_transcript_context abort_ctx; + memset(&abort_ctx, 0, sizeof(abort_ctx)); + mbedtls_ssl_context *peer_ssl_context = NULL; + + PSA_INIT(); + + client_options.client_min_version = tls_version; + client_options.client_max_version = tls_version; + server_options.server_min_version = tls_version; + server_options.server_max_version = tls_version; + + abort_ctx.trigger = trigger; + TEST_ASSERT(abort_ctx.trigger != NULL); + + if (endpoint == MBEDTLS_SSL_IS_CLIENT) { + client_options.cli_log_obj = &abort_ctx; + client_options.cli_log_fun = tls_abort_transcript; + abort_ctx.ssl = &client_ep.ssl; + peer_ssl_context = &server_ep.ssl; + } else { + server_options.srv_log_obj = &abort_ctx; + server_options.srv_log_fun = tls_abort_transcript; + abort_ctx.ssl = &server_ep.ssl; + peer_ssl_context = &client_ep.ssl; + } + + mbedtls_debug_set_threshold(4); + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, - &client_options), 0); + &client_options), 0); TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, &server_options), 0); - - /* Keep enough socket capacity for setup traffic so the final step below + + /* Keep enough socket capacity for setup traffic so the final step below * exercises the target state instead of only flushing previous messages. */ - TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket), - &(server_ep.socket), 4096), 0); - - if (endpoint == MBEDTLS_SSL_IS_CLIENT) { - /* Moving the client to its target state drives the server as needed. - * Moving the server afterwards can advance the client past that state. */ - TEST_EQUAL(mbedtls_test_move_handshake_to_state( - &(client_ep.ssl), &(server_ep.ssl), - client_state), 0); - - abort_ctx.ssl = &client_ep.ssl; - } else { - TEST_EQUAL(mbedtls_test_move_handshake_to_state( - &(server_ep.ssl), &(client_ep.ssl), - server_state), 0); - - TEST_EQUAL(mbedtls_test_move_handshake_to_state( - &(client_ep.ssl), &(server_ep.ssl), - client_state), 0); - abort_ctx.ssl = &server_ep.ssl; - } - - TEST_EQUAL(mbedtls_ssl_flush_output(abort_ctx.ssl), 0); - TEST_EQUAL(abort_ctx.ssl->state, - endpoint == MBEDTLS_SSL_IS_CLIENT ? client_state : server_state); - TEST_EQUAL(abort_ctx.triggered, 0); - - ret = mbedtls_ssl_handshake_step(abort_ctx.ssl); - TEST_ASSERT(abort_ctx.triggered); - TEST_ASSERT(ret != 0); - -exit: - mbedtls_test_ssl_endpoint_free(&client_ep); - mbedtls_test_ssl_endpoint_free(&server_ep); - mbedtls_test_free_handshake_options(&client_options); - mbedtls_test_free_handshake_options(&server_options); - mbedtls_debug_set_threshold(0); - PSA_DONE(); + TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket), + &(server_ep.socket), 4096), 0); + + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + abort_ctx.ssl, peer_ssl_context, + target_state), 0); + /* + * Advance the peer further through the handshake so that it emits the + * messages needed by the endpoint under test to proceed through its next + * step. + */ + if (peer_target_state != -1) { + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + peer_ssl_context, abort_ctx.ssl, + peer_target_state), 0); + } + + TEST_EQUAL(mbedtls_ssl_flush_output(abort_ctx.ssl), 0); + TEST_EQUAL(abort_ctx.ssl->state, target_state); + TEST_EQUAL(abort_ctx.triggered, 0); + + ret = mbedtls_ssl_handshake_step(abort_ctx.ssl); + TEST_ASSERT(abort_ctx.triggered); + TEST_ASSERT(ret != 0); + +exit: + mbedtls_test_ssl_endpoint_free(&client_ep); + mbedtls_test_ssl_endpoint_free(&server_ep); + mbedtls_test_free_handshake_options(&client_options); + mbedtls_test_free_handshake_options(&server_options); + mbedtls_debug_set_threshold(0); + PSA_DONE(); } /* END_CASE */ From 2e95cb7baacb047351ae0460bf1e6912dc0ded73 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Fri, 5 Jun 2026 08:39:39 +0100 Subject: [PATCH 114/168] Update error handling of return from ssl_write_ecjpake_kkpp_ext Signed-off-by: Ben Taylor --- library/ssl_tls12_server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index 7ff2833121..03ef8fd5f9 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -2170,11 +2170,11 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if ((ret = ssl_write_ecjpake_kkpp_ext(ssl, p + 2 + ext_len, &olen)) != 0) { + ret = ssl_write_ecjpake_kkpp_ext(ssl, p + 2 + ext_len, &olen); + if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_ecjpake_kkpp_ext", ret); return ret; } - ext_len += olen; #endif #if defined(MBEDTLS_SSL_ALPN) From 86b94d411cb74d5a364d5d0b76f9f2f10c5ef977 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Fri, 5 Jun 2026 08:42:19 +0100 Subject: [PATCH 115/168] Improve ChangeLog Signed-off-by: Ben Taylor --- ChangeLog.d/1583-1584-ssl-transcript-errors.txt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt index e21c52cfde..3a18c76df9 100644 --- a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt +++ b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt @@ -5,8 +5,12 @@ Security secret that was not correctly bound to the handshake transcript, undermining the security guarantees of the extended master secret extension. Report by Mathew Gretton-Dann. - * Fix a bug where TLS 1.3 servers could ignore errors when computing the - resumption master secret instead of causing the handshake to fail. This - could allow a server to issue resumption tickets derived from an invalid - resumption secret, weakening authentication of future resumptions made - with those tickets. Reported by jjfz123. + * Fix a TLS 1.3 server-side error-handling bug affecting session ticket + generation. Under rare conditions, such as memory allocation failures + while computing the resumption master secret, the server could issue + invalid session tickets instead of failing the handshake. Clients + presented with such tickets would fail session resumption and fall back to + a full handshake. In deployments relying on session resumption, repeated + occurrences could increase the frequency of full handshakes and amplify + resource consumption during periods of resource exhaustion or other + transient failures. Reported by jjfz123. From 14b2bdc8cebb51b81d50082d8c54ec23cdeff36a Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Fri, 5 Jun 2026 09:21:09 +0100 Subject: [PATCH 116/168] fix code style Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.function | 150 +++++++++++++-------------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 09b8ac8230..40041210ed 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4406,85 +4406,85 @@ exit: /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_SSL_TLS_C:MBEDTLS_DEBUG_C:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP:PSA_WANT_ALG_SHA_256 */ -void tls_transcript_error_propagation(int endpoint, - int tls_version, - const char *trigger, - int target_state, - int peer_target_state) -{ - int ret = -1; - mbedtls_test_ssl_endpoint client_ep, server_ep; - mbedtls_test_handshake_test_options client_options; - mbedtls_test_init_handshake_options(&client_options); - mbedtls_test_handshake_test_options server_options; - mbedtls_test_init_handshake_options(&server_options); - tls_abort_transcript_context abort_ctx; - memset(&abort_ctx, 0, sizeof(abort_ctx)); - mbedtls_ssl_context *peer_ssl_context = NULL; - - PSA_INIT(); - - client_options.client_min_version = tls_version; - client_options.client_max_version = tls_version; - server_options.server_min_version = tls_version; - server_options.server_max_version = tls_version; - - abort_ctx.trigger = trigger; - TEST_ASSERT(abort_ctx.trigger != NULL); - - if (endpoint == MBEDTLS_SSL_IS_CLIENT) { - client_options.cli_log_obj = &abort_ctx; - client_options.cli_log_fun = tls_abort_transcript; - abort_ctx.ssl = &client_ep.ssl; - peer_ssl_context = &server_ep.ssl; - } else { - server_options.srv_log_obj = &abort_ctx; - server_options.srv_log_fun = tls_abort_transcript; - abort_ctx.ssl = &server_ep.ssl; - peer_ssl_context = &client_ep.ssl; - } - - mbedtls_debug_set_threshold(4); - +void tls_transcript_error_propagation(int endpoint, + int tls_version, + const char *trigger, + int target_state, + int peer_target_state) +{ + int ret = -1; + mbedtls_test_ssl_endpoint client_ep, server_ep; + mbedtls_test_handshake_test_options client_options; + mbedtls_test_init_handshake_options(&client_options); + mbedtls_test_handshake_test_options server_options; + mbedtls_test_init_handshake_options(&server_options); + tls_abort_transcript_context abort_ctx; + memset(&abort_ctx, 0, sizeof(abort_ctx)); + mbedtls_ssl_context *peer_ssl_context = NULL; + + PSA_INIT(); + + client_options.client_min_version = tls_version; + client_options.client_max_version = tls_version; + server_options.server_min_version = tls_version; + server_options.server_max_version = tls_version; + + abort_ctx.trigger = trigger; + TEST_ASSERT(abort_ctx.trigger != NULL); + + if (endpoint == MBEDTLS_SSL_IS_CLIENT) { + client_options.cli_log_obj = &abort_ctx; + client_options.cli_log_fun = tls_abort_transcript; + abort_ctx.ssl = &client_ep.ssl; + peer_ssl_context = &server_ep.ssl; + } else { + server_options.srv_log_obj = &abort_ctx; + server_options.srv_log_fun = tls_abort_transcript; + abort_ctx.ssl = &server_ep.ssl; + peer_ssl_context = &client_ep.ssl; + } + + mbedtls_debug_set_threshold(4); + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, - &client_options), 0); + &client_options), 0); TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, &server_options), 0); - - /* Keep enough socket capacity for setup traffic so the final step below + + /* Keep enough socket capacity for setup traffic so the final step below * exercises the target state instead of only flushing previous messages. */ - TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket), - &(server_ep.socket), 4096), 0); - - TEST_EQUAL(mbedtls_test_move_handshake_to_state( - abort_ctx.ssl, peer_ssl_context, - target_state), 0); - /* - * Advance the peer further through the handshake so that it emits the - * messages needed by the endpoint under test to proceed through its next - * step. - */ - if (peer_target_state != -1) { - TEST_EQUAL(mbedtls_test_move_handshake_to_state( - peer_ssl_context, abort_ctx.ssl, - peer_target_state), 0); - } - - TEST_EQUAL(mbedtls_ssl_flush_output(abort_ctx.ssl), 0); - TEST_EQUAL(abort_ctx.ssl->state, target_state); - TEST_EQUAL(abort_ctx.triggered, 0); - - ret = mbedtls_ssl_handshake_step(abort_ctx.ssl); - TEST_ASSERT(abort_ctx.triggered); - TEST_ASSERT(ret != 0); - -exit: - mbedtls_test_ssl_endpoint_free(&client_ep); - mbedtls_test_ssl_endpoint_free(&server_ep); - mbedtls_test_free_handshake_options(&client_options); - mbedtls_test_free_handshake_options(&server_options); - mbedtls_debug_set_threshold(0); - PSA_DONE(); + TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket), + &(server_ep.socket), 4096), 0); + + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + abort_ctx.ssl, peer_ssl_context, + target_state), 0); + /* + * Advance the peer further through the handshake so that it emits the + * messages needed by the endpoint under test to proceed through its next + * step. + */ + if (peer_target_state != -1) { + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + peer_ssl_context, abort_ctx.ssl, + peer_target_state), 0); + } + + TEST_EQUAL(mbedtls_ssl_flush_output(abort_ctx.ssl), 0); + TEST_EQUAL(abort_ctx.ssl->state, target_state); + TEST_EQUAL(abort_ctx.triggered, 0); + + ret = mbedtls_ssl_handshake_step(abort_ctx.ssl); + TEST_ASSERT(abort_ctx.triggered); + TEST_ASSERT(ret != 0); + +exit: + mbedtls_test_ssl_endpoint_free(&client_ep); + mbedtls_test_ssl_endpoint_free(&server_ep); + mbedtls_test_free_handshake_options(&client_options); + mbedtls_test_free_handshake_options(&server_options); + mbedtls_debug_set_threshold(0); + PSA_DONE(); } /* END_CASE */ From fc2f108dfbfb3240d7ae5380f968e774ca3a369d Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 8 Jun 2026 13:26:35 +0100 Subject: [PATCH 117/168] Update dependencies for skipped test Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.data | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 24e9ae9033..f5fc712b3f 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3379,11 +3379,11 @@ TLS 1.3 resume session with ticket tls13_resume_session_with_ticket TLS 1.3 server propagates RMS computation error -depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3:"<= parse finished message":MBEDTLS_SSL_CLIENT_FINISHED:MBEDTLS_SSL_FLUSH_BUFFERS TLS 1.3 client propagates RMS computation error -depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3:"<= write finished message":MBEDTLS_SSL_CLIENT_FINISHED:-1 TLS 1.2 server propagates EMS computation error From 75bdaa35c39d2700795dc30808ee766ca518baae Mon Sep 17 00:00:00 2001 From: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> Date: Mon, 8 Jun 2026 13:28:07 +0100 Subject: [PATCH 118/168] Update ChangeLog to add CVE Co-authored-by: Gilles Peskine Signed-off-by: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> --- ChangeLog.d/1583-1584-ssl-transcript-errors.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt index 3a18c76df9..ef092386a9 100644 --- a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt +++ b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt @@ -4,7 +4,7 @@ Security handshake to fail. This could allow a handshake to continue with a master secret that was not correctly bound to the handshake transcript, undermining the security guarantees of the extended master secret - extension. Report by Mathew Gretton-Dann. + extension. Report by Mathew Gretton-Dann. CVE-2026-50581 * Fix a TLS 1.3 server-side error-handling bug affecting session ticket generation. Under rare conditions, such as memory allocation failures while computing the resumption master secret, the server could issue From fa003af2049463b6214b68cc61955010ece8fefa Mon Sep 17 00:00:00 2001 From: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> Date: Mon, 8 Jun 2026 13:28:42 +0100 Subject: [PATCH 119/168] Update ChangeLog with CVE number Co-authored-by: Ronald Cron Signed-off-by: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> --- ChangeLog.d/1583-1584-ssl-transcript-errors.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt index ef092386a9..f259bd711e 100644 --- a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt +++ b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt @@ -14,3 +14,4 @@ Security occurrences could increase the frequency of full handshakes and amplify resource consumption during periods of resource exhaustion or other transient failures. Reported by jjfz123. + CVE-2026-50640 From dc555d19eca0e3b4e7fc2b9c21a67a577f481572 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 8 Jun 2026 14:19:23 +0100 Subject: [PATCH 120/168] remove trailing whitespace Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.data | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index f5fc712b3f..1bdfa68def 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3378,20 +3378,20 @@ elliptic_curve_get_properties TLS 1.3 resume session with ticket tls13_resume_session_with_ticket -TLS 1.3 server propagates RMS computation error +TLS 1.3 server propagates RMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3:"<= parse finished message":MBEDTLS_SSL_CLIENT_FINISHED:MBEDTLS_SSL_FLUSH_BUFFERS - -TLS 1.3 client propagates RMS computation error + +TLS 1.3 client propagates RMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3:"<= write finished message":MBEDTLS_SSL_CLIENT_FINISHED:-1 - -TLS 1.2 server propagates EMS computation error -depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +TLS 1.2 server propagates EMS computation error +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:MBEDTLS_SSL_CERTIFICATE_VERIFY - -TLS 1.2 client propagates EMS computation error -depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +TLS 1.2 client propagates EMS computation error +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CERTIFICATE_VERIFY:-1 TLS 1.3 read early data, early data accepted From 0bf015a43b42acf777a43cf7520215174cded2b7 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Wed, 10 Jun 2026 08:11:37 +0100 Subject: [PATCH 121/168] restore missing ext_len set Signed-off-by: Ben Taylor --- library/ssl_tls12_server.c | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index 03ef8fd5f9..2a825e07b1 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -2175,6 +2175,7 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_ecjpake_kkpp_ext", ret); return ret; } + ext_len += olen; #endif #if defined(MBEDTLS_SSL_ALPN) From 414d284f4afba19d38aa4655f6307b4f6fae1265 Mon Sep 17 00:00:00 2001 From: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> Date: Thu, 11 Jun 2026 09:43:59 +0100 Subject: [PATCH 122/168] Update regression test Co-authored-by: Ronald Cron Signed-off-by: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> --- tests/suites/test_suite_ssl.function | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 40041210ed..3d9dc85aed 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4468,6 +4468,7 @@ void tls_transcript_error_propagation(int endpoint, TEST_EQUAL(mbedtls_test_move_handshake_to_state( peer_ssl_context, abort_ctx.ssl, peer_target_state), 0); + TEST_EQUAL(mbedtls_ssl_flush_output(peer_ssl_context), 0); } TEST_EQUAL(mbedtls_ssl_flush_output(abort_ctx.ssl), 0); From e98a0a84c3aad666a7e268d539d8247154a4d8f1 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 11 Jun 2026 10:30:44 +0100 Subject: [PATCH 123/168] Improve tls_transcript_error_propagation testing to check for error codes Signed-off-by: Ben Taylor --- tests/suites/test_suite_ssl.data | 8 ++++---- tests/suites/test_suite_ssl.function | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 1bdfa68def..79206899f2 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3380,19 +3380,19 @@ tls13_resume_session_with_ticket TLS 1.3 server propagates RMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN -tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3:"<= parse finished message":MBEDTLS_SSL_CLIENT_FINISHED:MBEDTLS_SSL_FLUSH_BUFFERS +tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3:"<= parse finished message":MBEDTLS_SSL_CLIENT_FINISHED:MBEDTLS_SSL_FLUSH_BUFFERS:MBEDTLS_ERR_SSL_WANT_READ TLS 1.3 client propagates RMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN -tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3:"<= write finished message":MBEDTLS_SSL_CLIENT_FINISHED:-1 +tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3:"<= write finished message":MBEDTLS_SSL_CLIENT_FINISHED:-1:MBEDTLS_ERR_SSL_INTERNAL_ERROR TLS 1.2 server propagates EMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED -tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:MBEDTLS_SSL_CERTIFICATE_VERIFY +tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:MBEDTLS_SSL_CERTIFICATE_VERIFY:PSA_ERROR_GENERIC_ERROR TLS 1.2 client propagates EMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED -tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CERTIFICATE_VERIFY:-1 +tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CERTIFICATE_VERIFY:-1:PSA_ERROR_GENERIC_ERROR TLS 1.3 read early data, early data accepted tls13_read_early_data:TEST_EARLY_DATA_ACCEPTED diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 3d9dc85aed..aba395a8ce 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4410,7 +4410,8 @@ void tls_transcript_error_propagation(int endpoint, int tls_version, const char *trigger, int target_state, - int peer_target_state) + int peer_target_state, + int expected_ret) { int ret = -1; mbedtls_test_ssl_endpoint client_ep, server_ep; @@ -4478,6 +4479,7 @@ void tls_transcript_error_propagation(int endpoint, ret = mbedtls_ssl_handshake_step(abort_ctx.ssl); TEST_ASSERT(abort_ctx.triggered); TEST_ASSERT(ret != 0); + TEST_EQUAL(ret, expected_ret); exit: mbedtls_test_ssl_endpoint_free(&client_ep); From 82bba7ef612bae6a0babcb252bba11c66c72f9b2 Mon Sep 17 00:00:00 2001 From: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> Date: Thu, 11 Jun 2026 10:37:00 +0100 Subject: [PATCH 124/168] Fix error codes for tls_transcript_error_propagation Co-authored-by: Ronald Cron Signed-off-by: Ben Taylor <32939606+bjwtaylor@users.noreply.github.com> --- tests/suites/test_suite_ssl.data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 79206899f2..fe279334a0 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3380,7 +3380,7 @@ tls13_resume_session_with_ticket TLS 1.3 server propagates RMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN -tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3:"<= parse finished message":MBEDTLS_SSL_CLIENT_FINISHED:MBEDTLS_SSL_FLUSH_BUFFERS:MBEDTLS_ERR_SSL_WANT_READ +tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3:"<= parse finished message":MBEDTLS_SSL_CLIENT_FINISHED:MBEDTLS_SSL_FLUSH_BUFFERS:MBEDTLS_ERR_SSL_INTERNAL_ERROR TLS 1.3 client propagates RMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN From c438b0b9a92d81fd7ec8aa9148d0272299815155 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Thu, 11 Jun 2026 11:12:10 +0100 Subject: [PATCH 125/168] Correct error handling in mbedtls_ssl_reset_checksum Signed-off-by: Ben Taylor --- library/ssl_tls.c | 25 ++++++++++++------------- tests/suites/test_suite_ssl.data | 4 ++-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 86bed60fd8..a1117ed123 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -29,7 +29,6 @@ #include #include "mbedtls/psa_util.h" -#include "md_psa.h" // for mbedtls_md_error_from_psa() #include "psa/crypto.h" #if defined(MBEDTLS_X509_CRT_PARSE_C) @@ -846,21 +845,21 @@ int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl) #if defined(PSA_WANT_ALG_SHA_256) status = psa_hash_abort(&ssl->handshake->fin_sha256_psa); if (status != PSA_SUCCESS) { - return mbedtls_md_error_from_psa(status); + return PSA_TO_MBEDTLS_ERR(status); } status = psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { - return mbedtls_md_error_from_psa(status); + return PSA_TO_MBEDTLS_ERR(status); } #endif #if defined(PSA_WANT_ALG_SHA_384) status = psa_hash_abort(&ssl->handshake->fin_sha384_psa); if (status != PSA_SUCCESS) { - return mbedtls_md_error_from_psa(status); + return PSA_TO_MBEDTLS_ERR(status); } status = psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384); if (status != PSA_SUCCESS) { - return mbedtls_md_error_from_psa(status); + return PSA_TO_MBEDTLS_ERR(status); } #endif return 0; @@ -880,13 +879,13 @@ static int ssl_update_checksum_start(mbedtls_ssl_context *ssl, #if defined(PSA_WANT_ALG_SHA_256) status = psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len); if (status != PSA_SUCCESS) { - return mbedtls_md_error_from_psa(status); + return PSA_TO_MBEDTLS_ERR(status); } #endif #if defined(PSA_WANT_ALG_SHA_384) status = psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len); if (status != PSA_SUCCESS) { - return mbedtls_md_error_from_psa(status); + return PSA_TO_MBEDTLS_ERR(status); } #endif return 0; @@ -896,8 +895,8 @@ static int ssl_update_checksum_start(mbedtls_ssl_context *ssl, static int ssl_update_checksum_sha256(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { - return mbedtls_md_error_from_psa(psa_hash_update( - &ssl->handshake->fin_sha256_psa, buf, len)); + return PSA_TO_MBEDTLS_ERR(psa_hash_update( + &ssl->handshake->fin_sha256_psa, buf, len)); } #endif @@ -905,8 +904,8 @@ static int ssl_update_checksum_sha256(mbedtls_ssl_context *ssl, static int ssl_update_checksum_sha384(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { - return mbedtls_md_error_from_psa(psa_hash_update( - &ssl->handshake->fin_sha384_psa, buf, len)); + return PSA_TO_MBEDTLS_ERR(psa_hash_update( + &ssl->handshake->fin_sha384_psa, buf, len)); } #endif @@ -6569,7 +6568,7 @@ static int ssl_calc_verify_tls_psa(const mbedtls_ssl_context *ssl, exit: psa_hash_abort(&cloned_op); - return mbedtls_md_error_from_psa(status); + return PSA_TO_MBEDTLS_ERR(status); } #if defined(PSA_WANT_ALG_SHA_256) @@ -7262,7 +7261,7 @@ static int ssl_calc_finished_tls_generic(mbedtls_ssl_context *ssl, void *ctx, exit: psa_hash_abort(&cloned_op); - return mbedtls_md_error_from_psa(status); + return PSA_TO_MBEDTLS_ERR(status); } #if defined(PSA_WANT_ALG_SHA_256) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index fe279334a0..dbe0dfe44c 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3388,11 +3388,11 @@ tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_ TLS 1.2 server propagates EMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED -tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:MBEDTLS_SSL_CERTIFICATE_VERIFY:PSA_ERROR_GENERIC_ERROR +tls_transcript_error_propagation:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:MBEDTLS_SSL_CERTIFICATE_VERIFY:MBEDTLS_ERR_SSL_INTERNAL_ERROR TLS 1.2 client propagates EMS computation error depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED -tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CERTIFICATE_VERIFY:-1:PSA_ERROR_GENERIC_ERROR +tls_transcript_error_propagation:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:"=> derive keys":MBEDTLS_SSL_CERTIFICATE_VERIFY:-1:MBEDTLS_ERR_SSL_INTERNAL_ERROR TLS 1.3 read early data, early data accepted tls13_read_early_data:TEST_EARLY_DATA_ACCEPTED From 3e191be15a7b5a51b1a9d76b48dc88f77929851c Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Jun 2026 14:28:22 +0200 Subject: [PATCH 126/168] 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 | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 2a6d98ab1c..c2f9507a78 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1324,6 +1324,15 @@ typedef union { void *p; /* typically a pointer to extra data */ } mbedtls_ssl_user_data_t; +/** + * Added at the end of "struct mbedtls_ssl_config" and "struct mbedtls_ssl_context" + * to reserve a field for future use. + */ +typedef union { + size_t number; + void *ptr; +} mbedtls_ssl_unused_data_t; + /** * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. */ @@ -1572,13 +1581,20 @@ struct mbedtls_ssl_config { const mbedtls_x509_crt *MBEDTLS_PRIVATE(dn_hints);/*!< acceptable client cert issuers */ #endif - /* Unused field reserved for future use */ - union { - size_t number; - void *ptr; - } MBEDTLS_PRIVATE(unused); + mbedtls_ssl_unused_data_t MBEDTLS_PRIVATE(unused); }; +/* + * 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 */ @@ -1861,11 +1877,7 @@ struct mbedtls_ssl_context { */ mbedtls_ssl_user_data_t MBEDTLS_PRIVATE(user_data); - /* Unused field reserved for future use */ - union { - size_t number; - void *ptr; - } MBEDTLS_PRIVATE(unused); + mbedtls_ssl_unused_data_t MBEDTLS_PRIVATE(unused); }; /** From 0a486086519d45ebe2b41d18564135c9ca6bc624 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Jun 2026 14:37:41 +0200 Subject: [PATCH 127/168] 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 | 92 ---------------- tests/include/test/ssl_helpers_internal.h | 110 +++++++++++++++++++ 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, 114 insertions(+), 92 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 467a27f342..c416f32eff 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,10 +29,6 @@ #include "mbedtls/ssl_cache.h" #endif -#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ - psa_to_ssl_errors, \ - psa_generic_status_to_mbedtls) - #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #if defined(PSA_WANT_KEY_TYPE_AES) #if defined(PSA_WANT_ALG_GCM) @@ -106,13 +100,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 @@ -614,68 +601,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(PSA_WANT_ALG_CBC_NO_PADDING) && defined(PSA_WANT_KEY_TYPE_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 && PSA_WANT_ALG_CBC_NO_PADDING && - PSA_WANT_KEY_TYPE_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. @@ -775,23 +700,6 @@ void mbedtls_test_ssl_perform_handshake( const 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..7180534f79 --- /dev/null +++ b/tests/include/test/ssl_helpers_internal.h @@ -0,0 +1,110 @@ +/** \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 + +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_ssl_errors, \ + psa_generic_status_to_mbedtls) + +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(PSA_WANT_ALG_CBC_NO_PADDING) && defined(PSA_WANT_KEY_TYPE_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 && PSA_WANT_ALG_CBC_NO_PADDING && + PSA_WANT_KEY_TYPE_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 08cfe252af..780c4f319b 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" #include diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index cc73f49aaf..e05cf72bcb 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -9,6 +9,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 7a22939eb4..dd26537127 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 8294a8fd6787fd6052dd711b83f611c6d5cb5f07 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Jun 2026 14:39:15 +0200 Subject: [PATCH 128/168] 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 a4dbd999c00f8aba37650d9f8e51c364eaa6db2b Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Jun 2026 14:49:38 +0200 Subject: [PATCH 129/168] 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 c416f32eff..6a86937df4 100644 --- a/tests/include/test/ssl_helpers.h +++ b/tests/include/test/ssl_helpers.h @@ -746,6 +746,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 fbd49c0c4e35d7a5586bf48d375deb53e06524f1 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Jun 2026 14:51:24 +0200 Subject: [PATCH 130/168] 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 | 10 ++++++++++ programs/ssl/ssl_server2.c | 9 +++++++++ tests/src/test_helpers/ssl_helpers.c | 8 ++++++++ 3 files changed, 27 insertions(+) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 9dc99c3e0b..ad87e225da 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -22,6 +22,7 @@ int main(void) #else /* !MBEDTLS_SSL_TEST_IMPOSSIBLE && MBEDTLS_SSL_CLI_C */ #include "test/psa_crypto_helpers.h" +#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. */ @@ -2800,12 +2801,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 541c6a6b43..b5cdc817b8 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -52,6 +52,7 @@ int main(void) #endif #include "test/psa_crypto_helpers.h" +#include "test/ssl_helpers.h" #include "mbedtls/pk.h" #if defined(MBEDTLS_PK_HAVE_PRIVATE_HEADER) @@ -3271,7 +3272,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 780c4f319b..0d2687e795 100644 --- a/tests/src/test_helpers/ssl_helpers.c +++ b/tests/src/test_helpers/ssl_helpers.c @@ -1035,6 +1035,14 @@ int mbedtls_test_ssl_endpoint_init( void mbedtls_test_ssl_endpoint_free( mbedtls_test_ssl_endpoint *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 a2338a21fa8c6c1c80284f80c032208168cdb183 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Jun 2026 14:53:21 +0200 Subject: [PATCH 131/168] library: ssl: reset some SSL context's fields in mbedtls_ssl_session_reset Following fields were not properly reset when mbedtls_ssl_session_reset was called: - badmac_seen - dtls_srtp_info - alert_reason - alert_type Signed-off-by: Valerio Setti --- library/ssl_tls.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index e8a44f834c..b1c6c22de1 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1309,6 +1309,8 @@ void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl, ssl->in_fatal_alert_recv = 0; ssl->in_fatal_alert_type = 0; ssl->send_alert = 0; + ssl->alert_reason = 0; + ssl->alert_type = 0; /* Reset outgoing message writing */ ssl->out_msgtype = 0; @@ -1358,6 +1360,8 @@ int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial) ssl->flags &= MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION; ssl->tls_version = ssl->conf->max_tls_version; + ssl->badmac_seen = 0; + mbedtls_ssl_session_reset_msg_layer(ssl, partial); /* Reset renegotiation state */ @@ -1383,6 +1387,10 @@ int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial) ssl->alpn_chosen = NULL; #endif +#if defined(MBEDTLS_SSL_DTLS_SRTP) + memset(&ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info)); +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) int free_cli_id = 1; #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) From 931b9831593cdab547f314f9dc33c2bf0909025f Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Jun 2026 14:55:31 +0200 Subject: [PATCH 132/168] changelog: add reset for some fields of the SSL context structure Signed-off-by: Valerio Setti --- ChangeLog.d/security1585.txt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 ChangeLog.d/security1585.txt diff --git a/ChangeLog.d/security1585.txt b/ChangeLog.d/security1585.txt new file mode 100644 index 0000000000..f9f21691db --- /dev/null +++ b/ChangeLog.d/security1585.txt @@ -0,0 +1,6 @@ +Security + * Ensure 'badmac_seen' and 'dtls_srtp_info' fields from 'mbedtls_ssl_context' + are properly zeroized when mbedtls_ssl_session_reset() is called. This + could cause premature DTLS connection failure or incorrect DTLS-SRTP + parameter inheritance for applications reusing an SSL context. + Reported by jjfz123. CVE-2026-50585. From 3bd3e47100f4b41aff81db91dbab96cd5733fc0d Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 23 Jun 2026 18:14:15 +0200 Subject: [PATCH 133/168] include: ssl: fix documentation of mbedtls_ssl_set_cid Specify that the configured CID will apply to all subsequent handshakes not just to the next one. Signed-off-by: Valerio Setti --- include/mbedtls/ssl.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index c2f9507a78..00e28442d6 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2181,7 +2181,7 @@ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, /** * \brief Configure the use of the Connection ID (CID) - * extension in the next handshake. + * extension in subsequent handshakes. * * Reference: RFC 9146 (or draft-ietf-tls-dtls-connection-id-05 * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 @@ -2202,7 +2202,7 @@ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, * headers of outgoing messages. * * This API enables or disables the use of the CID extension - * in the next handshake and sets the value of the CID to + * in subsequent handshakes and sets the value of the CID to * be used for incoming messages. * * \param ssl The SSL context to configure. This must be initialized. @@ -2233,11 +2233,11 @@ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, * successful call to this function to run the handshake. * * \note This call cannot guarantee that the use of the CID - * will be successfully negotiated in the next handshake, + * will be successfully negotiated in subsequent handshakes, * because the peer might not support it. Specifically: * - On the Client, enabling the use of the CID through - * this call implies that the `ClientHello` in the next - * handshake will include the CID extension, thereby + * this call implies that the `ClientHello` in subsequent + * handshakes will include the CID extension, thereby * offering the use of the CID to the server. Only if * the `ServerHello` contains the CID extension, too, * the CID extension will actually be put to use. @@ -2260,7 +2260,7 @@ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, * Mbed TLS. * * \return \c 0 on success. In this case, the CID configuration - * applies to the next handshake. + * applies to subsequent handshakes. * \return A negative error code on failure. */ int mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl, From 4b57c243bb5fbc66876e1c9ad95cdfbd98fe3729 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 23 Jun 2026 22:36:04 +0200 Subject: [PATCH 134/168] changelog: add note for documentation fix for mbedtls_ssl_set_cid Signed-off-by: Valerio Setti --- ChangeLog.d/mbedtls_ssl_set_cid-documentation.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 ChangeLog.d/mbedtls_ssl_set_cid-documentation.txt diff --git a/ChangeLog.d/mbedtls_ssl_set_cid-documentation.txt b/ChangeLog.d/mbedtls_ssl_set_cid-documentation.txt new file mode 100644 index 0000000000..1ad970fdfb --- /dev/null +++ b/ChangeLog.d/mbedtls_ssl_set_cid-documentation.txt @@ -0,0 +1,3 @@ +Bugfix + * Fixed documentation of mbedtls_ssl_set_cid(): the set CID configuration + is applied to all subsequent handshakes, not just to the next one. From b55e820fd1c2a563475856cd2bdb380c911c0658 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 23 Jun 2026 22:37:54 +0200 Subject: [PATCH 135/168] 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 365544616d2d7ea91ef1a41ad3cfca07e14931a0 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 23 Jun 2026 22:38:41 +0200 Subject: [PATCH 136/168] 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 d70169b85cb77ea8f00af4ffdda35157a730744d Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 23 Jun 2026 22:39:41 +0200 Subject: [PATCH 137/168] 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 6a86937df4..21965b0c9a 100644 --- a/tests/include/test/ssl_helpers.h +++ b/tests/include/test/ssl_helpers.h @@ -758,7 +758,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 508e9b1ca4417ffe5c0628bddfd157fa0294dbf3 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 23 Jun 2026 22:49:11 +0200 Subject: [PATCH 138/168] 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 dce45a7cfe6cb05841d4da2f47483224944ae95d Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 23 Jun 2026 23:34:01 +0200 Subject: [PATCH 139/168] 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 4c8a9b7a5e3d08f461248cd8eb793201511c4d63 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 24 Jun 2026 09:04:15 +0200 Subject: [PATCH 140/168] 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 c668f4e68e3e6eb953dae1b01b5cbffd220f9a80 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 24 Jun 2026 14:31:20 +0200 Subject: [PATCH 141/168] framework: update reference Signed-off-by: Valerio Setti --- framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework b/framework index d6dec17adf..dde0c4a0e4 160000 --- a/framework +++ b/framework @@ -1 +1 @@ -Subproject commit d6dec17adfb5bf283c6a7a5bb6c451ecdc0b8201 +Subproject commit dde0c4a0e448a0552f18817dcea633bb851fd288 From f722436e4619494cda0dc58f2efd09857d329f1d Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Wed, 24 Jun 2026 14:36:00 +0100 Subject: [PATCH 142/168] Changelog. Added attribution/CVE for 1569 Signed-off-by: Minos Galanakis --- ChangeLog.d/security-issue1569.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog.d/security-issue1569.txt b/ChangeLog.d/security-issue1569.txt index c7d3ca0782..c9e285b80e 100644 --- a/ChangeLog.d/security-issue1569.txt +++ b/ChangeLog.d/security-issue1569.txt @@ -1,4 +1,7 @@ Security * Improved documentation of mbedtls_ssl_conf_sig_algs() to emphasize that this function only sets signature algorithms that are enforced during - TLS key exchange and not on certificate verification. + TLS key exchange and not on certificate verification. Reported by + Xiangdong Li, Beijing University of Posts and Telecommunications (BUPT). + CVE-2026-54441 + From 4f92a63e4a2e07a62ae0da604d0269e25450345f Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 24 Jun 2026 15:37:00 +0200 Subject: [PATCH 143/168] 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 | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c index 0d2687e795..ebb9103de9 100644 --- a/tests/src/test_helpers/ssl_helpers.c +++ b/tests/src/test_helpers/ssl_helpers.c @@ -1035,14 +1035,17 @@ int mbedtls_test_ssl_endpoint_init( void mbedtls_test_ssl_endpoint_free( mbedtls_test_ssl_endpoint *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)); + /* 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_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 b340e27847ac2b80bb2e4435f8db6c1bd8c82d0a Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 3 Jun 2026 15:25:09 +0200 Subject: [PATCH 144/168] test_suite_ssl: Add early data drop tests Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 6 ++ tests/suites/test_suite_ssl.function | 153 +++++++++++++++++++++++++++ 2 files changed, 159 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index dbe0dfe44c..86cd311e01 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3586,3 +3586,9 @@ send_invalid_sig_alg:MBEDTLS_SSL_SIG_ECDSA:MBEDTLS_SSL_HASH_SHA512:MBEDTLS_ERR_S TLS 1.2 NewSessionTicket: failing ticket callback leaves lifetime unset depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY write_new_session_ticket_mem + +TLS 1.3 drop early data +tls13_drop_early_data:0 + +TLS 1.3 drop early data and insert an EndOfEarlyData +tls13_drop_early_data:1 diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index aba395a8ce..3b80db0a79 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6778,3 +6778,156 @@ exit: MD_OR_USE_PSA_DONE(); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_SSL_EARLY_DATA:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED:MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP:PSA_WANT_ALG_SHA_256:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:MBEDTLS_SSL_SESSION_TICKETS */ +void tls13_drop_early_data(int insert_end_of_early_data) +{ + int ret = -1; + mbedtls_test_ssl_endpoint client_ep, server_ep; + memset(&client_ep, 0, sizeof(client_ep)); + memset(&server_ep, 0, sizeof(server_ep)); + + mbedtls_test_handshake_test_options client_options, server_options; + mbedtls_test_init_handshake_options(&client_options); + mbedtls_test_init_handshake_options(&server_options); + + mbedtls_ssl_session saved_session; + mbedtls_ssl_session_init(&saved_session); + + const char *early_data = "This is early data."; + size_t early_data_len = strlen(early_data); + unsigned char buf[256]; + + PSA_INIT(); + + /* + * Run first handshake to get a ticket from the server. + */ + + client_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; + server_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; + ret = mbedtls_test_get_tls13_ticket(&client_options, &server_options, + &saved_session); + TEST_EQUAL(ret, 0); + + /* + * Prepare for handshake with the ticket. + */ + ret = mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, + &client_options); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, + &server_options); + TEST_EQUAL(ret, 0); + + mbedtls_ssl_conf_session_tickets_cb(&server_ep.conf, + mbedtls_test_ticket_write, + mbedtls_test_ticket_parse, + NULL); + + ret = mbedtls_test_mock_socket_connect(&(client_ep.socket), + &(server_ep.socket), 1024); + TEST_EQUAL(ret, 0); + + ret = mbedtls_ssl_set_session(&(client_ep.ssl), &saved_session); + TEST_EQUAL(ret, 0); + + /* + * Initiate handshake with ticket, up to the point where the client has + * written the ClientHello and only the ClientHello in its output socket + * buffer. + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO), 0); +#else + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + MBEDTLS_SSL_SERVER_HELLO), 0); +#endif + TEST_EQUAL(mbedtls_ssl_flush_output(&client_ep.ssl), 0); + + if (insert_end_of_early_data) { + /* + * Append an EndOfEarlyData message at the end of the record, just + * after the ClientHello message. + */ + unsigned char *client_output_buffer = client_ep.socket.output->buffer; + size_t record_size = MBEDTLS_GET_UINT16_BE(client_output_buffer, 3); + + MBEDTLS_PUT_UINT16_BE(record_size + 4, client_output_buffer, 3); + unsigned char end_of_early_data[] = { 0x05, 0x00, 0x00, 0x00 }; + ret = mbedtls_test_ssl_buffer_put(client_ep.socket.output, + end_of_early_data, + sizeof(end_of_early_data)); + TEST_EQUAL(ret, (int) sizeof(end_of_early_data)); + } + + /* + * The server read the record containing the ClientHello and possibly the + * EndOfEarlyData message and parse the ClientHello. + */ + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(server_ep.ssl), &(client_ep.ssl), + MBEDTLS_SSL_SERVER_HELLO), 0); + + /* The client application writes early data */ + ret = mbedtls_ssl_write_early_data(&(client_ep.ssl), + (unsigned char *) early_data, + early_data_len); + TEST_EQUAL(ret, early_data_len); + + /* Drop early data */ + TEST_ASSERT(client_ep.socket.output->content_length <= sizeof(buf)); + mbedtls_test_ssl_buffer_get(client_ep.socket.output, buf, sizeof(buf)); + TEST_EQUAL(server_ep.socket.input->content_length, 0); + + /* + * Resume the handshake, up to the point where the client is about to write + * the EndOfEarlyData message. + */ + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + MBEDTLS_SSL_END_OF_EARLY_DATA), 0); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_END_OF_EARLY_DATA); + + if (insert_end_of_early_data) { + /* + * Let the client write the EndOfEarlyData message and then read it + * from the output socket buffer, preventing it to reach the server as + * we have already inserted one. + */ + ret = mbedtls_ssl_handshake_step(&client_ep.ssl); + TEST_EQUAL(ret, 0); + ret = mbedtls_ssl_flush_output(&client_ep.ssl); + TEST_EQUAL(ret, 0); + TEST_ASSERT(client_ep.socket.output->content_length <= sizeof(buf)); + mbedtls_test_ssl_buffer_get(client_ep.socket.output, buf, sizeof(buf)); + } + + ret = mbedtls_test_move_handshake_to_state(&(server_ep.ssl), + &(client_ep.ssl), + MBEDTLS_SSL_HANDSHAKE_OVER); + if (insert_end_of_early_data) { + TEST_EQUAL(ret, 0); + } else { + /* + * If we have just dropped the early data then the EndOfEarlyData + * message is encrypted with the record number 1 while the server + * expects it to be encrypted with record number 0. Thus the + * handshake fails with MBEDTLS_ERR_SSL_INVALID_MAC. + */ + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_INVALID_MAC); + } + +exit: + mbedtls_test_ssl_endpoint_free(&client_ep); + mbedtls_test_ssl_endpoint_free(&server_ep); + mbedtls_test_free_handshake_options(&client_options); + mbedtls_test_free_handshake_options(&server_options); + mbedtls_ssl_session_free(&saved_session); + PSA_DONE(); +} +/* END_CASE */ From 3861588b47d045afcc66d9ba8b73b8217e87d2ce Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 22 May 2026 18:10:49 +0200 Subject: [PATCH 145/168] tls13: Add record boundary checks RFC 8446 (TLS 1.3 specification), Section 5.1, states: Handshake messages MAY be coalesced into a single TLSPlaintext record or fragmented across several records, provided that: ... -Handshake messages MUST NOT span key changes. Implementations MUST verify that all messages immediately preceding a key change align with a record boundary; if not, then they MUST terminate the connection with an "unexpected_message" alert. Because the ClientHello, EndOfEarlyData, ServerHello, Finished, and KeyUpdate messages can immediately precede a key change, implementations MUST send these messages in alignment with a record boundary. Signed-off-by: Ronald Cron --- library/ssl_misc.h | 1 + library/ssl_tls13_client.c | 8 ++-- library/ssl_tls13_generic.c | 10 +++-- library/ssl_tls13_server.c | 4 +- tests/suites/test_suite_ssl.function | 65 ++++++++++------------------ 5 files changed, 36 insertions(+), 52 deletions(-) diff --git a/library/ssl_misc.h b/library/ssl_misc.h index f0ca823f33..d85dbc6e1d 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -2028,6 +2028,7 @@ static inline int mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral( MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type, + unsigned record_boundary, unsigned char **buf, size_t *buf_len); diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index ecdf507eab..e4138fa2c7 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -2002,7 +2002,7 @@ static int ssl_tls13_process_server_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> %s", __func__)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len)); + ssl, MBEDTLS_SSL_HS_SERVER_HELLO, 1, &buf, &buf_len)); ret = ssl_tls13_preprocess_server_hello(ssl, buf, buf + buf_len); if (ret < 0) { @@ -2195,7 +2195,7 @@ static int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse encrypted extensions")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, + ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, 0, &buf, &buf_len)); /* Process the message contents */ @@ -2530,7 +2530,7 @@ static int ssl_tls13_process_certificate_request(mbedtls_ssl_context *ssl) size_t buf_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, + ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, 0, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_request( @@ -3025,7 +3025,7 @@ static int ssl_tls13_process_new_session_ticket(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse new session ticket")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, + ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, 0, &buf, &buf_len)); /* diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index 078daea352..90891567ec 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -47,6 +47,7 @@ const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[ int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type, + unsigned record_boundary, unsigned char **buf, size_t *buf_len) { @@ -58,7 +59,8 @@ int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || - ssl->in_msg[0] != hs_type) { + ssl->in_msg[0] != hs_type || + (record_boundary && (ssl->in_hslen != ssl->in_msglen))) { MBEDTLS_SSL_DEBUG_MSG(1, ("Receive unexpected handshake message.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); @@ -339,7 +341,7 @@ int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl) MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, &buf_len)); + ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, 0, &buf, &buf_len)); /* Need to calculate the hash of the transcript first * before reading the message since otherwise it gets @@ -691,7 +693,7 @@ int mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl) size_t buf_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_CERTIFICATE, + ssl, MBEDTLS_SSL_HS_CERTIFICATE, 0, &buf, &buf_len)); /* Parse the certificate chain sent by the peer. */ @@ -1110,7 +1112,7 @@ int mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished message")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len)); + ssl, MBEDTLS_SSL_HS_FINISHED, 1, &buf, &buf_len)); /* Preprocessing step: Compute handshake digest */ MBEDTLS_SSL_PROC_CHK(ssl_tls13_preprocess_finished_message(ssl)); diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index 38f2fe9370..0db142c50a 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -1936,7 +1936,7 @@ static int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, + ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, 1, &buf, &buflen)); MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_parse_client_hello(ssl, buf, @@ -3027,7 +3027,7 @@ static int ssl_tls13_process_end_of_early_data(mbedtls_ssl_context *ssl) size_t buf_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, + ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, 1, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_end_of_early_data( diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 3b80db0a79..d058401148 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4124,7 +4124,7 @@ void tls13_server_certificate_msg_invalid_vector_len() ret = mbedtls_ssl_tls13_fetch_handshake_msg(&(client_ep.ssl), MBEDTLS_SSL_HS_CERTIFICATE, - &buf, &buf_len); + 0, &buf, &buf_len); TEST_EQUAL(ret, 0); end = buf + buf_len; @@ -6865,14 +6865,21 @@ void tls13_drop_early_data(int insert_end_of_early_data) TEST_EQUAL(ret, (int) sizeof(end_of_early_data)); } - /* - * The server read the record containing the ClientHello and possibly the - * EndOfEarlyData message and parse the ClientHello. - */ - TEST_EQUAL(mbedtls_test_move_handshake_to_state( - &(server_ep.ssl), &(client_ep.ssl), - MBEDTLS_SSL_SERVER_HELLO), 0); + /* The server read the record containing the ClientHello. */ + ret = mbedtls_test_move_handshake_to_state(&(server_ep.ssl), + &(client_ep.ssl), + MBEDTLS_SSL_SERVER_HELLO); + if (insert_end_of_early_data) { + /* + * If an EndOfEarlyData message was appended to the record containing + * the ClientHello then the end of the ClientHello does not align with + * the record boundary and the handshake fails. + */ + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); + goto exit; + } + TEST_EQUAL(ret, 0); /* The client application writes early data */ ret = mbedtls_ssl_write_early_data(&(client_ep.ssl), (unsigned char *) early_data, @@ -6884,43 +6891,17 @@ void tls13_drop_early_data(int insert_end_of_early_data) mbedtls_test_ssl_buffer_get(client_ep.socket.output, buf, sizeof(buf)); TEST_EQUAL(server_ep.socket.input->content_length, 0); - /* - * Resume the handshake, up to the point where the client is about to write - * the EndOfEarlyData message. - */ - TEST_EQUAL(mbedtls_test_move_handshake_to_state( - &(client_ep.ssl), &(server_ep.ssl), - MBEDTLS_SSL_END_OF_EARLY_DATA), 0); - TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_END_OF_EARLY_DATA); - - if (insert_end_of_early_data) { - /* - * Let the client write the EndOfEarlyData message and then read it - * from the output socket buffer, preventing it to reach the server as - * we have already inserted one. - */ - ret = mbedtls_ssl_handshake_step(&client_ep.ssl); - TEST_EQUAL(ret, 0); - ret = mbedtls_ssl_flush_output(&client_ep.ssl); - TEST_EQUAL(ret, 0); - TEST_ASSERT(client_ep.socket.output->content_length <= sizeof(buf)); - mbedtls_test_ssl_buffer_get(client_ep.socket.output, buf, sizeof(buf)); - } - + /* Resume the handshake */ ret = mbedtls_test_move_handshake_to_state(&(server_ep.ssl), &(client_ep.ssl), MBEDTLS_SSL_HANDSHAKE_OVER); - if (insert_end_of_early_data) { - TEST_EQUAL(ret, 0); - } else { - /* - * If we have just dropped the early data then the EndOfEarlyData - * message is encrypted with the record number 1 while the server - * expects it to be encrypted with record number 0. Thus the - * handshake fails with MBEDTLS_ERR_SSL_INVALID_MAC. - */ - TEST_EQUAL(ret, MBEDTLS_ERR_SSL_INVALID_MAC); - } + /* + * The early data were dropped. The EndOfEarlyData message is encrypted + * with the record number 1, but the server expects it to be encrypted + * with record number 0. Thus the handshake fails with + * MBEDTLS_ERR_SSL_INVALID_MAC. + */ + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_INVALID_MAC); exit: mbedtls_test_ssl_endpoint_free(&client_ep); From c8fefcde05bc3bae9e344719308593fefe893180 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 8 Jun 2026 13:06:08 +0200 Subject: [PATCH 146/168] test_suite_ssl: Test ClientHello on record boundary check Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 3 + tests/suites/test_suite_ssl.function | 95 ++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 86cd311e01..43554ce112 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3592,3 +3592,6 @@ tls13_drop_early_data:0 TLS 1.3 drop early data and insert an EndOfEarlyData tls13_drop_early_data:1 + +TLS 1.3 ClientHello record boundary alignment enforcement +tls13_record_boundary_alignment:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_HS_CLIENT_HELLO diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index d058401148..772e64f02b 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6912,3 +6912,98 @@ exit: PSA_DONE(); } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_DEBUG_C:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_SHA_256:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN */ +void tls13_record_boundary_alignment(int endpoint, int handshake_message) +{ + int ret = -1; + int target_state, peer_target_state, encrypted; + mbedtls_test_ssl_endpoint client_ep, server_ep; + + mbedtls_test_handshake_test_options client_options, server_options; + mbedtls_test_init_handshake_options(&client_options); + mbedtls_test_init_handshake_options(&server_options); + + mbedtls_test_mock_socket *socket = NULL; + mbedtls_ssl_context *ssl_ctx = NULL; + mbedtls_ssl_context *peer_ssl_ctx = NULL; + unsigned char dummy_data[] = { 0x00 }; + + PSA_INIT(); + + switch (handshake_message) { + case MBEDTLS_SSL_HS_CLIENT_HELLO: + TEST_EQUAL(endpoint, MBEDTLS_SSL_IS_SERVER); + target_state = MBEDTLS_SSL_CLIENT_HELLO; + peer_target_state = MBEDTLS_SSL_SERVER_HELLO; + encrypted = 0; + break; + + default: + TEST_ASSERT(0); + } + + if (endpoint == MBEDTLS_SSL_IS_CLIENT) { + ssl_ctx = &client_ep.ssl; + peer_ssl_ctx = &server_ep.ssl; + socket = &client_ep.socket; + } else { + ssl_ctx = &server_ep.ssl; + peer_ssl_ctx = &client_ep.ssl; + socket = &server_ep.socket; + } + + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, + &client_options), 0); + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, + &server_options), 0); + TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket), + &(server_ep.socket), 1024), 0); + + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + ssl_ctx, peer_ssl_ctx, target_state), 0); + TEST_EQUAL(mbedtls_ssl_flush_output(ssl_ctx), 0); + /* + * Advance the peer further through the handshake so that it emits the + * messages needed by the endpoint under test to proceed through its next + * step. + */ + if (peer_target_state != -1) { + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + peer_ssl_ctx, ssl_ctx, peer_target_state), 0); + TEST_EQUAL(mbedtls_ssl_flush_output(peer_ssl_ctx), 0); + } + TEST_EQUAL(ssl_ctx->state, target_state); + + if (encrypted) { + TEST_ASSERT(0); + } else { + /* + * In case of the unencrypted ClientHello or ServerHello, add an + * additional byte to the record that contains the handshake message. + * The byte is added in the socket buffer, before to be fetched by + * `mbedtls_ssl_read_record()`, simulating a man-in-the-middle tampering + * with the record. + */ + unsigned char *input_buffer = socket->input->buffer; + size_t record_size = MBEDTLS_GET_UINT16_BE(input_buffer, 3); + ret = mbedtls_test_ssl_buffer_put(socket->input, dummy_data, + sizeof(dummy_data)); + TEST_EQUAL(ret, (int) sizeof(dummy_data)); + MBEDTLS_PUT_UINT16_BE(record_size + sizeof(dummy_data), input_buffer, 3); + } + + ret = mbedtls_ssl_handshake_step(ssl_ctx); + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); + TEST_EQUAL(ssl_ctx->in_msglen, + ssl_ctx->in_hslen + sizeof(dummy_data)); + TEST_EQUAL(ssl_ctx->in_msgtype, MBEDTLS_SSL_MSG_HANDSHAKE); + TEST_EQUAL(ssl_ctx->in_msg[0], handshake_message); + +exit: + mbedtls_test_ssl_endpoint_free(&client_ep); + mbedtls_test_ssl_endpoint_free(&server_ep); + mbedtls_test_free_handshake_options(&client_options); + mbedtls_test_free_handshake_options(&server_options); + PSA_DONE(); +} +/* END_CASE */ From 93eb43ed4fd09c51a6dc7a434d347199b1c9cf97 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 8 Jun 2026 13:18:20 +0200 Subject: [PATCH 147/168] test_suite_ssl: Test ServerHello on record boundary enforcement Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 3 +++ tests/suites/test_suite_ssl.function | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 43554ce112..575b26a9e3 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3595,3 +3595,6 @@ tls13_drop_early_data:1 TLS 1.3 ClientHello record boundary alignment enforcement tls13_record_boundary_alignment:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_HS_CLIENT_HELLO + +TLS 1.3 ServerHello record boundary alignement enforcement +tls13_record_boundary_alignment:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_HS_SERVER_HELLO diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 772e64f02b..767c6a607c 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6938,6 +6938,13 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) encrypted = 0; break; + case MBEDTLS_SSL_HS_SERVER_HELLO: + TEST_EQUAL(endpoint, MBEDTLS_SSL_IS_CLIENT); + target_state = MBEDTLS_SSL_SERVER_HELLO; + peer_target_state = MBEDTLS_SSL_ENCRYPTED_EXTENSIONS; + encrypted = 0; + break; + default: TEST_ASSERT(0); } From 53ac018b24e11762ba43521c0fb2d5e01c6e13ca Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 8 Jun 2026 14:10:19 +0200 Subject: [PATCH 148/168] test_suite_ssl: Test server Finished on record boundary enforcement Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 3 ++ tests/suites/test_suite_ssl.function | 78 +++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 575b26a9e3..7b9a81ce17 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3598,3 +3598,6 @@ tls13_record_boundary_alignment:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_HS_CLIENT_HELL TLS 1.3 ServerHello record boundary alignement enforcement tls13_record_boundary_alignment:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_HS_SERVER_HELLO + +TLS 1.3 server Finished record boundary alignement enforcement +tls13_record_boundary_alignment:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_HS_FINISHED diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 767c6a607c..617cbd58ae 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -552,6 +552,51 @@ exit: #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED etc */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_DEBUG_C) && \ + defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE) && \ + defined(MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP) && \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) && \ + defined(PSA_WANT_ALG_SHA_256) && \ + defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) +typedef struct { + /* Context for `tls_tweak_in_msglen()`. The debug callback + * watches for "<= read record" in the SSL debug trace. When the pattern is + * detected, it increases by `nb_bytes` the 'in_msglen' field of the + * associated SSL context. + */ + mbedtls_ssl_context *ssl; + int armed; + int nb_bytes; + int triggered; +} tls_tweak_in_msglen_context; + +static void tls_tweak_in_msglen(void *ctx, int level, + const char *file, int line, + const char *str) +{ + tls_tweak_in_msglen_context *tweak_in_msglen_ctx = ctx; + + (void) level; + (void) file; + (void) line; + + if (!tweak_in_msglen_ctx->armed) { + return; + } + if (strstr(str, "<= read record") == NULL) { + return; + } + + tweak_in_msglen_ctx->ssl->in_msglen += tweak_in_msglen_ctx->nb_bytes; + tweak_in_msglen_ctx->armed = 0; + tweak_in_msglen_ctx->triggered++; +} +#endif + + + /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -6923,6 +6968,9 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) mbedtls_test_init_handshake_options(&client_options); mbedtls_test_init_handshake_options(&server_options); + tls_tweak_in_msglen_context tweak_in_msglen_ctx; + memset(&tweak_in_msglen_ctx, 0, sizeof(tweak_in_msglen_ctx)); + mbedtls_test_mock_socket *socket = NULL; mbedtls_ssl_context *ssl_ctx = NULL; mbedtls_ssl_context *peer_ssl_ctx = NULL; @@ -6945,6 +6993,14 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) encrypted = 0; break; + case MBEDTLS_SSL_HS_FINISHED: + if (endpoint == MBEDTLS_SSL_IS_CLIENT) { + target_state = MBEDTLS_SSL_SERVER_FINISHED; + peer_target_state = MBEDTLS_SSL_CLIENT_CERTIFICATE; + } + encrypted = 1; + break; + default: TEST_ASSERT(0); } @@ -6953,12 +7009,19 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) ssl_ctx = &client_ep.ssl; peer_ssl_ctx = &server_ep.ssl; socket = &client_ep.socket; + client_options.cli_log_obj = &tweak_in_msglen_ctx; + client_options.cli_log_fun = tls_tweak_in_msglen; } else { ssl_ctx = &server_ep.ssl; peer_ssl_ctx = &client_ep.ssl; socket = &server_ep.socket; + server_options.srv_log_obj = &tweak_in_msglen_ctx; + server_options.srv_log_fun = tls_tweak_in_msglen; } + mbedtls_debug_set_threshold(2); + tweak_in_msglen_ctx.ssl = ssl_ctx; + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, &client_options), 0); TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, @@ -6982,7 +7045,15 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) TEST_EQUAL(ssl_ctx->state, target_state); if (encrypted) { - TEST_ASSERT(0); + /* + * If the message we want to test the record boundary enforcement is + * encrypted, we cannot manipulate easily the record that contains it. + * In that case, we tamper with the record size after the record has been + * fetched from the socket buffer and decrypted by + * `mbedtls_ssl_read_record()`. + */ + tweak_in_msglen_ctx.armed = 1; + tweak_in_msglen_ctx.nb_bytes = sizeof(dummy_data); } else { /* * In case of the unencrypted ClientHello or ServerHello, add an @@ -7006,11 +7077,16 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) TEST_EQUAL(ssl_ctx->in_msgtype, MBEDTLS_SSL_MSG_HANDSHAKE); TEST_EQUAL(ssl_ctx->in_msg[0], handshake_message); + if (encrypted) { + TEST_EQUAL(tweak_in_msglen_ctx.triggered, 1); + } + exit: mbedtls_test_ssl_endpoint_free(&client_ep); mbedtls_test_ssl_endpoint_free(&server_ep); mbedtls_test_free_handshake_options(&client_options); mbedtls_test_free_handshake_options(&server_options); + mbedtls_debug_set_threshold(0); PSA_DONE(); } /* END_CASE */ From cbef7256ce41778617e76c7c84b629d74338586d Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 8 Jun 2026 16:21:57 +0200 Subject: [PATCH 149/168] test_suite_ssl: Test client Finished on record boundary enforcement Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 3 +++ tests/suites/test_suite_ssl.function | 3 +++ 2 files changed, 6 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 7b9a81ce17..eecb4abfbd 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3601,3 +3601,6 @@ tls13_record_boundary_alignment:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_HS_SERVER_HELL TLS 1.3 server Finished record boundary alignement enforcement tls13_record_boundary_alignment:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_HS_FINISHED + +TLS 1.3 client Finished record boundary alignement enforcement +tls13_record_boundary_alignment:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_HS_FINISHED diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 617cbd58ae..e4857e0b21 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6997,6 +6997,9 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) if (endpoint == MBEDTLS_SSL_IS_CLIENT) { target_state = MBEDTLS_SSL_SERVER_FINISHED; peer_target_state = MBEDTLS_SSL_CLIENT_CERTIFICATE; + } else { + target_state = MBEDTLS_SSL_CLIENT_FINISHED; + peer_target_state = MBEDTLS_SSL_FLUSH_BUFFERS; } encrypted = 1; break; From 2de65b79a3e2b7930b9b4a3eb90bc4813fa61548 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 9 Jun 2026 13:20:49 +0200 Subject: [PATCH 150/168] test_suite_ssl: Test EndOfEarlyData on record boundary enforcement Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 4 ++++ tests/suites/test_suite_ssl.function | 32 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index eecb4abfbd..c856da44ff 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3604,3 +3604,7 @@ tls13_record_boundary_alignment:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_HS_FINISHED TLS 1.3 client Finished record boundary alignement enforcement tls13_record_boundary_alignment:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_HS_FINISHED + +TLS 1.3 EndOfEarlyData record boundary alignement enforcement +depends_on:MBEDTLS_SSL_EARLY_DATA:MBEDTLS_SSL_SESSION_TICKETS +tls13_record_boundary_alignment:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_HS_END_OF_EARLY_DATA diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index e4857e0b21..c7b15824b4 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6968,6 +6968,9 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) mbedtls_test_init_handshake_options(&client_options); mbedtls_test_init_handshake_options(&server_options); + mbedtls_ssl_session saved_session; + mbedtls_ssl_session_init(&saved_session); + tls_tweak_in_msglen_context tweak_in_msglen_ctx; memset(&tweak_in_msglen_ctx, 0, sizeof(tweak_in_msglen_ctx)); @@ -7004,6 +7007,21 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) encrypted = 1; break; + +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_HS_END_OF_EARLY_DATA: + TEST_EQUAL(endpoint, MBEDTLS_SSL_IS_SERVER); + target_state = MBEDTLS_SSL_END_OF_EARLY_DATA; + peer_target_state = MBEDTLS_SSL_CLIENT_CERTIFICATE; + encrypted = 1; + client_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; + server_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; + ret = mbedtls_test_get_tls13_ticket(&client_options, &server_options, + &saved_session); + TEST_EQUAL(ret, 0); + break; +#endif + default: TEST_ASSERT(0); } @@ -7029,6 +7047,19 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) &client_options), 0); TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, &server_options), 0); + +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SESSION_TICKETS) + if (handshake_message == MBEDTLS_SSL_HS_END_OF_EARLY_DATA) { + mbedtls_ssl_conf_session_tickets_cb(&server_ep.conf, + mbedtls_test_ticket_write, + mbedtls_test_ticket_parse, + NULL); + + ret = mbedtls_ssl_set_session(&(client_ep.ssl), &saved_session); + TEST_EQUAL(ret, 0); + } +#endif + TEST_EQUAL(mbedtls_test_mock_socket_connect(&(client_ep.socket), &(server_ep.socket), 1024), 0); @@ -7090,6 +7121,7 @@ exit: mbedtls_test_free_handshake_options(&client_options); mbedtls_test_free_handshake_options(&server_options); mbedtls_debug_set_threshold(0); + mbedtls_ssl_session_free(&saved_session); PSA_DONE(); } /* END_CASE */ From e55d0b76ed5980c1ac46169b37bdbe0ea3fbb466 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 10 Jun 2026 10:47:57 +0200 Subject: [PATCH 151/168] Add change log Signed-off-by: Ronald Cron --- ChangeLog.d/drop-early-data.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 ChangeLog.d/drop-early-data.txt diff --git a/ChangeLog.d/drop-early-data.txt b/ChangeLog.d/drop-early-data.txt new file mode 100644 index 0000000000..dc597a23f0 --- /dev/null +++ b/ChangeLog.d/drop-early-data.txt @@ -0,0 +1,7 @@ +Security + * Fixed a TLS 1.3 record-boundary validation issue that could allow + unauthenticated plaintext data to be processed across a key change. In + servers with MBEDTLS_SSL_EARLY_DATA enabled, this could be exploited by a + man-in-the-middle attacker to cause loss of 0-RTT early data. + Reported by Ben Smyth. + CVE-2026-TODO. From c494497256057f2fda69d9bb260f37f975d03c35 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 11 Jun 2026 19:23:15 +0200 Subject: [PATCH 152/168] Fix typos Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index c856da44ff..a08bb2b961 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3596,15 +3596,15 @@ tls13_drop_early_data:1 TLS 1.3 ClientHello record boundary alignment enforcement tls13_record_boundary_alignment:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_HS_CLIENT_HELLO -TLS 1.3 ServerHello record boundary alignement enforcement +TLS 1.3 ServerHello record boundary alignment enforcement tls13_record_boundary_alignment:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_HS_SERVER_HELLO -TLS 1.3 server Finished record boundary alignement enforcement +TLS 1.3 server Finished record boundary alignment enforcement tls13_record_boundary_alignment:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_HS_FINISHED -TLS 1.3 client Finished record boundary alignement enforcement +TLS 1.3 client Finished record boundary alignment enforcement tls13_record_boundary_alignment:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_HS_FINISHED -TLS 1.3 EndOfEarlyData record boundary alignement enforcement +TLS 1.3 EndOfEarlyData record boundary alignment enforcement depends_on:MBEDTLS_SSL_EARLY_DATA:MBEDTLS_SSL_SESSION_TICKETS tls13_record_boundary_alignment:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_HS_END_OF_EARLY_DATA From 86315b62a833cc28ff0c3a3c659854f62e0ff4b8 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 11 Jun 2026 19:38:42 +0200 Subject: [PATCH 153/168] test_suite_ssl: Add initialization to all zeroes of test endpoint structs Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.function | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index c7b15824b4..f6eeeabe1f 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6963,6 +6963,8 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) int ret = -1; int target_state, peer_target_state, encrypted; mbedtls_test_ssl_endpoint client_ep, server_ep; + memset(&client_ep, 0, sizeof(client_ep)); + memset(&server_ep, 0, sizeof(server_ep)); mbedtls_test_handshake_test_options client_options, server_options; mbedtls_test_init_handshake_options(&client_options); From 0c9d3d4a0fb50216993d4142335a2888929bcd72 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 11 Jun 2026 19:40:36 +0200 Subject: [PATCH 154/168] tls13: Improve argument name Signed-off-by: Ronald Cron --- library/ssl_misc.h | 2 +- library/ssl_tls13_generic.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/ssl_misc.h b/library/ssl_misc.h index d85dbc6e1d..8d9323c6de 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -2028,7 +2028,7 @@ static inline int mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral( MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type, - unsigned record_boundary, + unsigned require_record_boundary, unsigned char **buf, size_t *buf_len); diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index 90891567ec..1465de1ec0 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -47,7 +47,7 @@ const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[ int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type, - unsigned record_boundary, + unsigned require_record_boundary, unsigned char **buf, size_t *buf_len) { @@ -60,7 +60,7 @@ int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || ssl->in_msg[0] != hs_type || - (record_boundary && (ssl->in_hslen != ssl->in_msglen))) { + (require_record_boundary && (ssl->in_hslen != ssl->in_msglen))) { MBEDTLS_SSL_DEBUG_MSG(1, ("Receive unexpected handshake message.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); From 6c557a70f6a2992282e5a342714be4c89130b8f4 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 15 Jun 2026 14:09:17 +0200 Subject: [PATCH 155/168] tls13: Rework mbedtls_ssl_tls13_fetch_handshake_msg() Signed-off-by: Ronald Cron --- library/ssl_tls13_generic.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index 1465de1ec0..92dfcc3dfc 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -53,19 +53,23 @@ int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, { int ret; - if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { + ret = mbedtls_ssl_read_record(ssl, 0); + if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); - goto cleanup; + goto error; } + ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || - ssl->in_msg[0] != hs_type || - (require_record_boundary && (ssl->in_hslen != ssl->in_msglen))) { + ssl->in_msg[0] != hs_type) { MBEDTLS_SSL_DEBUG_MSG(1, ("Receive unexpected handshake message.")); - MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, - MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); - ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; - goto cleanup; + goto error; + } + + if (require_record_boundary && (ssl->in_hslen != ssl->in_msglen)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Handshake message %s end not aligned with a record boundary", + mbedtls_ssl_get_hs_msg_name(hs_type))); + goto error; } /* @@ -75,11 +79,15 @@ int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, * uint24 length; * ... */ - *buf = ssl->in_msg + 4; + *buf = ssl->in_msg + 4; *buf_len = ssl->in_hslen - 4; + return 0; -cleanup: - +error: + if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, + MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); + } return ret; } From 1a58c59470788ac93e101b4c4869f0e46975c973 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 15 Jun 2026 14:18:34 +0200 Subject: [PATCH 156/168] Various improvements of tls13_(drop_early_data|record_boundary_alignment)() Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.function | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index f6eeeabe1f..1f6d542eb4 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6957,6 +6957,7 @@ exit: PSA_DONE(); } /* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_DEBUG_C:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_SHA_256:MBEDTLS_X509_RSASSA_PSS_SUPPORT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN */ void tls13_record_boundary_alignment(int endpoint, int handshake_message) { @@ -7025,7 +7026,7 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) #endif default: - TEST_ASSERT(0); + TEST_FAIL("Handshake message type not supported"); } if (endpoint == MBEDTLS_SSL_IS_CLIENT) { @@ -7073,11 +7074,10 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) * messages needed by the endpoint under test to proceed through its next * step. */ - if (peer_target_state != -1) { - TEST_EQUAL(mbedtls_test_move_handshake_to_state( - peer_ssl_ctx, ssl_ctx, peer_target_state), 0); - TEST_EQUAL(mbedtls_ssl_flush_output(peer_ssl_ctx), 0); - } + TEST_ASSERT(peer_target_state != -1); + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + peer_ssl_ctx, ssl_ctx, peer_target_state), 0); + TEST_EQUAL(mbedtls_ssl_flush_output(peer_ssl_ctx), 0); TEST_EQUAL(ssl_ctx->state, target_state); if (encrypted) { From e08cea612f8931fef9af83c0ec0248f8c1aa31c3 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 15 Jun 2026 15:16:36 +0200 Subject: [PATCH 157/168] tls13_record_boundary_alignement: Append empty hs msg Append an empty handshake message to expand the record instead of just a zero byte. Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.function | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 1f6d542eb4..f48543d4c9 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6980,7 +6980,7 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) mbedtls_test_mock_socket *socket = NULL; mbedtls_ssl_context *ssl_ctx = NULL; mbedtls_ssl_context *peer_ssl_ctx = NULL; - unsigned char dummy_data[] = { 0x00 }; + unsigned char additional_empty_hs_msg[4] = { 0, 0, 0, 0 }; PSA_INIT(); @@ -6989,6 +6989,7 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) TEST_EQUAL(endpoint, MBEDTLS_SSL_IS_SERVER); target_state = MBEDTLS_SSL_CLIENT_HELLO; peer_target_state = MBEDTLS_SSL_SERVER_HELLO; + additional_empty_hs_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; encrypted = 0; break; @@ -6996,6 +6997,7 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) TEST_EQUAL(endpoint, MBEDTLS_SSL_IS_CLIENT); target_state = MBEDTLS_SSL_SERVER_HELLO; peer_target_state = MBEDTLS_SSL_ENCRYPTED_EXTENSIONS; + additional_empty_hs_msg[0] = MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS; encrypted = 0; break; @@ -7007,6 +7009,10 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) target_state = MBEDTLS_SSL_CLIENT_FINISHED; peer_target_state = MBEDTLS_SSL_FLUSH_BUFFERS; } + /* Finished messages are not followed by any handshake message, + * insert an empty Finished message at the end of the record. + */ + additional_empty_hs_msg[0] = MBEDTLS_SSL_HS_FINISHED; encrypted = 1; break; @@ -7016,6 +7022,7 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) TEST_EQUAL(endpoint, MBEDTLS_SSL_IS_SERVER); target_state = MBEDTLS_SSL_END_OF_EARLY_DATA; peer_target_state = MBEDTLS_SSL_CLIENT_CERTIFICATE; + additional_empty_hs_msg[0] = MBEDTLS_SSL_HS_FINISHED; encrypted = 1; client_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; server_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; @@ -7089,7 +7096,7 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) * `mbedtls_ssl_read_record()`. */ tweak_in_msglen_ctx.armed = 1; - tweak_in_msglen_ctx.nb_bytes = sizeof(dummy_data); + tweak_in_msglen_ctx.nb_bytes = sizeof(additional_empty_hs_msg); } else { /* * In case of the unencrypted ClientHello or ServerHello, add an @@ -7100,16 +7107,17 @@ void tls13_record_boundary_alignment(int endpoint, int handshake_message) */ unsigned char *input_buffer = socket->input->buffer; size_t record_size = MBEDTLS_GET_UINT16_BE(input_buffer, 3); - ret = mbedtls_test_ssl_buffer_put(socket->input, dummy_data, - sizeof(dummy_data)); - TEST_EQUAL(ret, (int) sizeof(dummy_data)); - MBEDTLS_PUT_UINT16_BE(record_size + sizeof(dummy_data), input_buffer, 3); + ret = mbedtls_test_ssl_buffer_put(socket->input, additional_empty_hs_msg, + sizeof(additional_empty_hs_msg)); + TEST_EQUAL(ret, (int) sizeof(additional_empty_hs_msg)); + MBEDTLS_PUT_UINT16_BE(record_size + sizeof(additional_empty_hs_msg), + input_buffer, 3); } ret = mbedtls_ssl_handshake_step(ssl_ctx); TEST_EQUAL(ret, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); TEST_EQUAL(ssl_ctx->in_msglen, - ssl_ctx->in_hslen + sizeof(dummy_data)); + ssl_ctx->in_hslen + sizeof(additional_empty_hs_msg)); TEST_EQUAL(ssl_ctx->in_msgtype, MBEDTLS_SSL_MSG_HANDSHAKE); TEST_EQUAL(ssl_ctx->in_msg[0], handshake_message); From 74b9ab200820537b8f5cf8e55bd4f42d912a4c78 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 16 Jun 2026 18:41:56 +0200 Subject: [PATCH 158/168] tls13_fetch_handshake_msg(): Remove require_record_boundary parameter Deduce it from the handshake message type Signed-off-by: Ronald Cron --- library/ssl_misc.h | 1 - library/ssl_tls13_client.c | 8 ++++---- library/ssl_tls13_generic.c | 29 +++++++++++++++++++++++----- library/ssl_tls13_server.c | 4 ++-- tests/suites/test_suite_ssl.function | 2 +- 5 files changed, 31 insertions(+), 13 deletions(-) diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 8d9323c6de..f0ca823f33 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -2028,7 +2028,6 @@ static inline int mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral( MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type, - unsigned require_record_boundary, unsigned char **buf, size_t *buf_len); diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index e4138fa2c7..ecdf507eab 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -2002,7 +2002,7 @@ static int ssl_tls13_process_server_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> %s", __func__)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_SERVER_HELLO, 1, &buf, &buf_len)); + ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len)); ret = ssl_tls13_preprocess_server_hello(ssl, buf, buf + buf_len); if (ret < 0) { @@ -2195,7 +2195,7 @@ static int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse encrypted extensions")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, 0, + ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, &buf, &buf_len)); /* Process the message contents */ @@ -2530,7 +2530,7 @@ static int ssl_tls13_process_certificate_request(mbedtls_ssl_context *ssl) size_t buf_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, 0, + ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_request( @@ -3025,7 +3025,7 @@ static int ssl_tls13_process_new_session_ticket(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse new session ticket")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, 0, + ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, &buf, &buf_len)); /* diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index 92dfcc3dfc..0cdce76903 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -47,11 +47,30 @@ const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[ int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type, - unsigned require_record_boundary, unsigned char **buf, size_t *buf_len) { - int ret; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int require_record_boundary; + + /* Require record-boundary alignment by default. The exceptions below are + * handshake messages that may legitimately be followed by additional + * handshake messages in the same record. Using the default behaviour for a + * message that should be exempt is an interoperability bug; exempting a + * message that should not be exempt may have security implications. + */ + switch (hs_type) { + case MBEDTLS_SSL_HS_NEW_SESSION_TICKET: + case MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS: + case MBEDTLS_SSL_HS_CERTIFICATE: + case MBEDTLS_SSL_HS_CERTIFICATE_REQUEST: + case MBEDTLS_SSL_HS_CERTIFICATE_VERIFY: + require_record_boundary = 0; + break; + + default: + require_record_boundary = 1; + } ret = mbedtls_ssl_read_record(ssl, 0); if (ret != 0) { @@ -349,7 +368,7 @@ int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl) MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, 0, &buf, &buf_len)); + ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, &buf_len)); /* Need to calculate the hash of the transcript first * before reading the message since otherwise it gets @@ -701,7 +720,7 @@ int mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl) size_t buf_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_CERTIFICATE, 0, + ssl, MBEDTLS_SSL_HS_CERTIFICATE, &buf, &buf_len)); /* Parse the certificate chain sent by the peer. */ @@ -1120,7 +1139,7 @@ int mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished message")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_FINISHED, 1, &buf, &buf_len)); + ssl, MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len)); /* Preprocessing step: Compute handshake digest */ MBEDTLS_SSL_PROC_CHK(ssl_tls13_preprocess_finished_message(ssl)); diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index 0db142c50a..38f2fe9370 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -1936,7 +1936,7 @@ static int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, 1, + ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, &buf, &buflen)); MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_parse_client_hello(ssl, buf, @@ -3027,7 +3027,7 @@ static int ssl_tls13_process_end_of_early_data(mbedtls_ssl_context *ssl) size_t buf_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( - ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, 1, + ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_end_of_early_data( diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index f48543d4c9..f655b1cf90 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4169,7 +4169,7 @@ void tls13_server_certificate_msg_invalid_vector_len() ret = mbedtls_ssl_tls13_fetch_handshake_msg(&(client_ep.ssl), MBEDTLS_SSL_HS_CERTIFICATE, - 0, &buf, &buf_len); + &buf, &buf_len); TEST_EQUAL(ret, 0); end = buf + buf_len; From b188f399f926af64d06fdb842cbbceed2209f6a8 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 23 Jun 2026 10:34:33 +0200 Subject: [PATCH 159/168] Check ServerHello record boundary alignment only in TLS 1.3 case Signed-off-by: Ronald Cron --- library/ssl_tls13_client.c | 13 +++++++++++++ library/ssl_tls13_generic.c | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index ecdf507eab..e8b6063f32 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -2016,6 +2016,19 @@ static int ssl_tls13_process_server_hello(mbedtls_ssl_context *ssl) goto cleanup; } + /* + * TLS 1.3 is negotiated. Check that ServerHello/HRR ends at a record + * boundary. For HRR, which does not trigger a key update, this checks + * that HRR terminates the server flight. + */ + if (ssl->in_hslen != ssl->in_msglen) { + MBEDTLS_SSL_DEBUG_MSG(1, ("ServerHello end not aligned with a record boundary")); + ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, + MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); + goto cleanup; + } + MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_server_hello(ssl, buf, buf + buf_len, is_hrr)); diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index 0cdce76903..abb8b4f3e4 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -65,10 +65,20 @@ int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, case MBEDTLS_SSL_HS_CERTIFICATE: case MBEDTLS_SSL_HS_CERTIFICATE_REQUEST: case MBEDTLS_SSL_HS_CERTIFICATE_VERIFY: + /* + * For TLS 1.3, ServerHello (including HelloRetryRequest) must end at a + * record boundary, but not for TLS 1.2. At this point the ServerHello + * has not yet been processed, so we do not know whether it negotiates + * TLS 1.3 or TLS 1.2. Defer the boundary check until the protocol + * version is known to be TLS 1.3. + */ + case MBEDTLS_SSL_HS_SERVER_HELLO: require_record_boundary = 0; break; default: + /* ClientHello, EndOfEarlyData, Finished, and KeyUpdate. + */ require_record_boundary = 1; } From 97a9420455aadd93c5018847c7688f2d26682d0a Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Fri, 26 Jun 2026 22:25:51 +0100 Subject: [PATCH 160/168] Updated tf-psa-crypto submodule Signed-off-by: Minos Galanakis --- tf-psa-crypto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tf-psa-crypto b/tf-psa-crypto index c35df96204..73c5da561c 160000 --- a/tf-psa-crypto +++ b/tf-psa-crypto @@ -1 +1 @@ -Subproject commit c35df962041731b08c6ff6a39a59e239c344e1ee +Subproject commit 73c5da561c8e5253db7b1fb440eda86fde8d8024 From b11a07f274c4ed13581e66b1e8f3b5e094ec99d0 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Fri, 26 Jun 2026 22:28:45 +0100 Subject: [PATCH 161/168] Bump version --version 4.2.0 ./scripts/bump_version.sh --version 4.2.0 Signed-off-by: Minos Galanakis --- CMakeLists.txt | 2 +- doxygen/input/doc_mainpage.h | 2 +- doxygen/mbedtls.doxyfile | 2 +- include/mbedtls/build_info.h | 8 ++++---- tests/suites/test_suite_version.data | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c6d076346c..527b443050 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ cmake_policy(SET CMP0011 NEW) # is deprecated and will be removed in future versions. cmake_policy(SET CMP0012 NEW) -set(MBEDTLS_VERSION 4.1.0) +set(MBEDTLS_VERSION 4.2.0) set(MBEDTLS_CRYPTO_SOVERSION 18) set(MBEDTLS_X509_SOVERSION 9) set(MBEDTLS_TLS_SOVERSION 23) diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h index b28b82b851..bb86551778 100644 --- a/doxygen/input/doc_mainpage.h +++ b/doxygen/input/doc_mainpage.h @@ -10,7 +10,7 @@ */ /** - * @mainpage Mbed TLS v4.1.0 API Documentation + * @mainpage Mbed TLS v4.2.0 API Documentation * * This documentation describes the application programming interface (API) * of Mbed TLS. diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile index c6a5e4f4fd..e52790af6b 100644 --- a/doxygen/mbedtls.doxyfile +++ b/doxygen/mbedtls.doxyfile @@ -1,4 +1,4 @@ -PROJECT_NAME = "Mbed TLS v4.1.0" +PROJECT_NAME = "Mbed TLS v4.2.0" OUTPUT_DIRECTORY = ../apidoc/ FULL_PATH_NAMES = NO OPTIMIZE_OUTPUT_FOR_C = YES diff --git a/include/mbedtls/build_info.h b/include/mbedtls/build_info.h index e077bbce40..d71e12068b 100644 --- a/include/mbedtls/build_info.h +++ b/include/mbedtls/build_info.h @@ -27,7 +27,7 @@ * Major, Minor, Patchlevel */ #define MBEDTLS_VERSION_MAJOR 4 -#define MBEDTLS_VERSION_MINOR 1 +#define MBEDTLS_VERSION_MINOR 2 #define MBEDTLS_VERSION_PATCH 0 /** @@ -35,9 +35,9 @@ * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x04010000 -#define MBEDTLS_VERSION_STRING "4.1.0" -#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 4.1.0" +#define MBEDTLS_VERSION_NUMBER 0x04020000 +#define MBEDTLS_VERSION_STRING "4.2.0" +#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 4.2.0" #if defined(MBEDTLS_CONFIG_FILES_READ) #error "Something went wrong: MBEDTLS_CONFIG_FILES_READ defined before reading the config files!" diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data index 5ffdfe71f9..c22e121461 100644 --- a/tests/suites/test_suite_version.data +++ b/tests/suites/test_suite_version.data @@ -1,8 +1,8 @@ Check compile time library version -check_compiletime_version:"4.1.0" +check_compiletime_version:"4.2.0" Check runtime library version -check_runtime_version:"4.1.0" +check_runtime_version:"4.2.0" Check for MBEDTLS_VERSION_C check_feature:"MBEDTLS_VERSION_C":0 From f3c2896076152fbc657807cc9957117becb1bac2 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Fri, 26 Jun 2026 22:30:10 +0100 Subject: [PATCH 162/168] Assemble ChangeLog ./framework/scripts/assemble_changelog.py Signed-off-by: Minos Galanakis --- ChangeLog | 100 ++++++++++++++++++ .../1583-1584-ssl-transcript-errors.txt | 17 --- ChangeLog.d/cmake-destdir-instal.txt | 3 - ChangeLog.d/drop-early-data.txt | 7 -- ChangeLog.d/ecdh-psk-integer-overflow.txt | 3 - ChangeLog.d/fix-info-leak-in-ssl.txt | 6 -- ChangeLog.d/fix-tls12-rsa-pss-sigalgs.txt | 4 - ChangeLog.d/issue10740.txt | 3 - .../mbedtls_ssl_set_cid-documentation.txt | 3 - ChangeLog.d/oob-key-exchange-restricted.txt | 4 - ChangeLog.d/pkcs-free-stale-pointers.txt | 6 -- ChangeLog.d/pkcs7-reject-weak-hashes.txt | 7 -- .../pr_10695__fix_build_llvm_mingw.txt | 3 - ChangeLog.d/security-advice.txt | 2 - ChangeLog.d/security-issue1569.txt | 7 -- ChangeLog.d/security1585.txt | 6 -- .../serialized-data-load-hardening.txt | 5 - ...pare_new_session_ticket-psa_get_random.txt | 5 - ChangeLog.d/tls13-hrr-selected-group.txt | 7 -- .../x509-crt-parse-basicConstraints.txt | 15 --- .../x509-csr-extension-request-bounds.txt | 3 - 21 files changed, 100 insertions(+), 116 deletions(-) delete mode 100644 ChangeLog.d/1583-1584-ssl-transcript-errors.txt delete mode 100644 ChangeLog.d/cmake-destdir-instal.txt delete mode 100644 ChangeLog.d/drop-early-data.txt delete mode 100644 ChangeLog.d/ecdh-psk-integer-overflow.txt delete mode 100644 ChangeLog.d/fix-info-leak-in-ssl.txt delete mode 100644 ChangeLog.d/fix-tls12-rsa-pss-sigalgs.txt delete mode 100644 ChangeLog.d/issue10740.txt delete mode 100644 ChangeLog.d/mbedtls_ssl_set_cid-documentation.txt delete mode 100644 ChangeLog.d/oob-key-exchange-restricted.txt delete mode 100644 ChangeLog.d/pkcs-free-stale-pointers.txt delete mode 100644 ChangeLog.d/pkcs7-reject-weak-hashes.txt delete mode 100644 ChangeLog.d/pr_10695__fix_build_llvm_mingw.txt delete mode 100644 ChangeLog.d/security-advice.txt delete mode 100644 ChangeLog.d/security-issue1569.txt delete mode 100644 ChangeLog.d/security1585.txt delete mode 100644 ChangeLog.d/serialized-data-load-hardening.txt delete mode 100644 ChangeLog.d/ssl_tls13_prepare_new_session_ticket-psa_get_random.txt delete mode 100644 ChangeLog.d/tls13-hrr-selected-group.txt delete mode 100644 ChangeLog.d/x509-crt-parse-basicConstraints.txt delete mode 100644 ChangeLog.d/x509-csr-extension-request-bounds.txt diff --git a/ChangeLog b/ChangeLog index b7a79ce348..7dc74ddc68 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,105 @@ Mbed TLS ChangeLog (Sorted per branch, date) += Mbed TLS 4.2.0 branch released 2026-07-07 + +Features + * Restore DESTDIR support for CMake installs of compatibility + libmbedcrypto symlinks. Fixes #10627. + * SHA3-256, SHA3-384 and SHA3-512 are now accepted in the default X.509 + certificate profile. + +Security + * Added advice about compiler options in SECURITY.md. + * Fix a bug where transcript-hash computation errors during TLS 1.2 + extended master secret calculation could be ignored instead of causing the + handshake to fail. This could allow a handshake to continue with a master + secret that was not correctly bound to the handshake transcript, + undermining the security guarantees of the extended master secret + extension. Report by Mathew Gretton-Dann. CVE-2026-50581 + * Fix a TLS 1.3 server-side error-handling bug affecting session ticket + generation. Under rare conditions, such as memory allocation failures + while computing the resumption master secret, the server could issue + invalid session tickets instead of failing the handshake. Clients + presented with such tickets would fail session resumption and fall back to + a full handshake. In deployments relying on session resumption, repeated + occurrences could increase the frequency of full handshakes and amplify + resource consumption during periods of resource exhaustion or other + transient failures. Reported by jjfz123. + CVE-2026-50640 + * Fixed a TLS 1.3 record-boundary validation issue that could allow + unauthenticated plaintext data to be processed across a key change. In + servers with MBEDTLS_SSL_EARLY_DATA enabled, this could be exploited by a + man-in-the-middle attacker to cause loss of 0-RTT early data. + Reported by Ben Smyth. + CVE-2026-TODO. + * Fix a remote buffer overflow in (D)TLS with ECDHE-PSK cipher suites when + CBC is disabled. Reported by Karnakar Reddy. CVE-2026-50580 + * Fix a potential information disclosure in TLS 1.2 servers using session + tickets. If the session ticket write callback failed without setting the + lifetime output parameter, Mbed TLS could send 4 bytes of uninitialized + stack memory to the peer in the NewSessionTicket message. Fixes #1570. + Reported by James Love. CVE-2026-50586. + * Fix an out-of-bounds read when parsing TLS 1.2 ECJPAKE ServerKeyExchange + messages. Reported-by Biniam Demissie. + CVE-2026-50588 + * Fix a use-after-free/double-free risk in mbedtls_pkcs7_free() when reusing + an mbedtls_pkcs7 context across parse -> free -> parse -> free cycles. The + function now resets the context after freeing it, ensuring stale + signed_data.signers.next pointers cannot be walked by a later free + operation. CVE-2026-50579 + * PKCS7 now rejects weak hash algorithms (RIPEMD160, MD5, SHA-1, SHA-224, + SHA3-224) on signature verification. + * Improved documentation of mbedtls_ssl_conf_sig_algs() to emphasize that + this function only sets signature algorithms that are enforced during + TLS key exchange and not on certificate verification. Reported by + Xiangdong Li, Beijing University of Posts and Telecommunications (BUPT). + CVE-2026-54441 + * Ensure 'badmac_seen' and 'dtls_srtp_info' fields from 'mbedtls_ssl_context' + are properly zeroized when mbedtls_ssl_session_reset() is called. This + could cause premature DTLS connection failure or incorrect DTLS-SRTP + parameter inheritance for applications reusing an SSL context. + Reported by jjfz123. CVE-2026-50585. + * Fix a bug where mbedtls_ssl_read() and mbedtls_ssl_write() could return + 1 instead of an error code if the random generator failed when a server + called these functions before the end of a TLS 1.3 handshake. + Reported by Mohammad Seet (mhdsait101). CVE-2026-40294 + * Fix TLS 1.3 clients to reject a HelloRetryRequest whose selected group was + not advertised in the original ClientHello. Reported independently by + Din Asotić / Xiangdong Li, Beijing University of Posts and + Telecommunications (BUPT), and NVIDIA Project Vanessa. + CVE-2026-25832. + * Fix two bugs in the X.509 certificate parser that caused some inputs + with a malformed basicConstraints extension to be accepted. This + could have dangerous results, in particular causing some certificates + to be parsed as CA certificates when other X.509 implementations would + parse them as end-entity certificates. Reported by Mohammad Seet + (mhdsait101), Pablo Ruiz García and NVIDIA Project Vanessa. CVE-2026-49300 + +Bugfix + * Fix a TLS 1.2 regression that caused clients to reject valid + ServerKeyExchange signatures using RSA-PSS signature algorithms. + Fixes #10668. + * Fix a build error using the LLVM based MinGW toolchain. + Bug reported and fix contributed by valord577. + * Fixed a bug which prevented the inclusion of standard C library header + files from the user provided configuration file. Fixes #10740. + * Reject malformed TLS 1.3 serialized sessions instead of accepting + unterminated strings or extra trailing data. + * Reject serialized SSL contexts whose DTLS Connection ID length exceeds + the maximum supported size, instead of overflowing the internal buffer. + * Fixed documentation of mbedtls_ssl_set_cid(): the set CID configuration + is applied to all subsequent handshakes, not just to the next one. + * Reject malformed X.509 CSRs where the extensionRequest attribute + wrappers do not exactly contain the requested extensions. + +Changes + * X.509 certificates with a basicConstraints extension starting with an + INTEGER field are no longer accepted. According to RFC 5280, such + certificates are syntactically valid and the first field is the + pathLenConstraint value, but certificate authorities must not emit such + certificates. Mbed TLS interpreted it as a cA value, which was nonstandard + and dangerous. + = Mbed TLS 4.1.0 branch released 2026-03-31 API changes diff --git a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt b/ChangeLog.d/1583-1584-ssl-transcript-errors.txt deleted file mode 100644 index f259bd711e..0000000000 --- a/ChangeLog.d/1583-1584-ssl-transcript-errors.txt +++ /dev/null @@ -1,17 +0,0 @@ -Security - * Fix a bug where transcript-hash computation errors during TLS 1.2 - extended master secret calculation could be ignored instead of causing the - handshake to fail. This could allow a handshake to continue with a master - secret that was not correctly bound to the handshake transcript, - undermining the security guarantees of the extended master secret - extension. Report by Mathew Gretton-Dann. CVE-2026-50581 - * Fix a TLS 1.3 server-side error-handling bug affecting session ticket - generation. Under rare conditions, such as memory allocation failures - while computing the resumption master secret, the server could issue - invalid session tickets instead of failing the handshake. Clients - presented with such tickets would fail session resumption and fall back to - a full handshake. In deployments relying on session resumption, repeated - occurrences could increase the frequency of full handshakes and amplify - resource consumption during periods of resource exhaustion or other - transient failures. Reported by jjfz123. - CVE-2026-50640 diff --git a/ChangeLog.d/cmake-destdir-instal.txt b/ChangeLog.d/cmake-destdir-instal.txt deleted file mode 100644 index 1638a4bea9..0000000000 --- a/ChangeLog.d/cmake-destdir-instal.txt +++ /dev/null @@ -1,3 +0,0 @@ -Features - * Restore DESTDIR support for CMake installs of compatibility - libmbedcrypto symlinks. Fixes #10627. diff --git a/ChangeLog.d/drop-early-data.txt b/ChangeLog.d/drop-early-data.txt deleted file mode 100644 index dc597a23f0..0000000000 --- a/ChangeLog.d/drop-early-data.txt +++ /dev/null @@ -1,7 +0,0 @@ -Security - * Fixed a TLS 1.3 record-boundary validation issue that could allow - unauthenticated plaintext data to be processed across a key change. In - servers with MBEDTLS_SSL_EARLY_DATA enabled, this could be exploited by a - man-in-the-middle attacker to cause loss of 0-RTT early data. - Reported by Ben Smyth. - CVE-2026-TODO. diff --git a/ChangeLog.d/ecdh-psk-integer-overflow.txt b/ChangeLog.d/ecdh-psk-integer-overflow.txt deleted file mode 100644 index 47dfd428de..0000000000 --- a/ChangeLog.d/ecdh-psk-integer-overflow.txt +++ /dev/null @@ -1,3 +0,0 @@ -Security - * Fix a remote buffer overflow in (D)TLS with ECDHE-PSK cipher suites when - CBC is disabled. Reported by Karnakar Reddy. CVE-2026-50580 diff --git a/ChangeLog.d/fix-info-leak-in-ssl.txt b/ChangeLog.d/fix-info-leak-in-ssl.txt deleted file mode 100644 index 2a0309fc40..0000000000 --- a/ChangeLog.d/fix-info-leak-in-ssl.txt +++ /dev/null @@ -1,6 +0,0 @@ -Security - * Fix a potential information disclosure in TLS 1.2 servers using session - tickets. If the session ticket write callback failed without setting the - lifetime output parameter, Mbed TLS could send 4 bytes of uninitialized - stack memory to the peer in the NewSessionTicket message. Fixes #1570. - Reported by James Love. CVE-2026-50586. diff --git a/ChangeLog.d/fix-tls12-rsa-pss-sigalgs.txt b/ChangeLog.d/fix-tls12-rsa-pss-sigalgs.txt deleted file mode 100644 index 34296b602e..0000000000 --- a/ChangeLog.d/fix-tls12-rsa-pss-sigalgs.txt +++ /dev/null @@ -1,4 +0,0 @@ -Bugfix - * Fix a TLS 1.2 regression that caused clients to reject valid - ServerKeyExchange signatures using RSA-PSS signature algorithms. - Fixes #10668. diff --git a/ChangeLog.d/issue10740.txt b/ChangeLog.d/issue10740.txt deleted file mode 100644 index eb7a36c063..0000000000 --- a/ChangeLog.d/issue10740.txt +++ /dev/null @@ -1,3 +0,0 @@ -Bugfix - * Fixed a bug which prevented the inclusion of standard C library header - files from the user provided configuration file. Fixes #10740. diff --git a/ChangeLog.d/mbedtls_ssl_set_cid-documentation.txt b/ChangeLog.d/mbedtls_ssl_set_cid-documentation.txt deleted file mode 100644 index 1ad970fdfb..0000000000 --- a/ChangeLog.d/mbedtls_ssl_set_cid-documentation.txt +++ /dev/null @@ -1,3 +0,0 @@ -Bugfix - * Fixed documentation of mbedtls_ssl_set_cid(): the set CID configuration - is applied to all subsequent handshakes, not just to the next one. diff --git a/ChangeLog.d/oob-key-exchange-restricted.txt b/ChangeLog.d/oob-key-exchange-restricted.txt deleted file mode 100644 index 2e48ce0fec..0000000000 --- a/ChangeLog.d/oob-key-exchange-restricted.txt +++ /dev/null @@ -1,4 +0,0 @@ -Security - * Fix an out-of-bounds read when parsing TLS 1.2 ECJPAKE ServerKeyExchange - messages. Reported-by Biniam Demissie. - CVE-2026-50588 diff --git a/ChangeLog.d/pkcs-free-stale-pointers.txt b/ChangeLog.d/pkcs-free-stale-pointers.txt deleted file mode 100644 index 2c29fed5ef..0000000000 --- a/ChangeLog.d/pkcs-free-stale-pointers.txt +++ /dev/null @@ -1,6 +0,0 @@ -Security - * Fix a use-after-free/double-free risk in mbedtls_pkcs7_free() when reusing - an mbedtls_pkcs7 context across parse -> free -> parse -> free cycles. The - function now resets the context after freeing it, ensuring stale - signed_data.signers.next pointers cannot be walked by a later free - operation. CVE-2026-50579 diff --git a/ChangeLog.d/pkcs7-reject-weak-hashes.txt b/ChangeLog.d/pkcs7-reject-weak-hashes.txt deleted file mode 100644 index a62cca9b96..0000000000 --- a/ChangeLog.d/pkcs7-reject-weak-hashes.txt +++ /dev/null @@ -1,7 +0,0 @@ -Security - * PKCS7 now rejects weak hash algorithms (RIPEMD160, MD5, SHA-1, SHA-224, - SHA3-224) on signature verification. - -Features - * SHA3-256, SHA3-384 and SHA3-512 are now accepted in the default X.509 - certificate profile. diff --git a/ChangeLog.d/pr_10695__fix_build_llvm_mingw.txt b/ChangeLog.d/pr_10695__fix_build_llvm_mingw.txt deleted file mode 100644 index 3fed87143f..0000000000 --- a/ChangeLog.d/pr_10695__fix_build_llvm_mingw.txt +++ /dev/null @@ -1,3 +0,0 @@ -Bugfix - * Fix a build error using the LLVM based MinGW toolchain. - Bug reported and fix contributed by valord577. diff --git a/ChangeLog.d/security-advice.txt b/ChangeLog.d/security-advice.txt deleted file mode 100644 index 1f7677a882..0000000000 --- a/ChangeLog.d/security-advice.txt +++ /dev/null @@ -1,2 +0,0 @@ -Security - * Added advice about compiler options in SECURITY.md. diff --git a/ChangeLog.d/security-issue1569.txt b/ChangeLog.d/security-issue1569.txt deleted file mode 100644 index c9e285b80e..0000000000 --- a/ChangeLog.d/security-issue1569.txt +++ /dev/null @@ -1,7 +0,0 @@ -Security - * Improved documentation of mbedtls_ssl_conf_sig_algs() to emphasize that - this function only sets signature algorithms that are enforced during - TLS key exchange and not on certificate verification. Reported by - Xiangdong Li, Beijing University of Posts and Telecommunications (BUPT). - CVE-2026-54441 - diff --git a/ChangeLog.d/security1585.txt b/ChangeLog.d/security1585.txt deleted file mode 100644 index f9f21691db..0000000000 --- a/ChangeLog.d/security1585.txt +++ /dev/null @@ -1,6 +0,0 @@ -Security - * Ensure 'badmac_seen' and 'dtls_srtp_info' fields from 'mbedtls_ssl_context' - are properly zeroized when mbedtls_ssl_session_reset() is called. This - could cause premature DTLS connection failure or incorrect DTLS-SRTP - parameter inheritance for applications reusing an SSL context. - Reported by jjfz123. CVE-2026-50585. diff --git a/ChangeLog.d/serialized-data-load-hardening.txt b/ChangeLog.d/serialized-data-load-hardening.txt deleted file mode 100644 index e068988dac..0000000000 --- a/ChangeLog.d/serialized-data-load-hardening.txt +++ /dev/null @@ -1,5 +0,0 @@ -Bugfix - * Reject malformed TLS 1.3 serialized sessions instead of accepting - unterminated strings or extra trailing data. - * Reject serialized SSL contexts whose DTLS Connection ID length exceeds - the maximum supported size, instead of overflowing the internal buffer. diff --git a/ChangeLog.d/ssl_tls13_prepare_new_session_ticket-psa_get_random.txt b/ChangeLog.d/ssl_tls13_prepare_new_session_ticket-psa_get_random.txt deleted file mode 100644 index b020546b12..0000000000 --- a/ChangeLog.d/ssl_tls13_prepare_new_session_ticket-psa_get_random.txt +++ /dev/null @@ -1,5 +0,0 @@ -Security - * Fix a bug where mbedtls_ssl_read() and mbedtls_ssl_write() could return - 1 instead of an error code if the random generator failed when a server - called these functions before the end of a TLS 1.3 handshake. - Reported by Mohammad Seet (mhdsait101). CVE-2026-40294 diff --git a/ChangeLog.d/tls13-hrr-selected-group.txt b/ChangeLog.d/tls13-hrr-selected-group.txt deleted file mode 100644 index 4c338480f6..0000000000 --- a/ChangeLog.d/tls13-hrr-selected-group.txt +++ /dev/null @@ -1,7 +0,0 @@ -Security - * Fix TLS 1.3 clients to reject a HelloRetryRequest whose selected group was - not advertised in the original ClientHello. Reported independently by - Din Asotić / Xiangdong Li, Beijing University of Posts and - Telecommunications (BUPT), and NVIDIA Project Vanessa. - CVE-2026-25832. - diff --git a/ChangeLog.d/x509-crt-parse-basicConstraints.txt b/ChangeLog.d/x509-crt-parse-basicConstraints.txt deleted file mode 100644 index 251dc8f0fd..0000000000 --- a/ChangeLog.d/x509-crt-parse-basicConstraints.txt +++ /dev/null @@ -1,15 +0,0 @@ -Security - * Fix two bugs in the X.509 certificate parser that caused some inputs - with a malformed basicConstraints extension to be accepted. This - could have dangerous results, in particular causing some certificates - to be parsed as CA certificates when other X.509 implementations would - parse them as end-entity certificates. Reported by Mohammad Seet - (mhdsait101), Pablo Ruiz García and NVIDIA Project Vanessa. CVE-2026-49300 - -Changes - * X.509 certificates with a basicConstraints extension starting with an - INTEGER field are no longer accepted. According to RFC 5280, such - certificates are syntactically valid and the first field is the - pathLenConstraint value, but certificate authorities must not emit such - certificates. Mbed TLS interpreted it as a cA value, which was nonstandard - and dangerous. diff --git a/ChangeLog.d/x509-csr-extension-request-bounds.txt b/ChangeLog.d/x509-csr-extension-request-bounds.txt deleted file mode 100644 index dfc706703c..0000000000 --- a/ChangeLog.d/x509-csr-extension-request-bounds.txt +++ /dev/null @@ -1,3 +0,0 @@ -Bugfix - * Reject malformed X.509 CSRs where the extensionRequest attribute - wrappers do not exactly contain the requested extensions. From 7f64d9609b8877915f4ca12b61f51460b507e51b Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Mon, 29 Jun 2026 18:05:23 +0100 Subject: [PATCH 163/168] Changelog: Added reference to tf-psa-crypto update Signed-off-by: Minos Galanakis --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 7dc74ddc68..9882407054 100644 --- a/ChangeLog +++ b/ChangeLog @@ -93,6 +93,7 @@ Bugfix wrappers do not exactly contain the requested extensions. Changes + * Upgraded TF-PSA-Crypto from 1.1.0 to 1.2.0. See tf-psa-crypto/ChangeLog. * X.509 certificates with a basicConstraints extension starting with an INTEGER field are no longer accepted. According to RFC 5280, such certificates are syntactically valid and the first field is the From c1cc0ed3ed991db3432c722f8570e1f1c7a79de9 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Mon, 29 Jun 2026 18:13:24 +0100 Subject: [PATCH 164/168] ChangeLog: Removed todo placeholder for CVE Signed-off-by: Minos Galanakis --- ChangeLog | 1 - 1 file changed, 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 9882407054..44dbe3ca2b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,7 +31,6 @@ Security servers with MBEDTLS_SSL_EARLY_DATA enabled, this could be exploited by a man-in-the-middle attacker to cause loss of 0-RTT early data. Reported by Ben Smyth. - CVE-2026-TODO. * Fix a remote buffer overflow in (D)TLS with ECDHE-PSK cipher suites when CBC is disabled. Reported by Karnakar Reddy. CVE-2026-50580 * Fix a potential information disclosure in TLS 1.2 servers using session From b4ee2d42778255a5b8d2b5a85ec674eb44685ff5 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Fri, 26 Jun 2026 22:31:08 +0100 Subject: [PATCH 165/168] Update BRANCHES.md Signed-off-by: Minos Galanakis --- BRANCHES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BRANCHES.md b/BRANCHES.md index 8abb39cefb..cce737cd25 100644 --- a/BRANCHES.md +++ b/BRANCHES.md @@ -88,9 +88,9 @@ The following branches are currently maintained: - [`development`](https://github.com/Mbed-TLS/mbedtls/) - [`mbedtls-3.6`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-3.6) maintained until March 2027, see - . + . - [`mbedtls-4.1`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-4.1) maintained until March 2029, see - . + . Users are urged to always use the latest version of a maintained branch. From ece41aa84d7879d7e55c59e955a5884b541f7f3b Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Wed, 1 Jul 2026 12:00:14 +0100 Subject: [PATCH 166/168] ChangeLog: Removed CVE-ID Signed-off-by: Minos Galanakis --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 44dbe3ca2b..76d65c6ac2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -61,7 +61,7 @@ Security * Fix a bug where mbedtls_ssl_read() and mbedtls_ssl_write() could return 1 instead of an error code if the random generator failed when a server called these functions before the end of a TLS 1.3 handshake. - Reported by Mohammad Seet (mhdsait101). CVE-2026-40294 + Reported by Mohammad Seet (mhdsait101). * Fix TLS 1.3 clients to reject a HelloRetryRequest whose selected group was not advertised in the original ClientHello. Reported independently by Din Asotić / Xiangdong Li, Beijing University of Posts and From 53aaf3215b656e10bff9f7e34256635e1978d4eb Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Tue, 7 Jul 2026 16:52:40 +0100 Subject: [PATCH 167/168] Updated tf-psa-crypto submodule Signed-off-by: Minos Galanakis --- tf-psa-crypto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tf-psa-crypto b/tf-psa-crypto index 73c5da561c..a92cb6a97d 160000 --- a/tf-psa-crypto +++ b/tf-psa-crypto @@ -1 +1 @@ -Subproject commit 73c5da561c8e5253db7b1fb440eda86fde8d8024 +Subproject commit a92cb6a97d84762d2f4355eae99af7b9ff5c6ae1 From bacdd16661ef293af2b9521d4539b3bed3e11620 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Tue, 7 Jul 2026 16:52:40 +0100 Subject: [PATCH 168/168] Updated framework Signed-off-by: Minos Galanakis --- framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework b/framework index dde0c4a0e4..a307955223 160000 --- a/framework +++ b/framework @@ -1 +1 @@ -Subproject commit dde0c4a0e448a0552f18817dcea633bb851fd288 +Subproject commit a3079552234917a9831dd70693983af5e62c70de