Commit Graph
381 Commits
Author SHA1 Message Date
Tobias Brunner bff18d9048 tls-protection: Reject unencrypted TLS 1.3 records
We only allow unencrypted change_cipher_spec records (as before), which
are handled by the upper layers accordingly.  Without the check, we
also accepted unprotected alerts and handshake records that could
potentially cause state confusion.

Fixes: 7a2b02667c ("libtls: Implement TLS 1.3 handshake on client-side")
2026-07-23 10:26:08 +02:00
Tobias Brunner fcac9fe5df tls-socket: Avoid accessing stale data when processing application data
In non-blocking mode, the previous code set `in_done` to -1 (SIZE_MAX)
if `recv()` would block and nothing was read yet.  If this was followed
by a call to `write()` and `process()` is called and actually processed
application data, the length calculation in the callback underflows and
`memcpy()` would write to `in.ptr + SIZE_MAX`.  Since `read()` already
sets `errno` to `EWOULDBLOCK` and returns -1 if `in_done` is 0, the
removed check was redundant anyway.

Also, the buffer from the previous `read()` call might not be valid
anymore when `write()` is called (e.g. `splice()` uses the same buffer
for both, and the buffer could even be defined on a now invalid stack
frame of the function that called `read()` previously).  Clearing the
data avoids that and ensures the application data is cached until the
next call to `read()`.

However, triggering this is rather difficult as `write()` should only
reach `recv()` while the handshake isn't complete and until then
`process_application()` doesn't accept application data.  But if the
handshake is completed during a call to `write()` that follows a
non-blocking read and data immediately arrives, it's theoretically
imaginable.  This scenario is highly unlikely on a TLS server, which
starts the process with a call to `read()` that then basically loops
until the handshake is done.  Even if multiple calls are required, the
server will generally not call `write()` before it received application
data.  And any calls to `write()` afterwards do not reach `recv()`
anymore (unless no data to send was passed, which would be weird, or
maybe for some weird corner case that lets `build()` fail before all
outbound application data was processed).
2026-07-21 10:37:43 +02:00
Tobias Brunner 95f615a603 unit-tests: Replace expired self-signed TLS certificates 2026-05-22 14:33:28 +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 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
Tobias Brunner b56b3d48b6 tls-server: Avoid allocating large buffer for cipher suites on stack
The `cipher_suites` field has a 16-bit length field, so up to 32k 2-byte
cipher suites could technically be proposed.  With `tls_cipher_suite_t`
typically being 4 bytes wide, the necessary allocation for the temporary
array can be up to 128 KiB.  Even though this should be fine on typical
systems, we avoid potentially overflowing the stack by using malloc()
instead of alloca().
2026-04-02 08:34:23 +02:00
Tobias Brunner 236ef93c50 tls-peer: Ensure TLS 1.3 CertificateRequest structure is valid
If nothing was read from the message, the previous code could result in
a crash depending on where `ext.ptr` pointed to, as determined by the
current stack contents.  Since TLS 1.3 is still disabled by default and
this is usually used for TLS-based EAP methods after validating the
IKEv2 server's certificate, the real world impact seems relatively low.

Fixes: 9ef46cfaf9 ("tls-peer: Mutual authentication support for TLS 1.3")
2026-04-02 08:14:29 +02:00
Tobias Brunner b83aed1362 libtls: Use correct constant in error message
Closes strongswan/strongswan#2896

Fixes: e731396280 ("tls-server: Check if peer sent hash and signature algorithms")
2025-10-02 10:02:49 +02:00
Tobias Brunner 9da68ec9f5 libtls: Fix double-free when enumerating private keys 2025-08-22 12:07:55 +02:00
Tobias Brunner d5d2568ff0 callback-job: Replace return_false() in constructors with dedicated function
Besides being clearer, this fixes issues with GCC 15.  The latter uses
C23 by default, which changes the meaning of function declarations
without parameters such as

	bool return false();

Instead of "this function takes an unknown number of arguments", this
now equals (void), that is, "this function takes no arguments".  So we
run into incompatible pointer type warnings all over when using such
functions.  They could be cast to (void*) but this seems the cleaner
solution for this use case.
2025-03-19 10:22:37 +01:00
Tobias Brunner b5e4bf4b6c tls-server: Also change DH group when selecting a different EC curve
If we initially selected a group the peer doesn't support (e.g. because
curve25519 is the first ECDH group provided by plugins), then found
a supported curve, we previously still instantiated a DH object for the
original group and might have formatted the parameters incorrectly.
2023-11-06 11:00:51 +01:00
Tobias Brunner 6086029056 libtls: Fix build with DEBUG_LEVEL < 3 2023-05-08 17:32:17 +02:00
Tobias Brunner db87087fae tls: Only return EAP MSK if TLS handshake is complete
The MSK is generated when the keys are derived.  For TLS 1.3 that's also
when the handshake is complete.  However, for TLS 1.2 it happens when
generating or processing the ClientKeyExchange message, which, on the
client, happens before the final Finished handshake message has been
received from the server.  This caused the EAP-TLS client to accept an
EAP-Success message instead of the server's final TLS handshake
messages, unintentionally allowing servers to cut the exchange short by
two EAP messages (in the regular exchange the response to the server's
final handshake messages is an empty EAP-Response, which is then
followed by the server's EAP-Success).

While this is not correct, it does not seem to pose a security issue.
If DH is used as key exchange, the server signs the ServerKeyExchange
message and the client is sure to communicate with a trusted server
before it derives the MSK.  If RSA encryption is used as key exchange,
the client sends the premaster secret, on which the MSK is based,
encrypted with the server's public key (as extracted from the trusted
certificate).  An attacker won't be able to decrypt this and, therefore,
can't derive the same MSK to generate a valid AUTH payload and the IKE
authentication will fail.
2023-03-21 16:11:49 +01:00
Tobias Brunner 5401a74d36 eap-tls: Add support for TLS 1.3
As defined in RFC 9190, a "protected success indication" (0x00) is sent
from the server to the client over the TLS connection when using TLS 1.3.

The client responds with an empty EAP message, which is interpreted as
acknowledgement in our stack.

If we ever support session resumption with tunneled methods such as
EAP-TTLS, we'd have to send such an indication there too.
2023-02-22 13:34:53 +01:00
Tobias Brunner 06abdf1d31 tls-crypto: Fix MSK calculation for TLS 1.3
As noted in 121ac4b9e3 ("tls-crypto: Generate MSK for TLS 1.3"), the
calculation was only preliminary.  It is now fixed according to RFC 9190
and draft-ietf-emu-tls-eap-types (soon to become an RFC, currently in
the RFC editor queue).

Fixes: 121ac4b9e3 ("tls-crypto: Generate MSK for TLS 1.3")
2023-02-22 13:34:31 +01:00
Tobias Brunner 4d3fc90caf libtls: Fix double-free for untrusted peer certificates
`public` is returned, but previously only if a trusted key was found.
We obviously don't want to return untrusted keys and since the reference
was correctly destroyed after determining the key type, this later caused
a double-free.

Fixes: 63fd718915 ("libtls: call create_public_enumerator() with key_type")
2023-02-17 15:11:43 +01:00
Tobias Brunner bdc7f84a23 unit-tests: Don't use test data on stack for TLS socket tests
The stack of that function might not be valid anymore once data is read.
2022-09-15 12:16:12 +02:00
Tobias Brunner 55f7268eb1 unit-tests: Let the TLS server thread close its own socket
Closing the socket from the main thread, while the server thread is
still in accept() (or is just about to enter it), seems to
occasionally cause a deadlock on macOS.
2022-09-06 15:40:32 +02:00
Tobias Brunner 879ffd7ece unit-tests: Make TLS echo server cancelable
Seems to be required on macOS (libtls tests didn't run before the recent
implicit enabling via pki).  Other platforms apparently let accept() fail
if the socket is shutdown/closed in teardown_creds(), macOS apparently
doesn't do that.
2022-09-06 09:33:00 +02:00
Tobias Brunner 88859b506c libtls: Fix encoding of TLS 1.3 certificate extension as server
Same as 9664ef4ba6 ("libtls: Fixed encoding of TLS 1.3 certificate
extension") but for the server.
2022-09-06 09:33:00 +02:00
Andreas Steffen 52a3c3662d libtls: the signature unit tests use scheme-specific credentials 2022-08-26 12:17:22 +02:00
Andreas Steffen 63fd718915 libtls: call create_public_enumerator() with key_type 2022-08-26 12:17:22 +02:00
Andreas Steffen a417703301 libtls: enforce correct signature scheme for ECDSA keys 2022-08-26 12:17:22 +02:00
Andreas Steffen 9664ef4ba6 libtls: Fixed encoding of TLS 1.3 certificate extension 2022-08-25 10:51:05 +02:00
Andreas Steffen b392fbd68c libtls: unit tests run with default plugins
The gcm plugin has been added to the default plugins and all
certificate types are loaded to allow the libtls socket unit
tests to run with the strongSwan default plugins.
2022-08-25 07:02:29 +02:00
Andreas Steffen a3914d7db5 libtls: Send empty cert payload upon cert request
Currently when a TLS client doesn't have a certificate, it doesn't
send a certficiate payload upon receiving a certificate request
from the TLS server. According to the TLS 1.2 and 1.3 RFCs an
empty certificate payload must be sent.
2022-08-25 07:02:29 +02:00
Andreas Steffen b7c167f972 Rename MODP_NONE to KE_NONE 2022-06-29 10:28:50 +02:00
Tobias Brunner 3af7c6db87 Rename diffie_hellman_t to key_exchange_t and change the interface etc.
This makes it more generic so we can use it for QSKE methods.
2022-06-29 10:28:50 +02:00
Tobias Brunner 19ef2aec15 Update copyright headers after acquisition by secunet 2022-06-28 10:22:56 +02:00
Tobias Brunner a6a0fa980f tls-crypto: Initialize cipher suites arrays to avoid warnings 2022-04-22 09:49:37 +02:00
Tobias Brunner df16d7902a tls-hkdf: Use plugin-provided prf+ 2022-04-14 19:02:56 +02:00
Tobias Brunner 2ade4311bc tls-server: Use correct error alerts if client doesn't send a certificate
TLS 1.3 defines a specific alert for this and for TLS 1.2, RFC 5246,
section 7.4.6 defines handshake_failure as correct response.
2022-03-01 10:05:26 +01:00
Tobias Brunner eccfd27f03 tls-peer: Simplify identity check for server certificate
has_subject() already matches the identity against the subject DN and
all the SANs (it actually already did when this check was added with
c811479986 ("Strictly check if the server certificate matches the TLS
server identity")).
2022-02-15 16:54:39 +01:00
Tobias Brunner e4b4aabc49 libtls: Enforce client/server identity when looking for public key
The client already enforces that the server identity is contained in the
received certificate.  But on the server, the referenced commit changed
the lookup from the configured (or adopted if %any was configured) client
identity to the subject DN of the received client certificate.  So any
client with a trusted certificate was accepted.

Fixes: d2fc9b0961 ("tls-server: Mutual authentication support for TLS 1.3")
Closes strongswan/strongswan#873
2022-02-15 16:53:25 +01:00
Tobias Brunner 88e7654c6c libtls: Shutdown server socket in test teardown function
If a test fails and the server thread is blocked reading on the socket,
it would stay stuck.
2021-12-08 11:32:55 +01:00
Tobias Brunner d95381ec7a tls-socket: Handle sending fatal errors better
In particular as server, the previous code might cause it to hang in
recv() if this case wasn't triggered by a close notify (followed by a
shutdown of the socket) but it e.g. failed processing a ServerHello and
responded with a fatal alert.

Fixes: 09fbaad6bd ("tls-socket: Don't fail reading if sending data failed")
2021-12-08 11:32:50 +01:00
Andreas Steffen 4abb29f639 credentials: Added void *params to public_key encrypt() and private_key decrypt() methods 2021-11-09 17:58:28 +01:00
Tobias Brunner f6aafb3005 Fixed some typos, courtesy of codespell
Main change is the conversion from the British cancelling/-ed to the
American canceling/-ed.
2021-06-25 11:32:29 +02:00
Tobias Brunner 760f3b730f tls-server: Add flag that makes client authentication optional
This allows clients to send an empty certificate payload if the server
sent a certificate request.  If an identity was set previously, it will
be reset so get_peer_id() may be used to check if the client was
authenticated.
2021-02-18 15:35:46 +01:00
Tobias Brunner 11a4687930 libtls: Add control flags and replace GENERIC_NULLOK purpose with one 2021-02-18 15:10:29 +01:00
Tobias Brunner 4b7cfb252e tls-server: Use subject DN as peer identity if it was ID_ANY
To request client authentication if we don't know the client's identity,
it's possible to use ID_ANY.  However, if we don't change the identity
get_peer_id() would still report ID_ANY after the authentication.
2021-02-18 12:34:05 +01:00
Tobias Brunner 024120f8ea tls-eap: Only servers conclude EAP method after processing packets
As client with older TLS versions, we have to ack the receipt of the server's
Finished message instead.

Fixes: 083f38259c ("tls-eap: Conclude EAP method also after processing packets")
2021-02-18 12:02:32 +01:00
Tobias Brunner 8384527ff5 tls-crypto: Fix potential memory leak
Fixes: d8e42a3d4e ("tls-crypto: Share private key search between client and server")
2021-02-16 14:52:43 +01:00
Tobias Brunner 74b9ba7cdb tls-crypto: Simplify and extend cipher config filter
This way we automatically can filter for newer algorithms (e.g.
chacha20poly1305).
2021-02-12 14:35:23 +01:00
Tobias Brunner 966a26eaa2 tls-server: Support x25519/448 for TLS 1.2 2021-02-12 14:35:23 +01:00
Tobias Brunner f77ecf0728 tls-crypto: Fallback to any supported ECDH group
If the default group listed in the cipher suite is not supported, we try
to use any other supported group (the groups are negotiated separately
so we are not locked in to a specific group).
2021-02-12 14:35:23 +01:00
Tobias Brunner 311405c34d tls-crypto: Don't filter suites with specific ECDH group if any is available
Since DH groups (or with TLS < 1.3 curves) are negotiated separately,
it doesn't matter which one is listed in the cipher suite as any one could
be used.
2021-02-12 14:35:23 +01:00
Pascal Knecht e3757300eb tls-crypto: Add signature scheme config file filter
And add signature scheme unit tests.
2021-02-12 14:35:23 +01:00
Pascal Knecht e5b6565730 tls-crypto: Rename DH group/key exchange method config option
TLS key exchange methods are now configured with `ke_group`.
2021-02-12 14:35:23 +01:00
Tobias Brunner a60e248b0d libtls: Increase default min version to 1.2
The older versions are generally considered deprecated (there is an
Internet-Draft that aims to do that formally).
2021-02-12 14:35:23 +01:00