diff options
Diffstat (limited to 'lib/ssl/test/ssl_basic_SUITE.erl')
-rw-r--r-- | lib/ssl/test/ssl_basic_SUITE.erl | 388 |
1 files changed, 374 insertions, 14 deletions
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index fbe2d4f6b0..a5ece4fad8 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -22,12 +22,71 @@ -module(ssl_basic_SUITE). -%% Note: This directive should only be used in test suites. --compile(export_all). +-behaviour(ct_suite). -include_lib("common_test/include/ct.hrl"). +-include_lib("public_key/include/public_key.hrl"). -include_lib("ssl/src/ssl_api.hrl"). +%% Callback functions +-export([all/0, + groups/0, + init_per_suite/1, + end_per_suite/1, + init_per_testcase/2, + end_per_testcase/2]). + +%% Testcases +-export([app/0, + app/1, + appup/0, + appup/1, + version_option/0, + version_option/1, + connect_twice/0, + connect_twice/1, + connect_dist/0, + connect_dist/1, + defaults/1, + fallback/0, + fallback/1, + cipher_format/0, + cipher_format/1, + tls_versions_option/0, + tls_versions_option/1, + eccs/0, + eccs/1, + cipher_suites/0, + cipher_suites/1, + old_cipher_suites/0, + old_cipher_suites/1, + cipher_suites_mix/0, + cipher_suites_mix/1, + unordered_protocol_versions_server/0, + unordered_protocol_versions_server/1, + unordered_protocol_versions_client/0, + unordered_protocol_versions_client/1, + fake_root/0, + fake_root/1, + fake_root_legacy/0, + fake_root_legacy/1, + fake_root_no_intermediate/0, + fake_root_no_intermediate/1, + fake_root_no_intermediate_legacy/0, + fake_root_no_intermediate_legacy/1, + fake_intermediate_cert/0, + fake_intermediate_cert/1 + ]). + +%% Apply export +-export([tcp_send_recv_result/1, + result_ok/1, + protocol_info_result/1, + version_info_result/1, + connect_dist_s/1, + connect_dist_c/1, + dummy/1 + ]). -define(TIMEOUT, 20000). -define(EXPIRE, 10). @@ -63,7 +122,12 @@ basic_tests() -> eccs, cipher_suites, old_cipher_suites, - cipher_suites_mix + cipher_suites_mix, + fake_root, + fake_root_no_intermediate, + fake_root_legacy, + fake_root_no_intermediate_legacy, + fake_intermediate_cert ]. options_tests() -> @@ -76,7 +140,7 @@ init_per_suite(Config0) -> try crypto:start() of ok -> ssl_test_lib:clean_start(), - %% make rsa certs using oppenssl + %% make rsa certs using openssl {ok, _} = make_certs:all(proplists:get_value(data_dir, Config0), proplists:get_value(priv_dir, Config0)), Config1 = ssl_test_lib:make_dsa_cert(Config0), @@ -173,7 +237,7 @@ connect_twice(Config) when is_list(Config) -> ssl_test_lib:close(Client1). defaults(Config) when is_list(Config)-> Versions = ssl:versions(), - true = lists:member(sslv3, proplists:get_value(available, Versions)), + false = 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)), false = lists:member('tlsv1', proplists:get_value(supported, Versions)), @@ -244,7 +308,7 @@ cipher_suites(Config) when is_list(Config) -> cipher => 'aes_128_cbc', mac => sha, prf => default_prf}, - Version = ssl_test_lib:protocol_version(Config), + Version = tls_record:highest_protocol_version([]), All = [_|_] = ssl:cipher_suites(all, Version), Default = [_|_] = ssl:cipher_suites(default, Version), Anonymous = [_|_] = ssl:cipher_suites(anonymous, Version), @@ -321,7 +385,7 @@ cipher_suites_mix(Config) when is_list(Config) -> {host, Hostname}, {from, self()}, {mfa, {ssl_test_lib, send_recv_result_active, []}}, - {options, [{ciphers, CipherSuites} | ClientOpts]}]), + {options, [{versions, ['tlsv1.2']},{ciphers, CipherSuites} | ClientOpts]}]), ssl_test_lib:check_result(Server, ok, Client, ok), ssl_test_lib:close(Server), @@ -406,7 +470,6 @@ eccs() -> eccs(Config) when is_list(Config) -> [_|_] = All = ssl:eccs(), - [] = ssl:eccs(sslv3), [_|_] = Tls = ssl:eccs(tlsv1), [_|_] = Tls1 = ssl:eccs('tlsv1.1'), [_|_] = Tls2 = ssl:eccs('tlsv1.2'), @@ -450,14 +513,252 @@ tls_versions_option(Config) when is_list(Config) -> end, ssl_test_lib:check_client_alert(ErrClient, protocol_version). +fake_root() -> + [{doc,"Test that we can not use a fake root signed by other key but with correct name and serial number."}]. +fake_root(Config) when is_list(Config) -> + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Ext = x509_test:extensions([{key_usage, [keyCertSign, cRLSign, digitalSignature, keyAgreement]}]), + ROOT = #{cert := Cert, + key := _Key} = public_key:pkix_test_root_cert("SERVER ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(6)}, + {extensions, Ext}]), + + FakeKey = ssl_test_lib:hardcode_rsa_key(1), + OTPCert = public_key:pkix_decode_cert(Cert, otp), + TBS = OTPCert#'OTPCertificate'.tbsCertificate, + FakeCert = public_key:pkix_sign(TBS, FakeKey), + + + AuthExt = #'AuthorityKeyIdentifier'{authorityCertIssuer = [{directoryName, TBS#'OTPTBSCertificate'.issuer}], + authorityCertSerialNumber = TBS#'OTPTBSCertificate'.serialNumber}, + [AuthKeyExt] = x509_test:extensions([{?'id-ce-authorityKeyIdentifier', + AuthExt, + false}]), + + #{server_config := ServerConf, + client_config := ClientConf} = public_key:pkix_test_data(#{server_chain => + #{root => ROOT, + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}, + {extensions, [AuthKeyExt]}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(4)}]}, + client_chain => + #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}], + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}} + ), + + #{server_config := FakeServerConf} = public_key:pkix_test_data(#{server_chain => + #{root => #{cert => FakeCert, key => FakeKey}, + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}, + {extensions, [AuthKeyExt]}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}, + client_chain => + #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}], + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}} + ), + + + test_fake_root(Hostname, ServerNode, ClientNode, ServerConf, ClientConf, FakeCert, FakeServerConf, bad_certificate, bad_certificate). + +fake_root_no_intermediate() -> + [{doc,"Test that we can not use a fake root signed by other key but with correct name and serial number."}]. + +fake_root_no_intermediate(Config) when is_list(Config) -> + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Ext = x509_test:extensions([{key_usage, [keyCertSign, cRLSign, digitalSignature, keyAgreement]}]), + ROOT = #{cert := Cert, + key := _Key} = public_key:pkix_test_root_cert("SERVER ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(6)}, + {extensions, Ext}]), + + FakeKey = ssl_test_lib:hardcode_rsa_key(1), + OTPCert = public_key:pkix_decode_cert(Cert, otp), + TBS = OTPCert#'OTPCertificate'.tbsCertificate, + FakeCert = public_key:pkix_sign(TBS, FakeKey), + + AuthExt = #'AuthorityKeyIdentifier'{authorityCertIssuer = [{directoryName, TBS#'OTPTBSCertificate'.issuer}], + authorityCertSerialNumber = TBS#'OTPTBSCertificate'.serialNumber}, + [AuthKeyExt] = x509_test:extensions([{?'id-ce-authorityKeyIdentifier', + AuthExt, + false}]), + + + #{server_config := ServerConf, + client_config := ClientConf} = public_key:pkix_test_data(#{server_chain => + #{root => ROOT, + intermediates => [], + peer => [{key, ssl_test_lib:hardcode_rsa_key(4)}, + {extensions, [AuthKeyExt]}]}, + client_chain => + #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}], + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}} + ), + + #{server_config := FakeServerConf} = public_key:pkix_test_data(#{server_chain => + #{root => #{cert => FakeCert, key => FakeKey}, + intermediates => [], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}, + {extensions, [AuthKeyExt]}]}, + client_chain => + #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}], + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}} + ), + test_fake_root(Hostname, ServerNode, ClientNode, ServerConf, ClientConf, FakeCert, FakeServerConf, bad_certificate, bad_certificate). + +fake_root_legacy() -> + [{doc,"Test that we can not use a fake root signed by other key but with correct name and serial number."}]. +fake_root_legacy(Config) when is_list(Config) -> + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Ext = x509_test:extensions([{key_usage, [keyCertSign, cRLSign, digitalSignature, keyAgreement]}]), + ROOT = #{cert := Cert, + key := _Key} = public_key:pkix_test_root_cert("SERVER ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(6)}, + {extensions, Ext}]), + + FakeKey = ssl_test_lib:hardcode_rsa_key(1), + OTPCert = public_key:pkix_decode_cert(Cert, otp), + TBS = OTPCert#'OTPCertificate'.tbsCertificate, + FakeCert = public_key:pkix_sign(TBS, FakeKey), + + #{server_config := ServerConf, + client_config := ClientConf} = public_key:pkix_test_data(#{server_chain => + #{root => ROOT, + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(4)}]}, + client_chain => + #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}], + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}} + ), + + #{server_config := FakeServerConf} = public_key:pkix_test_data(#{server_chain => + #{root => #{cert => FakeCert, key => FakeKey}, + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}, + client_chain => + #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}], + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}} + ), + + + test_fake_root(Hostname, ServerNode, ClientNode, ServerConf, ClientConf, FakeCert, FakeServerConf, unknown_ca, unknown_ca). + +fake_root_no_intermediate_legacy() -> + [{doc,"Test that we can not use a fake root signed by other key but with correct name and serial number."}]. +fake_root_no_intermediate_legacy(Config) when is_list(Config) -> + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Ext = x509_test:extensions([{key_usage, [keyCertSign, cRLSign, digitalSignature, keyAgreement]}]), + ROOT = #{cert := Cert, + key := _Key} = public_key:pkix_test_root_cert("SERVER ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(6)}, + {extensions, Ext}]), + + FakeKey = ssl_test_lib:hardcode_rsa_key(1), + OTPCert = public_key:pkix_decode_cert(Cert, otp), + TBS = OTPCert#'OTPCertificate'.tbsCertificate, + FakeCert = public_key:pkix_sign(TBS, FakeKey), + + #{server_config := ServerConf, + client_config := ClientConf} = public_key:pkix_test_data(#{server_chain => + #{root => ROOT, + intermediates => [], + peer => [{key, ssl_test_lib:hardcode_rsa_key(4)}]}, + client_chain => + #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}], + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}} + ), + + #{server_config := FakeServerConf} = public_key:pkix_test_data(#{server_chain => + #{root => #{cert => FakeCert, key => FakeKey}, + intermediates => [], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}, + client_chain => + #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}], + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}} + ), + test_fake_root(Hostname, ServerNode, ClientNode, ServerConf, ClientConf, FakeCert, FakeServerConf, unknown_ca, unknown_ca). + +fake_intermediate_cert() -> + [{doc,"Test that we can not use a fake intermediat cert claiming to be signed by a trusted ROOT but is not."}]. + +fake_intermediate_cert(Config) when is_list(Config) -> + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Ext = x509_test:extensions([{key_usage, [keyCertSign, cRLSign, digitalSignature, keyAgreement]}]), + ROOT = #{cert := Cert, + key := _Key} = public_key:pkix_test_root_cert("SERVER ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(6)}, + {extensions, Ext}]), + + OtherSROOT = #{cert := OtherSCert, + key := OtherSKey} = public_key:pkix_test_root_cert("OTHER SERVER ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(3)}, + {extensions, Ext}]), + OtherCROOT = #{cert := OtherCCert, + key := _OtherCKey} = public_key:pkix_test_root_cert("OTHER Client ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(1)}, + {extensions, Ext}]), + + #{client_config := ClientConf} = public_key:pkix_test_data(#{server_chain => + #{root => ROOT, + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(4)}]}, + client_chain => + #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}], + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}} + ), + + #{server_config := OtherServerConf} = public_key:pkix_test_data(#{server_chain => + #{root => OtherSROOT, + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(1)}]}, + client_chain => + #{root => OtherCROOT, + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}} + ), + OTPCert = public_key:pkix_decode_cert(Cert, otp), + TBS = OTPCert#'OTPCertificate'.tbsCertificate, + TBSExt = TBS#'OTPTBSCertificate'.extensions, + AuthExt = #'AuthorityKeyIdentifier'{authorityCertIssuer = [{directoryName, TBS#'OTPTBSCertificate'.issuer}], + authorityCertSerialNumber = TBS#'OTPTBSCertificate'.serialNumber}, + [AuthKeyExt] = x509_test:extensions([{?'id-ce-authorityKeyIdentifier', + AuthExt, + false}]), + + + CAs = proplists:get_value(cacerts, OtherServerConf), + + [ICA] = CAs -- [OtherSCert, OtherCCert], + + OTPICACert = public_key:pkix_decode_cert(ICA, otp), + ICATBS = OTPICACert#'OTPCertificate'.tbsCertificate, + + FakeICA = public_key:pkix_sign(ICATBS#'OTPTBSCertificate'{extensions = [AuthKeyExt | TBSExt]}, OtherSKey), + + ServerCert = proplists:get_value(cert, OtherServerConf), + FakeServer = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, no_result, []}}, + {options, [{cert, [ServerCert, FakeICA]} | + proplists:delete(cert, OtherServerConf)] + }]), + Port1 = ssl_test_lib:inet_port(FakeServer), + + Client1 = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port1}, + {host, Hostname}, + {from, self()}, + {options, [{verify, verify_peer} | ClientConf]}]), + + ssl_test_lib:check_client_alert(Client1, bad_certificate). %%-------------------------------------------------------------------- -%% Internal functions ------------------------------------------------ +%% callback functions ------------------------------------------------ %%-------------------------------------------------------------------- -send_recv_result(Socket) -> - ssl:send(Socket, "Hello world"), - {ok,"Hello world"} = ssl:recv(Socket, 11), - ok. tcp_send_recv_result(Socket) -> gen_tcp:send(Socket, "Hello world"), {ok,"Hello world"} = gen_tcp:recv(Socket, 11), @@ -489,7 +790,9 @@ dummy(_Socket) -> %% Should not happen as the ssl connection will not be established %% due to fatal handshake failiure exit(kill). - +%%-------------------------------------------------------------------- +%% Internal functions ------------------------------------------------ +%%-------------------------------------------------------------------- version_option_test(Config, Version) -> ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), @@ -526,3 +829,60 @@ remove_supported_versions(Available, Supported) -> Versions0 end. + +test_fake_root(Hostname, ServerNode, ClientNode, ServerConf, ClientConf, FakeCert, FakeServerConf, ResultRootIncluded, ResultRootExcluded) -> + RealServer = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, ServerConf}]), + Port0 = ssl_test_lib:inet_port(RealServer), + Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port0}, + {host, Hostname}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {from, self()}, + {options, [{verify, verify_peer} | ClientConf]}]), + + ssl_test_lib:check_result(RealServer, ok, Client0, ok), + + ssl_test_lib:close(RealServer), + ssl_test_lib:close(Client0), + + %% Fake server sends ROOT cert + FakeServer = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, no_result, []}}, + {options, FakeServerConf}]), + Port1 = ssl_test_lib:inet_port(FakeServer), + + Client1 = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port1}, + {host, Hostname}, + {from, self()}, + {options, [{verify, verify_peer} | ClientConf]}]), + + ssl_test_lib:check_client_alert(Client1, ResultRootIncluded), + + + %%Fake server does not send ROOT cert + CAS0 = proplists:get_value(cacerts, FakeServerConf), + CAS1 = CAS0 -- [FakeCert], + + FakeServer1 = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, no_result, []}}, + {options, [{cacerts, CAS1} | proplists:delete(cacerts, FakeServerConf)]}]), + + Port2 = ssl_test_lib:inet_port(FakeServer1), + + Client2 = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port2}, + {host, Hostname}, + {from, self()}, + {options, [{verify, verify_peer} | ClientConf]}]), + + ssl_test_lib:check_client_alert(Client2, ResultRootExcluded), + + ssl_test_lib:close(FakeServer1). + + + + + |