diff options
author | Matt Caswell <matt@openssl.org> | 2021-12-10 17:17:27 +0000 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2022-01-10 16:38:35 +0000 |
commit | 357bccc8ba64ec8a5f587b04b5d6b6ca9e8dcbdc (patch) | |
tree | 1084f1b3497e0aee5b21aebead310d480a12cc7c /crypto/evp | |
parent | d9ad5b16b32172df6f7d02cfb1c339cc85d0db01 (diff) | |
download | openssl-new-357bccc8ba64ec8a5f587b04b5d6b6ca9e8dcbdc.tar.gz |
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)
Diffstat (limited to 'crypto/evp')
-rw-r--r-- | crypto/evp/digest.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index 5fe80a63f4..cdcb60092e 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 @@ void evp_md_ctx_clear_digest(EVP_MD_CTX *ctx, int force) * 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 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type, 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 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type, } #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; |