aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/test/ssl_ECC_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/test/ssl_ECC_SUITE.erl')
-rw-r--r--lib/ssl/test/ssl_ECC_SUITE.erl320
1 files changed, 280 insertions, 40 deletions
diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl
index b8a03f578d..f779765b18 100644
--- a/lib/ssl/test/ssl_ECC_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_SUITE.erl
@@ -46,7 +46,7 @@ groups() ->
{'tlsv1', [], all_versions_groups()},
{'erlang_server', [], key_cert_combinations()},
{'erlang_client', [], key_cert_combinations()},
- {'erlang', [], key_cert_combinations() ++ misc()}
+ {'erlang', [], key_cert_combinations() ++ misc() ++ ecc_negotiation()}
].
all_versions_groups ()->
@@ -68,6 +68,23 @@ key_cert_combinations() ->
misc()->
[client_ecdsa_server_ecdsa_with_raw_key].
+ecc_negotiation() ->
+ [ecc_default_order,
+ ecc_default_order_custom_curves,
+ ecc_client_order,
+ ecc_client_order_custom_curves,
+ ecc_unknown_curve,
+ client_ecdh_server_ecdh_ecc_server_custom,
+ client_rsa_server_ecdh_ecc_server_custom,
+ client_ecdh_server_rsa_ecc_server_custom,
+ client_rsa_server_rsa_ecc_server_custom,
+ client_ecdsa_server_ecdsa_ecc_server_custom,
+ client_ecdsa_server_rsa_ecc_server_custom,
+ client_rsa_server_ecdsa_ecc_server_custom,
+ client_ecdsa_server_ecdsa_ecc_client_custom,
+ client_rsa_server_ecdsa_ecc_client_custom
+ ].
+
%%--------------------------------------------------------------------
init_per_suite(Config0) ->
end_per_suite(Config0),
@@ -145,7 +162,7 @@ init_per_testcase(TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:log("Ciphers: ~p~n ", [ ssl:cipher_suites()]),
end_per_testcase(TestCase, Config),
- ssl:start(),
+ ssl_test_lib:clean_start(),
ct:timetrap({seconds, 15}),
Config.
@@ -159,42 +176,42 @@ end_per_testcase(_TestCase, Config) ->
client_ecdh_server_ecdh(Config) when is_list(Config) ->
COpts = proplists:get_value(client_ecdh_rsa_opts, Config),
- SOpts = proplists:get_value(server_ecdh_rsa_verify_opts, Config),
+ SOpts = proplists:get_value(server_ecdh_rsa_opts, Config),
basic_test(COpts, SOpts, Config).
client_ecdh_server_rsa(Config) when is_list(Config) ->
COpts = proplists:get_value(client_ecdh_rsa_opts, Config),
- SOpts = proplists:get_value(server_ecdh_rsa_verify_opts, Config),
+ SOpts = proplists:get_value(server_opts, Config),
basic_test(COpts, SOpts, Config).
client_rsa_server_ecdh(Config) when is_list(Config) ->
- COpts = proplists:get_value(client_ecdh_rsa_opts, Config),
- SOpts = proplists:get_value(server_ecdh_rsa_verify_opts, Config),
+ COpts = proplists:get_value(client_opts, Config),
+ SOpts = proplists:get_value(server_ecdh_rsa_opts, Config),
basic_test(COpts, SOpts, Config).
client_rsa_server_rsa(Config) when is_list(Config) ->
- COpts = proplists:get_value(client_verification_opts, Config),
- SOpts = proplists:get_value(server_verification_opts, Config),
+ COpts = proplists:get_value(client_opts, Config),
+ SOpts = proplists:get_value(server_opts, Config),
basic_test(COpts, SOpts, Config).
client_ecdsa_server_ecdsa(Config) when is_list(Config) ->
COpts = proplists:get_value(client_ecdsa_opts, Config),
- SOpts = proplists:get_value(server_ecdsa_verify_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
basic_test(COpts, SOpts, Config).
client_ecdsa_server_rsa(Config) when is_list(Config) ->
COpts = proplists:get_value(client_ecdsa_opts, Config),
- SOpts = proplists:get_value(server_ecdsa_verify_opts, Config),
+ SOpts = proplists:get_value(server_opts, Config),
basic_test(COpts, SOpts, Config).
client_rsa_server_ecdsa(Config) when is_list(Config) ->
- COpts = proplists:get_value(client_ecdsa_opts, Config),
- SOpts = proplists:get_value(server_ecdsa_verify_opts, Config),
+ COpts = proplists:get_value(client_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
basic_test(COpts, SOpts, Config).
client_ecdsa_server_ecdsa_with_raw_key(Config) when is_list(Config) ->
COpts = proplists:get_value(client_ecdsa_opts, Config),
- SOpts = proplists:get_value(server_ecdsa_verify_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
ServerCert = proplists:get_value(certfile, SOpts),
ServerKeyFile = proplists:get_value(keyfile, SOpts),
{ok, PemBin} = file:read_file(ServerKeyFile),
@@ -218,6 +235,132 @@ client_ecdsa_server_ecdsa_with_raw_key(Config) when is_list(Config) ->
check_result(Server, SType, Client, CType),
close(Server, Client).
+ecc_default_order(Config) ->
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ ECCOpts = [],
+ case supported_eccs([{eccs, [sect571r1]}]) of
+ true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+ecc_default_order_custom_curves(Config) ->
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ ECCOpts = [{eccs, [secp256r1, sect571r1]}],
+ case supported_eccs(ECCOpts) of
+ true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+ecc_client_order(Config) ->
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ ECCOpts = [{honor_ecc_order, false}],
+ case supported_eccs([{eccs, [sect571r1]}]) of
+ true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+ecc_client_order_custom_curves(Config) ->
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ ECCOpts = [{honor_ecc_order, false}, {eccs, [secp256r1, sect571r1]}],
+ case supported_eccs(ECCOpts) of
+ true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+ecc_unknown_curve(Config) ->
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ ECCOpts = [{eccs, ['123_fake_curve']}],
+ ecc_test_error(COpts, SOpts, [], ECCOpts, Config).
+
+%% We can only expect to see a named curve on a conn with
+%% a server supporting ecdsa. Otherwise the curve is selected
+%% but not used and communicated to the client?
+client_ecdh_server_ecdh_ecc_server_custom(Config) ->
+ COpts = proplists:get_value(client_ecdh_rsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdh_rsa_opts, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ case supported_eccs(ECCOpts) of
+ true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_ecdh_server_rsa_ecc_server_custom(Config) ->
+ COpts = proplists:get_value(client_ecdh_rsa_opts, Config),
+ SOpts = proplists:get_value(server_opts, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ case supported_eccs(ECCOpts) of
+ true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_rsa_server_ecdh_ecc_server_custom(Config) ->
+ COpts = proplists:get_value(client_opts, Config),
+ SOpts = proplists:get_value(server_ecdh_rsa_opts, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ case supported_eccs(ECCOpts) of
+ true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_rsa_server_rsa_ecc_server_custom(Config) ->
+ COpts = proplists:get_value(client_opts, Config),
+ SOpts = proplists:get_value(server_opts, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ case supported_eccs(ECCOpts) of
+ true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_ecdsa_server_ecdsa_ecc_server_custom(Config) ->
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ case supported_eccs(ECCOpts) of
+ true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_ecdsa_server_rsa_ecc_server_custom(Config) ->
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_opts, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ case supported_eccs(ECCOpts) of
+ true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_rsa_server_ecdsa_ecc_server_custom(Config) ->
+ COpts = proplists:get_value(client_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ case supported_eccs(ECCOpts) of
+ true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_ecdsa_server_ecdsa_ecc_client_custom(Config) ->
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ ECCOpts = [{eccs, [secp256r1, sect571r1]}],
+ case supported_eccs(ECCOpts) of
+ true -> ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_rsa_server_ecdsa_ecc_client_custom(Config) ->
+ COpts = proplists:get_value(client_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ ECCOpts = [{eccs, [secp256r1, sect571r1]}],
+ case supported_eccs(ECCOpts) of
+ true -> ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
@@ -244,20 +387,48 @@ basic_test(ClientCert, ClientKey, ClientCA, ServerCert, ServerKey, ServerCA, Con
check_result(Server, SType, Client, CType),
close(Server, Client).
-start_client(openssl, Port, CA, OwnCa, Cert, Key, Config) ->
+
+ecc_test(Expect, COpts, SOpts, CECCOpts, SECCOpts, Config) ->
+ CCA = proplists:get_value(cacertfile, COpts),
+ CCert = proplists:get_value(certfile, COpts),
+ CKey = proplists:get_value(keyfile, COpts),
+ SCA = proplists:get_value(cacertfile, SOpts),
+ SCert = proplists:get_value(certfile, SOpts),
+ SKey = proplists:get_value(keyfile, SOpts),
+ {Server, Port} = start_server_ecc(erlang, CCA, SCA, SCert, SKey, Expect, SECCOpts, Config),
+ Client = start_client_ecc(erlang, Port, SCA, CCA, CCert, CKey, Expect, CECCOpts, Config),
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ close(Server, Client).
+
+ecc_test_error(COpts, SOpts, CECCOpts, SECCOpts, Config) ->
+ CCA = proplists:get_value(cacertfile, COpts),
+ CCert = proplists:get_value(certfile, COpts),
+ CKey = proplists:get_value(keyfile, COpts),
+ SCA = proplists:get_value(cacertfile, SOpts),
+ SCert = proplists:get_value(certfile, SOpts),
+ SKey = proplists:get_value(keyfile, SOpts),
+ {Server, Port} = start_server_ecc_error(erlang, CCA, SCA, SCert, SKey, SECCOpts, Config),
+ Client = start_client_ecc_error(erlang, Port, SCA, CCA, CCert, CKey, CECCOpts, Config),
+ Error = {error, {tls_alert, "insufficient security"}},
+ ssl_test_lib:check_result(Server, Error, Client, Error).
+
+
+start_client(openssl, Port, PeerCA, OwnCa, Cert, Key, Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
- NewCA = new_ca(filename:join(PrivDir, "new_ca.pem"), CA, OwnCa),
+ CA = new_openssl_ca(filename:join(PrivDir, "openssl_client_ca.pem"), PeerCA, OwnCa),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
Exe = "openssl",
Args = ["s_client", "-verify", "2", "-port", integer_to_list(Port),
ssl_test_lib:version_flag(Version),
- "-cert", Cert, "-CAfile", NewCA,
+ "-cert", Cert, "-CAfile", CA,
"-key", Key, "-host","localhost", "-msg", "-debug"],
OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, "Hello world"),
OpenSslPort;
-start_client(erlang, Port, CA, _, Cert, Key, Config) ->
+start_client(erlang, Port, PeerCA, OwnCa, Cert, Key, Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ CA = new_ca(filename:join(PrivDir,"erlang_client_ca.pem"), PeerCA, OwnCa),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -267,20 +438,48 @@ start_client(erlang, Port, CA, _, Cert, Key, Config) ->
{cacertfile, CA},
{certfile, Cert}, {keyfile, Key}]}]).
-start_server(openssl, CA, OwnCa, Cert, Key, Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- NewCA = new_ca(filename:join(PrivDir, "new_ca.pem"), CA, OwnCa),
+start_client_ecc(erlang, Port, PeerCA, OwnCa, Cert, Key, Expect, ECCOpts, Config) ->
+ CA = new_ca("erlang_client_ca", PeerCA, OwnCa),
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+ ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, check_ecc, [client, Expect]}},
+ {options,
+ ECCOpts ++
+ [{verify, verify_peer},
+ {cacertfile, CA},
+ {certfile, Cert}, {keyfile, Key}]}]).
+
+start_client_ecc_error(erlang, Port, PeerCA, OwnCa, Cert, Key, ECCOpts, Config) ->
+ CA = new_ca("erlang_client_ca", PeerCA, OwnCa),
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+ ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {options,
+ ECCOpts ++
+ [{verify, verify_peer},
+ {cacertfile, CA},
+ {certfile, Cert}, {keyfile, Key}]}]).
+
+
+start_server(openssl, PeerCA, OwnCa, Cert, Key, Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ CA = new_openssl_ca(filename:join(PrivDir,"openssl_server_ca.pem"), PeerCA, OwnCa),
Port = ssl_test_lib:inet_port(node()),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
Exe = "openssl",
Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
- "-verify", "2", "-cert", Cert, "-CAfile", NewCA,
+ "-verify", "2", "-cert", Cert, "-CAfile", CA,
"-key", Key, "-msg", "-debug"],
OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, "Hello world"),
{OpenSslPort, Port};
-start_server(erlang, CA, _, Cert, Key, Config) ->
+start_server(erlang, PeerCA, OwnCa, Cert, Key, Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ CA = new_ca(filename:join(PrivDir,"erlang_server_ca.pem"), PeerCA, OwnCa),
{_, ServerNode, _} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
@@ -291,16 +490,42 @@ start_server(erlang, CA, _, Cert, Key, Config) ->
[{verify, verify_peer}, {cacertfile, CA},
{certfile, Cert}, {keyfile, Key}]}]),
{Server, ssl_test_lib:inet_port(Server)}.
-start_server_with_raw_key(erlang, CA, _, Cert, Key, Config) ->
+
+start_server_with_raw_key(erlang, PeerCA, OwnCa, Cert, Key, Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ CA = new_ca(filename:join(PrivDir, "erlang_server_ca.pem"), PeerCA, OwnCa),
{_, ServerNode, _} = 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,
- [{verify, verify_peer}, {cacertfile, CA},
- {certfile, Cert}, {key, Key}]}]),
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ send_recv_result_active,
+ []}},
+ {options,
+ [{verify, verify_peer}, {cacertfile, CA},
+ {certfile, Cert}, {key, Key}]}]),
+ {Server, ssl_test_lib:inet_port(Server)}.
+
+start_server_ecc(erlang, PeerCA, OwnCa, Cert, Key, Expect, ECCOpts, Config) ->
+ CA = new_ca("erlang_server_ca", PeerCA, OwnCa),
+ {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, check_ecc, [server, Expect]}},
+ {options,
+ ECCOpts ++
+ [{verify, verify_peer}, {cacertfile, CA},
+ {certfile, Cert}, {keyfile, Key}]}]),
+ {Server, ssl_test_lib:inet_port(Server)}.
+
+start_server_ecc_error(erlang, PeerCA, OwnCa, Cert, Key, ECCOpts, Config) ->
+ CA = new_ca("erlang_server_ca", PeerCA, OwnCa),
+ {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options,
+ ECCOpts ++
+ [{verify, verify_peer}, {cacertfile, CA},
+ {certfile, Cert}, {keyfile, Key}]}]),
{Server, ssl_test_lib:inet_port(Server)}.
check_result(Server, erlang, Client, erlang) ->
@@ -336,19 +561,34 @@ close(Client, Server) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
-%% Work around OpenSSL bug, apparently the same bug as we had fixed in
-%% 11629690ba61f8e0c93ef9b2b6102fd279825977
new_ca(FileName, CA, OwnCa) ->
{ok, P1} = file:read_file(CA),
E1 = public_key:pem_decode(P1),
{ok, P2} = file:read_file(OwnCa),
E2 = public_key:pem_decode(P2),
- case os:cmd("openssl version") of
- "OpenSSL 1.0.1p-freebsd" ++ _ ->
- Pem = public_key:pem_encode(E1 ++E2),
- file:write_file(FileName, Pem);
- _ ->
- Pem = public_key:pem_encode(E2 ++E1),
- file:write_file(FileName, Pem)
- end,
+ Pem = public_key:pem_encode(E1 ++E2),
+ file:write_file(FileName, Pem),
FileName.
+
+new_openssl_ca(FileName, CA, OwnCa) ->
+ {ok, P1} = file:read_file(CA),
+ E1 = public_key:pem_decode(P1),
+ {ok, P2} = file:read_file(OwnCa),
+ E2 = public_key:pem_decode(P2),
+ Pem = public_key:pem_encode(E2 ++E1),
+ file:write_file(FileName, Pem),
+ FileName.
+
+supported_eccs(Opts) ->
+ ToCheck = proplists:get_value(eccs, Opts, []),
+ Supported = ssl:eccs(),
+ lists:all(fun(Curve) -> lists:member(Curve, Supported) end, ToCheck).
+
+check_ecc(SSL, Role, Expect) ->
+ {ok, Data} = ssl:connection_information(SSL),
+ case lists:keyfind(ecc, 1, Data) of
+ {ecc, {named_curve, Expect}} -> ok;
+ false when Expect =:= undefined -> ok;
+ Other -> {error, Role, Expect, Other}
+ end.
+