File 1501-ssl-Make-key-share-groups-configurable.patch of Package erlang

From 01e5dafdd7162be0513ec98b5d534b97d3201d79 Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin <ingela@erlang.org>
Date: Mon, 15 Sep 2025 08:43:25 +0200
Subject: [PATCH 1/2] ssl: Make key share groups configurable

---
 lib/ssl/src/ssl.erl                       |  6 ++++++
 lib/ssl/src/ssl_config.erl                | 25 +++++++++++++++++++++--
 lib/ssl/src/tls_client_connection_1_3.erl |  8 +++-----
 lib/ssl/test/ssl_api_SUITE.erl            | 14 ++++++++++---
 4 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index b70c89231b..6cf1612b01 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -1380,6 +1380,11 @@ certificate signatures.
 The following options are specific to the client side, or have
 different semantics for the client and server:
 
+- **`{psk_groups, Groups}`** - key exchange groups that the client
+will send pre share keys for, defaults to first group in
+supported_groups. Must be a subset of supported_groups and will
+be sent in the same order as they appear in supported_groups.
+
 - **`{alpn_advertised_protocols, AppProtocols}`** - Application layer protocol
 
   The list of protocols supported by the client to be sent to the server to be
@@ -1397,6 +1402,7 @@ different semantics for the client and server:
 
 -type client_option() :: client_option_cert() |
                          common_option_cert() |
+                         {psk_groups, [group()]} |
                          {alpn_advertised_protocols, AppProtocols::[AppProto::binary()]} |
                          {max_fragment_length, MaxLen:: undefined | 512 | 1024 | 2048 | 4096} |
                          client_option_tls13() |
diff --git a/lib/ssl/src/ssl_config.erl b/lib/ssl/src/ssl_config.erl
index e901617211..eeaedb2fac 100644
--- a/lib/ssl/src/ssl_config.erl
+++ b/lib/ssl/src/ssl_config.erl
@@ -493,6 +493,7 @@ ssl_options() ->
      partial_chain,
      password,
      protocol,
+     psk_groups,
      psk_identity,
      receiver_spawn_opts,
      renegotiate_at,
@@ -1371,7 +1372,7 @@ handle_user_lookup(UserOpts, #{versions := Versions} = Opts) ->
     end.
     
 
-opt_supported_groups(UserOpts, #{versions := TlsVsns} = Opts, _Env) ->
+opt_supported_groups(UserOpts, #{versions := TlsVsns} = Opts, Env) ->
     SG = case get_opt_list(supported_groups,  undefined, UserOpts, Opts) of
              {default, undefined} ->
                  try assert_version_dep(supported_groups, TlsVsns, ['tlsv1.3']) of
@@ -1404,7 +1405,27 @@ opt_supported_groups(UserOpts, #{versions := TlsVsns} = Opts, _Env) ->
                 throw:_ ->
                     []
             end,
-    Opts#{ciphers => CPHS, eccs => ECCS, supported_groups => SG}.
+    case opt_psk_groups(SG, UserOpts, Opts, Env)  of
+        undefined ->
+            Opts#{ciphers => CPHS, eccs => ECCS, supported_groups => SG};
+        PSKGroups ->
+            Opts#{ciphers => CPHS, eccs => ECCS, supported_groups => SG, psk_groups => PSKGroups}
+    end.
+
+opt_psk_groups(undefined, _,  _, _) ->
+    undefined;
+opt_psk_groups(#supported_groups{supported_groups = SupportedGroups},  UserOpts, Opts, _Env) ->
+    %% Version dependency already asserted when SupportedGroups is supported
+    %% so is psk_groups
+    First = hd(SupportedGroups),
+    case get_opt_list(psk_groups, [First], UserOpts, Opts) of
+        {default, Default} ->
+            Default;
+        {new, PSKGroups} ->
+            [Group || Group <- SupportedGroups, lists:member(Group, PSKGroups)];
+        {old, PSKGroups} ->
+            PSKGroups
+    end.
 
 opt_crl(UserOpts, Opts, _Env) ->
     {_, Check} = get_opt_of(crl_check, [best_effort, peer, true, false], false, UserOpts, Opts),
diff --git a/lib/ssl/src/tls_client_connection_1_3.erl b/lib/ssl/src/tls_client_connection_1_3.erl
index 9282319a34..c6f0c54dca 100644
--- a/lib/ssl/src/tls_client_connection_1_3.erl
+++ b/lib/ssl/src/tls_client_connection_1_3.erl
@@ -593,11 +593,9 @@ maybe_resumption(_) ->
     ok.
 
 maybe_generate_client_shares(#{versions := [?TLS_1_3|_],
-                               supported_groups :=
-                                   #supported_groups{
-                                      supported_groups = [Group|_]}}) ->
-    %% Generate only key_share entry for the most preferred group
-    ssl_cipher:generate_client_shares([Group]);
+                               psk_groups := Groups}) ->
+    %% Default will be the list of only the most preferred supported group
+    generate_client_shares(Groups);
 maybe_generate_client_shares(_) ->
     undefined.
 
diff --git a/lib/ssl/test/ssl_api_SUITE.erl b/lib/ssl/test/ssl_api_SUITE.erl
index 63bd79ba9c..4648f12f57 100644
--- a/lib/ssl/test/ssl_api_SUITE.erl
+++ b/lib/ssl/test/ssl_api_SUITE.erl
@@ -29,6 +29,7 @@
 -include_lib("common_test/include/ct.hrl").
 -include_lib("ssl/src/ssl_api.hrl").
 -include_lib("ssl/src/ssl_internal.hrl").
+-include_lib("ssl/src/ssl_handshake.hrl").
 -include_lib("public_key/include/public_key.hrl").
 -include_lib("ssl/src/ssl_record.hrl").
 
@@ -3122,12 +3123,19 @@ options_sign_alg(_Config) ->  %% signature_algs[_cert]
     ok.
 
 options_supported_groups(_Config) ->
-    Default = ssl:groups(default),
-    ?OK(#{supported_groups := {supported_groups, Default}},
+    DefaultGroups = ssl:groups(default),
+    First = hd(DefaultGroups),
+    ?OK(#{supported_groups := #supported_groups{supported_groups = DefaultGroups}},
         [], client),
-    ?OK(#{supported_groups := {supported_groups, [secp521r1, ffdhe2048]}},
+    ?OK(#{supported_groups := #supported_groups{supported_groups = [secp521r1, ffdhe2048]}},
         [{supported_groups, [secp521r1, ffdhe2048]}], client),
 
+    ?OK(#{psk_groups := [First]},
+        [], client),
+    ?OK(#{psk_groups := [secp521r1, secp256r1],
+          supported_groups := #supported_groups{supported_groups = [secp521r1, secp256r1, ffdhe2048]}},
+        [{supported_groups, [secp521r1, secp256r1, ffdhe2048]}, {psk_groups, [secp521r1, secp384r1, secp256r1]}], client),
+
     %% ERRORs
     ?ERR({{'tlvs1.2'},{versions,[{'tlvs1.2'}]}},
          [{supported_groups, []}, {versions, [{'tlvs1.2'}]}], client),
-- 
2.51.0

openSUSE Build Service is sponsored by