While the validity of a pre-trusted certificate for which an issuer is
found is enforced via `check_certificate()`, the validity of such a
certificate in an incomplete trust chain, or rather that of the last
certificate in such a chain, was not enforced. This fixes that
inconsistency.
Unlike `struct ifreq` that's used for IPv4, `struct in6_ifreq` contains
not a `struct sockaddr[_in6]` but only a `struct in6_addr`.
Setting addresses like this is currently not used on Linux (the feature
was added to install virtual IPs on FreeBSD/macOS).
Fixes: fccc76449d ("tun-device: Fix handling of IPv6 addresses")
Keys loaded via generic loader (KEY_ANY) or from a PKCS#12 file (or an
engine) don't go through the openssl_ec_private_key_load() constructor
that checks for explicit parameters.
This was broken since the Botan 3 release, which removed the EMSA1
class and the define. The "EMSA1()" wrapper when signing/verifying is
technically not necessary anymore since then (it's deprecated but still
accepted). But to still support Botan 2, we keep that in for now.
The leak detective doesn't wrap this function and calling the original
causes unknown memory frees and even segmentation faults. This is now
triggered with OpenSSL 4 as the implementation of ECP256 uses
OPENSSL_aligned_alloc_array().
Setting a custom memory functions forces OpenSSL to implement aligned
allocations internally, using the registered allocation function.
Using the return value of i2d_* directly as input of chunk_alloc imposes
the risk of creating an invalid chunk when the return value of the i2d_*
function is -1. The openssl_i2chunk macro is meant to avoid this.
Signed-off-by: Thomas Egerer <[email protected]>
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.
Fixes: d615ffdcf3 ("implement gmp_rsa_private_key.decrypt()")
Fixes: CVE-2026-35334
As the previous issue, this can be triggered via IKEv1 CERT payloads.
Fixes: d7aa09104f ("Implement PKCS#7 enveloped-data parsing and decryption")
Fixes: CVE-2026-35329
Can be triggered via empty PKCS#7 encrypted content in IKEv1 CERT payload.
Fixes: 4076e3ee91 ("Extract PKCS#5 handling from pkcs8 plugin to separate helper class")
Fixes: CVE-2026-35329
There is an issue similar to the one fixed with the previous commit when
using directoryName (DN) name constraints. 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: a2b340764f ("Implemented NameConstraint matching in constraints plugin")
Fixes: CVE-2026-35331
The case is generally ignored when matching such 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.
Fixes: a2b340764f ("Implemented NameConstraint matching in constraints plugin")
Fixes: CVE-2026-35331
wolfSSL 5.9.1 starts to enforce a minimum (and maximum) length for the
hash when signing. Since we'll always require SHA-1, use 20 bytes as
input in the tests to succeed with SIGN_ECDSA_WITH_NULL.
This mainly intended as defense-in-depth measure to avoid parsing
massively nested structures that could cause a call stack overflow due
to the massive recursion. In particular PKCS#7 signed data is prone to
this as these can be nested basically infinitely. When used in IKEv1 via
ENC_PKCS7_WRAPPED_X509 CERT payloads, our default of 10000 bytes for IKE
messages guards against this, but that's configurable and there might be
a chance for some bug that triggers problematic recursive parsing for
smaller input.
The upper limit is chosen arbitrarily, but there are currently no known
cases that require a depth of more than 10 levels.
This ensures that we don't load a key with e=1, which basically renders
RSA into a no-op. Since keys are universally generated with e=65537 and
no reputable CA will sign keys with e=1, allowing this before didn't have
any real world impact.
GCC 15 tightened its built-in declarations for strchr() and strstr() so
that they now propagate const from their first argument, triggering
-Werror=discarded-qualifiers on three assignments in string.c:
translate():
char *match = strchr(from, *pos)
`from` is const char *, so the result of strchr() is const char *.
`match` is only used for pointer arithmetic (match - from), so
declaring it const char * is correct and safe.
strreplace():
found = strstr(str, search) [line ~73]
found = strstr(pos, search) [line ~89, while condition]
`str`/`pos` are derived from a const char * parameter, so strstr()
returns const char *. `found` is used as a mutable char * later
(pos = found + slen), consistent with the existing (char*) casts
already used throughout this function for the same reason.
Add explicit (char*) casts to match the established pattern.
Closesstrongswan/strongswan#3015
While 3c12905103 ("ipsec: Add function to compare two ipsec_sa_cfg_t
instances") added a comparison function to avoid issues with non-zeroed
padding, hashes were still calculated using chunk_hash().
Distributions like Debian/Ubuntu ship the plugins in multiple packages
that are not all installed by default. When running tools like pki or
swanctl, which don't use modular loading with config snippets by default,
there are errors in the output if these packages and plugins are
currently not available. In order to not alarm users, this change adds
a configure option that package maintainers can use. It causes the log
level of the message to increase and also adds a note that mentions that
plugins are potentially available in other packages (which should be the
case unless the user tried to load a plugin, e.g. via load statement,
that is not actually built and shipped by the package maintainers).
Such a recursive call occurs when sorting the array of Child SAs inside
an IKE SA that causes comparisons of the child configs and their
proposals, which in turn creates a merged array of all transform types
and that uses array_sort() and array_bsearch().
Closesstrongswan/strongswan#2926
Fixes: 8e7f379f71 ("ike-sa: Sort CHILD_SAs by CPU ID")
Clean up leak-detective whitelist for newer Botan versions but add
`botan_private_key_load` as `botan_privkey_load*` won't show up anymore
without bfd-backtraces due to inlining if we don't call it directly.
Ref: https://github.com/randombit/botan/discussions/4868
The buffer size for individual parts of a key now match the maximum length
of names in VICI. The full pattern should accommodate several long names
(e.g. for connections and child connections in swanctl) even if no
printf-specifiers are used.
If a CRL server is unresponsive, all threads trying to fetch this CRL will
block execution. If a recent previous attempt to fetch the CRL failed, it
is likely that it will fail again. While it makes sense to retry fetching
the CRL on demand with one thread, it hardly does to block additional
threads while the first one is blocked during the fetch.
So remember the timestamp of the last CRL fetch failure per URL, and do
not block more than one thread in the CRL fetch for some time. This time
is a multiple of the configured fetch timeout, so that it works well for
any configured value. With the default configuration, a failing CRL fetch
will impact concurrent CRL fetches for the same URL for 30s.
When handling many connection attempts from peers using the same CA, a slow
or non-responsive CRL distribution point can lead to concurrent fetches of
the same CRL by multiple threads. This is not only inefficient, but results
in all threads blocking for the full fetch timeout, potentially blocking
all threads in the pool.
As a first step, synchronize CRL fetches using a global mutex and a per-URL
condvar, so threads can wait for the CRL if another is already fetching it.
This reduces the number of useless concurrent CRL fetches, and allows threads
joining the party late to get blocked only until the first fetch completes
or times out.
The URL entry is preserved in the hashtable after completing the fetch.
This will allow subsequent optimizations to store the last fetch result
and act accordingly. The CRL itself is not, as CRLs can be rather large
and caching them can be done using existing mechanisms controlled via
corresponding options.
Before adding stateful CRL fetching extensions, refactor CRL fetching to
a helper class for better separation. While there are currently no plans
to extend OCSP fetching, move it as well for consistency.
As future commits will require shared state during fetch operations, a common
context is required. So pass along the "this" parameter in various revocation
functions.
No part of IKE/IPsec or X.509 uses MD2 anymore, so there really is no
reason to still support it (unlike MD4 that is used in EAP-MSCHAPv2,
MD5 that's used in EAP-MD5, or SHA-1 that's used for e.g. NAT-D hashes).
It caused test vectors to fail on systems where OpenSSL is built with
MD2 support but has it disabled at runtime.