File 1664-ssl-Improve-maintainability-and-correct-keylogging.patch of Package erlang

From b29d8afbf185cd49e78998b58ababdbde4c39126 Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin <ingela@erlang.org>
Date: Wed, 10 Dec 2025 13:40:34 +0100
Subject: [PATCH 4/4] ssl: Improve maintainability and correct keylogging

Remove confusing update function and adjust key logging functionality.
Also add timeout to clear secrets on client side if connection
apparently succeeds and keylog_hs is specified.

The adjustment also means that skipping of key log messages in
ssl_session_SUITE test can be changed back as correction of
connection steping also requires a change in the key
logging functionality.
---
 lib/ssl/src/ssl_gen_statem.erl            | 148 +++++---
 lib/ssl/src/tls_client_connection_1_3.erl |  26 +-
 lib/ssl/src/tls_gen_connection_1_3.erl    |  16 +-
 lib/ssl/src/tls_handshake_1_3.erl         | 396 +++++++++++-----------
 lib/ssl/src/tls_record.erl                |   2 +-
 lib/ssl/src/tls_server_connection_1_3.erl |  57 +---
 lib/ssl/test/ssl_session_ticket_SUITE.erl |   4 +-
 lib/ssl/test/tls_1_3_version_SUITE.erl    | 123 ++++---
 8 files changed, 423 insertions(+), 349 deletions(-)

diff --git a/lib/ssl/src/ssl_gen_statem.erl b/lib/ssl/src/ssl_gen_statem.erl
index e9994be201..a345ecebb2 100644
--- a/lib/ssl/src/ssl_gen_statem.erl
+++ b/lib/ssl/src/ssl_gen_statem.erl
@@ -1976,16 +1976,16 @@ connection_info(#state{handshake_env = #handshake_env{sni_hostname = SNIHostname
      {sni_hostname, SNIHostname},
      {srp_username, SrpUsername} | CurveInfo] ++ MFLInfo ++ ssl_options_list(Opts).
 
-security_info(#state{connection_states = ConnectionStates,
+security_info(#state{connection_states = #{current_read := Read,
+                                           current_write := Write},
                      static_env = #static_env{role = Role},
                      connection_env = #connection_env{negotiated_version = Version},
                      ssl_options = Opts,
                      protocol_specific = ProtocolSpecific}) ->
-    ReadState = ssl_record:current_connection_state(ConnectionStates, read),
     #{security_parameters :=
 	  #security_parameters{client_random = ClientRand,
                                server_random = ServerRand,
-                               master_secret = MasterSecret}} = ReadState,
+                               master_secret = MasterSecret}} = Read,
     SecInfo = [{client_random, ClientRand},
                {server_random, ServerRand}, {master_secret, MasterSecret}],
     KeepSecrets = maps:get(keep_secrets, Opts, false),
@@ -1995,30 +1995,31 @@ security_info(#state{connection_states = ConnectionStates,
             %% to be able to run in user process context
             [{keep_secrets, false} | SecInfo];
         _  -> %% true or keylog fun tuple
-            maybe_security_info_1_3(Version, ReadState, ProtocolSpecific, Role)
+            maybe_security_info_1_3(Version, Read, Write,  ProtocolSpecific, Role)
                 ++ SecInfo
     end.
 
-maybe_security_info_1_3(Version, #{security_parameters :=
-                             #security_parameters{application_traffic_secret = AppTrafSecretRead,
-                                                  client_early_data_secret = EarlyData
-                                                 }} = ReadState,
-              ProtocolSpecific, Role) when ?TLS_GTE(Version, ?TLS_1_3)->
+maybe_security_info_1_3(Version,
+                        #{security_parameters :=
+                              #security_parameters{application_traffic_secret = AppTrafSecretRead,
+                                                   client_early_data_secret = EarlyData
+                                                  }} = Read, Write,
+                        ProtocolSpecific, Role) when ?TLS_GTE(Version, ?TLS_1_3)->
     N = maps:get(num_key_updates, ProtocolSpecific, 0),
     Sender = maps:get(sender, ProtocolSpecific, undefined),
     case Role of
         server ->
             tls_handshake_1_3:early_data_secret(EarlyData) ++
-                tls_handshake_1_3:hs_traffic_secrets(ReadState) ++
+                tls_handshake_1_3:hs_traffic_secrets(Read, Write) ++
                 [{client_traffic_secret, AppTrafSecretRead, N},
                  {Role, Sender}];
         client ->
             tls_handshake_1_3:early_data_secret(EarlyData) ++
-                tls_handshake_1_3:hs_traffic_secrets(ReadState) ++
+                tls_handshake_1_3:hs_traffic_secrets(Read, Write) ++
                 [{server_traffic_secret, AppTrafSecretRead, N},
                  {Role, Sender}]
     end;
-maybe_security_info_1_3(_,_,_,_) ->
+maybe_security_info_1_3(_,_,_,_,_) ->
     [].
 
 record_cb(tls) ->
@@ -2244,56 +2245,111 @@ maybe_keylog_hs_callback(#alert{level = ?FATAL}, StateName,
     end;
 maybe_keylog_hs_callback(_, _, _) ->
     ok.
- 
+
 keylog_hs_alert(start, _) -> %% TLS 1.3: No secrets yet established
     {[], undefined};
 keylog_hs_alert(wait_sh, _) -> %% TLS 1.3: No secrets yet established
     {[], undefined};
-%% Server alert for certificate validation can happen when client is in connection state already.
-keylog_hs_alert(connection,  #state{static_env = #static_env{role = client},
-                                    connection_env =
-                                        #connection_env{negotiated_version = TlsVersion},
-                                    connection_states = ConnectionStates,
-                                    protocol_specific = #{sender := Sender} = PS})
+keylog_hs_alert(negotiated, #state{static_env = #static_env{role = server},
+                                   connection_env =
+                                       #connection_env{negotiated_version = TlsVersion},
+                                   connection_states = #{current_read := Read,
+                                                         current_write := Write
+                                                        }})
   when ?TLS_GTE(TlsVersion, ?TLS_1_3) ->
-    CSRead =  #{security_parameters :=
-                    #security_parameters{application_traffic_secret = SecretRead,
-                                         client_random = ClientRandom,
-                                         prf_algorithm = Prf}}
-        = ssl_record:current_connection_state(ConnectionStates, read),
-    NRead = maps:get(num_key_updates, PS, 0),
-    {ok, SecretWrite, NWrite} = call(Sender, get_application_traffic_secret),
-    {keylog_hs_1_3(CSRead) ++
-        ssl_logger:keylog_traffic_1_3(client, ClientRandom, Prf, SecretWrite, NWrite) ++
-        ssl_logger:keylog_traffic_1_3(server, ClientRandom, Prf, SecretRead, NRead), ClientRandom};
-keylog_hs_alert(_, #state{connection_env =
+     #{server_handshake_traffic_secret := ServerHSSecret,
+      security_parameters :=
+          #security_parameters{client_random = ClientRandomBin,
+                               client_early_data_secret = EarlySecret,
+                               prf_algorithm = Prf
+                              }} = Write,
+    #{client_handshake_traffic_secret := ClientHSSecret} = Read,
+    {keylog_hs_1_3(ClientRandomBin, Prf, EarlySecret, ServerHSSecret, ClientHSSecret),
+     ClientRandomBin};
+keylog_hs_alert(wait_eoed, #state{static_env = #static_env{role = server},
+                                  connection_env =
+                                      #connection_env{negotiated_version = TlsVersion},
+                                  connection_states = #{pending_read := Read,
+                                                        current_write := Write
+                                                       }})
+  when ?TLS_GTE(TlsVersion, ?TLS_1_3) ->
+    keylog_1_3_client_finished(Read, Write);
+keylog_hs_alert(StateName, #state{static_env = #static_env{role = server},
+                                  connection_states =
+                                      #{current_read := Read,
+                                        current_write := Write
+                                       }}) when StateName == wait_cert;
+                                                StateName == wait_cv;
+                                                StateName == wait_finished ->
+    keylog_1_3_client_finished(Read, Write);
+keylog_hs_alert(connection, #state{static_env = #static_env{role = client},
+                                   connection_env =
+                                       #connection_env{negotiated_version = TlsVersion},
+                                   connection_states = #{current_read := Read,
+                                                         current_write := Write
+                                               }})
+  when ?TLS_GTE(TlsVersion, ?TLS_1_3) ->
+    #{server_handshake_traffic_secret := ServerHSSecret,
+      security_parameters :=
+          #security_parameters{client_random = ClientRandomBin,
+                               client_early_data_secret = EarlySecret,
+                               prf_algorithm = Prf,
+                               master_secret = {master_secret, STrafficSecret}
+                              }}
+        = Read,
+    #{client_handshake_traffic_secret := ClientHSSecret,
+       security_parameters :=
+          #security_parameters{master_secret = {master_secret, CTrafficSecret}
+                              }} = Write,
+
+    {keylog_hs_1_3(ClientRandomBin, Prf, EarlySecret, ClientHSSecret, ServerHSSecret) ++
+         ssl_logger:keylog_traffic_1_3(client, ClientRandomBin, Prf, CTrafficSecret, 0) ++
+         ssl_logger:keylog_traffic_1_3(server, ClientRandomBin, Prf, STrafficSecret, 0),
+     ClientRandomBin};
+keylog_hs_alert(_, #state{static_env = #static_env{role = client},
+                          connection_env =
                               #connection_env{negotiated_version = TlsVersion},
-                          connection_states = ConnectionStates})
+                          connection_states = #{current_read := Read,
+                                                current_write := Write
+                                               }})
   when ?TLS_GTE(TlsVersion, ?TLS_1_3) ->
-    CSRead = #{security_parameters :=
-                   #security_parameters{client_random = ClientRandom}}
-        = ssl_record:pending_connection_state(ConnectionStates, read),
-    {keylog_hs_1_3(CSRead), ClientRandom};
-keylog_hs_alert(_,_) -> % NOT Relevant pre TLS-1.3
+   #{server_handshake_traffic_secret := ServerHSSecret,
+      security_parameters :=
+                   #security_parameters{client_random = ClientRandomBin,
+                                        client_early_data_secret = EarlySecret,
+                                        prf_algorithm = Prf
+                                       }}
+        = Write,
+    #{client_handshake_traffic_secret := ClientHSSecret} = Read,
+    {keylog_hs_1_3(ClientRandomBin, Prf, EarlySecret, ClientHSSecret, ServerHSSecret),
+     ClientRandomBin};
+keylog_hs_alert(_, _) -> % NOT Relevant pre TLS-1.3
     {[], undefined}.
 
-keylog_hs_1_3(#{client_handshake_traffic_secret := ClientHSTrafficSecret,
-                server_handshake_traffic_secret := ServerHSTrafficSecret,
-                security_parameters := #security_parameters{client_random = ClientRandomBin,
-                                                            prf_algorithm = Prf,
-                                                            client_early_data_secret = EarlySecret}}) ->
+keylog_hs_1_3(ClientRandomBin, Prf, EarlySecret, ClientSecret, ServerSecret) ->
     HSItems =
-        ssl_logger:keylog_hs(ClientRandomBin, Prf, ClientHSTrafficSecret, ServerHSTrafficSecret),
+        ssl_logger:keylog_hs(ClientRandomBin, Prf, ClientSecret, ServerSecret),
     case EarlySecret of
         undefined ->
             HSItems;
         _  ->
             [ssl_logger:keylog_early_data(ClientRandomBin, Prf, EarlySecret) | HSItems]
-    end;
-keylog_hs_1_3(_) ->
-    [].
+    end.
+
+keylog_1_3_client_finished(Read, Write) ->
+    #{server_handshake_traffic_secret := ServerHSSecret,
+      security_parameters :=
+                   #security_parameters{client_random = ClientRandomBin,
+                                        client_early_data_secret = EarlySecret,
+                                        prf_algorithm = Prf,
+                                        master_secret = {master_secret, TrafficSecret}
+                                       }}
+        = Write,
+    #{client_handshake_traffic_secret := ClientHSSecret} = Read,
+    {keylog_hs_1_3(ClientRandomBin, Prf, EarlySecret, ServerHSSecret, ClientHSSecret) ++
+         ssl_logger:keylog_traffic_1_3(server, ClientRandomBin, Prf, TrafficSecret, 0),
+     ClientRandomBin}.
 
- 
 %%%################################################################
 %%%#
 %%%# Tracing
diff --git a/lib/ssl/src/tls_client_connection_1_3.erl b/lib/ssl/src/tls_client_connection_1_3.erl
index 7870b6b603..834bc8b17d 100644
--- a/lib/ssl/src/tls_client_connection_1_3.erl
+++ b/lib/ssl/src/tls_client_connection_1_3.erl
@@ -458,12 +458,13 @@ wait_finished(internal,
         State4 = Connection:queue_handshake(Finished, State3),
         %% Send first flight
         {State5, _} = Connection:send_handshake_flight(State4),
-        State6 = tls_handshake_1_3:calculate_traffic_secrets(State5),
-        State7 = tls_handshake_1_3:maybe_calculate_resumption_master_secret(State6),
-        State8 = ssl_record:step_encryption_state(State7),
-        State9 = tls_handshake_1_3:prepare_connection(State8),
+        State6 = tls_handshake_1_3:calculate_write_traffic_secrets(State5),
+        State7 = tls_handshake_1_3:calculate_read_traffic_secrets(State6),
+        State8 = tls_handshake_1_3:maybe_calculate_resumption_master_secret(State7),
+        State9 = ssl_record:step_encryption_state(State8),
+        State10 = tls_handshake_1_3:prepare_connection(State9),
         {Record, State} =
-            ssl_gen_statem:prepare_connection(State9, tls_gen_connection),
+            ssl_gen_statem:prepare_connection(State10, tls_gen_connection),
         KeepSecrets = maps:get(keep_secrets, SSLOpts, false),
         tls_gen_connection_1_3:maybe_traffic_keylog_1_3(KeepSecrets, Role,
                                                         State#state.connection_states, 0),
@@ -482,6 +483,21 @@ wait_finished(Type, Msg, State) ->
                  term(), #state{}) ->
           gen_statem:state_function_result().
 %%--------------------------------------------------------------------
+connection(enter, _, #state{ssl_options = Opts} = State) ->
+    case maps:get(keep_secrets, Opts, undefined) of
+        {keylog_hs, _} ->
+            %% Mitigate consequences of keylog_hs being activated, as
+            %% this forces the client to remember secrets longer, that
+            %% is the client certification can fail after the client
+            %% reached connection state.
+            {next_state, ?STATE(connection), State, [{timeout, 1000, forget}]};
+        _ ->
+            {keep_state, State}
+    end;
+connection(timeout, forget, State) ->
+    {next_state, ?STATE(connection), tls_handshake_1_3:forget_master_secret(State)};
+connection(info, Msg, State) ->
+    tls_gen_connection:gen_info(Msg, connection, State);
 connection(Type, Msg, State) ->
     tls_gen_connection_1_3:connection(Type, Msg, State).
 
diff --git a/lib/ssl/src/tls_gen_connection_1_3.erl b/lib/ssl/src/tls_gen_connection_1_3.erl
index f42f6a4072..6e52b9f991 100644
--- a/lib/ssl/src/tls_gen_connection_1_3.erl
+++ b/lib/ssl/src/tls_gen_connection_1_3.erl
@@ -52,7 +52,7 @@
          do_maybe/0]).
 
 %%--------------------------------------------------------------------
-%%  Internal API 
+%%  Internal API
 %%--------------------------------------------------------------------
 initial_state(Role, Sender, Host, Port, Socket,
               {SSLOptions, SocketOptions, Trackers}, User,
@@ -247,13 +247,17 @@ handle_resumption(#state{handshake_env = HSEnv0} = State, _) ->
     HSEnv = HSEnv0#handshake_env{resumption = true},
     State#state{handshake_env = HSEnv}.
 
-maybe_forget_hs_secrets({keylog_hs, _}, #state{connection_states = CS} = State) ->
+maybe_forget_hs_secrets({keylog_hs, _}, #state{connection_states =
+                                                   #{current_read := Read0,
+                                                     current_write := Write0} = CS} = State) ->
     %% Server finishes the handshake last and  is able to immediately forget
     %% hs secrets used for handshake alert logging.
-    Read0 = #{security_parameters := SecParams} = ssl_record:current_connection_state(CS, read),
-    Read1 = Read0#{security_parameters => SecParams#security_parameters{client_early_data_secret = undefined}},
-    Read = maps:without([client_handshake_traffic_secret, server_handshake_traffic_secret], Read1),
-    State#state{connection_states = CS#{current_read => Read}};
+    #{security_parameters := SecParams} = Read0,
+    Read1 = Read0#{security_parameters =>
+                       SecParams#security_parameters{client_early_data_secret = undefined}},
+    Read = maps:without([client_handshake_traffic_secret], Read1),
+    Write = maps:without([server_handshake_traffic_secret], Write0),
+    State#state{connection_states = CS#{current_read => Read, current_write => Write}};
 maybe_forget_hs_secrets(_, State) ->
     State.
 
diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl
index 3a789a5e2c..aa3638fa9d 100644
--- a/lib/ssl/src/tls_handshake_1_3.erl
+++ b/lib/ssl/src/tls_handshake_1_3.erl
@@ -80,14 +80,14 @@
          get_pre_shared_key/4,
          get_pre_shared_key_early_data/2,
          get_supported_groups/1,
-         calculate_traffic_secrets/1,
          calculate_client_early_traffic_secret/5,
          calculate_client_early_traffic_secret/2,
          calculate_read_traffic_secrets/1,
          calculate_write_traffic_secrets/1,
          maybe_calculate_resumption_master_secret/1,
          early_data_secret/1,
-         hs_traffic_secrets/1,
+         hs_traffic_secrets/2,
+         forget_master_secret/1,
          encode_early_data/2,
          get_ticket_data/3,
          ciphers_for_early_data/1,
@@ -873,49 +873,149 @@ message_hash(ClientHello1, HKDFAlgo) ->
      0,0,ssl_cipher:hash_size(HKDFAlgo),
      crypto:hash(HKDFAlgo, ClientHello1)].
 
-prepare_connection(State0) ->
+prepare_connection(#state{static_env = #static_env{role = Role}, ssl_options = Opts} =State0) ->
     %% Handle different secrets on transition to the connection state
     State1 = #state{protocol_specific = PS} = maybe_calculate_resumption_master_secret(State0),
     ExporterSecret = calculate_exporter_master_secret(State1),
-    State =  State0#state{protocol_specific = PS#{exporter_master_secret => ExporterSecret}},
-    forget_master_secret(State).
+    State = State0#state{protocol_specific = PS#{exporter_master_secret => ExporterSecret}},
+    Keep = case maps:get(keep_secrets, Opts, undefined) of
+               {keylog_hs, _} ->
+                   true;
+               _ ->
+                   false
+           end,
+    case Role == client andalso Keep of
+        true ->
+            %% Remember
+            State;
+        false ->
+            forget_master_secret(State)
+    end.
 
-calculate_handshake_secrets(PublicKey, PrivateKey, SelectedGroup, PSK,
-                              #state{connection_states = ConnectionStates,
-                                     handshake_env =
-                                         #handshake_env{
-                                            tls_handshake_history = HHistory}} = State0) ->
-    #{security_parameters := SecParamsR} =
-        ssl_record:pending_connection_state(ConnectionStates, read),
-    #security_parameters{prf_algorithm = HKDFAlgo,
-                         cipher_suite = CipherSuite} = SecParamsR,
+calculate_handshake_secrets(PublicKey, PrivateKeyOrSecret, SelectedGroup, PSK,
+                              #state{connection_states = ConnectionStates0,
+                                    ssl_options = Opts} = State0) ->
+    PendingRead1 = calculate_read_handshake_secrets(PublicKey, PrivateKeyOrSecret,
+                                                  SelectedGroup, PSK, State0),
+    PendingWrite1 = calculate_write_handshake_secrets(PublicKey, PrivateKeyOrSecret,
+                                                   SelectedGroup, PSK, State0),
+    {PendingRead, PendingWrite} = maybe_handshake_keylog(PendingRead1, PendingWrite1, Opts),
+    ConnectionStates = ConnectionStates0#{pending_read => PendingRead,
+                                          pending_write => PendingWrite},
+    State0#state{connection_states = ConnectionStates}.
+
+calculate_read_handshake_secrets(PublicKey, PrivateKeyOrSecret, SelectedGroup, PSK,
+                                #state{ssl_options = Opts,
+                                       static_env = #static_env{role = Role},
+                                       connection_states = #{pending_read := PendingRead0},
+                                       handshake_env =
+                                           #handshake_env{
+                                              tls_handshake_history = HHistory}}) ->
+    #{security_parameters := SecParams} = PendingRead0,
+    #security_parameters{prf_algorithm = HKDFAlgo} = SecParams,
+    HandshakeSecret = calculate_handshake_master_secret(PublicKey, PrivateKeyOrSecret,
+                                                        SelectedGroup, PSK, HKDFAlgo),
+    Keep = maps:get(keep_secrets, Opts, false),
+    calculate_handshake_secret(HandshakeSecret, PendingRead0, read, Role, HHistory, Keep).
+
+calculate_write_handshake_secrets(PublicKey, PrivateKeyOrSecret, SelectedGroup, PSK,
+                                  #state{ssl_options = Opts,
+                                         static_env = #static_env{role = Role},
+                                         connection_states = #{pending_write := PendingWrite0},
+                                         handshake_env =
+                                             #handshake_env{
+                                                tls_handshake_history = HHistory}}) ->
+    #{security_parameters := SecParams} = PendingWrite0,
+    #security_parameters{prf_algorithm = HKDFAlgo} = SecParams,
+    HandshakeSecret = calculate_handshake_master_secret(PublicKey, PrivateKeyOrSecret,
+                                                        SelectedGroup, PSK, HKDFAlgo),
+    Keep = maps:get(keep_secrets, Opts, false),
+    calculate_handshake_secret(HandshakeSecret, PendingWrite0, write, Role, HHistory, Keep).
+
+calculate_handshake_master_secret(PublicKey, PrivateKeyOrSecret, SelectedGroup,
+                                  PSK, HKDFAlgo) ->
     EarlySecret = tls_v1:key_schedule(early_secret, HKDFAlgo , {psk, PSK}),
+    IKM = calculate_shared_secret(PublicKey, PrivateKeyOrSecret, SelectedGroup),
+    tls_v1:key_schedule(handshake_secret, HKDFAlgo, IKM, EarlySecret).
 
-    IKM = calculate_shared_secret(PublicKey, PrivateKey, SelectedGroup),
-    HandshakeSecret = tls_v1:key_schedule(handshake_secret, HKDFAlgo, IKM, EarlySecret),
-
-    %% Calculate [sender]_handshake_traffic_secret
-    {Messages, _} =  HHistory,
-    ClientHSTrafficSecret =
-        tls_v1:client_handshake_traffic_secret(HKDFAlgo, HandshakeSecret, lists:reverse(Messages)),
-    ServerHSTrafficSecret =
-        tls_v1:server_handshake_traffic_secret(HKDFAlgo, HandshakeSecret, lists:reverse(Messages)),
+calculate_handshake_secret(HandshakeSecret, ConnectionState, ReadorWrite, Role, HHistory, Keep)  ->
+    #{security_parameters := SecParams} = ConnectionState,
+    #security_parameters{prf_algorithm = HKDFAlgo,
+                         bulk_cipher_algorithm = BulkCipherAlgo,
+                        cipher_suite = CipherSuite} = SecParams,
+    Messages = get_handshake_context(Role, HHistory),
+    {HsTrafficSecret, SecretType} =
+        case {Role, ReadorWrite} of
+            {server, write} ->
+                {tls_v1:server_handshake_traffic_secret(HKDFAlgo,
+                                                       HandshakeSecret, Messages), server} ;
+            {client, read} ->
+                {tls_v1:server_handshake_traffic_secret(HKDFAlgo,
+                                                       HandshakeSecret, Messages), server};
+            {client, write} ->
+                {tls_v1:client_handshake_traffic_secret(HKDFAlgo,
+                                                       HandshakeSecret, Messages), client};
+            {server, read} ->
+                {tls_v1:client_handshake_traffic_secret(HKDFAlgo,
+                                                       HandshakeSecret, Messages), client}
+        end,
 
-    %% Calculate traffic keys
     KeyLength = tls_v1:key_length(CipherSuite),
-    {ReadKey, ReadIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, KeyLength, ClientHSTrafficSecret),
-    {WriteKey, WriteIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, KeyLength, ServerHSTrafficSecret),
-
-    %% Calculate Finished Keys
-    ReadFinishedKey = tls_v1:finished_key(ClientHSTrafficSecret, HKDFAlgo),
-    WriteFinishedKey = tls_v1:finished_key(ServerHSTrafficSecret, HKDFAlgo),
-
-    State1 = maybe_store_handshake_traffic_secret(State0, HKDFAlgo, ClientHSTrafficSecret, ServerHSTrafficSecret),
-
-    update_pending_connection_states(State1, HandshakeSecret, undefined,
-                                     undefined, undefined,
-                                     ReadKey, ReadIV, ReadFinishedKey,
-                                     WriteKey, WriteIV, WriteFinishedKey).
+    {Key, IV} = tls_v1:calculate_traffic_keys(HKDFAlgo, KeyLength, HsTrafficSecret),
+
+    FinishedKey = tls_v1:finished_key(HsTrafficSecret, HKDFAlgo),
+
+    NewSecParams =
+        SecParams#security_parameters{master_secret = HandshakeSecret},
+
+    NewConnectionState = ConnectionState#{security_parameters => NewSecParams,
+                                         cipher_state =>
+                                             cipher_init(BulkCipherAlgo, Key, IV, FinishedKey)},
+    maybe_store_handshake_traffic_secret(SecretType, NewConnectionState, HsTrafficSecret, Keep).
+
+maybe_store_handshake_traffic_secret(client, ConnectionState, HsTrafficSecret, Keep)
+  when Keep =/=  false ->
+    ConnectionState#{client_handshake_traffic_secret => HsTrafficSecret};
+maybe_store_handshake_traffic_secret(server, ConnectionState, HsTrafficSecret, Keep)
+  when Keep =/=  false ->
+    ConnectionState#{server_handshake_traffic_secret => HsTrafficSecret};
+maybe_store_handshake_traffic_secret(_,ConnectionState, _,_) ->
+    ConnectionState.
+
+maybe_handshake_keylog(Read0, Write0, Opts) ->
+    Keep = maps:get(keep_secrets, Opts, undefined),
+    #{security_parameters := SecParams} = Read0,
+    #security_parameters{prf_algorithm = HKDFAlgo} = SecParams,
+    case Keep of
+        {keylog, Fun} ->
+            #{security_parameters := SecParams0} = Read0,
+            ClientRand = SecParams0#security_parameters.client_random,
+            {ClientHSTrafficSecret, ServerHSTrafficSecret} =
+                hs_secrets(Read0, Write0),
+            KeyLog = ssl_logger:keylog_hs(ClientRand, HKDFAlgo,
+                                          ClientHSTrafficSecret, ServerHSTrafficSecret),
+            ssl_logger:keylog(KeyLog, ClientRand, Fun),
+            {maps:without([client_handshake_traffic_secret, server_handshake_traffic_secret],
+                          Read0),
+             maps:without([client_handshake_traffic_secret, server_handshake_traffic_secret],
+                          Write0)};
+        _ ->
+            {Read0, Write0}
+    end.
+hs_secrets(Read, Write) ->
+    {hs_traffic_secret(client_handshake_traffic_secret, Read, Write),
+     hs_traffic_secret(server_handshake_traffic_secret, Read, Write)}.
+
+hs_traffic_secret(SecretType, Read, Write) ->
+    %% Depending on if caller is a client or server temporary saved
+    %% handshake secrets for key-logging will be saved in either the
+    %% Read or The Write connection state.
+    case maps:get(SecretType, Read, undefined) of
+        undefined ->
+            maps:get(SecretType, Write, undefined);
+        Secret ->
+            Secret
+    end.
 
 %% Server
 calculate_client_early_traffic_secret(#state{connection_states = ConnectionStates,
@@ -933,7 +1033,8 @@ calculate_client_early_traffic_secret(#state{connection_states = ConnectionState
 %% Client
 calculate_client_early_traffic_secret(
   ClientHello, PSK, Cipher, HKDFAlgo,
-  #state{connection_states = ConnectionStates,
+  #state{connection_states = #{pending_write := PendingWrite0,
+                               pending_read := PendingRead0} = ConnectionStates,
          ssl_options = Opts,
          static_env = #static_env{role = Role}} = State0) ->
     EarlySecret = tls_v1:key_schedule(early_secret, HKDFAlgo , {psk, PSK}),
@@ -946,20 +1047,21 @@ calculate_client_early_traffic_secret(
     %% Update pending connection states
     case Role of
         client ->
-            PendingWrite0 = ssl_record:pending_connection_state(ConnectionStates, write),
-            PendingWrite1 = maybe_store_early_data_secret(Opts, ClientEarlyTrafficSecret,
-                                                          PendingWrite0, HKDFAlgo),
-            PendingWrite = update_connection_state(PendingWrite1, undefined, undefined,
-                                                   undefined,
-                                                   Key, IV, undefined),
+            PendingWrite1 = #{security_parameters := SecParams} =
+                maybe_store_early_data_secret(Opts, ClientEarlyTrafficSecret,
+                                              PendingWrite0, HKDFAlgo),
+            BulkCipherAlgo = SecParams#security_parameters.bulk_cipher_algorithm,
+            PendingWrite = PendingWrite1#{cipher_state =>
+                               cipher_init(BulkCipherAlgo, Key, IV, undefined)},
+
             State0#state{connection_states = ConnectionStates#{pending_write => PendingWrite}};
         server ->
-            PendingRead0 = ssl_record:pending_connection_state(ConnectionStates, read),
-            PendingRead1 = maybe_store_early_data_secret(Opts, ClientEarlyTrafficSecret,
-                                                         PendingRead0, HKDFAlgo),
-            PendingRead = update_connection_state(PendingRead1, undefined, undefined,
-                                                   undefined,
-                                                   Key, IV, undefined),
+            PendingRead1  = #{security_parameters := SecParams} =
+                maybe_store_early_data_secret(Opts, ClientEarlyTrafficSecret,
+                                              PendingRead0, HKDFAlgo),
+            BulkCipherAlgo = SecParams#security_parameters.bulk_cipher_algorithm,
+            PendingRead = PendingRead1#{cipher_state =>
+                                            cipher_init(BulkCipherAlgo, Key, IV, undefined)},
             State0#state{connection_states = ConnectionStates#{pending_read => PendingRead}}
     end.
 
@@ -968,12 +1070,14 @@ early_data_secret(undefined) ->
 early_data_secret(Secret) ->
     [{client_early_data_secret, Secret}].
 
-hs_traffic_secrets(#{client_handshake_traffic_secret := ClientHSTrafficSecret,
-                      server_handshake_traffic_secret := ServerHSTrafficSecret}) ->
-     [{client_handshake_traffic_secret, ClientHSTrafficSecret},
-      {server_handshake_traffic_secret, ServerHSTrafficSecret}];
-hs_traffic_secrets(_) ->
-    [].
+hs_traffic_secrets(Read, Write) ->
+    case hs_secrets(Read, Write) of
+        {undefined, undefined} ->
+            [];
+        {ClientHSTrafficSecret, ServerHSTrafficSecret} ->
+            [{client_handshake_traffic_secret, ClientHSTrafficSecret},
+             {server_handshake_traffic_secret, ServerHSTrafficSecret}]
+    end.
 
 maybe_store_early_data_secret(#{keep_secrets := Keep}, EarlySecret,
                               #{security_parameters := SecParams0} = CSState,
@@ -1067,42 +1171,6 @@ choose_psk([#ticket_data{
 choose_psk([_|T], SelectedIdentity) ->
     choose_psk(T, SelectedIdentity).
 
-
-calculate_traffic_secrets(#state{
-                             static_env = #static_env{role = Role},
-                             connection_states = ConnectionStates,
-                             handshake_env =
-                                 #handshake_env{
-                                    tls_handshake_history = HHistory}} = State0) ->
-    #{security_parameters := SecParamsR} =
-        ssl_record:pending_connection_state(ConnectionStates, read),
-    #security_parameters{prf_algorithm = HKDFAlgo,
-                         cipher_suite = CipherSuite,
-                         master_secret = HandshakeSecret} = SecParamsR,
-
-    MasterSecret =
-        tls_v1:key_schedule(master_secret, HKDFAlgo, HandshakeSecret),
-
-    %% Get the correct list messages for the handshake context.
-    Messages = get_handshake_context(Role, HHistory),
-
-    %% Calculate [sender]_application_traffic_secret_0
-    ClientAppTrafficSecret0 =
-        tls_v1:client_application_traffic_secret_0(HKDFAlgo, MasterSecret, Messages),
-    ServerAppTrafficSecret0 =
-        tls_v1:server_application_traffic_secret_0(HKDFAlgo, MasterSecret, Messages),
-
-    %% Calculate traffic keys
-    KeyLength = tls_v1:key_length(CipherSuite),
-    {ReadKey, ReadIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, KeyLength, ClientAppTrafficSecret0),
-    {WriteKey, WriteIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, KeyLength, ServerAppTrafficSecret0),
-
-    update_pending_connection_states(State0, MasterSecret, undefined,
-                                     ClientAppTrafficSecret0, ServerAppTrafficSecret0,
-                                     ReadKey, ReadIV, undefined,
-                                     WriteKey, WriteIV, undefined).
-
-
 calculate_read_traffic_secrets(#state{
                              static_env = #static_env{role = Role},
                                   connection_states = #{pending_read := PendingRead0} =
@@ -1110,29 +1178,7 @@ calculate_read_traffic_secrets(#state{
                                   handshake_env =
                                       #handshake_env{
                                          tls_handshake_history = HHistory}} = State0) ->
-    #{security_parameters := SecParamsR,
-      cipher_state := #cipher_state{finished_key = FinishedKey}} =
-        ssl_record:pending_connection_state(ConnectionStates, read),
-    #security_parameters{prf_algorithm = HKDFAlgo,
-                         cipher_suite = CipherSuite,
-                         master_secret = HandshakeSecret} = SecParamsR,
-
-    MasterSecret =
-        tls_v1:key_schedule(master_secret, HKDFAlgo, HandshakeSecret),
-
-    %% Get the correct list messages for the handshake context.
-    Messages = get_handshake_context(Role, HHistory),
-
-    %% Calculate [sender]_application_traffic_secret_0
-    ClientAppTrafficSecret0 =
-        tls_v1:client_application_traffic_secret_0(HKDFAlgo, MasterSecret, lists:reverse(Messages)),
-
-    %% Calculate traffic keys
-    KeyLength = tls_v1:key_length(CipherSuite),
-    {ReadKey, ReadIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, KeyLength, ClientAppTrafficSecret0),
-    PendingRead = update_connection_state(PendingRead0, MasterSecret, undefined,
-                                          ClientAppTrafficSecret0,
-                                          ReadKey, ReadIV, FinishedKey),
+    PendingRead = calculate_traffic_secrets(PendingRead0, read, Role, HHistory),
     State0#state{connection_states = ConnectionStates#{pending_read => PendingRead}}.
 
 calculate_write_traffic_secrets(#state{
@@ -1142,31 +1188,47 @@ calculate_write_traffic_secrets(#state{
                              handshake_env =
                                  #handshake_env{
                                     tls_handshake_history = HHistory}} = State0) ->
-    #{security_parameters := SecParamsR,
-      cipher_state := #cipher_state{finished_key = FinishedKey}} =
-        ssl_record:pending_connection_state(ConnectionStates, write),
+    PendingWrite = calculate_traffic_secrets(PendingWrite0, write, Role, HHistory),
+    State0#state{connection_states = ConnectionStates#{pending_write => PendingWrite}}.
+
+
+calculate_traffic_secrets(ConnectionState, ReadorWrite, Role, HHistory)  ->
+    #{security_parameters := SecParams,
+      cipher_state := #cipher_state{finished_key = FinishedKey}} = ConnectionState,
     #security_parameters{prf_algorithm = HKDFAlgo,
                          cipher_suite = CipherSuite,
-                         master_secret = HandshakeSecret} = SecParamsR,
-
+                         master_secret = HandshakeSecret,
+                         bulk_cipher_algorithm = BulkCipherAlgo} = SecParams,
     MasterSecret =
         tls_v1:key_schedule(master_secret, HKDFAlgo, HandshakeSecret),
-
-    %% Get the correct list messages for the handshake context.
     Messages = get_handshake_context(Role, HHistory),
 
-    %% Calculate [sender]_application_traffic_secret_0
-    ServerAppTrafficSecret0 =
-        tls_v1:server_application_traffic_secret_0(HKDFAlgo, MasterSecret, lists:reverse(Messages)),
+    AppTrafficSecret0 =
+        case {Role, ReadorWrite} of
+            {server, write} ->
+                tls_v1:server_application_traffic_secret_0(HKDFAlgo,
+                                                           MasterSecret, Messages);
+            {client, read} ->
+                tls_v1:server_application_traffic_secret_0(HKDFAlgo,
+                                                            MasterSecret, Messages);
+            {client, write} ->
+                tls_v1:client_application_traffic_secret_0(HKDFAlgo,
+                                                           MasterSecret, Messages);
+            {server, read} ->
+                tls_v1:client_application_traffic_secret_0(HKDFAlgo,
+                                                           MasterSecret, Messages)
+        end,
 
-    %% Calculate traffic keys
     KeyLength = tls_v1:key_length(CipherSuite),
-    {WriteKey, WriteIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, KeyLength, ServerAppTrafficSecret0),
-    PendingWrite = update_connection_state(PendingWrite0, MasterSecret, undefined,
-                                          ServerAppTrafficSecret0,
-                                          WriteKey, WriteIV, FinishedKey),
-    State0#state{connection_states = ConnectionStates#{pending_write => PendingWrite}}.
+    {Key, IV} = tls_v1:calculate_traffic_keys(HKDFAlgo, KeyLength, AppTrafficSecret0),
+
+    NewSecParams =
+        SecParams#security_parameters{master_secret = MasterSecret,
+                                      application_traffic_secret = AppTrafficSecret0},
 
+    ConnectionState#{security_parameters => NewSecParams,
+                     cipher_state =>
+                         cipher_init(BulkCipherAlgo, Key, IV, FinishedKey)}.
 
 %% X25519, X448
 calculate_shared_secret(OthersKey, MyKey, Group)
@@ -1249,78 +1311,6 @@ overwrite_client_random(ConnectionState = #{security_parameters := SecurityParam
     ConnectionState#{security_parameters => SecurityParameters}.
 
 
-maybe_store_handshake_traffic_secret(#state{connection_states =
-                                                #{pending_read := PendingRead0}= CS,
-                                            ssl_options = #{keep_secrets := Keep}} = State, Prf,
-                                     ClientHSTrafficSecret, ServerHSTrafficSecret) when Keep =/= false ->
-     case Keep of
-        {keylog, Fun} ->
-             #{security_parameters := SecParams0} = PendingRead0,
-             ClientRand = SecParams0#security_parameters.client_random,
-             KeyLog = ssl_logger:keylog_hs(ClientRand, Prf, ClientHSTrafficSecret, ServerHSTrafficSecret),
-             ssl_logger:keylog(KeyLog, ClientRand, Fun),
-             State;
-         _ ->
-             PendingRead = store_handshake_traffic_secret(PendingRead0, ClientHSTrafficSecret, ServerHSTrafficSecret),
-             State#state{connection_states = CS#{pending_read => PendingRead}}
-     end;
-maybe_store_handshake_traffic_secret(State, _, _, _) ->
-    State.
-
-store_handshake_traffic_secret(ConnectionState, ClientHSTrafficSecret, ServerHSTrafficSecret) ->
-    ConnectionState#{client_handshake_traffic_secret => ClientHSTrafficSecret,
-                     server_handshake_traffic_secret => ServerHSTrafficSecret}.
-
-
-update_pending_connection_states(#state{
-                                    static_env = #static_env{role = server},
-                                    connection_states =
-                                        CS = #{pending_read := PendingRead0,
-                                               pending_write := PendingWrite0}} = State,
-                                 HandshakeSecret, ResumptionMasterSecret,
-                                 ClientAppTrafficSecret, ServerAppTrafficSecret,
-                                 ReadKey, ReadIV, ReadFinishedKey,
-                                 WriteKey, WriteIV, WriteFinishedKey) ->
-    PendingRead = update_connection_state(PendingRead0, HandshakeSecret, ResumptionMasterSecret,
-                                          ClientAppTrafficSecret,
-                                          ReadKey, ReadIV, ReadFinishedKey),
-    PendingWrite = update_connection_state(PendingWrite0, HandshakeSecret, ResumptionMasterSecret,
-                                           ServerAppTrafficSecret,
-                                           WriteKey, WriteIV, WriteFinishedKey),
-    State#state{connection_states = CS#{pending_read => PendingRead,
-                                        pending_write => PendingWrite}};
-update_pending_connection_states(#state{
-                                    static_env = #static_env{role = client},
-                                    connection_states =
-                                        CS = #{pending_read := PendingRead0,
-                                               pending_write := PendingWrite0}} = State,
-                                 HandshakeSecret, ResumptionMasterSecret,
-                                 ClientAppTrafficSecret, ServerAppTrafficSecret,
-                                 ReadKey, ReadIV, ReadFinishedKey,
-                                 WriteKey, WriteIV, WriteFinishedKey) ->
-    PendingRead = update_connection_state(PendingRead0, HandshakeSecret, ResumptionMasterSecret,
-                                          ServerAppTrafficSecret,
-                                          WriteKey, WriteIV, WriteFinishedKey),
-    PendingWrite = update_connection_state(PendingWrite0, HandshakeSecret, ResumptionMasterSecret,
-                                           ClientAppTrafficSecret,
-                                           ReadKey, ReadIV, ReadFinishedKey),
-    State#state{connection_states = CS#{pending_read => PendingRead,
-                                        pending_write => PendingWrite}}.
-
-
-update_connection_state(ConnectionState = #{security_parameters := SecurityParameters0},
-                        HandshakeSecret, ResumptionMasterSecret,
-                        ApplicationTrafficSecret, Key, IV, FinishedKey) ->
-    %% Store secret
-    SecurityParameters = SecurityParameters0#security_parameters{
-                           master_secret = HandshakeSecret,
-                           resumption_master_secret = ResumptionMasterSecret,
-                           application_traffic_secret = ApplicationTrafficSecret},
-    BulkCipherAlgo = SecurityParameters#security_parameters.bulk_cipher_algorithm,
-    ConnectionState#{security_parameters => SecurityParameters,
-                     cipher_state => cipher_init(BulkCipherAlgo, Key, IV, FinishedKey)}.
-
-
 update_start_state(State, Map) ->
     Cipher = maps:get(cipher, Map, undefined),
     KeyShare = maps:get(key_share, Map, undefined),
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index 420089f4d1..ca32f81267 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -459,7 +459,7 @@ initial_connection_state(ConnectionEnd, MaxEarlyDataSize) ->
       mac_secret  => undefined,
       early_data => #{pending_early_data_size => MaxEarlyDataSize,
                       trial_decryption => false,
-                      early_data_expected => false
+                      early_data_accepted => false
                      },
       reneg => #{secure_renegotiation => undefined,
                  client_verify_data => undefined,
diff --git a/lib/ssl/src/tls_server_connection_1_3.erl b/lib/ssl/src/tls_server_connection_1_3.erl
index e907258084..3630ac70fe 100644
--- a/lib/ssl/src/tls_server_connection_1_3.erl
+++ b/lib/ssl/src/tls_server_connection_1_3.erl
@@ -258,7 +258,6 @@ negotiated(internal, {start_handshake, _} = Message, State0) ->
         {State1, NextState} ->
             State2 = tls_handshake_1_3:calculate_write_traffic_secrets(State1),
             State = ssl_record:step_encryption_state_write(State2),
-            maybe_keylog(State),
             {next_state, NextState, State, []}
     end;
 negotiated(info, Msg, State) ->
@@ -552,14 +551,7 @@ send_hello_flight({start_handshake, PSK0},
                 true ->
                     ssl_record:step_encryption_state_write(State3);
                 false ->
-                    %% Read state is overwritten when handshake secrets are set.
-                    %% Trial_decryption and early_data_accepted must be set here!
-                    update_current_read(
-                      ssl_record:step_encryption_state(State3),
-                      true,   %% trial_decryption
-                      false   %% early_data_accepted
-                    )
-
+                    ssl_record:step_encryption_state(State3)
             end,
 
         %% Create EncryptedExtensions
@@ -629,8 +621,11 @@ session_resumption({#state{ssl_options = #{session_tickets := Tickets},
   when Tickets =/= disabled -> % Resumption but early data prohibited
     State1 = tls_gen_connection_1_3:handle_resumption(State0, ok),
     {Index, PSK, PeerCert} = PSKInfo,
-    State = maybe_store_peer_cert(State1, PeerCert),
-    {ok, {State, negotiated, {Index, PSK}}};
+    State = #state{connection_states = #{pending_read := Read0} = CS} =
+        maybe_store_peer_cert(State1, PeerCert),
+     #{early_data := EarlyData0} = Read0,
+    Read = Read0#{early_data => EarlyData0#{trial_decryption => true}},
+    {ok, {State#state{connection_states = CS#{pending_read => Read}}, negotiated, {Index, PSK}}};
 session_resumption({#state{ssl_options = #{session_tickets := Tickets},
                            handshake_env = #handshake_env{
                                               early_data_accepted = true}} = State0,
@@ -639,11 +634,16 @@ session_resumption({#state{ssl_options = #{session_tickets := Tickets},
     State1 = tls_gen_connection_1_3:handle_resumption(State0, ok),
     %% TODO Refactor PSK-tuple {Index, PSK}, index might not be needed.
     {Index, PSK, PeerCert} = PSKInfo,
-    State2 = tls_handshake_1_3:calculate_client_early_traffic_secret(State1, PSK),
+    State2 = maybe_store_peer_cert(State1, PeerCert),
+    State3 =
+        tls_handshake_1_3:calculate_client_early_traffic_secret(State2, PSK),
     %% Set 0-RTT traffic keys for reading early_data
-    State3 = ssl_record:step_encryption_state_read(State2),
-    State4 = maybe_store_peer_cert(State3, PeerCert),
-    State = update_current_read(State4, true, true),
+    State4 = #state{connection_states = #{current_read := Read0} = CS}
+        = ssl_record:step_encryption_state_read(State3),
+    #{early_data := EarlyData0} = Read0,
+    Read = Read0#{early_data => EarlyData0#{trial_decryption => true,
+                                            early_data_accepted => true}},
+    State = State4#state{connection_states = CS#{current_read => Read}},
     {ok, {State, negotiated, {Index, PSK}}}.
 
 maybe_store_peer_cert(State, undefined) ->
@@ -803,13 +803,6 @@ send_hello_retry_request(State0, _, _, _) ->
     %% Suitable key found.
     {ok, {State0, negotiated}}.
 
-update_current_read(#state{connection_states = CS} = State, TrialDecryption, EarlyDataExpected) ->
-    #{early_data := EarlyData0} = Read0 = ssl_record:current_connection_state(CS, read),
-    EarlyData = EarlyData0#{trial_decryption => TrialDecryption,
-                            early_data_accepted => EarlyDataExpected},
-    Read = Read0#{early_data := EarlyData},
-    State#state{connection_states = CS#{current_read => Read}}.
-
 handle_early_data(State, enabled, #early_data_indication{}) ->
     %% Accept early data
     HsEnv = (State#state.handshake_env)#handshake_env{early_data_accepted = true},
@@ -932,23 +925,3 @@ handle_alpn([ServerProtocol|T], ClientProtocols) ->
         false ->
             handle_alpn(T, ClientProtocols)
     end.
-
-maybe_keylog(#state{ssl_options = Options,
-                    connection_states = ConnectionStates,
-                    protocol_specific = PS})->
-    KeylogFun = maps:get(keep_secrets, Options, undefined),
-    maybe_keylog(KeylogFun, PS, ConnectionStates).
-
-maybe_keylog({Keylog, Fun}, ProtocolSpecific, ConnectionStates) when Keylog == keylog_hs;
-                                                                     Keylog == keylog ->
-    N = maps:get(num_key_updates, ProtocolSpecific, 0),
-    #{security_parameters := #security_parameters{client_random = ClientRandom,
-                                                  prf_algorithm = Prf,
-                                                  application_traffic_secret = TrafficSecret}}
-        = ssl_record:current_connection_state(ConnectionStates, write),
-    TrafficKeyLog = ssl_logger:keylog_traffic_1_3(server, ClientRandom,
-                                                  Prf, TrafficSecret, N),
-
-    ssl_logger:keylog(TrafficKeyLog, ClientRandom, Fun);
-maybe_keylog(_,_,_) ->
-    ok.
diff --git a/lib/ssl/test/ssl_session_ticket_SUITE.erl b/lib/ssl/test/ssl_session_ticket_SUITE.erl
index 1ce8d29e53..c721f3f010 100644
--- a/lib/ssl/test/ssl_session_ticket_SUITE.erl
+++ b/lib/ssl/test/ssl_session_ticket_SUITE.erl
@@ -1222,7 +1222,7 @@ early_data_basic(Config) when is_list(Config) ->
                                                 verify_active_session_resumption,
                                                 [false]}},
                                          {from, self()}, {options, ClientOpts1}]),
-    skip_keylogs(4), %% HS and two traffic secrets
+    skip_keylogs(3), %% HS and two traffic secrets
 
     ssl_test_lib:check_result(Server0, ok, Client0, ok),
 
@@ -1247,7 +1247,7 @@ early_data_basic(Config) when is_list(Config) ->
         {keylog, #{items := EarlyKeylog}} ->
             ["CLIENT_EARLY_TRAFFIC_SECRET" ++ _| _] = EarlyKeylog
     end,
-    skip_keylogs(4), %% HS and two traffic secrets so they do not end up
+    skip_keylogs(3), %% HS and two traffic secrets so they do not end up
                      %% in check_result
 
     ssl_test_lib:check_result(Server0, ok, Client1, ok),
diff --git a/lib/ssl/test/tls_1_3_version_SUITE.erl b/lib/ssl/test/tls_1_3_version_SUITE.erl
index 913b7eafff..83001fe5e2 100644
--- a/lib/ssl/test/tls_1_3_version_SUITE.erl
+++ b/lib/ssl/test/tls_1_3_version_SUITE.erl
@@ -29,6 +29,8 @@
          groups/0,
          init_per_suite/1,
          init_per_group/2,
+         init_per_testcase/2,
+         end_per_testcase/2,
          end_per_suite/1,
          end_per_group/2
         ]).
@@ -91,7 +93,7 @@
 %%--------------------------------------------------------------------
 %% Common Test interface functions -----------------------------------
 %%--------------------------------------------------------------------
-all() -> 
+all() ->
     [
      cert_groups()
     ].
@@ -139,10 +141,10 @@ legacy_tests() ->
 init_per_suite(Config) ->
     case application:ensure_started(crypto) of
 	ok ->
-            case ssl_test_lib:sufficient_crypto_support('tlsv1.3') of                
+            case ssl_test_lib:sufficient_crypto_support('tlsv1.3') of
                 true ->
                     ssl_test_lib:clean_start(),
-                    [{client_type, erlang}, {server_type, erlang} | 
+                    [{client_type, erlang}, {server_type, erlang} |
                      Config];
                 false ->
                     {skip, "Insufficient crypto support for TLS-1.3"}
@@ -160,18 +162,18 @@ init_per_group(rsa, Config0) ->
     COpts = proplists:get_value(client_rsa_opts, Config),
     SOpts = proplists:get_value(server_rsa_opts, Config),
     [{client_type, erlang},
-     {server_type, erlang},{client_cert_opts, COpts}, {server_cert_opts, SOpts} | 
+     {server_type, erlang},{client_cert_opts, COpts}, {server_cert_opts, SOpts} |
      lists:delete(server_cert_opts, lists:delete(client_cert_opts, Config))];
 init_per_group(ecdsa, Config0) ->
     PKAlg = crypto:supports(public_keys),
-    case lists:member(ecdsa, PKAlg) andalso 
+    case lists:member(ecdsa, PKAlg) andalso
         (lists:member(ecdh, PKAlg) orelse lists:member(dh, PKAlg)) of
         true ->
             Config = ssl_test_lib:make_ecdsa_cert(Config0),
             COpts = proplists:get_value(client_ecdsa_opts, Config),
             SOpts = proplists:get_value(server_ecdsa_opts, Config),
             [{client_type, erlang},
-             {server_type, erlang},{client_cert_opts, COpts}, {server_cert_opts, SOpts} | 
+             {server_type, erlang},{client_cert_opts, COpts}, {server_cert_opts, SOpts} |
              lists:delete(server_cert_opts, lists:delete(client_cert_opts, Config))];
         false ->
             {skip, "Missing EC crypto support"}
@@ -179,6 +181,15 @@ init_per_group(ecdsa, Config0) ->
 
 end_per_group(GroupName, Config) ->
     ssl_test_lib:end_per_group(GroupName, Config).
+
+init_per_testcase(_TestCase, Config) ->
+    ssl_test_lib:ct_log_supported_protocol_versions(Config),
+    ct:timetrap({seconds, 20}),
+    Config.
+
+end_per_testcase(_TestCase, Config) ->
+    Config.
+
 %%--------------------------------------------------------------------
 %% Test Cases --------------------------------------------------------
 %%--------------------------------------------------------------------
@@ -195,9 +206,8 @@ tls13_client_tls12_server(Config) when is_list(Config) ->
     ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
 
 
-    
 tls13_client_with_ext_tls12_server() ->
-     [{doc,"Test basic connection between TLS 1.2 server and TLS 1.3 client when " 
+     [{doc,"Test basic connection between TLS 1.2 server and TLS 1.3 client when "
        "client has TLS 1.3 specific extensions"}].
 
 tls13_client_with_ext_tls12_server(Config) ->
@@ -217,11 +227,11 @@ tls13_client_with_ext_tls12_server(Config) ->
                                          rsa_pkcs1_sha256,
                                          ecdsa_sha1]}|ClientOpts0],
     ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
-   
+
 tls12_client_tls13_server() ->
     [{doc,"Test that a TLS 1.2 client can connect to a TLS 1.3 server."}].
 
-tls12_client_tls13_server(Config) when is_list(Config) ->    
+tls12_client_tls13_server(Config) when is_list(Config) ->
     ClientOpts = [{versions, ['tlsv1.1', 'tlsv1.2']} |
                   ssl_test_lib:ssl_options(client_cert_opts, Config)],
     ServerOpts =  [{versions, ['tlsv1.3', 'tlsv1.2']},
@@ -236,7 +246,7 @@ tls_client_tls10_server(Config) when is_list(Config) ->
                                         [{key_exchange, fun(srp_rsa)  -> false;
                                                            (srp_anon) -> false;
                                                            (srp_dss) -> false;
-                                                           (_) -> true end}]),        
+                                                           (_) -> true end}]),
     ClientOpts = [{versions, ['tlsv1', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3']},
                   {ciphers, CCiphers} |
                   ssl_test_lib:ssl_options(client_cert_opts, Config)],
@@ -253,14 +263,14 @@ tls_client_tls11_server(Config) when is_list(Config) ->
                                         [{key_exchange, fun(srp_rsa)  -> false;
                                                            (srp_anon) -> false;
                                                            (srp_dss) -> false;
-                                                           (_) -> true end}]),    
+                                                           (_) -> true end}]),
     ClientOpts = [{versions,
                    ['tlsv1', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3']},
                   {ciphers, CCiphers} |
                   ssl_test_lib:ssl_options(client_cert_opts, Config)],
     ServerOpts =  [{versions,['tlsv1.1']},
                    {verify, verify_peer}, {fail_if_no_peer_cert, true},
-                   {ciphers, ssl:cipher_suites(all, 'tlsv1.1')}  
+                   {ciphers, ssl:cipher_suites(all, 'tlsv1.1')}
                   | ssl_test_lib:ssl_options(server_cert_opts, Config)],
     ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
 
@@ -282,7 +292,7 @@ tls10_client_tls_server(Config) when is_list(Config) ->
                                         [{key_exchange, fun(srp_rsa)  -> false;
                                                            (srp_anon) -> false;
                                                            (srp_dss) -> false;
-                                                           (_) -> true end}]),    
+                                                           (_) -> true end}]),
     ClientOpts = [{versions, ['tlsv1']},
                   {ciphers, ssl:cipher_suites(all, 'tlsv1')} |
                   ssl_test_lib:ssl_options(client_cert_opts, Config)],
@@ -300,7 +310,6 @@ tls11_client_tls_server(Config) when is_list(Config) ->
                                                            (srp_anon) -> false;
                                                            (srp_dss) -> false;
                                                            (_) -> true end}]),
-    
     ClientOpts = [{versions, ['tlsv1.1']},
                   {ciphers, ssl:cipher_suites(all, 'tlsv1.1')} |
                   ssl_test_lib:ssl_options(client_cert_opts, Config)],
@@ -341,7 +350,7 @@ legacy_tls12_server_tls_client(Config) when is_list(Config) ->
     SHA = sha384,
     Prop = proplists:get_value(tc_group_properties, Config),
     Alg = proplists:get_value(name, Prop),
-    #{client_config := ClientOpts0, 
+    #{client_config := ClientOpts0,
       server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(Alg, [{server_chain,
                                                                                [[{digest, SHA}],
                                                                                 [{digest, SHA}],
@@ -608,55 +617,61 @@ keylog_on_alert(Config) when is_list(Config) ->
     Fun = fun(AlertInfo) ->
                   Me ! {alert_info, AlertInfo}
           end,
-    alert_passive([{keep_secrets, {keylog_hs, Fun}} | ServerOpts], ClientOpts, recv,
-                  ServerNode, Hostname, unknown_ca),
+    keylog_alert_passive([{keep_secrets, {keylog_hs, Fun}} | ServerOpts], ClientOpts, recv,
+                         ServerNode, Hostname),
 
-    receive_server_keylog_for_client_cert_alert(),
+    receive_server_keylog_for_server_cert_alert(),
 
-    alert_passive(ServerOpts, [{keep_secrets, {keylog_hs, Fun}} | ClientOpts], recv,
-                  ServerNode, Hostname, unknown_ca),
+    keylog_alert_passive(ServerOpts,
+                         [{keep_secrets, {keylog_hs, Fun}} | ClientOpts], recv,
+                         ServerNode, Hostname),
 
     receive_client_keylog_for_client_cert_alert(),
 
     ClientNoCert = proplists:delete(keyfile, proplists:delete(certfile, ClientOpts0)),
-    alert_passive([{keep_secrets, {keylog_hs, Fun}} | ServerOpts], [{active, false} | ClientNoCert], recv,
-                  ServerNode, Hostname, certificate_required),
+    keylog_alert_passive([{keep_secrets, {keylog_hs, Fun}} | ServerOpts],
+                         [{active, false} | ClientNoCert],
+                         recv, ServerNode, Hostname),
+    receive_server_keylog_for_server_cert_alert().
 
-    receive_server_keylog_for_client_cert_alert().
-
-receive_server_keylog_for_client_cert_alert() ->
+receive_server_keylog_for_server_cert_alert() ->
     %% This alert will be decrypted with application secrets
     %% as client is already in connection
-    receive
-        {alert_info, #{items := SKeyLog1}} ->
-            case SKeyLog1 of
-                ["SERVER_TRAFFIC_SECRET_0"++_] ->
-                    ok;
-                S1Other ->
-                    ct:fail({server_received, S1Other})
-            end
-    end,
-
     receive
         {alert_info, #{items := SKeyLog}} ->
-            case SKeyLog of
-                ["CLIENT_HANDSHAKE_TRAFFIC_SECRET"++_,_|_] ->
+            case keylog_prefixes(["CLIENT_HANDSHAKE_TRAFFIC_SECRET",
+                                  "SERVER_HANDSHAKE_TRAFFIC_SECRET",
+                                  "SERVER_TRAFFIC_SECRET_0"], SKeyLog) of
+                true ->
                     ok;
-                SOther ->
-                    ct:fail({server_received, SOther})
+                false ->
+                    ct:fail({server_received, SKeyLog})
             end
     end.
 
 receive_client_keylog_for_client_cert_alert() ->
     receive
         {alert_info, #{items := CKeyLog}} ->
-            case CKeyLog of
-                ["CLIENT_HANDSHAKE_TRAFFIC_SECRET"++_,_,_,_|_] ->
+            case keylog_prefixes(["CLIENT_HANDSHAKE_TRAFFIC_SECRET",
+                                  "SERVER_HANDSHAKE_TRAFFIC_SECRET",
+                                  "CLIENT_TRAFFIC_SECRET_0",
+                                  "SERVER_TRAFFIC_SECRET_0"], CKeyLog) of
+                true ->
                     ok;
-                COther ->
-                    ct:fail({client_received, COther})
+                false ->
+                    ct:fail({client_received, CKeyLog})
             end
     end.
+keylog_prefixes([], []) ->
+    true;
+keylog_prefixes([Prefix | Prefixes], [Secret | Secrets]) ->
+    case lists:prefix(Prefix, Secret) of
+        true  ->
+            keylog_prefixes(Prefixes, Secrets);
+        false ->
+            false
+    end.
+
 %%--------------------------------------------------------------------
 %% Internal functions and callbacks -----------------------------------
 %%--------------------------------------------------------------------
@@ -703,6 +718,26 @@ alert_passive(ServerOpts, ClientOpts, Function,
             {error, {tls_alert, {unknown_ca,_}}} = ssl:setopts(Socket, [{active, once}])
     end.
 
+keylog_alert_passive(ServerOpts, ClientOpts, Function,
+                     ServerNode, Hostname) ->
+    Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+                                        {from, self()},
+                                        {mfa, {ssl_test_lib, no_result, []}},
+                                        {options, ServerOpts}]),
+    Port = ssl_test_lib:inet_port(Server),
+
+    Fun = fun() ->
+                  {ok, Socket} = ssl:connect(Hostname, Port, ClientOpts),
+                  case Function of
+                      recv ->
+                          ssl:recv(Socket, 0);
+                      setopts ->
+                          ssl:setopts(Socket, [{active, once}])
+                  end
+          end,
+    %% Execute in other process and let test case detect key-log message.
+    spawn_link(Fun).
+
 create_bad_client_certfile(NewClientCertFile, ClientOpts) ->
     KeyFile =  proplists:get_value(keyfile, ClientOpts),
     [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
-- 
2.51.0

openSUSE Build Service is sponsored by