diff options
author | Pauli <paul.dale@oracle.com> | 2020-09-16 11:10:01 +1000 |
---|---|---|
committer | Pauli <paul.dale@oracle.com> | 2020-09-23 08:39:43 +1000 |
commit | 4640cd00c36f0535d297d1ed10665597c4e2c7f2 (patch) | |
tree | 6cfc1e1d8566472d2878090d5bd2f2e347be031d /crypto/evp/evp_rand.c | |
parent | 8e3a64fdb6e1e2826a334b095147d3ebe1acac2a (diff) |
rand: reference count the EVP_RAND contexts.
This is required before the RAND/DRBG framework can be made user mutable.
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/12904)
Diffstat (limited to 'crypto/evp/evp_rand.c')
-rw-r--r-- | crypto/evp/evp_rand.c | 38 |
1 files changed, 33 insertions, 5 deletions
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); + } } } |