File 4002-ssl-public_key-Adjust-handling-of-extended-key-usage.patch of Package erlang
From 4c8c99b74bd84cc4460c50be982c22607d456e0b Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin <ingela@erlang.org>
Date: Tue, 29 Aug 2023 08:26:28 +0200
Subject: [PATCH 2/2] ssl, public_key: Adjust handling of extended key usage
certificate extension
This extension is in general found in end entity certificates, but can apper
in CA certificates. See RFC 5280.
ssl application will validate id-kp-serverAuth and id-kp-clientAuth
in end entity certificates.
---
lib/public_key/src/pubkey_cert.erl | 11 ++-------
lib/ssl/src/ssl_certificate.erl | 24 +++++++++----------
lib/ssl/src/ssl_handshake.erl | 4 +++-
lib/ssl/src/tls_handshake_1_3.erl | 38 ++++++++++++++++--------------
4 files changed, 37 insertions(+), 40 deletions(-)
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index cb1ddbfa05..78dccd6a5c 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -73,7 +73,6 @@
file_to_certificats/2,
file_to_crls/2,
validate/3,
- is_valid_extkey_usage/2,
is_valid_key_usage/2,
select_extension/2,
extensions_list/1,
@@ -204,7 +203,8 @@ file_to_crls(File, DbHandle) ->
%%--------------------------------------------------------------------
validate(_,{extension, #'Extension'{extnID = ?'id-ce-extKeyUsage',
critical = Critical,
- extnValue = KeyUse}}, #{pathlen := 1} = UserState) ->
+ extnValue = KeyUse}}, #{path_len := 1} = UserState) ->
+ %% If extension in peer, check for TLS server/client usage
case is_valid_extkey_usage(KeyUse, Critical, UserState) of
true ->
{valid, UserState};
@@ -217,14 +217,14 @@ validate(Issuer, {bad_cert, cert_expired}, #{issuer := Issuer}) ->
{fail, {bad_cert, root_cert_expired}};
validate(_, {bad_cert, _} = Reason, _) ->
{fail, Reason};
-validate(Cert, valid, #{pathlen := N} = UserState) ->
+validate(Cert, valid, #{path_len := N} = UserState) ->
case verify_sign(Cert, UserState) of
true ->
case maps:get(cert_ext, UserState, undefined) of
undefined ->
- {valid, UserState#{pathlen => N-1}};
+ {valid, UserState#{path_len => N-1}};
_ ->
- verify_cert_extensions(Cert, UserState#{pathlen => N -1})
+ verify_cert_extensions(Cert, UserState#{path_len => N-1})
end;
false ->
{fail, {bad_cert, invalid_signature}}
@@ -495,19 +495,19 @@ do_find_issuer(IssuerFun, CertDbHandle, CertDb) ->
Return
end.
-is_valid_extkey_usage(KeyUse, true, #{role := Role, pathlen := 1}) when is_list(KeyUse) ->
- is_valid_key_usage(ext_keysage(Role), KeyUse);
-is_valid_key_usage(KeyUse, true, #{role := Role, pathlen := 1}) ->
- is_valid_key_usage(ext_keysage(Role), [KeyUse]);
-is_valid_key_usage(_, false, _) ->
+is_valid_extkey_usage(KeyUse, true, #{role := Role}) when is_list(KeyUse) ->
+ is_valid_key_usage(KeyUse, ext_keysage(Role));
+is_valid_extkey_usage(KeyUse, true, #{role := Role}) ->
+ is_valid_key_usage([KeyUse], ext_keysage(Role));
+is_valid_extkey_usage(_, false, _) ->
false.
ext_keysage(client) ->
%% Client wants to verify server
- ?'id-kp-serverAuth'.
+ ?'id-kp-serverAuth';
ext_keysage(server) ->
%% Server wants to verify client
- ?'id-kp-serverAuth'.
+ ?'id-kp-clientAuth'.
verify_cert_signer(BinCert, SignerTBSCert) ->
PublicKey = public_key(SignerTBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo),
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 56a1ca81b9..04601dfbf2 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -3879,7 +3879,9 @@ path_validation(TrustedCert, Path, ServerName, Role, CertDbHandle, CertDbRef, CR
cert_ext => CertExt,
issuer => TrustedCert,
ocsp_responder_certs => OcspResponderCerts,
- ocsp_state => OcspState},
+ ocsp_state => OcspState,
+ path_len => length(Path)
+ },
Path, Level),
Options = [{max_path_length, Depth},
{verify_fun, ValidationFunAndState}],
diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl
index 750a79887f..34690ef9dd 100644
--- a/lib/ssl/src/tls_handshake_1_3.erl
+++ b/lib/ssl/src/tls_handshake_1_3.erl
@@ -2943,24 +2943,26 @@ path_validation(TrustedCert, Path, ServerName, Role, CertDbHandle, CertDbRef, CR
#{cert_ext := CertExt,
ocsp_responder_certs := OcspResponderCerts,
ocsp_state := OcspState}) ->
- ValidationFunAndState =
- ssl_handshake:validation_fun_and_state(VerifyFun, #{role => Role,
- certdb => CertDbHandle,
- certdb_ref => CertDbRef,
- server_name => ServerName,
- customize_hostname_check =>
- CustomizeHostnameCheck,
- crl_check => CrlCheck,
- crl_db => CRLDbHandle,
- signature_algs => filter_tls13_algs(SignAlgos),
- signature_algs_cert =>
- filter_tls13_algs(SignAlgosCert),
- version => Version,
- issuer => TrustedCert,
- cert_ext => CertExt,
- ocsp_responder_certs => OcspResponderCerts,
- ocsp_state => OcspState
- },
+ ValidationFunAndState =
+ ssl_handshake:validation_fun_and_state(VerifyFun,
+ #{role => Role,
+ certdb => CertDbHandle,
+ certdb_ref => CertDbRef,
+ server_name => ServerName,
+ customize_hostname_check =>
+ CustomizeHostnameCheck,
+ crl_check => CrlCheck,
+ crl_db => CRLDbHandle,
+ signature_algs => filter_tls13_algs(SignAlgos),
+ signature_algs_cert =>
+ filter_tls13_algs(SignAlgosCert),
+ version => Version,
+ issuer => TrustedCert,
+ cert_ext => CertExt,
+ ocsp_responder_certs => OcspResponderCerts,
+ ocsp_state => OcspState,
+ path_len => length(Path)
+ },
Path, LogLevel),
Options = [{max_path_length, Depth},
{verify_fun, ValidationFunAndState}],
--
2.35.3