diff --git a/libreswan-5.3-outstanding-ike-auth-crossing.patch b/libreswan-5.3-outstanding-ike-auth-crossing.patch index 754161a..cccf3a7 100644 --- a/libreswan-5.3-outstanding-ike-auth-crossing.patch +++ b/libreswan-5.3-outstanding-ike-auth-crossing.patch @@ -1,7 +1,7 @@ -From a671b9ce5ff86ffc31142436e9c93031083d7221 Mon Sep 17 00:00:00 2001 +From f58dec967328c9b11b834c42b1506e2d261d8bb2 Mon Sep 17 00:00:00 2001 From: Ondrej Moris Date: Fri, 21 Nov 2025 22:42:33 +0100 -Subject: [PATCH 1/5] Add option reject-simultaneous-ike-auth +Subject: [PATCH 1/7] Add option reject-simultaneous-ike-auth Newly added option (default values is yes) decides what to do when IKE_AUTH request is received from the peer while having @@ -190,10 +190,10 @@ index a5a95045bf..5e47e009b8 100644 2.52.0 -From 6d1d06ef085cbdfdfeb24f677cec9d4540db2903 Mon Sep 17 00:00:00 2001 +From 31ce0692217e18c3e5ed6cc2cded7c937b7ae1c9 Mon Sep 17 00:00:00 2001 From: Ondrej Moris -Date: Fri, 21 Nov 2025 22:42:33 +0100 -Subject: [PATCH 2/5] ikev2: reject simultaneous IKE_AUTH requests +Date: Fri, 13 Mar 2026 15:00:05 +0100 +Subject: [PATCH 2/7] ikev2: reject simultaneous IKE_AUTH requests If initiator has another IKE SA with IKE_AUTH request outstanding for the same permanent connection then send @@ -209,8 +209,8 @@ Signed-off-by: Ondrej Moris programs/pluto/ikev2_auth.c | 53 +++++++++++++++++++++++++++++++++ programs/pluto/ikev2_auth.h | 3 ++ programs/pluto/ikev2_child.c | 13 ++++++++ - programs/pluto/ikev2_ike_auth.c | 15 +++++++++- - 4 files changed, 83 insertions(+), 1 deletion(-) + programs/pluto/ikev2_ike_auth.c | 13 ++++++++ + 4 files changed, 82 insertions(+) diff --git a/programs/pluto/ikev2_auth.c b/programs/pluto/ikev2_auth.c index 6e89bce58b..2e1b6df655 100644 @@ -286,17 +286,17 @@ index 13ee71c36d..d616534507 100644 + const struct msg_digest *md); #endif diff --git a/programs/pluto/ikev2_child.c b/programs/pluto/ikev2_child.c -index 49aaff98a2..5b2c0d7028 100644 +index 49aaff98a2..e53f53f4b3 100644 --- a/programs/pluto/ikev2_child.c +++ b/programs/pluto/ikev2_child.c -@@ -66,6 +66,7 @@ - #include "ikev2_parent.h" - #include "ikev2_states.h" +@@ -68,6 +68,7 @@ #include "ikev2_notification.h" -+#include "ikev2_auth.h" #include "iface.h" #include "nat_traversal.h" ++#include "ikev2_auth.h" + static bool emit_v2_child_response_payloads(struct ike_sa *ike, + const struct child_sa *child, @@ -1029,6 +1030,18 @@ static v2_notification_t process_v2_IKE_AUTH_request_child_sa_payloads(struct ik ldbg_sa(child, "skipping TS processing, mainly to stop tests failing but rumored to cause connection flips?!?"); } @@ -317,14 +317,13 @@ index 49aaff98a2..5b2c0d7028 100644 ike, child, md, child->sa.st_connection->config->child_sa.v2_ike_auth_proposals, diff --git a/programs/pluto/ikev2_ike_auth.c b/programs/pluto/ikev2_ike_auth.c -index ba5aeace88..08f7c79739 100644 +index ba5aeace88..f70c06e9ef 100644 --- a/programs/pluto/ikev2_ike_auth.c +++ b/programs/pluto/ikev2_ike_auth.c -@@ -674,6 +674,20 @@ stf_status process_v2_IKE_AUTH_request_standard_payloads(struct ike_sa *ike, str - return STF_FATAL; - } +@@ -683,6 +683,19 @@ stf_status process_v2_IKE_AUTH_request_standard_payloads(struct ike_sa *ike, str + */ -+ const struct connection *c = ike->sa.st_connection; + const struct connection *c = ike->sa.st_connection; + + /* If initiator has another IKE SA with IKE_AUTH request + * outstanding for the same permanent connection then send @@ -338,14 +337,6 @@ index ba5aeace88..08f7c79739 100644 + return STF_FATAL; + } + - /* - * This both decodes the initiator's ID and, when necessary, - * switches connection based on that ID. -@@ -682,7 +696,6 @@ stf_status process_v2_IKE_AUTH_request_standard_payloads(struct ike_sa *ike, str - * switch based on the contents of the CERTREQ. - */ - -- const struct connection *c = ike->sa.st_connection; bool found_ppk = false; /* @@ -353,10 +344,10 @@ index ba5aeace88..08f7c79739 100644 2.52.0 -From 437d0ff3a4b32b22b2272347881f49a333e9ffbf Mon Sep 17 00:00:00 2001 +From 877c8c9c2fd963bb23842cdddf798b34f7e6d42f Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Sat, 17 Jan 2026 13:28:39 +0900 -Subject: [PATCH 3/5] pluto: reject crossing IKE_AUTH request only for the one +Subject: [PATCH 3/7] pluto: reject crossing IKE_AUTH request only for the one side When an IKE_AUTH request is crossed, both sides previously rejected it @@ -368,12 +359,12 @@ Suggested-by: Ondrej Moris Signed-off-by: Daiki Ueno --- include/ike_spi.h | 1 + - programs/pluto/ike_spi.c | 11 +++++++++++ - programs/pluto/ikev2_auth.c | 10 +++++----- + programs/pluto/ike_spi.c | 11 ++++++++++ + programs/pluto/ikev2_auth.c | 10 ++++----- programs/pluto/ikev2_auth.h | 2 +- - programs/pluto/ikev2_child.c | 35 +++++++++++++++++++++++++++++---- - programs/pluto/ikev2_ike_auth.c | 35 +++++++++++++++++++++++++++++---- - 6 files changed, 80 insertions(+), 14 deletions(-) + programs/pluto/ikev2_child.c | 35 ++++++++++++++++++++++++++++---- + programs/pluto/ikev2_ike_auth.c | 36 +++++++++++++++++++++++++++++---- + 6 files changed, 81 insertions(+), 14 deletions(-) diff --git a/include/ike_spi.h b/include/ike_spi.h index 0c05542bae..376c120c0e 100644 @@ -460,13 +451,13 @@ index d616534507..bb659ce88f 100644 const struct msg_digest *md); #endif diff --git a/programs/pluto/ikev2_child.c b/programs/pluto/ikev2_child.c -index 5b2c0d7028..63df00956f 100644 +index e53f53f4b3..09b5862cd0 100644 --- a/programs/pluto/ikev2_child.c +++ b/programs/pluto/ikev2_child.c @@ -69,6 +69,7 @@ - #include "ikev2_auth.h" #include "iface.h" #include "nat_traversal.h" + #include "ikev2_auth.h" +#include "terminate.h" static bool emit_v2_child_response_payloads(struct ike_sa *ike, @@ -513,18 +504,19 @@ index 5b2c0d7028..63df00956f 100644 n = process_childs_v2SA_payload("IKE_AUTH responder matching remote ESP/AH proposals", diff --git a/programs/pluto/ikev2_ike_auth.c b/programs/pluto/ikev2_ike_auth.c -index 08f7c79739..acd268e89a 100644 +index f70c06e9ef..406469dc75 100644 --- a/programs/pluto/ikev2_ike_auth.c +++ b/programs/pluto/ikev2_ike_auth.c -@@ -76,6 +76,7 @@ +@@ -76,6 +76,8 @@ #include "ikev2_notification.h" #include "peer_id.h" #include "ddos.h" ++#include "ikev2_nat.h" +#include "terminate.h" static ikev2_state_transition_fn process_v2_IKE_AUTH_request; -@@ -682,10 +683,36 @@ stf_status process_v2_IKE_AUTH_request_standard_payloads(struct ike_sa *ike, str +@@ -690,10 +692,36 @@ stf_status process_v2_IKE_AUTH_request_standard_payloads(struct ike_sa *ike, str * IKE_AUTH request and terminate current IKE SA. This is to * prevent potential crossing streams scenario. */ @@ -564,15 +556,15 @@ index 08f7c79739..acd268e89a 100644 + } } - /* + bool found_ppk = false; -- 2.52.0 -From e812e32c2d58d0a96ebfb38cd5a03ea4bf99161e Mon Sep 17 00:00:00 2001 +From f35e32abc6b1e8d027ce811f0954f4b5de618f68 Mon Sep 17 00:00:00 2001 From: Ondrej Moris Date: Sun, 25 Jan 2026 19:41:25 +0100 -Subject: [PATCH 4/5] ikev2: refactor simultaneous IKE_AUTH logic +Subject: [PATCH 4/7] ikev2: refactor simultaneous IKE_AUTH logic 1. Moved decision which IKE to reject into the function. 2. Renamed function to better capture its new structure. @@ -586,7 +578,7 @@ Signed-off-by: Ondrej Moris 4 files changed, 80 insertions(+), 93 deletions(-) diff --git a/programs/pluto/ikev2_auth.c b/programs/pluto/ikev2_auth.c -index ee36ef8b03..f0c08fb27f 100644 +index ee36ef8b03..3c61e45cdd 100644 --- a/programs/pluto/ikev2_auth.c +++ b/programs/pluto/ikev2_auth.c @@ -1046,13 +1046,23 @@ lset_t proposed_v2AUTH(struct ike_sa *ike, @@ -687,11 +679,11 @@ index ee36ef8b03..f0c08fb27f 100644 + */ + if (ike_spis_gt(&simultaneous_ike->sa.st_ike_spis, &ike->sa.st_ike_spis)) { + ldbg(ike->sa.logger, "preferring the simultaneous IKE SA "PRI_SO" over the current IKE SA "PRI_SO, -+ pri_so(simultaneous_ike->sa.st_serialno), pri_so(ike->sa.st_serialno)); ++ pri_so(simultaneous_ike->sa.st_serialno), pri_so(ike->sa.st_serialno)); + return (struct ike_sa *) ike; -+ } else { ++ } else { + ldbg(ike->sa.logger, "preferring the current IKE SA "PRI_SO" over the simultanoues IKE SA "PRI_SO"", -+ pri_so(ike->sa.st_serialno), pri_so(simultaneous_ike->sa.st_serialno)); ++ pri_so(ike->sa.st_serialno), pri_so(simultaneous_ike->sa.st_serialno)); + return simultaneous_ike; + } } @@ -711,7 +703,7 @@ index bb659ce88f..1c25479ed7 100644 + const struct msg_digest *md); #endif diff --git a/programs/pluto/ikev2_child.c b/programs/pluto/ikev2_child.c -index 63df00956f..1205622b27 100644 +index 09b5862cd0..9763112ddf 100644 --- a/programs/pluto/ikev2_child.c +++ b/programs/pluto/ikev2_child.c @@ -1032,41 +1032,19 @@ static v2_notification_t process_v2_IKE_AUTH_request_child_sa_payloads(struct ik @@ -768,10 +760,10 @@ index 63df00956f..1205622b27 100644 n = process_childs_v2SA_payload("IKE_AUTH responder matching remote ESP/AH proposals", diff --git a/programs/pluto/ikev2_ike_auth.c b/programs/pluto/ikev2_ike_auth.c -index acd268e89a..fc35ecc200 100644 +index 406469dc75..c9eb40e420 100644 --- a/programs/pluto/ikev2_ike_auth.c +++ b/programs/pluto/ikev2_ike_auth.c -@@ -678,41 +678,18 @@ stf_status process_v2_IKE_AUTH_request_standard_payloads(struct ike_sa *ike, str +@@ -687,41 +687,18 @@ stf_status process_v2_IKE_AUTH_request_standard_payloads(struct ike_sa *ike, str const struct connection *c = ike->sa.st_connection; /* If initiator has another IKE SA with IKE_AUTH request @@ -822,15 +814,15 @@ index acd268e89a..fc35ecc200 100644 + terminate_ike_family(&ike_to_reject, REASON_SUPERSEDED_BY_NEW_SA, HERE); } - /* + bool found_ppk = false; -- 2.52.0 -From 47fc2d3bb650d4ecfd066ab04ebc454bcefb91d1 Mon Sep 17 00:00:00 2001 +From c956e30d304ac460559116dbf53487ebd2696f8a Mon Sep 17 00:00:00 2001 From: Ondrej Moris Date: Sun, 25 Jan 2026 19:46:45 +0100 -Subject: [PATCH 5/5] ikev2: extend check for simultaneous IKE_AUTH +Subject: [PATCH 5/7] ikev2: extend check for simultaneous IKE_AUTH On initiator, if simultaneous IKE receives IKE_AUTH response shortly before the current IKE_AUTH request is received, @@ -842,11 +834,11 @@ one will be dropped. Signed-off-by: Ondrej Moris --- - programs/pluto/ikev2_auth.c | 21 +++++++++++++++++++-- - 1 file changed, 19 insertions(+), 2 deletions(-) + programs/pluto/ikev2_auth.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/programs/pluto/ikev2_auth.c b/programs/pluto/ikev2_auth.c -index f0c08fb27f..c1fed3bcdd 100644 +index 3c61e45cdd..10d583b4c1 100644 --- a/programs/pluto/ikev2_auth.c +++ b/programs/pluto/ikev2_auth.c @@ -1054,6 +1054,7 @@ lset_t proposed_v2AUTH(struct ike_sa *ike, @@ -865,7 +857,7 @@ index f0c08fb27f..c1fed3bcdd 100644 + /* Was candidate established within the last second of the current IKE_AUTH request arrival? */ + if (candidate->sa.st_state->kind == STATE_V2_ESTABLISHED_IKE_SA) { + deltatime_t age = monotime_diff(mononow(), candidate->sa.st_v2_msgid_windows.initiator.last_recv); -+ if (deltatime_cmp(age, <, deltatime(1))) { ++ if (deltatime_cmp(age, <, one_second)) { + llog(RC_LOG, ike->sa.logger, "IKE SA "PRI_SO" recently established", + pri_so(candidate->sa.st_serialno)); + simultaneous_ike = candidate; @@ -875,7 +867,7 @@ index f0c08fb27f..c1fed3bcdd 100644 } /* No simultaneous IKE found */ -@@ -1117,9 +1129,14 @@ struct ike_sa *check_simultaneous_ike_auth(const struct connection *c, +@@ -1117,8 +1129,15 @@ struct ike_sa *check_simultaneous_ike_auth(const struct connection *c, /* Simultaneous IKE found, we need to decide if we keep that one or current IKE. * @@ -883,15 +875,182 @@ index f0c08fb27f..c1fed3bcdd 100644 + * If simultaneous IKE is already established, we keep it. Otherwise we keep one + * with higher SPI. */ -- if (ike_spis_gt(&simultaneous_ike->sa.st_ike_spis, &ike->sa.st_ike_spis)) { + if (simultaneous_ike->sa.st_state->kind == STATE_V2_ESTABLISHED_IKE_SA) { + llog(RC_LOG, ike->sa.logger, "rejecting IKE_AUTH request; IKE SA "PRI_SO" already established", -+ pri_so(simultaneous_ike->sa.st_serialno)); ++ pri_so(simultaneous_ike->sa.st_serialno)); + return (struct ike_sa *) ike; -+ } else if (ike_spis_gt(&simultaneous_ike->sa.st_ike_spis, &ike->sa.st_ike_spis)) { ++ } ++ + if (ike_spis_gt(&simultaneous_ike->sa.st_ike_spis, &ike->sa.st_ike_spis)) { ldbg(ike->sa.logger, "preferring the simultaneous IKE SA "PRI_SO" over the current IKE SA "PRI_SO, - pri_so(simultaneous_ike->sa.st_serialno), pri_so(ike->sa.st_serialno)); + pri_so(simultaneous_ike->sa.st_serialno), pri_so(ike->sa.st_serialno)); +-- +2.52.0 + + +From 182a09854935d505aa8cb5cfd7843bd133508452 Mon Sep 17 00:00:00 2001 +From: Ondrej Moris +Date: Tue, 24 Feb 2026 12:59:29 +0100 +Subject: [PATCH 6/7] ikev2: use nonces to tie-break simultaneous IKE + +Previously, SPI was used to tie-break simultaneous IKE_AUTH +request. Using nonces follows RFC 7296 better. + +Signed-off-by: Ondrej Moris +--- + include/ike_spi.h | 1 - + programs/pluto/ike_spi.c | 11 ----------- + programs/pluto/ikev2_auth.c | 4 ++-- + 3 files changed, 2 insertions(+), 14 deletions(-) + +diff --git a/include/ike_spi.h b/include/ike_spi.h +index 376c120c0e..0c05542bae 100644 +--- a/include/ike_spi.h ++++ b/include/ike_spi.h +@@ -39,7 +39,6 @@ typedef struct { + } ike_spis_t; + + bool ike_spis_eq(const ike_spis_t *lhs, const ike_spis_t *rhs); +-bool ike_spis_gt(const ike_spis_t *lhs, const ike_spis_t *rhs); + + /* + * Need to handle two cases: +diff --git a/programs/pluto/ike_spi.c b/programs/pluto/ike_spi.c +index d7bb73a6e8..312c835bed 100644 +--- a/programs/pluto/ike_spi.c ++++ b/programs/pluto/ike_spi.c +@@ -42,17 +42,6 @@ bool ike_spis_eq(const ike_spis_t *lhs, const ike_spis_t *rhs) + ike_spi_eq(&lhs->responder, &rhs->responder)); + } + +-bool ike_spis_gt(const ike_spis_t *lhs, const ike_spis_t *rhs) +-{ +- int d = memcmp(lhs->initiator.bytes, rhs->initiator.bytes, +- sizeof(lhs->initiator.bytes)); +- if (d == 0) { +- d = memcmp(lhs->responder.bytes, rhs->responder.bytes, +- sizeof(lhs->responder.bytes)); +- } +- return d > 0; +-} +- + static struct { + uint8_t bytes[SHA2_256_DIGEST_SIZE]; + } ike_spi_secret; +diff --git a/programs/pluto/ikev2_auth.c b/programs/pluto/ikev2_auth.c +index 10d583b4c1..7785860995 100644 +--- a/programs/pluto/ikev2_auth.c ++++ b/programs/pluto/ikev2_auth.c +@@ -1130,7 +1130,7 @@ struct ike_sa *check_simultaneous_ike_auth(const struct connection *c, + /* Simultaneous IKE found, we need to decide if we keep that one or current IKE. + * + * If simultaneous IKE is already established, we keep it. Otherwise we keep one +- * with higher SPI. ++ * with higher nonce. + */ + if (simultaneous_ike->sa.st_state->kind == STATE_V2_ESTABLISHED_IKE_SA) { + llog(RC_LOG, ike->sa.logger, "rejecting IKE_AUTH request; IKE SA "PRI_SO" already established", +@@ -1138,7 +1138,7 @@ struct ike_sa *check_simultaneous_ike_auth(const struct connection *c, + return (struct ike_sa *) ike; + } + +- if (ike_spis_gt(&simultaneous_ike->sa.st_ike_spis, &ike->sa.st_ike_spis)) { ++ if (hunk_cmp(simultaneous_ike->sa.st_ni, ike->sa.st_ni) > 0) { + ldbg(ike->sa.logger, "preferring the simultaneous IKE SA "PRI_SO" over the current IKE SA "PRI_SO, + pri_so(simultaneous_ike->sa.st_serialno), pri_so(ike->sa.st_serialno)); return (struct ike_sa *) ike; -- 2.52.0 + +From be59b08e8f88937ae513c65902ce1af97f7a1eb3 Mon Sep 17 00:00:00 2001 +From: Ondrej Moris +Date: Tue, 24 Feb 2026 14:54:35 +0100 +Subject: [PATCH 7/7] impair: add impair option for setting nonces + +New impair options 'impair_initiator_nonce' and 'impair_responder_nonce' +allow setting all 32 bytes of nonce to specified value, e.g. to set high +nonce value one can use 'impair ike_initiator_nonce:0xff'. This might be +useful for testing. + +Signed-off-by: Ondrej Moris +--- + include/impair.h | 2 ++ + lib/libswan/impair.c | 2 ++ + programs/pluto/crypt_ke.c | 14 ++++++++++++++ + 3 files changed, 18 insertions(+) + +diff --git a/include/impair.h b/include/impair.h +index d3b2b68b3d..e6897e18d6 100644 +--- a/include/impair.h ++++ b/include/impair.h +@@ -111,6 +111,8 @@ struct impair { + + struct impair_unsigned ike_initiator_spi; + struct impair_unsigned ike_responder_spi; ++ struct impair_unsigned ike_initiator_nonce; ++ struct impair_unsigned ike_responder_nonce; + + bool bust_mi2; + bool bust_mr2; +diff --git a/lib/libswan/impair.c b/lib/libswan/impair.c +index 9e7cd829de..ba28d6420b 100644 +--- a/lib/libswan/impair.c ++++ b/lib/libswan/impair.c +@@ -210,6 +210,8 @@ struct impairment impairments[] = { + + U(ike_initiator_spi, "corrupt the IKE initiator SPI setting it to the value"), + U(ike_responder_spi, "corrupt the IKE responder SPI setting it to the value"), ++ U(ike_initiator_nonce, "corrupt the IKE initiator nonce setting it to the "), ++ U(ike_responder_nonce, "corrupt the IKE responder nonce setting it to the "), + + B(ikev1_del_with_notify, "causes pluto to send IKE Delete with additional bogus Notify payload"), + +diff --git a/programs/pluto/crypt_ke.c b/programs/pluto/crypt_ke.c +index 1d7dfd5ad5..8535a350fc 100644 +--- a/programs/pluto/crypt_ke.c ++++ b/programs/pluto/crypt_ke.c +@@ -52,12 +52,14 @@ + #include "ike_alg.h" + #include "crypt_dh.h" + #include "crypt_ke.h" ++#include "impair.h" + + struct task { + const struct dh_desc *dh; + chunk_t nonce; + struct dh_local_secret *local_secret; + ke_and_nonce_cb *cb; ++ enum sa_role role; + }; + + static void compute_ke_and_nonce(struct logger *logger, +@@ -72,6 +74,17 @@ static void compute_ke_and_nonce(struct logger *logger, + } + } + task->nonce = alloc_rnd_chunk(DEFAULT_NONCE_SIZE, "nonce"); ++ ++ if (impair.ike_initiator_nonce.enabled && task->role == SA_INITIATOR) { ++ uint8_t pattern = (uint8_t)impair.ike_initiator_nonce.value; ++ memset(task->nonce.ptr, pattern, task->nonce.len); ++ llog(RC_LOG, logger, "IMPAIR: forcing IKE initiator nonce to all 0x%02x bytes", pattern); ++ } else if (impair.ike_responder_nonce.enabled && task->role == SA_RESPONDER) { ++ uint8_t pattern = (uint8_t)impair.ike_responder_nonce.value; ++ memset(task->nonce.ptr, pattern, task->nonce.len); ++ llog(RC_LOG, logger, "IMPAIR: forcing IKE responder nonce to all 0x%02x bytes", pattern); ++ } ++ + if (LDBGP(DBG_CRYPT, logger)) { + LDBG_log_hunk(logger, "generated nonce:", task->nonce); + } +@@ -112,6 +125,7 @@ void submit_ke_and_nonce(struct state *callback_sa, + struct task *task = alloc_thing(struct task, "dh"); + task->dh = dh; + task->cb = cb; ++ task->role = task_sa->st_sa_role; + submit_task(/*callback*/callback_sa, /*task*/task_sa, md, detach_whack, + task, &ke_and_nonce_handler, where); + } +-- +2.52.0 +