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