summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2021-12-10 17:17:27 +0000
committerMatt Caswell <matt@openssl.org>2022-01-13 11:45:45 +0000
commit93dd7ab35f6ccfb8bde7a7a6e38ea5817c5b54e2 (patch)
tree07a9123add74398ae68b4da813ccbcc7bfc10477
parent5e7098e11581b6b3a4083a1c17889ed817e8ac22 (diff)
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: Paul Dale <pauli@openssl.org> Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/17472)
-rw-r--r--crypto/evp/digest.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index d1bfa274ca..41ecdd8e5a 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -15,6 +15,22 @@
#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;
+ }
+ }
+}
+
/* This call frees resources associated with the context */
int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
{
@@ -25,13 +41,8 @@ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
* 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)) {
- OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
- }
+ cleanup_old_md_data(ctx, 0);
+
/*
* pctx should be freed by the user of EVP_MD_CTX
* if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set
@@ -76,6 +87,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
if (ctx->engine && ctx->digest &&
(type == NULL || (type->type == ctx->digest->type)))
goto skip_to_init;
+
if (type) {
/*
* Ensure an ENGINE left lying around from last time is cleared (the
@@ -119,10 +131,8 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
}
#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;