Skip to content

Commit

Permalink
ssl: Backport cert_auth exclusion option to pre TLS-1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
IngelaAndin committed Oct 29, 2024
1 parent 44ffe88 commit 3174c08
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 13 deletions.
13 changes: 11 additions & 2 deletions lib/ssl/src/ssl.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1776,6 +1776,11 @@ Certificate related options for a server.
certificate request message that is sent when the option `verify` is set to
`verify_peer`. Defaults to `true`.
If set to `false` for older TLS versions its corresponding certificate authorities
defenition in its certificate request will be set to the empty list instead of
including the appropriate certificate authorities. This has the same affect
as excluding the TLS-1.3 extension.
A reason to exclude the extension would be if the server wants to communicate
with clients incapable of sending complete certificate chains that adhere to the
extension, but the server still has the capability to recreate a chain that it
Expand Down Expand Up @@ -4080,8 +4085,12 @@ opt_cacerts(UserOpts, #{verify := Verify, log_level := LogLevel, versions := Ver
[{verify, verify_peer}, {cacerts, undefined}]),

{Where2, CA} = get_opt_bool(certificate_authorities, Role =:= server, UserOpts, Opts),
assert_version_dep(Where2 =:= new, certificate_authorities, Versions, ['tlsv1.3']),

case Role of
server ->
assert_version_dep(Where2 =:= new, certificate_authorities, Versions, ['tlsv1.3', 'tlsv1.2', 'tlsv1.1', 'tlsv1']);
client ->
assert_version_dep(Where2 =:= new, certificate_authorities, Versions, ['tlsv1.3'])
end,
Opts1 = set_opt_new(new, cacertfile, <<>>, CaCertFile, Opts),
Opts2 = set_opt_new(Where2, certificate_authorities, Role =:= server, CA, Opts1),
Opts2#{cacerts => CaCerts}.
Expand Down
24 changes: 15 additions & 9 deletions lib/ssl/src/ssl_handshake.erl
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
server_hello_done/0,
certificate/4,
client_certificate_verify/6,
certificate_request/4,
certificate_request/5,
key_exchange/3,
finished/5,
next_protocol/1,
Expand Down Expand Up @@ -219,19 +219,25 @@ client_certificate_verify([OwnCert|_], MasterSecret, Version,

%%--------------------------------------------------------------------
-spec certificate_request(ssl_manager:db_handle(),
ssl_manager:certdb_ref(), #hash_sign_algos{}, ssl_record:ssl_version()) ->
#certificate_request{}.
ssl_manager:certdb_ref(), #hash_sign_algos{},
ssl_record:ssl_version(), boolean()) ->
#certificate_request{}.
%%
%% Description: Creates a certificate_request message, called by the server.
%%--------------------------------------------------------------------
certificate_request(CertDbHandle, CertDbRef, HashSigns, Version) ->
certificate_request(CertDbHandle, CertDbRef, HashSigns, Version, IncludeCertAuths) ->
Types = certificate_types(Version),
Authorities = certificate_authorities(CertDbHandle, CertDbRef),
Authorities = case IncludeCertAuths of
true ->
certificate_authorities(CertDbHandle, CertDbRef);
false ->
[]
end,
#certificate_request{
certificate_types = Types,
hashsign_algorithms = HashSigns,
certificate_authorities = Authorities
}.
certificate_types = Types,
hashsign_algorithms = HashSigns,
certificate_authorities = Authorities
}.
%%--------------------------------------------------------------------
-spec key_exchange(client | server, ssl_record:ssl_version(),
{premaster_secret, binary(), public_key_info()} |
Expand Down
3 changes: 2 additions & 1 deletion lib/ssl/src/tls_dtls_server_connection.erl
Original file line number Diff line number Diff line change
Expand Up @@ -660,8 +660,9 @@ request_client_cert(#state{static_env = #static_env{cert_db = CertDbHandle,
TLSVersion = ssl:tls_version(Version),
HashSigns = ssl_handshake:available_signature_algs(SupportedHashSigns,
TLSVersion),
IncludeCertAuths = maps:get(certificate_authorities, Opts, true),
Msg = ssl_handshake:certificate_request(CertDbHandle, CertDbRef,
HashSigns, TLSVersion),
HashSigns, TLSVersion, IncludeCertAuths),
#state{handshake_env = HsEnv0} = State = Connection:queue_handshake(Msg, State0),
HsEnv = HsEnv0#handshake_env{client_certificate_status = requested},
State#state{handshake_env = HsEnv};
Expand Down
1 change: 1 addition & 0 deletions lib/ssl/test/ssl_api_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2772,6 +2772,7 @@ options_certificate_authorities(_Config) ->
?OK(#{certificate_authorities := true}, [{certificate_authorities, true}], client),
?OK(#{}, [{certificate_authorities, false}], client, [certificate_authorities]),
?OK(#{certificate_authorities := false}, [{certificate_authorities, false}], server),
?OK(#{certificate_authorities := false}, [{certificate_authorities, false}, {versions, ['tlsv1.2']}], server),
?OK(#{}, [{certificate_authorities, true}], server, [certificate_authorities]),

%% Errors
Expand Down
18 changes: 17 additions & 1 deletion lib/ssl/test/ssl_cert_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@
signature_algorithms_bad_curve_secp521r1/1,
server_certificate_authorities_disabled/0,
server_certificate_authorities_disabled/1,
legacy_server_certificate_authorities_disabled/0,
legacy_server_certificate_authorities_disabled/1,
cert_auth_in_first_ca/0,
cert_auth_in_first_ca/1
]).
Expand Down Expand Up @@ -207,7 +209,8 @@ tls_1_3_tests() ->

pre_tls_1_3_rsa_tests() ->
[
key_auth_ext_sign_only
key_auth_ext_sign_only,
legacy_server_certificate_authorities_disabled
].

rsa_tests() ->
Expand Down Expand Up @@ -1405,6 +1408,19 @@ server_certificate_authorities_disabled(Config) ->
ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required),
ssl_test_lib:basic_test(ClientOpts, [{certificate_authorities, false} | ServerOpts], Config).

%%--------------------------------------------------------------------
legacy_server_certificate_authorities_disabled() ->
[{doc,"Test that code pre TLS-1.3 can send an empty list for certificate authorities in the certificate request"
"will be run and not fail, black box verification is not possible without strict legacy client, but code coverage will show that right thing happens"}].

legacy_server_certificate_authorities_disabled(Config) ->
Version = proplists:get_value(version,Config),
ClientOpts = ssl_test_lib:ssl_options(client_cert_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_cert_opts, Config),
ssl_test_lib:basic_test([{versions, [Version]} | ClientOpts], [{versions, [Version]}, {verify, verify_peer},
{fail_if_no_peer_cert, true},
{certificate_authorities, false} | ServerOpts], Config).

%%--------------------------------------------------------------------
%% Internal functions -----------------------------------------------
%%--------------------------------------------------------------------
Expand Down

0 comments on commit 3174c08

Please sign in to comment.