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 {
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;
}
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;
}
|| !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);
+ }
}
}