File 2953-ssl-Send-change_cipher_spec-in-ssl-server.patch of Package erlang
From 21f83f5a9618db7ba8a9e5edcad6bb637c79b22c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= <peterdmv@erlang.org>
Date: Fri, 20 Mar 2020 10:03:21 +0100
Subject: [PATCH 3/3] ssl: Send change_cipher_spec in ssl server
---
lib/ssl/doc/src/standards_compliance.xml | 4 +-
lib/ssl/src/tls_connection.erl | 5 ++-
lib/ssl/src/tls_handshake_1_3.erl | 66 ++++++++++++++++++++++----------
3 files changed, 51 insertions(+), 24 deletions(-)
diff --git a/lib/ssl/doc/src/standards_compliance.xml b/lib/ssl/doc/src/standards_compliance.xml
index d70f12ad51..75e6854499 100644
--- a/lib/ssl/doc/src/standards_compliance.xml
+++ b/lib/ssl/doc/src/standards_compliance.xml
@@ -2336,8 +2336,8 @@
</url>
</cell>
<cell align="left" valign="middle"><em></em></cell>
- <cell align="left" valign="middle"><em>PC</em></cell>
- <cell align="left" valign="middle"><em>22</em></cell>
+ <cell align="left" valign="middle"><em>C</em></cell>
+ <cell align="left" valign="middle"><em>23</em></cell>
</row>
<row>
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index dc54a972a4..4a02d34a6b 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -430,7 +430,10 @@ queue_handshake(Handshake, #state{handshake_env = #handshake_env{tls_handshake_h
handshake_env = HsEnv#handshake_env{tls_handshake_history = Hist},
flight_buffer = Flight0 ++ [BinHandshake]}.
-
+-spec send_handshake_flight(StateIn) -> {StateOut, FlightBuffer} when
+ StateIn :: #state{},
+ StateOut :: #state{},
+ FlightBuffer :: list().
send_handshake_flight(#state{static_env = #static_env{socket = Socket,
transport_cb = Transport},
flight_buffer = Flight} = State0) ->
diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl
index 9a87d98dbe..982d0fa787 100644
--- a/lib/ssl/src/tls_handshake_1_3.erl
+++ b/lib/ssl/src/tls_handshake_1_3.erl
@@ -741,42 +741,44 @@ do_negotiated({start_handshake, PSK0},
try
%% Create server_hello
ServerHello = server_hello(server_hello, SessionId, KeyShare, PSK0, ConnectionStates0),
-
- {State1, _} = tls_connection:send_handshake(ServerHello, State0),
+ State1 = tls_connection:queue_handshake(ServerHello, State0),
+ %% D.4. Middlebox Compatibility Mode
+ State2 = maybe_queue_change_cipher_spec(State1, last),
+ {State3, _} = tls_connection:send_handshake_flight(State2),
PSK = get_pre_shared_key(PSK0, HKDF),
- State2 =
+ State4 =
calculate_handshake_secrets(ClientPublicKey, ServerPrivateKey, SelectedGroup,
- PSK, State1),
+ PSK, State3),
- State3 = ssl_record:step_encryption_state(State2),
+ State5 = ssl_record:step_encryption_state(State4),
%% Create EncryptedExtensions
- EncryptedExtensions = encrypted_extensions(State2),
+ EncryptedExtensions = encrypted_extensions(State5),
%% Encode EncryptedExtensions
- State4 = tls_connection:queue_handshake(EncryptedExtensions, State3),
+ State6 = tls_connection:queue_handshake(EncryptedExtensions, State5),
%% Create and send CertificateRequest ({verify, verify_peer})
- {State5, NextState} = maybe_send_certificate_request(State4, SslOpts, PSK0),
+ {State7, NextState} = maybe_send_certificate_request(State6, SslOpts, PSK0),
%% Create and send Certificate (if PSK is undefined)
- State6 = Maybe(maybe_send_certificate(State5, PSK0)),
+ State8 = Maybe(maybe_send_certificate(State7, PSK0)),
%% Create and send CertificateVerify (if PSK is undefined)
- State7 = Maybe(maybe_send_certificate_verify(State6, PSK0)),
+ State9 = Maybe(maybe_send_certificate_verify(State8, PSK0)),
%% Create Finished
- Finished = finished(State7),
+ Finished = finished(State9),
%% Encode Finished
- State8 = tls_connection:queue_handshake(Finished, State7),
+ State10= tls_connection:queue_handshake(Finished, State9),
%% Send first flight
- {State9, _} = tls_connection:send_handshake_flight(State8),
+ {State, _} = tls_connection:send_handshake_flight(State10),
- {State9, NextState}
+ {State, NextState}
catch
{Ref, #alert{} = Alert} ->
@@ -838,7 +840,7 @@ do_wait_finished(#finished{verify_data = VerifyData},
Maybe(validate_finished(State0, VerifyData)),
%% D.4. Middlebox Compatibility Mode
- State1 = maybe_queue_change_cipher_spec(State0),
+ State1 = maybe_queue_change_cipher_spec(State0, first),
%% Maybe send Certificate + CertificateVerify
State2 = Maybe(maybe_queue_cert_cert_cv(State1)),
@@ -994,12 +996,14 @@ handle_resumption(#state{handshake_env = HSEnv0} = State, _) ->
HSEnv = HSEnv0#handshake_env{resumption = true},
State#state{handshake_env = HSEnv}.
-%% @doc Enqueues a change_cipher_spec record as the first message of
+%% @doc Enqueues a change_cipher_spec record as the first/last message of
%% the current flight buffer
%% @end
-maybe_queue_change_cipher_spec(#state{flight_buffer = FlightBuffer0} = State0) ->
- %%CCSBin = create_change_cipher_spec(State0),
+maybe_queue_change_cipher_spec(#state{flight_buffer = FlightBuffer0} = State0, first) ->
{State, FlightBuffer} = maybe_prepend_change_cipher_spec(State0, FlightBuffer0),
+ State#state{flight_buffer = FlightBuffer};
+maybe_queue_change_cipher_spec(#state{flight_buffer = FlightBuffer0} = State0, last) ->
+ {State, FlightBuffer} = maybe_append_change_cipher_spec(State0, FlightBuffer0),
State#state{flight_buffer = FlightBuffer}.
%% @doc Prepends a change_cipher_spec record to the input binary
@@ -1028,6 +1032,21 @@ maybe_prepend_change_cipher_spec(#state{
maybe_prepend_change_cipher_spec(State, Bin) ->
{State, Bin}.
+%% @doc Appends a change_cipher_spec record to the input binary
+%% @end
+maybe_append_change_cipher_spec(#state{
+ ssl_options =
+ #{middlebox_comp_mode := true},
+ handshake_env =
+ #handshake_env{
+ change_cipher_spec_sent = false} = HSEnv} = State, Bin) ->
+ CCSBin = create_change_cipher_spec(State),
+ {State#state{handshake_env =
+ HSEnv#handshake_env{change_cipher_spec_sent = true}},
+ Bin ++ [CCSBin]};
+maybe_append_change_cipher_spec(State, Bin) ->
+ {State, Bin}.
+
maybe_queue_cert_cert_cv(#state{client_certificate_requested = false} = State) ->
{ok, State};
maybe_queue_cert_cert_cv(#state{connection_states = _ConnectionStates0,
@@ -1109,12 +1128,17 @@ compare_verify_data(_, _) ->
send_hello_retry_request(#state{connection_states = ConnectionStates0} = State0,
no_suitable_key, KeyShare, SessionId) ->
ServerHello = server_hello(hello_retry_request, SessionId, KeyShare, undefined, ConnectionStates0),
- {State1, _} = tls_connection:send_handshake(ServerHello, State0),
+
+
+ State1 = tls_connection:queue_handshake(ServerHello, State0),
+ %% D.4. Middlebox Compatibility Mode
+ State2 = maybe_queue_change_cipher_spec(State1, last),
+ {State3, _} = tls_connection:send_handshake_flight(State2),
%% Update handshake history
- State2 = replace_ch1_with_message_hash(State1),
+ State4 = replace_ch1_with_message_hash(State3),
- {ok, {State2, start}};
+ {ok, {State4, start}};
send_hello_retry_request(State0, _, _, _) ->
%% Suitable key found.
{ok, {State0, negotiated}}.
--
2.16.4