From db3e6ebebee5a2654d332a389a59e91ab9ddc873 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 2 Oct 2025 15:52:59 +0100 Subject: [PATCH 1/6] 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 658b4f637a..2b65f66653 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -1178,6 +1178,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:MBEDTLS_MD_CAN_SHA1: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 be0cef43eab3818c0b8d52c10350cea21cc280f1 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 2 Oct 2025 15:53:56 +0100 Subject: [PATCH 2/6] Add ASan to test_sw_inet_pton Signed-off-by: Janos Follath --- tests/scripts/components-configuration-x509.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/scripts/components-configuration-x509.sh b/tests/scripts/components-configuration-x509.sh index 800d98ed69..78104b48e1 100644 --- a/tests/scripts/components-configuration-x509.sh +++ b/tests/scripts/components-configuration-x509.sh @@ -28,7 +28,8 @@ component_test_sw_inet_pton () { # MBEDTLS_TEST_HOOKS required for x509_crt_parse_cn_inet_pton scripts/config.py set MBEDTLS_TEST_HOOKS - make 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 test From 763a0cfd159030da6d29808541a22f05dbb6f433 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 20 Jan 2026 18:19:33 +0000 Subject: [PATCH 3/6] 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 9fc0e55dff..a35a03f540 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -482,12 +482,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 4595bb47d27c2aae522c54eca28605f270ab5f5a Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 20 Jan 2026 18:46:52 +0000 Subject: [PATCH 4/6] 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 53cdcf0266..ba87e67bcf 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2748,8 +2748,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 51fc6428ebd2dec1431187ab844b40e872ba1f75 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 21 Jan 2026 09:16:07 +0000 Subject: [PATCH 5/6] 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 72e18e003297c6f06dd87b207b332b710a6ce20a Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 21 Jan 2026 17:29:07 +0000 Subject: [PATCH 6/6] 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 ba87e67bcf..f15aa99d5d 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2758,16 +2758,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,