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