[Pkg-swan-devel] [Git][debian/strongswan][debian/bookworm] 12 commits: d/patch: fix integer overflow in EAP-TTLS plugin (CVE-2026-25075)

Yves-Alexis Perez (@corsac) gitlab at salsa.debian.org
Sun Apr 26 10:11:02 BST 2026



Yves-Alexis Perez pushed to branch debian/bookworm at Debian / strongswan


Commits:
a38a2bda by Yves-Alexis Perez at 2026-03-18T08:52:51+01:00
d/patch: fix integer overflow in EAP-TTLS plugin (CVE-2026-25075)

- - - - -
0ec1d539 by Yves-Alexis Perez at 2026-03-18T08:53:09+01:00
finalize changelog

- - - - -
89f72384 by Yves-Alexis Perez at 2026-03-18T08:56:49+01:00
upload strongSwan 5.9.8-5+deb12u3 to bookworm-security

- - - - -
e93db378 by Yves-Alexis Perez at 2026-04-11T15:56:38+02:00
d/patches: add fix for integer underflow in libsimaka when handling EAP-SIM/AKA attributes (CVE-2026-35330)

- - - - -
29c4c175 by Yves-Alexis Perez at 2026-04-11T15:57:21+02:00
d/patches: add fix for integer underflow in libradius when handling RADIUS attributes (CVE-2026-35333)

- - - - -
06a42d75 by Yves-Alexis Perez at 2026-04-11T15:57:54+02:00
d/patches: add fix for NULL-pointer dereference in libtls when handling ECDH public values (CVE-2026-35332)

- - - - -
c3a59193 by Yves-Alexis Perez at 2026-04-11T15:58:29+02:00
d/patches: add fix for infinite loop in libtls when handling supported versions TLS extension (CVE-2026-35328)

- - - - -
1d560c69 by Yves-Alexis Perez at 2026-04-11T15:59:02+02:00
d/patches: add fix for NULL-pointer dereference in libstrongswan (pkcs5) and the pkcs7 plugin when processing padding in PKCS#7 (CVE-2026-35329)

- - - - -
2e8f60cc by Yves-Alexis Perez at 2026-04-13T10:53:44+02:00
d/patches: add fix for acceptation of authentication certificates violating name constraints (CVE-2026-35331)

- - - - -
50c5137b by Yves-Alexis Perez at 2026-04-13T10:53:44+02:00
d/patches: add fix for possible NULL-pointer dereference in gmp plugin for RSA decryption (CVE-2026-35334)

- - - - -
59d41a65 by Yves-Alexis Perez at 2026-04-13T10:53:44+02:00
finalize changelog

- - - - -
ba3f4829 by Yves-Alexis Perez at 2026-04-13T11:19:28+02:00
upload strongSwan 5.9.8-5+deb12u4 to bookworm-security

- - - - -


10 changed files:

- debian/changelog
- + debian/patches/0008-eap-ttls-Prevent-crash-if-AVP-length-header-field-is.patch
- + debian/patches/0009-libsimaka-Reject-zero-length-EAP-SIM-AKA-attributes.patch
- + debian/patches/0010-libradius-Reject-undersized-attributes-in-enumerator.patch
- + debian/patches/0011-tls-server-Only-accept-non-empty-ECDH-public-keys-wi.patch
- + debian/patches/0012-tls-server-Prevent-infinite-loop-if-supported-versio.patch
- + debian/patches/0013-pkcs5-pkcs7-Avoid-NULL-pointer-dereference-when-veri.patch
- + debian/patches/0014-constraints-Case-insensitive-matching-and-reject-exc.patch
- + debian/patches/0015-gmp-Avoid-crash-and-timing-leaks-in-PKCS-1-v1.5-decr.patch
- debian/patches/series


Changes:

=====================================
debian/changelog
=====================================
@@ -1,3 +1,28 @@
+strongswan (5.9.8-5+deb12u4) bookworm-security; urgency=medium
+
+  * d/patches: add fix for integer underflow in libsimaka when handling
+    EAP-SIM/AKA attributes (CVE-2026-35330)
+  * d/patches: add fix for integer underflow in libradius when handling RADIUS
+    attributes (CVE-2026-35333)
+  * d/patches: add fix for NULL-pointer dereference in libtls when handling
+    ECDH public values (CVE-2026-35332)
+  * d/patches: add fix for infinite loop in libtls when handling supported
+    versions TLS extension (CVE-2026-35328)
+  * d/patches: add fix for NULL-pointer dereference in libstrongswan (pkcs5)
+    and the pkcs7 plugin when processing padding in PKCS#7 (CVE-2026-35329)
+  * d/patches: add fix for acceptation of authentication certificates
+    violating name constraints (CVE-2026-35331)
+  * d/patches: add fix for possible NULL-pointer dereference in gmp plugin for
+    RSA decryption (CVE-2026-35334)
+
+ -- Yves-Alexis Perez <corsac at debian.org>  Mon, 13 Apr 2026 11:19:15 +0200
+
+strongswan (5.9.8-5+deb12u3) bookworm-security; urgency=medium
+
+  * d/patch: fix integer overflow in EAP-TTLS plugin (CVE-2026-25075)
+
+ -- Yves-Alexis Perez <corsac at debian.org>  Wed, 18 Mar 2026 08:53:16 +0100
+
 strongswan (5.9.8-5+deb12u2) bookworm-security; urgency=medium
 
   * d/patches: add fix for buffer overflow in EAP-MSCHAPv2 (CVE-2025-62291)


=====================================
debian/patches/0008-eap-ttls-Prevent-crash-if-AVP-length-header-field-is.patch
=====================================
@@ -0,0 +1,42 @@
+From: Tobias Brunner <tobias at strongswan.org>
+Date: Thu, 5 Mar 2026 12:43:12 +0100
+Subject: eap-ttls: Prevent crash if AVP length header field is invalid
+
+The length field in the AVP header includes the 8 bytes of the header
+itself.  Not checking for that and later subtracting it causes an
+integer underflow that usually triggers a crash when accessing a
+NULL pointer that resulted from the failing chunk_alloc() call because
+of the high value.
+
+The attempted allocations for invalid lengths (0-7) are 0xfffffff8,
+0xfffffffc, or 0x100000000 (0 on 32-bit hosts), so this doesn't result
+in a buffer overflow even if the allocation succeeds.
+
+Fixes: 79f2102cb442 ("implemented server side support for EAP-TTLS")
+Fixes: CVE-2026-25075
+---
+ src/libcharon/plugins/eap_ttls/eap_ttls_avp.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_avp.c b/src/libcharon/plugins/eap_ttls/eap_ttls_avp.c
+index 06389f7..2983bd0 100644
+--- a/src/libcharon/plugins/eap_ttls/eap_ttls_avp.c
++++ b/src/libcharon/plugins/eap_ttls/eap_ttls_avp.c
+@@ -119,7 +119,7 @@ METHOD(eap_ttls_avp_t, process, status_t,
+ 		chunk_free(&this->input);
+ 		this->inpos = 0;
+ 
+-		if (!success)
++		if (!success || avp_len < AVP_HEADER_LEN)
+ 		{
+ 			DBG1(DBG_IKE, "received invalid AVP header");
+ 			return FAILED;
+@@ -130,7 +130,7 @@ METHOD(eap_ttls_avp_t, process, status_t,
+ 			return FAILED;
+ 		}
+ 		this->process_header = FALSE;
+-		this->data_len = avp_len - 8;
++		this->data_len = avp_len - AVP_HEADER_LEN;
+ 		this->input = chunk_alloc(this->data_len + (4 - avp_len) % 4);
+ 	}
+ 


=====================================
debian/patches/0009-libsimaka-Reject-zero-length-EAP-SIM-AKA-attributes.patch
=====================================
@@ -0,0 +1,53 @@
+From: =?utf-8?q?Lukas_Johannes_M=C3=B6ller?= <research at johannes-moeller.dev>
+Date: Wed, 11 Mar 2026 16:07:10 +0000
+Subject: libsimaka: Reject zero-length EAP-SIM/AKA attributes
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+parse_attributes() accepts hdr->length == 0 in the AT_ENCR_DATA,
+AT_RAND, AT_PADDING, default branches. The code then subtracts the
+fixed attribute header size from the encoded length, which underflows
+and exposes a wrapped payload length to later code.  In particular,
+for the cases where add_attribute() is called, this causes a heap-based
+buffer overflow (a buffer of 12 bytes is allocated to which the wrapped
+length is written).  For AT_PADDING, the underflow is irrelevant as
+add_attribute() is not called. Instead, this results in an infinite loop.
+
+Reject zero-length attributes before subtracting the attribute header.
+
+Signed-off-by: Lukas Johannes Möller <research at johannes-moeller.dev>
+
+Fixes: f8330d03953b ("Added a libsimaka library with shared message handling code for EAP-SIM/AKA")
+Fixes: CVE-2026-35330
+---
+ src/libsimaka/simaka_message.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/src/libsimaka/simaka_message.c b/src/libsimaka/simaka_message.c
+index 6706568..4862048 100644
+--- a/src/libsimaka/simaka_message.c
++++ b/src/libsimaka/simaka_message.c
+@@ -416,7 +416,7 @@ static bool parse_attributes(private_simaka_message_t *this, chunk_t in)
+ 			case AT_ENCR_DATA:
+ 			case AT_RAND:
+ 			{
+-				if (hdr->length * 4 > in.len || in.len < 4)
++				if (hdr->length == 0 || hdr->length * 4 > in.len || in.len < 4)
+ 				{
+ 					return invalid_length(hdr->type);
+ 				}
+@@ -439,7 +439,7 @@ static bool parse_attributes(private_simaka_message_t *this, chunk_t in)
+ 			case AT_PADDING:
+ 			default:
+ 			{
+-				if (hdr->length * 4 > in.len || in.len < 4)
++				if (hdr->length == 0 || hdr->length * 4 > in.len || in.len < 4)
+ 				{
+ 					return invalid_length(hdr->type);
+ 				}
+@@ -932,4 +932,3 @@ simaka_message_t *simaka_message_create(bool request, uint8_t identifier,
+ 	return simaka_message_create_data(chunk_create((char*)&hdr, sizeof(hdr)),
+ 									  crypto);
+ }
+-


=====================================
debian/patches/0010-libradius-Reject-undersized-attributes-in-enumerator.patch
=====================================
@@ -0,0 +1,40 @@
+From: =?utf-8?q?Lukas_Johannes_M=C3=B6ller?= <research at johannes-moeller.dev>
+Date: Thu, 12 Mar 2026 10:24:45 +0000
+Subject: libradius: Reject undersized attributes in enumerator
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+attribute_enumerate() accepts RADIUS attributes whose length byte is
+smaller than sizeof(rattr_t) (2).  For length == 0, the iterator never
+advances and traps callers — including verify() — in a non-advancing
+loop.  For length == 1, misaligned packed-struct reads occur.
+
+Add a separate check for this->next->length < sizeof(rattr_t) after
+the existing truncation guard.  This mirrors radius_message_parse(),
+which already distinguishes invalid length from truncation.
+
+Signed-off-by: Lukas Johannes Möller <research at johannes-moeller.dev>
+
+Fixes: 4a6b84a93461 ("reintegrated eap-radius branch into trunk")
+Fixes: CVE-2026-35333
+---
+ src/libradius/radius_message.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/src/libradius/radius_message.c b/src/libradius/radius_message.c
+index 8e2db0c..5679e47 100644
+--- a/src/libradius/radius_message.c
++++ b/src/libradius/radius_message.c
+@@ -261,6 +261,11 @@ METHOD(enumerator_t, attribute_enumerate, bool,
+ 		DBG1(DBG_IKE, "RADIUS message truncated");
+ 		return FALSE;
+ 	}
++	if (this->next->length < sizeof(rattr_t))
++	{
++		DBG1(DBG_IKE, "RADIUS attribute has invalid length");
++		return FALSE;
++	}
+ 	*type = this->next->type;
+ 	data->ptr = this->next->value;
+ 	data->len = this->next->length - sizeof(rattr_t);


=====================================
debian/patches/0011-tls-server-Only-accept-non-empty-ECDH-public-keys-wi.patch
=====================================
@@ -0,0 +1,49 @@
+From: Tobias Brunner <tobias at strongswan.org>
+Date: Fri, 20 Mar 2026 17:38:07 +0100
+Subject: tls-server: Only accept non-empty ECDH public keys with TLS < 1.3
+
+This prevents a crash due to a null-pointer dereference when processing
+an empty ECDH public key.
+
+The previous length check only applied in the `!ec` case, so in the `ec`
+case, the access to `pub.ptr[0]` was unguarded.  If a crafted TLS
+record ends with an empty ClientKeyExchange, then `read_data8` sets
+`pub` to `chunk_empty`, causing a null-pointer dereference.
+
+Note that if some data follows the empty ClientKeyExchange, this just
+causes a 1-byte out-of-bounds read that has no further effect as the
+TLS session is aborted immediately.  Either because the read value
+doesn't equal TLS_ANSI_UNCOMPRESSED or because the empty public key
+is rejected by `set_public_key()`.
+
+The referenced commit that introduced the pointer access, added the
+check for `pub.len` specifically to the `!ec` case, while the pointer
+access was initially unconditional (probably because the code was just
+copied from `tls_peer.c` which processes ECDH public keys in a separate
+function, so there was no `ec` flag).  The latter was fixed a couple of
+days later with 7b3c01845f63 ("Read the compression type byte for EC
+groups, only").  However, that commit didn't change the length check.
+Anyway, it's possible that the original intention was to add the check
+to the `ec` case on the previous line, or that there was some confusion
+with the parenthesis and something like the current code was intended to
+begin with.
+
+Fixes: e6cce7ff0d1b ("Prepend point format to ECDH public key")
+Fixes: CVE-2026-35332
+---
+ src/libtls/tls_server.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c
+index 573893f..7321bd1 100644
+--- a/src/libtls/tls_server.c
++++ b/src/libtls/tls_server.c
+@@ -860,7 +860,7 @@ static status_t process_key_exchange_dhe(private_tls_server_t *this,
+ 	group = this->dh->get_method(this->dh);
+ 	ec = key_exchange_is_ecdh(group);
+ 	if ((ec && !reader->read_data8(reader, &pub)) ||
+-		(!ec && (!reader->read_data16(reader, &pub) || pub.len == 0)))
++		(!ec && !reader->read_data16(reader, &pub)) || pub.len == 0)
+ 	{
+ 		DBG1(DBG_TLS, "received invalid Client Key Exchange");
+ 		this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);


=====================================
debian/patches/0012-tls-server-Prevent-infinite-loop-if-supported-versio.patch
=====================================
@@ -0,0 +1,41 @@
+From: Tobias Brunner <tobias at strongswan.org>
+Date: Wed, 25 Mar 2026 10:17:46 +0100
+Subject: tls-server: Prevent infinite loop if supported versions are too
+ short
+
+If the extension doesn't contain a multiple of two bytes, the previous
+code would get stuck in an infinite loop as `remaining()` continued to
+return TRUE while `read_uint16()` failed to parse a value. Initiating
+several connections with such an extension allows a DoS attack as no
+threads would eventually be available to handle packets/events.
+
+Fixes: 7fbe2e27ecf6 ("tls-server: TLS 1.3 support for TLS server implementation")
+Fixes: CVE-2026-35328
+---
+ src/libtls/tls_server.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c
+index 7321bd1..b4e6b78 100644
+--- a/src/libtls/tls_server.c
++++ b/src/libtls/tls_server.c
+@@ -471,15 +471,12 @@ static status_t process_client_hello(private_tls_server_t *this,
+ 		bio_reader_t *client_versions;
+ 
+ 		client_versions = bio_reader_create(versions);
+-		while (client_versions->remaining(client_versions))
++		while (client_versions->read_uint16(client_versions, &version))
+ 		{
+-			if (client_versions->read_uint16(client_versions, &version))
++			if (this->tls->set_version(this->tls, version, version))
+ 			{
+-				if (this->tls->set_version(this->tls, version, version))
+-				{
+-					this->client_version = version;
+-					break;
+-				}
++				this->client_version = version;
++				break;
+ 			}
+ 		}
+ 		client_versions->destroy(client_versions);


=====================================
debian/patches/0013-pkcs5-pkcs7-Avoid-NULL-pointer-dereference-when-veri.patch
=====================================
@@ -0,0 +1,56 @@
+From: Tobias Brunner <tobias at strongswan.org>
+Date: Wed, 25 Mar 2026 10:28:45 +0100
+Subject: pkcs5/pkcs7: Avoid NULL pointer dereference when verifying padding
+
+Can be triggered via empty PKCS#7 encrypted- or enveloped-data content
+in IKEv1 CERT payload.
+
+Fixes: 4076e3ee9121 ("Extract PKCS#5 handling from pkcs8 plugin to separate helper class")
+Fixes: d7aa09104f08 ("Implement PKCS#7 enveloped-data parsing and decryption")
+Fixes: CVE-2026-35329
+---
+ src/libstrongswan/crypto/pkcs5.c                       |  5 +++++
+ src/libstrongswan/plugins/pkcs7/pkcs7_enveloped_data.c | 14 +++++++++++---
+ 2 files changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/src/libstrongswan/crypto/pkcs5.c b/src/libstrongswan/crypto/pkcs5.c
+index e48a9ad..4851d3f 100644
+--- a/src/libstrongswan/crypto/pkcs5.c
++++ b/src/libstrongswan/crypto/pkcs5.c
+@@ -113,6 +113,11 @@ static bool verify_padding(crypter_t *crypter, chunk_t *blob)
+ {
+ 	uint8_t padding, count;
+ 
++	if (!blob->len)
++	{
++		return FALSE;
++	}
++
+ 	padding = count = blob->ptr[blob->len - 1];
+ 
+ 	if (padding > crypter->get_block_size(crypter))
+diff --git a/src/libstrongswan/plugins/pkcs7/pkcs7_enveloped_data.c b/src/libstrongswan/plugins/pkcs7/pkcs7_enveloped_data.c
+index 14bfaf3..e78af19 100644
+--- a/src/libstrongswan/plugins/pkcs7/pkcs7_enveloped_data.c
++++ b/src/libstrongswan/plugins/pkcs7/pkcs7_enveloped_data.c
+@@ -182,9 +182,17 @@ static bool decrypt(private_key_t *private, chunk_t key, chunk_t iv, int oid,
+  */
+ static bool remove_padding(private_pkcs7_enveloped_data_t *this)
+ {
+-	u_char *pos = this->content.ptr + this->content.len - 1;
+-	u_char pattern = *pos;
+-	size_t padding = pattern;
++	u_char *pos, pattern;
++	size_t padding;
++
++	if (!this->content.len)
++	{
++		return FALSE;
++	}
++
++	pos = this->content.ptr + this->content.len - 1;
++	pattern = *pos;
++	padding = pattern;
+ 
+ 	if (padding > this->content.len)
+ 	{


=====================================
debian/patches/0014-constraints-Case-insensitive-matching-and-reject-exc.patch
=====================================
@@ -0,0 +1,123 @@
+From: Tobias Brunner <tobias at strongswan.org>
+Date: Mon, 23 Mar 2026 17:45:11 +0100
+Subject: constraints: Case-insensitive matching and reject excluded DN name
+ constraints
+
+The case is generally ignored when matching identities.  So this is
+an issue with excluded name constraints where a malicious intermediate
+CA could evade the constraints by issuing certificates with names that
+just modify the case (e.g. strongSwan.org instead strongswan.org).
+
+Note that it's likely that permitted name constraints are preferred over
+excluded name constraints as it might be difficult to come up with a
+conclusive list of names to exclude.
+
+With directoryName (DN) name constraints the issue is a bit more comples.
+Some RDNs have to be matched in a case-insensitive manner, which we e.g.
+do in `identification.c::rdn_equals`.  By not doing it for name
+constraints, a malicious intermediate CA could evade an excluded name
+constraint just by modifying the case in such an RDN.
+
+While we could use the mentioned function in `dn_matches`, this doesn't
+properly fix the problem because the function is basically too strict.
+Especially in regards to RDNs of type UTF8String, which are only compared
+binary.  To match these properly, we'd have to implement the string
+preparation described in RFC 5280, section 7.1 and the referenced RFCs.
+Until that's the case, we reject excluded name constraints of type
+directoryName as we are unable to enforce them.
+
+Fixes: a2b340764fac ("Implemented NameConstraint matching in constraints plugin")
+Fixes: CVE-2026-35331
+---
+ .../plugins/constraints/constraints_validator.c    | 25 +++++++++++++++++++---
+ src/libstrongswan/tests/suites/test_certnames.c    | 10 ++++-----
+ 2 files changed, 27 insertions(+), 8 deletions(-)
+
+diff --git a/src/libstrongswan/plugins/constraints/constraints_validator.c b/src/libstrongswan/plugins/constraints/constraints_validator.c
+index 0f074c4..ade9b97 100644
+--- a/src/libstrongswan/plugins/constraints/constraints_validator.c
++++ b/src/libstrongswan/plugins/constraints/constraints_validator.c
+@@ -52,6 +52,18 @@ static bool check_pathlen(x509_t *issuer, int pathlen)
+ 	return TRUE;
+ }
+ 
++/**
++ * Check if the constraint and ID strings match case-insensitively
++ */
++static bool string_matches(chunk_t constraint, chunk_t id)
++{
++	/* make sure the two strings have actually the same length */
++	return constraint.len == id.len &&
++		   memchr(constraint.ptr, 0, constraint.len) == NULL &&
++		   memchr(id.ptr, 0, id.len) == NULL &&
++		   strncasecmp(constraint.ptr, id.ptr, constraint.len) == 0;
++}
++
+ /**
+  * Check if a FQDN constraint matches
+  */
+@@ -67,7 +79,7 @@ static bool fqdn_matches(identification_t *constraint, identification_t *id)
+ 		return FALSE;
+ 	}
+ 	diff = chunk_create(i.ptr, i.len - c.len);
+-	if (!chunk_equals(c, chunk_skip(i, diff.len)))
++	if (!string_matches(c, chunk_skip(i, diff.len)))
+ 	{
+ 		return FALSE;
+ 	}
+@@ -98,10 +110,10 @@ static bool email_matches(identification_t *constraint, identification_t *id)
+ 	}
+ 	if (memchr(c.ptr, '@', c.len))
+ 	{	/* constraint is a full email address */
+-		return chunk_equals(c, i);
++		return string_matches(c, i);
+ 	}
+ 	diff = chunk_create(i.ptr, i.len - c.len);
+-	if (!diff.len || !chunk_equals(c, chunk_skip(i, diff.len)))
++	if (!string_matches(c, chunk_skip(i, diff.len)))
+ 	{
+ 		return FALSE;
+ 	}
+@@ -158,6 +170,13 @@ static bool name_constraint_matches(identification_t *constraint,
+ 	type = constraint->get_type(constraint);
+ 	if (type == ID_DER_ASN1_DN)
+ 	{
++		if (!permitted)
++		{
++			DBG1(DBG_CFG, "excluded %N NameConstraint not supported",
++				 id_type_names, type);
++			/* we have to return TRUE to let the constraint fail */
++			return TRUE;
++		}
+ 		matches = dn_matches(constraint, cert->get_subject(cert));
+ 		if (matches != permitted)
+ 		{
+diff --git a/src/libstrongswan/tests/suites/test_certnames.c b/src/libstrongswan/tests/suites/test_certnames.c
+index 3672912..390f202 100644
+--- a/src/libstrongswan/tests/suites/test_certnames.c
++++ b/src/libstrongswan/tests/suites/test_certnames.c
+@@ -232,11 +232,11 @@ static struct {
+ 	char *subject;
+ 	bool good;
+ } excluded_dn[] = {
+-	{ "C=CH, O=another", "C=CH, O=strongSwan, CN=tester", TRUE },
+-	{ "C=CH, O=another", "C=CH, O=anot", TRUE },
+-	{ "C=CH, O=another", "C=CH, O=anot, CN=tester", TRUE },
++	{ "C=CH, O=another", "C=CH, O=strongSwan, CN=tester", FALSE },
++	{ "C=CH, O=another", "C=CH, O=anot", FALSE },
++	{ "C=CH, O=another", "C=CH, O=anot, CN=tester", FALSE },
+ 	{ "C=CH, O=another", "C=CH, O=another, CN=tester", FALSE },
+-	{ "C=CH, O=another", "C=CH, CN=tester, O=another", TRUE },
++	{ "C=CH, O=another", "C=CH, CN=tester, O=another", FALSE },
+ };
+ 
+ START_TEST(test_excluded_dn)
+@@ -334,7 +334,7 @@ static struct {
+ 	char *subject;
+ 	bool good;
+ } excluded_dninh[] = {
+-	{ "C=CH, O=strongSwan", "C=CH", "C=DE", TRUE },
++	{ "C=CH, O=strongSwan", "C=CH", "C=DE", FALSE },
+ 	{ "C=CH, O=strongSwan", "C=DE", "C=CH", FALSE },
+ 	{ "C=CH", "C=CH, O=strongSwan", "C=CH, O=strongSwan, CN=tester", FALSE },
+ };


=====================================
debian/patches/0015-gmp-Avoid-crash-and-timing-leaks-in-PKCS-1-v1.5-decr.patch
=====================================
@@ -0,0 +1,246 @@
+From: Tobias Brunner <tobias at strongswan.org>
+Date: Tue, 24 Mar 2026 18:00:23 +0100
+Subject: gmp: Avoid crash and timing leaks in PKCS#1 v1.5 decryption padding
+ validation
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+This fixes a potential crash due to a null-pointer dereference if rsadp()
+returns NULL (e.g. with an all-zero ciphertext).
+
+And it also implements the PKCS#1 v1.5 decryption padding check in
+constant time.
+
+The timing leak caused by the previous implementation was measured at
+~17.5 μs at 3 GHz, which could allow a Bleichenbacher-like attack in
+LAN environments.  However, because of how RSA encryption is used in
+strongSwan, this is not that much of an issue in practice.  The mechanism
+is only used for two use cases.  One is SCEP/EST via PKCS#7 enveloped
+data.  Fortunately, this can not be triggered in significant numbers by
+an attacker.  The other use case is TLS as used by EAP methods (EAP-TLS,
+EAP-PEAP/TTLS) during the authentication.  While the cipher suites that
+use RSA encryption are still enabled by default, the TLS messages are
+wrapped in EAP and encrypted by IKE, making any kind of attack difficult.
+
+Note that the gmp plugin isn't enabled anymore by default.  And even
+before that, most setups had the openssl plugin enabled, which has
+priority over the gmp plugin.  So it's unlikely the plugin was used in
+practice.
+
+Also note that this patch doesn't modify libstrongswan's Makefile.am
+to avoid potentially requiring autotools when patching a tarball.
+
+Fixes: d615ffdcf3cd ("implement gmp_rsa_private_key.decrypt()")
+Fixes: CVE-2026-35334
+---
+ .../plugins/gmp/gmp_rsa_private_key.c              |  54 +++++++----
+ src/libstrongswan/utils/utils.h                    |   1 +
+ src/libstrongswan/utils/utils/constant_time.h      | 103 +++++++++++++++++++++
+ 3 files changed, 140 insertions(+), 18 deletions(-)
+ create mode 100644 src/libstrongswan/utils/utils/constant_time.h
+
+diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
+index 47784b6..7312fa9 100644
+--- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
++++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
+@@ -495,8 +495,8 @@ METHOD(private_key_t, decrypt, bool,
+ 	private_gmp_rsa_private_key_t *this, encryption_scheme_t scheme,
+ 	void *params, chunk_t crypto, chunk_t *plain)
+ {
+-	chunk_t em, stripped;
+-	bool success = FALSE;
++	chunk_t em;
++	u_int valid, i, j, found_sep = 0, sep_index = 0, m_index;
+ 
+ 	if (scheme != ENCRYPT_RSA_PKCS1)
+ 	{
+@@ -505,33 +505,51 @@ METHOD(private_key_t, decrypt, bool,
+ 		return FALSE;
+ 	}
+ 	/* rsa decryption using PKCS#1 RSADP */
+-	stripped = em = rsadp(this, crypto);
++	em = rsadp(this, crypto);
++	if (em.len != this->k)
++	{
++		return FALSE;
++	}
+ 
+-	/* PKCS#1 v1.5 8.1 encryption-block formatting (EB = 00 || 02 || PS || 00 || D) */
++	/* PKCS#1 v1.5, RFC 8017, section 7.2.2 message structure:
++	 * EM = 00 || 02 || PS || 00 || M */
+ 
+ 	/* check for hex pattern 00 02 in decrypted message */
+-	if ((*stripped.ptr++ != 0x00) || (*(stripped.ptr++) != 0x02))
++	valid  = constant_time_eq(em.ptr[0], 0x00);
++	valid &= constant_time_eq(em.ptr[1], 0x02);
++
++	/* the plaintext data starts after first 0x00 byte */
++	for (i = 2; i < em.len; i++)
+ 	{
+-		DBG1(DBG_LIB, "incorrect padding - probably wrong rsa key");
+-		goto end;
++		u_int zero = constant_time_eq(em.ptr[i], 0x00);
++
++		sep_index = constant_time_select(i, sep_index, ~found_sep & zero);
++		found_sep |= zero;
+ 	}
+-	stripped.len -= 2;
+ 
+-	/* the plaintext data starts after first 0x00 byte */
+-	while (stripped.len-- > 0 && *stripped.ptr++ != 0x00)
++	/* make sure PS is at least eight bytes long (plus the initial bytes) */
++	valid &= constant_time_ge(sep_index, 10);
++
++	/* instead of copying the message directly, we try not to reveal the message
++	 * length i.e. where the 0x00 byte was. and since clearing a chunk is
++	 * relatively efficient, i.e. doesn't leak much, we always allocate and copy
++	 * a value and then clear it if the structure was invalid */
++	m_index = constant_time_select(sep_index + 1, 11, valid);
+ 
+-	if (stripped.len == 0)
++	*plain = chunk_alloc(this->k);
++	for (i = 0, j = 0; i < em.len; i++)
+ 	{
+-		DBG1(DBG_LIB, "no plaintext data");
+-		goto end;
++		plain->ptr[j] = em.ptr[i];
++		j += constant_time_ge(i, m_index);
+ 	}
++	plain->len = j;
+ 
+-	*plain = chunk_clone(stripped);
+-	success = TRUE;
+-
+-end:
++	if (!valid)
++	{
++		chunk_clear(plain);
++	}
+ 	chunk_clear(&em);
+-	return success;
++	return valid;
+ }
+ 
+ METHOD(private_key_t, get_keysize, int,
+diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h
+index 083f553..2bc2f9a 100644
+--- a/src/libstrongswan/utils/utils.h
++++ b/src/libstrongswan/utils/utils.h
+@@ -53,6 +53,7 @@
+ #include "utils/atomics.h"
+ #include "utils/align.h"
+ #include "utils/byteorder.h"
++#include "utils/constant_time.h"
+ #include "utils/string.h"
+ #include "utils/memory.h"
+ #include "utils/strerror.h"
+diff --git a/src/libstrongswan/utils/utils/constant_time.h b/src/libstrongswan/utils/utils/constant_time.h
+new file mode 100644
+index 0000000..0c2c6a2
+--- /dev/null
++++ b/src/libstrongswan/utils/utils/constant_time.h
+@@ -0,0 +1,103 @@
++/*
++ * Copyright (C) 2026 Tobias Brunner
++ *
++ * Copyright (C) secunet Security Networks AG
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ */
++
++/**
++ * @defgroup constant_time_i constant_time
++ * @{ @ingroup constant_time_i
++ */
++
++#ifndef CONSTANT_TIME_H_
++#define CONSTANT_TIME_H_
++
++#include <stdint.h>
++
++/**
++ * Check if the given values are not equal in constant time.
++ *
++ * @param x		first value to check
++ * @param y		second value to check
++ * @return		1 if values are not equal, 0 otherwise
++ */
++static inline u_int constant_time_neq(uint32_t x, uint32_t y)
++{
++	return ((x-y) | (y-x)) >> 31;
++}
++
++/**
++ * Check if the given values are equal in constant time.
++ *
++ * @param x		first value to check
++ * @param y		second value to check
++ * @return		1 if values are equal, 0 otherwise
++ */
++static inline u_int constant_time_eq(uint32_t x, uint32_t y)
++{
++	return 1 ^ constant_time_neq(x, y);
++}
++
++/**
++ * Compare the two values and return 1 if the first argument is lower than
++ * the second in constant time.
++ *
++ * @param x		first value to check
++ * @param y		second value to check
++ * @return		1 if first value is lower than second
++ */
++static inline u_int constant_time_lt(uint32_t x, uint32_t y)
++{
++	return (x ^ ((x^y) | ((x-y) ^ y))) >> 31;
++}
++
++/**
++ * Compare the two values and return 1 if the first argument greater or equal to
++ * the second in constant time.
++ *
++ * @param x		first value to check
++ * @param y		second value to check
++ * @return		1 if first value is greater or equal to the second
++ */
++static inline u_int constant_time_ge(uint32_t x, uint32_t y)
++{
++	return 1 ^ constant_time_lt(x, y);
++}
++
++/**
++ * Return a 32-bit all bit-set mask if the given value is not 0.
++ *
++ * @param x		value to check
++ * @return		0xffffffff if value is != 0, 0 otherwise
++ */
++static inline uint32_t constant_time_mask(uint32_t x)
++{
++	return -(uint32_t)constant_time_neq(x, 0);
++}
++
++/**
++ * Select one of two values depending on whether the condition is != 0 or not.
++ * Basically equivalent to 'c ? x : y'.
++ *
++ * @param x		first value to select
++ * @param y		second value to select
++ * @param c		condition
++ * @return		x if c is != 0, y otherwise
++ */
++static inline uint32_t constant_time_select(uint32_t x, uint32_t y, uint32_t c)
++{
++	uint32_t m = constant_time_mask(c);
++	return (x & m) | (y & ~m);
++}
++
++#endif /** CONSTANT_TIME_H_ @} */


=====================================
debian/patches/series
=====================================
@@ -5,3 +5,11 @@ dont-load-kernel-libipsec-plugin-by-default.patch
 0005-libtls-Fix-authentication-bypass-and-expired-pointer.patch
 0006-charon-tkm-Validate-DH-public-key-to-fix-potential-b.patch
 0007-eap-mschapv2-Fix-length-check-for-Failure-Request-pa.patch
+0008-eap-ttls-Prevent-crash-if-AVP-length-header-field-is.patch
+0009-libsimaka-Reject-zero-length-EAP-SIM-AKA-attributes.patch
+0010-libradius-Reject-undersized-attributes-in-enumerator.patch
+0011-tls-server-Only-accept-non-empty-ECDH-public-keys-wi.patch
+0012-tls-server-Prevent-infinite-loop-if-supported-versio.patch
+0013-pkcs5-pkcs7-Avoid-NULL-pointer-dereference-when-veri.patch
+0014-constraints-Case-insensitive-matching-and-reject-exc.patch
+0015-gmp-Avoid-crash-and-timing-leaks-in-PKCS-1-v1.5-decr.patch



View it on GitLab: https://salsa.debian.org/debian/strongswan/-/compare/9f73a11358e66c263a22fd9cf9173d8a14a7ff66...ba3f482959648744d08f13419d67565ae7b2db5a

-- 
View it on GitLab: https://salsa.debian.org/debian/strongswan/-/compare/9f73a11358e66c263a22fd9cf9173d8a14a7ff66...ba3f482959648744d08f13419d67565ae7b2db5a
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-swan-devel/attachments/20260426/6eb0d41e/attachment-0001.htm>


More information about the Pkg-swan-devel mailing list