From 73b526ce765dc7ac71fdae349da44941d8201d9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Wed, 24 Jul 2019 11:11:07 +0200 Subject: ssl: Implement option honor_cipher_order in TLS 1.3 --- lib/ssl/src/tls_handshake_1_3.erl | 15 ++++++--- lib/ssl/test/ssl_api_SUITE.erl | 64 ++++++++++++++++++++++++++++++++++----- 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl index 6aeb9f5663..c29366e717 100644 --- a/lib/ssl/src/tls_handshake_1_3.erl +++ b/lib/ssl/src/tls_handshake_1_3.erl @@ -504,7 +504,8 @@ do_start(#client_hello{cipher_suites = ClientCiphers, ssl_options = #ssl_options{ciphers = ServerCiphers, signature_algs = ServerSignAlgs, supported_groups = ServerGroups0, - alpn_preferred_protocols = ALPNPreferredProtocols}, + alpn_preferred_protocols = ALPNPreferredProtocols, + honor_cipher_order = HonorCipherOrder}, session = #session{own_certificate = Cert}} = State0) -> ClientGroups0 = maps:get(elliptic_curves, Extensions, undefined), ClientGroups = get_supported_groups(ClientGroups0), @@ -531,7 +532,7 @@ do_start(#client_hello{cipher_suites = ClientCiphers, %% cipher suite, an (EC)DHE group and key share for key establishment, %% and a signature algorithm/certificate pair to authenticate itself to %% the client. - Cipher = Maybe(select_cipher_suite(ClientCiphers, ServerCiphers)), + Cipher = Maybe(select_cipher_suite(HonorCipherOrder, ClientCiphers, ServerCiphers)), Groups = Maybe(select_common_groups(ServerGroups, ClientGroups)), Maybe(validate_client_key_share(ClientGroups, ClientShares)), @@ -1731,15 +1732,19 @@ handle_alpn([ServerProtocol|T], ClientProtocols) -> end. -select_cipher_suite([], _) -> +select_cipher_suite(_, [], _) -> {error, no_suitable_cipher}; -select_cipher_suite([Cipher|ClientCiphers], ServerCiphers) -> +%% If honor_cipher_order is set to true, use the server's preference for +%% cipher suite selection. +select_cipher_suite(true, ClientCiphers, ServerCiphers) -> + select_cipher_suite(false, ServerCiphers, ClientCiphers); +select_cipher_suite(false, [Cipher|ClientCiphers], ServerCiphers) -> case lists:member(Cipher, tls_v1:suites('TLS_v1.3')) andalso lists:member(Cipher, ServerCiphers) of true -> {ok, Cipher}; false -> - select_cipher_suite(ClientCiphers, ServerCiphers) + select_cipher_suite(false, ClientCiphers, ServerCiphers) end. diff --git a/lib/ssl/test/ssl_api_SUITE.erl b/lib/ssl/test/ssl_api_SUITE.erl index a7b2a71690..4b44b4dc3e 100644 --- a/lib/ssl/test/ssl_api_SUITE.erl +++ b/lib/ssl/test/ssl_api_SUITE.erl @@ -127,7 +127,9 @@ beast_mitigation_test() -> tls13_group() -> [ - supported_groups + supported_groups, + honor_server_cipher_order_tls13, + honor_client_cipher_order_tls13 ]. @@ -1198,11 +1200,35 @@ honor_server_cipher_order(Config) when is_list(Config) -> cipher => aes_128_cbc, mac => sha, prf => default_prf}], - honor_cipher_order(Config, true, ServerCiphers, ClientCiphers, #{key_exchange => dhe_rsa, - cipher => aes_256_cbc, + honor_cipher_order(Config, true, ServerCiphers, ClientCiphers, #{key_exchange => dhe_rsa, + cipher => aes_256_cbc, mac => sha, prf => default_prf}). %%-------------------------------------------------------------------- +honor_server_cipher_order_tls13() -> + [{doc,"Test API honor server cipher order in TLS 1.3."}]. +honor_server_cipher_order_tls13(Config) when is_list(Config) -> + ClientCiphers = [#{key_exchange => any, + cipher => aes_256_gcm, + mac => aead, + prf => sha384}, + #{key_exchange => any, + cipher => aes_128_gcm, + mac => aead, + prf => sha256}], + ServerCiphers = [#{key_exchange => any, + cipher => aes_128_gcm, + mac => aead, + prf => sha256}, + #{key_exchange => any, + cipher => aes_256_gcm, + mac => aead, + prf => sha384}], + honor_cipher_order(Config, true, ServerCiphers, ClientCiphers, #{key_exchange => any, + cipher => aes_128_gcm, + mac => aead, + prf => sha256}). +%%-------------------------------------------------------------------- honor_client_cipher_order() -> [{doc,"Test API honor server cipher order."}]. honor_client_cipher_order(Config) when is_list(Config) -> @@ -1222,10 +1248,34 @@ honor_client_cipher_order(Config) when is_list(Config) -> 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, false, ServerCiphers, ClientCiphers, #{key_exchange => dhe_rsa, + cipher => aes_128_cbc, + mac => sha, + prf => default_prf}). +%%-------------------------------------------------------------------- +honor_client_cipher_order_tls13() -> + [{doc,"Test API honor server cipher order in TLS 1.3."}]. +honor_client_cipher_order_tls13(Config) when is_list(Config) -> + ClientCiphers = [#{key_exchange => any, + cipher => aes_256_gcm, + mac => aead, + prf => sha384}, + #{key_exchange => any, + cipher => aes_128_gcm, + mac => aead, + prf => sha256}], + ServerCiphers = [#{key_exchange => any, + cipher => aes_128_gcm, + mac => aead, + prf => sha256}, + #{key_exchange => any, + cipher => aes_256_gcm, + mac => aead, + prf => sha384}], + honor_cipher_order(Config, false, ServerCiphers, ClientCiphers, #{key_exchange => any, + cipher => aes_256_gcm, + mac => aead, + prf => sha384}). %%-------------------------------------------------------------------- ipv6() -> [{require, ipv6_hosts}, -- cgit v1.2.3