From f01b3c75198aeadb60b7ace2284b56ebea8ec6b6 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 20 Mar 2026 17:38:07 +0100 Subject: [PATCH] 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 --- src/libtls/tls_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c index f70f0504e523..0d2ae1a72403 100644 --- a/src/libtls/tls_server.c +++ b/src/libtls/tls_server.c @@ -860,7 +860,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); -- 2.43.0