]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
tls-server: Only accept non-empty ECDH public keys with TLS < 1.3
authorTobias Brunner <tobias@strongswan.org>
Fri, 20 Mar 2026 16:38:07 +0000 (17:38 +0100)
committerTobias Brunner <tobias@strongswan.org>
Tue, 21 Apr 2026 14:48:56 +0000 (16:48 +0200)
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

index fc767c0fad9fbe8f81fbfc06fc791b99b94cefbe..60fbcd2ea6cbcfa92eeefea58a95785ffd5ead10 100644 (file)
@@ -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);