mirror of
git://git.openembedded.org/meta-openembedded
synced 2026-01-01 13:58:06 +00:00
openvpn: patch CVE-2025-13086
Details https://nvd.nist.gov/vuln/detail/CVE-2025-13086 Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com> Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
parent
c42bfd596e
commit
86abe3d5de
|
|
@ -0,0 +1,157 @@
|
|||
From c56eb06a59ce8ccd601f1d58aa71cbd1211ee8d6 Mon Sep 17 00:00:00 2001
|
||||
From: Arne Schwabe <arne@rfc2549.org>
|
||||
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 <contact@joshua.hu>
|
||||
Found-by: ZeroPath (https://zeropath.com/)
|
||||
Reported-By: stefan@srlabs.de
|
||||
|
||||
Change-Id: I9cbe2bf535575b47ddd7f34e985c5c1c6953a6fc
|
||||
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
|
||||
Acked-by: Max Fillinger <max@max-fillinger.net>
|
||||
(cherry picked from commit 68ec931e7fb4af11d5ba0d4283df0350083fd373)
|
||||
|
||||
CVE: CVE-2025-13086
|
||||
Upstream-Status: Backport [https://github.com/OpenVPN/openvpn/commit/fa6a1824b0f37bff137204156a74ca28cf5b6f83]
|
||||
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
|
||||
---
|
||||
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),
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user