From f7b4b5aac088c3a105e454bb0bfa98f09f6fc7c9 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 2 Oct 2025 15:52:59 +0100 Subject: [PATCH 01/66] Add malicious ip test for inet_pton Signed-off-by: Janos Follath --- tests/suites/test_suite_x509parse.data | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 0ca27a9d68..4fc5054b49 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -1170,6 +1170,9 @@ x509_crt_parse_cn_inet_pton:"\:\:ffff\:1111.2.3.4":"":0 X509 CRT parse CN: IPv6 invalid address IPv4-mapped #3 x509_crt_parse_cn_inet_pton:"\:\:1.2.3.4\:ffff":"":0 +X509 CRT parse CN: IPv6 invalid address IPv4-mapped #4 +x509_crt_parse_cn_inet_pton:"1.2.3.4\:":"":0 + X509 CRT verification with ca callback: failure depends_on:MBEDTLS_PEM_PARSE_C:PSA_WANT_ALG_SHA_1:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK x509_verify_ca_cb_failure:"../framework/data_files/server1.crt":"../framework/data_files/test-ca.crt":"NULL":MBEDTLS_ERR_X509_FATAL_ERROR From 346720d674728b8600a8e8d2696a00dd5c38592d Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 2 Oct 2025 15:53:56 +0100 Subject: [PATCH 02/66] Add ASan to test_sw_inet_pton Signed-off-by: Janos Follath --- tests/scripts/components-configuration-x509.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/scripts/components-configuration-x509.sh b/tests/scripts/components-configuration-x509.sh index 8010a2a2e6..66e9b16da8 100644 --- a/tests/scripts/components-configuration-x509.sh +++ b/tests/scripts/components-configuration-x509.sh @@ -28,8 +28,9 @@ component_test_sw_inet_pton () { # MBEDTLS_TEST_HOOKS required for x509_crt_parse_cn_inet_pton scripts/config.py set MBEDTLS_TEST_HOOKS - $MAKE_COMMAND CFLAGS="-DMBEDTLS_TEST_SW_INET_PTON" + CC=$ASAN_CC CFLAGS="-DMBEDTLS_TEST_SW_INET_PTON" cmake -D CMAKE_BUILD_TYPE:String=Asan . + make msg "test: default plus MBEDTLS_TEST_SW_INET_PTON" - $MAKE_COMMAND test + make test } From d5e7465ea07bb708c82a1710a2867596e7e78b2e Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 20 Jan 2026 18:19:33 +0000 Subject: [PATCH 03/66] inet_pton: help ASan find the underflow The generated unit tests have the input parameters in large stack buffers and therefore ASan doesn't notice under or overflows in them. Copy the input parameter into a locally allocated buffer to trigger ASan if something goes wrong. Signed-off-by: Janos Follath --- tests/suites/test_suite_x509parse.function | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index e892ab9a9e..25d229d6f1 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -488,12 +488,22 @@ exit: void x509_crt_parse_cn_inet_pton(const char *cn, data_t *exp, int ref_ret) { uint32_t addr[4]; - size_t addrlen = mbedtls_x509_crt_parse_cn_inet_pton(cn, addr); + + char *cn_local = NULL; + size_t cn_local_len = strlen(cn) + 1; + TEST_CALLOC(cn_local, cn_local_len); + memcpy(cn_local, cn, cn_local_len); + + size_t addrlen = mbedtls_x509_crt_parse_cn_inet_pton(cn_local, addr); TEST_EQUAL(addrlen, (size_t) ref_ret); if (addrlen) { TEST_MEMORY_COMPARE(exp->x, exp->len, addr, addrlen); } + +exit: + mbedtls_free(cn_local); + } /* END_CASE */ From 1a127e3c892076dd9725fce2ee10015eb20448f4 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 20 Jan 2026 18:46:52 +0000 Subject: [PATCH 04/66] inet_pton: fix buggy condition The flawed condition made us accept invalid IPv6 addresses and in some cases lead to a buffer underread. Signed-off-by: Janos Follath --- library/x509_crt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index 59c3204467..25a4bbaf68 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2719,8 +2719,12 @@ static int x509_inet_pton_ipv6(const char *src, void *dst) if (*p == '\0') { break; } else if (*p == '.') { - /* Don't accept IPv4 too early or late */ - if ((nonzero_groups == 0 && zero_group_start == -1) || + /* Don't accept IPv4 too early or late: + * - The first 6 nonzero groups must be 16 bit pieces of address delimited by ':' + * - This might be fully or partially represented with compressed syntax (a zero + * group "::") + */ + if ((nonzero_groups < 6 && zero_group_start == -1) || nonzero_groups >= 7) { break; } From 57f189887bf72268d3de042cf1437e324f022708 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 21 Jan 2026 09:16:07 +0000 Subject: [PATCH 05/66] Add ChangeLog entry Signed-off-by: Janos Follath --- ChangeLog.d/inet_pton.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ChangeLog.d/inet_pton.txt diff --git a/ChangeLog.d/inet_pton.txt b/ChangeLog.d/inet_pton.txt new file mode 100644 index 0000000000..526cd9be5f --- /dev/null +++ b/ChangeLog.d/inet_pton.txt @@ -0,0 +1,4 @@ +Security + * Fix a limited buffer underflow in x509_inet_pton_ipv6(). In rare cases + (e.g. on platforms with memory protection when the overread crosses page + boundary) this could lead to DoS. Found and reported by Haruto Kimura. From 50376926a7356c25da12f1d2e66cacf2d3e9bbcb Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 21 Jan 2026 17:29:07 +0000 Subject: [PATCH 06/66] inet_pton: simplify IPv4 walkback loop Signed-off-by: Janos Follath --- library/x509_crt.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index 25a4bbaf68..028ae8bf14 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2729,16 +2729,15 @@ static int x509_inet_pton_ipv6(const char *src, void *dst) break; } - /* Walk back to prior ':', then parse as IPv4-mapped */ - int steps = 4; + /* Walk back to prior ':', then parse as IPv4-mapped. + * At this point nonzero_groups == 6 or zero_group_start >= 0. Either way we have a + * ':' before the current position and still inside the buffer. Thus it is safe to + * search back for that ':' without any further checks. + */ do { p--; - steps--; - } while (*p != ':' && steps > 0); + } while (*p != ':'); - if (*p != ':') { - break; - } p++; nonzero_groups--; if (x509_inet_pton_ipv4((const char *) p, From 64898a5e5caff176d9f70bdde4bacd3f7d9e9c0a Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 25 Feb 2026 08:40:28 +0100 Subject: [PATCH 07/66] Add warning in mbedtls_ssl_context_save/load documentation Signed-off-by: Ronald Cron --- include/mbedtls/ssl.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 6b98ad4584..d0114240b0 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -5138,6 +5138,27 @@ void mbedtls_ssl_free(mbedtls_ssl_context *ssl); * * \see mbedtls_ssl_context_load() * + * \warning The serialized data contains highly sensitive material, + * including the master secret from which the session's traffic + * keys are derived. + * + * The serialized data is not cryptographically protected. + * It is the responsibility of the user of the + * mbedtls_ssl_context_save() and + * mbedtls_ssl_context_load() APIs to ensure both its + * confidentiality and integrity while stored or transported. + * + * A breach of confidentiality could result in full compromise + * of the associated TLS session, including loss of + * confidentiality and integrity of past and future + * application data protected under that session. + * + * A breach of integrity may allow modification of the + * serialized data prior to restoration. As it represents + * trusted internal context, tampering could potentially result + * in arbitrary code execution or other severe compromise of + * the hosting process. + * \note The serialized data only contains the data that is * necessary to resume the connection: negotiated protocol * options, session identifier, keys, etc. @@ -5204,6 +5225,27 @@ int mbedtls_ssl_context_save(mbedtls_ssl_context *ssl, * more than one context would cause severe security failures * including but not limited to loss of confidentiality. * + * \warning The serialized data contains highly sensitive material, + * including the master secret from which the session's traffic + * keys are derived. + * + * The serialized data is not cryptographically protected. + * It is the responsibility of the user of the + * mbedtls_ssl_context_save() and + * mbedtls_ssl_context_load() APIs to ensure both its + * confidentiality and integrity while stored or transported. + * + * A breach of confidentiality could result in full compromise + * of the associated TLS session, including loss of + * confidentiality and integrity of past and future + * application data protected under that session. + * + * A breach of integrity may allow modification of the + * serialized data prior to restoration. As it represents + * trusted internal context, tampering could potentially result + * in arbitrary code execution or other severe compromise of + * the hosting process. + * * \note Before calling this function, the SSL context must be * prepared in one of the two following ways. The first way is * to take a context freshly initialised with From d5d7131eb5f0e9f66d17e65829fa3028d47e50a9 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 25 Feb 2026 09:04:08 +0100 Subject: [PATCH 08/66] Add warning in mbedtls_ssl_session_load/save documentation Signed-off-by: Ronald Cron --- include/mbedtls/ssl.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index d0114240b0..fac87623af 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3156,6 +3156,27 @@ int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session * On server, this can be used for alternative implementations * of session cache or session tickets. * + * \warning The serialized data contains highly sensitive material, + * including a resumption key (TLS 1.3) or the master secret + * (TLS 1.2) from which the session's traffic keys are derived. + * + * The serialized data is not cryptographically protected. + * It is the responsibility of the user of the + * mbedtls_ssl_session_save() and + * mbedtls_ssl_session_load() APIs to ensure both its + * confidentiality and integrity while stored or transported. + * + * A breach of confidentiality could result in full compromise + * of the associated TLS session, including loss of + * confidentiality and integrity of past and future + * application data protected under that session. + * + * A breach of integrity may allow modification of the + * serialized data prior to restoration. As it represents + * trusted internal context, tampering could potentially result + * in arbitrary code execution or other severe compromise of + * the hosting process. + * * \warning If a peer certificate chain is associated with the session, * the serialized state will only contain the peer's * end-entity certificate and the result of the chain @@ -3194,6 +3215,27 @@ int mbedtls_ssl_session_load(mbedtls_ssl_session *session, * * \see mbedtls_ssl_session_load() * + * \warning The serialized data contains highly sensitive material, + * including a resumption key (TLS 1.3) or the master secret + * (TLS 1.2) from which the session's traffic keys are derived. + * + * The serialized data is not cryptographically protected. + * It is the responsibility of the user of the + * mbedtls_ssl_session_save() and + * mbedtls_ssl_session_load() APIs to ensure both its + * confidentiality and integrity while stored or transported. + * + * A breach of confidentiality could result in full compromise + * of the associated TLS session, including loss of + * confidentiality and integrity of past and future + * application data protected under that session. + * + * A breach of integrity may allow modification of the + * serialized data prior to restoration. As it represents + * trusted internal context, tampering could potentially result + * in arbitrary code execution or other severe compromise of + * the hosting process. + * * \param session The session structure to be saved. * \param buf The buffer to write the serialized data to. It must be a * writeable buffer of at least \p buf_len bytes, or may be \c From 027ed1fef0fcd6450d8ba1c21e8fc86d40e6ee4b Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 25 Feb 2026 18:56:12 +0100 Subject: [PATCH 09/66] Reduce duplication between save/load documentations Signed-off-by: Ronald Cron --- include/mbedtls/ssl.h | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index fac87623af..1fa66f00c8 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3225,16 +3225,8 @@ int mbedtls_ssl_session_load(mbedtls_ssl_session *session, * mbedtls_ssl_session_load() APIs to ensure both its * confidentiality and integrity while stored or transported. * - * A breach of confidentiality could result in full compromise - * of the associated TLS session, including loss of - * confidentiality and integrity of past and future - * application data protected under that session. - * - * A breach of integrity may allow modification of the - * serialized data prior to restoration. As it represents - * trusted internal context, tampering could potentially result - * in arbitrary code execution or other severe compromise of - * the hosting process. + * See the mbedtls_ssl_session_load() documentation for + * additional information. * * \param session The session structure to be saved. * \param buf The buffer to write the serialized data to. It must be a @@ -5190,17 +5182,9 @@ void mbedtls_ssl_free(mbedtls_ssl_context *ssl); * mbedtls_ssl_context_load() APIs to ensure both its * confidentiality and integrity while stored or transported. * - * A breach of confidentiality could result in full compromise - * of the associated TLS session, including loss of - * confidentiality and integrity of past and future - * application data protected under that session. + * See the mbedtls_ssl_context_load() documentation for + * additional information. * - * A breach of integrity may allow modification of the - * serialized data prior to restoration. As it represents - * trusted internal context, tampering could potentially result - * in arbitrary code execution or other severe compromise of - * the hosting process. - * \note The serialized data only contains the data that is * necessary to resume the connection: negotiated protocol * options, session identifier, keys, etc. From 75b8b0f4d95d6c1520c7ec0016ecbc18cde95e8e Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 17 Feb 2026 10:46:42 +0100 Subject: [PATCH 10/66] Add unit test with TLS 1.2 nego after HRR Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 3 + tests/suites/test_suite_ssl.function | 154 +++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index b05de38509..be7aa90bf0 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3367,3 +3367,6 @@ ssl_tls_exporter_too_early:MBEDTLS_SSL_VERSION_TLS1_3:1:MBEDTLS_SSL_SERVER_CERTI TLS fatal alert getter ssl_get_alert_after_fatal + +TLS 1.3 - HRR then TLS 1.2 second ClientHello +tls13_hrr_then_tls12_second_client_hello diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 628a183853..d438f230c4 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -5981,3 +5981,157 @@ exit: USE_PSA_DONE(); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_HAS_TLS1_3_CHACHA20_POLY1305_SHA256: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_hrr_then_tls12_second_client_hello() +{ + int ret = -1; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + 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; + mbedtls_test_handshake_test_options server_options; + mbedtls_ssl_session saved_session; + uint16_t group_list[3] = { + MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, + MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, + MBEDTLS_SSL_IANA_TLS_GROUP_NONE + }; + const int tls12_ciphersuite_list[2] = { + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + 0 + }; + + mbedtls_test_init_handshake_options(&client_options); + mbedtls_test_init_handshake_options(&server_options); + mbedtls_ssl_session_init(&saved_session); + + PSA_INIT(); + + /* + * Run first handshake to get a ticket from the server. + */ + client_options.pk_alg = MBEDTLS_PK_ECDSA; + client_options.group_list = group_list; + client_options.cipher = "TLS1-3-CHACHA20-POLY1305-SHA256"; + server_options.pk_alg = MBEDTLS_PK_ECDSA; + server_options.group_list = group_list; + + ret = mbedtls_test_get_tls13_ticket(&client_options, &server_options, + &saved_session); + TEST_EQUAL(ret, 0); + + /* + * Prepare for handshake with the ticket. + */ + /* Remove the group SECP256R1 fron the list of groups supported by the + * server such that it sends an HRR in response to the ClientHello. + */ + server_options.group_list = group_list + 1; + + 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); + + /* + * Progress the handshake up to the point where the server has sent the + * HRR and the client as received and processed the server HRR but not + * written the second ClientHello in response to the HRR. + */ + 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( + &(client_ep.ssl), &(server_ep.ssl), + MBEDTLS_SSL_CLIENT_HELLO); + TEST_EQUAL(ret, 0); + + #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + /* If the compatibility mode is enabled, filter the dummy change_cipher_spec + * record sent by the server after the HRR. Otherwise, as we have switched + * the client to TLS 1.2 it would fail when reading this record. + */ + ret = mbedtls_ssl_read_record(&(client_ep.ssl), 0); + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_WANT_READ); + #endif + + /* + * Reset the client and tweak its configuration and context such as it + * resumes a TLS 1.2 session using an all-zeroes master secret as the + * server will when it receives the TLS 1.2 ClientHello. + * To be able to compute the Finished message the server will expect, we + * also initiate the handshake transcript by cloning the server current one. + * This transcript is the server's one after the call to + * `mbedtls_ssl_reset_transcript_for_hrr()`. It is computed only + * with the data of the first ClientHello thus a man-in-the-middle could + * compute it without having access to the server context. Here we use + * the server context just for convenience. + */ + + client_ep.ssl.tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + mbedtls_ssl_conf_min_tls_version((mbedtls_ssl_config *) client_ep.ssl.conf, + MBEDTLS_SSL_VERSION_TLS1_2); + mbedtls_ssl_conf_max_tls_version((mbedtls_ssl_config *) client_ep.ssl.conf, + MBEDTLS_SSL_VERSION_TLS1_2); + mbedtls_ssl_conf_ciphersuites((mbedtls_ssl_config *) client_ep.ssl.conf, + tls12_ciphersuite_list); + + ret = mbedtls_ssl_session_reset(&(client_ep.ssl)); + + client_ep.ssl.handshake->resume = 1; + client_ep.ssl.session_negotiate->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + memset(client_ep.ssl.session_negotiate->id, 0xa5, + sizeof(client_ep.ssl.session_negotiate->id)); + client_ep.ssl.session_negotiate->id_len = sizeof(client_ep.ssl.session_negotiate->id); + client_ep.ssl.session_negotiate->ciphersuite = + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256; + + status = psa_hash_abort(&client_ep.ssl.handshake->fin_sha256_psa); + TEST_EQUAL(status, PSA_SUCCESS); + + status = psa_hash_clone(&server_ep.ssl.handshake->fin_sha256_psa, + &client_ep.ssl.handshake->fin_sha256_psa); + TEST_EQUAL(status, PSA_SUCCESS); + + /* + * Restart and complete the handshake. + */ + + ret = mbedtls_test_move_handshake_to_state( + &(server_ep.ssl), &(client_ep.ssl), + MBEDTLS_SSL_HANDSHAKE_OVER); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + MBEDTLS_SSL_HANDSHAKE_OVER); + TEST_EQUAL(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_ssl_session_free(&saved_session); + PSA_DONE(); +} +/* END_CASE */ From f549fc7bdcc9b435236de5594bec0ed8e587988c Mon Sep 17 00:00:00 2001 From: David Horstmann Date: Thu, 26 Feb 2026 11:57:17 +0000 Subject: [PATCH 11/66] Fix null pointer dereference in string to names In mbedtls_x509_string_to_names() we were not checking for allocation failures. An allocation failure would lead to a memcpy() to a null pointer address. Fix this by checking the result of the call to mbedtls_calloc() and returning MBEDTLS_ERR_X509_ALLOC_FAILED in the error case. Signed-off-by: David Horstmann --- library/x509_create.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/x509_create.c b/library/x509_create.c index 370eb9b2e1..e424cbb47c 100644 --- a/library/x509_create.c +++ b/library/x509_create.c @@ -487,6 +487,9 @@ int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *nam } else { oid.len = strlen(attr_descr->oid); oid.p = mbedtls_calloc(1, oid.len); + if (oid.p == NULL) { + return MBEDTLS_ERR_X509_ALLOC_FAILED; + } memcpy(oid.p, attr_descr->oid, oid.len); numericoid = 0; } From 2acb9a2e7b4ed18aaa32d4ce65f90279e94455d5 Mon Sep 17 00:00:00 2001 From: David Horstmann Date: Thu, 26 Feb 2026 14:04:40 +0000 Subject: [PATCH 12/66] Add ChangeLog entry for NULL dereference fix Signed-off-by: David Horstmann --- ChangeLog.d/fix-null-pointer-dereference.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ChangeLog.d/fix-null-pointer-dereference.txt diff --git a/ChangeLog.d/fix-null-pointer-dereference.txt b/ChangeLog.d/fix-null-pointer-dereference.txt new file mode 100644 index 0000000000..1eb3c416a8 --- /dev/null +++ b/ChangeLog.d/fix-null-pointer-dereference.txt @@ -0,0 +1,4 @@ +Security + * Fix a NULL pointer dereference in mbedtls_x509_string_to_names() when + mbedtls_calloc() fails to allocate memory. This was caused by failing to + check whether mbedtls_calloc() returned NULL. From ed767bada9108fb7e15a1012f384a08e2cd637f2 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 19 Feb 2026 18:11:19 +0100 Subject: [PATCH 13/66] tls13: Do not negotiate TLS 1.2 after an HRR Signed-off-by: Ronald Cron --- library/ssl_tls13_server.c | 10 +++++- tests/suites/test_suite_ssl.function | 47 +++++++++------------------- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index 982e6f8c3b..b0e22230aa 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -1948,6 +1948,9 @@ static int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl) /* * Version 1.2 of the protocol has to be used for the handshake. + * If we have sent an HRR, then the second ClientHello is inconsistent + * with the first one and we abort the handshake with an `illegal_parameter` + * fatal alert. * If TLS 1.2 is not supported, abort the handshake. Otherwise, set the * ssl->keep_current_message flag for the ClientHello to be kept and parsed * as a TLS 1.2 ClientHello. We also change ssl->tls_version to @@ -1955,7 +1958,12 @@ static int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl) * will dispatch to the TLS 1.2 state machine. */ if (SSL_CLIENT_HELLO_TLS1_2 == parse_client_hello_ret) { - /* Check if server supports TLS 1.2 */ + if (ssl->handshake->hello_retry_request_flag) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Non compliant 2nd ClientHello, TLS 1.2 version")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } if (!mbedtls_ssl_conf_is_tls12_enabled(ssl->conf)) { MBEDTLS_SSL_DEBUG_MSG( 1, ("TLS 1.2 not supported.")); diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index d438f230c4..a42ff8b964 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -5982,17 +5982,18 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_HAS_TLS1_3_CHACHA20_POLY1305_SHA256: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 */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_HAS_TLS1_3_CHACHA20_POLY1305_SHA256: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:MBEDTLS_DEBUG_C */ void tls13_hrr_then_tls12_second_client_hello() { int ret = -1; - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 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; mbedtls_test_handshake_test_options server_options; mbedtls_ssl_session saved_session; + mbedtls_test_ssl_log_pattern server_pattern = + { "Non compliant 2nd ClientHello, TLS 1.2 version", 0 }; uint16_t group_list[3] = { MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, @@ -6034,6 +6035,8 @@ void tls13_hrr_then_tls12_second_client_hello() &client_options); TEST_EQUAL(ret, 0); + server_options.srv_log_fun = mbedtls_test_ssl_log_analyzer; + server_options.srv_log_obj = &server_pattern; ret = mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, &server_options); TEST_EQUAL(ret, 0); @@ -6075,16 +6078,8 @@ void tls13_hrr_then_tls12_second_client_hello() #endif /* - * Reset the client and tweak its configuration and context such as it - * resumes a TLS 1.2 session using an all-zeroes master secret as the - * server will when it receives the TLS 1.2 ClientHello. - * To be able to compute the Finished message the server will expect, we - * also initiate the handshake transcript by cloning the server current one. - * This transcript is the server's one after the call to - * `mbedtls_ssl_reset_transcript_for_hrr()`. It is computed only - * with the data of the first ClientHello thus a man-in-the-middle could - * compute it without having access to the server context. Here we use - * the server context just for convenience. + * Reset the client and force it to TLS 1.2 so that it sends a TLS 1.2 + * ClientHello. */ client_ep.ssl.tls_version = MBEDTLS_SSL_VERSION_TLS1_2; @@ -6097,34 +6092,20 @@ void tls13_hrr_then_tls12_second_client_hello() ret = mbedtls_ssl_session_reset(&(client_ep.ssl)); - client_ep.ssl.handshake->resume = 1; - client_ep.ssl.session_negotiate->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; - memset(client_ep.ssl.session_negotiate->id, 0xa5, - sizeof(client_ep.ssl.session_negotiate->id)); - client_ep.ssl.session_negotiate->id_len = sizeof(client_ep.ssl.session_negotiate->id); - client_ep.ssl.session_negotiate->ciphersuite = - MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256; - - status = psa_hash_abort(&client_ep.ssl.handshake->fin_sha256_psa); - TEST_EQUAL(status, PSA_SUCCESS); - - status = psa_hash_clone(&server_ep.ssl.handshake->fin_sha256_psa, - &client_ep.ssl.handshake->fin_sha256_psa); - TEST_EQUAL(status, PSA_SUCCESS); - /* - * Restart and complete the handshake. + * Restart and try to complete the handshake on server side which is + * expected to fail early. */ + mbedtls_debug_set_threshold(1); ret = mbedtls_test_move_handshake_to_state( &(server_ep.ssl), &(client_ep.ssl), MBEDTLS_SSL_HANDSHAKE_OVER); - TEST_EQUAL(ret, 0); + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); - ret = mbedtls_test_move_handshake_to_state( - &(client_ep.ssl), &(server_ep.ssl), - MBEDTLS_SSL_HANDSHAKE_OVER); - TEST_EQUAL(ret, 0); + TEST_EQUAL(server_pattern.counter, 1); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + TEST_EQUAL(server_ep.ssl.state, MBEDTLS_SSL_CLIENT_HELLO); exit: mbedtls_test_ssl_endpoint_free(&client_ep); From 8731587e41379e8ea5cd7ddda7e418059947ed7a Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 26 Feb 2026 12:06:19 +0100 Subject: [PATCH 14/66] tls13: Commit to session resume only when we actually do it Signed-off-by: Ronald Cron --- library/ssl_tls13_server.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index b0e22230aa..19aa0e6b32 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -1755,6 +1755,11 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl, return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } + if (handshake->key_exchange_mode != + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) { + hrr_required = (no_usable_share_for_key_agreement != 0); + } + #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) if (handshake->key_exchange_mode & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL) { @@ -1765,17 +1770,12 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl, ((unsigned) psk.ciphersuite_info->id), psk.ciphersuite_info->name)); - if (psk.type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) { + if (psk.type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION && (!hrr_required)) { handshake->resume = 1; } } #endif - if (handshake->key_exchange_mode != - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) { - hrr_required = (no_usable_share_for_key_agreement != 0); - } - mbedtls_ssl_optimize_checksum(ssl, handshake->ciphersuite_info); return hrr_required ? SSL_CLIENT_HELLO_HRR_REQUIRED : SSL_CLIENT_HELLO_OK; From 68c44a4a9772ff6fb17f5db573eb00ff9fb77dfe Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 5 Mar 2026 12:10:16 +0100 Subject: [PATCH 15/66] Update attribution to conform to contributor's request Signed-off-by: Gilles Peskine --- ChangeLog.d/inet_pton.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog.d/inet_pton.txt b/ChangeLog.d/inet_pton.txt index 526cd9be5f..22e6806556 100644 --- a/ChangeLog.d/inet_pton.txt +++ b/ChangeLog.d/inet_pton.txt @@ -1,4 +1,5 @@ Security * Fix a limited buffer underflow in x509_inet_pton_ipv6(). In rare cases (e.g. on platforms with memory protection when the overread crosses page - boundary) this could lead to DoS. Found and reported by Haruto Kimura. + boundary) this could lead to DoS. Found and reported by Haruto Kimura + (Stella). From ba5774387bd285f59b0d88750cd219259cdfcebe Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Sun, 8 Mar 2026 20:30:08 +0100 Subject: [PATCH 16/66] Update framework with psasim serialise supporting unsigned and crypto dir reorg prep Signed-off-by: Gilles Peskine --- framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework b/framework index e07b6643e8..9b92164c47 160000 --- a/framework +++ b/framework @@ -1 +1 @@ -Subproject commit e07b6643e8db5fe2fdc20be288b91a2194316862 +Subproject commit 9b92164c47fdaecb2600b417733507e2a105c3a5 From e051abd5e3830ae98014ed9b73903d3a07dd344b Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 10 Mar 2026 14:56:26 +0100 Subject: [PATCH 17/66] tls13_hrr_then_tls12_second_client_hello: Various improvements Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.function | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index a42ff8b964..b3c34aeac0 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6026,7 +6026,7 @@ void tls13_hrr_then_tls12_second_client_hello() /* * Prepare for handshake with the ticket. */ - /* Remove the group SECP256R1 fron the list of groups supported by the + /* Remove the group SECP256R1 from the list of groups supported by the * server such that it sends an HRR in response to the ClientHello. */ server_options.group_list = group_list + 1; @@ -6055,7 +6055,7 @@ void tls13_hrr_then_tls12_second_client_hello() /* * Progress the handshake up to the point where the server has sent the - * HRR and the client as received and processed the server HRR but not + * HRR and the client has received and processed the server HRR but not * written the second ClientHello in response to the HRR. */ ret = mbedtls_test_move_handshake_to_state( @@ -6083,14 +6083,12 @@ void tls13_hrr_then_tls12_second_client_hello() */ client_ep.ssl.tls_version = MBEDTLS_SSL_VERSION_TLS1_2; - mbedtls_ssl_conf_min_tls_version((mbedtls_ssl_config *) client_ep.ssl.conf, - MBEDTLS_SSL_VERSION_TLS1_2); - mbedtls_ssl_conf_max_tls_version((mbedtls_ssl_config *) client_ep.ssl.conf, - MBEDTLS_SSL_VERSION_TLS1_2); - mbedtls_ssl_conf_ciphersuites((mbedtls_ssl_config *) client_ep.ssl.conf, - tls12_ciphersuite_list); + mbedtls_ssl_conf_min_tls_version(&client_ep.conf, MBEDTLS_SSL_VERSION_TLS1_2); + mbedtls_ssl_conf_max_tls_version(&client_ep.conf, MBEDTLS_SSL_VERSION_TLS1_2); + mbedtls_ssl_conf_ciphersuites(&client_ep.conf, tls12_ciphersuite_list); ret = mbedtls_ssl_session_reset(&(client_ep.ssl)); + TEST_EQUAL(ret, 0); /* * Restart and try to complete the handshake on server side which is @@ -6113,6 +6111,7 @@ exit: mbedtls_test_free_handshake_options(&client_options); mbedtls_test_free_handshake_options(&server_options); mbedtls_ssl_session_free(&saved_session); + mbedtls_debug_set_threshold(0); PSA_DONE(); } /* END_CASE */ From 139ac457ab92d56488d3619a7728d57830b4ebf0 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 10 Mar 2026 15:40:00 +0100 Subject: [PATCH 18/66] tls13_hrr_then_tls12_second_client_hello: Improve some comments Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.function | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index b3c34aeac0..c039b95c26 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6027,7 +6027,8 @@ void tls13_hrr_then_tls12_second_client_hello() * Prepare for handshake with the ticket. */ /* Remove the group SECP256R1 from the list of groups supported by the - * server such that it sends an HRR in response to the ClientHello. + * server. Since it is the client's preferred group, the client will + * send a key share only for SECP256R1, forcing the server to send a HRR. */ server_options.group_list = group_list + 1; @@ -6078,10 +6079,12 @@ void tls13_hrr_then_tls12_second_client_hello() #endif /* - * Reset the client and force it to TLS 1.2 so that it sends a TLS 1.2 - * ClientHello. + * The client has just received the server's HRR and is expected to send a + * second ClientHello. Instead of sending a compliant second TLS 1.3 + * ClientHello, we want it to send a TLS 1.2-only ClientHello. To achieve + * this, we reset the client with a TLS 1.2-only configuration before + * resuming the handshake with the server. */ - client_ep.ssl.tls_version = MBEDTLS_SSL_VERSION_TLS1_2; mbedtls_ssl_conf_min_tls_version(&client_ep.conf, MBEDTLS_SSL_VERSION_TLS1_2); mbedtls_ssl_conf_max_tls_version(&client_ep.conf, MBEDTLS_SSL_VERSION_TLS1_2); From 759895e7df1b108ed640f6f5b9527bf10cb06e66 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 10 Mar 2026 16:16:19 +0100 Subject: [PATCH 19/66] tls13_hrr_then_tls12_second_client_hello: Improve client and server state checks 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 c039b95c26..8c57ec1b6e 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -6063,11 +6063,13 @@ void tls13_hrr_then_tls12_second_client_hello() &(server_ep.ssl), &(client_ep.ssl), MBEDTLS_SSL_HELLO_RETRY_REQUEST); TEST_EQUAL(ret, 0); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); ret = mbedtls_test_move_handshake_to_state( &(client_ep.ssl), &(server_ep.ssl), MBEDTLS_SSL_CLIENT_HELLO); TEST_EQUAL(ret, 0); + TEST_EQUAL(server_ep.ssl.state, MBEDTLS_SSL_CLIENT_HELLO); #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) /* If the compatibility mode is enabled, filter the dummy change_cipher_spec From 622b69d1d059d5e5b6dd5792cf8402f22908baab Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 10 Mar 2026 17:01:50 +0100 Subject: [PATCH 20/66] Add change log Signed-off-by: Ronald Cron --- ChangeLog.d/tls12-2nd-client-hello.txt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 ChangeLog.d/tls12-2nd-client-hello.txt diff --git a/ChangeLog.d/tls12-2nd-client-hello.txt b/ChangeLog.d/tls12-2nd-client-hello.txt new file mode 100644 index 0000000000..7513e0b945 --- /dev/null +++ b/ChangeLog.d/tls12-2nd-client-hello.txt @@ -0,0 +1,9 @@ +Security + * Fixed an issue in TLS 1.3 server handling of the second ClientHello, after + sending a HelloRetryRequest message. A man-in-the-middle attacker could + force a TLS 1.3 session resumption using a ticket to fall back to an + unintended TLS 1.2 session resumption with an all-zero master secret. + This could result in client authentication being bypassed and allow client + impersonation. + Found and reported by Jaehun Lee, Pohang University of Science and + Technology (POSTECH). From f51e72ab2da9bbdb619ce6e0f8a2958d0e7f220b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 11 Mar 2026 12:35:30 +0100 Subject: [PATCH 21/66] Update tf-psa-crypto to development Signed-off-by: Gilles Peskine --- tf-psa-crypto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tf-psa-crypto b/tf-psa-crypto index 293cfe5ece..125474d4e0 160000 --- a/tf-psa-crypto +++ b/tf-psa-crypto @@ -1 +1 @@ -Subproject commit 293cfe5eceed98a2ee75d5241a78657b466750c7 +Subproject commit 125474d4e05965a6dfe2af350b5462ce62bed4cd From d7b85b76a66354fedab299c27e6a8da9e26e08fe Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 23 Jan 2026 16:22:50 +0000 Subject: [PATCH 22/66] sig_algs: fix typo in client's sig_algs check This bug caused the client accepting sig_algs used by the server that it explicitly wanted to disallow. Signed-off-by: Janos Follath --- library/ssl_tls12_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c index ebcc0d56bb..b03859a8d6 100644 --- a/library/ssl_tls12_client.c +++ b/library/ssl_tls12_client.c @@ -1910,8 +1910,8 @@ start_processing: MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); sig_alg = MBEDTLS_GET_UINT16_BE(p, 0); if (mbedtls_ssl_get_pk_sigalg_and_md_alg_from_sig_alg( - sig_alg, &pk_alg, &md_alg) != 0 && - !mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg) && + sig_alg, &pk_alg, &md_alg) != 0 || + !mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg) || !mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); From 01f6ccf020485f6c29d769226c5cdd12340fb315 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 18 Feb 2026 19:39:56 +0000 Subject: [PATCH 23/66] Fix root cert prerequisites This root certificate uses SECP-384 and if we don't have it in the build, the parsing already fails even if we don't try to use it, there is no reason to have it in the build without the SECP-384. Signed-off-by: Janos Follath --- tests/src/certs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/certs.c b/tests/src/certs.c index c45f0628c0..3ec99cd516 100644 --- a/tests/src/certs.c +++ b/tests/src/certs.c @@ -443,7 +443,7 @@ const unsigned char *mbedtls_test_cas_der[] = { mbedtls_test_ca_crt_rsa_sha1_der, #endif /* PSA_WANT_ALG_SHA_1 */ #endif /* MBEDTLS_RSA_C */ -#if defined(PSA_HAVE_ALG_SOME_ECDSA) +#if defined(PSA_HAVE_ALG_SOME_ECDSA) && defined(PSA_WANT_ECC_SECP_R1_384) mbedtls_test_ca_crt_ec_der, #endif /* PSA_HAVE_ALG_SOME_ECDSA */ NULL From bab37f69d99cd14d64799dc6c4749d83a062e6d9 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 18 Feb 2026 14:25:41 +0000 Subject: [PATCH 24/66] Fix mbedtls_test_free_handshake_options We usually follow the pattern that a zero-initialised struct is safe to free. This wasn't the case here. Signed-off-by: Janos Follath --- tests/src/test_helpers/ssl_helpers.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c index 83dac17419..db29413de6 100644 --- a/tests/src/test_helpers/ssl_helpers.c +++ b/tests/src/test_helpers/ssl_helpers.c @@ -99,8 +99,10 @@ void mbedtls_test_free_handshake_options( mbedtls_test_handshake_test_options *opts) { #if defined(MBEDTLS_SSL_CACHE_C) - mbedtls_ssl_cache_free(opts->cache); - mbedtls_free(opts->cache); + if (opts->cache != NULL) { + mbedtls_ssl_cache_free(opts->cache); + mbedtls_free(opts->cache); + } #else (void) opts; #endif From 475ac34e1fac035792d0a49c514d34f993f368bc Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 23 Jan 2026 16:18:01 +0000 Subject: [PATCH 25/66] sig_algs: Add non-regression test Signed-off-by: Janos Follath --- tests/include/test/ssl_helpers.h | 28 +++++++ tests/suites/test_suite_ssl.data | 8 ++ tests/suites/test_suite_ssl.function | 114 +++++++++++++++++++++++++++ 3 files changed, 150 insertions(+) diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h index d019c5065e..70e4bbaae1 100644 --- a/tests/include/test/ssl_helpers.h +++ b/tests/include/test/ssl_helpers.h @@ -68,12 +68,40 @@ #define MBEDTLS_CAN_HANDLE_RSA_TEST_KEY #endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + defined(PSA_WANT_ECC_SECP_R1_384) && \ + defined(PSA_WANT_ALG_SHA_384) +#define MBEDTLS_CAN_HANDLE_ECDSA_TEST_KEY +#endif + +#if defined(PSA_WANT_ECC_MONTGOMERY_255) || \ + defined(PSA_WANT_ECC_SECP_R1_256) || \ + defined(PSA_WANT_ECC_SECP_R1_384) || \ + defined(PSA_WANT_ECC_MONTGOMERY_448) || \ + defined(PSA_WANT_ECC_SECP_R1_521) || \ + defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) || \ + defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) || \ + defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) +#define MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP +#endif + #if defined(PSA_WANT_ALG_GCM) || \ defined(PSA_WANT_ALG_CCM) || \ defined(PSA_WANT_ALG_CHACHA20_POLY1305) #define MBEDTLS_TEST_HAS_AEAD_ALG #endif +/* + * To use the test keys we need PSA_WANT_ALG_SHA_256. Some test cases need an additional hash that + * can be used in modern TLS, but it doesn't matter which one. + */ +#if defined(PSA_WANT_ALG_SHA_512) || \ + defined(PSA_WANT_ALG_SHA_384) || \ + defined(PSA_WANT_ALG_SHA_224) || \ + defined(PSA_WANT_ALG_SHA_1) +#define MBEDTLS_TEST_HAS_ADDITIONAL_HASH +#endif + enum { #define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \ tls13_label_ ## name, diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 99856e304b..da9a5e738e 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3530,3 +3530,11 @@ ssl_get_alert_after_fatal TLS 1.3 - HRR then TLS 1.2 second ClientHello tls13_hrr_then_tls12_second_client_hello + +Negative Test: Server using sig_alg not offered by the client #1 +depends_on:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY:PSA_WANT_ALG_SHA_256 +send_invalid_sig_alg:MBEDTLS_SSL_SIG_RSA:MBEDTLS_SSL_HASH_SHA256:MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER + +Negative Test: Server using sig_alg not offered by the client #2 +depends_on:MBEDTLS_CAN_HANDLE_ECDSA_TEST_KEY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_512 +send_invalid_sig_alg:MBEDTLS_SSL_SIG_ECDSA:MBEDTLS_SSL_HASH_SHA512:MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index ca59346cc8..b447773f12 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -5725,6 +5725,120 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_ALG_SHA_256:MBEDTLS_TEST_HAS_ADDITIONAL_HASH:MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP*/ +void send_invalid_sig_alg(int sig, int hash, int expected_ret) +{ + // This is a test about the client behaviour in case it receives a key exchange signed with a + // sig_alg it didn't specify in the client hello. The input specifies a target_sig_alg, which we + // make sure that the client does not offer but the server does. Then we make the server beleive + // that target_sig_alg is the only one the client offered. + + // Remark: We need an additional hash algorithm offered, because if we don't have it, the server + // realises too early that there is no common ground and we don't get the chance to manipulate + // it. This is why we need MBEDTLS_TEST_HAS_ADDITIONAL_HASH in the requirements. + + enum { BUFFSIZE = 16384 }; + uint16_t *client_sig_algs = NULL; + mbedtls_test_ssl_endpoint server, client; + memset(&server, 0, sizeof(server)); + memset(&client, 0, sizeof(client)); + mbedtls_test_handshake_test_options options; + memset(&options, 0, sizeof(options)); + + uint16_t target_sig_alg = ((hash << 8) | sig); + + mbedtls_test_init_handshake_options(&options); + + // Make sure the server has credentals for target_sig_alg + if (sig == MBEDTLS_SSL_SIG_ECDSA) { + options.pk_alg = MBEDTLS_PK_ECDSA; + } else { + options.pk_alg = MBEDTLS_PK_RSA; + } + + // Force a ciphersuite where target_sig_alg is relevant + if (sig == MBEDTLS_SSL_SIG_ECDSA) { + options.cipher = "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256"; + } else { + options.cipher = "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256"; + } + + // Force TLS 1.2 as this test is a non-regression test for a bug in TLS 1.2 client and TLS 1.3 + // behaviour in this regard is substantially different. + options.client_max_version = MBEDTLS_SSL_VERSION_TLS1_2; + options.server_max_version = MBEDTLS_SSL_VERSION_TLS1_2; + + // Add loggers for easier debugging - we are not looking for any patterns. + // To turn on debug output, uncomment the threshold line and set the macro in + // the definition of mbedtls_test_ssl_log_analyzer(). +#if defined(MBEDTLS_DEBUG_C) + options.srv_log_obj = NULL; + options.srv_log_fun = mbedtls_test_ssl_log_analyzer; + options.cli_log_obj = NULL; + options.cli_log_fun = mbedtls_test_ssl_log_analyzer; + mbedtls_debug_set_threshold(3); +#endif + + int ret = -1; + + PSA_INIT(); + + ret = mbedtls_test_ssl_endpoint_init_conf(&client, MBEDTLS_SSL_IS_CLIENT, &options); + TEST_EQUAL(ret, 0); + + // Remove the target signature algorithm from the client's list + size_t client_sig_algs_len = 0; + while (client.conf.sig_algs[client_sig_algs_len++] != MBEDTLS_TLS1_3_SIG_NONE) { + ; + } + client_sig_algs_len--; + + TEST_CALLOC(client_sig_algs, client_sig_algs_len); + size_t j = 0; + for (size_t i = 0; client.conf.sig_algs[i] != MBEDTLS_TLS1_3_SIG_NONE; i++) { + if (client.conf.sig_algs[i] != target_sig_alg) { + client_sig_algs[j++] = client.conf.sig_algs[i]; + } + } + TEST_ASSERT(j < client_sig_algs_len); + client_sig_algs[j] = MBEDTLS_TLS1_3_SIG_NONE; + client.conf.sig_algs = client_sig_algs; + + ret = mbedtls_test_ssl_endpoint_init_ssl(&client, &options); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_ssl_endpoint_init(&server, MBEDTLS_SSL_IS_SERVER, + &options); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_mock_socket_connect(&server.socket, &client.socket, + BUFFSIZE); + TEST_EQUAL(ret, 0); + + // Move the connection to the point before the server sending the key exchange message + ret = mbedtls_test_move_handshake_to_state(&server.ssl, &client.ssl, + MBEDTLS_SSL_SERVER_KEY_EXCHANGE); + TEST_EQUAL(ret, 0); + + // Make the server beleive that the only sig_alg the client accepts is target_sig_alg + server.ssl.handshake->received_sig_algs[0] = target_sig_alg; + server.ssl.handshake->received_sig_algs[1] = MBEDTLS_TLS1_3_SIG_NONE; + + // Move the connection to a state where it is certain that the client has parsed the server key + // exchange + ret = mbedtls_test_move_handshake_to_state(&client.ssl, &server.ssl, + MBEDTLS_SSL_CERTIFICATE_REQUEST); + TEST_EQUAL(ret, expected_ret); + +exit: + mbedtls_test_free_handshake_options(&options); + mbedtls_test_ssl_endpoint_free(&server); + mbedtls_test_ssl_endpoint_free(&client); + mbedtls_free(client_sig_algs); + PSA_DONE(); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_SSL_KEYING_MATERIAL_EXPORT:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256 */ void ssl_tls_exporter_consistent_result(int proto, int exported_key_length, int use_context) { From f68d402029c6fb61a73b63ba5b977ec9a8a52270 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 23 Jan 2026 16:31:53 +0000 Subject: [PATCH 26/66] sig_algs: add ChangeLog Signed-off-by: Janos Follath --- ChangeLog.d/sig_algs_check.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 ChangeLog.d/sig_algs_check.txt diff --git a/ChangeLog.d/sig_algs_check.txt b/ChangeLog.d/sig_algs_check.txt new file mode 100644 index 0000000000..b0aed6dfd3 --- /dev/null +++ b/ChangeLog.d/sig_algs_check.txt @@ -0,0 +1,5 @@ +Security + * Fix a bug in the TLS 1.2 client's signature algorithm check, which caused + the client to accept server key exchange messages signed with a signature + algorithm explicitly disallowed by the client. Found and reported by + EFR-GmbH and M. Heuft of Security-Research-Consulting GmbH. CVE-2026-25834 From e8894974cbc8dc98b4ddeea0f645ce0e19ac84f5 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 10 Mar 2026 11:51:30 +0000 Subject: [PATCH 27/66] Reintroduce ssl_parse_signature_algorithm The logic was easier to follow before 693a47a, which removed the ssl_parse_signature_algorithm function and introduced the bug being fixed in this PR. When validating multiple conditions, it's easier to read, easier to debug and, as we can see, easier to get right if you validate them separately. Signed-off-by: Janos Follath --- library/ssl_tls12_client.c | 74 +++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c index b03859a8d6..8d26562c1e 100644 --- a/library/ssl_tls12_client.c +++ b/library/ssl_tls12_client.c @@ -1732,6 +1732,71 @@ static int ssl_parse_server_psk_hint(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end, + mbedtls_md_type_t *md_alg, + mbedtls_pk_sigalg_t *pk_alg) +{ + *md_alg = MBEDTLS_MD_NONE; + *pk_alg = MBEDTLS_PK_SIGALG_NONE; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(*p, end, 2); + uint16_t sig_alg = MBEDTLS_GET_UINT16_BE(*p, 0); + + if (mbedtls_ssl_get_pk_sigalg_and_md_alg_from_sig_alg(sig_alg, pk_alg, md_alg) != 0) { + /* + * Check hash algorithm + */ + if (*md_alg == MBEDTLS_MD_NONE) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported HashAlgorithm %d", (*p)[0])); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* + * Check signature algorithm + */ + if (*pk_alg == MBEDTLS_PK_SIGALG_NONE) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported SignatureAlgorithm %d", (*p)[1])); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* + * This shouldn't happen, but be robust. + */ + MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported value in SigAlg extension %d", sig_alg)); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* + * mbedtls_ssl_get_pk_sigalg_and_md_alg_from_sig_alg() understands sig_alg code points across + * TLS versions. Make sure that the received sig_alg extension is valid in TLS 1.2. + */ + if (!mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg)) { + MBEDTLS_SSL_DEBUG_MSG( 1, ("Server used unsupported value in SigAlg extension %d", sig_alg)); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* + * Check if the signature algorithm is acceptable + */ + if(!mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Server used SigAlg value %d that was not offered", sig_alg)); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("Server used SignatureAlgorithm %d", (*p)[1])); + MBEDTLS_SSL_DEBUG_MSG(2, ("Server used HashAlgorithm %d", (*p)[0])); + *p += 2; + + return 0; +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) { @@ -1889,7 +1954,6 @@ start_processing: unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); size_t params_len = (size_t) (p - params); void *rs_ctx = NULL; - uint16_t sig_alg; mbedtls_pk_context *peer_pk; @@ -1907,12 +1971,7 @@ start_processing: /* * Handle the digitally-signed structure */ - MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); - sig_alg = MBEDTLS_GET_UINT16_BE(p, 0); - if (mbedtls_ssl_get_pk_sigalg_and_md_alg_from_sig_alg( - sig_alg, &pk_alg, &md_alg) != 0 || - !mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg) || - !mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg)) { + if (ssl_parse_signature_algorithm(ssl, &p, end, &md_alg, &pk_alg) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( @@ -1921,7 +1980,6 @@ start_processing: MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } - p += 2; psa_hash_alg = mbedtls_md_psa_alg_from_type(md_alg); if (!mbedtls_pk_can_do_psa(peer_pk, From 25f971db8750fc87f19f9981719b35b32040b74f Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 10 Mar 2026 14:02:38 +0000 Subject: [PATCH 28/66] Fix the MBEDTLS_TEST_HAS_ADDITIONAL_HASH macro It should require a hash that is configured in TLS 1.2 SSL contexts by default. Signed-off-by: Janos Follath --- tests/include/test/ssl_helpers.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h index 70e4bbaae1..2744016fa8 100644 --- a/tests/include/test/ssl_helpers.h +++ b/tests/include/test/ssl_helpers.h @@ -93,12 +93,10 @@ /* * To use the test keys we need PSA_WANT_ALG_SHA_256. Some test cases need an additional hash that - * can be used in modern TLS, but it doesn't matter which one. + * is configured by default (see mbedtls_ssl_config_defaults()), but it doesn't matter which one. */ #if defined(PSA_WANT_ALG_SHA_512) || \ - defined(PSA_WANT_ALG_SHA_384) || \ - defined(PSA_WANT_ALG_SHA_224) || \ - defined(PSA_WANT_ALG_SHA_1) + defined(PSA_WANT_ALG_SHA_384) #define MBEDTLS_TEST_HAS_ADDITIONAL_HASH #endif From 971309addfdb4f026fa86561803d732d09cd18fa Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 10 Mar 2026 14:17:14 +0000 Subject: [PATCH 29/66] Use API function to set sig_alg config in test Signed-off-by: Janos Follath --- 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 b447773f12..90580b393d 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -5802,7 +5802,7 @@ void send_invalid_sig_alg(int sig, int hash, int expected_ret) } TEST_ASSERT(j < client_sig_algs_len); client_sig_algs[j] = MBEDTLS_TLS1_3_SIG_NONE; - client.conf.sig_algs = client_sig_algs; + mbedtls_ssl_conf_sig_algs(&client.conf, client_sig_algs); ret = mbedtls_test_ssl_endpoint_init_ssl(&client, &options); TEST_EQUAL(ret, 0); From 305aef1ad7b603f54152ee26874263b37daaf264 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 10 Mar 2026 14:44:02 +0000 Subject: [PATCH 30/66] send_invalid_sig_alg: check logs There are other issues that can fail with the same error code. Make sure that the handshake fails exactly the way we want it to fail by analysing the client logs. Signed-off-by: Janos Follath --- tests/suites/test_suite_ssl.function | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 90580b393d..4a2ca71835 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -5768,14 +5768,17 @@ void send_invalid_sig_alg(int sig, int hash, int expected_ret) options.client_max_version = MBEDTLS_SSL_VERSION_TLS1_2; options.server_max_version = MBEDTLS_SSL_VERSION_TLS1_2; - // Add loggers for easier debugging - we are not looking for any patterns. - // To turn on debug output, uncomment the threshold line and set the macro in - // the definition of mbedtls_test_ssl_log_analyzer(). + mbedtls_test_ssl_log_pattern cli_pattern; + cli_pattern.pattern = "that was not offered"; + cli_pattern.counter = 0; + options.cli_log_obj = &cli_pattern; + options.cli_log_fun = mbedtls_test_ssl_log_analyzer; #if defined(MBEDTLS_DEBUG_C) + // Add loggers for easier debugging - we are not looking for any patterns in the server logs. + // To turn on debug output, uncomment the threshold line and set the macro in the definition + // of mbedtls_test_ssl_log_analyzer(). options.srv_log_obj = NULL; options.srv_log_fun = mbedtls_test_ssl_log_analyzer; - options.cli_log_obj = NULL; - options.cli_log_fun = mbedtls_test_ssl_log_analyzer; mbedtls_debug_set_threshold(3); #endif @@ -5829,8 +5832,12 @@ void send_invalid_sig_alg(int sig, int hash, int expected_ret) ret = mbedtls_test_move_handshake_to_state(&client.ssl, &server.ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST); TEST_EQUAL(ret, expected_ret); + TEST_EQUAL(cli_pattern.counter, 1); exit: +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold(0); +#endif mbedtls_test_free_handshake_options(&options); mbedtls_test_ssl_endpoint_free(&server); mbedtls_test_ssl_endpoint_free(&client); From 6cb0d86f16b4a0728bbceaafc9adc5d51769a074 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 10 Mar 2026 14:58:27 +0000 Subject: [PATCH 31/66] Fix some compile time guards Signed-off-by: Janos Follath --- tests/src/certs.c | 2 +- tests/suites/test_suite_ssl.data | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/src/certs.c b/tests/src/certs.c index 3ec99cd516..b9ba13b7ee 100644 --- a/tests/src/certs.c +++ b/tests/src/certs.c @@ -458,7 +458,7 @@ const size_t mbedtls_test_cas_der_len[] = { sizeof(mbedtls_test_ca_crt_rsa_sha1_der), #endif /* PSA_WANT_ALG_SHA_1 */ #endif /* MBEDTLS_RSA_C */ -#if defined(PSA_HAVE_ALG_SOME_ECDSA) +#if defined(PSA_HAVE_ALG_SOME_ECDSA) && defined(PSA_WANT_ECC_SECP_R1_384) sizeof(mbedtls_test_ca_crt_ec_der), #endif /* PSA_HAVE_ALG_SOME_ECDSA */ 0 diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index da9a5e738e..7a6999687f 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3536,5 +3536,5 @@ depends_on:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY:PSA_WANT_ALG_SHA_256 send_invalid_sig_alg:MBEDTLS_SSL_SIG_RSA:MBEDTLS_SSL_HASH_SHA256:MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER Negative Test: Server using sig_alg not offered by the client #2 -depends_on:MBEDTLS_CAN_HANDLE_ECDSA_TEST_KEY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_512 +depends_on:MBEDTLS_CAN_HANDLE_ECDSA_TEST_KEY:PSA_WANT_ALG_SHA_512 send_invalid_sig_alg:MBEDTLS_SSL_SIG_ECDSA:MBEDTLS_SSL_HASH_SHA512:MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER From c139e44935a7086cef5697ba9580cadc92a8e125 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 10 Mar 2026 15:01:11 +0000 Subject: [PATCH 32/66] Fix typos Signed-off-by: Janos Follath --- tests/suites/test_suite_ssl.function | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 4a2ca71835..3149668e99 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -5749,7 +5749,7 @@ void send_invalid_sig_alg(int sig, int hash, int expected_ret) mbedtls_test_init_handshake_options(&options); - // Make sure the server has credentals for target_sig_alg + // Make sure the server has credentials for target_sig_alg if (sig == MBEDTLS_SSL_SIG_ECDSA) { options.pk_alg = MBEDTLS_PK_ECDSA; } else { @@ -5823,7 +5823,7 @@ void send_invalid_sig_alg(int sig, int hash, int expected_ret) MBEDTLS_SSL_SERVER_KEY_EXCHANGE); TEST_EQUAL(ret, 0); - // Make the server beleive that the only sig_alg the client accepts is target_sig_alg + // Make the server believe that the only sig_alg the client accepts is target_sig_alg server.ssl.handshake->received_sig_algs[0] = target_sig_alg; server.ssl.handshake->received_sig_algs[1] = MBEDTLS_TLS1_3_SIG_NONE; From 6394676a741b4b7fc42a25509a26d9b12eafa50a Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 11 Mar 2026 09:21:32 +0000 Subject: [PATCH 33/66] Fix test case dependency Signed-off-by: Janos Follath --- tests/suites/test_suite_ssl.function | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 3149668e99..c00acd755b 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -5725,7 +5725,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_ALG_SHA_256:MBEDTLS_TEST_HAS_ADDITIONAL_HASH:MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP*/ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_ALG_SHA_256:MBEDTLS_TEST_HAS_ADDITIONAL_HASH:MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP:MBEDTLS_DEBUG_C*/ void send_invalid_sig_alg(int sig, int hash, int expected_ret) { // This is a test about the client behaviour in case it receives a key exchange signed with a @@ -5773,14 +5773,12 @@ void send_invalid_sig_alg(int sig, int hash, int expected_ret) cli_pattern.counter = 0; options.cli_log_obj = &cli_pattern; options.cli_log_fun = mbedtls_test_ssl_log_analyzer; -#if defined(MBEDTLS_DEBUG_C) // Add loggers for easier debugging - we are not looking for any patterns in the server logs. // To turn on debug output, uncomment the threshold line and set the macro in the definition // of mbedtls_test_ssl_log_analyzer(). options.srv_log_obj = NULL; options.srv_log_fun = mbedtls_test_ssl_log_analyzer; mbedtls_debug_set_threshold(3); -#endif int ret = -1; @@ -5835,9 +5833,7 @@ void send_invalid_sig_alg(int sig, int hash, int expected_ret) TEST_EQUAL(cli_pattern.counter, 1); exit: -#if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold(0); -#endif mbedtls_test_free_handshake_options(&options); mbedtls_test_ssl_endpoint_free(&server); mbedtls_test_ssl_endpoint_free(&client); From 75092c82620cb6d9ecda5dbda32ca3bda80b435f Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 11 Mar 2026 09:57:04 +0000 Subject: [PATCH 34/66] send_invalid_sig_alg: add baseline test Add a test case with a successful handshake for each test case that causes the desired handshake failure, with minimal differences between the two. The reason is to have more assurance that the handshake is failing for the desired reason (as opposed to not having done something correctly in the test code). Signed-off-by: Janos Follath --- tests/suites/test_suite_ssl.data | 12 ++++++++++-- tests/suites/test_suite_ssl.function | 13 +++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 7a6999687f..15b986a805 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3531,10 +3531,18 @@ ssl_get_alert_after_fatal TLS 1.3 - HRR then TLS 1.2 second ClientHello tls13_hrr_then_tls12_second_client_hello -Negative Test: Server using sig_alg not offered by the client #1 +Baseline for: Server using sig_alg not offered by the client - RSA with SHA256 +depends_on:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY:PSA_WANT_ALG_SHA_256 +send_invalid_sig_alg:MBEDTLS_SSL_SIG_RSA:MBEDTLS_SSL_HASH_SHA256:0 + +Negative Test: Server using sig_alg not offered by the client - RSA with SHA256 depends_on:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY:PSA_WANT_ALG_SHA_256 send_invalid_sig_alg:MBEDTLS_SSL_SIG_RSA:MBEDTLS_SSL_HASH_SHA256:MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER -Negative Test: Server using sig_alg not offered by the client #2 +Baseline for: Server using sig_alg not offered by the client - ECDSA with SHA512 +depends_on:MBEDTLS_CAN_HANDLE_ECDSA_TEST_KEY:PSA_WANT_ALG_SHA_512 +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:PSA_WANT_ALG_SHA_512 send_invalid_sig_alg:MBEDTLS_SSL_SIG_ECDSA:MBEDTLS_SSL_HASH_SHA512:MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index c00acd755b..6d37b908c4 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -5821,16 +5821,21 @@ void send_invalid_sig_alg(int sig, int hash, int expected_ret) MBEDTLS_SSL_SERVER_KEY_EXCHANGE); TEST_EQUAL(ret, 0); - // Make the server believe that the only sig_alg the client accepts is target_sig_alg - server.ssl.handshake->received_sig_algs[0] = target_sig_alg; - server.ssl.handshake->received_sig_algs[1] = MBEDTLS_TLS1_3_SIG_NONE; + if (expected_ret != 0) { + // Make the server believe that the only sig_alg the client accepts is target_sig_alg + server.ssl.handshake->received_sig_algs[0] = target_sig_alg; + server.ssl.handshake->received_sig_algs[1] = MBEDTLS_TLS1_3_SIG_NONE; + } // Move the connection to a state where it is certain that the client has parsed the server key // exchange ret = mbedtls_test_move_handshake_to_state(&client.ssl, &server.ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST); TEST_EQUAL(ret, expected_ret); - TEST_EQUAL(cli_pattern.counter, 1); + + if (expected_ret != 0) { + TEST_EQUAL(cli_pattern.counter, 1); + } exit: mbedtls_debug_set_threshold(0); From 3d0235328123a77321a7ec90f94bf9652aa11f29 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 11 Mar 2026 11:35:44 +0000 Subject: [PATCH 35/66] Fix code style Signed-off-by: Janos Follath --- library/ssl_tls12_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c index 8d26562c1e..4673827557 100644 --- a/library/ssl_tls12_client.c +++ b/library/ssl_tls12_client.c @@ -1776,14 +1776,14 @@ static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, * TLS versions. Make sure that the received sig_alg extension is valid in TLS 1.2. */ if (!mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg)) { - MBEDTLS_SSL_DEBUG_MSG( 1, ("Server used unsupported value in SigAlg extension %d", sig_alg)); + MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported value in SigAlg extension %d", sig_alg)); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* * Check if the signature algorithm is acceptable */ - if(!mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)) { + if (!mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("Server used SigAlg value %d that was not offered", sig_alg)); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } From 8d21dbf8e899f5ae501c2b6bc23550a21bac685f Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 11 Mar 2026 16:09:37 +0000 Subject: [PATCH 36/66] Fix dependencies The unit test framework always loads the client key as well, which requires a different curve and a hash than the server key. Signed-off-by: Janos Follath --- tests/include/test/ssl_helpers.h | 6 ++++++ tests/suites/test_suite_ssl.data | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h index 2744016fa8..a653c9643e 100644 --- a/tests/include/test/ssl_helpers.h +++ b/tests/include/test/ssl_helpers.h @@ -74,6 +74,12 @@ #define MBEDTLS_CAN_HANDLE_ECDSA_TEST_KEY #endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + defined(PSA_WANT_ECC_SECP_R1_256) && \ + defined(PSA_WANT_ALG_SHA_256) +#define MBEDTLS_CAN_HANDLE_ECDSA_CLIENT_TEST_KEY +#endif + #if defined(PSA_WANT_ECC_MONTGOMERY_255) || \ defined(PSA_WANT_ECC_SECP_R1_256) || \ defined(PSA_WANT_ECC_SECP_R1_384) || \ diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 15b986a805..53c1c035a8 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3540,9 +3540,9 @@ depends_on:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY:PSA_WANT_ALG_SHA_256 send_invalid_sig_alg:MBEDTLS_SSL_SIG_RSA:MBEDTLS_SSL_HASH_SHA256:MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER Baseline for: Server using sig_alg not offered by the client - ECDSA with SHA512 -depends_on:MBEDTLS_CAN_HANDLE_ECDSA_TEST_KEY:PSA_WANT_ALG_SHA_512 +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:0 Negative Test: Server using sig_alg not offered by the client - ECDSA with SHA512 -depends_on:MBEDTLS_CAN_HANDLE_ECDSA_TEST_KEY:PSA_WANT_ALG_SHA_512 +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 From c46eccf6ef0df8e54e50cc19eaaa3c90142d3c7a Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 11 Mar 2026 16:40:02 +0000 Subject: [PATCH 37/66] ssl_parse_signature_algorithm: caller to get bytes After the recent refactoring ssl_parse_signature_algorithm() sends an alert on failure, but the caller also sends an alert on failure. Sending two alerts is at least a protocol violation, and might not leave the SSL context in a good state. It is simpler to have the caller read the two bytes, and pass them to this function. Signed-off-by: Janos Follath --- library/ssl_tls12_client.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c index 4673827557..0bcbc7a5e1 100644 --- a/library/ssl_tls12_client.c +++ b/library/ssl_tls12_client.c @@ -1736,23 +1736,19 @@ static int ssl_parse_server_psk_hint(mbedtls_ssl_context *ssl, defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, - unsigned char **p, - unsigned char *end, + uint16_t sig_alg, mbedtls_md_type_t *md_alg, mbedtls_pk_sigalg_t *pk_alg) { *md_alg = MBEDTLS_MD_NONE; *pk_alg = MBEDTLS_PK_SIGALG_NONE; - MBEDTLS_SSL_CHK_BUF_READ_PTR(*p, end, 2); - uint16_t sig_alg = MBEDTLS_GET_UINT16_BE(*p, 0); - if (mbedtls_ssl_get_pk_sigalg_and_md_alg_from_sig_alg(sig_alg, pk_alg, md_alg) != 0) { /* * Check hash algorithm */ if (*md_alg == MBEDTLS_MD_NONE) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported HashAlgorithm %d", (*p)[0])); + MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported HashAlgorithm %d", sig_alg >> 8)); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } @@ -1760,7 +1756,8 @@ static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, * Check signature algorithm */ if (*pk_alg == MBEDTLS_PK_SIGALG_NONE) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported SignatureAlgorithm %d", (*p)[1])); + MBEDTLS_SSL_DEBUG_MSG(1, + ("Server used unsupported SignatureAlgorithm %d", sig_alg & 0x00FF)); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } @@ -1788,9 +1785,8 @@ static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } - MBEDTLS_SSL_DEBUG_MSG(2, ("Server used SignatureAlgorithm %d", (*p)[1])); - MBEDTLS_SSL_DEBUG_MSG(2, ("Server used HashAlgorithm %d", (*p)[0])); - *p += 2; + MBEDTLS_SSL_DEBUG_MSG(2, ("Server used SignatureAlgorithm %d", sig_alg & 0x00FF)); + MBEDTLS_SSL_DEBUG_MSG(2, ("Server used HashAlgorithm %d", sig_alg >> 8)); return 0; } @@ -1971,7 +1967,9 @@ start_processing: /* * Handle the digitally-signed structure */ - if (ssl_parse_signature_algorithm(ssl, &p, end, &md_alg, &pk_alg) != 0) { + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + uint16_t sig_alg = MBEDTLS_GET_UINT16_BE(p, 0); + if (ssl_parse_signature_algorithm(ssl, sig_alg, &md_alg, &pk_alg) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( @@ -1980,6 +1978,7 @@ start_processing: MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } + p += 2; psa_hash_alg = mbedtls_md_psa_alg_from_type(md_alg); if (!mbedtls_pk_can_do_psa(peer_pk, From 862c191f4f004de89702c86e38049694fd52a7f0 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 11 Mar 2026 16:55:28 +0000 Subject: [PATCH 38/66] send_invalid_sig_alg: reduce debug dependency Run as much of the test as we can even in the abscence of MBEDTLS_DEBUG_C. Signed-off-by: Janos Follath --- tests/suites/test_suite_ssl.function | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 6d37b908c4..6b3bca6edd 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -5768,6 +5768,7 @@ void send_invalid_sig_alg(int sig, int hash, int expected_ret) options.client_max_version = MBEDTLS_SSL_VERSION_TLS1_2; options.server_max_version = MBEDTLS_SSL_VERSION_TLS1_2; +#if defined(MBEDTLS_DEBUG_C) mbedtls_test_ssl_log_pattern cli_pattern; cli_pattern.pattern = "that was not offered"; cli_pattern.counter = 0; @@ -5779,6 +5780,7 @@ void send_invalid_sig_alg(int sig, int hash, int expected_ret) options.srv_log_obj = NULL; options.srv_log_fun = mbedtls_test_ssl_log_analyzer; mbedtls_debug_set_threshold(3); +#endif int ret = -1; @@ -5833,12 +5835,16 @@ void send_invalid_sig_alg(int sig, int hash, int expected_ret) MBEDTLS_SSL_CERTIFICATE_REQUEST); TEST_EQUAL(ret, expected_ret); +#if defined(MBEDTLS_DEBUG_C) if (expected_ret != 0) { TEST_EQUAL(cli_pattern.counter, 1); } +#endif exit: +#if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold(0); +#endif mbedtls_test_free_handshake_options(&options); mbedtls_test_ssl_endpoint_free(&server); mbedtls_test_ssl_endpoint_free(&client); From 7b255e3a12a93fc87e3170ee2230a95550ba3df6 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 11 Mar 2026 17:02:56 +0000 Subject: [PATCH 39/66] ssl_parse_signature_algorithm: match error codes The caller is returning MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER if ssl_parse_signature_algorithm() fails, but ssl_parse_signature_algorithm() returns MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE upon failure. There is no good reason for this mismatch and better to be aligned. Signed-off-by: Janos Follath --- library/ssl_tls12_client.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c index 0bcbc7a5e1..841f911e66 100644 --- a/library/ssl_tls12_client.c +++ b/library/ssl_tls12_client.c @@ -1749,7 +1749,7 @@ static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, */ if (*md_alg == MBEDTLS_MD_NONE) { MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported HashAlgorithm %d", sig_alg >> 8)); - return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } /* @@ -1758,14 +1758,14 @@ static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, if (*pk_alg == MBEDTLS_PK_SIGALG_NONE) { MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported SignatureAlgorithm %d", sig_alg & 0x00FF)); - return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } /* * This shouldn't happen, but be robust. */ MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported value in SigAlg extension %d", sig_alg)); - return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } /* @@ -1774,7 +1774,7 @@ static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, */ if (!mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported value in SigAlg extension %d", sig_alg)); - return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } /* @@ -1782,7 +1782,7 @@ static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, */ if (!mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("Server used SigAlg value %d that was not offered", sig_alg)); - return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } MBEDTLS_SSL_DEBUG_MSG(2, ("Server used SignatureAlgorithm %d", sig_alg & 0x00FF)); From 5ffef2897161abf432d957442a7ddc5d96b1e87d Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 12 Mar 2026 12:12:30 +0000 Subject: [PATCH 40/66] Fix code style Signed-off-by: Janos Follath --- library/ssl_tls12_client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c index 841f911e66..76ec4b6c4b 100644 --- a/library/ssl_tls12_client.c +++ b/library/ssl_tls12_client.c @@ -1757,7 +1757,8 @@ static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, */ if (*pk_alg == MBEDTLS_PK_SIGALG_NONE) { MBEDTLS_SSL_DEBUG_MSG(1, - ("Server used unsupported SignatureAlgorithm %d", sig_alg & 0x00FF)); + ("Server used unsupported SignatureAlgorithm %d", + sig_alg & 0x00FF)); return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } From 703c2a6d7c7ead396d170dfe5e1df28c6c074b2a Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 13 Mar 2026 11:13:29 +0000 Subject: [PATCH 41/66] Fix a typo and an oversight DEBUG_C supposed to have been removed from the test dependencies, still being there is an oversight. Removing it was the sole purpose of 3e58109fbd. Signed-off-by: Janos Follath --- tests/suites/test_suite_ssl.function | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 6b3bca6edd..a283b65e53 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -5725,12 +5725,12 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_ALG_SHA_256:MBEDTLS_TEST_HAS_ADDITIONAL_HASH:MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP:MBEDTLS_DEBUG_C*/ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_ALG_SHA_256:MBEDTLS_TEST_HAS_ADDITIONAL_HASH:MBEDTLS_TEST_HAS_DEFAULT_EC_GROUP*/ void send_invalid_sig_alg(int sig, int hash, int expected_ret) { // This is a test about the client behaviour in case it receives a key exchange signed with a // sig_alg it didn't specify in the client hello. The input specifies a target_sig_alg, which we - // make sure that the client does not offer but the server does. Then we make the server beleive + // make sure that the client does not offer but the server does. Then we make the server believe // that target_sig_alg is the only one the client offered. // Remark: We need an additional hash algorithm offered, because if we don't have it, the server From 6714b3901775978bd6ed6681cc65b957f9c9966f Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 13 Mar 2026 11:26:57 +0000 Subject: [PATCH 42/66] Improve ssl_parse_signature_algorithm Simplify and improve error reporting and remove unnecessary initialisation (the caller is responsible for initialising those values). Signed-off-by: Janos Follath --- library/ssl_tls12_client.c | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c index 76ec4b6c4b..a0170d51f6 100644 --- a/library/ssl_tls12_client.c +++ b/library/ssl_tls12_client.c @@ -1740,32 +1740,10 @@ static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, mbedtls_md_type_t *md_alg, mbedtls_pk_sigalg_t *pk_alg) { - *md_alg = MBEDTLS_MD_NONE; - *pk_alg = MBEDTLS_PK_SIGALG_NONE; - if (mbedtls_ssl_get_pk_sigalg_and_md_alg_from_sig_alg(sig_alg, pk_alg, md_alg) != 0) { - /* - * Check hash algorithm - */ - if (*md_alg == MBEDTLS_MD_NONE) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported HashAlgorithm %d", sig_alg >> 8)); - return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; - } - - /* - * Check signature algorithm - */ - if (*pk_alg == MBEDTLS_PK_SIGALG_NONE) { - MBEDTLS_SSL_DEBUG_MSG(1, - ("Server used unsupported SignatureAlgorithm %d", - sig_alg & 0x00FF)); - return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; - } - - /* - * This shouldn't happen, but be robust. - */ - MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported value in SigAlg extension %d", sig_alg)); + MBEDTLS_SSL_DEBUG_MSG(1, + ("Server used unsupported value in SigAlg extension 0x%04x", + sig_alg)); return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } @@ -1774,7 +1752,9 @@ static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, * TLS versions. Make sure that the received sig_alg extension is valid in TLS 1.2. */ if (!mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg)) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Server used unsupported value in SigAlg extension %d", sig_alg)); + MBEDTLS_SSL_DEBUG_MSG(1, + ("Server used unsupported value in SigAlg extension 0x%04x", + sig_alg)); return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } @@ -1782,7 +1762,7 @@ static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, * Check if the signature algorithm is acceptable */ if (!mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Server used SigAlg value %d that was not offered", sig_alg)); + MBEDTLS_SSL_DEBUG_MSG(1, ("Server used SigAlg value 0x%04x that was not offered", sig_alg)); return MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } From 894cea1fa2e81ec2c410b78a680573e3f056d537 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 16 Mar 2026 11:05:21 +0100 Subject: [PATCH 43/66] Add change log Signed-off-by: Ronald Cron --- ChangeLog.d/context_load_and_session_load_documentation.txt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 ChangeLog.d/context_load_and_session_load_documentation.txt diff --git a/ChangeLog.d/context_load_and_session_load_documentation.txt b/ChangeLog.d/context_load_and_session_load_documentation.txt new file mode 100644 index 0000000000..f7c1d27f8e --- /dev/null +++ b/ChangeLog.d/context_load_and_session_load_documentation.txt @@ -0,0 +1,6 @@ +Security + * The documentation of mbedtls_ssl_session_save(), + mbedtls_ssl_session_load(), mbedtls_ssl_context_save(), and + mbedtls_ssl_context_load() has been updated to clarify the responsibility + of the application to preserve the confidentiality and integrity of + serialized data, mitigating the risk of misuse of these APIs. From ccea2fd244d9f96637149ff0c56d1a1241c58c2b Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 17 Mar 2026 11:06:04 +0100 Subject: [PATCH 44/66] Improve change log Signed-off-by: Ronald Cron --- ChangeLog.d/context_load_and_session_load_documentation.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog.d/context_load_and_session_load_documentation.txt b/ChangeLog.d/context_load_and_session_load_documentation.txt index f7c1d27f8e..200ab27bf1 100644 --- a/ChangeLog.d/context_load_and_session_load_documentation.txt +++ b/ChangeLog.d/context_load_and_session_load_documentation.txt @@ -4,3 +4,5 @@ Security mbedtls_ssl_context_load() has been updated to clarify the responsibility of the application to preserve the confidentiality and integrity of serialized data, mitigating the risk of misuse of these APIs. + Credit to Haruto Kimura (Stella) for highlighting risks associated with + tampered serialized data. From ade56554a6103f7de26c16d4348f6efadb2d8b97 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 24 Mar 2026 18:38:01 +0100 Subject: [PATCH 45/66] Revert "ssl_server2.c: DTLS: Attempt to read the response to the close notification" This reverts commit 2e9b9681e60ff52d69a3a68b4c7be0bcbab9191b. Signed-off-by: Ronald Cron --- programs/ssl/ssl_server2.c | 50 +------------------ tests/compat.sh | 1 - tests/scripts/components-configuration-tls.sh | 1 - 3 files changed, 1 insertion(+), 51 deletions(-) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index f2e8eff47a..79cbad877d 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -4131,55 +4131,7 @@ close_notify: } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); ret = 0; - /* - * In the DTLS case, attempt to read a possible response to the close - * notification. This avoids reconnecting to the same client when we - * reset and later receive its close-notification response during - * step 3 (waiting for a client to connect). - * - * Stop waiting for the response if the connection has already ended. - * - * The waiting loop below relies on mbedtls_ssl_read() returning regularly - * in order to keep the total waiting time approximately bounded to 1s. If - * no read timeout is configured (see the read_timeout option), or if the - * configured timeout is close to or larger than 1s, the total waiting time - * may exceed 1s by a significant margin. - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) && defined(MBEDTLS_HAVE_TIME) - if (opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - mbedtls_ms_time_t start = mbedtls_ms_time(); - for (;;) { - ret = mbedtls_ssl_read(&ssl, buf, opt.buffer_size); - /* - * mbedtls_ssl_read() returned some data or timed out, loop if we - * have not spent already too much time, quite arbitrarily 1s. - */ - if ((ret > 0) || (ret == MBEDTLS_ERR_SSL_TIMEOUT)) { - if ((mbedtls_ms_time() - start) < 1000) { - continue; - } - } - - if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - mbedtls_printf(" done, received client close notification.\n"); - } else { - /* ret = 0, silent transport EOF or ret < 0 except - * MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY. Note that we do not - * handle specifically the non-fatal error codes like - * MBEDTLS_ERR_SSL_WANT_READ as we do not really expect them - * here. - */ - mbedtls_printf(" done\n"); - } - break; - } - ret = 0; - } else -#endif /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_HAVE_TIME */ - { - mbedtls_printf(" done\n"); - } - fflush(stdout); + mbedtls_printf(" done\n"); #if defined(MBEDTLS_SSL_CACHE_C) if (opt.cache_remove > 0) { diff --git a/tests/compat.sh b/tests/compat.sh index 3f44c984fb..2b6f454127 100755 --- a/tests/compat.sh +++ b/tests/compat.sh @@ -557,7 +557,6 @@ setup_arguments() # with OpenSSL 1.0.1h, -www, -WWW and -HTTP break DTLS handshakes if is_dtls "$MODE"; then O_SERVER_ARGS="$O_SERVER_ARGS" - M_SERVER_ARGS="$M_SERVER_ARGS read_timeout=1000" else O_SERVER_ARGS="$O_SERVER_ARGS -www" fi diff --git a/tests/scripts/components-configuration-tls.sh b/tests/scripts/components-configuration-tls.sh index d017eef182..5a77c4defc 100644 --- a/tests/scripts/components-configuration-tls.sh +++ b/tests/scripts/components-configuration-tls.sh @@ -165,7 +165,6 @@ component_test_tls1_2_ccm_psk_dtls () { msg "build: configs/config-ccm-psk-dtls1_2.h" MBEDTLS_CONFIG="configs/config-ccm-psk-dtls1_2.h" CRYPTO_CONFIG="configs/crypto-config-ccm-psk-tls1_2.h" - tf-psa-crypto/scripts/config.py -f "$CRYPTO_CONFIG" set MBEDTLS_HAVE_TIME CC=$ASAN_CC cmake -DMBEDTLS_CONFIG_FILE="$MBEDTLS_CONFIG" -DTF_PSA_CRYPTO_CONFIG_FILE="$CRYPTO_CONFIG" -D CMAKE_BUILD_TYPE:String=Asan . make From 315c970fbeb4ac13446c56f16dd4c8f4c3df0222 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 20 Mar 2026 11:21:56 +0100 Subject: [PATCH 46/66] dtls: Fix debug log Signed-off-by: Ronald Cron --- library/ssl_msg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ssl_msg.c b/library/ssl_msg.c index abb5a5696f..86c23d766c 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -3618,7 +3618,7 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl, ( "datagram of length %u too small to hold DTLS record header of length %u", (unsigned) len, - (unsigned) (rec_hdr_len_len + rec_hdr_len_len))); + (unsigned) (rec_hdr_len_offset + rec_hdr_len_len))); return MBEDTLS_ERR_SSL_INVALID_RECORD; } From 676d74e4c74ce71a38b321f4567dfa8a20f30ff7 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 20 Mar 2026 17:19:10 +0100 Subject: [PATCH 47/66] dtls: Error out on invalid/unexpected record header Error out on invalid/unexpected record header when reading the DTLS 1.2 ClientHello. Signed-off-by: Ronald Cron --- library/ssl_msg.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/library/ssl_msg.c b/library/ssl_msg.c index 86c23d766c..65609b8ff9 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -4750,6 +4750,30 @@ static int ssl_get_next_record(mbedtls_ssl_context *ssl) ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; } +#if defined(MBEDTLS_SSL_SRV_C) + /* + * When retrieving the DTLS ClientHello on server side, error out + * when detecting an invalid or unexpected record. + */ + if ((ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) && + (ssl->state == MBEDTLS_SSL_CLIENT_HELLO) +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && (ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE) +#endif + ) { + /* + * For backward compatibility, return + * MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE rather than + * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD. + */ + if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) { + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + } else { + return ret; + } + } +#endif /* MBEDTLS_SSL_SRV_C */ + if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) { #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) /* Reset in pointers to default state for TLS/DTLS records, From 16c5dd99b3278f3ed0582f76baa9a1bc031b5187 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 18 Mar 2026 12:06:59 +0100 Subject: [PATCH 48/66] Introduce ssl_buffering_shift_slots Signed-off-by: Ronald Cron --- library/ssl_msg.c | 57 +++++++++++++++++++++++++++++++---------------- tests/ssl-opt.sh | 2 +- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/library/ssl_msg.c b/library/ssl_msg.c index 65609b8ff9..7eb91031d7 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -275,6 +275,7 @@ exit: /* Forward declarations for functions related to message buffering. */ static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl, uint8_t slot); +static void ssl_buffering_shift_slots(mbedtls_ssl_context *ssl, unsigned shift); static void ssl_free_buffered_record(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_load_buffered_message(mbedtls_ssl_context *ssl); @@ -3180,28 +3181,10 @@ int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl) #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake != NULL) { - unsigned offset; - mbedtls_ssl_hs_buffer *hs_buf; /* Increment handshake sequence number */ hs->in_msg_seq++; - - /* - * Clear up handshake buffering and reassembly structure. - */ - - /* Free first entry */ - ssl_buffering_free_slot(ssl, 0); - - /* Shift all other entries */ - for (offset = 0, hs_buf = &hs->buffering.hs[0]; - offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS; - offset++, hs_buf++) { - *hs_buf = *(hs_buf + 1); - } - - /* Create a fresh last entry */ - memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer)); + ssl_buffering_shift_slots(ssl, 1); } #endif return 0; @@ -6158,6 +6141,42 @@ static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl, } } +/* + * Shift the buffering slots to the left by `shift` positions. + * After the operation, slot i contains the previous slot i + shift. + */ +static void ssl_buffering_shift_slots(mbedtls_ssl_context *ssl, + unsigned shift) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + unsigned offset; + + if (shift == 0) { + return; + } + + if (shift >= MBEDTLS_SSL_MAX_BUFFERED_HS) { + shift = MBEDTLS_SSL_MAX_BUFFERED_HS; + } + + /* Free discarded entries */ + for (offset = 0; offset < shift; offset++) { + ssl_buffering_free_slot(ssl, offset); + } + + /* Shift remaining entries left */ + for (offset = 0; offset + shift < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) { + hs->buffering.hs[offset] = hs->buffering.hs[offset + shift]; + } + + /* Reset the remaining entries at the end. It may have been already + * partially done by the loop freing the discarded entries but that is + * simpler and safer. + */ + for (; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) { + memset(&hs->buffering.hs[offset], 0, sizeof(hs->buffering.hs[offset])); + } +} #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index a999c94f5b..b5e968b751 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -2168,7 +2168,7 @@ run_test "Default, TLS 1.2" \ requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 requires_ciphersuite_enabled TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256 run_test "Default, DTLS" \ - "$P_SRV dtls=1" \ + "$P_SRV debug_level=5 dtls=1" \ "$P_CLI dtls=1" \ 0 \ -s "Protocol is DTLSv1.2" \ From 912ef74195a105650bb95c8296dc880c241d4369 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 18 Mar 2026 12:15:52 +0100 Subject: [PATCH 49/66] Update buffering when adapting to ClientHello message_seq Signed-off-by: Ronald Cron --- library/ssl_msg.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/library/ssl_msg.c b/library/ssl_msg.c index 7eb91031d7..6a9d88d850 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -2986,17 +2986,21 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) * expected `message_seq` for the incoming and outgoing * handshake messages. */ - ssl->handshake->in_msg_seq = recv_msg_seq; - ssl->handshake->out_msg_seq = recv_msg_seq; + if ((ssl->handshake->in_msg_seq == 0) && (recv_msg_seq > 0)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("shift slots by %u", recv_msg_seq)); + ssl_buffering_shift_slots(ssl, recv_msg_seq); + ssl->handshake->in_msg_seq = recv_msg_seq; + ssl->handshake->out_msg_seq = recv_msg_seq; - /* Epoch should be 0 for initial handshakes */ - if (ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + /* Epoch should be 0 for initial handshakes */ + if (ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + memcpy(&ssl->cur_out_ctr[2], ssl->in_ctr + 2, + sizeof(ssl->cur_out_ctr) - 2); } - - memcpy(&ssl->cur_out_ctr[2], ssl->in_ctr + 2, - sizeof(ssl->cur_out_ctr) - 2); } else if (mbedtls_ssl_is_handshake_over(ssl) == 1) { /* In case of a post-handshake ClientHello that initiates a * renegotiation check that the handshake message sequence From 0c301a686aa296433d01f4d5db7f4612a1da4aaa Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 23 Mar 2026 15:40:02 +0100 Subject: [PATCH 50/66] dtls: Improve comment Signed-off-by: Ronald Cron --- library/ssl_msg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/ssl_msg.c b/library/ssl_msg.c index 6a9d88d850..287b0bf507 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -6174,8 +6174,8 @@ static void ssl_buffering_shift_slots(mbedtls_ssl_context *ssl, } /* Reset the remaining entries at the end. It may have been already - * partially done by the loop freing the discarded entries but that is - * simpler and safer. + * done for the first ones by the loop freing the discarded entries but + * that is simpler and safer. */ for (; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) { memset(&hs->buffering.hs[offset], 0, sizeof(hs->buffering.hs[offset])); From f9b7441542734d91bcd52cb234ccd76409559745 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 23 Mar 2026 18:23:03 +0100 Subject: [PATCH 51/66] dtls: Keep invalid/unexpected record header error code Signed-off-by: Ronald Cron --- library/ssl_msg.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/library/ssl_msg.c b/library/ssl_msg.c index 287b0bf507..812f578baf 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -4748,16 +4748,7 @@ static int ssl_get_next_record(mbedtls_ssl_context *ssl) && (ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE) #endif ) { - /* - * For backward compatibility, return - * MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE rather than - * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD. - */ - if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) { - return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; - } else { - return ret; - } + return ret; } #endif /* MBEDTLS_SSL_SRV_C */ From 140ebea442ce2436f2f8ce59b554df6a70baad2f Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 24 Mar 2026 00:48:28 +0100 Subject: [PATCH 52/66] dtls: parse_client_hello: Adapt mbedtls_ssl_read_record() error code Signed-off-by: Ronald Cron --- library/ssl_tls12_server.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index 94e61a8aca..5dbdd3854c 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -879,6 +879,31 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) */ if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record ", ret); + + /* + * In the case of an alert message corresponding to the termination of + * a previous connection, `ssl_parse_record_header()` and then + * `mbedtls_ssl_read_record()` may return + * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD because of a non zero epoch. + * + * Historically, the library has returned + * MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE in this situation. + * The sample program dtls_server.c relies on this behavior + * (see + * https://github.com/Mbed-TLS/mbedtls/blob/d5e35a376bee23fad0b17f2e3e94a32ce4017c64/programs/ssl/dtls_server.c#L295), + * and user applications may rely on it as well. + * + * For compatibility, map MBEDTLS_ERR_SSL_UNEXPECTED_RECORD + * to MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE here. + * + * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD does not appear to be + * used to detect a specific error condition, so this mapping + * should not remove any meaningful distinction. + */ + if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) { + ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + } + return ret; } From c9264ad227d1e70780bfd6a1e4db3fd70a7155b3 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 23 Mar 2026 16:25:33 +0100 Subject: [PATCH 53/66] dtls: Fix log level Signed-off-by: Ronald Cron --- library/ssl_msg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ssl_msg.c b/library/ssl_msg.c index 812f578baf..c0c2825c4d 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -2987,7 +2987,7 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) * handshake messages. */ if ((ssl->handshake->in_msg_seq == 0) && (recv_msg_seq > 0)) { - MBEDTLS_SSL_DEBUG_MSG(1, ("shift slots by %u", recv_msg_seq)); + MBEDTLS_SSL_DEBUG_MSG(3, ("shift slots by %u", recv_msg_seq)); ssl_buffering_shift_slots(ssl, recv_msg_seq); ssl->handshake->in_msg_seq = recv_msg_seq; ssl->handshake->out_msg_seq = recv_msg_seq; From f285018fa368ae832d43309e14703501038fee90 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 24 Mar 2026 10:03:21 +0100 Subject: [PATCH 54/66] Disable "DTLS proxy: 3d, (openssl|gnutls) client, fragmentation" tests The tests fail intermittently on the CI with a frequency that significantly impacts CI throughput. Signed-off-by: Ronald Cron --- tests/scripts/analyze_outcomes.py | 9 +++++++++ tests/ssl-opt.sh | 13 +++++++++++++ 2 files changed, 22 insertions(+) diff --git a/tests/scripts/analyze_outcomes.py b/tests/scripts/analyze_outcomes.py index 2bd4bd8162..b6f18c5b88 100755 --- a/tests/scripts/analyze_outcomes.py +++ b/tests/scripts/analyze_outcomes.py @@ -50,6 +50,15 @@ class CoverageTask(outcome_analysis.CoverageTask): # TLS doesn't use restartable ECDH yet. # https://github.com/Mbed-TLS/mbedtls/issues/7294 re.compile(r'EC restart:.*no USE_PSA.*'), + # The following test fails intermittently on the CI with a frequency + # that significantly impacts CI throughput. They are thus disabled + # for the time being. See + # https://github.com/Mbed-TLS/mbedtls/issues/10652 for more + # information. + 'DTLS proxy: 3d, openssl client, fragmentation', + 'DTLS proxy: 3d, openssl client, fragmentation, nbio', + 'DTLS proxy: 3d, gnutls client, fragmentation', + 'DTLS proxy: 3d, gnutls client, fragmentation, nbio=2', ], 'test_suite_config.mbedtls_boolean': [ # Missing coverage of test configurations. diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index b5e968b751..7abcd4b96d 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -12169,6 +12169,9 @@ run_test "DTLS proxy: 3d, openssl client" \ 0 \ -s "HTTP/1.0 200 OK" +# The following test fails intermittently on the CI with a frequency that +# significantly impacts CI throughput. Disable it for the time being. +skip_next_test requires_openssl_next client_needs_more_time 8 not_with_valgrind # risk of non-mbedtls peer timing out @@ -12182,6 +12185,9 @@ run_test "DTLS proxy: 3d, openssl client, fragmentation" \ -s "found fragmented DTLS handshake message" \ -s "Certificate handshake message has been buffered and reassembled" +# The following test fails intermittently on the CI with a frequency that +# significantly impacts CI throughput. Disable it for the time being. +skip_next_test requires_openssl_next client_needs_more_time 8 not_with_valgrind # risk of non-mbedtls peer timing out @@ -12250,6 +12256,10 @@ run_test "DTLS proxy: 3d, gnutls client" \ # fragmentation to remain the case across GnuTLS version updates. Avoid using a # smaller MTU, as the smaller the MTU, the more likely the handshake is to fail # in this very unreliable connection emulation. + +# The following test fails intermittently on the CI with a frequency that +# significantly impacts CI throughput. Disable it for the time being. +skip_next_test requires_gnutls client_needs_more_time 8 not_with_valgrind # risk of non-mbedtls peer timing out @@ -12262,6 +12272,9 @@ run_test "DTLS proxy: 3d, gnutls client, fragmentation" \ -s "HTTP/1.0 200 OK" \ -s "ClientHello handshake message has been buffered and reassembled" +# The following test fails intermittently on the CI with a frequency that +# significantly impacts CI throughput. Disable it for the time being. +skip_next_test requires_gnutls client_needs_more_time 8 not_with_valgrind # risk of non-mbedtls peer timing out From fbe388dc287bfe3414b565c0a009c879172c744e Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 24 Mar 2026 12:25:34 +0100 Subject: [PATCH 55/66] ssl-opt.sh: Fix log checks in some "DTLS reassembly" tests In DTLS reassembly tests, the server may receive a close_notify alert at the end of a test. In this case, the Mbed TLS server logs an error, so these tests should not check for the absence of the string "error" in the server logs. Signed-off-by: Ronald Cron --- 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 7abcd4b96d..aa339a9eab 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -9978,7 +9978,7 @@ run_test "DTLS reassembly: no fragmentation (gnutls client)" \ "$G_NEXT_CLI -u --mtu 2048 --insecure 127.0.0.1" \ 0 \ -S "found fragmented DTLS handshake message" \ - -S "error" + -s "HTTP/1.0 200 OK" requires_gnutls requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 @@ -9988,7 +9988,7 @@ run_test "DTLS reassembly: some fragmentation (gnutls client)" \ 0 \ -s "found fragmented DTLS handshake message" \ -s "Certificate handshake message has been buffered and reassembled" \ - -S "error" + -s "HTTP/1.0 200 OK" # Set the MTU to 128 bytes. The minimum size of a DTLS 1.2 record # containing a ClientHello handshake message is 69 bytes, without any cookie, @@ -10003,7 +10003,7 @@ run_test "DTLS reassembly: more fragmentation (gnutls client)" \ "$G_NEXT_CLI -u --mtu 103 --insecure 127.0.0.1" \ 0 \ -s "ClientHello handshake message has been buffered and reassembled" \ - -S "error" + -s "HTTP/1.0 200 OK" requires_gnutls requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 @@ -10012,7 +10012,7 @@ run_test "DTLS reassembly: more fragmentation, nbio (gnutls client)" \ "$G_NEXT_CLI -u --mtu 103 --insecure 127.0.0.1" \ 0 \ -s "ClientHello handshake message has been buffered and reassembled" \ - -S "error" + -s "HTTP/1.0 200 OK" # No fragmentation and renegotiation tests with GnuTLS client as the feature # does not work properly. @@ -10053,7 +10053,7 @@ run_test "DTLS reassembly: no fragmentation (openssl client)" \ "$O_NEXT_CLI -dtls -mtu 2048 -cert $DATA_FILES_PATH/server5.crt -key $DATA_FILES_PATH/server5.key" \ 0 \ -S "found fragmented DTLS handshake message" \ - -S "error" + -s "HTTP/1.0 200 OK" # Minimum possible MTU for OpenSSL server: 256 bytes. # We expect the client Certificate handshake message to be fragmented and @@ -10068,7 +10068,7 @@ run_test "DTLS reassembly: some fragmentation (openssl client)" \ 0 \ -s "found fragmented DTLS handshake message" \ -s "Certificate handshake message has been buffered and reassembled" \ - -S "error" + -s "HTTP/1.0 200 OK" requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "DTLS reassembly: fragmentation, nbio (openssl client)" \ @@ -10077,7 +10077,7 @@ run_test "DTLS reassembly: fragmentation, nbio (openssl client)" \ 0 \ -s "found fragmented DTLS handshake message" \ -s "Certificate handshake message has been buffered and reassembled" \ - -S "error" + -s "HTTP/1.0 200 OK" # Tests for sending fragmented handshake messages with DTLS # From f2f44a9c9f7c3c3d66324029d1131f5bc1d5910e Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 24 Mar 2026 15:42:42 +0100 Subject: [PATCH 56/66] Restrict mapping of UNEXPECTED_RECORD to UNEXPECTED_MESSAGE Signed-off-by: Ronald Cron --- library/ssl_tls12_server.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index 5dbdd3854c..26ba8590ac 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -880,6 +880,7 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record ", ret); +#if defined(MBEDTLS_SSL_PROTO_DTLS) /* * In the case of an alert message corresponding to the termination of * a previous connection, `ssl_parse_record_header()` and then @@ -900,9 +901,16 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) * used to detect a specific error condition, so this mapping * should not remove any meaningful distinction. */ - if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) { - ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + if ((ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && (ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE) +#endif + ) { + if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) { + ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + } } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ return ret; } From 1141cd0fb634c754a4ad9a3572621b0656511247 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 24 Mar 2026 15:47:55 +0100 Subject: [PATCH 57/66] Improve comments Signed-off-by: Ronald Cron --- library/ssl_msg.c | 20 +++++++++++++++----- tests/ssl-opt.sh | 4 ++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/library/ssl_msg.c b/library/ssl_msg.c index c0c2825c4d..0799a0067e 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -4739,8 +4739,18 @@ static int ssl_get_next_record(mbedtls_ssl_context *ssl) #if defined(MBEDTLS_SSL_SRV_C) /* - * When retrieving the DTLS ClientHello on server side, error out - * when detecting an invalid or unexpected record. + * In DTLS, invalid records are usually ignored because it is easy + * for an attacker to inject UDP datagrams, and we do not want such + * packets to disrupt the entire connection. + * + * However, when expecting the ClientHello, we reject invalid or + * unexpected records. This avoids waiting for further records + * before receiving at least one valid message. Such records could + * be leftover messages from a previous connection, accidental + * input, or part of a DoS attempt. + * + * Since no valid message has been received yet, immediately + * closing the connection does not result in any loss. */ if ((ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) && (ssl->state == MBEDTLS_SSL_CLIENT_HELLO) @@ -6164,9 +6174,9 @@ static void ssl_buffering_shift_slots(mbedtls_ssl_context *ssl, hs->buffering.hs[offset] = hs->buffering.hs[offset + shift]; } - /* Reset the remaining entries at the end. It may have been already - * done for the first ones by the loop freing the discarded entries but - * that is simpler and safer. + /* Reset the remaining entries at the end. Some may already have been + * cleared by the loop freeing the discarded entries, but resetting all + * of them is simpler and avoids tracking which ones were already handled. */ for (; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) { memset(&hs->buffering.hs[offset], 0, sizeof(hs->buffering.hs[offset])); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index aa339a9eab..2b0341ebef 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -12171,6 +12171,7 @@ run_test "DTLS proxy: 3d, openssl client" \ # The following test fails intermittently on the CI with a frequency that # significantly impacts CI throughput. Disable it for the time being. +# See https://github.com/Mbed-TLS/mbedtls/issues/10652 for more information. skip_next_test requires_openssl_next client_needs_more_time 8 @@ -12187,6 +12188,7 @@ run_test "DTLS proxy: 3d, openssl client, fragmentation" \ # The following test fails intermittently on the CI with a frequency that # significantly impacts CI throughput. Disable it for the time being. +# See https://github.com/Mbed-TLS/mbedtls/issues/10652 for more information. skip_next_test requires_openssl_next client_needs_more_time 8 @@ -12259,6 +12261,7 @@ run_test "DTLS proxy: 3d, gnutls client" \ # The following test fails intermittently on the CI with a frequency that # significantly impacts CI throughput. Disable it for the time being. +# See https://github.com/Mbed-TLS/mbedtls/issues/10652 for more information. skip_next_test requires_gnutls client_needs_more_time 8 @@ -12274,6 +12277,7 @@ run_test "DTLS proxy: 3d, gnutls client, fragmentation" \ # The following test fails intermittently on the CI with a frequency that # significantly impacts CI throughput. Disable it for the time being. +# See https://github.com/Mbed-TLS/mbedtls/issues/10652 for more information. skip_next_test requires_gnutls client_needs_more_time 8 From 7a8fbc2100fc2d04e558526c1cc5b7f3c18e58b5 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 24 Mar 2026 15:49:25 +0100 Subject: [PATCH 58/66] Remove debug leftover Signed-off-by: Ronald Cron --- tests/ssl-opt.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 2b0341ebef..4d0b6f6082 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -2168,7 +2168,7 @@ run_test "Default, TLS 1.2" \ requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 requires_ciphersuite_enabled TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256 run_test "Default, DTLS" \ - "$P_SRV debug_level=5 dtls=1" \ + "$P_SRV dtls=1" \ "$P_CLI dtls=1" \ 0 \ -s "Protocol is DTLSv1.2" \ From 1330606ca1ea4d9296fc97ed320735075293e2f6 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 24 Mar 2026 16:49:34 +0100 Subject: [PATCH 59/66] dtls: Fix adaptation to first ClientHello For each received ClientHello fragment, check that its epoch is zero and update the record-level sequence number. Signed-off-by: Ronald Cron --- library/ssl_msg.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/library/ssl_msg.c b/library/ssl_msg.c index 0799a0067e..87d64788bd 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -2991,16 +2991,17 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) ssl_buffering_shift_slots(ssl, recv_msg_seq); ssl->handshake->in_msg_seq = recv_msg_seq; ssl->handshake->out_msg_seq = recv_msg_seq; - - /* Epoch should be 0 for initial handshakes */ - if (ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; - } - - memcpy(&ssl->cur_out_ctr[2], ssl->in_ctr + 2, - sizeof(ssl->cur_out_ctr) - 2); } + + /* Epoch should be 0 for initial handshakes */ + if (ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + memcpy(&ssl->cur_out_ctr[2], ssl->in_ctr + 2, + sizeof(ssl->cur_out_ctr) - 2); + } else if (mbedtls_ssl_is_handshake_over(ssl) == 1) { /* In case of a post-handshake ClientHello that initiates a * renegotiation check that the handshake message sequence From f3f27070a6e3d2a2bc4ad3a859e9173310c44224 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Thu, 26 Mar 2026 11:07:16 +0000 Subject: [PATCH 60/66] Added attributions & CVE Signed-off-by: Minos Galanakis --- ChangeLog.d/fix-null-pointer-dereference.txt | 3 ++- ChangeLog.d/inet_pton.txt | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog.d/fix-null-pointer-dereference.txt b/ChangeLog.d/fix-null-pointer-dereference.txt index 1eb3c416a8..1dd7d61905 100644 --- a/ChangeLog.d/fix-null-pointer-dereference.txt +++ b/ChangeLog.d/fix-null-pointer-dereference.txt @@ -1,4 +1,5 @@ Security * Fix a NULL pointer dereference in mbedtls_x509_string_to_names() when mbedtls_calloc() fails to allocate memory. This was caused by failing to - check whether mbedtls_calloc() returned NULL. + check whether mbedtls_calloc() returned NULL. Found and reported by + Haruto Kimura (Stella). diff --git a/ChangeLog.d/inet_pton.txt b/ChangeLog.d/inet_pton.txt index 22e6806556..1acb8de84e 100644 --- a/ChangeLog.d/inet_pton.txt +++ b/ChangeLog.d/inet_pton.txt @@ -3,3 +3,4 @@ Security (e.g. on platforms with memory protection when the overread crosses page boundary) this could lead to DoS. Found and reported by Haruto Kimura (Stella). + CVE-2026-25833 From feb0dd04bafac7838a67deba8956693fb23e3cd4 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Thu, 26 Mar 2026 14:51:04 +0000 Subject: [PATCH 61/66] Extended attributions & CVE Signed-off-by: Minos Galanakis --- ChangeLog.d/context_load_and_session_load_documentation.txt | 4 ++-- ChangeLog.d/inet_pton.txt | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ChangeLog.d/context_load_and_session_load_documentation.txt b/ChangeLog.d/context_load_and_session_load_documentation.txt index 200ab27bf1..dbbbda1fea 100644 --- a/ChangeLog.d/context_load_and_session_load_documentation.txt +++ b/ChangeLog.d/context_load_and_session_load_documentation.txt @@ -4,5 +4,5 @@ Security mbedtls_ssl_context_load() has been updated to clarify the responsibility of the application to preserve the confidentiality and integrity of serialized data, mitigating the risk of misuse of these APIs. - Credit to Haruto Kimura (Stella) for highlighting risks associated with - tampered serialized data. + Credit to Haruto Kimura (Stella) and Eva Crystal (0xiviel) for + highlighting risks associated with tampered serialized data. diff --git a/ChangeLog.d/inet_pton.txt b/ChangeLog.d/inet_pton.txt index 1acb8de84e..73b9aa6b19 100644 --- a/ChangeLog.d/inet_pton.txt +++ b/ChangeLog.d/inet_pton.txt @@ -2,5 +2,4 @@ Security * Fix a limited buffer underflow in x509_inet_pton_ipv6(). In rare cases (e.g. on platforms with memory protection when the overread crosses page boundary) this could lead to DoS. Found and reported by Haruto Kimura - (Stella). - CVE-2026-25833 + (Stella). CVE-2026-25833 From 43b89543ecbb42d463c5352e17926a2d315e339e Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Thu, 26 Mar 2026 22:20:01 +0000 Subject: [PATCH 62/66] Updated framework submodule Signed-off-by: Minos Galanakis --- framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework b/framework index 9b92164c47..dff9da0443 160000 --- a/framework +++ b/framework @@ -1 +1 @@ -Subproject commit 9b92164c47fdaecb2600b417733507e2a105c3a5 +Subproject commit dff9da04438d712f7647fd995bc90fadd0c0e2ce From 83d1ebc1148d563e41aeb4ed4cc488af31cfc7c3 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Thu, 26 Mar 2026 22:20:06 +0000 Subject: [PATCH 63/66] 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 ed3c7d281e..29160dd877 160000 --- a/tf-psa-crypto +++ b/tf-psa-crypto @@ -1 +1 @@ -Subproject commit ed3c7d281e710ef44264d29f3157fd572165a74d +Subproject commit 29160dd877d29658279fd683b2ae57b320ddcf09 From e89565f92a863bfd9314e65fbe3ce0178a98af20 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Thu, 26 Mar 2026 22:20:52 +0000 Subject: [PATCH 64/66] Bump version ./scripts/bump_version.sh --version 4.1.0 \ --so-crypto 18 --so-tls 23 --so-x509 9 Signed-off-by: Minos Galanakis --- CMakeLists.txt | 8 ++++---- doxygen/input/doc_mainpage.h | 2 +- doxygen/mbedtls.doxyfile | 2 +- include/mbedtls/build_info.h | 8 ++++---- library/Makefile | 6 +++--- tests/suites/test_suite_version.data | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 42e4ccb34d..a19b6f723b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,10 +37,10 @@ cmake_policy(SET CMP0011 NEW) # is deprecated and will be removed in future versions. cmake_policy(SET CMP0012 NEW) -set(MBEDTLS_VERSION 4.0.0) -set(MBEDTLS_CRYPTO_SOVERSION 17) -set(MBEDTLS_X509_SOVERSION 8) -set(MBEDTLS_TLS_SOVERSION 22) +set(MBEDTLS_VERSION 4.1.0) +set(MBEDTLS_CRYPTO_SOVERSION 18) +set(MBEDTLS_X509_SOVERSION 9) +set(MBEDTLS_TLS_SOVERSION 23) if(TEST_CPP) project("Mbed TLS" diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h index 4eda5ba2aa..b28b82b851 100644 --- a/doxygen/input/doc_mainpage.h +++ b/doxygen/input/doc_mainpage.h @@ -10,7 +10,7 @@ */ /** - * @mainpage Mbed TLS v4.0.0 API Documentation + * @mainpage Mbed TLS v4.1.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 80e459cc72..c6a5e4f4fd 100644 --- a/doxygen/mbedtls.doxyfile +++ b/doxygen/mbedtls.doxyfile @@ -1,4 +1,4 @@ -PROJECT_NAME = "Mbed TLS v4.0.0" +PROJECT_NAME = "Mbed TLS v4.1.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 7b7ff49f5a..e077bbce40 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 0 +#define MBEDTLS_VERSION_MINOR 1 #define MBEDTLS_VERSION_PATCH 0 /** @@ -35,9 +35,9 @@ * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x04000000 -#define MBEDTLS_VERSION_STRING "4.0.0" -#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 4.0.0" +#define MBEDTLS_VERSION_NUMBER 0x04010000 +#define MBEDTLS_VERSION_STRING "4.1.0" +#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 4.1.0" #if defined(MBEDTLS_CONFIG_FILES_READ) #error "Something went wrong: MBEDTLS_CONFIG_FILES_READ defined before reading the config files!" diff --git a/library/Makefile b/library/Makefile index ad2854ad3a..cb6a99cc6c 100644 --- a/library/Makefile +++ b/library/Makefile @@ -72,9 +72,9 @@ LOCAL_CFLAGS += -fPIC -fpic endif endif -SOEXT_TLS?=so.21 -SOEXT_X509?=so.8 -SOEXT_CRYPTO?=so.16 +SOEXT_TLS?=so.23 +SOEXT_X509?=so.9 +SOEXT_CRYPTO?=so.18 ARFLAGS = $(AR_DASH)src ifdef APPLE_BUILD diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data index 3c818583fd..5ffdfe71f9 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.0.0" +check_compiletime_version:"4.1.0" Check runtime library version -check_runtime_version:"4.0.0" +check_runtime_version:"4.1.0" Check for MBEDTLS_VERSION_C check_feature:"MBEDTLS_VERSION_C":0 From 641fa2695cab74d25b8d9315daacd6839d393ed1 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Thu, 26 Mar 2026 22:23:55 +0000 Subject: [PATCH 65/66] Assemble ChangeLog ./framework/scripts/assemble_changelog.py Signed-off-by: Minos Galanakis --- ChangeLog | 77 +++++++++++++++++++ ChangeLog.d/alert-getter.txt | 6 -- ...nfig_checks_generator-fix-windows-path.txt | 3 - ...xt_load_and_session_load_documentation.txt | 8 -- .../dtls-client-hello-defragmentation.txt | 5 -- ChangeLog.d/fix-null-pointer-dereference.txt | 5 -- ChangeLog.d/gnuinstalldirs_include.txt | 3 - ChangeLog.d/iar-6.5fs.txt | 3 - ChangeLog.d/inet_pton.txt | 5 -- ChangeLog.d/issue10349.txt | 8 -- ChangeLog.d/sig_algs_check.txt | 5 -- ChangeLog.d/timing.txt | 13 ---- ChangeLog.d/tls12-2nd-client-hello.txt | 9 --- ChangeLog.d/unistd.txt | 3 - ChangeLog.d/verify-result-default-value.txt | 5 -- 15 files changed, 77 insertions(+), 81 deletions(-) delete mode 100644 ChangeLog.d/alert-getter.txt delete mode 100644 ChangeLog.d/config_checks_generator-fix-windows-path.txt delete mode 100644 ChangeLog.d/context_load_and_session_load_documentation.txt delete mode 100644 ChangeLog.d/dtls-client-hello-defragmentation.txt delete mode 100644 ChangeLog.d/fix-null-pointer-dereference.txt delete mode 100644 ChangeLog.d/gnuinstalldirs_include.txt delete mode 100644 ChangeLog.d/iar-6.5fs.txt delete mode 100644 ChangeLog.d/inet_pton.txt delete mode 100644 ChangeLog.d/issue10349.txt delete mode 100644 ChangeLog.d/sig_algs_check.txt delete mode 100644 ChangeLog.d/timing.txt delete mode 100644 ChangeLog.d/tls12-2nd-client-hello.txt delete mode 100644 ChangeLog.d/unistd.txt delete mode 100644 ChangeLog.d/verify-result-default-value.txt diff --git a/ChangeLog b/ChangeLog index 4dc0941fee..12191e1116 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,82 @@ Mbed TLS ChangeLog (Sorted per branch, date) += Mbed TLS 4.1.0 branch released 2026-03-31 + +API changes + * MBEDTLS_TIMING_C now requires MBEDTLS_HAVE_TIME to be enabled in the + TF-PSA-Crypto configuration, unless MBEDTLS_TIMING_ALT is enabled. + As a benefit, platforms where the default implementation is not + supported now only need to implement MBEDTLS_PLATFORM_MS_TIME_ALT. + * When MBEDTLS_TIMING_ALT is enabled, the function + mbedtls_timing_get_timer() now returns unsigned long long instead + of unsigned long. + +Features + * Add the function mbedtls_ssl_get_fatal_alert(), which returns the type of + the last received fatal alert. This allows callers to retrieve more + detailed information when mbedtls_ssl_handshake(), + mbedtls_ssl_handshake_step(), or mbedtls_ssl_read() returns the generic + MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE error code. + * Function mbedtls_ssl_get_supported_group_list() is added to return the list + of supported groups IDs (curves and finite fields). + * MBEDTLS_SSL_IANA_TLS_GROUPS_INFO is added to allow defining the list of + mbedtls_ssl_iana_tls_group_info_t items which represent known TLS groups + with corresponding informations. + If MBEDTLS_DEBUG_C is also enabled then mbedtls_ssl_iana_tls_group_info is + also available as implementation of such list. + +Security + * The documentation of mbedtls_ssl_session_save(), + mbedtls_ssl_session_load(), mbedtls_ssl_context_save(), and + mbedtls_ssl_context_load() has been updated to clarify the responsibility + of the application to preserve the confidentiality and integrity of + serialized data, mitigating the risk of misuse of these APIs. + Credit to Haruto Kimura (Stella) and Eva Crystal (0xiviel) for + highlighting risks associated with tampered serialized data. + * Fix a NULL pointer dereference in mbedtls_x509_string_to_names() when + mbedtls_calloc() fails to allocate memory. This was caused by failing to + check whether mbedtls_calloc() returned NULL. Found and reported by + Haruto Kimura (Stella). + * Fix a limited buffer underflow in x509_inet_pton_ipv6(). In rare cases + (e.g. on platforms with memory protection when the overread crosses page + boundary) this could lead to DoS. Found and reported by Haruto Kimura + (Stella). CVE-2026-25833 + * Fix a bug in the TLS 1.2 client's signature algorithm check, which caused + the client to accept server key exchange messages signed with a signature + algorithm explicitly disallowed by the client. Found and reported by + EFR-GmbH and M. Heuft of Security-Research-Consulting GmbH. CVE-2026-25834 + * Fixed an issue in TLS 1.3 server handling of the second ClientHello, after + sending a HelloRetryRequest message. A man-in-the-middle attacker could + force a TLS 1.3 session resumption using a ticket to fall back to an + unintended TLS 1.2 session resumption with an all-zero master secret. + This could result in client authentication being bypassed and allow client + impersonation. + Found and reported by Jaehun Lee, Pohang University of Science and + Technology (POSTECH). + +Bugfix + * CMake now installs headers to `CMAKE_INSTALL_INCLUDEDIR` instead of the + hard-coded `include` directory. + * Fix CMake failure on Windows because of a native directory separator. + Fixes #10502. + * mbedtls_timing_get_delay() now correctly treats a timer as expired + after more than 2^32 ms (about 49 days) on platforms where long is + a 32-bit type. Fixes #10613. + * Support re-assembly of fragmented DTLS 1.2 ClientHello in Mbed TLS server. + * Support re-assembly of fragmented TLS 1.2 ClientHello in Mbed TLS server + even if TLS 1.3 support is disabled. This removes the main limitation on + support for re-assembly of fragmented handshake messages in TLS 1.2. + +Changes + * Add casts to some Enums to remove compiler errors thrown by IAR 6.5. + Removes Warning "mixed ENUM with other type". + * Tweak the detection of Unix-like platforms, which makes more system + interfaces (timing, threading) available on Haiku, QNX and Midipix. + * Harden mbedtls_ssl_get_verify_result() against misuse. + If the handshake has not yet been attempted, return -1u to indicate + that the result is not available. Previously the result of verification + was zero-initialized so the function would return 0 (indicating success). + = Mbed TLS 4.0.0 branch released 2025-10-15 API changes diff --git a/ChangeLog.d/alert-getter.txt b/ChangeLog.d/alert-getter.txt deleted file mode 100644 index da90cf31d7..0000000000 --- a/ChangeLog.d/alert-getter.txt +++ /dev/null @@ -1,6 +0,0 @@ -Features - * Add the function mbedtls_ssl_get_fatal_alert(), which returns the type of - the last received fatal alert. This allows callers to retrieve more - detailed information when mbedtls_ssl_handshake(), - mbedtls_ssl_handshake_step(), or mbedtls_ssl_read() returns the generic - MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE error code. diff --git a/ChangeLog.d/config_checks_generator-fix-windows-path.txt b/ChangeLog.d/config_checks_generator-fix-windows-path.txt deleted file mode 100644 index e5726cf77b..0000000000 --- a/ChangeLog.d/config_checks_generator-fix-windows-path.txt +++ /dev/null @@ -1,3 +0,0 @@ -Bugfix - * Fix CMake failure on Windows because of a native directory separator. - Fixes #10502. diff --git a/ChangeLog.d/context_load_and_session_load_documentation.txt b/ChangeLog.d/context_load_and_session_load_documentation.txt deleted file mode 100644 index dbbbda1fea..0000000000 --- a/ChangeLog.d/context_load_and_session_load_documentation.txt +++ /dev/null @@ -1,8 +0,0 @@ -Security - * The documentation of mbedtls_ssl_session_save(), - mbedtls_ssl_session_load(), mbedtls_ssl_context_save(), and - mbedtls_ssl_context_load() has been updated to clarify the responsibility - of the application to preserve the confidentiality and integrity of - serialized data, mitigating the risk of misuse of these APIs. - Credit to Haruto Kimura (Stella) and Eva Crystal (0xiviel) for - highlighting risks associated with tampered serialized data. diff --git a/ChangeLog.d/dtls-client-hello-defragmentation.txt b/ChangeLog.d/dtls-client-hello-defragmentation.txt deleted file mode 100644 index f5ff0b754c..0000000000 --- a/ChangeLog.d/dtls-client-hello-defragmentation.txt +++ /dev/null @@ -1,5 +0,0 @@ -Bugfix - * Support re-assembly of fragmented DTLS 1.2 ClientHello in Mbed TLS server. - * Support re-assembly of fragmented TLS 1.2 ClientHello in Mbed TLS server - even if TLS 1.3 support is disabled. This removes the main limitation on - support for re-assembly of fragmented handshake messages in TLS 1.2. diff --git a/ChangeLog.d/fix-null-pointer-dereference.txt b/ChangeLog.d/fix-null-pointer-dereference.txt deleted file mode 100644 index 1dd7d61905..0000000000 --- a/ChangeLog.d/fix-null-pointer-dereference.txt +++ /dev/null @@ -1,5 +0,0 @@ -Security - * Fix a NULL pointer dereference in mbedtls_x509_string_to_names() when - mbedtls_calloc() fails to allocate memory. This was caused by failing to - check whether mbedtls_calloc() returned NULL. Found and reported by - Haruto Kimura (Stella). diff --git a/ChangeLog.d/gnuinstalldirs_include.txt b/ChangeLog.d/gnuinstalldirs_include.txt deleted file mode 100644 index 7e0782d1e1..0000000000 --- a/ChangeLog.d/gnuinstalldirs_include.txt +++ /dev/null @@ -1,3 +0,0 @@ -Bugfix - * CMake now installs headers to `CMAKE_INSTALL_INCLUDEDIR` instead of the - hard-coded `include` directory. diff --git a/ChangeLog.d/iar-6.5fs.txt b/ChangeLog.d/iar-6.5fs.txt deleted file mode 100644 index 63e903b9c3..0000000000 --- a/ChangeLog.d/iar-6.5fs.txt +++ /dev/null @@ -1,3 +0,0 @@ -Changes - * Add casts to some Enums to remove compiler errors thrown by IAR 6.5. - Removes Warning "mixed ENUM with other type". diff --git a/ChangeLog.d/inet_pton.txt b/ChangeLog.d/inet_pton.txt deleted file mode 100644 index 73b9aa6b19..0000000000 --- a/ChangeLog.d/inet_pton.txt +++ /dev/null @@ -1,5 +0,0 @@ -Security - * Fix a limited buffer underflow in x509_inet_pton_ipv6(). In rare cases - (e.g. on platforms with memory protection when the overread crosses page - boundary) this could lead to DoS. Found and reported by Haruto Kimura - (Stella). CVE-2026-25833 diff --git a/ChangeLog.d/issue10349.txt b/ChangeLog.d/issue10349.txt deleted file mode 100644 index ab47659ed8..0000000000 --- a/ChangeLog.d/issue10349.txt +++ /dev/null @@ -1,8 +0,0 @@ -Features - * Function mbedtls_ssl_get_supported_group_list() is added to return the list - of supported groups IDs (curves and finite fields). - * MBEDTLS_SSL_IANA_TLS_GROUPS_INFO is added to allow defining the list of - mbedtls_ssl_iana_tls_group_info_t items which represent known TLS groups - with corresponding informations. - If MBEDTLS_DEBUG_C is also enabled then mbedtls_ssl_iana_tls_group_info is - also available as implementation of such list. diff --git a/ChangeLog.d/sig_algs_check.txt b/ChangeLog.d/sig_algs_check.txt deleted file mode 100644 index b0aed6dfd3..0000000000 --- a/ChangeLog.d/sig_algs_check.txt +++ /dev/null @@ -1,5 +0,0 @@ -Security - * Fix a bug in the TLS 1.2 client's signature algorithm check, which caused - the client to accept server key exchange messages signed with a signature - algorithm explicitly disallowed by the client. Found and reported by - EFR-GmbH and M. Heuft of Security-Research-Consulting GmbH. CVE-2026-25834 diff --git a/ChangeLog.d/timing.txt b/ChangeLog.d/timing.txt deleted file mode 100644 index b3943cdcf2..0000000000 --- a/ChangeLog.d/timing.txt +++ /dev/null @@ -1,13 +0,0 @@ -API changes - * MBEDTLS_TIMING_C now requires MBEDTLS_HAVE_TIME to be enabled in the - TF-PSA-Crypto configuration, unless MBEDTLS_TIMING_ALT is enabled. - As a benefit, platforms where the default implementation is not - supported now only need to implement MBEDTLS_PLATFORM_MS_TIME_ALT. - * When MBEDTLS_TIMING_ALT is enabled, the function - mbedtls_timing_get_timer() now returns unsigned long long instead - of unsigned long. - -Bugfix - * mbedtls_timing_get_delay() now correctly treats a timer as expired - after more than 2^32 ms (about 49 days) on platforms where long is - a 32-bit type. Fixes #10613. diff --git a/ChangeLog.d/tls12-2nd-client-hello.txt b/ChangeLog.d/tls12-2nd-client-hello.txt deleted file mode 100644 index 7513e0b945..0000000000 --- a/ChangeLog.d/tls12-2nd-client-hello.txt +++ /dev/null @@ -1,9 +0,0 @@ -Security - * Fixed an issue in TLS 1.3 server handling of the second ClientHello, after - sending a HelloRetryRequest message. A man-in-the-middle attacker could - force a TLS 1.3 session resumption using a ticket to fall back to an - unintended TLS 1.2 session resumption with an all-zero master secret. - This could result in client authentication being bypassed and allow client - impersonation. - Found and reported by Jaehun Lee, Pohang University of Science and - Technology (POSTECH). diff --git a/ChangeLog.d/unistd.txt b/ChangeLog.d/unistd.txt deleted file mode 100644 index d2e4d4301a..0000000000 --- a/ChangeLog.d/unistd.txt +++ /dev/null @@ -1,3 +0,0 @@ -Changes - * Tweak the detection of Unix-like platforms, which makes more system - interfaces (timing, threading) available on Haiku, QNX and Midipix. diff --git a/ChangeLog.d/verify-result-default-value.txt b/ChangeLog.d/verify-result-default-value.txt deleted file mode 100644 index 2cf3f0c21b..0000000000 --- a/ChangeLog.d/verify-result-default-value.txt +++ /dev/null @@ -1,5 +0,0 @@ -Changes - * Harden mbedtls_ssl_get_verify_result() against misuse. - If the handshake has not yet been attempted, return -1u to indicate - that the result is not available. Previously the result of verification - was zero-initialized so the function would return 0 (indicating success). From 0fe989b6b514192783c469039edd325fd0989806 Mon Sep 17 00:00:00 2001 From: Minos Galanakis Date: Wed, 18 Mar 2026 16:37:06 +0000 Subject: [PATCH 66/66] Update BRANCHES.md Signed-off-by: Minos Galanakis --- BRANCHES.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/BRANCHES.md b/BRANCHES.md index c781704977..8abb39cefb 100644 --- a/BRANCHES.md +++ b/BRANCHES.md @@ -11,6 +11,7 @@ At any point in time, we have a number of maintained branches, currently consist - One or more long-time support (LTS) branches: these only get bug fixes and security fixes. Currently, the supported LTS branches are: - [`mbedtls-3.6`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-3.6). +- [`mbedtls-4.1`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-4.1). We retain a number of historical branches, whose names are prefixed by `archive/`, such as [`archive/mbedtls-2.7`](https://github.com/Mbed-TLS/mbedtls/tree/archive/mbedtls-2.7). @@ -22,11 +23,11 @@ the API of 4.(x+1) is backward compatible with 4.x). We only break API compatibility on major version changes (e.g. from 3.x to 4.0). We also maintain ABI compatibility within LTS branches; see the next section for details. -We will make regular LTS releases on an 18-month cycle, each of which will have -a 3 year support lifetime. On this basis, 3.6 LTS (released March 2024) will be -supported until March 2027. The next LTS release will be a 4.x release. Due to -the size and scope of the 4.0 release, the release date of the first 4.x LTS is -yet to be determined. +We plan to make regular LTS releases on an 18-month cycle, each with a support +lifetime of three years.On this basis, Mbed TLS 3.6 LTS (released in March 2024) +will be supported until March 2027. Due to the size and scope of the 4.0 release, +the first 4.x LTS, version 4.1, was released two years after 3.6, in March 2026, +and will be supported until March 2029. ## Backwards Compatibility for application code @@ -87,6 +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.