diff options
author | Matt Caswell <matt@openssl.org> | 2023-05-15 15:30:10 +0100 |
---|---|---|
committer | Pauli <pauli@openssl.org> | 2023-06-02 07:30:04 +1000 |
commit | 61f11cad7a0dffc7abd234164a0e74c6ae8e7c2a (patch) | |
tree | 032a1d0ac0dc716d00bc1464f91e74ebb534f56c | |
parent | 189ad3ab2028babd39241015fc3975e8334c87eb (diff) |
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)
-rw-r--r-- | providers/implementations/rands/drbg.c | 43 | ||||
-rw-r--r-- | providers/implementations/rands/drbg_ctr.c | 8 | ||||
-rw-r--r-- | providers/implementations/rands/drbg_hash.c | 8 | ||||
-rw-r--r-- | providers/implementations/rands/drbg_hmac.c | 8 | ||||
-rw-r--r-- | providers/implementations/rands/drbg_local.h | 2 |
5 files changed, 59 insertions, 10 deletions
diff --git a/providers/implementations/rands/drbg.c b/providers/implementations/rands/drbg.c index 4b16873724..4690d73cca 100644 --- a/providers/implementations/rands/drbg.c +++ b/providers/implementations/rands/drbg.c @@ -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; } diff --git a/providers/implementations/rands/drbg_ctr.c b/providers/implementations/rands/drbg_ctr.c index 40d7dbe86d..c303d03eb0 100644 --- a/providers/implementations/rands/drbg_ctr.c +++ b/providers/implementations/rands/drbg_ctr.c @@ -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; diff --git a/providers/implementations/rands/drbg_hash.c b/providers/implementations/rands/drbg_hash.c index a911840c9b..bad20d00fe 100644 --- a/providers/implementations/rands/drbg_hash.c +++ b/providers/implementations/rands/drbg_hash.c @@ -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; diff --git a/providers/implementations/rands/drbg_hmac.c b/providers/implementations/rands/drbg_hmac.c index 4c6482894b..3df0c2ac2b 100644 --- a/providers/implementations/rands/drbg_hmac.c +++ b/providers/implementations/rands/drbg_hmac.c @@ -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; diff --git a/providers/implementations/rands/drbg_local.h b/providers/implementations/rands/drbg_local.h index c3df1bc962..4c815ae2e6 100644 --- a/providers/implementations/rands/drbg_local.h +++ b/providers/implementations/rands/drbg_local.h @@ -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 \ |