Sophie

Sophie

distrib > Mageia > 6 > armv7hl > media > core-updates-src > by-pkgid > 66b02c29b62f01a562ef179c7a1ffd5d > files > 5

erlang-18.3.2-9.1.mga6.src.rpm

From de3b9cdb8521d7edd524b4e17d1e3f883f832ec0 Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin <ingela@erlang.org>
Date: Tue, 7 Nov 2017 18:34:34 +0100
Subject: [PATCH] ssl: Countermeasurements for Bleichenbacher attack

Back ported for security reasons.
Remove DTLS changes as DTLS is not at all working in OTP 18.
---
 lib/ssl/src/ssl_connection.erl | 21 +++++++++++++++++++--
 lib/ssl/src/ssl_connection.hrl |  3 ++-
 lib/ssl/src/tls_connection.erl |  1 +
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 0f0072ba345..4be59501e41 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -1157,8 +1157,25 @@ server_certify_and_key_exchange(State0, Connection) ->
     request_client_cert(State2, Connection).
 
 certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS},
-			    #state{private_key = Key} = State, Connection) ->
-    PremasterSecret = ssl_handshake:premaster_secret(EncPMS, Key),
+			    #state{private_key = Key, client_hello_version = {Major, Minor} = Version} = State, Connection) ->
+
+    %% Countermeasure for Bleichenbacher attack always provide some kind of premaster secret
+    %% and fail handshake later.RFC 5246 section 7.4.7.1.
+    PremasterSecret =
+        try ssl_handshake:premaster_secret(EncPMS, Key) of
+            Secret when erlang:byte_size(Secret) == ?NUM_OF_PREMASTERSECRET_BYTES ->
+                case Secret of
+                    <<?BYTE(Major), ?BYTE(Minor), _/binary>> -> %% Correct
+                        Secret;
+                    <<?BYTE(_), ?BYTE(_), Rest/binary>> -> %% Version mismatch
+                        <<?BYTE(Major), ?BYTE(Minor), Rest/binary>>
+                end;
+            _ -> %% erlang:byte_size(Secret) =/= ?NUM_OF_PREMASTERSECRET_BYTES
+                make_premaster_secret(Version, rsa)
+        catch 
+            #alert{description = ?DECRYPT_ERROR} ->
+                make_premaster_secret(Version, rsa)     
+        end,        
     calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
 
 certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPublicDhKey},
diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl
index 9a58f2b8f74..e3abc7d4aac 100644
--- a/lib/ssl/src/ssl_connection.hrl
+++ b/lib/ssl/src/ssl_connection.hrl
@@ -54,7 +54,8 @@
 	  session_cache         :: db_handle(),
 	  session_cache_cb      :: atom(),
 	  crl_db                :: term(), 
-          negotiated_version    :: ssl_record:ssl_version(),
+          negotiated_version    :: ssl_record:ssl_version() | 'undefined',
+          client_hello_version  :: ssl_record:ssl_version() | 'undefined',
           client_certificate_requested = false :: boolean(),
 	  key_algorithm         :: ssl_cipher:key_algo(),
 	  hashsign_algorithm = {undefined, undefined},
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 93716d31b83..5a70cf96dc7 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -206,6 +206,7 @@ hello(Hello = #client_hello{client_version = ClientVersion,
 	    ssl_connection:hello({common_client_hello, Type, ServerHelloExt},
 				 State#state{connection_states  = ConnectionStates,
 					     negotiated_version = Version,
+                                             client_hello_version = ClientVersion,
 					     hashsign_algorithm = HashSign,
 					     session = Session,
 					     client_ecc = {EllipticCurves, EcPointFormats},