From: Richard Levitte Date: Tue, 3 Sep 2019 15:47:13 +0000 (+0200) Subject: New function EVP_MD_free() X-Git-Tag: openssl-3.0.0-alpha1~1507 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=3fd7026276475d72a3b5bbbe42cd1f5ff6b0e736;p=oweals%2Fopenssl.git New function EVP_MD_free() This function re-implements EVP_MD_meth_free(), but has a name that isn't encumbered by legacy EVP_MD construction functionality. We also refactor most of EVP_MD_meth_new() into an internal evp_md_new() that's used when creating fetched methods. EVP_MD_meth_new() and EVP_MD_meth_free() are rewritten in terms of evp_md_new() and EVP_MD_free(). This means that at any time, we can deprecate all the EVP_MD_meth_ functions with no harmful consequence. Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/9758) --- diff --git a/apps/list.c b/apps/list.c index 446a6e1ab9..f3ef233c84 100644 --- a/apps/list.c +++ b/apps/list.c @@ -143,7 +143,7 @@ static void list_digests(void) EVP_MD_CTX_settable_params(m), 4); } } - sk_EVP_MD_pop_free(digests, EVP_MD_meth_free); + sk_EVP_MD_pop_free(digests, EVP_MD_free); } DEFINE_STACK_OF(EVP_MAC) diff --git a/crypto/bn/bn_rand.c b/crypto/bn/bn_rand.c index d1743ddf7a..fa75a3b10e 100644 --- a/crypto/bn/bn_rand.c +++ b/crypto/bn/bn_rand.c @@ -310,7 +310,7 @@ int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, err: EVP_MD_CTX_free(mdctx); - EVP_MD_meth_free(md); + EVP_MD_free(md); OPENSSL_free(k_bytes); OPENSSL_cleanse(private_bytes, sizeof(private_bytes)); return ret; diff --git a/crypto/ec/curve448/eddsa.c b/crypto/ec/curve448/eddsa.c index 58e9e92d4c..45b6c4ab69 100644 --- a/crypto/ec/curve448/eddsa.c +++ b/crypto/ec/curve448/eddsa.c @@ -41,7 +41,7 @@ static c448_error_t oneshot_hash(OPENSSL_CTX *ctx, uint8_t *out, size_t outlen, ret = C448_SUCCESS; err: EVP_MD_CTX_free(hashctx); - EVP_MD_meth_free(shake256); + EVP_MD_free(shake256); return ret; } @@ -77,11 +77,11 @@ static c448_error_t hash_init_with_dom(OPENSSL_CTX *ctx, EVP_MD_CTX *hashctx, || !EVP_DigestUpdate(hashctx, dom_s, strlen(dom_s)) || !EVP_DigestUpdate(hashctx, dom, sizeof(dom)) || !EVP_DigestUpdate(hashctx, context, context_len)) { - EVP_MD_meth_free(shake256); + EVP_MD_free(shake256); return C448_FAILURE; } - EVP_MD_meth_free(shake256); + EVP_MD_free(shake256); return C448_SUCCESS; } diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index bb6d31bf4f..6cb9064b6c 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -86,7 +86,7 @@ void EVP_MD_CTX_free(EVP_MD_CTX *ctx) EVP_MD_CTX_reset(ctx); - EVP_MD_meth_free(ctx->fetched_digest); + EVP_MD_free(ctx->fetched_digest); ctx->fetched_digest = NULL; ctx->digest = NULL; ctx->reqdigest = NULL; @@ -156,7 +156,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) || (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0) { if (ctx->digest == ctx->fetched_digest) ctx->digest = NULL; - EVP_MD_meth_free(ctx->fetched_digest); + EVP_MD_free(ctx->fetched_digest); ctx->fetched_digest = NULL; goto legacy; } @@ -181,7 +181,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) return 0; } type = provmd; - EVP_MD_meth_free(ctx->fetched_digest); + EVP_MD_free(ctx->fetched_digest); ctx->fetched_digest = provmd; #endif } @@ -415,7 +415,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) EVP_MD_CTX_reset(out); if (out->fetched_digest != NULL) - EVP_MD_meth_free(out->fetched_digest); + EVP_MD_free(out->fetched_digest); *out = *in; /* NULL out pointers in case of error */ out->pctx = NULL; @@ -616,6 +616,21 @@ int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2) return ret; } +EVP_MD *evp_md_new(void) +{ + EVP_MD *md = OPENSSL_zalloc(sizeof(*md)); + + if (md != NULL) { + md->lock = CRYPTO_THREAD_lock_new(); + if (md->lock == NULL) { + OPENSSL_free(md); + return NULL; + } + md->refcnt = 1; + } + return md; +} + static void *evp_md_from_dispatch(const char *name, const OSSL_DISPATCH *fns, OSSL_PROVIDER *prov, void *unused) { @@ -623,9 +638,9 @@ static void *evp_md_from_dispatch(const char *name, const OSSL_DISPATCH *fns, int fncnt = 0; /* EVP_MD_fetch() will set the legacy NID if available */ - if ((md = EVP_MD_meth_new(NID_undef, NID_undef)) == NULL + if ((md = evp_md_new()) == NULL || (md->name = OPENSSL_strdup(name)) == NULL) { - EVP_MD_meth_free(md); + EVP_MD_free(md); EVPerr(0, ERR_R_MALLOC_FAILURE); return NULL; } @@ -718,7 +733,7 @@ static void *evp_md_from_dispatch(const char *name, const OSSL_DISPATCH *fns, * The "digest" function can standalone. We at least need one way to * generate digests. */ - EVP_MD_meth_free(md); + EVP_MD_free(md); ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); return NULL; } @@ -736,7 +751,7 @@ static int evp_md_up_ref(void *md) static void evp_md_free(void *md) { - EVP_MD_meth_free(md); + EVP_MD_free(md); } EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm, @@ -750,6 +765,30 @@ EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm, return md; } +int EVP_MD_up_ref(EVP_MD *md) +{ + int ref = 0; + + CRYPTO_UP_REF(&md->refcnt, &ref, md->lock); + return 1; +} + +void EVP_MD_free(EVP_MD *md) +{ + int i; + + if (md == NULL) + return; + + CRYPTO_DOWN_REF(&md->refcnt, &i, md->lock); + if (i > 0) + return; + ossl_provider_free(md->prov); + OPENSSL_free(md->name); + CRYPTO_THREAD_lock_free(md->lock); + OPENSSL_free(md); +} + void EVP_MD_do_all_ex(OPENSSL_CTX *libctx, void (*fn)(EVP_MD *mac, void *arg), void *arg) diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index 460a5db003..b5b39a7f2d 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -529,54 +529,38 @@ unsigned long EVP_MD_flags(const EVP_MD *md) EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type) { - EVP_MD *md = OPENSSL_zalloc(sizeof(*md)); + EVP_MD *md = evp_md_new(); if (md != NULL) { md->type = md_type; md->pkey_type = pkey_type; - md->lock = CRYPTO_THREAD_lock_new(); - if (md->lock == NULL) { - OPENSSL_free(md); - return NULL; - } - md->refcnt = 1; } return md; } EVP_MD *EVP_MD_meth_dup(const EVP_MD *md) { - EVP_MD *to = EVP_MD_meth_new(md->type, md->pkey_type); + EVP_MD *to = NULL; - if (to != NULL) { + /* + * Non-legacy EVP_MDs can't be duplicated like this. + * Use EVP_MD_up_ref() instead. + */ + if (md->prov != NULL) + return NULL; + + if ((to = EVP_MD_meth_new(md->type, md->pkey_type)) != NULL) { CRYPTO_RWLOCK *lock = to->lock; + memcpy(to, md, sizeof(*to)); to->lock = lock; } return to; } -int EVP_MD_up_ref(EVP_MD *md) -{ - int ref = 0; - - CRYPTO_UP_REF(&md->refcnt, &ref, md->lock); - return 1; -} - void EVP_MD_meth_free(EVP_MD *md) { - if (md != NULL) { - int i; - - CRYPTO_DOWN_REF(&md->refcnt, &i, md->lock); - if (i > 0) - return; - ossl_provider_free(md->prov); - OPENSSL_free(md->name); - CRYPTO_THREAD_lock_free(md->lock); - OPENSSL_free(md); - } + EVP_MD_free(md); } int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize) { diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h index a7b36dbc0e..4342956531 100644 --- a/crypto/evp/evp_locl.h +++ b/crypto/evp/evp_locl.h @@ -156,6 +156,9 @@ void evp_generic_do_all(OPENSSL_CTX *libctx, int operation_id, void *method_data, void (*free_method)(void *)); +/* Internal structure constructors for fetched methods */ +EVP_MD *evp_md_new(void); + /* Helper functions to avoid duplicating code */ /* diff --git a/crypto/rand/drbg_hash.c b/crypto/rand/drbg_hash.c index bb6f36ce54..6bef917e0f 100644 --- a/crypto/rand/drbg_hash.c +++ b/crypto/rand/drbg_hash.c @@ -290,7 +290,7 @@ static int drbg_hash_generate(RAND_DRBG *drbg, static int drbg_hash_uninstantiate(RAND_DRBG *drbg) { - EVP_MD_meth_free(drbg->data.hash.md); + EVP_MD_free(drbg->data.hash.md); EVP_MD_CTX_free(drbg->data.hash.ctx); OPENSSL_cleanse(&drbg->data.hash, sizeof(drbg->data.hash)); return 1; @@ -346,12 +346,12 @@ int drbg_hash_init(RAND_DRBG *drbg) if (hash->ctx == NULL) { hash->ctx = EVP_MD_CTX_new(); if (hash->ctx == NULL) { - EVP_MD_meth_free(md); + EVP_MD_free(md); return 0; } } - EVP_MD_meth_free(hash->md); + EVP_MD_free(hash->md); hash->md = md; /* These are taken from SP 800-90 10.1 Table 2 */ diff --git a/crypto/rand/drbg_hmac.c b/crypto/rand/drbg_hmac.c index baafc59064..14c4570b6b 100644 --- a/crypto/rand/drbg_hmac.c +++ b/crypto/rand/drbg_hmac.c @@ -184,7 +184,7 @@ static int drbg_hmac_generate(RAND_DRBG *drbg, static int drbg_hmac_uninstantiate(RAND_DRBG *drbg) { - EVP_MD_meth_free(drbg->data.hmac.md); + EVP_MD_free(drbg->data.hmac.md); HMAC_CTX_free(drbg->data.hmac.ctx); OPENSSL_cleanse(&drbg->data.hmac, sizeof(drbg->data.hmac)); return 1; @@ -239,13 +239,13 @@ int drbg_hmac_init(RAND_DRBG *drbg) if (hmac->ctx == NULL) { hmac->ctx = HMAC_CTX_new(); if (hmac->ctx == NULL) { - EVP_MD_meth_free(md); + EVP_MD_free(md); return 0; } } /* These are taken from SP 800-90 10.1 Table 2 */ - EVP_MD_meth_free(hmac->md); + EVP_MD_free(hmac->md); hmac->md = md; hmac->blocklen = EVP_MD_size(md); /* See SP800-57 Part1 Rev4 5.6.1 Table 3 */ diff --git a/crypto/rand/rand_crng_test.c b/crypto/rand/rand_crng_test.c index a014f936fa..0ba0986b96 100644 --- a/crypto/rand/rand_crng_test.c +++ b/crypto/rand/rand_crng_test.c @@ -87,7 +87,7 @@ int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx, if (r != 0) memcpy(buf, p, CRNGT_BUFSIZ); rand_pool_reattach(pool, p); - EVP_MD_meth_free(fmd); + EVP_MD_free(fmd); return r; } return 0; diff --git a/doc/man3/EVP_DigestInit.pod b/doc/man3/EVP_DigestInit.pod index bdc48c3a4b..cc38235274 100644 --- a/doc/man3/EVP_DigestInit.pod +++ b/doc/man3/EVP_DigestInit.pod @@ -2,7 +2,7 @@ =head1 NAME -EVP_MD_fetch, +EVP_MD_fetch, EVP_MD_up_ref, EVP_MD_free, EVP_MD_get_params, EVP_MD_gettable_params, EVP_MD_CTX_new, EVP_MD_CTX_reset, EVP_MD_CTX_free, EVP_MD_CTX_copy, EVP_MD_CTX_copy_ex, EVP_MD_CTX_ctrl, @@ -28,6 +28,8 @@ EVP_MD_do_all_ex EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm, const char *properties); + int EVP_MD_up_ref(EVP_MD *md); + void EVP_MD_free(EVP_MD *md); int EVP_MD_get_params(const EVP_MD *digest, OSSL_PARAM params[]); const OSSL_PARAM *EVP_MD_gettable_params(const EVP_MD *digest); EVP_MD_CTX *EVP_MD_CTX_new(void); @@ -92,7 +94,9 @@ EVP_MD_do_all_ex =head1 DESCRIPTION The EVP digest routines are a high level interface to message digests, -and should be used instead of the cipher-specific functions. +and should be used instead of the digest-specific functions. + +The B type is a structure for digest method implementation. =over 4 @@ -102,7 +106,18 @@ Fetches the digest implementation for the given B from any provider offering it, within the criteria given by the B. See L for further information. -The returned value must eventually be freed with L. +The returned value must eventually be freed with EVP_MD_free(). + +Fetched B structures are reference counted. + +=item EVP_MD_up_ref() + +Increments the reference count for an B structure. + +=item EVP_MD_free() + +Decrements the reference count for the fetched B structure. +If the reference count drops to 0 then the structure is freed. =item EVP_MD_CTX_new() @@ -409,6 +424,10 @@ disabled with this flag. Returns a pointer to a B for success or NULL for failure. +=item EVP_MD_up_ref() + +Returns 1 for success or 0 for failure. + =item EVP_DigestInit_ex(), EVP_DigestUpdate(), EVP_DigestFinal_ex() @@ -573,8 +592,8 @@ The EVP_dss1() function was removed in OpenSSL 1.1.0. The EVP_MD_CTX_set_pkey_ctx() function was added in 1.1.1. -The EVP_MD_CTX_set_params() and EVP_MD_CTX_get_params() functions were -added in 3.0. +The EVP_MD_fetch(), EVP_MD_free(), EVP_MD_up_ref(), EVP_MD_CTX_set_params() +and EVP_MD_CTX_get_params() functions were added in 3.0. =head1 COPYRIGHT diff --git a/doc/man3/EVP_MD_meth_new.pod b/doc/man3/EVP_MD_meth_new.pod index 5e35539efe..7777a33586 100644 --- a/doc/man3/EVP_MD_meth_new.pod +++ b/doc/man3/EVP_MD_meth_new.pod @@ -2,8 +2,8 @@ =head1 NAME -EVP_MD_meth_dup, -EVP_MD_meth_new, EVP_MD_meth_free, EVP_MD_meth_set_input_blocksize, +EVP_MD_meth_new, EVP_MD_meth_dup, EVP_MD_meth_free, +EVP_MD_meth_set_input_blocksize, EVP_MD_meth_set_result_size, EVP_MD_meth_set_app_datasize, EVP_MD_meth_set_flags, EVP_MD_meth_set_init, EVP_MD_meth_set_update, EVP_MD_meth_set_final, EVP_MD_meth_set_copy, EVP_MD_meth_set_cleanup, @@ -11,8 +11,8 @@ EVP_MD_meth_set_ctrl, EVP_MD_meth_get_input_blocksize, EVP_MD_meth_get_result_size, EVP_MD_meth_get_app_datasize, EVP_MD_meth_get_flags, EVP_MD_meth_get_init, EVP_MD_meth_get_update, EVP_MD_meth_get_final, EVP_MD_meth_get_copy, EVP_MD_meth_get_cleanup, -EVP_MD_meth_get_ctrl, EVP_MD_up_ref -- Routines to build up EVP_MD methods +EVP_MD_meth_get_ctrl +- Routines to build up legacy EVP_MD methods =head1 SYNOPSIS @@ -54,16 +54,14 @@ EVP_MD_meth_get_ctrl, EVP_MD_up_ref int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd, int p1, void *p2); - int EVP_MD_up_ref(EVP_MD *md); - =head1 DESCRIPTION The B type is a structure for digest method implementation. It can also have associated public/private key signing and verifying routines. -EVP_MD_meth_new() creates a new B structure. Note that B -structures are reference counted. +EVP_MD_meth_new() creates a new B structure. +These B structures are reference counted. EVP_MD_meth_dup() creates a copy of B. @@ -162,8 +160,6 @@ EVP_MD_meth_get_cleanup() and EVP_MD_meth_get_ctrl() are all used to retrieve the method data given with the EVP_MD_meth_set_*() functions above. -EVP_MD_up_ref() increments the reference count for an EVP_MD structure. - =head1 RETURN VALUES EVP_MD_meth_new() and EVP_MD_meth_dup() return a pointer to a newly @@ -175,8 +171,6 @@ indicated sizes or flags. All other EVP_CIPHER_meth_get_*() functions return pointers to their respective B function. -EVP_MD_up_ref() returns 1 for success or 0 otherwise. - =head1 SEE ALSO L, L, L @@ -184,8 +178,10 @@ L, L, L =head1 HISTORY The B structure was openly available in OpenSSL before version -1.1. EVP_MD_up_ref() was added in OpenSSL 3.0. All other functions described -here were added in OpenSSL 1.1. +1.1. +The functions described here were added in OpenSSL 1.1. +The B structure created with these functions became reference +counted in OpenSSL 3.0. =head1 COPYRIGHT diff --git a/include/openssl/evp.h b/include/openssl/evp.h index c778ef43da..6c59aae701 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -81,7 +81,6 @@ int EVP_set_default_properties(OPENSSL_CTX *libctx, const char *propq); # ifndef EVP_MD EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type); EVP_MD *EVP_MD_meth_dup(const EVP_MD *md); -int EVP_MD_up_ref(EVP_MD *md); void EVP_MD_meth_free(EVP_MD *md); int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize); @@ -585,6 +584,8 @@ __owur int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, __owur EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm, const char *properties); +int EVP_MD_up_ref(EVP_MD *md); +void EVP_MD_free(EVP_MD *md); int EVP_read_pw_string(char *buf, int length, const char *prompt, int verify); int EVP_read_pw_string_min(char *buf, int minlen, int maxlen, diff --git a/providers/common/macs/hmac_prov.c b/providers/common/macs/hmac_prov.c index e9be9802e6..d5f6db79de 100644 --- a/providers/common/macs/hmac_prov.c +++ b/providers/common/macs/hmac_prov.c @@ -79,7 +79,7 @@ static void hmac_free(void *vmacctx) if (macctx != NULL) { HMAC_CTX_free(macctx->ctx); - EVP_MD_meth_free(macctx->alloc_md); + EVP_MD_free(macctx->alloc_md); OPENSSL_free(macctx); } } @@ -222,7 +222,7 @@ static int hmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) propquery = p->data; } - EVP_MD_meth_free(macctx->alloc_md); + EVP_MD_free(macctx->alloc_md); macctx->tmpmd = macctx->alloc_md = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(macctx->provctx), diff --git a/providers/common/macs/kmac_prov.c b/providers/common/macs/kmac_prov.c index b1e852ac77..9ffdbd5249 100644 --- a/providers/common/macs/kmac_prov.c +++ b/providers/common/macs/kmac_prov.c @@ -150,7 +150,7 @@ static void kmac_free(void *vmacctx) if (kctx != NULL) { EVP_MD_CTX_free(kctx->ctx); - EVP_MD_meth_free(kctx->alloc_md); + EVP_MD_free(kctx->alloc_md); OPENSSL_cleanse(kctx->key, kctx->key_len); OPENSSL_cleanse(kctx->custom, kctx->custom_len); OPENSSL_free(kctx); @@ -197,7 +197,7 @@ static void *kmac_fetch_new(void *provctx, const char *mdname) ret = kmac_new(provctx, fetched_md, md); if (ret == NULL) - EVP_MD_meth_free(fetched_md); + EVP_MD_free(fetched_md); return ret; } diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index f8f0a90c24..000bf73672 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -186,7 +186,7 @@ static int dummy_evp_call(void *provctx) BN_CTX_free(bnctx); EVP_MD_CTX_free(ctx); - EVP_MD_meth_free(sha256); + EVP_MD_free(sha256); #ifndef OPENSSL_NO_EC EC_KEY_free(key); diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index f187f73bf0..eba7f64bab 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -1154,8 +1154,8 @@ static int test_EVP_MD_fetch(int tst) if (!TEST_true(EVP_MD_up_ref(md))) goto err; /* Ref count should now be 2. Release both */ - EVP_MD_meth_free(md); - EVP_MD_meth_free(md); + EVP_MD_free(md); + EVP_MD_free(md); md = NULL; /* @@ -1174,7 +1174,7 @@ static int test_EVP_MD_fetch(int tst) goto err; } - EVP_MD_meth_free(md); + EVP_MD_free(md); md = NULL; /* @@ -1195,7 +1195,7 @@ static int test_EVP_MD_fetch(int tst) goto err; } - EVP_MD_meth_free(md); + EVP_MD_free(md); md = NULL; /* @@ -1217,7 +1217,7 @@ static int test_EVP_MD_fetch(int tst) ret = 1; err: - EVP_MD_meth_free(md); + EVP_MD_free(md); OSSL_PROVIDER_unload(defltprov); OSSL_PROVIDER_unload(fipsprov); /* Not normally needed, but we would like to test that diff --git a/util/libcrypto.num b/util/libcrypto.num index ac1c110133..3ace3ad1b9 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4732,3 +4732,4 @@ EVP_MAC_get_params 4841 3_0_0 EXIST::FUNCTION: EVP_MAC_gettable_params 4842 3_0_0 EXIST::FUNCTION: EVP_MAC_provider 4843 3_0_0 EXIST::FUNCTION: EVP_MAC_do_all_ex 4844 3_0_0 EXIST::FUNCTION: +EVP_MD_free 4845 3_0_0 EXIST::FUNCTION: