Commit Graph
15305 Commits
Author SHA1 Message Date
R. Elliott Childre 075323d895 identification: Fix double-free when cloning empty IDs
The clone() method was missing a branch when there is an encoded chunk
of length 0 that still needed to be cloned.  Otherwise, the destruction
of the clone frees the same pointer that the original owns.

This double free was found with an improved `fuzz_ids` fuzz harness and
a two byte input to create an identification from "@#" or [0x40, 0x23].
It can also be triggered with `<type>:#` e.g. `dns:#`.

One of the problematic constructors is used to parse EAP-Identities,
which are cloned before storing them in the auth-cfg.   So this can be
triggered by an unauthenticated attacker.

Note that while the length check was already added with 418dbd6243
("cloning %any ID without zero-byte memleak") and identities that trigger
this can be created since 86ab5636c2 ("support for @#hex ID_KEY_ID
identification_t"), it was the referenced commit that made the length
check problematic.

Fixes: 2147da40a5 ("simplified identification_t.clone() using memcpy")
Fixes: CVE-2026-47895
2026-06-05 17:35:06 +02:00
Tobias Brunner 5fc403702b leak-detective: Also ignore unknown memory freed in OPENSSL_cleanup()
It seems that 18a94525a7 was a bit hasty.  Apparently, it's still the
case that there were reports (at least in some test scenarios).  Luckily,
the new facility added in the previous commit allows us to whitelist
these allocations without having to ignore all unknown memory.
2026-06-05 16:58:45 +02:00
Tobias Brunner 3216646bdb leak-detective: Add workaround for unknown memory reports with glibc
With glibc, there is an issue if TZ is not set, which causes a change
of the internally cached TZ value.  Because the original value was
cached before LD was active via `init_static_allocations()`, the memory
is freed as unknown memory later.  This change allows whitelisting
a function that might free such memory (tzset() only for now).
2026-06-05 16:40:49 +02:00
Tobias Brunner 4df53109a5 eap-aka: Make sure AT_RAND has the correct length in AKA-Challenge
This prevents an OOB read if the AT_RAND data is shorter than the
expected 16 bytes.

The check for AT_AUTN is changed for consistency even though its length
is already enforced by the parser (for AT_RAND it isn't because EAP-SIM
expects a length of either 32 or 48 bytes).

Fixes: aea334ec1c ("Splitted EAP-AKA in peer and server implementations, use libsimaka helper library")
2026-06-04 11:31:11 +02:00
Tobias Brunner a904f9125d kernel-netlink: Enable mixed-family IPComp scenarios
Since 6.3, the kernel allows setting XFRM_STATE_AF_UNSPEC for transport
mode SAs, which allows mixed-family use of IPComp.
2026-06-04 11:22:58 +02:00
Tobias Brunner 531de4d858 pkcs7: Fail parsing PKCS#7 signed-data if content can't be parsed
This avoids a crash after verifying the signed attributes in the signature
enumerator.
2026-06-01 18:21:43 +02:00
Tobias Brunner 74fd2593a7 charon-cmd: Make local host configurable
This allows preferring a particular address family (via 0.0.0.0 or ::)
or even a specific local address.
2026-06-01 09:03:02 +02:00
Tobias Brunner 64e01e2812 charon-cmd: Use %any as local address so IPv4 is not preferred
When resolving the remote host, we first determine if a particular
address family is preferred locally.  With `0.0.0.0` that's IPv4, with
`%any` that's not the case.  So we use the latter to allow resolvers
to return an IPv6 address.
2026-06-01 08:54:49 +02:00
Tobias Brunner 5185b6f6e8 swanctl: Add option to only list a specific connection with --list-conns 2026-05-28 16:54:06 +02:00
Tobias Brunner b3ef007d28 vici: Return proposals in a more structured way
This allows clients to distinguish between algorithms of different
transform types more easily.  The names are similar to those used
when returning the algorithms of the selected proposal in list-sas (except
for `ke` instead of `dh` and `sn` instead of `esn` to reflect the
latest IETF/IANA changes).
2026-05-28 14:40:25 +02:00
Mathijs Smit c70ab88363 vici: Include proposals in connection listings
Signed-off-by: Mathijs Smit <smit.mathijs@gmail.com>
2026-05-28 14:40:25 +02:00
Tobias Brunner eb9e44f783 ike-cfg: Add flag to suppress log message when retrieving proposals 2026-05-28 14:40:25 +02:00
Tobias Brunner 60adb95f58 child-cfg: Add flag to suppress log message when retrieving proposals 2026-05-28 14:40:25 +02:00
Tobias Brunner bff405c349 oid: Fix confusing identifiers for elliptic curves over prime fields
SECT (indicating a binary field) was incorrectly used in constants for
the SECP (prime field) curves.
2026-05-28 13:30:07 +02:00
Tobias Brunner 5fcf1fc0ef public-key: Fix mapping of RSA with PKCS#1 v1.5 and SHA3-512 to OID
Fixes: 40f2589abf ("gmp: Support of SHA-3 RSA signatures")
2026-05-28 13:21:22 +02:00
Tobias Brunner dc8b479eb8 ike-init: Fix key derivation if SA is reset after IKE_INTERMEDIATE retransmits
Because the `derived` flag was not reset (it's set after the initial
IKE_SA_INIT exchange), no keys would get derived when sending
IKE_INTERMEDIATE during the next try.  As there is then no `aead_t`
available, encrypting the message would fail and the initiation would
remain stuck.

Fixes: 0d49ddec2e ("ike-init: Add support for multiple key exchanges")
2026-05-22 14:33:28 +02:00
Thomas Jarosch f0a489f7e2 credential-manager: Check certificate expiry also for trusted self-signed certs
This serves as a defense-in-depth measure against forgotten
configs/credentials.
2026-05-22 14:33:28 +02:00
Thomas Jarosch 0d17838b99 credential-manager: Check expiry also for last cert in incomplete trust chain
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.
2026-05-22 14:33:28 +02:00
Tobias Brunner 95f615a603 unit-tests: Replace expired self-signed TLS certificates 2026-05-22 14:33:28 +02:00
Tobias Brunner 9ac3db8e63 swid-gen: Use process_t to avoid potential command injection
In a targeted request, the software ID is provided by the IMV.  If no
database is used (which is not the recommended setup), the ID is not
validated and could potentially contain special characters.  With the
previous command string construction and use of popen(), which runs a
shell, that could potentially allow running arbitrary commands.
2026-05-19 17:27:33 +02:00
Tobias Brunner ac703e48c3 ike-init: Destroy KE object after each derivation during initial exchanges
This fixes error handling in build_r_multi_ke() so we don't incorrectly
reuse the object from the previous exchange if we don't receive a KE
payload.
2026-05-19 17:27:33 +02:00
Tobias Brunner 158b4c4aa4 child-rekey: Avoid potential use-after-free for deleted SPIs array 2026-05-19 17:27:33 +02:00
Tobias Brunner ea569867d2 tun-device: Fix setting IPv6 address on Linux
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")
2026-05-19 17:27:33 +02:00
Tobias Brunner 7bdd4bf77b swanctl: Make sure options array passed to getopt_long() ends with a NULL entry 2026-05-19 17:27:33 +02:00
Tobias Brunner a1ad9e39fc pki: Make sure options array passed to getopt_long() ends with a NULL entry 2026-05-19 17:27:33 +02:00
Tobias Brunner 4950a37e56 pts: Fix error string if mandatory DH group is unavailable
Fixes: 0841280cdd ("libimcv: Fix build with DEBUG_LEVEL < 3")
2026-05-19 17:27:33 +02:00
Tobias Brunner 3b224a70ba xof: Fix mapping for SHA3-512 to a corresponding MGF1 identifier
Fixes: 3b7c49bc31 ("mgf1: Support of RSA PSS with SHA3 hash")
2026-05-19 17:27:33 +02:00
Tobias Brunner a26dd3da33 openssl: Check that EC keys don't have explicit params for internally loaded keys
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.
2026-05-19 17:27:33 +02:00
Tobias Brunner ab19f691c7 botan: Fix registration of ECDSA signature/verification plugin features
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.
2026-05-19 17:27:33 +02:00
Tobias Brunner 7e7629499f receiver: Avoid unaligned memory access in COOKIE verification
This access could be an issue on platforms with strict alignment
requirements.
2026-05-19 17:27:33 +02:00
Tobias Brunner 8f22345542 dhcp: Fix potential OOB read when parsing DHCP messages
The missing parentheses around the additions when calculating optlen
in the previous code can cause an out-of-bound read of up to 228 bytes
if no DHCP_OPTEND is found in the message (the calculation basically
evaluated to `- 20 + 8 + 240`).

Since the buffer for the received packet (via pf_handler_t) is located
on the stack, this shouldn't cause much of an issue in practice.
2026-05-19 17:27:33 +02:00
Tobias Brunner 8ff3238027 openssl: Prevent OpenSSL from using posix_memalign() if LD is enabled
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.
2026-05-06 10:46:43 +02:00
Tobias Brunner 374b17fe88 openssl: Fix 'const' issues that came up with OpenSSL 4 2026-05-06 10:46:43 +02:00
Tobias Brunner 528e5f07c3 openssl: Use functions for ASN.1 struct members hidden in OpenSSL 4
According to the docs, most ASN.1 types are just typedefs of ASN1_STRING.
2026-05-06 10:46:43 +02:00
Thomas Egerer 82c01b7060 openssl: Use openssl_i2chunk when creating ASN.1 chunks
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 <thomas.egerer@secunet.com>
2026-05-06 10:46:43 +02:00
Tobias Brunner 4821758d46 kernel-pfkey: Add some sanity checks when processing kernel events
These are always set in kernel messages, but just make sure so static
analyzers like SonarQube are happy.
2026-04-23 15:21:45 +02:00
Tobias Brunner 0a64c27a1f constant-time: Fix Doxygen group assignment 2026-04-23 11:46:52 +02:00
Tobias Brunner b4ba8a6fb5 openssl: Fix memory leak if ipAddrBlock is non-canonical 2026-04-22 14:12:12 +02:00
Tobias Brunner 9e8292cb37 nm: Version bump to 1.6.5 2026-04-22 14:01:52 +02:00
Tobias Brunner e2fa67e8fc gmp: Avoid crash and timing leaks in PKCS#1 v1.5 decryption padding validation
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
2026-04-21 16:48:56 +02:00
Tobias Brunner 90fd268088 utils: Add constant-time comparison primitives for uint32_t 2026-04-21 16:48:56 +02:00
Tobias Brunner 8dae5605a7 pkcs7: Avoid NULL pointer dereference when verifying padding in enveloped content
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
2026-04-21 16:48:56 +02:00
Tobias Brunner c6a2185c42 pkcs5: Fail decryption if data is empty
This avoids the previous bug early.
2026-04-21 16:48:56 +02:00
Tobias Brunner 4da84019cc pkcs5: Avoid NULL pointer dereference when verifying padding
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
2026-04-21 16:48:56 +02:00
Tobias Brunner 56c7f0d13d 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: 7fbe2e27ec ("tls-server: TLS 1.3 support for TLS server implementation")
Fixes: CVE-2026-35328
2026-04-21 16:48:56 +02:00
Tobias Brunner 64130ede5c constraints: Reject excluded directoryName (DN) name constraints
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
2026-04-21 16:48:56 +02:00
Tobias Brunner c66143db48 constraints: Match FQDN and email addresses case-insensitively
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
2026-04-21 16:48:56 +02:00
Tobias Brunner 1e0643bef1 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 7b3c01845f ("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: e6cce7ff0d ("Prepend point format to ECDH public key")
Fixes: CVE-2026-35332
2026-04-21 16:48:56 +02:00
Lukas Johannes Möller e067d24293 libradius: Reject undersized attributes in enumerator
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@johannes-moeller.dev>

Fixes: 4a6b84a934 ("reintegrated eap-radius branch into trunk")
Fixes: CVE-2026-35333
2026-04-21 16:48:56 +02:00
Lukas Johannes Möller aa5aaebc33 libsimaka: Reject zero-length EAP-SIM/AKA attributes
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@johannes-moeller.dev>

Fixes: f8330d0395 ("Added a libsimaka library with shared message handling code for EAP-SIM/AKA")
Fixes: CVE-2026-35330
2026-04-21 16:48:56 +02:00