From: Ankur Tyagi <[email protected]> Details https://nvd.nist.gov/vuln/detail/CVE-2025-13086
Signed-off-by: Ankur Tyagi <[email protected]> --- .../openvpn/openvpn/CVE-2025-13086.patch | 157 ++++++++++++++++++ .../recipes-support/openvpn/openvpn_2.6.14.bb | 1 + 2 files changed, 158 insertions(+) create mode 100644 meta-networking/recipes-support/openvpn/openvpn/CVE-2025-13086.patch diff --git a/meta-networking/recipes-support/openvpn/openvpn/CVE-2025-13086.patch b/meta-networking/recipes-support/openvpn/openvpn/CVE-2025-13086.patch new file mode 100644 index 0000000000..a37ef84a8d --- /dev/null +++ b/meta-networking/recipes-support/openvpn/openvpn/CVE-2025-13086.patch @@ -0,0 +1,157 @@ +From c56eb06a59ce8ccd601f1d58aa71cbd1211ee8d6 Mon Sep 17 00:00:00 2001 +From: Arne Schwabe <[email protected]> +Date: Mon, 27 Oct 2025 10:05:55 +0100 +Subject: [PATCH] Fix memcmp check for the hmac verification in the 3way + handshake being inverted + +This is a stupid mistake but causes all hmac cookies to be accepted, +thus breaking source IP address validation. As a consequence, TLS +sessions can be openend and state can be consumed in the server from +IP addresses that did not initiate an initial connection. + +While at it, fix check to only allow [t-2;t] timeslots, disallowing +HMACs coming in from a future timeslot. + +Github: OpenVPN/openvpn-private-issues#56 + +CVE: 2025-13086 + +Reported-By: Joshua Rogers <[email protected]> +Found-by: ZeroPath (https://zeropath.com/) +Reported-By: [email protected] + +Change-Id: I9cbe2bf535575b47ddd7f34e985c5c1c6953a6fc +Signed-off-by: Arne Schwabe <[email protected]> +Acked-by: Max Fillinger <[email protected]> +(cherry picked from commit 68ec931e7fb4af11d5ba0d4283df0350083fd373) + +CVE: CVE-2025-13086 +Upstream-Status: Backport [https://github.com/OpenVPN/openvpn/commit/fa6a1824b0f37bff137204156a74ca28cf5b6f83] +Signed-off-by: Ankur Tyagi <[email protected]> +--- + src/openvpn/ssl_pkt.c | 7 ++-- + tests/unit_tests/openvpn/test_pkt.c | 57 ++++++++++++++++++++++++++++- + 2 files changed, 60 insertions(+), 4 deletions(-) + +diff --git a/src/openvpn/ssl_pkt.c b/src/openvpn/ssl_pkt.c +index 41299f46..e820dc93 100644 +--- a/src/openvpn/ssl_pkt.c ++++ b/src/openvpn/ssl_pkt.c +@@ -545,13 +545,14 @@ check_session_id_hmac(struct tls_pre_decrypt_state *state, + return false; + } + +- /* check adjacent timestamps too */ +- for (int offset = -2; offset <= 1; offset++) ++ /* check adjacent timestamps too, the handwindow is split in 2 for the ++ * offset, so we check the current timeslot and the two before that */ ++ for (int offset = -2; offset <= 0; offset++) + { + struct session_id expected_id = + calculate_session_id_hmac(state->peer_session_id, from, hmac, handwindow, offset); + +- if (memcmp_constant_time(&expected_id, &state->server_session_id, SID_SIZE)) ++ if (memcmp_constant_time(&expected_id, &state->server_session_id, SID_SIZE) == 0) + { + return true; + } +diff --git a/tests/unit_tests/openvpn/test_pkt.c b/tests/unit_tests/openvpn/test_pkt.c +index 74d7311f..4e97384d 100644 +--- a/tests/unit_tests/openvpn/test_pkt.c ++++ b/tests/unit_tests/openvpn/test_pkt.c +@@ -429,6 +429,8 @@ test_verify_hmac_tls_auth(void **ut_state) + hmac_ctx_t *hmac = session_id_hmac_init(); + + struct link_socket_actual from = { 0 }; ++ from.dest.addr.sa.sa_family = AF_INET; ++ from.dest.addr.in4.sin_addr.s_addr = ntohl(0x01020304); + struct tls_auth_standalone tas = { 0 }; + struct tls_pre_decrypt_state state = { 0 }; + +@@ -456,10 +458,12 @@ test_verify_hmac_tls_auth(void **ut_state) + static void + test_verify_hmac_none(void **ut_state) + { ++ now = 1000; + hmac_ctx_t *hmac = session_id_hmac_init(); + + struct link_socket_actual from = { 0 }; + from.dest.addr.sa.sa_family = AF_INET; ++ from.dest.addr.in4.sin_addr.s_addr = ntohl(0x01020304); + + struct tls_auth_standalone tas = { 0 }; + struct tls_pre_decrypt_state state = { 0 }; +@@ -475,8 +479,59 @@ test_verify_hmac_none(void **ut_state) + assert_int_equal(verdict, VERDICT_VALID_ACK_V1); + + bool valid = check_session_id_hmac(&state, &from.dest, hmac, 30); ++ assert_false(valid); ++ ++ struct session_id client_id = { { 0xae, 0xb9, 0xaf, 0xe1, 0xf0, 0x1d, 0x79, 0xc8 } }; ++ assert_memory_equal(&client_id, &state.peer_session_id, sizeof(struct session_id)); ++ ++ struct session_id expected_id = calculate_session_id_hmac(client_id, &from.dest, hmac, 30, 0); ++ ++ free_tls_pre_decrypt_state(&state); ++ buf_reset_len(&buf); ++ ++ /* Write the packet again into the buffer but this time, replacing the peer packet ++ * id with the expected one */ ++ buf_write(&buf, client_ack_none_random_id, sizeof(client_ack_none_random_id) - 8); ++ buf_write(&buf, expected_id.id, 8); ++ ++ verdict = tls_pre_decrypt_lite(&tas, &state, &from, &buf); ++ assert_int_equal(verdict, VERDICT_VALID_ACK_V1); ++ valid = check_session_id_hmac(&state, &from.dest, hmac, 30); ++ + assert_true(valid); + ++ /* Our handwindow is 30 so the slices are half of that, so they are ++ * (975,990), (990, 1005), (1005, 1020), (1020, 1035), (1035, 1050) ++ * So setting time to the two future ones should work ++ */ ++ now = 980; ++ assert_false(check_session_id_hmac(&state, &from.dest, hmac, 30)); ++ now = 1040; ++ assert_false(check_session_id_hmac(&state, &from.dest, hmac, 30)); ++ now = 1002; ++ assert_true(check_session_id_hmac(&state, &from.dest, hmac, 30)); ++ now = 1022; ++ assert_true(check_session_id_hmac(&state, &from.dest, hmac, 30)); ++ now = 1010; ++ assert_true(check_session_id_hmac(&state, &from.dest, hmac, 30)); ++ ++ /* Changing the IP address should make this invalid */ ++ from.dest.addr.in4.sin_addr.s_addr = ntohl(0x01020305); ++ assert_false(check_session_id_hmac(&state, &from.dest, hmac, 30)); ++ ++ /* Change to the correct one again */ ++ from.dest.addr.in4.sin_addr.s_addr = ntohl(0x01020304); ++ assert_true(check_session_id_hmac(&state, &from.dest, hmac, 30)); ++ ++ /* Modify the peer id, should now fail hmac verification */ ++ buf_inc_len(&buf, -4); ++ buf_write_u32(&buf, 0x12345678); ++ ++ free_tls_pre_decrypt_state(&state); ++ verdict = tls_pre_decrypt_lite(&tas, &state, &from, &buf); ++ assert_int_equal(verdict, VERDICT_VALID_ACK_V1); ++ assert_false(check_session_id_hmac(&state, &from.dest, hmac, 30)); ++ + free_tls_pre_decrypt_state(&state); + free_buf(&buf); + hmac_ctx_cleanup(hmac); +@@ -663,12 +718,12 @@ int + main(void) + { + const struct CMUnitTest tests[] = { ++ cmocka_unit_test(test_verify_hmac_none), + cmocka_unit_test(test_tls_decrypt_lite_none), + cmocka_unit_test(test_tls_decrypt_lite_auth), + cmocka_unit_test(test_tls_decrypt_lite_crypt), + cmocka_unit_test(test_parse_ack), + cmocka_unit_test(test_calc_session_id_hmac_static), +- cmocka_unit_test(test_verify_hmac_none), + cmocka_unit_test(test_verify_hmac_tls_auth), + cmocka_unit_test(test_generate_reset_packet_plain), + cmocka_unit_test(test_generate_reset_packet_tls_auth), diff --git a/meta-networking/recipes-support/openvpn/openvpn_2.6.14.bb b/meta-networking/recipes-support/openvpn/openvpn_2.6.14.bb index 5361709f0c..305a69bec4 100644 --- a/meta-networking/recipes-support/openvpn/openvpn_2.6.14.bb +++ b/meta-networking/recipes-support/openvpn/openvpn_2.6.14.bb @@ -10,6 +10,7 @@ inherit autotools systemd update-rc.d pkgconfig SRC_URI = "http://swupdate.openvpn.org/community/releases/${BP}.tar.gz \ file://0001-configure.ac-eliminate-build-path-from-openvpn-versi.patch \ file://openvpn \ + file://CVE-2025-13086.patch \ " UPSTREAM_CHECK_URI = "https://openvpn.net/community-downloads"
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#122685): https://lists.openembedded.org/g/openembedded-devel/message/122685 Mute This Topic: https://lists.openembedded.org/mt/116806383/21656 Group Owner: [email protected] Unsubscribe: https://lists.openembedded.org/g/openembedded-devel/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
