From e23b33a9956b45b61bd447169ddd3841ca9dfd61 Mon Sep 17 00:00:00 2001 From: Joachim Vandersmissen Date: Mon, 15 Dec 2025 17:46:12 +1100 Subject: [PATCH] Support FFDHE groups in tls1_shared_group MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Update tls1_shared_group to allow filtering for FFDHE and/or ECDHE groups. This will be used for implementing RFC 7919 groups support in the TLS 1.2 server. As defined in RFC 7919: Codepoints in the "Supported Groups Registry" with a high byte of 0x01 (that is, between 256 and 511, inclusive) are set aside for FFDHE groups Reviewed-by: Viktor Dukhovni Reviewed-by: Matt Caswell Reviewed-by: Saša Nedvědický MergeDate: Thu Feb 5 09:09:38 2026 (Merged from https://github.com/openssl/openssl/pull/24551) --- include/internal/tlsgroups.h | 19 +++++++++++++++++++ providers/common/capabilities.c | 10 +++++----- ssl/s3_lib.c | 2 +- ssl/ssl_local.h | 8 +++++++- ssl/statem/statem_srvr.c | 3 ++- ssl/t1_lib.c | 25 +++++++++++++++++-------- 6 files changed, 51 insertions(+), 16 deletions(-) diff --git a/include/internal/tlsgroups.h b/include/internal/tlsgroups.h index 1fd41993ea7..7c1eb26e3e9 100644 --- a/include/internal/tlsgroups.h +++ b/include/internal/tlsgroups.h @@ -63,4 +63,23 @@ #define OSSL_TLS_GROUP_ID_X25519MLKEM768 0x11EC #define OSSL_TLS_GROUP_ID_SecP384r1MLKEM1024 0x11ED +/* + * RFC 7919: "Codepoints ... between 256 and 511, inclusive ... are set aside + * for FFDHE groups" + */ +#define OSSL_TLS_GROUP_ID_FFDHE_START 0x0100 /* inclusive */ +#define OSSL_TLS_GROUP_ID_FFDHE_END 0x01FF /* inclusive */ + +static ossl_inline int is_ecdhe_group(const uint16_t group_id) +{ + /* This includes the usual EC groups, and also ECX, GOST ... */ + return group_id < OSSL_TLS_GROUP_ID_FFDHE_START; +} + +static ossl_inline int is_ffdhe_group(const uint16_t group_id) +{ + return group_id >= OSSL_TLS_GROUP_ID_FFDHE_START + && group_id <= OSSL_TLS_GROUP_ID_FFDHE_END; +} + #endif diff --git a/providers/common/capabilities.c b/providers/common/capabilities.c index eb96627a67e..e1521dc9d8a 100644 --- a/providers/common/capabilities.c +++ b/providers/common/capabilities.c @@ -80,11 +80,11 @@ static const TLS_GROUP_CONSTANTS group_list[] = { /* 30 */ { OSSL_TLS_GROUP_ID_brainpoolP256r1_tls13, 128, TLS1_3_VERSION, 0, -1, -1, 0 }, /* 31 */ { OSSL_TLS_GROUP_ID_brainpoolP384r1_tls13, 192, TLS1_3_VERSION, 0, -1, -1, 0 }, /* 32 */ { OSSL_TLS_GROUP_ID_brainpoolP512r1_tls13, 256, TLS1_3_VERSION, 0, -1, -1, 0 }, - /* 33 */ { OSSL_TLS_GROUP_ID_ffdhe2048, 112, TLS1_3_VERSION, 0, -1, -1, 0 }, - /* 34 */ { OSSL_TLS_GROUP_ID_ffdhe3072, 128, TLS1_3_VERSION, 0, -1, -1, 0 }, - /* 35 */ { OSSL_TLS_GROUP_ID_ffdhe4096, 128, TLS1_3_VERSION, 0, -1, -1, 0 }, - /* 36 */ { OSSL_TLS_GROUP_ID_ffdhe6144, 128, TLS1_3_VERSION, 0, -1, -1, 0 }, - /* 37 */ { OSSL_TLS_GROUP_ID_ffdhe8192, 192, TLS1_3_VERSION, 0, -1, -1, 0 }, + /* 33 */ { OSSL_TLS_GROUP_ID_ffdhe2048, 112, TLS1_VERSION, 0, -1, -1, 0 }, + /* 34 */ { OSSL_TLS_GROUP_ID_ffdhe3072, 128, TLS1_VERSION, 0, -1, -1, 0 }, + /* 35 */ { OSSL_TLS_GROUP_ID_ffdhe4096, 128, TLS1_VERSION, 0, -1, -1, 0 }, + /* 36 */ { OSSL_TLS_GROUP_ID_ffdhe6144, 128, TLS1_VERSION, 0, -1, -1, 0 }, + /* 37 */ { OSSL_TLS_GROUP_ID_ffdhe8192, 192, TLS1_VERSION, 0, -1, -1, 0 }, /* 38 */ { OSSL_TLS_GROUP_ID_mlkem512, ML_KEM_512_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 }, /* 39 */ { OSSL_TLS_GROUP_ID_mlkem768, ML_KEM_768_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 }, /* 40 */ { OSSL_TLS_GROUP_ID_mlkem1024, ML_KEM_1024_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 }, diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 872812e4f4c..fc3f5892fd2 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -4214,7 +4214,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) parg); case SSL_CTRL_GET_SHARED_GROUP: { - uint16_t id = tls1_shared_group(sc, larg); + uint16_t id = tls1_shared_group(sc, larg, TLS1_GROUPS_ALL_GROUPS); if (larg != -1) return tls1_group_id2nid(id, 1); diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index 606fded1118..382a6cc9023 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -2772,6 +2772,12 @@ __owur int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL_CONNECTION *s); SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n); +#define TLS1_GROUPS_RETURN_NUMBER -1 +#define TLS1_GROUPS_RETURN_TMP_ID -2 +#define TLS1_GROUPS_FFDHE_GROUPS 0 +#define TLS1_GROUPS_NON_FFDHE_GROUPS 1 +#define TLS1_GROUPS_ALL_GROUPS 2 + __owur const TLS_GROUP_INFO *tls1_group_id_lookup(SSL_CTX *ctx, uint16_t curve_id); __owur const char *tls1_group_id2name(SSL_CTX *ctx, uint16_t group_id); __owur int tls1_group_id2nid(uint16_t group_id, int include_unknown); @@ -2783,7 +2789,7 @@ __owur int tls1_get0_implemented_groups(int min_proto_version, TLS_GROUP_INFO *grps, size_t num, long all, STACK_OF(OPENSSL_CSTRING) *out); -__owur uint16_t tls1_shared_group(SSL_CONNECTION *s, int nmatch); +__owur uint16_t tls1_shared_group(SSL_CONNECTION *s, int nmatch, int groups); __owur int tls1_set_groups(uint16_t **grpext, size_t *grpextlen, uint16_t **ksext, size_t *ksextlen, size_t **tplext, size_t *tplextlen, diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index bdb46716ef6..b648e79d15f 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -2666,7 +2666,8 @@ CON_FUNC_RETURN tls_construct_server_key_exchange(SSL_CONNECTION *s, } /* Get NID of appropriate shared curve */ - curve_id = tls1_shared_group(s, -2); + curve_id = tls1_shared_group(s, TLS1_GROUPS_RETURN_TMP_ID, + TLS1_GROUPS_NON_FFDHE_GROUPS); if (curve_id == 0) { SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 02f5d43055b..81bf83d94b4 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -1001,11 +1001,18 @@ end: /*- * For nmatch >= 0, return the id of the |nmatch|th shared group or 0 * if there is no match. - * For nmatch == -1, return number of matches - * For nmatch == -2, return the id of the group to use for - * a tmp key, or 0 if there is no match. + * For nmatch == TLS1_GROUPS_RETURN_NUMBER, return number of matches + * For nmatch == TLS1_GROUPS_RETURN_TMP_ID, return the id of the group to use + * for a tmp key, or 0 if there is no match. + * If groups == TLS1_GROUPS_FFDHE_GROUPS, only shared groups that are FFDHE + * groups (i.e., between OSSL_TLS_GROUP_ID_FFDHE_START and + * OSSL_TLS_GROUP_ID_FFDHE_END, inclusive) will be included in the search. + * If groups == TLS1_GROUPS_NON_FFDHE_GROUPS, only shared groups that are not + * FFDHE groups will be included in the search. + * If groups == TLS1_GROUPS_ALL_GROUPS, all groups will be included in the + * search. */ -uint16_t tls1_shared_group(SSL_CONNECTION *s, int nmatch) +uint16_t tls1_shared_group(SSL_CONNECTION *s, int nmatch, int groups) { const uint16_t *pref, *supp; size_t num_pref, num_supp, i; @@ -1015,8 +1022,8 @@ uint16_t tls1_shared_group(SSL_CONNECTION *s, int nmatch) /* Can't do anything on client side */ if (s->server == 0) return 0; - if (nmatch == -2) { - if (tls1_suiteb(s)) { + if (nmatch == TLS1_GROUPS_RETURN_TMP_ID) { + if (groups != TLS1_GROUPS_FFDHE_GROUPS && tls1_suiteb(s)) { /* * For Suite B ciphersuite determines curve: we already know * these are acceptable due to previous checks. @@ -1051,6 +1058,8 @@ uint16_t tls1_shared_group(SSL_CONNECTION *s, int nmatch) int minversion, maxversion; if (!tls1_in_list(id, supp, num_supp) + || (groups == TLS1_GROUPS_NON_FFDHE_GROUPS && is_ffdhe_group(id)) + || (groups == TLS1_GROUPS_FFDHE_GROUPS && !is_ffdhe_group(id)) || !tls_group_allowed(s, id, SSL_SECOP_CURVE_SHARED)) continue; inf = tls1_group_id_lookup(ctx, id); @@ -1074,7 +1083,7 @@ uint16_t tls1_shared_group(SSL_CONNECTION *s, int nmatch) return id; k++; } - if (nmatch == -1) + if (nmatch == TLS1_GROUPS_RETURN_NUMBER) return k; /* Out of range (nmatch > k). */ return 0; @@ -1907,7 +1916,7 @@ int tls1_check_ec_tmp_key(SSL_CONNECTION *s, unsigned long cid) { /* If not Suite B just need a shared group */ if (!tls1_suiteb(s)) - return tls1_shared_group(s, 0) != 0; + return tls1_shared_group(s, 0, TLS1_GROUPS_NON_FFDHE_GROUPS) != 0; /* * If Suite B, AES128 MUST use P-256 and AES256 MUST use P-384, no other * curves permitted. -- 2.47.3