]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add hybrid ML-KEM based groups to default TLS groups
authorViktor Dukhovni <openssl-users@dukhovni.org>
Mon, 17 Feb 2025 15:41:51 +0000 (02:41 +1100)
committerTomas Mraz <tomas@openssl.org>
Tue, 25 Feb 2025 14:34:23 +0000 (15:34 +0100)
- send two key shares by default
- trim down the list of default groups

The default TLS group list setting is now:
?*X25519MLKEM768 / ?*X25519:?secp256r1 / ?X448:?secp384r1:?secp521r1 / ?ffdhe2048:?ffdhe3072

Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26801)

ssl/ssl_lib.c
ssl/ssl_local.h
ssl/t1_lib.c
test/clienthellotest.c
test/recipes/70-test_tls13cookie.t
test/sslapitest.c
test/tls13groupselection_test.c

index 74246c71b3d85927ce8de0f7046d07f65bfa4f99..3f5abaa48c43e4f64bb3ba1c581959794f9ff56c 100644 (file)
@@ -4383,7 +4383,6 @@ void SSL_CTX_free(SSL_CTX *a)
     OPENSSL_free(a->ext.supportedgroups);
     OPENSSL_free(a->ext.keyshares);
     OPENSSL_free(a->ext.tuples);
-    OPENSSL_free(a->ext.supported_groups_default);
     OPENSSL_free(a->ext.alpn);
     OPENSSL_secure_free(a->ext.secure);
 
index fad69d8d4688713b7e5eea202b085023aa05e08e..3cebc1c50695d85fbb4a7ff10d744920968dbd2b 100644 (file)
@@ -1037,8 +1037,6 @@ struct ssl_ctx_st {
         size_t tuples_len; /* Number of group tuples */
         size_t *tuples; /* Number of groups in each group tuple */
 
-        uint16_t *supported_groups_default;
-        size_t supported_groups_default_len;
         /*
          * ALPN information (we are in the process of transitioning from NPN to
          * ALPN.)
index 83047349a529671c977fb4830dc4e6e9e21bfbb2..04c0c99160edcd0fb71bdfe89e265f18694e48c3 100644 (file)
@@ -198,30 +198,12 @@ static const unsigned char ecformats_default[] = {
     TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2
 };
 
-/* The default curves */
-static const uint16_t supported_groups_default[] = {
-    OSSL_TLS_GROUP_ID_x25519,        /* X25519 (29) */
-    OSSL_TLS_GROUP_ID_secp256r1,     /* secp256r1 (23) */
-    OSSL_TLS_GROUP_ID_x448,          /* X448 (30) */
-    OSSL_TLS_GROUP_ID_secp521r1,     /* secp521r1 (25) */
-    OSSL_TLS_GROUP_ID_secp384r1,     /* secp384r1 (24) */
-    OSSL_TLS_GROUP_ID_gc256A,        /* GC256A (34) */
-    OSSL_TLS_GROUP_ID_gc256B,        /* GC256B (35) */
-    OSSL_TLS_GROUP_ID_gc256C,        /* GC256C (36) */
-    OSSL_TLS_GROUP_ID_gc256D,        /* GC256D (37) */
-    OSSL_TLS_GROUP_ID_gc512A,        /* GC512A (38) */
-    OSSL_TLS_GROUP_ID_gc512B,        /* GC512B (39) */
-    OSSL_TLS_GROUP_ID_gc512C,        /* GC512C (40) */
-    OSSL_TLS_GROUP_ID_ffdhe2048,     /* ffdhe2048 (0x100) */
-    OSSL_TLS_GROUP_ID_ffdhe3072,     /* ffdhe3072 (0x101) */
-    OSSL_TLS_GROUP_ID_ffdhe4096,     /* ffdhe4096 (0x102) */
-    OSSL_TLS_GROUP_ID_ffdhe6144,     /* ffdhe6144 (0x103) */
-    OSSL_TLS_GROUP_ID_ffdhe8192,     /* ffdhe8192 (0x104) */
-};
-
 /* Group list string of the built-in pseudo group DEFAULT */
 #define DEFAULT_GROUP_NAME "DEFAULT"
-#define DEFAULT_GROUP_LIST "X25519:secp256r1:X448:secp521r1:secp384r1:GC256A:GC256B:GC256C:GC256D:GC512A:GC512B:GC512C:ffdhe2048:ffdhe3072:ffdhe4096:ffdhe6144:ffdhe8192",
+#define TLS_DEFAULT_GROUP_LIST \
+    "?*X25519MLKEM768 / ?*X25519:?secp256r1 / ?X448:?secp384r1:?secp521r1 / ?ffdhe2048:?ffdhe3072"
+#define QUIC_DEFAULT_GROUP_LIST \
+    "X25519:secp256r1:X448:secp521r1:secp384r1:ffdhe2048:ffdhe3072:ffdhe4096:ffdhe6144:ffdhe8192"
 
 static const uint16_t suiteb_curves[] = {
     OSSL_TLS_GROUP_ID_secp256r1,
@@ -380,55 +362,12 @@ static int discover_provider_groups(OSSL_PROVIDER *provider, void *vctx)
 
 int ssl_load_groups(SSL_CTX *ctx)
 {
-    size_t i, j, num_deflt_grps = 0;
-    uint16_t tmp_supp_groups[OSSL_NELEM(supported_groups_default)];
-
     if (!OSSL_PROVIDER_do_all(ctx->libctx, discover_provider_groups, ctx))
         return 0;
 
-    for (i = 0; i < OSSL_NELEM(supported_groups_default); i++) {
-        for (j = 0; j < ctx->group_list_len; j++) {
-            if (ctx->group_list[j].group_id == supported_groups_default[i]) {
-                tmp_supp_groups[num_deflt_grps++] = ctx->group_list[j].group_id;
-                break;
-            }
-        }
-    }
-
-    if (num_deflt_grps == 0)
-        return 1;
-
-    ctx->ext.supported_groups_default
-        = OPENSSL_malloc(sizeof(uint16_t) * num_deflt_grps);
-
-    if (ctx->ext.supported_groups_default == NULL)
-        return 0;
-
-    memcpy(ctx->ext.supported_groups_default,
-           tmp_supp_groups,
-           num_deflt_grps * sizeof(tmp_supp_groups[0]));
-    ctx->ext.supported_groups_default_len = num_deflt_grps;
-
-    /*
-     * Default groups have no explicit key share nor a tuple,
-     * hence we'll generate a key share for the first group and
-     * define one big tuple consisting of all default groups
-     */
-    if (ctx->ext.keyshares == NULL)
-        ctx->ext.keyshares = OPENSSL_malloc(sizeof(*ctx->ext.keyshares));
-    if (ctx->ext.keyshares == NULL)
-        return 0;
-    ctx->ext.keyshares_len = 1;
-    ctx->ext.keyshares[0] = 0;
-
-    if (ctx->ext.tuples == NULL)
-        ctx->ext.tuples = OPENSSL_malloc(sizeof(*ctx->ext.tuples));
-    if (ctx->ext.tuples == NULL)
-        return 0;
-    ctx->ext.tuples_len = 1;
-    ctx->ext.tuples[0] = ctx->ext.supported_groups_default_len;
-
-    return 1;
+    if (!IS_QUIC_CTX(ctx))
+        return SSL_CTX_set1_groups_list(ctx, TLS_DEFAULT_GROUP_LIST);
+    return SSL_CTX_set1_groups_list(ctx, QUIC_DEFAULT_GROUP_LIST);
 }
 
 #define TLS_SIGALG_LIST_MALLOC_BLOCK_SIZE        10
@@ -846,8 +785,8 @@ void tls1_get_supported_groups(SSL_CONNECTION *s, const uint16_t **pgroups,
 
     default:
         if (s->ext.supportedgroups == NULL) {
-            *pgroups = sctx->ext.supported_groups_default;
-            *pgroupslen = sctx->ext.supported_groups_default_len;
+            *pgroups = sctx->ext.supportedgroups;
+            *pgroupslen = sctx->ext.supportedgroups_len;
         } else {
             *pgroups = s->ext.supportedgroups;
             *pgroupslen = s->ext.supportedgroups_len;
@@ -875,8 +814,8 @@ void tls1_get_requested_keyshare_groups(SSL_CONNECTION *s, const uint16_t **pgro
     SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
 
     if (s->ext.supportedgroups == NULL) {
-        *pgroups = sctx->ext.supported_groups_default;
-        *pgroupslen = sctx->ext.supported_groups_default_len;
+        *pgroups = sctx->ext.supportedgroups;
+        *pgroupslen = sctx->ext.supportedgroups_len;
     } else {
         *pgroups = s->ext.keyshares;
         *pgroupslen = s->ext.keyshares_len;
@@ -1192,7 +1131,7 @@ static const char *DEFAULT_GROUPNAME_FIRST_CHARACTER = "D";
 
 /* The list of all built-in pseudo-group-name structures */
 static const default_group_string_st default_group_strings[] = {
-    {DEFAULT_GROUP_NAME, DEFAULT_GROUP_LIST},
+    {DEFAULT_GROUP_NAME, TLS_DEFAULT_GROUP_LIST},
     {SUITE_B_GROUP_NAME, SUITE_B_GROUP_LIST}
 };
 
index b4f2c20bdb9ff223607caa162c294c0dcfd6bbd1..c922586415a6de255a51ac5213c01f5ee2b1b44e 100644 (file)
@@ -98,6 +98,10 @@ static int test_client_hello(int currtest)
         SSL_CTX_set_options(ctx, SSL_OP_TLSEXT_PADDING);
         /* Make sure we get a consistent size across TLS versions */
         SSL_CTX_clear_options(ctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
+        /* Avoid large keyshares */
+        if (!TEST_true(SSL_CTX_set1_groups_list(ctx,
+                       "?X25519:?secp256r1:?ffdhe2048:?ffdhe3072")))
+            goto end;
         /*
          * Add some dummy ALPN protocols so that the ClientHello is at least
          * F5_WORKAROUND_MIN_MSG_LEN bytes long - meaning padding will be
index 4be31c52e7f9c313bd8b31c713baebfc959243da..bcc29b88f325f406779e7b7d3ec46e6c9460af4b 100644 (file)
@@ -44,7 +44,8 @@ my $testtype;
 #Test 1: Inserting a cookie into an HRR should see it echoed in the ClientHello
 $testtype = COOKIE_ONLY;
 $proxy->filter(\&cookie_filter);
-$proxy->serverflags("-curves X25519") if !disabled("ecx");
+$proxy->serverflags("-curves X25519");
+$proxy->clientflags("-curves X25519:secp256r1");
 $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
 plan tests => 2;
 SKIP: {
index 1d4fbab5817adaa701a6476662b2b27499d73812..8c1b2073b872a0422f7e7b5f5fc29e118166311c 100644 (file)
@@ -9873,44 +9873,38 @@ static int test_unknown_sigalgs_groups(void)
     return ret;
 }
 
+#if (!defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)) || !defined(OPENSSL_NO_ML_KEM)
 static int test_configuration_of_groups(void)
 {
     int ret = 0;
     SSL_CTX *ctx = NULL;
-#if (!defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH))
-    size_t default_groups_len;
-#endif
+    size_t groups_len;
 
     if (!TEST_ptr(ctx = SSL_CTX_new_ex(libctx, NULL, TLS_server_method())))
         goto end;
+    groups_len = ctx->ext.supportedgroups_len;
 
-#if (!defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH))
-    default_groups_len = ctx->ext.supported_groups_default_len;
-
-    if (!TEST_size_t_gt(default_groups_len, 0)
+    if (!TEST_size_t_gt(groups_len, 0)
         || !TEST_int_gt(SSL_CTX_set1_groups_list(ctx, "DEFAULT"), 0)
-        || !TEST_size_t_eq(ctx->ext.supportedgroups_len, default_groups_len))
+        || !TEST_size_t_eq(ctx->ext.supportedgroups_len, groups_len))
         goto end;
-#endif
 
-#if (!defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH))
     if (!TEST_int_gt(SSL_CTX_set1_groups_list(ctx, "DEFAULT:-?P-256"), 0)
 # if !defined(OPENSSL_NO_EC)
-        || !TEST_size_t_eq(ctx->ext.supportedgroups_len, default_groups_len - 1)
+        || !TEST_size_t_eq(ctx->ext.supportedgroups_len, groups_len - 1)
 # else
-        || !TEST_size_t_eq(ctx->ext.supportedgroups_len, default_groups_len)
+        || !TEST_size_t_eq(ctx->ext.supportedgroups_len, groups_len)
 # endif
         )
         goto end;
-#endif
 
-#if !defined(OPENSSL_NO_EC)
+# if !defined(OPENSSL_NO_EC)
     if (!TEST_int_gt(SSL_CTX_set1_groups_list(ctx, "?P-256:?P-521:-?P-256"), 0)
         || !TEST_size_t_eq(ctx->ext.supportedgroups_len, 1)
         || !TEST_int_eq(ctx->ext.supportedgroups[0], OSSL_TLS_GROUP_ID_secp521r1)
         )
         goto end;
-#endif
+# endif
 
     ret = 1;
 
@@ -9918,6 +9912,7 @@ end:
     SSL_CTX_free(ctx);
     return ret;
 }
+#endif
 
 #if !defined(OPENSSL_NO_EC) \
     && (!defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2))
@@ -9988,6 +9983,13 @@ static int test_sigalgs_available(int idx)
     if (!TEST_ptr(cctx) || !TEST_ptr(sctx))
         goto end;
 
+    /* Avoid MLKEM groups that depend on possibly filtered-out digests */
+    if (!TEST_true(SSL_CTX_set1_groups_list(cctx,
+                        "?X25519:?secp256r1:?ffdhe2048:?ffdhe3072"))
+        || !TEST_true(SSL_CTX_set1_groups_list(sctx,
+                        "?X25519:?secp256r1:?ffdhe2048:?ffdhe3072")))
+        goto end;
+
     if (idx != 5) {
         /* RSA first server key */
         if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
@@ -13212,7 +13214,9 @@ int setup_tests(void)
 #endif
     ADD_ALL_TESTS(test_servername, 10);
     ADD_TEST(test_unknown_sigalgs_groups);
+#if (!defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)) || !defined(OPENSSL_NO_ML_KEM)
     ADD_TEST(test_configuration_of_groups);
+#endif
 #if !defined(OPENSSL_NO_EC) \
     && (!defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2))
     ADD_ALL_TESTS(test_sigalgs_available, 6);
index e3a25dba134f31e29cc50ed6d031605c839f3bf3..fcebc1e43e658a389237c8884c649452adef7427 100644 (file)
@@ -81,7 +81,7 @@ static const struct tls13groupselection_test_st tls13groupselection_tests[] =
         { "secp521r1:secp384r1:X25519:prime256v1:X448", /* test 3 */
           "X25519:secp384r1:prime256v1",
           SERVER_PREFERENCE,
-          "X25519", HRR
+          "x25519", HRR
         },
 
         /*
@@ -94,12 +94,12 @@ static const struct tls13groupselection_test_st tls13groupselection_tests[] =
         { "secp521r1:secp384r1:*X25519/*prime256v1:X448", /* test 4 */
           "secp521r1:*prime256v1:X25519:X448",
           CLIENT_PREFERENCE,
-          "X25519", SH
+          "x25519", SH
         },
         { "secp521r1:secp384r1:*X25519/*prime256v1:X448", /* test 5 */
           "secp521r1:*prime256v1:X25519:X448",
           SERVER_PREFERENCE,
-          "prime256v1", SH
+          "secp256r1", SH
         },
 
         /*
@@ -126,24 +126,24 @@ static const struct tls13groupselection_test_st tls13groupselection_tests[] =
         { "*X25519:prime256v1:*X448", /* test 8 */
           "secp521r1:secp384r1/X448:X25519",
           CLIENT_PREFERENCE,
-          "X25519", SH
+          "x25519", SH
         },
         { "*X25519:prime256v1:*X448", /* test 9 */
           "secp521r1:secp384r1/X448:X25519",
           SERVER_PREFERENCE,
-          "X448", SH
+          "x448", SH
         },
 
         /* (F) Check that '?' will ignore unknown group but use known group */
         { "*X25519:?unknown_group_123:prime256v1:*X448", /* test 10 */
           "secp521r1:secp384r1/X448:?unknown_group_456:?X25519",
           CLIENT_PREFERENCE,
-          "X25519", SH
+          "x25519", SH
         },
         { "*X25519:prime256v1:*X448:?*unknown_group_789", /* test 11 */
           "secp521r1:secp384r1/?X448:?unknown_group_456:X25519",
           SERVER_PREFERENCE,
-          "X448", SH
+          "x448", SH
         },
 
         /*
@@ -152,12 +152,20 @@ static const struct tls13groupselection_test_st tls13groupselection_tests[] =
         { NULL, /* test 12 */
           NULL,
           CLIENT_PREFERENCE,
-          "X25519", SH
+#ifndef OPENSSL_NO_ML_KEM
+          "X25519MLKEM768", SH
+#else
+          "x25519", SH
+#endif
         },
         { NULL, /* test 13 */
           NULL,
           SERVER_PREFERENCE,
-          "X25519", SH
+#ifndef OPENSSL_NO_ML_KEM
+          "X25519MLKEM768", SH
+#else
+          "x25519", SH
+#endif
         },
 
         /*
@@ -166,35 +174,35 @@ static const struct tls13groupselection_test_st tls13groupselection_tests[] =
         { "*X25519:*X448", /* test 14 */
           "secp521r1:X25519:prime256v1:-X25519:secp384r1/X448",
           CLIENT_PREFERENCE,
-          "X448", SH
+          "x448", SH
         },
         { "*X25519:*X448", /* test 15 */
           "secp521r1:X25519:prime256v1:-X25519:secp384r1/X448",
           SERVER_PREFERENCE,
-          "X448", SH
+          "x448", SH
         },
         { "*X25519:prime256v1:*X448", /* test 16 */
           "X25519:prime256v1/X448:-X25519",
           CLIENT_PREFERENCE,
-          "prime256v1", HRR
+          "secp256r1", HRR
         },
         { "*X25519:prime256v1:*X448", /* test 17 */
           "X25519:prime256v1/X448:-X25519",
           SERVER_PREFERENCE,
-          "prime256v1", HRR
+          "secp256r1", HRR
         },
         /*
          * (I) Check handling of the "DEFAULT" 'pseudo group name'
          */
         { "*X25519:DEFAULT:-prime256v1:-X448", /* test 18 */
-          "DEFAULT:-X25519",
+          "DEFAULT:-X25519:-?X25519MLKEM768",
           CLIENT_PREFERENCE,
-          "secp521r1", HRR
+          "secp384r1", HRR
         },
         { "*X25519:DEFAULT:-prime256v1:-X448", /* test 19 */
-          "DEFAULT:-X25519",
+          "DEFAULT:-X25519:-?X25519MLKEM768",
           SERVER_PREFERENCE,
-          "secp521r1", HRR
+          "secp384r1", HRR
         },
         /*
          * (J) Deduplication check
@@ -215,7 +223,7 @@ static const struct tls13groupselection_test_st tls13groupselection_tests[] =
         { "*X25519:*prime256v1:-X25519", /* test 22 */
           "X25519:prime256v1",
           CLIENT_PREFERENCE,
-          "prime256v1", SH
+          "secp256r1", SH
         },
         /*
          * (L) Syntax errors
@@ -408,6 +416,7 @@ static int test_groupnegotiation(const struct tls13groupselection_test_st *curre
     int ok = 0;
     int negotiated_group_client = 0;
     int negotiated_group_server = 0;
+    const char *group_name_client;
     SSL_CTX *client_ctx = NULL, *server_ctx = NULL;
     SSL *clientssl = NULL, *serverssl = NULL;
     enum SERVER_RESPONSE server_response;
@@ -471,11 +480,12 @@ static int test_groupnegotiation(const struct tls13groupselection_test_st *curre
          */
         negotiated_group_client = SSL_get_negotiated_group(clientssl);
         negotiated_group_server = SSL_get_negotiated_group(serverssl);
+        group_name_client = SSL_group_to_name(clientssl, negotiated_group_client);
         if (!TEST_int_eq(negotiated_group_client, negotiated_group_server))
             goto end;
         if (!TEST_int_eq((int)current_test_vector->expected_server_response, (int)server_response))
             goto end;
-        if (TEST_int_eq(negotiated_group_client, OBJ_sn2nid(current_test_vector->expected_group)))
+        if (TEST_str_eq(group_name_client, current_test_vector->expected_group))
             ok = 1;
     } else {
         TEST_false_or_end(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE));