]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
supported_groups: give KEM groups higher priority than DH
authorDaiki Ueno <ueno@gnu.org>
Wed, 9 Oct 2024 09:10:25 +0000 (18:10 +0900)
committerDaiki Ueno <ueno@gnu.org>
Tue, 29 Oct 2024 13:03:44 +0000 (22:03 +0900)
Signed-off-by: Daiki Ueno <ueno@gnu.org>
lib/algorithms.h
lib/ext/supported_groups.c

index 9aaa64b030128a978d1abf325625f8202a7c5b82..4eb48e9cdde57fc18a52df7ac2b7de21012ae928 100644 (file)
@@ -49,6 +49,9 @@
         ((x) == GNUTLS_PK_EDDSA_ED25519) || ((x) == GNUTLS_PK_ECDH_X448) || \
         ((x) == GNUTLS_PK_EDDSA_ED448))
 
+#define IS_KEM(x) \
+       (((x) == GNUTLS_PK_MLKEM768) || ((x) == GNUTLS_PK_EXP_KYBER768))
+
 #define SIG_SEM_PRE_TLS12 (1 << 1)
 #define SIG_SEM_TLS13 (1 << 2)
 #define SIG_SEM_DEFAULT (SIG_SEM_PRE_TLS12 | SIG_SEM_TLS13)
index 510ef6d23011d545d380243198d6cbb7b2382522..5461c868e76ccc543aabe1b7ebe2330dbe6e1d09 100644 (file)
@@ -105,8 +105,10 @@ static int _gnutls_supported_groups_recv_params(gnutls_session_t session,
        unsigned tls_id;
        unsigned min_dh;
        unsigned j;
-       int serv_ec_idx, serv_dh_idx; /* index in server's priority listing */
-       int cli_ec_pos, cli_dh_pos; /* position in listing sent by client */
+       int serv_ec_idx, serv_dh_idx,
+               serv_kem_idx; /* index in server's priority listing */
+       int cli_ec_pos, cli_dh_pos,
+               cli_kem_pos; /* position in listing sent by client */
 
        if (session->security_parameters.entity == GNUTLS_CLIENT) {
                /* A client shouldn't receive this extension in TLS1.2. It is
@@ -132,8 +134,8 @@ static int _gnutls_supported_groups_recv_params(gnutls_session_t session,
                /* we figure what is the minimum DH allowed for this session, if any */
                min_dh = get_min_dh(session);
 
-               serv_ec_idx = serv_dh_idx = -1;
-               cli_ec_pos = cli_dh_pos = -1;
+               serv_ec_idx = serv_dh_idx = serv_kem_idx = -1;
+               cli_ec_pos = cli_dh_pos = cli_kem_pos = -1;
 
                /* This extension is being processed prior to a ciphersuite being selected,
                 * so we cannot rely on ciphersuite information. */
@@ -178,6 +180,14 @@ static int _gnutls_supported_groups_recv_params(gnutls_session_t session,
                                                                break;
                                                        serv_ec_idx = j;
                                                        cli_ec_pos = i;
+                                               } else if (IS_KEM(group->pk)) {
+                                                       if (serv_kem_idx !=
+                                                                   -1 &&
+                                                           (int)j >
+                                                                   serv_kem_idx)
+                                                               break;
+                                                       serv_kem_idx = j;
+                                                       cli_kem_pos = i;
                                                }
                                        } else {
                                                if (group->pk == GNUTLS_PK_DH) {
@@ -190,6 +200,11 @@ static int _gnutls_supported_groups_recv_params(gnutls_session_t session,
                                                                break;
                                                        cli_ec_pos = i;
                                                        serv_ec_idx = j;
+                                               } else if (IS_KEM(group->pk)) {
+                                                       if (cli_kem_pos != -1)
+                                                               break;
+                                                       cli_kem_pos = i;
+                                                       serv_kem_idx = j;
                                                }
                                        }
                                        break;
@@ -197,7 +212,7 @@ static int _gnutls_supported_groups_recv_params(gnutls_session_t session,
                        }
                }
 
-               /* serv_dh/ec_pos contain the index of the groups we want to use.
+               /* serv_{dh,ec,kem}_idx contain the index of the groups we want to use.
                 */
                if (serv_dh_idx != -1) {
                        session->internals.cand_dh_group =
@@ -221,6 +236,21 @@ static int _gnutls_supported_groups_recv_params(gnutls_session_t session,
                        }
                }
 
+               /* KEM can only be used in TLS 1.3, where no separation from
+                * ECDH and DH, and thus only cand_group is set here.
+                */
+               if (serv_kem_idx != -1) {
+                       if (session->internals.cand_group == NULL ||
+                           (session->internals.priorities->server_precedence &&
+                            serv_kem_idx < MIN(serv_ec_idx, serv_dh_idx)) ||
+                           (!session->internals.priorities->server_precedence &&
+                            cli_kem_pos < MIN(cli_ec_pos, cli_dh_pos))) {
+                               session->internals.cand_group =
+                                       session->internals.priorities->groups
+                                               .entry[serv_kem_idx];
+                       }
+               }
+
                if (session->internals.cand_group)
                        _gnutls_handshake_log(
                                "EXT[%p]: Selected group %s\n", session,