Skip to content

Commit

Permalink
Enable obtaining certain DRBG params without a lock
Browse files Browse the repository at this point in the history
Even if a DRBG has locking enabled on it, there are certain parameters
which are still safe to obtain even without a lock. The max_request
value is constant for all our DRBGs. The reseed_counter does not matter
if we get it wrong - so it is safe to avoid the lock. So if all we are
reading are those parameters then we take no lock at all.

Partially fixes #20286

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Todd Short <todd.short@me.com>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from #20970)
  • Loading branch information
mattcaswell authored and paulidale committed Jun 1, 2023
1 parent 189ad3a commit 61f11ca
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 10 deletions.
43 changes: 36 additions & 7 deletions providers/implementations/rands/drbg.c
Expand Up @@ -893,10 +893,6 @@ int ossl_drbg_get_ctx_params(PROV_DRBG *drbg, OSSL_PARAM params[])
if (p != NULL && !OSSL_PARAM_set_int(p, drbg->strength))
return 0;

p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_request))
return 0;

p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MIN_ENTROPYLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->min_entropylen))
return 0;
Expand Down Expand Up @@ -933,10 +929,43 @@ int ossl_drbg_get_ctx_params(PROV_DRBG *drbg, OSSL_PARAM params[])
if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time_interval))
return 0;

return 1;
}

/*
* Helper function to get certain params that require no lock to obtain. Sets
* *complete to 1 if all the params were processed, or 0 otherwise
*/
int ossl_drbg_get_ctx_params_no_lock(PROV_DRBG *drbg, OSSL_PARAM params[],
int *complete)
{
size_t cnt = 0;
OSSL_PARAM *p;

/* This value never changes once set */
p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
if (p != NULL) {
if (!OSSL_PARAM_set_size_t(p, drbg->max_request))
return 0;
cnt++;
}

/*
* Can be changed by multiple threads, but we tolerate inaccuracies in this
* value.
*/
p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_COUNTER);
if (p != NULL
&& !OSSL_PARAM_set_uint(p, tsan_load(&drbg->reseed_counter)))
return 0;
if (p != NULL) {
if (!OSSL_PARAM_set_uint(p, tsan_load(&drbg->reseed_counter)))
return 0;
cnt++;
}

if (params[cnt].key == NULL)
*complete = 1;
else
*complete = 0;

return 1;
}

Expand Down
8 changes: 7 additions & 1 deletion providers/implementations/rands/drbg_ctr.c
Expand Up @@ -658,7 +658,13 @@ static int drbg_ctr_get_ctx_params(void *vdrbg, OSSL_PARAM params[])
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
OSSL_PARAM *p;
int ret = 0;
int ret = 0, complete = 0;

if (!ossl_drbg_get_ctx_params_no_lock(drbg, params, &complete))
return 0;

if (complete)
return 1;

if (drbg->lock != NULL && !CRYPTO_THREAD_read_lock(drbg->lock))
return 0;
Expand Down
8 changes: 7 additions & 1 deletion providers/implementations/rands/drbg_hash.c
Expand Up @@ -463,7 +463,13 @@ static int drbg_hash_get_ctx_params(void *vdrbg, OSSL_PARAM params[])
PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
const EVP_MD *md;
OSSL_PARAM *p;
int ret = 0;
int ret = 0, complete = 0;

if (!ossl_drbg_get_ctx_params_no_lock(drbg, params, &complete))
return 0;

if (complete)
return 1;

if (drbg->lock != NULL && !CRYPTO_THREAD_read_lock(drbg->lock))
return 0;
Expand Down
8 changes: 7 additions & 1 deletion providers/implementations/rands/drbg_hmac.c
Expand Up @@ -356,7 +356,13 @@ static int drbg_hmac_get_ctx_params(void *vdrbg, OSSL_PARAM params[])
const char *name;
const EVP_MD *md;
OSSL_PARAM *p;
int ret = 0;
int ret = 0, complete = 0;

if (!ossl_drbg_get_ctx_params_no_lock(drbg, params, &complete))
return 0;

if (complete)
return 1;

if (drbg->lock != NULL && !CRYPTO_THREAD_read_lock(drbg->lock))
return 0;
Expand Down
2 changes: 2 additions & 0 deletions providers/implementations/rands/drbg_local.h
Expand Up @@ -222,6 +222,8 @@ OSSL_FUNC_rand_unlock_fn ossl_drbg_unlock;

/* Common parameters for all of our DRBGs */
int ossl_drbg_get_ctx_params(PROV_DRBG *drbg, OSSL_PARAM params[]);
int ossl_drbg_get_ctx_params_no_lock(PROV_DRBG *drbg, OSSL_PARAM params[],
int *complete);
int ossl_drbg_set_ctx_params(PROV_DRBG *drbg, const OSSL_PARAM params[]);

#define OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON \
Expand Down

0 comments on commit 61f11ca

Please sign in to comment.