aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/doc/src/notes.xml25
-rw-r--r--lib/ssl/doc/src/ssl.xml2
-rw-r--r--lib/ssl/src/dtls_connection.erl5
-rw-r--r--lib/ssl/src/ssl_cipher.erl37
-rw-r--r--lib/ssl/src/ssl_connection.erl8
-rw-r--r--lib/ssl/src/ssl_connection.hrl2
-rw-r--r--lib/ssl/src/tls_connection.erl18
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl10
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl29
-rw-r--r--lib/ssl/test/ssl_test_lib.erl17
-rw-r--r--lib/ssl/vsn.mk2
11 files changed, 85 insertions, 70 deletions
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index d02e21a013..c7f50777a8 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -28,6 +28,31 @@
<p>This document describes the changes made to the SSL application.</p>
+<section><title>SSL 8.0.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A timing related bug in event handling could cause
+ interoperability problems between an erlang TLS server
+ and some TLS clients, especially noticed with Firefox as
+ TLS client.</p>
+ <p>
+ Own Id: OTP-13917</p>
+ </item>
+ <item>
+ <p>
+ Correct ECC curve selection, the error could cause the
+ default to always be selected.</p>
+ <p>
+ Own Id: OTP-13918</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 8.0.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index abba5aaf59..68f2f97b6e 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -155,7 +155,7 @@
<tag><c>cipher() =</c></tag>
<item><p><c>rc4_128 | des_cbc | '3des_ede_cbc'
- | aes_128_cbc | aes_256_cbc | aes_128_gcm | aes_256_gcm</c></p></item>
+ | aes_128_cbc | aes_256_cbc | aes_128_gcm | aes_256_gcm | chacha20_poly1305</c></p></item>
<tag><c>hash() =</c></tag>
<item><p><c>md5 | sha | sha224 | sha256 | sha348 | sha512</c></p></item>
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index 479f68f4bb..4f1f050e4b 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -232,9 +232,7 @@ error(_, _, _) ->
#state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-hello(internal, #client_hello{client_version = ClientVersion,
- extensions = #hello_extensions{ec_point_formats = EcPointFormats,
- elliptic_curves = EllipticCurves}} = Hello,
+hello(internal, #client_hello{client_version = ClientVersion} = Hello,
State = #state{connection_states = ConnectionStates0,
port = Port, session = #session{own_certificate = Cert} = Session0,
renegotiation = {Renegotiation, _},
@@ -260,7 +258,6 @@ hello(internal, #client_hello{client_version = ClientVersion,
negotiated_version = Version,
hashsign_algorithm = HashSign,
session = Session,
- client_ecc = {EllipticCurves, EcPointFormats},
negotiated_protocol = Protocol}, ?MODULE)
end;
hello(internal, #server_hello{} = Hello,
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index e935c033c7..542dab11b8 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -46,9 +46,9 @@
erl_cipher_suite/0, openssl_cipher_suite/0,
hash/0, key_algo/0, sign_algo/0]).
--type cipher() :: null |rc4_128 | idea_cbc | des40_cbc | des_cbc | '3des_ede_cbc'
+-type cipher() :: null |rc4_128 | des_cbc | '3des_ede_cbc'
| aes_128_cbc | aes_256_cbc | aes_128_gcm | aes_256_gcm | chacha20_poly1305.
--type hash() :: null | sha | md5 | sha224 | sha256 | sha384 | sha512.
+-type hash() :: null | md5 | sha | sha224 | sha256 | sha384 | sha512.
-type sign_algo() :: rsa | dsa | ecdsa.
-type key_algo() :: null | rsa | dhe_rsa | dhe_dss | ecdhe_ecdsa| ecdh_ecdsa | ecdh_rsa| srp_rsa| srp_dss |
psk | dhe_psk | rsa_psk | dh_anon | ecdh_anon | srp_anon.
@@ -333,21 +333,27 @@ anonymous_suites({3, N}) ->
anonymous_suites(N)
when N >= 3 ->
[?TLS_DH_anon_WITH_AES_128_GCM_SHA256,
- ?TLS_DH_anon_WITH_AES_256_GCM_SHA384
- ] ++ anonymous_suites(0);
-
-anonymous_suites(_) ->
- [?TLS_DH_anon_WITH_RC4_128_MD5,
- ?TLS_DH_anon_WITH_DES_CBC_SHA,
- ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
- ?TLS_DH_anon_WITH_AES_128_CBC_SHA,
- ?TLS_DH_anon_WITH_AES_256_CBC_SHA,
+ ?TLS_DH_anon_WITH_AES_256_GCM_SHA384,
?TLS_DH_anon_WITH_AES_128_CBC_SHA256,
?TLS_DH_anon_WITH_AES_256_CBC_SHA256,
- ?TLS_ECDH_anon_WITH_RC4_128_SHA,
- ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
?TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
- ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA].
+ ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
+ ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_DH_anon_WITH_RC4_128_MD5];
+
+anonymous_suites(2) ->
+ [?TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
+ ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
+ ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_DH_anon_WITH_DES_CBC_SHA,
+ ?TLS_DH_anon_WITH_RC4_128_MD5];
+
+anonymous_suites(N) when N == 0;
+ N == 1 ->
+ [?TLS_DH_anon_WITH_RC4_128_MD5,
+ ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_DH_anon_WITH_DES_CBC_SHA
+ ].
%%--------------------------------------------------------------------
-spec psk_suites(ssl_record:ssl_version() | integer()) -> [cipher_suite()].
@@ -1458,6 +1464,9 @@ is_acceptable_cipher(Cipher, Algos)
is_acceptable_cipher(Cipher, Algos)
when Cipher == chacha20_poly1305 ->
proplists:get_bool(Cipher, Algos);
+is_acceptable_cipher(Cipher, Algos)
+ when Cipher == rc4_128 ->
+ proplists:get_bool(rc4, Algos);
is_acceptable_cipher(_, _) ->
true.
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 304d1706f5..08fca76123 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -1430,13 +1430,14 @@ key_exchange(#state{role = server, private_key = Key, key_algorithm = Algo} = St
key_exchange(#state{role = server, key_algorithm = Algo,
hashsign_algorithm = HashSignAlgo,
private_key = PrivateKey,
+ session = #session{ecc = ECCCurve},
connection_states = ConnectionStates0,
negotiated_version = Version
} = State0, Connection)
when Algo == ecdhe_ecdsa; Algo == ecdhe_rsa;
Algo == ecdh_anon ->
- ECDHKeys = public_key:generate_key(select_curve(State0)),
+ ECDHKeys = public_key:generate_key(ECCCurve),
#{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates0, read),
#security_parameters{client_random = ClientRandom,
@@ -1845,11 +1846,6 @@ cipher_role(server, Data, Session, #state{connection_states = ConnectionStates0
{Record, State} = prepare_connection(State1, Connection),
Connection:next_event(connection, Record, State).
-select_curve(#state{client_ecc = {[Curve|_], _}}) ->
- {namedCurve, Curve};
-select_curve(_) ->
- {namedCurve, ?secp256r1}.
-
is_anonymous(Algo) when Algo == dh_anon;
Algo == ecdh_anon;
Algo == psk;
diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl
index f1e612a41b..fca3e11894 100644
--- a/lib/ssl/src/ssl_connection.hrl
+++ b/lib/ssl/src/ssl_connection.hrl
@@ -48,6 +48,7 @@
socket_options :: #socket_options{},
connection_states :: ssl_record:connection_states() | secret_printout(),
protocol_buffers :: term() | secret_printout() , %% #protocol_buffers{} from tls_record.hrl or dtls_recor.hrl
+ unprocessed_handshake_events = 0 :: integer(),
tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout()
| 'undefined',
cert_db :: reference() | 'undefined',
@@ -81,7 +82,6 @@
expecting_next_protocol_negotiation = false ::boolean(),
expecting_finished = false ::boolean(),
negotiated_protocol = undefined :: undefined | binary(),
- client_ecc, % {Curves, PointFmt}
tracker :: pid() | 'undefined', %% Tracker process for listen socket
sni_hostname = undefined,
downgrade,
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 9b9031473a..932bb139c1 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -237,9 +237,7 @@ error(_, _, _) ->
#state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-hello(internal, #client_hello{client_version = ClientVersion,
- extensions = #hello_extensions{ec_point_formats = EcPointFormats,
- elliptic_curves = EllipticCurves}} = Hello,
+hello(internal, #client_hello{client_version = ClientVersion} = Hello,
#state{connection_states = ConnectionStates0,
port = Port, session = #session{own_certificate = Cert} = Session0,
renegotiation = {Renegotiation, _},
@@ -265,7 +263,6 @@ hello(internal, #client_hello{client_version = ClientVersion,
negotiated_version = Version,
hashsign_algorithm = HashSign,
session = Session,
- client_ecc = {EllipticCurves, EcPointFormats},
negotiated_protocol = Protocol})
end;
hello(internal, #server_hello{} = Hello,
@@ -421,7 +418,7 @@ handle_common_event(internal, #ssl_tls{type = ?HANDSHAKE, fragment = Data},
connection ->
ssl_connection:hibernate_after(StateName, State, Events);
_ ->
- {next_state, StateName, State, Events}
+ {next_state, StateName, State#state{unprocessed_handshake_events = unprocessed_events(Events)}, Events}
end
catch throw:#alert{} = Alert ->
ssl_connection:handle_own_alert(Alert, Version, StateName, State0)
@@ -537,7 +534,9 @@ next_tls_record(Data, #state{protocol_buffers = #protocol_buffers{tls_record_buf
#alert{} = Alert ->
Alert
end.
-
+next_record(#state{unprocessed_handshake_events = N} = State) when N > 0 ->
+ {no_record, State#state{unprocessed_handshake_events = N-1}};
+
next_record(#state{protocol_buffers =
#protocol_buffers{tls_packets = [], tls_cipher_texts = [CT | Rest]}
= Buffers,
@@ -712,3 +711,10 @@ gen_info(Event, StateName, #state{negotiated_version = Version} = State) ->
Version, StateName, State)
end.
+unprocessed_events(Events) ->
+ %% The first handshake event will be processed immediately
+ %% as it is entered first in the event queue and
+ %% when it is processed there will be length(Events)-1
+ %% handshake events left to process before we should
+ %% process more TLS-records received on the socket.
+ erlang:length(Events)-1.
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 57963fd44b..322f93b94c 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -2171,7 +2171,7 @@ anonymous_cipher_suites()->
[{doc,"Test the anonymous ciphersuites"}].
anonymous_cipher_suites(Config) when is_list(Config) ->
Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:anonymous_suites(),
+ Ciphers = ssl_test_lib:anonymous_suites(Version),
run_suites(Ciphers, Version, Config, anonymous).
%%-------------------------------------------------------------------
psk_cipher_suites() ->
@@ -2272,8 +2272,8 @@ default_reject_anonymous(Config) when is_list(Config) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
-
- [Cipher | _] = ssl_test_lib:anonymous_suites(),
+ Version = tls_record:highest_protocol_version(tls_record:supported_protocol_versions()),
+ [CipherSuite | _] = ssl_test_lib:anonymous_suites(Version),
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
@@ -2283,7 +2283,7 @@ default_reject_anonymous(Config) when is_list(Config) ->
{host, Hostname},
{from, self()},
{options,
- [{ciphers,[Cipher]} |
+ [{ciphers,[CipherSuite]} |
ClientOpts]}]),
ssl_test_lib:check_result(Server, {error, {tls_alert, "insufficient security"}},
@@ -4437,7 +4437,7 @@ run_suites(Ciphers, Version, Config, Type) ->
anonymous ->
%% No certs in opts!
{ssl_test_lib:ssl_options(client_verification_opts, Config),
- ssl_test_lib:ssl_options(server_anon, Config)};
+ [{reuseaddr, true}, {ciphers, ssl_test_lib:anonymous_suites(Version)}]};
psk ->
{ssl_test_lib:ssl_options(client_psk, Config),
ssl_test_lib:ssl_options(server_psk, Config)};
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index 81a49776e4..942e68967a 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -2011,26 +2011,19 @@ active_once_raw(Socket, Data, N) ->
active_once_raw(_, _, 0, _) ->
ok;
-active_once_raw(Socket, Data, N, Acc) ->
- receive
- {ssl, Socket, Byte} when length(Byte) == 1 ->
- ssl:setopts(Socket, [{active, once}]),
+active_once_raw(Socket, Data, N, Acc0) ->
+ case lists:prefix(Data, Acc0) of
+ true ->
+ DLen = length(Data),
+ Start = DLen + 1,
+ Len = length(Acc0) - DLen,
+ Acc = string:substr(Acc0, Start, Len),
+ active_once_raw(Socket, Data, N-1, Acc);
+ false ->
receive
- {ssl, Socket, _} ->
- ssl:setopts(Socket, [{active, once}]),
- active_once_raw(Socket, Data, N-1, [])
- end;
- {ssl, Socket, Data} ->
- ssl:setopts(Socket, [{active, once}]),
- active_once_raw(Socket, Data, N-1, []);
- {ssl, Socket, Other} ->
- case Acc ++ Other of
- Data ->
- ssl:setopts(Socket, [{active, once}]),
- active_once_raw(Socket, Data, N-1, []);
- NewAcc ->
+ {ssl, Socket, Info} ->
ssl:setopts(Socket, [{active, once}]),
- active_once_raw(Socket, Data, N, NewAcc)
+ active_once_raw(Socket, Data, N, Acc0 ++ Info)
end
end.
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 81f16030f7..cab22a60a8 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -398,7 +398,7 @@ cert_options(Config) ->
{ssl_imp, new}]},
{server_opts, [{ssl_imp, new},{reuseaddr, true}, {cacertfile, ServerCaCertFile},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
- {server_anon, [{ssl_imp, new},{reuseaddr, true}, {ciphers, anonymous_suites()}]},
+ %%{server_anon, [{ssl_imp, new},{reuseaddr, true}, {ciphers, anonymous_suites()}]},
{client_psk, [{ssl_imp, new},{reuseaddr, true},
{psk_identity, "Test-User"},
{user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}]},
@@ -908,19 +908,8 @@ string_regex_filter(Str, Search) when is_list(Str) ->
string_regex_filter(_Str, _Search) ->
false.
-anonymous_suites() ->
- Suites =
- [{dh_anon, rc4_128, md5},
- {dh_anon, des_cbc, sha},
- {dh_anon, '3des_ede_cbc', sha},
- {dh_anon, aes_128_cbc, sha},
- {dh_anon, aes_256_cbc, sha},
- {dh_anon, aes_128_gcm, null, sha256},
- {dh_anon, aes_256_gcm, null, sha384},
- {ecdh_anon,rc4_128,sha},
- {ecdh_anon,'3des_ede_cbc',sha},
- {ecdh_anon,aes_128_cbc,sha},
- {ecdh_anon,aes_256_cbc,sha}],
+anonymous_suites(Version) ->
+ Suites = ssl_cipher:anonymous_suites(Version),
ssl_cipher:filter_suites(Suites).
psk_suites() ->
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 914eb43505..59732c7926 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 8.0.2
+SSL_VSN = 8.0.3