]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Fix an EVP_MD_CTX leak
authorMatt Caswell <matt@openssl.org>
Thu, 3 Sep 2020 10:50:30 +0000 (11:50 +0100)
committerTomas Mraz <tmraz@fedoraproject.org>
Thu, 10 Sep 2020 09:35:42 +0000 (11:35 +0200)
If we initialise an EVP_MD_CTX with a legacy MD, and then reuse the same
EVP_MD_CTX with a provided MD then we end up leaking the md_data.

We need to ensure we free the md_data if we change to a provided MD.

Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/12779)

crypto/evp/digest.c
crypto/evp/m_sigver.c
include/crypto/evp.h

index 19fddb74abef70b971e123c3c123a75bb147f298..07bf12e5aed46fc926a7bb8da1157b3753eba437 100644 (file)
 #include "internal/provider.h"
 #include "evp_local.h"
 
-/* This call frees resources associated with the context */
-int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
-{
-    if (ctx == NULL)
-        return 1;
-
-#ifndef FIPS_MODULE
-    /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */
-    /*
-     * pctx should be freed by the user of EVP_MD_CTX
-     * if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set
-     */
-    if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) {
-        EVP_PKEY_CTX_free(ctx->pctx);
-        ctx->pctx = NULL;
-    }
-#endif
 
+void evp_md_ctx_clear_digest(EVP_MD_CTX *ctx, int force)
+{
     EVP_MD_free(ctx->fetched_digest);
     ctx->fetched_digest = NULL;
     ctx->reqdigest = NULL;
@@ -61,16 +46,36 @@ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
         && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED))
         ctx->digest->cleanup(ctx);
     if (ctx->digest && ctx->digest->ctx_size && ctx->md_data
-        && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) {
+            && (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE) || force))
         OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
-    }
+    if (force)
+        ctx->digest = NULL;
 
 #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
     ENGINE_finish(ctx->engine);
+    ctx->engine = NULL;
 #endif
+}
 
-    /* TODO(3.0): End of legacy code */
+/* This call frees resources associated with the context */
+int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
+{
+    if (ctx == NULL)
+        return 1;
+
+#ifndef FIPS_MODULE
+    /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */
+    /*
+     * pctx should be freed by the user of EVP_MD_CTX
+     * if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set
+     */
+    if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) {
+        EVP_PKEY_CTX_free(ctx->pctx);
+        ctx->pctx = NULL;
+    }
+#endif
 
+    evp_md_ctx_clear_digest(ctx, 0);
     OPENSSL_cleanse(ctx, sizeof(*ctx));
 
     return 1;
index a60d6e770b1df37e037c7c55b27a97d39703d0fe..e2bb613a20132a22215893d6214cccd43cac611d 100644 (file)
@@ -176,6 +176,12 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
         }
 
         if (mdname != NULL) {
+            /*
+             * We're about to get a new digest so clear anything associated with
+             * an old digest.
+             */
+            evp_md_ctx_clear_digest(ctx, 1);
+
             /*
              * This might be requested by a later call to EVP_MD_CTX_md().
              * In that case the "explicit fetch" rules apply for that
@@ -185,6 +191,10 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
              */
             ctx->digest = ctx->reqdigest = ctx->fetched_digest =
                 EVP_MD_fetch(locpctx->libctx, mdname, props);
+            if (ctx->digest == NULL) {
+                ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+                goto err;
+            }
         }
     }
 
index 9d9b0a7298c516ab908e1bdb425b3d7095179c1b..bdff97f639783907e5f574f0120416dfb3ea685e 100644 (file)
@@ -808,3 +808,5 @@ int evp_pkey_ctx_use_cached_data(EVP_PKEY_CTX *ctx);
 void evp_method_store_flush(OPENSSL_CTX *libctx);
 int evp_set_default_properties_int(OPENSSL_CTX *libctx, const char *propq,
                                    int loadconfig);
+
+void evp_md_ctx_clear_digest(EVP_MD_CTX *ctx, int force);