summaryrefslogtreecommitdiffstats
path: root/crypto/evp/evp_rand.c
diff options
context:
space:
mode:
authorPauli <paul.dale@oracle.com>2020-09-16 11:10:01 +1000
committerPauli <paul.dale@oracle.com>2020-09-23 08:39:43 +1000
commit4640cd00c36f0535d297d1ed10665597c4e2c7f2 (patch)
tree6cfc1e1d8566472d2878090d5bd2f2e347be031d /crypto/evp/evp_rand.c
parent8e3a64fdb6e1e2826a334b095147d3ebe1acac2a (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.c38
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);
+ }
}
}