aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/doc/src/notes.xml15
-rw-r--r--lib/ssl/doc/src/ssl.xml5
-rw-r--r--lib/ssl/src/ssl.erl2
-rw-r--r--lib/ssl/src/ssl_cipher.erl11
-rw-r--r--lib/ssl/src/ssl_connection.erl4
-rw-r--r--lib/ssl/src/ssl_handshake.erl9
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl31
-rw-r--r--lib/ssl/test/ssl_engine_SUITE.erl39
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl122
9 files changed, 210 insertions, 28 deletions
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 79176f5edf..bdf8711b2f 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -307,6 +307,21 @@
</section>
</section>
+<section><title>SSL 8.1.3.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix alert handling so that unexpected messages are logged
+ and alerted correctly</p>
+ <p>
+ Own Id: OTP-14929</p>
+ </item>
+ </list>
+ </section>
+</section>
+
<section><title>SSL 8.1.3.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index 4f72114ae9..7267083e32 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -264,8 +264,9 @@
<item><p>Specifies if to reject renegotiation attempt that does
not live up to
<url href="http://www.ietf.org/rfc/rfc5746.txt">RFC 5746</url>.
- By default <c>secure_renegotiate</c> is set to <c>false</c>,
- that is, secure renegotiation is used if possible,
+ By default <c>secure_renegotiate</c> is set to <c>true</c>,
+ that is, secure renegotiation is enforced. If set to <c>false</c> secure renegotiation
+ will still be used if possible,
but it falls back to insecure renegotiation if the peer
does not support
<url href="http://www.ietf.org/rfc/rfc5746.txt">RFC 5746</url>.</p>
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 0b035d31be..82f62b51b9 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -843,7 +843,7 @@ handle_options(Opts0, Role, Host) ->
%% Server side option
reuse_session = handle_option(reuse_session, Opts, ReuseSessionFun),
reuse_sessions = handle_option(reuse_sessions, Opts, true),
- secure_renegotiate = handle_option(secure_renegotiate, Opts, false),
+ secure_renegotiate = handle_option(secure_renegotiate, Opts, true),
client_renegotiation = handle_option(client_renegotiation, Opts,
default_option_role(server, true, Role),
server, Role),
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 1d645e5782..a83ce42455 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -96,7 +96,7 @@ security_parameters(Version, CipherSuite, SecParams) ->
expanded_key_material_length = expanded_key_material(Cipher),
key_material_length = key_material(Cipher),
iv_size = iv_size(Cipher),
- mac_algorithm = hash_algorithm(Hash),
+ mac_algorithm = mac_algorithm(Hash),
prf_algorithm = prf_algorithm(PrfHashAlg, Version),
hash_size = hash_size(Hash)}.
@@ -2531,6 +2531,11 @@ prf_algorithm(default_prf, {3, _}) ->
prf_algorithm(Algo, _) ->
hash_algorithm(Algo).
+mac_algorithm(aead) ->
+ aead;
+mac_algorithm(Algo) ->
+ hash_algorithm(Algo).
+
hash_algorithm(null) -> ?NULL;
hash_algorithm(md5) -> ?MD5;
hash_algorithm(sha) -> ?SHA; %% Only sha always refers to "SHA-1"
@@ -2561,6 +2566,10 @@ sign_algorithm(Other) when is_integer(Other) andalso ((Other >= 224) and (Other
hash_size(null) ->
0;
+%% The AEAD MAC hash size is not used in the context
+%% of calculating the master secret. See RFC 5246 Section 6.2.3.3.
+hash_size(aead) ->
+ 0;
hash_size(md5) ->
16;
hash_size(sha) ->
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index d046145dff..2031735a71 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -1148,8 +1148,8 @@ handle_common_event(internal, #change_cipher_spec{type = <<1>>}, StateName,
StateName, State);
handle_common_event(_Type, Msg, StateName, #state{negotiated_version = Version} = State,
_) ->
- Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE),
- handle_own_alert(Alert, Version, {StateName, Msg}, State).
+ Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, {unexpected_msg, Msg}),
+ handle_own_alert(Alert, Version, StateName, State).
handle_call({application_data, _Data}, _, _, _, _) ->
%% In renegotiation priorities handshake, send data when handshake is finished
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 0c55af9174..09160e2f9c 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -774,9 +774,8 @@ decode_suites('3_bytes', Dec) ->
%%====================================================================
available_suites(UserSuites, Version) ->
- lists:filtermap(fun(Suite) ->
- lists:member(Suite, ssl_cipher:all_suites(Version))
- end, UserSuites).
+ VersionSuites = ssl_cipher:all_suites(Version) ++ ssl_cipher:anonymous_suites(Version),
+ lists:filtermap(fun(Suite) -> lists:member(Suite, VersionSuites) end, UserSuites).
available_suites(ServerCert, UserSuites, Version, undefined, Curve) ->
ssl_cipher:filter(ServerCert, available_suites(UserSuites, Version))
@@ -1056,7 +1055,9 @@ select_curve(undefined, _, _) ->
%%
%% Description: Handles signature_algorithms hello extension (server)
%%--------------------------------------------------------------------
-select_hashsign(_, undefined, _, _, _Version) ->
+select_hashsign(_, _, KeyExAlgo, _, _Version) when KeyExAlgo == dh_anon;
+ KeyExAlgo == ecdh_anon;
+ KeyExAlgo == srp_anon ->
{null, anon};
%% The signature_algorithms extension was introduced with TLS 1.2. Ignore it if we have
%% negotiated a lower version.
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 2781203557..05979d3cfd 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -194,6 +194,7 @@ renegotiate_tests() ->
[client_renegotiate,
server_renegotiate,
client_secure_renegotiate,
+ client_secure_renegotiate_fallback,
client_renegotiate_reused_session,
server_renegotiate_reused_session,
client_no_wrap_sequence_number,
@@ -2898,6 +2899,36 @@ client_secure_renegotiate(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+%%--------------------------------------------------------------------
+client_secure_renegotiate_fallback() ->
+ [{doc,"Test that we can set secure_renegotiate to false that is "
+ "fallback option, we however do not have a insecure server to test against!"}].
+client_secure_renegotiate_fallback(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From erlang to erlang",
+
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
+ {options, [{secure_renegotiate, false} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ renegotiate, [Data]}},
+ {options, [{reuse_sessions, false},
+ {secure_renegotiate, false}| ClientOpts]}]),
+
+ ssl_test_lib:check_result(Client, ok, Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
server_renegotiate() ->
diff --git a/lib/ssl/test/ssl_engine_SUITE.erl b/lib/ssl/test/ssl_engine_SUITE.erl
index bc221d35fd..71891356e8 100644
--- a/lib/ssl/test/ssl_engine_SUITE.erl
+++ b/lib/ssl/test/ssl_engine_SUITE.erl
@@ -39,23 +39,28 @@ init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- ssl_test_lib:clean_start(),
- case crypto:get_test_engine() of
- {ok, EngineName} ->
- try crypto:engine_load(<<"dynamic">>,
- [{<<"SO_PATH">>, EngineName},
- <<"LOAD">>],
- []) of
- {ok, Engine} ->
- [{engine, Engine} |Config];
- {error, Reason} ->
- ct:pal("Reason ~p", [Reason]),
- {skip, "No dynamic engine support"}
- catch error:notsup ->
- {skip, "No engine support in OpenSSL"}
- end;
- {error, notexist} ->
- {skip, "Test engine not found"}
+ case crypto:info_lib() of
+ [{_,_, <<"OpenSSL 1.0.1s-freebsd 1 Mar 2016">>}] ->
+ {skip, "Problem with engine on OpenSSL 1.0.1s-freebsd"};
+ _ ->
+ ssl_test_lib:clean_start(),
+ case crypto:get_test_engine() of
+ {ok, EngineName} ->
+ try crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, EngineName},
+ <<"LOAD">>],
+ []) of
+ {ok, Engine} ->
+ [{engine, Engine} |Config];
+ {error, Reason} ->
+ ct:pal("Reason ~p", [Reason]),
+ {skip, "No dynamic engine support"}
+ catch error:notsup ->
+ {skip, "No engine support in OpenSSL"}
+ end;
+ {error, notexist} ->
+ {skip, "Test engine not found"}
+ end
end
catch _:_ ->
{skip, "Crypto did not start"}
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index f091c8786e..dcdea6beb5 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -70,6 +70,9 @@ all_versions_tests() ->
erlang_server_openssl_client,
erlang_client_openssl_server_dsa_cert,
erlang_server_openssl_client_dsa_cert,
+ erlang_client_openssl_server_anon,
+ erlang_server_openssl_client_anon,
+ erlang_server_openssl_client_anon_with_cert,
erlang_server_openssl_client_reuse_session,
erlang_client_openssl_server_renegotiate,
erlang_client_openssl_server_nowrap_seqnum,
@@ -89,6 +92,9 @@ dtls_all_versions_tests() ->
erlang_server_openssl_client,
erlang_client_openssl_server_dsa_cert,
erlang_server_openssl_client_dsa_cert,
+ erlang_client_openssl_server_anon,
+ erlang_server_openssl_client_anon,
+ erlang_server_openssl_client_anon_with_cert,
erlang_server_openssl_client_reuse_session,
erlang_client_openssl_server_renegotiate,
erlang_client_openssl_server_nowrap_seqnum,
@@ -550,7 +556,121 @@ erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
ssl_test_lib:close_port(OpenSslPort),
process_flag(trap_exit, false).
-%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------
+erlang_client_openssl_server_anon() ->
+ [{doc,"Test erlang client with openssl server, anonymous"}].
+erlang_client_openssl_server_anon(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ %% OpenSSL expects a certificate and key, even if the cipher spec
+ %% is restructed to aNULL, so we use 'server_rsa_opts' here
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_anon_opts, Config),
+ VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:anonymous_suites(VersionTuple),
+
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ Port = ssl_test_lib:inet_port(node()),
+ CertFile = proplists:get_value(certfile, ServerOpts),
+ KeyFile = proplists:get_value(keyfile, ServerOpts),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cert", CertFile, "-key", KeyFile,
+ "-cipher", "aNULL", "-msg"],
+
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ erlang_ssl_receive, [Data]}},
+ {options, [{ciphers, Ciphers} | ClientOpts]}]),
+
+ true = port_command(OpensslPort, Data),
+
+ ssl_test_lib:check_result(Client, ok),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close_port(OpensslPort),
+ ssl_test_lib:close(Client),
+ process_flag(trap_exit, false),
+ ok.
+%%--------------------------------------------------------------------
+erlang_server_openssl_client_anon() ->
+ [{doc,"Test erlang server with openssl client, anonymous"}].
+erlang_server_openssl_client_anon(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ServerOpts = ssl_test_lib:ssl_options(server_anon_opts, Config),
+ VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:anonymous_suites(VersionTuple),
+
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
+ {options, [{ciphers, Ciphers} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cipher", "aNULL", "-msg"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ true = port_command(OpenSslPort, Data),
+
+ ssl_test_lib:check_result(Server, ok),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close_port(OpenSslPort),
+ process_flag(trap_exit, false).
+
+ %%--------------------------------------------------------------------
+ erlang_server_openssl_client_anon_with_cert() ->
+ [{doc,"Test erlang server with openssl client, anonymous (with cert)"}].
+ erlang_server_openssl_client_anon_with_cert(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:anonymous_suites(VersionTuple),
+
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
+ {options, [{ciphers, Ciphers} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cipher", "aNULL", "-msg"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ true = port_command(OpenSslPort, Data),
+
+ ssl_test_lib:check_result(Server, ok),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close_port(OpenSslPort),
+ process_flag(trap_exit, false).
+
+%%--------------------------------------------------------------------
erlang_server_openssl_client_reuse_session() ->
[{doc, "Test erlang server with openssl client that reconnects with the"