Blob Blame History Raw
From 428369896db1656af748a67bb36fba039e7b39ad Mon Sep 17 00:00:00 2001
From: Clemens Lang <cllang@redhat.com>
Date: Mon, 25 Apr 2022 15:21:46 +0200
Subject: [PATCH] Instrument SHA-1 signatures with USDT probes

In order to discover remaining uses of SHA-1 in signatures without
forcefully breaking the code paths, add USDT probes that can be queried
with systemtap at runtime.

This should allow identifying components that still use SHA-1 signatures
in production so that they can be transitioned to more modern hash
algorithms.
---
 crypto/evp/m_sigver.c                    | 13 +++++++++----
 crypto/evp/pmeth_lib.c                   | 13 +++++++++----
 crypto/x509/x509_vfy.c                   |  6 +++++-
 providers/common/securitycheck.c         | 22 +++++++++++++++-------
 providers/common/securitycheck_default.c | 13 +++++++++++--
 ssl/t1_lib.c                             |  8 +++++++-
 6 files changed, 56 insertions(+), 19 deletions(-)

diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c
index 8da2183ce0..c17cdfa5d5 100644
--- a/crypto/evp/m_sigver.c
+++ b/crypto/evp/m_sigver.c
@@ -16,6 +16,8 @@
 #include "internal/numbers.h"   /* includes SIZE_MAX */
 #include "evp_local.h"
 
+#include <sys/sdt.h>
+
 typedef struct ossl_legacy_digest_signatures_st {
     int allowed;
 } OSSL_LEGACY_DIGEST_SIGNATURES;
@@ -336,10 +338,13 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
             && !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 (mdnid == NID_sha1 || mdnid == NID_md5_sha1) {
+            if (!ossl_ctx_legacy_digest_signatures_allowed(locpctx->libctx, 0)) {
+                ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_DIGEST);
+                goto err;
+            } else {
+                DTRACE_PROBE1(libcrypto, fedora_do_sigver_init_1, mdnid);
+            }
         }
     }
 
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index b96f148c0d..54fcf24945 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -37,6 +37,8 @@
 #include "internal/sslconf.h"
 #include "evp_local.h"
 
+#include <sys/sdt.h>
+
 #ifndef FIPS_MODULE
 
 static int evp_pkey_ctx_store_cached_data(EVP_PKEY_CTX *ctx,
@@ -956,10 +958,13 @@ static int evp_pkey_ctx_set_md(EVP_PKEY_CTX *ctx, const EVP_MD *md,
             && !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 (mdnid == NID_sha1 || mdnid == NID_md5_sha1) {
+            if (!ossl_ctx_legacy_digest_signatures_allowed(ctx->libctx, 0)) {
+                ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_DIGEST);
+                return -1;
+            } else {
+                DTRACE_PROBE1(libcrypto, fedora_evp_pkey_ctx_set_md_1, mdnid);
+            }
         }
     }
 
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index bf0c608839..78638ce80e 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -29,6 +29,8 @@
 #include "crypto/x509.h"
 #include "x509_local.h"
 
+#include <sys/sdt.h>
+
 /* CRL score values */
 
 #define CRL_SCORE_NOCRITICAL    0x100 /* No unhandled critical extensions */
@@ -3462,11 +3464,13 @@ static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert)
 
     if ((nid == NID_sha1 || nid == NID_md5_sha1)
             && ossl_ctx_legacy_digest_signatures_allowed(libctx, 0)
-            && ctx->param->auth_level < 2)
+            && ctx->param->auth_level < 2) {
+        DTRACE_PROBE1(libcrypto, fedora_check_sig_level_1, nid);
         /* When rh-allow-sha1-signatures = yes and security level <= 1,
          * explicitly allow SHA1 for backwards compatibility. Also allow
          * MD5-SHA1 because TLS 1.0 is still supported, which uses it. */
         return 1;
+    }
 
     return secbits >= minbits_table[level - 1];
 }
diff --git a/providers/common/securitycheck.c b/providers/common/securitycheck.c
index e534ad0a5f..bf496450cf 100644
--- a/providers/common/securitycheck.c
+++ b/providers/common/securitycheck.c
@@ -21,6 +21,8 @@
 #include "prov/securitycheck.h"
 #include "internal/sslconf.h"
 
+#include <sys/sdt.h>
+
 /*
  * FIPS requires a minimum security strength of 112 bits (for encryption or
  * signing), and for legacy purposes 80 bits (for decryption or verifying).
@@ -238,11 +240,14 @@ int ossl_digest_get_approved_nid_with_sha1(OSSL_LIB_CTX *ctx, const EVP_MD *md,
 # 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)
+    if (mdnid == NID_sha1 && !sha1_allowed) {
+        if (!ossl_ctx_legacy_digest_signatures_allowed(ctx, 0))
+            /* SHA1 is globally disabled, check whether we want to locally allow
+             * it. */
             mdnid = -1;
+        else
+            DTRACE_PROBE1(libcrypto, fedora_ossl_digest_get_approved_nid_with_sha1_1, mdnid);
+    }
 #endif
 
     return mdnid;
@@ -258,9 +263,12 @@ int ossl_digest_is_allowed(OSSL_LIB_CTX *ctx, const EVP_MD *md)
 #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;
+        if (mdnid == NID_sha1 || mdnid == NID_md5_sha1) {
+            if (!ossl_ctx_legacy_digest_signatures_allowed(ctx, 0))
+                return 0;
+            else
+                DTRACE_PROBE1(libcrypto, fedora_ossl_digest_is_allowed_1, mdnid);
+        }
     }
 #endif
 
diff --git a/providers/common/securitycheck_default.c b/providers/common/securitycheck_default.c
index ce54a94fbc..2d21e4a7df 100644
--- a/providers/common/securitycheck_default.c
+++ b/providers/common/securitycheck_default.c
@@ -17,6 +17,8 @@
 #include "internal/nelem.h"
 #include "internal/sslconf.h"
 
+#include <sys/sdt.h>
+
 /* Disable the security checks in the default provider */
 int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx)
 {
@@ -40,9 +42,16 @@ int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md,
 
     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_sha1)
+        /* This will only happen if SHA1 is allowed, otherwise mdnid is -1. */
+        DTRACE_PROBE1(libcrypto, fedora_ossl_digest_rsa_sign_get_md_nid_1, mdnid);
     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;
+    if (mdnid == NID_md5_sha1) {
+        if (ldsigs_allowed)
+            DTRACE_PROBE1(libcrypto, fedora_ossl_digest_rsa_sign_get_md_nid_2, mdnid);
+        else
+            mdnid = -1;
+    }
     return mdnid;
 }
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 0b50266b69..d05e696a28 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -28,6 +28,8 @@
 #include "ssl_local.h"
 #include <openssl/ct.h>
 
+#include <sys/sdt.h>
+
 static const SIGALG_LOOKUP *find_sig_alg(SSL *s, X509 *x, EVP_PKEY *pkey);
 static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu);
 
@@ -1569,6 +1571,7 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
         /* When rh-allow-sha1-signatures = yes and security level <= 1,
          * explicitly allow SHA1 for backwards compatibility. Also allow
          * MD5-SHA1 because TLS 1.0 is still supported, which uses it. */
+        DTRACE_PROBE1(libssl, fedora_tls12_check_peer_sigalg_1, lu->hash);
     } else {
         /*
          * Make sure security callback allows algorithm. For historical
@@ -2122,6 +2125,7 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
         /* When rh-allow-sha1-signatures = yes and security level <= 1,
          * explicitly allow SHA1 for backwards compatibility. Also allow
          * MD5-SHA1 because TLS 1.0 is still supported, which uses it. */
+        DTRACE_PROBE1(libssl, fedora_tls12_sigalg_allowed_1, lu->hash);
         return 1;
     }
 
@@ -3020,11 +3024,13 @@ static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op)
             && 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. Also allow
          * MD5-SHA1 because TLS 1.0 is still supported, which uses it. */
+        DTRACE_PROBE1(libssl, fedora_ssl_security_cert_sig_1, nid);
         return 1;
+    }
 
     if (s)
         return ssl_security(s, op, secbits, nid, x);
-- 
2.35.1