Enable obtaining certain DRBG params without a lock

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 https://github.com/openssl/openssl/pull/20970)
This commit is contained in:
Matt Caswell 2023-05-15 15:30:10 +01:00 committed by Pauli
parent 189ad3ab20
commit 61f11cad7a
5 changed files with 59 additions and 10 deletions

View File

@ -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;
@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 \