Commit 447426a06c for openssl.org
commit 447426a06c20a7bd20bc30d6987fece865788859
Author: Matt Caswell <matt@openssl.org>
Date: Tue Mar 3 12:30:24 2026 +0000
Restrict the number of supported groups/sig algs
We restrict the number of supported groups and sig algs that the server
is willing to accept from the client to 128 (for both). Any more than
this are simply ignored. This number is significantly more than the total
amount of current codepoints assigned by IANA for these extensions.
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
MergeDate: Fri Mar 6 10:33:03 2026
(Merged from https://github.com/openssl/openssl/pull/30263)
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
index e91e910b1d..8a48c2099a 100644
--- a/ssl/ssl_local.h
+++ b/ssl/ssl_local.h
@@ -2794,7 +2794,7 @@ int tls_choose_sigalg(SSL_CONNECTION *s, int fatalerrs);
__owur long ssl_get_algorithm2(SSL_CONNECTION *s);
__owur int tls12_copy_sigalgs(SSL_CONNECTION *s, WPACKET *pkt,
const uint16_t *psig, size_t psiglen);
-__owur int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen);
+__owur int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen, size_t maxnum);
__owur int tls1_save_sigalgs(SSL_CONNECTION *s, PACKET *pkt, int cert);
__owur int tls1_process_sigalgs(SSL_CONNECTION *s);
__owur int tls1_set_peer_legacy_sigalg(SSL_CONNECTION *s, const EVP_PKEY *pkey);
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index 97c7fc9611..6c84518fae 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -19,6 +19,7 @@
#define COOKIE_STATE_FORMAT_VERSION 1
+#define MAX_SUPPORTED_GROUPS 128
#define MAX_KEY_SHARES 16
/*
@@ -1225,9 +1226,16 @@ int tls_parse_ctos_supported_groups(SSL_CONNECTION *s, PACKET *pkt,
OPENSSL_free(s->ext.peer_supportedgroups);
s->ext.peer_supportedgroups = NULL;
s->ext.peer_supportedgroups_len = 0;
+ /*
+ * We only pay attention to the first 128 supported groups and ignore
+ * any beyond that limit. Theoretically this could cause problems if
+ * the client also uses one of these groups (say in a key share extension)
+ * - but why would any valid client be sending such a huge supported
+ * groups list?
+ */
if (!tls1_save_u16(&supported_groups_list,
&s->ext.peer_supportedgroups,
- &s->ext.peer_supportedgroups_len)) {
+ &s->ext.peer_supportedgroups_len, MAX_SUPPORTED_GROUPS)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index ec7a7b643b..1f2ede5d92 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -29,6 +29,8 @@
#include "quic/quic_local.h"
#include <openssl/ct.h>
+#define MAX_SIGALGS 128
+
static const SIGALG_LOOKUP *find_sig_alg(SSL_CONNECTION *s, X509 *x, EVP_PKEY *pkey);
static int tls12_sigalg_allowed(const SSL_CONNECTION *s, int op, const SIGALG_LOOKUP *lu);
@@ -3673,7 +3675,7 @@ static int tls1_set_shared_sigalgs(SSL_CONNECTION *s)
return 1;
}
-int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen)
+int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen, size_t maxnum)
{
unsigned int stmp;
size_t size, i;
@@ -3687,6 +3689,13 @@ int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen)
size >>= 1;
+ /*
+ * We ignore any entries in the list larger than the maximum number we
+ * will accept.
+ */
+ if (size > maxnum)
+ size = maxnum;
+
if ((buf = OPENSSL_malloc_array(size, sizeof(*buf))) == NULL)
return 0;
for (i = 0; i < size && PACKET_get_net_2(pkt, &stmp); i++)
@@ -3713,12 +3722,16 @@ int tls1_save_sigalgs(SSL_CONNECTION *s, PACKET *pkt, int cert)
if (s->cert == NULL)
return 0;
+ /*
+ * We restrict the number of signature algorithms we are willing to process
+ * to 128. Any beyond this number are simply ignored.
+ */
if (cert)
return tls1_save_u16(pkt, &s->s3.tmp.peer_cert_sigalgs,
- &s->s3.tmp.peer_cert_sigalgslen);
+ &s->s3.tmp.peer_cert_sigalgslen, MAX_SIGALGS);
else
return tls1_save_u16(pkt, &s->s3.tmp.peer_sigalgs,
- &s->s3.tmp.peer_sigalgslen);
+ &s->s3.tmp.peer_sigalgslen, MAX_SIGALGS);
}
/* Set preferred digest for each key type */