Skip to content

Commit

Permalink
ssl: Make sure both TLS-1.3 and TLS-1.2 names for signature algorthim…
Browse files Browse the repository at this point in the history
…s are handled

Closes #7264
  • Loading branch information
IngelaAndin committed May 23, 2023
1 parent 8c0ea6b commit 9b792ac
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 26 deletions.
67 changes: 44 additions & 23 deletions lib/ssl/src/ssl_handshake.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1626,7 +1626,7 @@ select_hashsign({ClientHashSigns, ClientSignatureSchemes},
select_hashsign({#hash_sign_algos{hash_sign_algos = ClientHashSigns},
ClientSignatureSchemes0},
Cert, KeyExAlgo, SupportedHashSigns, ?TLS_1_2) ->
ClientSignatureSchemes = get_signature_scheme(ClientSignatureSchemes0),
ClientSignatureSchemes = client_signature_schemes(ClientHashSigns, ClientSignatureSchemes0),
{SignAlgo0, Param, PublicKeyAlgo0, _, _} = get_cert_params(Cert),
SignAlgo = sign_algo(SignAlgo0, Param),
PublicKeyAlgo = ssl_certificate:public_key_type(PublicKeyAlgo0),
Expand All @@ -1647,7 +1647,7 @@ select_hashsign({#hash_sign_algos{hash_sign_algos = ClientHashSigns},
%% If no "signature_algorithms_cert" extension is
%% present, then the "signature_algorithms" extension also applies to
%% signatures appearing in certificates.
case is_supported_sign(SignAlgo, Param, ClientHashSigns, ClientSignatureSchemes) of
case is_supported_sign(SignAlgo, ClientSignatureSchemes) of
true ->
case
(KeyExAlgo == psk) orelse
Expand All @@ -1657,9 +1657,9 @@ select_hashsign({#hash_sign_algos{hash_sign_algos = ClientHashSigns},
(KeyExAlgo == dh_anon) orelse
(KeyExAlgo == ecdhe_anon) of
true ->
ClientHashSigns;
ClientSignatureSchemes;
false ->
do_select_hashsign(ClientHashSigns, PublicKeyAlgo, SupportedHashSigns)
do_select_hashsign(ClientSignatureSchemes, PublicKeyAlgo, SupportedHashSigns)
end;
false ->
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_signature_algorithm)
Expand All @@ -1684,11 +1684,10 @@ select_hashsign(#certificate_request{
SupportedHashSigns,
?TLS_1_2) ->
{SignAlgo0, Param, PublicKeyAlgo0, _, _} = get_cert_params(Cert),
SignAlgo = {_, KeyType} = sign_algo(SignAlgo0, Param),
SignAlgo = sign_algo(SignAlgo0, Param),
PublicKeyAlgo = ssl_certificate:public_key_type(PublicKeyAlgo0),
SignatureSchemes = [Scheme || Scheme <- HashSigns, is_atom(Scheme), (KeyType == rsa_pss_pss) or (KeyType == rsa)],
case is_acceptable_cert_type(PublicKeyAlgo, Types) andalso
is_supported_sign(SignAlgo, Param, HashSigns, SignatureSchemes) of
is_supported_sign(SignAlgo, HashSigns) of
true ->
do_select_hashsign(HashSigns, PublicKeyAlgo, SupportedHashSigns);
false ->
Expand All @@ -1706,23 +1705,44 @@ select_hashsign(#certificate_request{certificate_types = Types}, Cert, _, Versio
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_signature_algorithm)
end.


do_select_hashsign(HashSigns, PublicKeyAlgo, SupportedHashSigns) ->
case lists:filter(fun({H, rsa_pss_pss = S} = Algos) when S == PublicKeyAlgo ->
case lists:filter(fun({H, rsa_pss_pss = S} = Algos) when S == PublicKeyAlgo -> %% Backported from TLS-1.3, but only TLS-1.2 configured
is_acceptable_hash_sign(list_to_existing_atom(atom_to_list(S) ++ "_" ++ atom_to_list(H)), SupportedHashSigns) orelse
is_acceptable_hash_sign(Algos, SupportedHashSigns);
({H, rsa_pss_rsae = S} = Algos) when PublicKeyAlgo == rsa ->
({H, rsa_pss_rsae = S} = Algos) when PublicKeyAlgo == rsa -> %% Backported from TLS-1.3, but only TLS-1.2 configured
is_acceptable_hash_sign(list_to_existing_atom(atom_to_list(S) ++ "_" ++ atom_to_list(H)), SupportedHashSigns) orelse
is_acceptable_hash_sign(Algos, SupportedHashSigns);
({_, S} = Algos) when S == PublicKeyAlgo ->
is_acceptable_hash_sign(Algos, SupportedHashSigns);
(_A) ->
%% Backported or legacy schemes from TLS-1.3 (TLS-1.2 negotiated when TLS-1.3 supported)
(Scheme) when is_atom(Scheme) ->
{H, S, _} = ssl_cipher:scheme_to_components(Scheme),
case S of
rsa_pkcs1 when PublicKeyAlgo == rsa ->
is_acceptable_hash_sign({H, rsa}, SupportedHashSigns) %% TLS-1.2 name
orelse is_acceptable_hash_sign(Scheme, SupportedHashSigns); %% TLS-1.3 legacy name
rsa_pss_rsae when PublicKeyAlgo == rsa_pss_rsae -> %% Backported
is_acceptable_hash_sign(Scheme, SupportedHashSigns);
rsa_pss_rsae when PublicKeyAlgo == rsa_pss_pss -> %% Backported
is_acceptable_hash_sign(Scheme, SupportedHashSigns);
ecdsa when (PublicKeyAlgo == ecdsa) andalso (H == sha) ->
is_acceptable_hash_sign({H, S}, SupportedHashSigns) orelse %% TLS-1.2 name
is_acceptable_hash_sign(Scheme, SupportedHashSigns); %% TLS-1.3 legacy name
_ ->
false
end;
(_) ->
false
end, HashSigns) of
[] ->
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_signature_algorithm);
[HashSign | _] ->
HashSign
case ssl_cipher:scheme_to_components(HashSign) of
{Hash, rsa_pkcs1, _} ->
{Hash, rsa};
{Hash, Sign, _} ->
{Hash, Sign}
end
end.


Expand Down Expand Up @@ -1845,10 +1865,10 @@ select_own_cert([OwnCert| _]) ->
select_own_cert(undefined) ->
undefined.

get_signature_scheme(undefined) ->
[];
get_signature_scheme(#signature_algorithms_cert{
signature_scheme_list = ClientSignatureSchemes}) ->
client_signature_schemes(ClientHashSigns, undefined) ->
ClientHashSigns;
client_signature_schemes(_, #signature_algorithms_cert{
signature_scheme_list = ClientSignatureSchemes}) ->
ClientSignatureSchemes.


Expand Down Expand Up @@ -3470,9 +3490,6 @@ is_acceptable_hash_sign(Algos, SupportedHashSigns) ->
is_acceptable_cert_type(Sign, Types) ->
lists:member(sign_type(Sign), binary_to_list(Types)).

%% signature_algorithms_cert = undefined
is_supported_sign(SignAlgo, _, HashSigns, []) ->
ssl_cipher:is_supported_sign(SignAlgo, HashSigns);
%% {'SignatureAlgorithm',{1,2,840,113549,1,1,11},'NULL'}
%% TODO: Implement validation for the curve used in the signature
%% RFC 3279 - 2.2.3 ECDSA Signature Algorithm
Expand All @@ -3484,13 +3501,17 @@ is_supported_sign(SignAlgo, _, HashSigns, []) ->
%% The elliptic curve parameters in the subjectPublicKeyInfo field of
%% the certificate of the issuer SHALL apply to the verification of the
%% signature.
is_supported_sign({Hash, Sign}, _Param, _, SignatureSchemes) ->
is_supported_sign({Hash, Sign}, SignatureSchemes) ->
Fun = fun (Scheme) ->
{H, S0, _} = ssl_cipher:scheme_to_components(Scheme),
S1 = case S0 of
rsa_pkcs1 -> rsa;
S -> S
end,
rsa_pkcs1 ->
rsa;
rsa_pss_rsae ->
rsa;
S ->
S
end,
(Sign =:= S1) andalso (Hash =:= H)
end,
lists:any(Fun, SignatureSchemes).
Expand Down
2 changes: 1 addition & 1 deletion lib/ssl/test/ssl_handshake_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ signature_algorithms(Config) ->
signature_scheme_list = [rsa_pkcs1_sha256,
ecdsa_sha1]},
{sha512, rsa} = ssl_handshake:select_hashsign(
{HashSigns0, Schemes0},
{HashSigns0, undefined},
Cert, ecdhe_rsa,
tls_v1:default_signature_algs([?TLS_1_2]),
?TLS_1_2),
Expand Down
4 changes: 2 additions & 2 deletions lib/ssl/test/tls_1_3_version_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,13 @@ tls13_client_with_ext_tls12_server(Config) ->
ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),

ServerOpts = [{versions, ['tlsv1.2']}|ServerOpts0],
ServerOpts = [{versions, ['tlsv1.2']}, {signature_algs, [{sha256, ecdsa}, {sha, ecdsa}]}| ServerOpts0],
ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
{signature_algs_cert, [ecdsa_secp384r1_sha384,
ecdsa_secp256r1_sha256,
rsa_pss_rsae_sha256,
rsa_pkcs1_sha256,
{sha256,rsa},{sha256,dsa}]}|ClientOpts0],
ecdsa_sha1]}|ClientOpts0],
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).

tls12_client_tls13_server() ->
Expand Down

0 comments on commit 9b792ac

Please sign in to comment.