diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 1509688ebd92..60fc34edb952 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -2128,6 +2128,7 @@ Key value list convening some information about the established connection. -type connection_info() :: [{protocol, protocol_version()} | {session_resumption, boolean()} | {selected_cipher_suite, erl_cipher_suite()} | + {selected_group, group()} | {sni_hostname, term()} | {ciphers, [erl_cipher_suite()]}] | connection_info_pre_tls13() | @@ -2163,6 +2164,7 @@ TLS connection keys for which information can be retrieved. """. -type connection_info_keys() :: [ protocol | selected_cipher_suite + | selected_group | sni_hostname | session_resumption | ciphers diff --git a/lib/ssl/src/ssl_gen_statem.erl b/lib/ssl/src/ssl_gen_statem.erl index 7d1fc074a60a..5695066db14e 100644 --- a/lib/ssl/src/ssl_gen_statem.erl +++ b/lib/ssl/src/ssl_gen_statem.erl @@ -1931,13 +1931,22 @@ connection_info(#state{handshake_env = #handshake_env{sni_hostname = SNIHostname _ -> [] end, + GroupInfo = case Version of + ?TLS_1_3 when is_atom(ECCCurve), ECCCurve =/= undefined -> + %% For TLS-1.3 the named group of the key exchange is + %% negotiated via the supported_groups and key_share + %% extensions and is kept in session.ecc + [{selected_group, ECCCurve}]; + _ -> + [] + end, [{protocol, RecordCB:protocol_version(Version)}, {session_id, SessionId}, {session_data, term_to_binary(Session)}, {session_resumption, Resumption}, {selected_cipher_suite, CipherSuiteDef}, {sni_hostname, SNIHostname}, - {srp_username, SrpUsername} | CurveInfo] ++ MFLInfo ++ ssl_options_list(Opts). + {srp_username, SrpUsername} | CurveInfo] ++ GroupInfo ++ MFLInfo ++ ssl_options_list(Opts). security_info(#state{connection_states = #{current_read := Read, current_write := Write}, diff --git a/lib/ssl/test/ssl_api_SUITE.erl b/lib/ssl/test/ssl_api_SUITE.erl index edb7e5e4ce12..931c9a332650 100644 --- a/lib/ssl/test/ssl_api_SUITE.erl +++ b/lib/ssl/test/ssl_api_SUITE.erl @@ -4098,6 +4098,15 @@ secs_since_1970() -> connection_information_result(Socket) -> {ok, Info = [_ | _]} = ssl:connection_information(Socket), + case proplists:get_value(protocol, Info) of + 'tlsv1.3' -> + %% For TLS-1.3 the negotiated key exchange group is exposed + {ok, [{selected_group, Group}]} = + ssl:connection_information(Socket, [selected_group]), + true = lists:member(Group, ssl:groups()); + _ -> + false = proplists:is_defined(selected_group, Info) + end, case length(Info) > 3 of true -> %% At least one ssl_option() is set