From: Pauli Date: Wed, 16 Sep 2020 01:10:01 +0000 (+1000) Subject: rand: reference count the EVP_RAND contexts. X-Git-Tag: openssl-3.0.0-alpha7~159 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4640cd00c36f0535d297d1ed10665597c4e2c7f2;p=thirdparty%2Fopenssl.git rand: reference count the EVP_RAND contexts. This is required before the RAND/DRBG framework can be made user mutable. Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/12904) --- diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index 3268aa41091..285c69103b5 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 0e5e8c11f9a..2e4edfff346 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 dfd2a7eb4c0..b7b836f03e1 100644 --- a/doc/man3/EVP_RAND.pod +++ b/doc/man3/EVP_RAND.pod @@ -85,6 +85,7 @@ cryptographically secure random bytes. B is a type that holds the implementation of a RAND. B is a context type that holds the algorithm inputs. +B structures are reference counted. =head2 Algorithm implementation fetching