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