Commit 1e0643bef1 for strongswan.org
commit 1e0643bef105704337efc141a37dfcfbaa53cb1f
Author: Tobias Brunner <tobias@strongswan.org>
Date: Fri Mar 20 17:38:07 2026 +0100
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
diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c
index fc767c0fad..60fbcd2ea6 100644
--- a/src/libtls/tls_server.c
+++ b/src/libtls/tls_server.c
@@ -862,7 +862,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);