From c893b76b45853643ab2acc725d3b2e9da2fb7017 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 30 Sep 2025 13:57:12 +0200 Subject: [PATCH] ssl: For TLS-1.2 cert signature must be compatible with cipher suite. In TLS-1.3 this is negotiated separtly --- lib/ssl/src/ssl_handshake.erl | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index ed647e40c8a3..a347954090bd 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -1159,7 +1159,7 @@ server_select_cert_key_pair_and_params(CipherSuites, [#{private_key := Key, cert no_suite -> server_select_cert_key_pair_and_params(CipherSuites, Rest, HashSigns, ECCCurve0, Opts, Version); CipherSuite0 -> - case is_acceptable_cert(Cert, HashSigns, ssl:tls_version(Version)) of + case is_acceptable_cert(CipherSuite0, Cert, HashSigns, ssl:tls_version(Version)) of true -> CurveAndSuite = cert_curve(Cert, ECCCurve0, CipherSuite0), {Certs, Key, CurveAndSuite}; @@ -1168,16 +1168,36 @@ server_select_cert_key_pair_and_params(CipherSuites, [#{private_key := Key, cert end end. -is_acceptable_cert(Cert, HashSigns, Version) +is_acceptable_cert(CipherSuite, Cert, HashSigns, Version) when ?TLS_1_X(Version), ?TLS_GTE(Version, ?TLS_1_2) -> {SignAlgo0, Param, _, _, _} = get_cert_params(Cert), SignAlgo = sign_algo(SignAlgo0, Param), - is_acceptable_hash_sign(SignAlgo, HashSigns); -is_acceptable_cert(_,_,_) -> + is_acceptable_hash_sign(SignAlgo, acceptable_hash_signs(CipherSuite, HashSigns)); +is_acceptable_cert(_, _,_,_) -> %% Not negotiable pre TLS-1.2. So if cert is available for version it is acceptable true. +acceptable_hash_signs(CipherSuite, HashSigns) -> + #{key_exchange := Kex} = ssl_cipher_format:suite_bin_to_map(CipherSuite), + Filter = fun({_, rsa}) when Kex == ecdh_rsa; + Kex == dhe_rsa; + Kex == srp_rsa; + Kex == rsa -> + true; + ({_, ecdsa}) when Kex == ecdh_ecdsa; + Kex == ecdhe_ecdsa -> + true; + ({_, dsa}) when Kex == dhe_dss; + Kex == srp_dss -> + true; + (_) when Kex == any -> + true; + (_) -> + false + end, + [HS || HS <- HashSigns, Filter(HS)]. + premaster_secret(OtherPublicDhKey, MyPrivateKey, #'DHParameter'{} = Params) -> try public_key:compute_key(OtherPublicDhKey, MyPrivateKey, Params)