public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Clemens Lang <cllang@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/openssl] rebase_40beta: Allow disabling of SHA1 signatures
Date: Tue, 09 Jun 2026 12:44:58 GMT	[thread overview]
Message-ID: <178100909809.1.9144658299778188945.rpms-openssl-432cfa2baa8d@fedoraproject.org> (raw)

            A new commit has been pushed.

            Repo   : rpms/openssl
            Branch : rebase_40beta
            Commit : 432cfa2baa8db94abf0daa9821a42ef40723e3c0
            Author : Clemens Lang <cllang@redhat.com>
            Date   : 2022-04-07T18:14:04+02:00
            Stats  : +733/-1 in 3 file(s)
            URL    : https://src.fedoraproject.org/rpms/openssl/c/432cfa2baa8db94abf0daa9821a42ef40723e3c0?branch=rebase_40beta

            Log:
            Allow disabling of SHA1 signatures

NOTE: This patch is ported from CentOS 9 / RHEL 9, where it defaults to
denying SHA1 signatures. On Fedora, the default is – for now – to allow
SHA1 signatures.

In order to phase out SHA1 signatures, introduce a new configuration
option in the alg_section named 'rh-allow-sha1-signatures'. This option
defaults to true. If set to false, any signature creation or
verification operations that involve SHA1 as digest will fail.

This also affects TLS, where the signature_algorithms extension of any
ClientHello message sent by OpenSSL will no longer include signatures
with the SHA1 digest if rh-allow-sha1-signatures is false. For servers
that request a client certificate, the same also applies for
CertificateRequest messages sent by them.

Resolves: rhbz#2070977
Related: rhbz#2031742, rhbz#2062640
Signed-off-by: Clemens Lang <cllang@redhat.com>

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

diff --git a/0052-Allow-SHA1-in-seclevel-1-if-rh-allow-sha1-signatures.patch b/0052-Allow-SHA1-in-seclevel-1-if-rh-allow-sha1-signatures.patch
new file mode 100644
index 0000000..eea02f8
--- /dev/null
+++ b/0052-Allow-SHA1-in-seclevel-1-if-rh-allow-sha1-signatures.patch
@@ -0,0 +1,217 @@
+From f695f140255f9b564cac4d5e9e38ba27ec927256 Mon Sep 17 00:00:00 2001
+From: Clemens Lang <cllang@redhat.com>
+Date: Tue, 1 Mar 2022 15:44:18 +0100
+Subject: [PATCH 2/2] Allow SHA1 in seclevel 1 if rh-allow-sha1-signatures =
+ yes
+
+NOTE: This patch is ported from CentOS 9 / RHEL 9, where it allows SHA1
+in seclevel 2 if rh-allow-sha1-signatures = yes. This was chosen because
+on CentOS 9 and RHEL 9, the LEGACY crypto policy sets the security level
+to 2.
+
+On Fedora 35 (with OpenSSL 1.1) the legacy crypto policy uses security
+level 1. Because Fedora 36 supports both OpenSSL 1.1 and OpenSSL 3, and
+we want the legacy crypto policy to allow SHA-1 in TLS, the only option
+to make this happen consistently in both OpenSSL 1.1 and OpenSSL 3 is
+SECLEVEL=1 (which will allow SHA-1 in OpenSSL 1.1) and this change to
+allow SHA-1 in SECLEVEL=1 with rh-allow-sha1-signatures = yes (which
+will allow SHA-1 in OpenSSL 3).
+
+The change from CentOS 9 / RHEL 9 cannot be applied unmodified, because
+rh-allow-sha1-signatures will default to yes in Fedora (according to our
+current plans including until F38), and the security level in the
+DEFAULT crypto policy is 2, i.e., the unmodified change would weaken the
+default configuration.
+
+Related: rhbz#2055796
+Related: rhbz#2070977
+---
+ crypto/x509/x509_vfy.c        | 19 ++++++++++-
+ doc/man5/config.pod           |  7 ++++
+ ssl/t1_lib.c                  | 64 ++++++++++++++++++++++++++++-------
+ test/recipes/25-test_verify.t |  4 +--
+ 4 files changed, 78 insertions(+), 16 deletions(-)
+
+diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
+index 2f175ca517..60aa26f552 100644
+--- a/crypto/x509/x509_vfy.c
++++ b/crypto/x509/x509_vfy.c
+@@ -25,6 +25,7 @@
+ #include <openssl/objects.h>
+ #include <openssl/core_names.h>
+ #include "internal/dane.h"
++#include "internal/sslconf.h"
+ #include "crypto/x509.h"
+ #include "x509_local.h"
+ 
+@@ -3441,14 +3442,30 @@ static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert)
+ {
+     int secbits = -1;
+     int level = ctx->param->auth_level;
++    int nid;
++    OSSL_LIB_CTX *libctx = NULL;
+ 
+     if (level <= 0)
+         return 1;
+     if (level > NUM_AUTH_LEVELS)
+         level = NUM_AUTH_LEVELS;
+ 
+-    if (!X509_get_signature_info(cert, NULL, NULL, &secbits, NULL))
++    if (ctx->libctx)
++        libctx = ctx->libctx;
++    else if (cert->libctx)
++        libctx = cert->libctx;
++    else
++        libctx = OSSL_LIB_CTX_get0_global_default();
++
++    if (!X509_get_signature_info(cert, &nid, NULL, &secbits, NULL))
+         return 0;
+ 
++    if (nid == NID_sha1
++            && ossl_ctx_legacy_digest_signatures_allowed(libctx, 0)
++            && ctx->param->auth_level < 2)
++        /* When rh-allow-sha1-signatures = yes and security level <= 1,
++         * explicitly allow SHA1 for backwards compatibility. */
++        return 1;
++
+     return secbits >= minbits_table[level - 1];
+ }
+diff --git a/doc/man5/config.pod b/doc/man5/config.pod
+index 0c9110d28a..02e7ca706f 100644
+--- a/doc/man5/config.pod
++++ b/doc/man5/config.pod
+@@ -309,6 +309,13 @@ this option is set to B<no>.  Because TLS 1.1 or lower use MD5-SHA1 as
+ pseudorandom function (PRF) to derive key material, disabling
+ B<rh-allow-sha1-signatures> requires the use of TLS 1.2 or newer.
+ 
++Note that enabling B<rh-allow-sha1-signatures> will allow TLS signature
++algorithms that use SHA1 in security level 1, despite the definition of
++security level 1 of FIXME bits of security, which SHA1 does not meet.  This
++allows using SHA1 in TLS in the LEGACY crypto-policy on Fedora without
++requiring to set the security level to 0, which would include further insecure
++algorithms.
++
+ =item B<fips_mode> (deprecated)
+ 
+ The value is a boolean that can be B<yes> or B<no>.  If the value is
+diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
+index dcd487ec2e..e47ddf56f1 100644
+--- a/ssl/t1_lib.c
++++ b/ssl/t1_lib.c
+@@ -20,6 +20,7 @@
+ #include <openssl/bn.h>
+ #include <openssl/provider.h>
+ #include <openssl/param_build.h>
++#include "crypto/x509.h"
+ #include "internal/sslconf.h"
+ #include "internal/nelem.h"
+ #include "internal/sizes.h"
+@@ -1561,19 +1562,27 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
+         SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_UNKNOWN_DIGEST);
+         return 0;
+     }
+-    /*
+-     * Make sure security callback allows algorithm. For historical
+-     * reasons we have to pass the sigalg as a two byte char array.
+-     */
+-    sigalgstr[0] = (sig >> 8) & 0xff;
+-    sigalgstr[1] = sig & 0xff;
+-    secbits = sigalg_security_bits(s->ctx, lu);
+-    if (secbits == 0 ||
+-        !ssl_security(s, SSL_SECOP_SIGALG_CHECK, secbits,
+-                      md != NULL ? EVP_MD_get_type(md) : NID_undef,
+-                      (void *)sigalgstr)) {
+-        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_WRONG_SIGNATURE_TYPE);
+-        return 0;
++
++    if (lu->hash == NID_sha1
++            && ossl_ctx_legacy_digest_signatures_allowed(s->ctx->libctx, 0)
++            && SSL_get_security_level(s) < 2) {
++        /* when rh-allow-sha1-signatures = yes and security level <= 1,
++         * explicitly allow SHA1 for backwards compatibility */
++    } else {
++        /*
++         * Make sure security callback allows algorithm. For historical
++         * reasons we have to pass the sigalg as a two byte char array.
++         */
++        sigalgstr[0] = (sig >> 8) & 0xff;
++        sigalgstr[1] = sig & 0xff;
++        secbits = sigalg_security_bits(s->ctx, lu);
++        if (secbits == 0 ||
++            !ssl_security(s, SSL_SECOP_SIGALG_CHECK, secbits,
++                          md != NULL ? EVP_MD_get_type(md) : NID_undef,
++                          (void *)sigalgstr)) {
++            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_WRONG_SIGNATURE_TYPE);
++            return 0;
++        }
+     }
+     /* Store the sigalg the peer uses */
+     s->s3.tmp.peer_sigalg = lu;
+@@ -2106,6 +2115,14 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
+         }
+     }
+ 
++    if (lu->hash == NID_sha1
++            && ossl_ctx_legacy_digest_signatures_allowed(s->ctx->libctx, 0)
++            && SSL_get_security_level(s) < 2) {
++        /* when rh-allow-sha1-signatures = yes and security level <= 1,
++         * explicitly allow SHA1 for backwards compatibility */
++        return 1;
++    }
++
+     /* Finally see if security callback allows it */
+     secbits = sigalg_security_bits(s->ctx, lu);
+     sigalgstr[0] = (lu->sigalg >> 8) & 0xff;
+@@ -2977,6 +2994,8 @@ static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op)
+ {
+     /* Lookup signature algorithm digest */
+     int secbits, nid, pknid;
++    OSSL_LIB_CTX *libctx = NULL;
++
+     /* Don't check signature if self signed */
+     if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0)
+         return 1;
+@@ -2985,6 +3004,25 @@ static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op)
+     /* If digest NID not defined use signature NID */
+     if (nid == NID_undef)
+         nid = pknid;
++
++    if (x && x->libctx)
++        libctx = x->libctx;
++    else if (ctx && ctx->libctx)
++        libctx = ctx->libctx;
++    else if (s && s->ctx && s->ctx->libctx)
++        libctx = s->ctx->libctx;
++    else
++        libctx = OSSL_LIB_CTX_get0_global_default();
++
++    if (nid == NID_sha1
++            && ossl_ctx_legacy_digest_signatures_allowed(libctx, 0)
++            && ((s != NULL && SSL_get_security_level(s) < 2)
++                || (ctx != NULL && SSL_CTX_get_security_level(ctx) < 2)
++            ))
++        /* When rh-allow-sha1-signatures = yes and security level <= 1,
++         * explicitly allow SHA1 for backwards compatibility. */
++        return 1;
++
+     if (s)
+         return ssl_security(s, op, secbits, nid, x);
+     else
+diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t
+index 700bbd849c..280477bc9d 100644
+--- a/test/recipes/25-test_verify.t
++++ b/test/recipes/25-test_verify.t
+@@ -387,8 +387,8 @@ ok(verify("ee-pss-sha1-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "0"
+ ok(verify("ee-pss-sha256-cert", "", ["root-cert"], ["ca-cert"], ),
+     "CA with PSS signature using SHA256");
+ 
+-ok(!verify("ee-pss-sha1-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "1"),
+-    "Reject PSS signature using SHA1 and auth level 1");
++ok(!verify("ee-pss-sha1-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "2"),
++    "Reject PSS signature using SHA1 and auth level 2");
+ 
+ ok(verify("ee-pss-sha256-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "2"),
+     "PSS signature using SHA256 and auth level 2");
+-- 
+2.35.1
+

diff --git a/openssl.spec b/openssl.spec
index 91e74a0..fb4de73 100644
--- a/openssl.spec
+++ b/openssl.spec
@@ -15,7 +15,7 @@
 Summary: Utilities from the general purpose cryptography library with TLS implementation
 Name: openssl
 Version: 3.0.2
-Release: 1%{?dist}
+Release: 2%{?dist}
 Epoch: 1
 # We have to remove certain patented algorithms from the openssl source
 # tarball with the hobble-openssl script which is included below.
@@ -56,8 +56,12 @@ Patch11: 0011-Remove-EC-curves.patch
 Patch12: 0012-Disable-explicit-ec.patch
 # Instructions to load legacy provider in openssl.cnf
 Patch24: 0024-load-legacy-prov.patch
+# Selectively disallow SHA1 signatures rhbz#2070977
+Patch49: 0049-Allow-disabling-of-SHA1-signatures.patch
 # Backport of patch for RHEL for Edge rhbz #2027261
 Patch51: 0051-Support-different-R_BITS-lengths-for-KBKDF.patch
+# Support SHA1 in TLS in LEGACY crypto-policy (which is SECLEVEL=1)
+Patch52: 0052-Allow-SHA1-in-seclevel-1-if-rh-allow-sha1-signatures.patch
 
 License: ASL 2.0
 URL: http://www.openssl.org/
@@ -384,6 +388,14 @@ install -m644 %{SOURCE9} \
 %ldconfig_scriptlets libs
 
 %changelog
+* Thu Apr 07 2022 Clemens Lang <cllang@redhat.com> - 1:3.0.2-2
+- Allow disabling SHA1 signature creation and verification.
+  Set rh-allow-sha1-signatures = no to disable.
+  Allow SHA1 in TLS in SECLEVEL 1 if rh-allow-sha1-signatures = yes. This will
+  support SHA1 in TLS in the LEGACY crypto-policy.
+  Resolves: rhbz#2070977
+  Related: rhbz#2031742, rhbz#2062640
+
 * Fri Mar 18 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 1:3.0.2-1
 - Rebase to upstream version 3.0.2
 

                 reply	other threads:[~2026-06-09 12:44 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178100909809.1.9144658299778188945.rpms-openssl-432cfa2baa8d@fedoraproject.org \
    --to=cllang@redhat.com \
    --cc=git-commits@fedoraproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox