diff options
Diffstat (limited to 'lib/ssl/test/ssl_basic_SUITE.erl')
-rw-r--r-- | lib/ssl/test/ssl_basic_SUITE.erl | 477 |
1 files changed, 364 insertions, 113 deletions
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index ce62017a7e..013786d863 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2017. All Rights Reserved. +%% Copyright Ericsson AB 2007-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -108,7 +108,8 @@ basic_tests() -> clear_pem_cache, defaults, fallback, - cipher_format + cipher_format, + suite_to_str ]. basic_tests_tls() -> @@ -146,8 +147,7 @@ options_tests_tls() -> tls_tcp_reuseaddr]. api_tests() -> - [connection_info, - secret_connection_info, + [secret_connection_info, connection_information, peercert, peercert_with_client_cert, @@ -164,7 +164,10 @@ api_tests() -> accept_pool, prf, socket_options, - cipher_suites + cipher_suites, + handshake_continue, + hello_client_cancel, + hello_server_cancel ]. api_tests_tls() -> @@ -194,6 +197,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, @@ -214,6 +218,8 @@ cipher_tests() -> ciphers_rsa_signed_certs_openssl_names, ciphers_dsa_signed_certs, ciphers_dsa_signed_certs_openssl_names, + chacha_rsa_cipher_suites, + chacha_ecdsa_cipher_suites, anonymous_cipher_suites, psk_cipher_suites, psk_with_hint_cipher_suites, @@ -236,7 +242,9 @@ error_handling_tests()-> [close_transport_accept, recv_active, recv_active_once, - recv_error_handling + recv_error_handling, + call_in_error_state, + close_in_error_state ]. error_handling_tests_tls()-> @@ -267,7 +275,8 @@ init_per_suite(Config0) -> proplists:get_value(priv_dir, Config0)), Config1 = ssl_test_lib:make_dsa_cert(Config0), Config2 = ssl_test_lib:make_ecdsa_cert(Config1), - Config = ssl_test_lib:make_ecdh_rsa_cert(Config2), + Config3 = ssl_test_lib:make_rsa_cert(Config2), + Config = ssl_test_lib:make_ecdh_rsa_cert(Config3), ssl_test_lib:cert_options(Config) catch _:_ -> {skip, "Crypto did not start"} @@ -288,6 +297,7 @@ init_per_group(GroupName, Config) when GroupName == basic_tls; -> ssl_test_lib:clean_tls_version(Config); init_per_group(GroupName, Config) -> + ssl_test_lib:clean_tls_version(Config), case ssl_test_lib:is_tls_version(GroupName) andalso ssl_test_lib:sufficient_crypto_support(GroupName) of true -> ssl_test_lib:init_tls_version(GroupName, Config); @@ -467,6 +477,8 @@ init_per_testcase(TestCase, Config) when TestCase == tls_ssl_accept_timeout; TestCase == tls_client_closes_socket; TestCase == tls_closed_in_active_once; TestCase == tls_downgrade -> + ssl:stop(), + ssl:start(), ssl_test_lib:ct_log_supported_protocol_versions(Config), ct:timetrap({seconds, 15}), Config; @@ -601,7 +613,16 @@ new_options_in_accept(Config) when is_list(Config) -> [_ , _ | ServerSslOpts] = ssl_test_lib:ssl_options(server_opts, Config), %% Remove non ssl opts {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), Version = ssl_test_lib:protocol_options(Config, [{tls, sslv3}, {dtls, dtlsv1}]), - Cipher = ssl_test_lib:protocol_options(Config, [{tls, {rsa,rc4_128,sha}}, {dtls, {rsa,aes_128_cbc,sha}}]), + Cipher = ssl_test_lib:protocol_options(Config, [{tls, #{key_exchange =>rsa, + cipher => rc4_128, + mac => sha, + prf => default_prf + }}, + {dtls, #{key_exchange =>rsa, + cipher => aes_128_cbc, + mac => sha, + prf => default_prf + }}]), Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, {ssl_extra_opts, [{versions, [Version]}, @@ -626,6 +647,89 @@ new_options_in_accept(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +handshake_continue() -> + [{doc, "Test API function ssl:handshake_continue/3"}]. +handshake_continue(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, ssl_test_lib:ssl_options([{reuseaddr, true}, {handshake, hello}], + Config)}, + {continue_options, proplists:delete(reuseaddr, ServerOpts)} + ]), + + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, ssl_test_lib:ssl_options([{handshake, hello}], + Config)}, + {continue_options, proplists:delete(reuseaddr, ClientOpts)}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +hello_client_cancel() -> + [{doc, "Test API function ssl:handshake_cancel/1 on the client side"}]. +hello_client_cancel(Config) when is_list(Config) -> + ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {options, ssl_test_lib:ssl_options([{handshake, hello}], Config)}, + {continue_options, proplists:delete(reuseaddr, ServerOpts)}]), + + Port = ssl_test_lib:inet_port(Server), + + %% That is ssl:handshake_cancel returns ok + {connect_failed, ok} = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {options, ssl_test_lib:ssl_options([{handshake, hello}], Config)}, + {continue_options, cancel}]), + receive + {Server, {error, {tls_alert, "user canceled"}}} -> + ok; + {Server, {error, closed}} -> + ct:pal("Did not receive the ALERT"), + ok + end. + +%%-------------------------------------------------------------------- +hello_server_cancel() -> + [{doc, "Test API function ssl:handshake_cancel/1 on the server side"}]. +hello_server_cancel(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {options, ssl_test_lib:ssl_options([{handshake, hello}], Config)}, + {continue_options, cancel}]), + + Port = ssl_test_lib:inet_port(Server), + + {connect_failed, _} = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {options, ssl_test_lib:ssl_options([{handshake, hello}], Config)}, + {continue_options, proplists:delete(reuseaddr, ClientOpts)}]), + + ssl_test_lib:check_result(Server, ok). + %%-------------------------------------------------------------------- prf() -> [{doc,"Test that ssl:prf/5 uses the negotiated PRF."}]. @@ -647,41 +751,6 @@ prf(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -connection_info() -> - [{doc,"Test the API function ssl:connection_information/2"}]. -connection_info(Config) when is_list(Config) -> - ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config), - ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, connection_info_result, []}}, - {options, ServerOpts}]), - - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, connection_info_result, []}}, - {options, - [{ciphers,[{rsa, aes_128_cbc, sha}]} | - ClientOpts]}]), - - ct:log("Testcase ~p, Client ~p Server ~p ~n", - [self(), Client, Server]), - - Version = ssl_test_lib:protocol_version(Config), - - ServerMsg = ClientMsg = {ok, {Version, {rsa, aes_128_cbc, sha}}}, - - ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- - secret_connection_info() -> [{doc,"Test the API function ssl:connection_information/2"}]. secret_connection_info(Config) when is_list(Config) -> @@ -959,7 +1028,7 @@ controller_dies(Config) when is_list(Config) -> {mfa, {?MODULE, controller_dies_result, [self(), ClientMsg]}}, - {options, [{reuseaddr,true}|ClientOpts]}]), + {options, ClientOpts}]), ct:sleep(?SLEEP), %% so that they are connected exit(Server, killed), @@ -984,7 +1053,7 @@ tls_client_closes_socket(Config) when is_list(Config) -> Connect = fun() -> {ok, _Socket} = rpc:call(ClientNode, gen_tcp, connect, - [Hostname, Port, TcpOpts]), + [Hostname, Port, [binary]]), %% Make sure that ssl_accept is called before %% client process ends and closes socket. ct:sleep(?SLEEP) @@ -1136,7 +1205,27 @@ cipher_format(Config) when is_list(Config) -> ssl:close(Socket1), {ok, Socket2} = ssl:listen(0, [{ciphers, ssl:cipher_suites(openssl)}]), ssl:close(Socket2). - + +%%-------------------------------------------------------------------- +suite_to_str() -> + [{doc, "Test that the suite_to_str API works"}]. +suite_to_str(Config) when is_list(Config) -> + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" = + ssl:suite_to_str(#{key_exchange => null, + cipher => null, + mac => null, + prf => null}), + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" = + ssl:suite_to_str(#{key_exchange => ecdhe_ecdsa, + cipher => aes_128_gcm, + mac => aead, + prf => sha256}), + "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256" = + ssl:suite_to_str(#{key_exchange => ecdh_rsa, + cipher => aes_128_cbc, + mac => sha256, + prf => sha256}). + %%-------------------------------------------------------------------- peername() -> @@ -1293,6 +1382,14 @@ cipher_suites() -> " and prepend|append_cipher_suites/2"}]. cipher_suites(Config) when is_list(Config) -> + MandatoryCipherSuiteTLS1_0TLS1_1 = #{key_exchange => rsa, + cipher => '3des_ede_cbc', + mac => sha, + prf => default_prf}, + MandatoryCipherSuiteTLS1_0TLS1_2 = #{key_exchange =>rsa, + cipher => 'aes_128_cbc', + mac => sha, + prf => default_prf}, Version = ssl_test_lib:protocol_version(Config), All = [_|_] = ssl:cipher_suites(all, Version), Default = [_|_] = ssl:cipher_suites(default, Version), @@ -1334,8 +1431,9 @@ cipher_suites(Config) when is_list(Config) -> true = lists:member(Cipher, Default), false = lists:member(Cipher, Rest1), [] = lists:dropwhile(fun(X) -> not lists:member(X, Default) end, Anonymous), - [] = lists:dropwhile(fun(X) -> not lists:member(X, All) end, Anonymous). - + [] = lists:dropwhile(fun(X) -> not lists:member(X, All) end, Anonymous), + true = lists:member(MandatoryCipherSuiteTLS1_0TLS1_1, All), + true = lists:member(MandatoryCipherSuiteTLS1_0TLS1_2, All). %%-------------------------------------------------------------------- @@ -1343,18 +1441,18 @@ old_cipher_suites() -> [{doc,"Test API function cipher_suites/0"}]. old_cipher_suites(Config) when is_list(Config) -> - MandatoryCipherSuite = {rsa,'3des_ede_cbc',sha}, + MandatoryCipherSuite = {rsa, '3des_ede_cbc', sha}, [_|_] = Suites = ssl:cipher_suites(), - true = lists:member(MandatoryCipherSuite, Suites), Suites = ssl:cipher_suites(erlang), - [_|_] =ssl:cipher_suites(openssl). + [_|_] = ssl:cipher_suites(openssl), + true = lists:member(MandatoryCipherSuite, ssl:cipher_suites(all)). %%-------------------------------------------------------------------- cipher_suites_mix() -> [{doc,"Test to have old and new cipher suites at the same time"}]. cipher_suites_mix(Config) when is_list(Config) -> - CipherSuites = [{ecdh_rsa,aes_128_cbc,sha256,sha256}, {rsa,aes_128_cbc,sha}], + CipherSuites = [{dhe_rsa,aes_128_cbc,sha256,sha256}, {dhe_rsa,aes_128_cbc,sha}], ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config), ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config), @@ -1799,7 +1897,7 @@ tls_send_close(Config) when is_list(Config) -> {options, [{active, false} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), {ok, TcpS} = rpc:call(ClientNode, gen_tcp, connect, - [Hostname,Port,[binary, {active, false}, {reuseaddr, true}]]), + [Hostname,Port,[binary, {active, false}]]), {ok, SslS} = rpc:call(ClientNode, ssl, connect, [TcpS,[{active, false}|ClientOpts]]), @@ -1943,7 +2041,7 @@ tls_upgrade(Config) when is_list(Config) -> {host, Hostname}, {from, self()}, {mfa, {?MODULE, upgrade_result, []}}, - {tcp_options, TcpOpts}, + {tcp_options, [binary]}, {ssl_options, ClientOpts}]), ct:log("Testcase ~p, Client ~p Server ~p ~n", @@ -2422,12 +2520,29 @@ ciphers_dsa_signed_certs_openssl_names() -> ciphers_dsa_signed_certs_openssl_names(Config) when is_list(Config) -> Ciphers = ssl_test_lib:openssl_dsa_suites(), run_suites(Ciphers, Config, dsa). + %%------------------------------------------------------------------- +chacha_rsa_cipher_suites()-> + [{doc,"Test the cacha with ECDSA signed certs ciphersuites"}]. +chacha_rsa_cipher_suites(Config) when is_list(Config) -> + NVersion = ssl_test_lib:protocol_version(Config, tuple), + Ciphers = [S || {KeyEx,_,_} = S <- ssl_test_lib:chacha_suites(NVersion), + KeyEx == ecdhe_rsa, KeyEx == dhe_rsa], + run_suites(Ciphers, Config, chacha_ecdsa). + +%%------------------------------------------------------------------- +chacha_ecdsa_cipher_suites()-> + [{doc,"Test the cacha with ECDSA signed certs ciphersuites"}]. +chacha_ecdsa_cipher_suites(Config) when is_list(Config) -> + NVersion = ssl_test_lib:protocol_version(Config, tuple), + Ciphers = [S || {ecdhe_ecdsa,_,_} = S <- ssl_test_lib:chacha_suites(NVersion)], + run_suites(Ciphers, Config, chacha_rsa). +%%----------------------------------------------------------------- anonymous_cipher_suites()-> [{doc,"Test the anonymous ciphersuites"}]. anonymous_cipher_suites(Config) when is_list(Config) -> NVersion = ssl_test_lib:protocol_version(Config, tuple), - Ciphers = ssl_test_lib:anonymous_suites(NVersion), + Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(NVersion), run_suites(Ciphers, Config, anonymous). %%------------------------------------------------------------------- psk_cipher_suites() -> @@ -2502,14 +2617,15 @@ rc4_ecdsa_cipher_suites(Config) when is_list(Config) -> des_rsa_cipher_suites()-> [{doc, "Test the des_rsa ciphersuites"}]. des_rsa_cipher_suites(Config) when is_list(Config) -> - Ciphers = ssl_test_lib:des_suites(Config), + NVersion = tls_record:highest_protocol_version([]), + Ciphers = [S || {rsa,_,_} = S <- ssl_test_lib:des_suites(NVersion)], run_suites(Ciphers, Config, des_rsa). %------------------------------------------------------------------- des_ecdh_rsa_cipher_suites()-> [{doc, "Test ECDH rsa signed ciphersuites"}]. des_ecdh_rsa_cipher_suites(Config) when is_list(Config) -> NVersion = ssl_test_lib:protocol_version(Config, tuple), - Ciphers = ssl_test_lib:des_suites(NVersion), + Ciphers = [S || {dhe_rsa,_,_} = S <- ssl_test_lib:des_suites(NVersion)], run_suites(Ciphers, Config, des_dhe_rsa). %%-------------------------------------------------------------------- @@ -2522,7 +2638,7 @@ default_reject_anonymous(Config) when is_list(Config) -> Version = ssl_test_lib:protocol_version(Config), TLSVersion = ssl_test_lib:tls_version(Version), - [CipherSuite | _] = ssl_test_lib:anonymous_suites(TLSVersion), + [CipherSuite | _] = ssl_test_lib:ecdh_dh_anonymous_suites(TLSVersion), Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, {from, self()}, @@ -2869,6 +2985,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() -> @@ -3038,10 +3184,10 @@ der_input(Config) when is_list(Config) -> Size = ets:info(CADb, size), - SeverVerifyOpts = ssl_test_lib:ssl_options(server_opts, Config), + SeverVerifyOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config), {ServerCert, ServerKey, ServerCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} | SeverVerifyOpts]), - ClientVerifyOpts = ssl_test_lib:ssl_options(client_opts, Config), + ClientVerifyOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config), {ClientCert, ClientKey, ClientCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} | ClientVerifyOpts]), ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}, @@ -3202,18 +3348,25 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) -> %%-------------------------------------------------------------------- defaults(Config) when is_list(Config)-> - [_, - {supported, Supported}, - {available, Available}] - = ssl:versions(), - true = lists:member(sslv3, Available), - false = lists:member(sslv3, Supported), + Versions = ssl:versions(), + true = lists:member(sslv3, proplists:get_value(available, Versions)), + false = lists:member(sslv3, proplists:get_value(supported, Versions)), + true = lists:member('tlsv1', proplists:get_value(available, Versions)), + true = lists:member('tlsv1', proplists:get_value(supported, Versions)), + true = lists:member('tlsv1.1', proplists:get_value(available, Versions)), + true = lists:member('tlsv1.1', proplists:get_value(supported, Versions)), + true = lists:member('tlsv1.2', proplists:get_value(available, Versions)), + true = lists:member('tlsv1.2', proplists:get_value(supported, Versions)), false = lists:member({rsa,rc4_128,sha}, ssl:cipher_suites()), true = lists:member({rsa,rc4_128,sha}, ssl:cipher_suites(all)), false = lists:member({rsa,des_cbc,sha}, ssl:cipher_suites()), true = lists:member({rsa,des_cbc,sha}, ssl:cipher_suites(all)), false = lists:member({dhe_rsa,des_cbc,sha}, ssl:cipher_suites()), - true = lists:member({dhe_rsa,des_cbc,sha}, ssl:cipher_suites(all)). + true = lists:member({dhe_rsa,des_cbc,sha}, ssl:cipher_suites(all)), + true = lists:member('dtlsv1.2', proplists:get_value(available_dtls, Versions)), + true = lists:member('dtlsv1', proplists:get_value(available_dtls, Versions)), + true = lists:member('dtlsv1.2', proplists:get_value(supported_dtls, Versions)), + true = lists:member('dtlsv1', proplists:get_value(supported_dtls, Versions)). %%-------------------------------------------------------------------- reuseaddr() -> @@ -3299,16 +3452,50 @@ tls_tcp_reuseaddr(Config) when is_list(Config) -> honor_server_cipher_order() -> [{doc,"Test API honor server cipher order."}]. honor_server_cipher_order(Config) when is_list(Config) -> - ClientCiphers = [{rsa, aes_128_cbc, sha}, {rsa, aes_256_cbc, sha}], - ServerCiphers = [{rsa, aes_256_cbc, sha}, {rsa, aes_128_cbc, sha}], -honor_cipher_order(Config, true, ServerCiphers, ClientCiphers, {rsa, aes_256_cbc, sha}). + ClientCiphers = [#{key_exchange => dhe_rsa, + cipher => aes_128_cbc, + mac => sha, + prf => default_prf}, + #{key_exchange => dhe_rsa, + cipher => aes_256_cbc, + mac => sha, + prf => default_prf}], + ServerCiphers = [#{key_exchange => dhe_rsa, + cipher => aes_256_cbc, + mac =>sha, + prf => default_prf}, + #{key_exchange => dhe_rsa, + cipher => aes_128_cbc, + mac => sha, + prf => default_prf}], + honor_cipher_order(Config, true, ServerCiphers, ClientCiphers, #{key_exchange => dhe_rsa, + cipher => aes_256_cbc, + mac => sha, + prf => default_prf}). honor_client_cipher_order() -> [{doc,"Test API honor server cipher order."}]. honor_client_cipher_order(Config) when is_list(Config) -> - ClientCiphers = [{rsa, aes_128_cbc, sha}, {rsa, aes_256_cbc, sha}], - ServerCiphers = [{rsa, aes_256_cbc, sha}, {rsa, aes_128_cbc, sha}], -honor_cipher_order(Config, false, ServerCiphers, ClientCiphers, {rsa, aes_128_cbc, sha}). + ClientCiphers = [#{key_exchange => dhe_rsa, + cipher => aes_128_cbc, + mac => sha, + prf => default_prf}, + #{key_exchange => dhe_rsa, + cipher => aes_256_cbc, + mac => sha, + prf => default_prf}], + ServerCiphers = [#{key_exchange => dhe_rsa, + cipher => aes_256_cbc, + mac =>sha, + prf => default_prf}, + #{key_exchange => dhe_rsa, + cipher => aes_128_cbc, + mac => sha, + prf => default_prf}], +honor_cipher_order(Config, false, ServerCiphers, ClientCiphers, #{key_exchange => dhe_rsa, + cipher => aes_128_cbc, + mac => sha, + prf => default_prf}). honor_cipher_order(Config, Honor, ServerCiphers, ClientCiphers, Expected) -> ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), @@ -3364,7 +3551,7 @@ tls_ciphersuite_vs_version(Config) when is_list(Config) -> >>), {ok, <<22, RecMajor:8, RecMinor:8, _RecLen:16, 2, HelloLen:24>>} = gen_tcp:recv(Socket, 9, 10000), {ok, <<HelloBin:HelloLen/binary>>} = gen_tcp:recv(Socket, HelloLen, 5000), - ServerHello = tls_handshake:decode_handshake({RecMajor, RecMinor}, 2, HelloBin, false), + ServerHello = tls_handshake:decode_handshake({RecMajor, RecMinor}, 2, HelloBin), case ServerHello of #server_hello{server_version = {3,0}, cipher_suite = <<0,57>>} -> ok; @@ -3817,6 +4004,64 @@ recv_error_handling(Config) when is_list(Config) -> ssl:close(SslSocket), ssl_test_lib:check_result(Server, ok). + + +%%-------------------------------------------------------------------- +call_in_error_state() -> + [{doc,"Special case of call error handling"}]. +call_in_error_state(Config) when is_list(Config) -> + ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config), + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = [{cacertfile, "foo.pem"} | proplists:delete(cacertfile, ServerOpts0)], + Pid = spawn_link(?MODULE, run_error_server, [[self() | ServerOpts]]), + receive + {Pid, Port} -> + spawn_link(?MODULE, run_client_error, [[Port, ClientOpts]]) + end, + receive + {error, closed} -> + ok; + Other -> + ct:fail(Other) + end. + +run_client_error([Port, Opts]) -> + ssl:connect("localhost", Port, Opts). + +run_error_server([ Pid | Opts]) -> + {ok, Listen} = ssl:listen(0, Opts), + {ok,{_, Port}} = ssl:sockname(Listen), + Pid ! {self(), Port}, + {ok, Socket} = ssl:transport_accept(Listen), + Pid ! ssl:controlling_process(Socket, self()). + +%%-------------------------------------------------------------------- + +close_in_error_state() -> + [{doc,"Special case of closing socket in error state"}]. +close_in_error_state(Config) when is_list(Config) -> + ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config), + ServerOpts = [{cacertfile, "foo.pem"} | proplists:delete(cacertfile, ServerOpts0)], + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + _ = spawn_link(?MODULE, run_error_server_close, [[self() | ServerOpts]]), + receive + {_Pid, Port} -> + spawn_link(?MODULE, run_client_error, [[Port, ClientOpts]]) + end, + receive + ok -> + ok; + Other -> + ct:fail(Other) + end. + +run_error_server_close([Pid | Opts]) -> + {ok, Listen} = ssl:listen(0, Opts), + {ok,{_, Port}} = ssl:sockname(Listen), + Pid ! {self(), Port}, + {ok, Socket} = ssl:transport_accept(Listen), + Pid ! ssl:close(Socket). + %%-------------------------------------------------------------------- rizzo() -> @@ -4036,17 +4281,17 @@ unordered_protocol_versions_server(Config) when is_list(Config) -> {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, connection_info_result, []}}, + {mfa, {?MODULE, protocol_info_result, []}}, {options, [{versions, ['tlsv1.1', 'tlsv1.2']} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, connection_info_result, []}}, + {mfa, {?MODULE, protocol_info_result, []}}, {options, ClientOpts}]), - CipherSuite = first_rsa_suite(ssl:cipher_suites()), - ServerMsg = ClientMsg = {ok, {'tlsv1.2', CipherSuite}}, + + ServerMsg = ClientMsg = {ok,'tlsv1.2'}, ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg). %%-------------------------------------------------------------------- @@ -4061,18 +4306,17 @@ unordered_protocol_versions_client(Config) when is_list(Config) -> {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, connection_info_result, []}}, + {mfa, {?MODULE, protocol_info_result, []}}, {options, ServerOpts }]), Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, connection_info_result, []}}, + {mfa, {?MODULE, protocol_info_result, []}}, {options, [{versions, ['tlsv1.1', 'tlsv1.2']} | ClientOpts]}]), - - CipherSuite = first_rsa_suite(ssl:cipher_suites()), - ServerMsg = ClientMsg = {ok, {'tlsv1.2', CipherSuite}}, + + ServerMsg = ClientMsg = {ok, 'tlsv1.2'}, ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg). %%-------------------------------------------------------------------- @@ -4709,38 +4953,39 @@ client_server_opts(#{key_exchange := KeyAlgo}, Config) when KeyAlgo == ecdh_rsa ssl_test_lib:ssl_options(server_ecdh_rsa_opts, Config)}. run_suites(Ciphers, Config, Type) -> - NVersion = ssl_test_lib:protocol_version(Config, tuple), Version = ssl_test_lib:protocol_version(Config), ct:log("Running cipher suites ~p~n", [Ciphers]), {ClientOpts, ServerOpts} = case Type of rsa -> {ssl_test_lib:ssl_options(client_verification_opts, Config), - ssl_test_lib:ssl_options(server_verification_opts, Config)}; + [{ciphers, Ciphers} | + ssl_test_lib:ssl_options(server_verification_opts, Config)]}; dsa -> {ssl_test_lib:ssl_options(client_verification_opts, Config), - ssl_test_lib:ssl_options(server_dsa_opts, Config)}; + [{ciphers, Ciphers} | + ssl_test_lib:ssl_options(server_dsa_opts, Config)]}; anonymous -> %% No certs in opts! {ssl_test_lib:ssl_options(client_verification_opts, Config), - [{reuseaddr, true}, {ciphers, ssl_test_lib:anonymous_suites(NVersion)} | + [{ciphers, Ciphers} | ssl_test_lib:ssl_options([], Config)]}; psk -> {ssl_test_lib:ssl_options(client_psk, Config), - [{ciphers, ssl_test_lib:psk_suites(NVersion)} | + [{ciphers, Ciphers} | ssl_test_lib:ssl_options(server_psk, Config)]}; psk_with_hint -> {ssl_test_lib:ssl_options(client_psk, Config), - [{ciphers, ssl_test_lib:psk_suites(NVersion)} | + [{ciphers, Ciphers} | ssl_test_lib:ssl_options(server_psk_hint, Config) ]}; psk_anon -> {ssl_test_lib:ssl_options(client_psk, Config), - [{ciphers, ssl_test_lib:psk_anon_suites(NVersion)} | + [{ciphers, Ciphers} | ssl_test_lib:ssl_options(server_psk_anon, Config)]}; psk_anon_with_hint -> {ssl_test_lib:ssl_options(client_psk, Config), - [{ciphers, ssl_test_lib:psk_anon_suites(NVersion)} | + [{ciphers, Ciphers} | ssl_test_lib:ssl_options(server_psk_anon_hint, Config)]}; srp -> {ssl_test_lib:ssl_options(client_srp, Config), @@ -4753,7 +4998,8 @@ run_suites(Ciphers, Config, Type) -> ssl_test_lib:ssl_options(server_srp_dsa, Config)}; ecdsa -> {ssl_test_lib:ssl_options(client_verification_opts, Config), - ssl_test_lib:ssl_options(server_ecdsa_opts, Config)}; + [{ciphers, Ciphers} | + ssl_test_lib:ssl_options(server_ecdsa_opts, Config)]}; ecdh_rsa -> {ssl_test_lib:ssl_options(client_verification_opts, Config), ssl_test_lib:ssl_options(server_ecdh_rsa_opts, Config)}; @@ -4776,9 +5022,17 @@ run_suites(Ciphers, Config, Type) -> des_rsa -> {ssl_test_lib:ssl_options(client_verification_opts, Config), [{ciphers, Ciphers} | - ssl_test_lib:ssl_options(server_verification_opts, Config)]} + ssl_test_lib:ssl_options(server_verification_opts, Config)]}; + chacha_rsa -> + {ssl_test_lib:ssl_options(client_verification_opts, Config), + [{ciphers, Ciphers} | + ssl_test_lib:ssl_options(server_verification_opts, Config)]}; + chacha_ecdsa -> + {ssl_test_lib:ssl_options(client_verification_opts, Config), + [{ciphers, Ciphers} | + ssl_test_lib:ssl_options(server_ecdsa_opts, Config)]} end, - + ct:pal("ssl_test_lib:filter_suites(~p ~p) -> ~p ", [Ciphers, Version, ssl_test_lib:filter_suites(Ciphers, Version)]), Result = lists:map(fun(Cipher) -> cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end, ssl_test_lib:filter_suites(Ciphers, Version)), @@ -4791,7 +5045,7 @@ run_suites(Ciphers, Config, Type) -> end. erlang_cipher_suite(Suite) when is_list(Suite)-> - ssl_cipher:erl_suite_definition(ssl_cipher:openssl_suite(Suite)); + ssl_cipher:suite_definition(ssl_cipher:openssl_suite(Suite)); erlang_cipher_suite(Suite) -> Suite. @@ -4843,8 +5097,13 @@ connection_information_result(Socket) -> end. connection_info_result(Socket) -> - {ok, Info} = ssl:connection_information(Socket, [protocol, cipher_suite]), - {ok, {proplists:get_value(protocol, Info), proplists:get_value(cipher_suite, Info)}}. + {ok, Info} = ssl:connection_information(Socket, [protocol, selected_cipher_suite]), + {ok, {proplists:get_value(protocol, Info), proplists:get_value(selected_cipher_suite, Info)}}. + +protocol_info_result(Socket) -> + {ok, [{protocol, PVersion}]} = ssl:connection_information(Socket, [protocol]), + {ok, PVersion}. + version_info_result(Socket) -> {ok, [{version, Version}]} = ssl:connection_information(Socket, [version]), {ok, Version}. @@ -4887,8 +5146,14 @@ tls_downgrade_result(Socket) -> tls_close(Socket) -> ok = ssl_test_lib:send_recv_result(Socket), - ok = ssl:close(Socket, 5000). - + case ssl:close(Socket, 5000) of + ok -> + ok; + {error, closed} -> + ok; + Other -> + ct:fail(Other) + end. %% First two clauses handles 1/n-1 splitting countermeasure Rizzo/Duong-Beast treashold(N, {3,0}) -> @@ -4967,20 +5232,6 @@ try_recv_active_once(Socket) -> {error, einval} = ssl:recv(Socket, 11), ok. -first_rsa_suite([{ecdhe_rsa, _, _} = Suite | _]) -> - Suite; -first_rsa_suite([{dhe_rsa, _, _} = Suite| _]) -> - Suite; -first_rsa_suite([{rsa, _, _} = Suite| _]) -> - Suite; -first_rsa_suite([{ecdhe_rsa, _, _, _} = Suite | _]) -> - Suite; -first_rsa_suite([{dhe_rsa, _, _, _} = Suite| _]) -> - Suite; -first_rsa_suite([{rsa, _, _, _} = Suite| _]) -> - Suite; -first_rsa_suite([_ | Rest]) -> - first_rsa_suite(Rest). wait_for_send(Socket) -> %% Make sure TLS process processed send message event |