Blame SOURCES/0052-Allow-SHA1-in-seclevel-2-if-rh-allow-sha1-signatures.patch

f57b16
From c63599ee9708d543205a9173207ee7167315c624 Mon Sep 17 00:00:00 2001
f57b16
From: Clemens Lang <cllang@redhat.com>
f57b16
Date: Tue, 1 Mar 2022 15:44:18 +0100
f57b16
Subject: [PATCH] Allow SHA1 in seclevel 2 if rh-allow-sha1-signatures = yes
f57b16
f57b16
References: rhbz#2055796
f57b16
---
f57b16
 crypto/x509/x509_vfy.c        | 19 ++++++++++-
f57b16
 doc/man5/config.pod           |  7 +++-
f57b16
 ssl/t1_lib.c                  | 64 ++++++++++++++++++++++++++++-------
f57b16
 test/recipes/25-test_verify.t |  7 ++--
f57b16
 4 files changed, 79 insertions(+), 18 deletions(-)
f57b16
f57b16
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
f57b16
index ff3ca83de6..a549c1c111 100644
f57b16
--- a/crypto/x509/x509_vfy.c
f57b16
+++ b/crypto/x509/x509_vfy.c
f57b16
@@ -25,6 +25,7 @@
f57b16
 #include <openssl/objects.h>
f57b16
 #include <openssl/core_names.h>
f57b16
 #include "internal/dane.h"
f57b16
+#include "internal/sslconf.h"
f57b16
 #include "crypto/x509.h"
f57b16
 #include "x509_local.h"
f57b16
 
f57b16
@@ -3440,14 +3441,30 @@ static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert)
f57b16
 {
f57b16
     int secbits = -1;
f57b16
     int level = ctx->param->auth_level;
f57b16
+    int nid;
f57b16
+    OSSL_LIB_CTX *libctx = NULL;
f57b16
 
f57b16
     if (level <= 0)
f57b16
         return 1;
f57b16
     if (level > NUM_AUTH_LEVELS)
f57b16
         level = NUM_AUTH_LEVELS;
f57b16
 
f57b16
-    if (!X509_get_signature_info(cert, NULL, NULL, &secbits, NULL))
f57b16
+    if (ctx->libctx)
f57b16
+        libctx = ctx->libctx;
f57b16
+    else if (cert->libctx)
f57b16
+        libctx = cert->libctx;
f57b16
+    else
f57b16
+        libctx = OSSL_LIB_CTX_get0_global_default();
f57b16
+
f57b16
+    if (!X509_get_signature_info(cert, &nid, NULL, &secbits, NULL))
f57b16
         return 0;
f57b16
 
f57b16
+    if (nid == NID_sha1
f57b16
+            && ossl_ctx_legacy_digest_signatures_allowed(libctx, 0)
f57b16
+            && ctx->param->auth_level < 3)
f57b16
+        /* When rh-allow-sha1-signatures = yes and security level <= 2,
f57b16
+         * explicitly allow SHA1 for backwards compatibility. */
f57b16
+        return 1;
f57b16
+
f57b16
     return secbits >= minbits_table[level - 1];
f57b16
 }
f57b16
diff --git a/doc/man5/config.pod b/doc/man5/config.pod
f57b16
index aa1be5ca7f..aa69e2b844 100644
f57b16
--- a/doc/man5/config.pod
f57b16
+++ b/doc/man5/config.pod
f57b16
@@ -305,7 +305,12 @@ When set to B<no>, any attempt to create or verify a signature with a SHA1
f57b16
 digest will fail.  For compatibility with older versions of OpenSSL, set this
f57b16
 option to B<yes>.  This setting also affects TLS, where signature algorithms
f57b16
 that use SHA1 as digest will no longer be supported if this option is set to
f57b16
-B<no>.
f57b16
+B<no>.  Note that enabling B<rh-allow-sha1-signatures> will allow TLS signature
f57b16
+algorithms that use SHA1 in security level 2, despite the definition of
f57b16
+security level 2 of 112 bits of security, which SHA1 does not meet.  Because
f57b16
+TLS 1.1 or lower use MD5-SHA1 as pseudorandom function (PRF) to derive key
f57b16
+material, disabling B<rh-allow-sha1-signatures> requires the use of TLS 1.2 or
f57b16
+newer.
f57b16
 
f57b16
 =item B<fips_mode> (deprecated)
f57b16
 
f57b16
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
f57b16
index 4b74ee1a34..5f089de107 100644
f57b16
--- a/ssl/t1_lib.c
f57b16
+++ b/ssl/t1_lib.c
f57b16
@@ -20,6 +20,7 @@
f57b16
 #include <openssl/bn.h>
f57b16
 #include <openssl/provider.h>
f57b16
 #include <openssl/param_build.h>
f57b16
+#include "crypto/x509.h"
f57b16
 #include "internal/sslconf.h"
f57b16
 #include "internal/nelem.h"
f57b16
 #include "internal/sizes.h"
f57b16
@@ -1561,19 +1562,27 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
f57b16
         SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_UNKNOWN_DIGEST);
f57b16
         return 0;
f57b16
     }
f57b16
-    /*
f57b16
-     * Make sure security callback allows algorithm. For historical
f57b16
-     * reasons we have to pass the sigalg as a two byte char array.
f57b16
-     */
f57b16
-    sigalgstr[0] = (sig >> 8) & 0xff;
f57b16
-    sigalgstr[1] = sig & 0xff;
f57b16
-    secbits = sigalg_security_bits(s->ctx, lu);
f57b16
-    if (secbits == 0 ||
f57b16
-        !ssl_security(s, SSL_SECOP_SIGALG_CHECK, secbits,
f57b16
-                      md != NULL ? EVP_MD_get_type(md) : NID_undef,
f57b16
-                      (void *)sigalgstr)) {
f57b16
-        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_WRONG_SIGNATURE_TYPE);
f57b16
-        return 0;
f57b16
+
f57b16
+    if (lu->hash == NID_sha1
f57b16
+            && ossl_ctx_legacy_digest_signatures_allowed(s->ctx->libctx, 0)
f57b16
+            && SSL_get_security_level(s) < 3) {
f57b16
+        /* when rh-allow-sha1-signatures = yes and security level <= 2,
f57b16
+         * explicitly allow SHA1 for backwards compatibility */
f57b16
+    } else {
f57b16
+        /*
f57b16
+         * Make sure security callback allows algorithm. For historical
f57b16
+         * reasons we have to pass the sigalg as a two byte char array.
f57b16
+         */
f57b16
+        sigalgstr[0] = (sig >> 8) & 0xff;
f57b16
+        sigalgstr[1] = sig & 0xff;
f57b16
+        secbits = sigalg_security_bits(s->ctx, lu);
f57b16
+        if (secbits == 0 ||
f57b16
+            !ssl_security(s, SSL_SECOP_SIGALG_CHECK, secbits,
f57b16
+                          md != NULL ? EVP_MD_get_type(md) : NID_undef,
f57b16
+                          (void *)sigalgstr)) {
f57b16
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_WRONG_SIGNATURE_TYPE);
f57b16
+            return 0;
f57b16
+        }
f57b16
     }
f57b16
     /* Store the sigalg the peer uses */
f57b16
     s->s3.tmp.peer_sigalg = lu;
f57b16
@@ -2106,6 +2115,14 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
f57b16
         }
f57b16
     }
f57b16
 
f57b16
+    if (lu->hash == NID_sha1
f57b16
+            && ossl_ctx_legacy_digest_signatures_allowed(s->ctx->libctx, 0)
f57b16
+            && SSL_get_security_level(s) < 3) {
f57b16
+        /* when rh-allow-sha1-signatures = yes and security level <= 2,
f57b16
+         * explicitly allow SHA1 for backwards compatibility */
f57b16
+        return 1;
f57b16
+    }
f57b16
+
f57b16
     /* Finally see if security callback allows it */
f57b16
     secbits = sigalg_security_bits(s->ctx, lu);
f57b16
     sigalgstr[0] = (lu->sigalg >> 8) & 0xff;
f57b16
@@ -2977,6 +2994,8 @@ static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op)
f57b16
 {
f57b16
     /* Lookup signature algorithm digest */
f57b16
     int secbits, nid, pknid;
f57b16
+    OSSL_LIB_CTX *libctx = NULL;
f57b16
+
f57b16
     /* Don't check signature if self signed */
f57b16
     if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0)
f57b16
         return 1;
f57b16
@@ -2985,6 +3004,25 @@ static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op)
f57b16
     /* If digest NID not defined use signature NID */
f57b16
     if (nid == NID_undef)
f57b16
         nid = pknid;
f57b16
+
f57b16
+    if (x && x->libctx)
f57b16
+        libctx = x->libctx;
f57b16
+    else if (ctx && ctx->libctx)
f57b16
+        libctx = ctx->libctx;
f57b16
+    else if (s && s->ctx && s->ctx->libctx)
f57b16
+        libctx = s->ctx->libctx;
f57b16
+    else
f57b16
+        libctx = OSSL_LIB_CTX_get0_global_default();
f57b16
+
f57b16
+    if (nid == NID_sha1
f57b16
+            && ossl_ctx_legacy_digest_signatures_allowed(libctx, 0)
f57b16
+            && ((s != NULL && SSL_get_security_level(s) < 3)
f57b16
+                || (ctx != NULL && SSL_CTX_get_security_level(ctx) < 3)
f57b16
+            ))
f57b16
+        /* When rh-allow-sha1-signatures = yes and security level <= 2,
f57b16
+         * explicitly allow SHA1 for backwards compatibility. */
f57b16
+        return 1;
f57b16
+
f57b16
     if (s)
f57b16
         return ssl_security(s, op, secbits, nid, x);
f57b16
     else
f57b16
diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t
f57b16
index 700bbd849c..2de1d76b5e 100644
f57b16
--- a/test/recipes/25-test_verify.t
f57b16
+++ b/test/recipes/25-test_verify.t
f57b16
@@ -29,7 +29,7 @@ sub verify {
f57b16
     run(app([@args]));
f57b16
 }
f57b16
 
22d461
-plan tests => 163;
22d461
+plan tests => 162;
f57b16
 
f57b16
 # Canonical success
f57b16
 ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]),
f57b16
@@ -387,8 +387,9 @@ ok(verify("ee-pss-sha1-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "0"
f57b16
 ok(verify("ee-pss-sha256-cert", "", ["root-cert"], ["ca-cert"], ),
f57b16
     "CA with PSS signature using SHA256");
f57b16
 
f57b16
-ok(!verify("ee-pss-sha1-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "1"),
f57b16
-    "Reject PSS signature using SHA1 and auth level 1");
f57b16
+## rh-allow-sha1-signatures=yes allows this to pass despite -auth_level 1
f57b16
+#ok(!verify("ee-pss-sha1-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "1"),
f57b16
+#    "Reject PSS signature using SHA1 and auth level 1");
f57b16
 
f57b16
 ok(verify("ee-pss-sha256-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "2"),
f57b16
     "PSS signature using SHA256 and auth level 2");
f57b16
-- 
f57b16
2.35.1
f57b16