From c9f236377e96640bc9a271449635ac58d80bf40f Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 5 Jul 2018 10:37:42 +0200 Subject: ssl: No cipher suite sign restriction in TLS-1.2 --- lib/ssl/src/ssl_cipher.erl | 2 ++ lib/ssl/src/ssl_handshake.erl | 44 +++++---------------------------- lib/ssl/test/ssl_ECC_SUITE.erl | 13 ++++++++-- lib/ssl/test/ssl_ECC_openssl_SUITE.erl | 17 ++++++++++--- lib/ssl/test/ssl_test_lib.erl | 45 ++++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 43 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl index 754fc46404..50dadd0903 100644 --- a/lib/ssl/src/ssl_cipher.erl +++ b/lib/ssl/src/ssl_cipher.erl @@ -2709,6 +2709,8 @@ filter_suites_pubkey(ec, Ciphers, _, OtpCert) -> ec_ecdhe_suites(Ciphers)), filter_keyuse_suites(keyAgreement, Uses, CiphersSuites, ec_ecdh_suites(Ciphers)). +filter_suites_signature(rsa, Ciphers, {3, N}) when N >= 3 -> + Ciphers; filter_suites_signature(rsa, Ciphers, Version) -> (Ciphers -- ecdsa_signed_suites(Ciphers, Version)) -- dsa_signed_suites(Ciphers, Version); filter_suites_signature(dsa, Ciphers, Version) -> diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 76fc7ae3d1..a6365f1bd3 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -1065,17 +1065,14 @@ select_hashsign(HashSigns, Cert, KeyExAlgo, select_hashsign(HashSigns, Cert, KeyExAlgo, tls_v1:default_signature_algs(Version), Version); select_hashsign(#hash_sign_algos{hash_sign_algos = HashSigns}, Cert, KeyExAlgo, SupportedHashSigns, {Major, Minor}) when Major >= 3 andalso Minor >= 3 -> - #'OTPCertificate'{tbsCertificate = TBSCert, - signatureAlgorithm = {_,SignAlgo, _}} = public_key:pkix_decode_cert(Cert, otp), + #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp), #'OTPSubjectPublicKeyInfo'{algorithm = {_, SubjAlgo, _}} = TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo, - Sign = sign_algo(SignAlgo), SubSign = sign_algo(SubjAlgo), case lists:filter(fun({_, S} = Algos) when S == SubSign -> - is_acceptable_hash_sign(Algos, Sign, - SubSign, KeyExAlgo, SupportedHashSigns); + is_acceptable_hash_sign(Algos, KeyExAlgo, SupportedHashSigns); (_) -> false end, HashSigns) of @@ -2232,37 +2229,7 @@ sign_algo(Alg) -> {_, Sign} =public_key:pkix_sign_types(Alg), Sign. -is_acceptable_hash_sign(Algos, _, _, KeyExAlgo, SupportedHashSigns) when - KeyExAlgo == dh_dss; - KeyExAlgo == dh_rsa; - KeyExAlgo == ecdh_rsa; - KeyExAlgo == ecdh_ecdsa - -> - %% *dh_* could be called only *dh in TLS-1.2 - is_acceptable_hash_sign(Algos, SupportedHashSigns); -is_acceptable_hash_sign(Algos, rsa, ecdsa, ecdhe_rsa, SupportedHashSigns) -> - is_acceptable_hash_sign(Algos, SupportedHashSigns); -is_acceptable_hash_sign({_, rsa} = Algos, rsa, _, dhe_rsa, SupportedHashSigns) -> - is_acceptable_hash_sign(Algos, SupportedHashSigns); -is_acceptable_hash_sign({_, rsa} = Algos, rsa, rsa, ecdhe_rsa, SupportedHashSigns) -> - is_acceptable_hash_sign(Algos, SupportedHashSigns); -is_acceptable_hash_sign({_, rsa} = Algos, rsa, rsa, rsa, SupportedHashSigns) -> - is_acceptable_hash_sign(Algos, SupportedHashSigns); -is_acceptable_hash_sign({_, rsa} = Algos, rsa, _, srp_rsa, SupportedHashSigns) -> - is_acceptable_hash_sign(Algos, SupportedHashSigns); -is_acceptable_hash_sign({_, rsa} = Algos, rsa, _, rsa_psk, SupportedHashSigns) -> - is_acceptable_hash_sign(Algos, SupportedHashSigns); -is_acceptable_hash_sign({_, dsa} = Algos, dsa, _, dhe_dss, SupportedHashSigns) -> - is_acceptable_hash_sign(Algos, SupportedHashSigns); -is_acceptable_hash_sign({_, dsa} = Algos, dsa, _, srp_dss, SupportedHashSigns) -> - is_acceptable_hash_sign(Algos, SupportedHashSigns); -is_acceptable_hash_sign({_, ecdsa} = Algos, ecdsa, _, dhe_ecdsa, SupportedHashSigns) -> - is_acceptable_hash_sign(Algos, SupportedHashSigns); -is_acceptable_hash_sign({_, ecdsa} = Algos, ecdsa, ecdsa, ecdh_ecdsa, SupportedHashSigns) -> - is_acceptable_hash_sign(Algos, SupportedHashSigns); -is_acceptable_hash_sign({_, ecdsa} = Algos, ecdsa, ecdsa, ecdhe_ecdsa, SupportedHashSigns) -> - is_acceptable_hash_sign(Algos, SupportedHashSigns); -is_acceptable_hash_sign(_, _, _, KeyExAlgo, _) when +is_acceptable_hash_sign( _, KeyExAlgo, _) when KeyExAlgo == psk; KeyExAlgo == dhe_psk; KeyExAlgo == ecdhe_psk; @@ -2271,8 +2238,9 @@ is_acceptable_hash_sign(_, _, _, KeyExAlgo, _) when KeyExAlgo == ecdhe_anon -> true; -is_acceptable_hash_sign(_,_,_,_,_) -> - false. +is_acceptable_hash_sign(Algos,_, SupportedHashSigns) -> + is_acceptable_hash_sign(Algos, SupportedHashSigns). + is_acceptable_hash_sign(Algos, SupportedHashSigns) -> lists:member(Algos, SupportedHashSigns). diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl index 3c8eda1812..9a83ae2ca6 100644 --- a/lib/ssl/test/ssl_ECC_SUITE.erl +++ b/lib/ssl/test/ssl_ECC_SUITE.erl @@ -43,10 +43,10 @@ all() -> groups() -> [ - {'tlsv1.2', [], test_cases()}, + {'tlsv1.2', [], [mix_sign | test_cases()]}, {'tlsv1.1', [], test_cases()}, {'tlsv1', [], test_cases()}, - {'dtlsv1.2', [], test_cases()}, + {'dtlsv1.2', [], [mix_sign | test_cases()]}, {'dtlsv1', [], test_cases()} ]. @@ -392,3 +392,12 @@ client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom(Config) -> true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config); false -> {skip, "unsupported named curves"} end. + +mix_sign(Config) -> + {COpts0, SOpts0} = ssl_test_lib:make_mix_cert(Config), + COpts = ssl_test_lib:ssl_options(COpts0, Config), + SOpts = ssl_test_lib:ssl_options(SOpts0, Config), + ECDHE_ECDSA = + ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'), + [{key_exchange, fun(ecdhe_ecdsa) -> true; (_) -> false end}]), + ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_ECDSA} | SOpts], Config). diff --git a/lib/ssl/test/ssl_ECC_openssl_SUITE.erl b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl index 5a08b152a6..81a7dfd2da 100644 --- a/lib/ssl/test/ssl_ECC_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl @@ -57,13 +57,13 @@ all_groups() -> groups() -> case ssl_test_lib:openssl_sane_dtls() of true -> - [{'tlsv1.2', [], test_cases()}, + [{'tlsv1.2', [], [mix_sign | test_cases()]}, {'tlsv1.1', [], test_cases()}, {'tlsv1', [], test_cases()}, - {'dtlsv1.2', [], test_cases()}, + {'dtlsv1.2', [], [mix_sign | test_cases()]}, {'dtlsv1', [], test_cases()}]; false -> - [{'tlsv1.2', [], test_cases()}, + [{'tlsv1.2', [], [mix_sign | test_cases()]}, {'tlsv1.1', [], test_cases()}, {'tlsv1', [], test_cases()}] end. @@ -202,6 +202,17 @@ client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) -> ssl_ECC:client_ecdh_ecdsa_server_ecdhe_ecdsa(Config). client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) -> ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config). + +mix_sign(Config) -> + {COpts0, SOpts0} = ssl_test_lib:make_mix_cert(Config), + COpts = ssl_test_lib:ssl_options(COpts0, Config), + SOpts = ssl_test_lib:ssl_options(SOpts0, Config), + ECDHE_ECDSA = + ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'), + [{key_exchange, fun(ecdhe_ecdsa) -> true; (_) -> false end}]), + ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_ECDSA} | SOpts], [{client_type, erlang}, + {server_type, openssl} | Config]). + %%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 5414b30e04..2931b9899d 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -585,6 +585,17 @@ default_cert_chain_conf() -> %% Use only default options [[],[],[]]. +gen_conf(mix, mix, UserClient, UserServer) -> + ClientTag = conf_tag("client"), + ServerTag = conf_tag("server"), + + DefaultClient = default_cert_chain_conf(), + DefaultServer = default_cert_chain_conf(), + + ClientConf = merge_chain_spec(UserClient, DefaultClient, []), + ServerConf = merge_chain_spec(UserServer, DefaultServer, []), + + new_format([{ClientTag, ClientConf}, {ServerTag, ServerConf}]); gen_conf(ClientChainType, ServerChainType, UserClient, UserServer) -> ClientTag = conf_tag("client"), ServerTag = conf_tag("server"), @@ -678,6 +689,32 @@ merge_spec(User, Default, [Conf | Rest], Acc) -> merge_spec(User, Default, Rest, [{Conf, Value} | Acc]) end. +make_mix_cert(Config) -> + Ext = x509_test:extensions([{key_usage, [digitalSignature]}]), + Digest = {digest, appropriate_sha(crypto:supports())}, + CurveOid = hd(tls_v1:ecc_curves(0)), + ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "mix"]), + ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "mix"]), + ClientChain = [[Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, hardcode_rsa_key(1)}], + [Digest, {key, {namedCurve, CurveOid}}, {extensions, Ext}] + ], + ServerChain = [[Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, hardcode_rsa_key(2)}], + [Digest, {key, {namedCurve, CurveOid}},{extensions, Ext}] + ], + ClientChainType =ServerChainType = mix, + CertChainConf = gen_conf(ClientChainType, ServerChainType, ClientChain, ServerChain), + ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ClientChainType)]), + ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ServerChainType)]), + GenCertData = public_key:pkix_test_data(CertChainConf), + [{server_config, ServerConf}, + {client_config, ClientConf}] = + x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase), + {[{verify, verify_peer} | ClientConf], + [{reuseaddr, true}, {verify, verify_peer} | ServerConf] + }. + make_ecdsa_cert(Config) -> CryptoSupport = crypto:supports(), case proplists:get_bool(ecdsa, proplists:get_value(public_keys, CryptoSupport)) of @@ -1468,10 +1505,13 @@ check_key_exchange_send_active(Socket, KeyEx) -> send_recv_result_active(Socket). check_key_exchange({KeyEx,_, _}, KeyEx, _) -> + ct:pal("Kex: ~p", [KeyEx]), true; check_key_exchange({KeyEx,_,_,_}, KeyEx, _) -> + ct:pal("Kex: ~p", [KeyEx]), true; check_key_exchange(KeyEx1, KeyEx2, Version) -> + ct:pal("Kex: ~p ~p", [KeyEx1, KeyEx2]), case Version of 'tlsv1.2' -> v_1_2_check(element(1, KeyEx1), KeyEx2); @@ -1486,6 +1526,11 @@ v_1_2_check(ecdh_ecdsa, ecdh_rsa) -> true; v_1_2_check(ecdh_rsa, ecdh_ecdsa) -> true; +v_1_2_check(ecdhe_ecdsa, ecdhe_rsa) -> + true; +v_1_2_check(ecdhe_rsa, ecdhe_ecdsa) -> + true; + v_1_2_check(_, _) -> false. -- cgit v1.2.3