EVP: fix reference counting for digest operations.
authorPauli <ppzgs1@gmail.com>
Mon, 8 Feb 2021 00:54:52 +0000 (10:54 +1000)
committerPauli <ppzgs1@gmail.com>
Fri, 12 Feb 2021 02:28:55 +0000 (12:28 +1000)
The reference count wasn't being incremented but the EVP_MD pointer was being
held.  In a no cache build, this resulted in a failure on update in some
circumstances.

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

crypto/evp/digest.c

index 40aedae47b815d146be3d00a1c8630beaeb67dae..3dfcfcda8e9930f80c17751854138157ce13680b 100644 (file)
@@ -235,8 +235,10 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
 #else
         EVP_MD *provmd = EVP_MD_fetch(NULL, OBJ_nid2sn(type->type), "");
 
-        if (provmd == NULL)
+        if (provmd == NULL) {
+            ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
             return 0;
+        }
         type = provmd;
         EVP_MD_free(ctx->fetched_digest);
         ctx->fetched_digest = provmd;
@@ -248,6 +250,14 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
             ctx->digest->freectx(ctx->provctx);
         ctx->provctx = NULL;
     }
+    if (type->prov != NULL && ctx->fetched_digest != type) {
+        if (!EVP_MD_up_ref((EVP_MD *)type)) {
+            ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+            return 0;
+        }
+        EVP_MD_free(ctx->fetched_digest);
+        ctx->fetched_digest = (EVP_MD *)type;
+    }
     ctx->digest = type;
     if (ctx->provctx == NULL) {
         ctx->provctx = ctx->digest->newctx(ossl_provider_ctx(type->prov));