forked from rpms/openssl
ELN: Disable SHA-1 by default using CentOS patches
ELN should ideally be ahead of CentOS and RHEL with policy changes, but due to time constraints was not. Fix that by bringing the current CentOS 9 / RHEL 9 state of SHA-1 disabling to ELN. Due to differences in their lifecycles, Fedora's packages will stay at allowing SHA-1 by default for now. There is a plan to gradually catch up to the ELN state over the next few releases. Signed-off-by: Clemens Lang <cllang@redhat.com>
This commit is contained in:
parent
82a6212c47
commit
0967bb5953
489
0049-Selectively-disallow-SHA1-signatures.patch
Normal file
489
0049-Selectively-disallow-SHA1-signatures.patch
Normal file
@ -0,0 +1,489 @@
|
||||
From 243201772cc6d583fae9eba81cb2c2c7425bc564 Mon Sep 17 00:00:00 2001
|
||||
From: Clemens Lang <cllang@redhat.com>
|
||||
Date: Mon, 21 Feb 2022 17:24:44 +0100
|
||||
Subject: Selectively disallow SHA1 signatures
|
||||
|
||||
For RHEL 9.0, we want to phase out SHA1. One of the steps to do that is
|
||||
disabling SHA1 signatures. Introduce a new configuration option in the
|
||||
alg_section named 'rh-allow-sha1-signatures'. This option defaults to
|
||||
false. If set to false (or unset), 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).
|
||||
|
||||
Resolves: rhbz#2031742
|
||||
---
|
||||
crypto/evp/evp_cnf.c | 13 ++++
|
||||
crypto/evp/m_sigver.c | 77 +++++++++++++++++++
|
||||
crypto/evp/pmeth_lib.c | 15 ++++
|
||||
doc/man5/config.pod | 11 +++
|
||||
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, 188 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 9188edbc21..db1a1d7bc3 100644
|
||||
--- a/crypto/evp/m_sigver.c
|
||||
+++ b/crypto/evp/m_sigver.c
|
||||
@@ -16,6 +16,71 @@
|
||||
#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)
|
||||
+{
|
||||
+ return OPENSSL_zalloc(sizeof(OSSL_LEGACY_DIGEST_SIGNATURES));
|
||||
+}
|
||||
+
|
||||
+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 0;
|
||||
+#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
|
||||
+
|
||||
+ return ldsigs != NULL ? ldsigs->allowed : 0;
|
||||
+}
|
||||
+
|
||||
+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 +323,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..aa1be5ca7f 100644
|
||||
--- a/doc/man5/config.pod
|
||||
+++ b/doc/man5/config.pod
|
||||
@@ -304,6 +304,17 @@ 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<no>.
|
||||
+
|
||||
+When set to B<no>, any attempt to create or verify a signature with a SHA1
|
||||
+digest will fail. For compatibility with older versions of OpenSSL, set this
|
||||
+option to B<yes>. 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>.
|
||||
+
|
||||
=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 fc32bb3556..4b74ee1a34 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_TIME_print_ex 5553 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
|
||||
|
206
0052-Allow-SHA1-in-seclevel-2-if-rh-allow-sha1-signatures.patch
Normal file
206
0052-Allow-SHA1-in-seclevel-2-if-rh-allow-sha1-signatures.patch
Normal file
@ -0,0 +1,206 @@
|
||||
From c63599ee9708d543205a9173207ee7167315c624 Mon Sep 17 00:00:00 2001
|
||||
From: Clemens Lang <cllang@redhat.com>
|
||||
Date: Tue, 1 Mar 2022 15:44:18 +0100
|
||||
Subject: [PATCH] Allow SHA1 in seclevel 2 if rh-allow-sha1-signatures = yes
|
||||
|
||||
References: rhbz#2055796
|
||||
---
|
||||
crypto/x509/x509_vfy.c | 19 ++++++++++-
|
||||
doc/man5/config.pod | 7 +++-
|
||||
ssl/t1_lib.c | 64 ++++++++++++++++++++++++++++-------
|
||||
test/recipes/25-test_verify.t | 7 ++--
|
||||
4 files changed, 79 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
|
||||
index ff3ca83de6..a549c1c111 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"
|
||||
|
||||
@@ -3440,14 +3441,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 < 3)
|
||||
+ /* When rh-allow-sha1-signatures = yes and security level <= 2,
|
||||
+ * 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 aa1be5ca7f..aa69e2b844 100644
|
||||
--- a/doc/man5/config.pod
|
||||
+++ b/doc/man5/config.pod
|
||||
@@ -305,7 +305,12 @@ When set to B<no>, any attempt to create or verify a signature with a SHA1
|
||||
digest will fail. For compatibility with older versions of OpenSSL, set this
|
||||
option to B<yes>. 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>.
|
||||
+B<no>. Note that enabling B<rh-allow-sha1-signatures> will allow TLS signature
|
||||
+algorithms that use SHA1 in security level 2, despite the definition of
|
||||
+security level 2 of 112 bits of security, which SHA1 does not meet. 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)
|
||||
|
||||
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
|
||||
index 4b74ee1a34..5f089de107 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) < 3) {
|
||||
+ /* when rh-allow-sha1-signatures = yes and security level <= 2,
|
||||
+ * 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) < 3) {
|
||||
+ /* when rh-allow-sha1-signatures = yes and security level <= 2,
|
||||
+ * 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) < 3)
|
||||
+ || (ctx != NULL && SSL_CTX_get_security_level(ctx) < 3)
|
||||
+ ))
|
||||
+ /* When rh-allow-sha1-signatures = yes and security level <= 2,
|
||||
+ * 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..2de1d76b5e 100644
|
||||
--- a/test/recipes/25-test_verify.t
|
||||
+++ b/test/recipes/25-test_verify.t
|
||||
@@ -29,7 +29,7 @@ sub verify {
|
||||
run(app([@args]));
|
||||
}
|
||||
|
||||
-plan tests => 160;
|
||||
+plan tests => 159;
|
||||
|
||||
# Canonical success
|
||||
ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]),
|
||||
@@ -387,8 +387,9 @@ 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");
|
||||
+## rh-allow-sha1-signatures=yes allows this to pass despite -auth_level 1
|
||||
+#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-sha256-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "2"),
|
||||
"PSS signature using SHA256 and auth level 2");
|
||||
--
|
||||
2.35.1
|
||||
|
19
openssl.spec
19
openssl.spec
@ -15,7 +15,7 @@
|
||||
Summary: Utilities from the general purpose cryptography library with TLS implementation
|
||||
Name: openssl
|
||||
Version: 3.0.2
|
||||
Release: 2%{?dist}
|
||||
Release: 3%{?dist}
|
||||
Epoch: 1
|
||||
# We have to remove certain patented algorithms from the openssl source
|
||||
# tarball with the hobble-openssl script which is included below.
|
||||
@ -57,12 +57,22 @@ 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
|
||||
%if 0%{?rhel}
|
||||
# Selectively disallow SHA1 signatures
|
||||
Patch49: 0049-Selectively-disallow-SHA1-signatures.patch
|
||||
%else
|
||||
# Selectively disallow SHA1 signatures rhbz#2070977
|
||||
Patch49: 0049-Allow-disabling-of-SHA1-signatures.patch
|
||||
%endif
|
||||
# Backport of patch for RHEL for Edge rhbz #2027261
|
||||
Patch51: 0051-Support-different-R_BITS-lengths-for-KBKDF.patch
|
||||
%if 0%{?rhel}
|
||||
# Allow SHA1 in seclevel 2 if rh-allow-sha1-signatures = yes
|
||||
Patch52: 0052-Allow-SHA1-in-seclevel-2-if-rh-allow-sha1-signatures.patch
|
||||
%else
|
||||
# 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
|
||||
%endif
|
||||
|
||||
License: ASL 2.0
|
||||
URL: http://www.openssl.org/
|
||||
@ -236,6 +246,10 @@ patch -p1 -R < %{PATCH4}
|
||||
|
||||
OPENSSL_ENABLE_MD5_VERIFY=
|
||||
export OPENSSL_ENABLE_MD5_VERIFY
|
||||
%if 0%{?rhel}
|
||||
OPENSSL_ENABLE_SHA1_SIGNATURES=
|
||||
export OPENSSL_ENABLE_SHA1_SIGNATURES
|
||||
%endif
|
||||
OPENSSL_SYSTEM_CIPHERS_OVERRIDE=xyz_nonexistent_file
|
||||
export OPENSSL_SYSTEM_CIPHERS_OVERRIDE
|
||||
make test HARNESS_JOBS=8
|
||||
@ -389,6 +403,9 @@ install -m644 %{SOURCE9} \
|
||||
%ldconfig_scriptlets libs
|
||||
|
||||
%changelog
|
||||
* Wed Apr 20 2022 Clemens Lang <cllang@redhat.com> - 1:3.0.2-3
|
||||
- Disable SHA-1 by default in ELN using the patches from CentOS
|
||||
|
||||
* Thu Apr 07 2022 Clemens Lang <cllang@redhat.com> - 1:3.0.2-2
|
||||
- Silence a few rpmlint false positives.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user