File 0150-ssl-Dissalow-two-change_cipher_specs-in-a-row-in-TLS.patch of Package erlang
From dd69c92f97753d77431de88617655b1526e4ee8d Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin <ingela@erlang.org>
Date: Fri, 17 Oct 2025 19:40:09 +0200
Subject: [PATCH] ssl: Dissalow two change_cipher_specs in a row in TLS-1.2
statemachine
This would always end up in a failed connection, but we like to
have early failure and not fail due to a broken state but instead
due to discovery of an unexpected protocol message.
---
lib/ssl/src/dtls_gen_connection.erl | 1 +
lib/ssl/src/tls_dtls_gen_connection.erl | 8 ++++----
lib/ssl/src/tls_gen_connection.erl | 3 ++-
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/lib/ssl/src/dtls_gen_connection.erl b/lib/ssl/src/dtls_gen_connection.erl
index f52994e98d..6552acb7c4 100644
--- a/lib/ssl/src/dtls_gen_connection.erl
+++ b/lib/ssl/src/dtls_gen_connection.erl
@@ -599,6 +599,7 @@ reinit_handshake_data(#state{static_env = #static_env{data_tag = DataTag},
State#state{handshake_env = HsEnv#handshake_env{tls_handshake_history = ssl_handshake:init_handshake_history(),
public_key_info = undefined,
premaster_secret = undefined,
+ expecting_finished = false,
flight_buffer = new_flight()},
protocol_specific = PS#{flight_state => initial_flight_state(DataTag)},
protocol_buffers =
diff --git a/lib/ssl/src/tls_dtls_gen_connection.erl b/lib/ssl/src/tls_dtls_gen_connection.erl
index 8aad23a6f9..3b935b54a2 100644
--- a/lib/ssl/src/tls_dtls_gen_connection.erl
+++ b/lib/ssl/src/tls_dtls_gen_connection.erl
@@ -299,9 +299,9 @@ abbreviated({call, From}, Msg, State) ->
handle_call(Msg, From, ?STATE(abbreviated), State);
abbreviated(internal,
#change_cipher_spec{type = <<1>>},
- #state{static_env = #static_env{protocol_cb = Connection},
- connection_states = ConnectionStates0,
- handshake_env = HsEnv} = State) ->
+ #state{handshake_env = #handshake_env{expecting_finished = false} = HsEnv,
+ static_env = #static_env{protocol_cb = Connection},
+ connection_states = ConnectionStates0} = State) ->
ConnectionStates1 =
ssl_record:activate_pending_connection_state(ConnectionStates0, read, Connection),
Connection:next_event(?STATE(abbreviated), no_record,
@@ -333,7 +333,7 @@ certify(Type, Event, State) ->
cipher({call, From}, Msg, State) ->
handle_call(Msg, From, ?STATE(cipher), State);
cipher(internal, #change_cipher_spec{type = <<1>>},
- #state{handshake_env = HsEnv,
+ #state{handshake_env = #handshake_env{expecting_finished = false} = HsEnv,
static_env = #static_env{protocol_cb = Connection},
connection_states = ConnectionStates0} = State) ->
ConnectionStates =
diff --git a/lib/ssl/src/tls_gen_connection.erl b/lib/ssl/src/tls_gen_connection.erl
index 5a81b26146..3bd2a7e877 100644
--- a/lib/ssl/src/tls_gen_connection.erl
+++ b/lib/ssl/src/tls_gen_connection.erl
@@ -220,7 +220,8 @@ reinit_handshake_data(#state{handshake_env = HsEnv} =State) ->
handshake_env = HsEnv#handshake_env{tls_handshake_history =
ssl_handshake:init_handshake_history(),
public_key_info = undefined,
- premaster_secret = undefined}
+ premaster_secret = undefined,
+ expecting_finished = false}
}.
select_sni_extension(#client_hello{extensions = #{sni := SNI}}) ->
--
2.51.0