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

openSUSE Build Service is sponsored by