The branch master has been updated via 4640cd00c36f0535d297d1ed10665597c4e2c7f2 (commit) from 8e3a64fdb6e1e2826a334b095147d3ebe1acac2a (commit)
- Log ----------------------------------------------------------------- commit 4640cd00c36f0535d297d1ed10665597c4e2c7f2 Author: Pauli <paul.d...@oracle.com> Date: Wed Sep 16 11:10:01 2020 +1000 rand: reference count the EVP_RAND contexts. This is required before the RAND/DRBG framework can be made user mutable. Reviewed-by: Tomas Mraz <tm...@fedoraproject.org> (Merged from https://github.com/openssl/openssl/pull/12904) ----------------------------------------------------------------------- Summary of changes: crypto/evp/evp_local.h | 3 +++ crypto/evp/evp_rand.c | 38 +++++++++++++++++++++++++++++++++----- doc/man3/EVP_RAND.pod | 1 + 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index 3268aa4109..285c69103b 100644 --- a/crypto/evp/evp_local.h +++ b/crypto/evp/evp_local.h @@ -69,6 +69,9 @@ struct evp_kdf_ctx_st { struct evp_rand_ctx_st { EVP_RAND *meth; /* Method structure */ void *data; /* Algorithm-specific data */ + EVP_RAND_CTX *parent; /* Parent EVP_RAND or NULL if none */ + CRYPTO_REF_COUNT refcnt; /* Context reference count */ + CRYPTO_RWLOCK *refcnt_lock; } /* EVP_RAND_CTX */ ; struct evp_keymgmt_st { diff --git a/crypto/evp/evp_rand.c b/crypto/evp/evp_rand.c index 0e5e8c11f9..2e4edfff34 100644 --- a/crypto/evp/evp_rand.c +++ b/crypto/evp/evp_rand.c @@ -308,6 +308,13 @@ int EVP_RAND_get_params(EVP_RAND *rand, OSSL_PARAM params[]) return 1; } +static int evp_rand_ctx_up_ref(EVP_RAND_CTX *ctx) +{ + int ref = 0; + + return CRYPTO_UP_REF(&ctx->refcnt, &ref, ctx->refcnt_lock); +} + EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent) { EVP_RAND_CTX *ctx; @@ -320,13 +327,21 @@ EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent) } ctx = OPENSSL_zalloc(sizeof(*ctx)); - if (ctx == NULL) { + if (ctx == NULL || (ctx->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL) { + OPENSSL_free(ctx); EVPerr(0, ERR_R_MALLOC_FAILURE); return NULL; } if (parent != NULL) { if (!EVP_RAND_enable_locking(parent)) { EVPerr(0, EVP_R_UNABLE_TO_ENABLE_PARENT_LOCKING); + CRYPTO_THREAD_lock_free(ctx->refcnt_lock); + OPENSSL_free(ctx); + return NULL; + } + if (!evp_rand_ctx_up_ref(parent)) { + EVPerr(0, ERR_R_INTERNAL_ERROR); + CRYPTO_THREAD_lock_free(ctx->refcnt_lock); OPENSSL_free(ctx); return NULL; } @@ -338,20 +353,33 @@ EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent) || !EVP_RAND_up_ref(rand)) { EVPerr(0, ERR_R_MALLOC_FAILURE); rand->freectx(ctx->data); + CRYPTO_THREAD_lock_free(ctx->refcnt_lock); OPENSSL_free(ctx); + EVP_RAND_CTX_free(parent); return NULL; } ctx->meth = rand; + ctx->parent = parent; + ctx->refcnt = 1; return ctx; } void EVP_RAND_CTX_free(EVP_RAND_CTX *ctx) { if (ctx != NULL) { - ctx->meth->freectx(ctx->data); - ctx->data = NULL; - EVP_RAND_free(ctx->meth); - OPENSSL_free(ctx); + int ref = 0; + + CRYPTO_DOWN_REF(&ctx->refcnt, &ref, ctx->refcnt_lock); + if (ref <= 0) { + EVP_RAND_CTX *parent = ctx->parent; + + ctx->meth->freectx(ctx->data); + ctx->data = NULL; + EVP_RAND_free(ctx->meth); + CRYPTO_THREAD_lock_free(ctx->refcnt_lock); + OPENSSL_free(ctx); + EVP_RAND_CTX_free(parent); + } } } diff --git a/doc/man3/EVP_RAND.pod b/doc/man3/EVP_RAND.pod index dfd2a7eb4c..b7b836f03e 100644 --- a/doc/man3/EVP_RAND.pod +++ b/doc/man3/EVP_RAND.pod @@ -85,6 +85,7 @@ cryptographically secure random bytes. B<EVP_RAND> is a type that holds the implementation of a RAND. B<EVP_RAND_CTX> is a context type that holds the algorithm inputs. +B<EVP_RAND_CTX> structures are reference counted. =head2 Algorithm implementation fetching