#22 Allow disabling of SHA1 signatures
Merged 10 months ago by clang. Opened 10 months ago by clang.
rpms/ clang/openssl rawhide-sha1-rhbz2070977  into  rawhide

@@ -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

+ 

@@ -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

+ 

file added
+9
@@ -0,0 +1,9 @@ 

+ # capi.so is a dummy only used on Windows, it doesn't need dependency information

+ addFilter("E: shared-lib(rary)?-without-dependency-information /usr/lib64/engines-3/capi.so")

+ 

+ # The sources are hobbled and thus not a valid URL. That's expected.

+ addFilter("W: invalid-url Source0: openssl-[0-9\\.]+-hobbled.tar.gz")

+ 

+ # Technically this warning is correct, but in the case of the openssl binary we

+ # want to allow SSL_CTX_set_cipher_list

+ addFilter("W: crypto-policy-non-compliance-openssl /usr/bin/openssl SSL_CTX_set_cipher_list")

file modified
+17 -1
@@ -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.
@@ -24,6 +24,7 @@ 

  Source1: hobble-openssl

  Source2: Makefile.certificate

  Source3: genpatches

+ Source4: openssl.rpmlintrc

  Source6: make-dummy-cert

  Source7: renew-dummy-cert

  Source9: configuration-switch.h
@@ -56,8 +57,12 @@ 

  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 +389,17 @@ 

  %ldconfig_scriptlets libs

  

  %changelog

+ * Thu Apr 07 2022 Clemens Lang <cllang@redhat.com> - 1:3.0.2-2

+ - Silence a few rpmlint false positives.

+ 

+ * 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

  

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

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci

1 new commit added

  • Silence rpmlint false positive on capi.so
10 months ago

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci

2 new commits added

  • Silence rpmlint false positive on capi.so
  • Allow disabling of SHA1 signatures
10 months ago

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci

2 new commits added

  • Silence rpmlint false positives
  • Allow disabling of SHA1 signatures
10 months ago

@churchyard The Python test you added seems to either fail or time out in https://fedora.softwarefactory-project.io/zuul/status/change/22,f3abf0e8065621eeae313a6f1651624f1734f039. The streaming log from https://fedora.softwarefactory-project.io/zuul/stream/333f3a40c19245a0a43dbebcd43b04aa?logfile=console.log hangs at

2022-04-07 10:54:16.556654 | TASK [include_role : testing-farm-run-test]
2022-04-07 10:54:16.605472 | container | ok
2022-04-07 10:54:16.654964 | 
2022-04-07 10:54:16.655122 | TASK [testing-farm-run-test : trigger a Testing Farm test]
2022-04-07 10:54:20.877804 | container | Output suppressed because no_log was given
2022-04-07 10:54:20.906289 | 
2022-04-07 10:54:20.906471 | TASK [testing-farm-run-test : debug]
2022-04-07 10:54:21.310357 | Request URL: https://api.dev.testing-farm.io/v0.1/requests/c21a24fb-76fb-4f3d-9909-8b7cfbeadc52
2022-04-07 10:54:21.331995 | 
2022-04-07 10:54:21.332144 | TASK [testing-farm-run-test : wait until the state is complete or error]

When I follow the request URL, and the URL in the run.artifacts key of the returned JSON, the logs say guest setup failed:

[32m[11:00:08] [+] [worker_1] [dist-git-repository-None-YWg59L/tests/tests_python.yml] Guest setup logs:
+---------------------------+--------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Stage                     | Log                | Location                                                                                                                                                                               |
|---------------------------+--------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| pre-artifact-installation | guest setup        | https://artifacts.dev.testing-farm.io/c21a24fb-76fb-4f3d-9909-8b7cfbeadc52/guest-setup-14176e83-47e3-4e42-bf35-24c7a369b6f5/guest-setup-output-pre-artifact-installation.txt           |
| artifact-installation     | build installation | https://artifacts.dev.testing-farm.io/c21a24fb-76fb-4f3d-9909-8b7cfbeadc52/guest-setup-14176e83-47e3-4e42-bf35-24c7a369b6f5/artifact-installation-14176e83-47e3-4e42-bf35-24c7a369b6f5 |
+---------------------------+--------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+[0m
[31m[11:00:08] [E] [dist-git-repository-None-YWg59L/tests/tests_python.yml] guest setup failed: Test environment installation failed: reason unknown, please escalate[0m
[32m[11:00:08] [+] [dist-git-repository-None-YWg59L/tests/tests_python.yml] Guest setup logs:
+---------------------------+--------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Stage                     | Log                | Location                                                                                                                                                                               |
|---------------------------+--------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| pre-artifact-installation | guest setup        | https://artifacts.dev.testing-farm.io/c21a24fb-76fb-4f3d-9909-8b7cfbeadc52/guest-setup-14176e83-47e3-4e42-bf35-24c7a369b6f5/guest-setup-output-pre-artifact-installation.txt           |
| artifact-installation     | build installation | https://artifacts.dev.testing-farm.io/c21a24fb-76fb-4f3d-9909-8b7cfbeadc52/guest-setup-14176e83-47e3-4e42-bf35-24c7a369b6f5/artifact-installation-14176e83-47e3-4e42-bf35-24c7a369b6f5 |
+---------------------------+--------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+[0m
[32m[11:00:08] [+] [dist-git-repository-None-YWg59L/tests/tests_python.yml] starting destroying guest[0m
[32m[11:00:08] [+] [artemis] [14176e83-47e3-4e42-bf35-24c7a369b6f5] destroying guest[0m
[32m[11:00:08] [+] [artemis] [14176e83-47e3-4e42-bf35-24c7a369b6f5] successfully released[0m

The logs of the artifact-installation stage do not show any errors. Any idea what's wrong here?

rebased onto 432cfa2

10 months ago

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci

Pull-Request has been merged by clang

10 months ago