[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