432cfa2
From b4f8964ad1903e24cd2ee07f42ce97c3047f4af4 Mon Sep 17 00:00:00 2001
432cfa2
From: Clemens Lang <cllang@redhat.com>
432cfa2
Date: Mon, 21 Feb 2022 17:24:44 +0100
432cfa2
Subject: [PATCH] Allow disabling of SHA1 signatures
432cfa2
MIME-Version: 1.0
432cfa2
Content-Type: text/plain; charset=UTF-8
432cfa2
Content-Transfer-Encoding: 8bit
432cfa2
432cfa2
NOTE: This patch is ported from CentOS 9 / RHEL 9, where it defaults to
432cfa2
denying SHA1 signatures. On Fedora, the default is – for now – to allow
432cfa2
SHA1 signatures.
432cfa2
432cfa2
In order to phase out SHA1 signatures, introduce a new configuration
432cfa2
option in the alg_section named 'rh-allow-sha1-signatures'. This option
432cfa2
defaults to true. If set to false, any signature creation or
432cfa2
verification operations that involve SHA1 as digest will fail.
432cfa2
432cfa2
This also affects TLS, where the signature_algorithms extension of any
432cfa2
ClientHello message sent by OpenSSL will no longer include signatures
432cfa2
with the SHA1 digest if rh-allow-sha1-signatures is false. For servers
432cfa2
that request a client certificate, the same also applies for
432cfa2
CertificateRequest messages sent by them.
432cfa2
432cfa2
For signatures created using the EVP_PKEY API, this is a best-effort
432cfa2
check that will deny signatures in cases where the digest algorithm is
432cfa2
known. This means, for example, that that following steps will still
432cfa2
work:
432cfa2
432cfa2
 $> openssl dgst -sha1 -binary -out sha1 infile
432cfa2
 $> openssl pkeyutl -inkey key.pem -sign -in sha1 -out sha1sig
432cfa2
 $> openssl pkeyutl -inkey key.pem -verify -sigfile sha1sig -in sha1
432cfa2
432cfa2
whereas these will not:
432cfa2
432cfa2
 $> openssl dgst -sha1 -binary -out sha1 infile
432cfa2
 $> openssl pkeyutl -inkey kem.pem -sign -in sha1 -out sha1sig -pkeyopt digest:sha1
432cfa2
 $> openssl pkeyutl -inkey kem.pem -verify -sigfile sha1sig -in sha1 -pkeyopt digest:sha1
432cfa2
432cfa2
This happens because in the first case, OpenSSL's signature
432cfa2
implementation does not know that it is signing a SHA1 hash (it could be
432cfa2
signing arbitrary data).
432cfa2
---
432cfa2
 crypto/evp/evp_cnf.c                          | 13 +++
432cfa2
 crypto/evp/m_sigver.c                         | 85 +++++++++++++++++++
432cfa2
 crypto/evp/pmeth_lib.c                        | 15 ++++
432cfa2
 doc/man5/config.pod                           | 13 +++
432cfa2
 include/internal/cryptlib.h                   |  3 +-
432cfa2
 include/internal/sslconf.h                    |  4 +
432cfa2
 providers/common/securitycheck.c              | 20 +++++
432cfa2
 providers/common/securitycheck_default.c      |  9 +-
432cfa2
 providers/implementations/signature/dsa_sig.c | 11 ++-
432cfa2
 .../implementations/signature/ecdsa_sig.c     |  4 +
432cfa2
 providers/implementations/signature/rsa_sig.c | 20 ++++-
432cfa2
 ssl/t1_lib.c                                  |  8 ++
432cfa2
 util/libcrypto.num                            |  2 +
432cfa2
 13 files changed, 198 insertions(+), 9 deletions(-)
432cfa2
432cfa2
diff --git a/crypto/evp/evp_cnf.c b/crypto/evp/evp_cnf.c
432cfa2
index 0e7fe64cf9..b9d3b6d226 100644
432cfa2
--- a/crypto/evp/evp_cnf.c
432cfa2
+++ b/crypto/evp/evp_cnf.c
432cfa2
@@ -10,6 +10,7 @@
432cfa2
 #include <stdio.h>
432cfa2
 #include <openssl/crypto.h>
432cfa2
 #include "internal/cryptlib.h"
432cfa2
+#include "internal/sslconf.h"
432cfa2
 #include <openssl/conf.h>
432cfa2
 #include <openssl/x509.h>
432cfa2
 #include <openssl/x509v3.h>
432cfa2
@@ -57,6 +58,18 @@ static int alg_module_init(CONF_IMODULE *md, const CONF *cnf)
432cfa2
                 ERR_raise(ERR_LIB_EVP, EVP_R_SET_DEFAULT_PROPERTY_FAILURE);
432cfa2
                 return 0;
432cfa2
             }
432cfa2
+        } else if (strcmp(oval->name, "rh-allow-sha1-signatures") == 0) {
432cfa2
+            int m;
432cfa2
+
432cfa2
+            /* Detailed error already reported. */
432cfa2
+            if (!X509V3_get_value_bool(oval, &m))
432cfa2
+                return 0;
432cfa2
+
432cfa2
+            if (!ossl_ctx_legacy_digest_signatures_allowed_set(
432cfa2
+                    NCONF_get0_libctx((CONF *)cnf), m > 0, 0)) {
432cfa2
+                ERR_raise(ERR_LIB_EVP, EVP_R_SET_DEFAULT_PROPERTY_FAILURE);
432cfa2
+                return 0;
432cfa2
+            }
432cfa2
         } else {
432cfa2
             ERR_raise_data(ERR_LIB_EVP, EVP_R_UNKNOWN_OPTION,
432cfa2
                            "name=%s, value=%s", oval->name, oval->value);
432cfa2
diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c
432cfa2
index 76a6814b42..8da2183ce0 100644
432cfa2
--- a/crypto/evp/m_sigver.c
432cfa2
+++ b/crypto/evp/m_sigver.c
432cfa2
@@ -16,6 +16,79 @@
432cfa2
 #include "internal/numbers.h"   /* includes SIZE_MAX */
432cfa2
 #include "evp_local.h"
432cfa2
 
432cfa2
+typedef struct ossl_legacy_digest_signatures_st {
432cfa2
+    int allowed;
432cfa2
+} OSSL_LEGACY_DIGEST_SIGNATURES;
432cfa2
+
432cfa2
+static void ossl_ctx_legacy_digest_signatures_free(void *vldsigs)
432cfa2
+{
432cfa2
+    OSSL_LEGACY_DIGEST_SIGNATURES *ldsigs = vldsigs;
432cfa2
+
432cfa2
+    if (ldsigs != NULL) {
432cfa2
+        OPENSSL_free(ldsigs);
432cfa2
+    }
432cfa2
+}
432cfa2
+
432cfa2
+static void *ossl_ctx_legacy_digest_signatures_new(OSSL_LIB_CTX *ctx)
432cfa2
+{
432cfa2
+    OSSL_LEGACY_DIGEST_SIGNATURES* ldsigs = OPENSSL_zalloc(sizeof(OSSL_LEGACY_DIGEST_SIGNATURES));
432cfa2
+    /* Warning: This patch differs from the same patch in CentOS and RHEL here,
432cfa2
+     * because the default on Fedora is to allow SHA-1 and support disabling
432cfa2
+     * it, while CentOS/RHEL disable it by default and allow enabling it. */
432cfa2
+    ldsigs->allowed = 1;
432cfa2
+    return ldsigs;
432cfa2
+}
432cfa2
+
432cfa2
+static const OSSL_LIB_CTX_METHOD ossl_ctx_legacy_digest_signatures_method = {
432cfa2
+    OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
432cfa2
+    ossl_ctx_legacy_digest_signatures_new,
432cfa2
+    ossl_ctx_legacy_digest_signatures_free,
432cfa2
+};
432cfa2
+
432cfa2
+static OSSL_LEGACY_DIGEST_SIGNATURES *ossl_ctx_legacy_digest_signatures(
432cfa2
+        OSSL_LIB_CTX *libctx, int loadconfig)
432cfa2
+{
432cfa2
+#ifndef FIPS_MODULE
432cfa2
+    if (loadconfig && !OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL))
432cfa2
+        return NULL;
432cfa2
+#endif
432cfa2
+
432cfa2
+    return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_LEGACY_DIGEST_SIGNATURES,
432cfa2
+                                 &ossl_ctx_legacy_digest_signatures_method);
432cfa2
+}
432cfa2
+
432cfa2
+int ossl_ctx_legacy_digest_signatures_allowed(OSSL_LIB_CTX *libctx, int loadconfig)
432cfa2
+{
432cfa2
+    OSSL_LEGACY_DIGEST_SIGNATURES *ldsigs
432cfa2
+        = ossl_ctx_legacy_digest_signatures(libctx, loadconfig);
432cfa2
+
432cfa2
+#ifndef FIPS_MODULE
432cfa2
+    if (ossl_safe_getenv("OPENSSL_ENABLE_SHA1_SIGNATURES") != NULL)
432cfa2
+        /* used in tests */
432cfa2
+        return 1;
432cfa2
+#endif
432cfa2
+
432cfa2
+    /* Warning: This patch differs from the same patch in CentOS and RHEL here,
432cfa2
+     * because the default on Fedora is to allow SHA-1 and support disabling
432cfa2
+     * it, while CentOS/RHEL disable it by default and allow enabling it. */
432cfa2
+    return ldsigs != NULL ? ldsigs->allowed : 1;
432cfa2
+}
432cfa2
+
432cfa2
+int ossl_ctx_legacy_digest_signatures_allowed_set(OSSL_LIB_CTX *libctx, int allow,
432cfa2
+                                                  int loadconfig)
432cfa2
+{
432cfa2
+    OSSL_LEGACY_DIGEST_SIGNATURES *ldsigs
432cfa2
+        = ossl_ctx_legacy_digest_signatures(libctx, loadconfig);
432cfa2
+
432cfa2
+    if (ldsigs == NULL) {
432cfa2
+        ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
432cfa2
+        return 0;
432cfa2
+    }
432cfa2
+
432cfa2
+    ldsigs->allowed = allow;
432cfa2
+    return 1;
432cfa2
+}
432cfa2
+
432cfa2
 #ifndef FIPS_MODULE
432cfa2
 
432cfa2
 static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen)
432cfa2
@@ -258,6 +331,18 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
432cfa2
         }
432cfa2
     }
432cfa2
 
432cfa2
+    if (ctx->reqdigest != NULL
432cfa2
+            && !EVP_PKEY_is_a(locpctx->pkey, SN_hmac)
432cfa2
+            && !EVP_PKEY_is_a(locpctx->pkey, SN_tls1_prf)
432cfa2
+            && !EVP_PKEY_is_a(locpctx->pkey, SN_hkdf)) {
432cfa2
+        int mdnid = EVP_MD_nid(ctx->reqdigest);
432cfa2
+        if (!ossl_ctx_legacy_digest_signatures_allowed(locpctx->libctx, 0)
432cfa2
+                && (mdnid == NID_sha1 || mdnid == NID_md5_sha1)) {
432cfa2
+            ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_DIGEST);
432cfa2
+            goto err;
432cfa2
+        }
432cfa2
+    }
432cfa2
+
432cfa2
     if (ver) {
432cfa2
         if (signature->digest_verify_init == NULL) {
432cfa2
             ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
432cfa2
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
432cfa2
index 2b9c6c2351..3c5a1e6f5d 100644
432cfa2
--- a/crypto/evp/pmeth_lib.c
432cfa2
+++ b/crypto/evp/pmeth_lib.c
432cfa2
@@ -33,6 +33,7 @@
432cfa2
 #include "internal/ffc.h"
432cfa2
 #include "internal/numbers.h"
432cfa2
 #include "internal/provider.h"
432cfa2
+#include "internal/sslconf.h"
432cfa2
 #include "evp_local.h"
432cfa2
 
432cfa2
 #ifndef FIPS_MODULE
432cfa2
@@ -946,6 +947,20 @@ static int evp_pkey_ctx_set_md(EVP_PKEY_CTX *ctx, const EVP_MD *md,
432cfa2
         return -2;
432cfa2
     }
432cfa2
 
432cfa2
+    if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
432cfa2
+            && md != NULL
432cfa2
+            && ctx->pkey != NULL
432cfa2
+            && !EVP_PKEY_is_a(ctx->pkey, SN_hmac)
432cfa2
+            && !EVP_PKEY_is_a(ctx->pkey, SN_tls1_prf)
432cfa2
+            && !EVP_PKEY_is_a(ctx->pkey, SN_hkdf)) {
432cfa2
+        int mdnid = EVP_MD_nid(md);
432cfa2
+        if ((mdnid == NID_sha1 || mdnid == NID_md5_sha1)
432cfa2
+                && !ossl_ctx_legacy_digest_signatures_allowed(ctx->libctx, 0)) {
432cfa2
+            ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_DIGEST);
432cfa2
+            return -1;
432cfa2
+        }
432cfa2
+    }
432cfa2
+
432cfa2
     if (fallback)
432cfa2
         return EVP_PKEY_CTX_ctrl(ctx, -1, op, ctrl, 0, (void *)(md));
432cfa2
 
432cfa2
diff --git a/doc/man5/config.pod b/doc/man5/config.pod
432cfa2
index 77a8055e81..0c9110d28a 100644
432cfa2
--- a/doc/man5/config.pod
432cfa2
+++ b/doc/man5/config.pod
432cfa2
@@ -296,6 +296,19 @@ Within the algorithm properties section, the following names have meaning:
432cfa2
 The value may be anything that is acceptable as a property query
432cfa2
 string for EVP_set_default_properties().
432cfa2
 
432cfa2
+=item B<rh-allow-sha1-signatures>
432cfa2
+
432cfa2
+The value is a boolean that can be B<yes> or B<no>.  If the value is not set,
432cfa2
+it behaves as if it was set to B<yes>.
432cfa2
+
432cfa2
+When set to B<no>, any attempt to create or verify a signature with a SHA1
432cfa2
+digest will fail.  To test whether your software will work with future versions
432cfa2
+of OpenSSL, set this option to B<no>.  This setting also affects TLS, where
432cfa2
+signature algorithms that use SHA1 as digest will no longer be supported if
432cfa2
+this option is set to B<no>.  Because TLS 1.1 or lower use MD5-SHA1 as
432cfa2
+pseudorandom function (PRF) to derive key material, disabling
432cfa2
+B<rh-allow-sha1-signatures> requires the use of TLS 1.2 or newer.
432cfa2
+
432cfa2
 =item B<fips_mode> (deprecated)
432cfa2
 
432cfa2
 The value is a boolean that can be B<yes> or B<no>.  If the value is
432cfa2
diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h
432cfa2
index 1291299b6e..e234341e6a 100644
432cfa2
--- a/include/internal/cryptlib.h
432cfa2
+++ b/include/internal/cryptlib.h
432cfa2
@@ -168,7 +168,8 @@ typedef struct ossl_ex_data_global_st {
432cfa2
 # define OSSL_LIB_CTX_PROVIDER_CONF_INDEX           16
432cfa2
 # define OSSL_LIB_CTX_BIO_CORE_INDEX                17
432cfa2
 # define OSSL_LIB_CTX_CHILD_PROVIDER_INDEX          18
432cfa2
-# define OSSL_LIB_CTX_MAX_INDEXES                   19
432cfa2
+# define OSSL_LIB_CTX_LEGACY_DIGEST_SIGNATURES      19
432cfa2
+# define OSSL_LIB_CTX_MAX_INDEXES                   20
432cfa2
 
432cfa2
 # define OSSL_LIB_CTX_METHOD_LOW_PRIORITY          -1
432cfa2
 # define OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY       0
432cfa2
diff --git a/include/internal/sslconf.h b/include/internal/sslconf.h
432cfa2
index fd7f7e3331..05464b0655 100644
432cfa2
--- a/include/internal/sslconf.h
432cfa2
+++ b/include/internal/sslconf.h
432cfa2
@@ -18,4 +18,8 @@ int conf_ssl_name_find(const char *name, size_t *idx);
432cfa2
 void conf_ssl_get_cmd(const SSL_CONF_CMD *cmd, size_t idx, char **cmdstr,
432cfa2
                       char **arg);
432cfa2
 
432cfa2
+/* Methods to support disabling all signatures with legacy digests */
432cfa2
+int ossl_ctx_legacy_digest_signatures_allowed(OSSL_LIB_CTX *libctx, int loadconfig);
432cfa2
+int ossl_ctx_legacy_digest_signatures_allowed_set(OSSL_LIB_CTX *libctx, int allow,
432cfa2
+                                                  int loadconfig);
432cfa2
 #endif
432cfa2
diff --git a/providers/common/securitycheck.c b/providers/common/securitycheck.c
432cfa2
index 699ada7c52..e534ad0a5f 100644
432cfa2
--- a/providers/common/securitycheck.c
432cfa2
+++ b/providers/common/securitycheck.c
432cfa2
@@ -19,6 +19,7 @@
432cfa2
 #include <openssl/core_names.h>
432cfa2
 #include <openssl/obj_mac.h>
432cfa2
 #include "prov/securitycheck.h"
432cfa2
+#include "internal/sslconf.h"
432cfa2
 
432cfa2
 /*
432cfa2
  * FIPS requires a minimum security strength of 112 bits (for encryption or
432cfa2
@@ -235,6 +236,15 @@ int ossl_digest_get_approved_nid_with_sha1(OSSL_LIB_CTX *ctx, const EVP_MD *md,
432cfa2
             mdnid = -1; /* disallowed by security checks */
432cfa2
     }
432cfa2
 # endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
432cfa2
+
432cfa2
+#ifndef FIPS_MODULE
432cfa2
+    if (!ossl_ctx_legacy_digest_signatures_allowed(ctx, 0))
432cfa2
+        /* SHA1 is globally disabled, check whether we want to locally allow
432cfa2
+         * it. */
432cfa2
+        if (mdnid == NID_sha1 && !sha1_allowed)
432cfa2
+            mdnid = -1;
432cfa2
+#endif
432cfa2
+
432cfa2
     return mdnid;
432cfa2
 }
432cfa2
 
432cfa2
@@ -244,5 +254,15 @@ int ossl_digest_is_allowed(OSSL_LIB_CTX *ctx, const EVP_MD *md)
432cfa2
     if (ossl_securitycheck_enabled(ctx))
432cfa2
         return ossl_digest_get_approved_nid(md) != NID_undef;
432cfa2
 # endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
432cfa2
+
432cfa2
+#ifndef FIPS_MODULE
432cfa2
+    {
432cfa2
+        int mdnid = EVP_MD_nid(md);
432cfa2
+        if ((mdnid == NID_sha1 || mdnid == NID_md5_sha1)
432cfa2
+                && !ossl_ctx_legacy_digest_signatures_allowed(ctx, 0))
432cfa2
+            return 0;
432cfa2
+    }
432cfa2
+#endif
432cfa2
+
432cfa2
     return 1;
432cfa2
 }
432cfa2
diff --git a/providers/common/securitycheck_default.c b/providers/common/securitycheck_default.c
432cfa2
index de7f0d3a0a..ce54a94fbc 100644
432cfa2
--- a/providers/common/securitycheck_default.c
432cfa2
+++ b/providers/common/securitycheck_default.c
432cfa2
@@ -15,6 +15,7 @@
432cfa2
 #include <openssl/obj_mac.h>
432cfa2
 #include "prov/securitycheck.h"
432cfa2
 #include "internal/nelem.h"
432cfa2
+#include "internal/sslconf.h"
432cfa2
 
432cfa2
 /* Disable the security checks in the default provider */
432cfa2
 int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx)
432cfa2
@@ -23,9 +24,10 @@ int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx)
432cfa2
 }
432cfa2
 
432cfa2
 int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md,
432cfa2
-                                    ossl_unused int sha1_allowed)
432cfa2
+                                    int sha1_allowed)
432cfa2
 {
432cfa2
     int mdnid;
432cfa2
+    int ldsigs_allowed;
432cfa2
 
432cfa2
     static const OSSL_ITEM name_to_nid[] = {
432cfa2
         { NID_md5,       OSSL_DIGEST_NAME_MD5       },
432cfa2
@@ -36,8 +38,11 @@ int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md,
432cfa2
         { NID_ripemd160, OSSL_DIGEST_NAME_RIPEMD160 },
432cfa2
     };
432cfa2
 
432cfa2
-    mdnid = ossl_digest_get_approved_nid_with_sha1(ctx, md, 1);
432cfa2
+    ldsigs_allowed = ossl_ctx_legacy_digest_signatures_allowed(ctx, 0);
432cfa2
+    mdnid = ossl_digest_get_approved_nid_with_sha1(ctx, md, sha1_allowed || ldsigs_allowed);
432cfa2
     if (mdnid == NID_undef)
432cfa2
         mdnid = ossl_digest_md_to_nid(md, name_to_nid, OSSL_NELEM(name_to_nid));
432cfa2
+    if (mdnid == NID_md5_sha1 && !ldsigs_allowed)
432cfa2
+        mdnid = -1;
432cfa2
     return mdnid;
432cfa2
 }
432cfa2
diff --git a/providers/implementations/signature/dsa_sig.c b/providers/implementations/signature/dsa_sig.c
432cfa2
index 28fd7c498e..fa3822f39f 100644
432cfa2
--- a/providers/implementations/signature/dsa_sig.c
432cfa2
+++ b/providers/implementations/signature/dsa_sig.c
432cfa2
@@ -124,12 +124,17 @@ static int dsa_setup_md(PROV_DSA_CTX *ctx,
432cfa2
         mdprops = ctx->propq;
432cfa2
 
432cfa2
     if (mdname != NULL) {
432cfa2
-        int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
432cfa2
         WPACKET pkt;
432cfa2
         EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
432cfa2
-        int md_nid = ossl_digest_get_approved_nid_with_sha1(ctx->libctx, md,
432cfa2
-                                                            sha1_allowed);
432cfa2
+        int md_nid;
432cfa2
         size_t mdname_len = strlen(mdname);
432cfa2
+#ifdef FIPS_MODULE
432cfa2
+        int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
432cfa2
+#else
432cfa2
+        int sha1_allowed = 0;
432cfa2
+#endif
432cfa2
+        md_nid = ossl_digest_get_approved_nid_with_sha1(ctx->libctx, md,
432cfa2
+                                                            sha1_allowed);
432cfa2
 
432cfa2
         if (md == NULL || md_nid < 0) {
432cfa2
             if (md == NULL)
432cfa2
diff --git a/providers/implementations/signature/ecdsa_sig.c b/providers/implementations/signature/ecdsa_sig.c
432cfa2
index 865d49d100..99b228e82c 100644
432cfa2
--- a/providers/implementations/signature/ecdsa_sig.c
432cfa2
+++ b/providers/implementations/signature/ecdsa_sig.c
432cfa2
@@ -237,7 +237,11 @@ static int ecdsa_setup_md(PROV_ECDSA_CTX *ctx, const char *mdname,
432cfa2
                        "%s could not be fetched", mdname);
432cfa2
         return 0;
432cfa2
     }
432cfa2
+#ifdef FIPS_MODULE
432cfa2
     sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
432cfa2
+#else
432cfa2
+    sha1_allowed = 0;
432cfa2
+#endif
432cfa2
     md_nid = ossl_digest_get_approved_nid_with_sha1(ctx->libctx, md,
432cfa2
                                                     sha1_allowed);
432cfa2
     if (md_nid < 0) {
432cfa2
diff --git a/providers/implementations/signature/rsa_sig.c b/providers/implementations/signature/rsa_sig.c
432cfa2
index 325e855333..bea397f0c1 100644
432cfa2
--- a/providers/implementations/signature/rsa_sig.c
432cfa2
+++ b/providers/implementations/signature/rsa_sig.c
432cfa2
@@ -26,6 +26,7 @@
432cfa2
 #include "internal/cryptlib.h"
432cfa2
 #include "internal/nelem.h"
432cfa2
 #include "internal/sizes.h"
432cfa2
+#include "internal/sslconf.h"
432cfa2
 #include "crypto/rsa.h"
432cfa2
 #include "prov/providercommon.h"
432cfa2
 #include "prov/implementations.h"
432cfa2
@@ -34,6 +35,7 @@
432cfa2
 #include "prov/securitycheck.h"
432cfa2
 
432cfa2
 #define RSA_DEFAULT_DIGEST_NAME OSSL_DIGEST_NAME_SHA1
432cfa2
+#define RSA_DEFAULT_DIGEST_NAME_NONLEGACY OSSL_DIGEST_NAME_SHA2_256
432cfa2
 
432cfa2
 static OSSL_FUNC_signature_newctx_fn rsa_newctx;
432cfa2
 static OSSL_FUNC_signature_sign_init_fn rsa_sign_init;
432cfa2
@@ -289,10 +291,15 @@ static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname,
432cfa2
 
432cfa2
     if (mdname != NULL) {
432cfa2
         EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
432cfa2
+        int md_nid;
432cfa2
+        size_t mdname_len = strlen(mdname);
432cfa2
+#ifdef FIPS_MODULE
432cfa2
         int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
432cfa2
-        int md_nid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md,
432cfa2
+#else
432cfa2
+        int sha1_allowed = 0;
432cfa2
+#endif
432cfa2
+        md_nid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md,
432cfa2
                                                      sha1_allowed);
432cfa2
-        size_t mdname_len = strlen(mdname);
432cfa2
 
432cfa2
         if (md == NULL
432cfa2
             || md_nid <= 0
432cfa2
@@ -1348,8 +1355,15 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
432cfa2
     prsactx->pad_mode = pad_mode;
432cfa2
 
432cfa2
     if (prsactx->md == NULL && pmdname == NULL
432cfa2
-        && pad_mode == RSA_PKCS1_PSS_PADDING)
432cfa2
+        && pad_mode == RSA_PKCS1_PSS_PADDING) {
432cfa2
         pmdname = RSA_DEFAULT_DIGEST_NAME;
432cfa2
+#ifndef FIPS_MODULE
432cfa2
+        if (!ossl_ctx_legacy_digest_signatures_allowed(prsactx->libctx, 0)) {
432cfa2
+            pmdname = RSA_DEFAULT_DIGEST_NAME_NONLEGACY;
432cfa2
+        }
432cfa2
+#endif
432cfa2
+    }
432cfa2
+
432cfa2
 
432cfa2
     if (pmgf1mdname != NULL
432cfa2
         && !rsa_setup_mgf1_md(prsactx, pmgf1mdname, pmgf1mdprops))
432cfa2
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
432cfa2
index 41fddf22a7..dcd487ec2e 100644
432cfa2
--- a/ssl/t1_lib.c
432cfa2
+++ b/ssl/t1_lib.c
432cfa2
@@ -20,6 +20,7 @@
432cfa2
 #include <openssl/bn.h>
432cfa2
 #include <openssl/provider.h>
432cfa2
 #include <openssl/param_build.h>
432cfa2
+#include "internal/sslconf.h"
432cfa2
 #include "internal/nelem.h"
432cfa2
 #include "internal/sizes.h"
432cfa2
 #include "internal/tlsgroups.h"
432cfa2
@@ -1145,11 +1146,13 @@ int ssl_setup_sig_algs(SSL_CTX *ctx)
432cfa2
         = OPENSSL_malloc(sizeof(*lu) * OSSL_NELEM(sigalg_lookup_tbl));
432cfa2
     EVP_PKEY *tmpkey = EVP_PKEY_new();
432cfa2
     int ret = 0;
432cfa2
+    int ldsigs_allowed;
432cfa2
 
432cfa2
     if (cache == NULL || tmpkey == NULL)
432cfa2
         goto err;
432cfa2
 
432cfa2
     ERR_set_mark();
432cfa2
+    ldsigs_allowed = ossl_ctx_legacy_digest_signatures_allowed(ctx->libctx, 0);
432cfa2
     for (i = 0, lu = sigalg_lookup_tbl;
432cfa2
          i < OSSL_NELEM(sigalg_lookup_tbl); lu++, i++) {
432cfa2
         EVP_PKEY_CTX *pctx;
432cfa2
@@ -1169,6 +1172,11 @@ int ssl_setup_sig_algs(SSL_CTX *ctx)
432cfa2
             cache[i].enabled = 0;
432cfa2
             continue;
432cfa2
         }
432cfa2
+        if ((lu->hash == NID_sha1 || lu->hash == NID_md5_sha1)
432cfa2
+                && !ldsigs_allowed) {
432cfa2
+            cache[i].enabled = 0;
432cfa2
+            continue;
432cfa2
+        }
432cfa2
 
432cfa2
         if (!EVP_PKEY_set_type(tmpkey, lu->sig)) {
432cfa2
             cache[i].enabled = 0;
432cfa2
diff --git a/util/libcrypto.num b/util/libcrypto.num
432cfa2
index 10b4e57d79..2d3c363bb0 100644
432cfa2
--- a/util/libcrypto.num
432cfa2
+++ b/util/libcrypto.num
432cfa2
@@ -5426,3 +5426,5 @@ ASN1_item_d2i_ex                        5552	3_0_0	EXIST::FUNCTION:
4f1033e
 OSSL_CMP_CTX_reset_geninfo_ITAVs        5558	3_0_8	EXIST::FUNCTION:CMP
9af90fc
 OSSL_CMP_MSG_update_recipNonce          5559	3_0_9	EXIST::FUNCTION:CMP
432cfa2
 ossl_safe_getenv                        ?	3_0_0	EXIST::FUNCTION:
432cfa2
+ossl_ctx_legacy_digest_signatures_allowed ?	3_0_1	EXIST::FUNCTION:
432cfa2
+ossl_ctx_legacy_digest_signatures_allowed_set ?	3_0_1	EXIST::FUNCTION:
432cfa2
-- 
432cfa2
2.35.1
432cfa2