From 115eb945acd9a27bf81c6c8923f43768f9e487a8 Mon Sep 17 00:00:00 2001 From: K1 Date: Wed, 8 Jun 2022 16:41:16 +0800 Subject: Fix a mem leak in evp_pkey_export_to_provider If keymgmt is NULL, tmp_keymgmt is allocated and will not be freed. Reviewed-by: Tomas Mraz Reviewed-by: Paul Yang Reviewed-by: Todd Short (Merged from https://github.com/openssl/openssl/pull/18499) --- crypto/evp/p_lib.c | 6 ++- test/keymgmt_internal_test.c | 66 +++++++++++++++++++++++++++++++++ test/recipes/02-test_internal_keymgmt.t | 9 +++-- 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index db1822f0d1..8d2eee11f1 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -1853,7 +1853,7 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx, if (ctx == NULL) goto end; - tmp_keymgmt = ctx->keymgmt; + allocated_keymgmt = tmp_keymgmt = ctx->keymgmt; ctx->keymgmt = NULL; EVP_PKEY_CTX_free(ctx); } @@ -1966,8 +1966,10 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx, if (keydata == NULL) tmp_keymgmt = NULL; - if (keymgmt != NULL) + if (keymgmt != NULL && tmp_keymgmt != NULL) { *keymgmt = tmp_keymgmt; + allocated_keymgmt = NULL; + } EVP_KEYMGMT_free(allocated_keymgmt); return keydata; diff --git a/test/keymgmt_internal_test.c b/test/keymgmt_internal_test.c index dd0de2f599..0f2030e61f 100644 --- a/test/keymgmt_internal_test.c +++ b/test/keymgmt_internal_test.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include "internal/core.h" @@ -33,6 +34,9 @@ typedef struct { OSSL_PROVIDER *prov2; } FIXTURE; +/* Collected arguments */ +static const char *cert_filename = NULL; + static void tear_down(FIXTURE *fixture) { if (fixture != NULL) { @@ -285,8 +289,70 @@ static int test_pass_key(int n) return result; } +static int test_evp_pkey_export_to_provider(int n) +{ + OSSL_LIB_CTX *libctx = NULL; + OSSL_PROVIDER *prov = NULL; + X509 *cert = NULL; + BIO *bio = NULL; + X509_PUBKEY *pubkey = NULL; + EVP_KEYMGMT *keymgmt = NULL; + EVP_PKEY *pkey = NULL; + void *keydata = NULL; + int ret = 0; + + if (!TEST_ptr(libctx = OSSL_LIB_CTX_new()) + || !TEST_ptr(prov = OSSL_PROVIDER_load(libctx, "default"))) + goto end; + + if ((bio = BIO_new_file(cert_filename, "r")) == NULL) { + TEST_error("Couldn't open '%s' for reading\n", cert_filename); + TEST_openssl_errors(); + goto end; + } + + if ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) { + TEST_error("'%s' doesn't appear to be a X.509 certificate in PEM format\n", + cert_filename); + TEST_openssl_errors(); + goto end; + } + + pubkey = X509_get_X509_PUBKEY(cert); + pkey = X509_PUBKEY_get0(pubkey); + + if (n == 0) { + if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL, + NULL, NULL))) + goto end; + } else if (n == 1) { + if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL, + &keymgmt, NULL))) + goto end; + } else { + keymgmt = EVP_KEYMGMT_fetch(libctx, "RSA", NULL); + + if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL, + &keymgmt, NULL))) + goto end; + } + + ret = 1; + end: + BIO_free(bio); + X509_free(cert); + EVP_KEYMGMT_free(keymgmt); + OSSL_PROVIDER_unload(prov); + OSSL_LIB_CTX_free(libctx); + return ret; +} + int setup_tests(void) { + if (!TEST_ptr(cert_filename = test_get_argument(0))) + return 0; + ADD_ALL_TESTS(test_pass_key, 1); + ADD_ALL_TESTS(test_evp_pkey_export_to_provider, 3); return 1; } diff --git a/test/recipes/02-test_internal_keymgmt.t b/test/recipes/02-test_internal_keymgmt.t index 269f624467..28f510f164 100644 --- a/test/recipes/02-test_internal_keymgmt.t +++ b/test/recipes/02-test_internal_keymgmt.t @@ -7,12 +7,15 @@ # https://www.openssl.org/source/license.html use strict; -use OpenSSL::Test qw(:DEFAULT bldtop_dir); -use OpenSSL::Test::Simple; +use OpenSSL::Test qw(:DEFAULT bldtop_dir srctop_file); use OpenSSL::Test::Utils; setup("test_internal_keymgmt"); +plan tests => 1; + $ENV{OPENSSL_MODULES} = bldtop_dir("test"); -simple_test("test_internal_keymgmt", "keymgmt_internal_test"); +ok(run(test(["keymgmt_internal_test", + srctop_file("test", "certs", "ee-cert.pem")])), + "running test_internal_keymgmt"); -- cgit v1.2.3