File 3171-ssl-public_key-Extended-key-extension-handling.patch of Package erlang

From e7cd7fc40973493096f1582ae9089d87a7e88991 Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin <ingela@erlang.org>
Date: Mon, 28 Aug 2023 15:48:34 +0200
Subject: [PATCH 1/2] ssl, public_key: Extended key extension handling

---
 lib/public_key/src/pubkey_cert.erl       | 27 ++++++++++++++++++++
 lib/public_key/test/public_key_SUITE.erl | 32 ++++++++++++++++++++++++
 lib/ssl/src/ssl_certificate.erl          | 30 ++++++++++++++--------
 3 files changed, 78 insertions(+), 11 deletions(-)

diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl
index 4d448fd42c..39084f3e76 100644
--- a/lib/public_key/src/pubkey_cert.erl
+++ b/lib/public_key/src/pubkey_cert.erl
@@ -905,6 +905,27 @@ validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-policyConstraints',
     validate_extensions(OtpCert, Rest, NewValidationState, ExistBasicCon,
 			SelfSigned, UserState, VerifyFun);
 
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-extKeyUsage',
+                                           critical = true,
+                                           extnValue = KeyUse} = Extension | Rest],
+		    ValidationState#path_validation_state{last_cert = false}, ExistBasicCon,
+		    SelfSigned, UserState0, VerifyFun) ->
+    UserState =
+        case ext_keyusage_includes_any(KeyUse) of
+            true -> %% CA cert that specifies ?anyExtendedKeyUsage should not be marked critical
+                verify_fun(OtpCert, {bad_cert, invalid_ext_key_usage}, UserState0, VerifyFun);
+            false ->
+                verify_fun(OtpCert, {extension, Extension}, UserState0, VerifyFun);
+        end,
+    validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon, SelfSigned,
+			UserState, VerifyFun);
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-extKeyUsage',
+                                           extnValue = KeyUse} = Extension | Rest],
+		    ValidationState, ExistBasicCon,
+		    SelfSigned, UserState0, VerifyFun) ->
+    UserState = verify_fun(OtpCert, {extension, Ext}, UserState0, VerifyFun),
+    validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon, SelfSigned,
+                        UserState, VerifyFun);
 validate_extensions(OtpCert, [#'Extension'{} = Extension | Rest],
 		    ValidationState, ExistBasicCon,
 		    SelfSigned, UserState0, VerifyFun) ->
@@ -1483,3 +1504,9 @@ verify_options(#'RSASSA-PSS-params'{saltLength = SaltLen,
     [{rsa_padding, rsa_pkcs1_pss_padding},
      {rsa_pss_saltlen, SaltLen},
      {rsa_mgf1_md, HashAlgo}].
+
+
+ext_keyusage_includes_any(KeyUse) when is_list(KeyUse) ->
+    lists:member(?anyExtendedKeyUsage, KeyUse);
+ext_keyusage_includes_any(_) ->
+    false.
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index 1a779e03bd..0edf3d29c6 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -95,6 +95,8 @@
          pkix_path_validation/1,
          pkix_path_validation_root_expired/0,
          pkix_path_validation_root_expired/1,
+         pkix_ext_key_usage/0,
+         pkix_ext_key_usage/1,
          pkix_verify_hostname_cn/1,
          pkix_verify_hostname_subjAltName/1,
          pkix_verify_hostname_options/1,
@@ -154,6 +156,7 @@ all() ->
      pkix_decode_cert,
      pkix_path_validation,
      pkix_path_validation_root_expired,
+     pkix_ext_key_usage,
      pkix_iso_rsa_oid, 
      pkix_iso_dsa_oid, 
      pkix_rsa_md2_oid,
@@ -927,6 +930,35 @@ pkix_path_validation_root_expired(Config) when is_list(Config) ->
     Peer = proplists:get_value(cert, Conf),
     {error, {bad_cert, cert_expired}} = public_key:pkix_path_validation(Root, [ICA, Peer], []).
     
+pkix_ext_key_usage() ->
+    [{doc, "Extended key usage is usually in end entity certs, may be in CA but should not be critical in such case"}].
+pkix_ext_key_usage(Config) when is_list(Config) ->
+    SRootSpec = public_key:pkix_test_root_cert("OTP test server ROOT", []),
+    CRootSpec = public_key:pkix_test_root_cert("OTP test client ROOT", []),
+
+    FailCAExt = [#'Extension'{extnID = ?'id-ce-extKeyUsage',
+                              extnValue = [?'anyExtendedKeyUsage'],
+                              critical = true}],
+    CAExt = [#'Extension'{extnID = ?'id-ce-extKeyUsage',
+                          extnValue = [?'anyExtendedKeyUsage'],
+                          critical = false}],
+
+    #{server_config := SConf,
+      client_config := CConf} = public_key:pkix_test_data(#{server_chain => #{root => SRootSpec,
+                                                                             intermediates => [[{extensions, FailCAExt}]],
+                                                                             peer => []},
+                                                           client_chain => #{root => CRootSpec,
+                                                                             intermediates => [[{extensions, CAExt}]],
+                                                                             peer => []}}),
+    [_STRoot, SICA, SRoot] = proplists:get_value(cacerts, SConf),
+    [_CTRoot, CICA, CRoot] = proplists:get_value(cacerts, CConf),
+    SPeer = proplists:get_value(cert, SConf),
+    CPeer = proplists:get_value(cert, CConf),
+
+    {error, {bad_cert, invalid_ext_key_usage}} = public_key:pkix_path_validation(SRoot, [SICA, SPeer], []),
+
+    {ok, _} = public_key:pkix_path_validation(CRoot, [CICA, CPeer], []).
+
 %%--------------------------------------------------------------------
 %% To generate the PEM file contents:
 %%
-- 
2.35.3

openSUSE Build Service is sponsored by