From 45b6afd71bbb7c4b9a0678067bbb7f9276be5605 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 13 Jan 2016 22:04:00 +0100 Subject: ssl: Handle incomplete and unorded chains If the peer sends an incomplete chain that we can reconstruct with our known CA-certs it will be accepted. We will assume that the peer honors the protocol and sends an orded chain, however if validation fails we will try to order the chain in case it was unorded. Will also handle that extraneous cert where present. See Note form RFC 8446 Note: Prior to TLS 1.3, "certificate_list" ordering required each certificate to certify the one immediately preceding it; however, some implementations allowed some flexibility. Servers sometimes send both a current and deprecated intermediate for transitional purposes, and others are simply configured incorrectly, but these cases can nonetheless be validated properly. For maximum compatibility, all implementations SHOULD be prepared to handle potentially extraneous certificates and arbitrary orderings from any TLS version, with the exception of the end-entity certificate which MUST be first. --- lib/ssl/test/ssl_handshake_SUITE.erl | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'lib/ssl/test/ssl_handshake_SUITE.erl') diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl index 9ae04184e2..b8b9989d30 100644 --- a/lib/ssl/test/ssl_handshake_SUITE.erl +++ b/lib/ssl/test/ssl_handshake_SUITE.erl @@ -40,7 +40,8 @@ all() -> [decode_hello_handshake, decode_single_hello_sni_extension_correctly, decode_empty_server_sni_correctly, select_proper_tls_1_2_rsa_default_hashsign, - ignore_hassign_extension_pre_tls_1_2]. + ignore_hassign_extension_pre_tls_1_2, + unorded_chain]. %%-------------------------------------------------------------------- init_per_suite(Config) -> @@ -173,6 +174,29 @@ ignore_hassign_extension_pre_tls_1_2(Config) -> {md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,2}), {3,2}), {md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,0}), {3,0}). +unorded_chain(Config) when is_list(Config) -> + DefConf = ssl_test_lib:default_cert_chain_conf(), + CertChainConf = ssl_test_lib:gen_conf(rsa, rsa, DefConf, DefConf), + #{server_config := ServerConf, + client_config := _ClientConf} = public_key:pkix_test_data(CertChainConf), + PeerCert = proplists:get_value(cert, ServerConf), + CaCerts = [_, C1, C2] = proplists:get_value(cacerts, ServerConf), + {ok, ExtractedCerts} = ssl_pkix_db:extract_trusted_certs({der, CaCerts}), + UnordedChain = case public_key:pkix_is_self_signed(C1) of + true -> + [C1, C2]; + false -> + [C2, C1] + end, + OrderedChain = [PeerCert | lists:reverse(UnordedChain)], + {ok, _, OrderedChain} = + ssl_certificate:certificate_chain(PeerCert, ets:new(foo, []), ExtractedCerts, UnordedChain). + + +%%-------------------------------------------------------------------- +%% Internal functions ------------------------------------------------ +%%-------------------------------------------------------------------- + is_supported(Hash) -> Algos = crypto:supports(), Hashs = proplists:get_value(hashs, Algos), -- cgit v1.2.3