Fix a leak in EVP_DigestInit_ex()

If an EVP_MD_CTX is reused then memory allocated and stored in md_data
can be leaked unless the EVP_MD's cleanup function is called.

Fixes #17149

Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/17255)
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 5fe80a6..cdcb600 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -25,6 +25,19 @@
 #include "crypto/evp.h"
 #include "evp_local.h"
 
+static void cleanup_old_md_data(EVP_MD_CTX *ctx, int force)
+{
+    if (ctx->digest != NULL) {
+        if (ctx->digest->cleanup != NULL
+                && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED))
+            ctx->digest->cleanup(ctx);
+        if (ctx->md_data != NULL && ctx->digest->ctx_size > 0
+                && (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)
+                    || force))
+            OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
+        ctx->md_data = NULL;
+    }
+}
 
 void evp_md_ctx_clear_digest(EVP_MD_CTX *ctx, int force)
 {
@@ -41,12 +54,7 @@
      * Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because
      * sometimes only copies of the context are ever finalised.
      */
-    if (ctx->digest && ctx->digest->cleanup
-        && !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) || force))
-        OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
+    cleanup_old_md_data(ctx, force);
     if (force)
         ctx->digest = NULL;
 
@@ -217,10 +225,7 @@
         goto legacy;
     }
 
-    if (ctx->digest != NULL && ctx->digest->ctx_size > 0) {
-        OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
-        ctx->md_data = NULL;
-    }
+    cleanup_old_md_data(ctx, 1);
 
     /* Start of non-legacy code below */
 
@@ -309,10 +314,8 @@
     }
 #endif
     if (ctx->digest != type) {
-        if (ctx->digest && ctx->digest->ctx_size) {
-            OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
-            ctx->md_data = NULL;
-        }
+        cleanup_old_md_data(ctx, 1);
+
         ctx->digest = type;
         if (!(ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) && type->ctx_size) {
             ctx->update = type->update;