From 08edd447c97854d6548c15149de90d6bd3ddd47b Mon Sep 17 00:00:00 2001 From: Pauli Date: Fri, 30 Oct 2020 15:54:03 +1000 Subject: prov: move the entropy source out of the FIPS provider Reviewed-by: Matt Caswell Reviewed-by: Matthias St. Pierre (Merged from https://github.com/openssl/openssl/pull/13226) --- providers/common/build.info | 2 +- providers/common/include/prov/providercommonerr.h | 2 +- providers/common/provider_err.c | 4 +- providers/common/provider_seeding.c | 73 +++++++ providers/defltprov.c | 4 +- providers/fips/fipsprov.c | 6 +- providers/implementations/include/prov/seeding.h | 20 +- providers/implementations/rands/build.info | 2 +- providers/implementations/rands/crngt.c | 120 ++++++----- providers/implementations/rands/drbg.c | 235 ++++++++------------- providers/implementations/rands/drbg_local.h | 24 +-- providers/implementations/rands/seeding/build.info | 1 - .../implementations/rands/seeding/rand_cpu_x86.c | 2 +- providers/implementations/rands/seeding/rand_tsc.c | 2 +- .../implementations/rands/seeding/rand_unix.c | 2 +- providers/implementations/rands/seeding/rand_vms.c | 2 +- .../implementations/rands/seeding/rand_vxworks.c | 2 +- providers/implementations/rands/seeding/rand_win.c | 2 +- providers/implementations/rands/test_rng.c | 4 +- 19 files changed, 276 insertions(+), 233 deletions(-) create mode 100644 providers/common/provider_seeding.c (limited to 'providers') diff --git a/providers/common/build.info b/providers/common/build.info index b6d56682a9..8de65f3fa8 100644 --- a/providers/common/build.info +++ b/providers/common/build.info @@ -2,6 +2,6 @@ SUBDIRS=der SOURCE[../libcommon.a]=provider_err.c provider_ctx.c $FIPSCOMMON=provider_util.c capabilities.c bio_prov.c digest_to_nid.c\ - securitycheck.c + securitycheck.c provider_seeding.c SOURCE[../libnonfips.a]=$FIPSCOMMON securitycheck_default.c SOURCE[../libfips.a]=$FIPSCOMMON securitycheck_fips.c diff --git a/providers/common/include/prov/providercommonerr.h b/providers/common/include/prov/providercommonerr.h index 05ca8abef0..86a3667641 100644 --- a/providers/common/include/prov/providercommonerr.h +++ b/providers/common/include/prov/providercommonerr.h @@ -141,6 +141,7 @@ int ERR_load_PROV_strings(void); # define PROV_R_NO_PARAMETERS_SET 177 # define PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 178 # define PROV_R_OUTPUT_BUFFER_TOO_SMALL 106 +# define PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS 228 # define PROV_R_PARENT_LOCKING_NOT_ENABLED 182 # define PROV_R_PARENT_STRENGTH_TOO_WEAK 194 # define PROV_R_PATH_MUST_BE_ABSOLUTE 219 @@ -158,7 +159,6 @@ int ERR_load_PROV_strings(void); # define PROV_R_UNABLE_TO_FIND_CIPHERS 207 # define PROV_R_UNABLE_TO_GET_ENTROPY 202 # define PROV_R_UNABLE_TO_GET_NONCE 203 -# define PROV_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER 198 # define PROV_R_UNABLE_TO_GET_PARENT_STRENGTH 199 # define PROV_R_UNABLE_TO_INITIALISE_CIPHERS 208 # define PROV_R_UNABLE_TO_LOAD_SHA1 143 diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index 2b65903a31..2915330b86 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -152,6 +152,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { "operation not supported for this keytype"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_OUTPUT_BUFFER_TOO_SMALL), "output buffer too small"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS), + "parent cannot generate random numbers"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PARENT_LOCKING_NOT_ENABLED), "parent locking not enabled"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PARENT_STRENGTH_TOO_WEAK), @@ -182,8 +184,6 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { "unable to get entropy"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_GET_NONCE), "unable to get nonce"}, - {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER), - "unable to get parent reseed prop counter"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH), "unable to get parent strength"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_INITIALISE_CIPHERS), diff --git a/providers/common/provider_seeding.c b/providers/common/provider_seeding.c new file mode 100644 index 0000000000..98704a2cdf --- /dev/null +++ b/providers/common/provider_seeding.c @@ -0,0 +1,73 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "prov/seeding.h" + +static OSSL_FUNC_get_entropy_fn *c_get_entropy = NULL; +static OSSL_FUNC_cleanup_entropy_fn *c_cleanup_entropy = NULL; +static OSSL_FUNC_get_nonce_fn *c_get_nonce = NULL; +static OSSL_FUNC_cleanup_nonce_fn *c_cleanup_nonce = NULL; + +int ossl_prov_seeding_from_dispatch(const OSSL_DISPATCH *fns) +{ + for (; fns->function_id != 0; fns++) { + switch (fns->function_id) { + case OSSL_FUNC_GET_ENTROPY: + if (c_get_entropy == NULL) + c_get_entropy = OSSL_FUNC_get_entropy(fns); + break; + case OSSL_FUNC_CLEANUP_ENTROPY: + if (c_cleanup_entropy == NULL) + c_cleanup_entropy = OSSL_FUNC_cleanup_entropy(fns); + break; + case OSSL_FUNC_GET_NONCE: + if (c_get_nonce == NULL) + c_get_nonce = OSSL_FUNC_get_nonce(fns); + break; + case OSSL_FUNC_CLEANUP_NONCE: + if (c_cleanup_nonce == NULL) + c_cleanup_nonce = OSSL_FUNC_cleanup_nonce(fns); + break; + } + } + return 1; +} + +size_t ossl_prov_get_entropy(PROV_CTX *prov_ctx, unsigned char **pout, + int entropy, size_t min_len, size_t max_len) +{ + if (c_get_entropy == NULL) + return 0; + return c_get_entropy(ossl_prov_ctx_get0_handle(prov_ctx), + pout, entropy, min_len, max_len); +} + +void ossl_prov_cleanup_entropy(PROV_CTX *prov_ctx, unsigned char *buf, + size_t len) +{ + if (c_cleanup_entropy != NULL) + c_cleanup_entropy(ossl_prov_ctx_get0_handle(prov_ctx), buf, len); +} + +size_t ossl_prov_get_nonce(PROV_CTX *prov_ctx, unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt,size_t salt_len) +{ + if (c_get_nonce == NULL) + return 0; + return c_get_nonce(ossl_prov_ctx_get0_handle(prov_ctx), pout, + min_len, max_len, salt, salt_len); +} + +void ossl_prov_cleanup_nonce(PROV_CTX *prov_ctx, unsigned char *buf, size_t len) +{ + if (c_cleanup_nonce != NULL) + c_cleanup_nonce(ossl_prov_ctx_get0_handle(prov_ctx), buf, len); +} diff --git a/providers/defltprov.c b/providers/defltprov.c index b309ba798c..e5d7fe4877 100644 --- a/providers/defltprov.c +++ b/providers/defltprov.c @@ -19,6 +19,7 @@ #include "prov/providercommon.h" #include "prov/implementations.h" #include "prov/provider_util.h" +#include "prov/seeding.h" #include "internal/nelem.h" /* @@ -527,7 +528,8 @@ int ossl_default_provider_init(const OSSL_CORE_HANDLE *handle, OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL; BIO_METHOD *corebiometh; - if (!ossl_prov_bio_from_dispatch(in)) + if (!ossl_prov_bio_from_dispatch(in) + || !ossl_prov_seeding_from_dispatch(in)) return 0; for (; in->function_id != 0; in++) { switch (in->function_id) { diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 33b2f0213e..ffb7510054 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -18,6 +18,7 @@ #include "prov/providercommon.h" #include "prov/providercommonerr.h" #include "prov/provider_util.h" +#include "prov/seeding.h" #include "self_test.h" static const char FIPS_DEFAULT_PROPERTIES[] = "provider=fips,fips=yes"; @@ -495,6 +496,8 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, FIPS_GLOBAL *fgbl; OSSL_LIB_CTX *libctx = NULL; + if (!ossl_prov_seeding_from_dispatch(in)) + return 0; for (; in->function_id != 0; in++) { switch (in->function_id) { case OSSL_FUNC_CORE_GET_LIBCTX: @@ -575,10 +578,9 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, case OSSL_FUNC_BIO_VSNPRINTF: c_BIO_vsnprintf = OSSL_FUNC_BIO_vsnprintf(in); break; - case OSSL_FUNC_SELF_TEST_CB: { + case OSSL_FUNC_SELF_TEST_CB: c_stcbfn = OSSL_FUNC_self_test_cb(in); break; - } default: /* Just ignore anything we don't understand */ break; diff --git a/providers/implementations/include/prov/seeding.h b/providers/implementations/include/prov/seeding.h index ec69040606..448ff0366b 100644 --- a/providers/implementations/include/prov/seeding.h +++ b/providers/implementations/include/prov/seeding.h @@ -7,7 +7,8 @@ * https://www.openssl.org/source/license.html */ -#include "prov/rand_pool.h" +#include "prov/provider_ctx.h" +#include "crypto/rand_pool.h" /* Hardware-based seeding functions. */ size_t prov_acquire_entropy_from_tsc(RAND_POOL *pool); @@ -18,9 +19,6 @@ size_t prov_drbg_get_additional_data(RAND_POOL *pool, unsigned char **pout); void prov_drbg_cleanup_additional_data(RAND_POOL *pool, unsigned char *out); -size_t ossl_pool_acquire_entropy(RAND_POOL *pool); -int ossl_pool_add_nonce_data(RAND_POOL *pool); - /* * Add some platform specific additional data * @@ -32,3 +30,17 @@ int ossl_pool_add_nonce_data(RAND_POOL *pool); */ int rand_pool_add_additional_data(RAND_POOL *pool); +/* + * External seeding functions from the core dispatch table. + */ +int ossl_prov_seeding_from_dispatch(const OSSL_DISPATCH *fns); + +size_t ossl_prov_get_entropy(PROV_CTX *prov_ctx, unsigned char **pout, + int entropy, size_t min_len, size_t max_len); +void ossl_prov_cleanup_entropy(PROV_CTX *prov_ctx, unsigned char *buf, + size_t len); +size_t ossl_prov_get_nonce(PROV_CTX *prov_ctx, unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len); +void ossl_prov_cleanup_nonce(PROV_CTX *prov_ctx, unsigned char *buf, + size_t len); diff --git a/providers/implementations/rands/build.info b/providers/implementations/rands/build.info index 1e710bb510..2ca0cdadc7 100644 --- a/providers/implementations/rands/build.info +++ b/providers/implementations/rands/build.info @@ -1,6 +1,6 @@ SUBDIRS=seeding -$COMMON=drbg.c test_rng.c drbg_ctr.c drbg_hash.c drbg_hmac.c crngt.c rand_pool.c +$COMMON=drbg.c test_rng.c drbg_ctr.c drbg_hash.c drbg_hmac.c crngt.c SOURCE[../../libfips.a]=$COMMON SOURCE[../../libnonfips.a]=$COMMON diff --git a/providers/implementations/rands/crngt.c b/providers/implementations/rands/crngt.c index 72907b5a88..f1b31df101 100644 --- a/providers/implementations/rands/crngt.c +++ b/providers/implementations/rands/crngt.c @@ -20,40 +20,35 @@ #include "prov/providercommon.h" #include "prov/provider_ctx.h" #include "internal/cryptlib.h" -#include "prov/rand_pool.h" +#include "crypto/rand_pool.h" #include "drbg_local.h" #include "prov/seeding.h" typedef struct crng_test_global_st { unsigned char crngt_prev[EVP_MAX_MD_SIZE]; - RAND_POOL *crngt_pool; + EVP_MD *md; + int preloaded; + CRYPTO_RWLOCK *lock; } CRNG_TEST_GLOBAL; -static int crngt_get_entropy(OSSL_LIB_CTX *ctx, RAND_POOL *pool, +static int crngt_get_entropy(PROV_CTX *provctx, const EVP_MD *digest, unsigned char *buf, unsigned char *md, unsigned int *md_size) { int r; size_t n; unsigned char *p; - EVP_MD *fmd; - if (pool == NULL) - return 0; - - n = ossl_pool_acquire_entropy(pool); - if (n >= CRNGT_BUFSIZ) { - fmd = EVP_MD_fetch(ctx, "SHA256", ""); - if (fmd == NULL) - return 0; - p = rand_pool_detach(pool); - r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, fmd, NULL); + n = ossl_prov_get_entropy(provctx, &p, 0, CRNGT_BUFSIZ, CRNGT_BUFSIZ); + if (n == CRNGT_BUFSIZ) { + r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, digest, NULL); if (r != 0) memcpy(buf, p, CRNGT_BUFSIZ); - rand_pool_reattach(pool, p); - EVP_MD_free(fmd); - return r; + ossl_prov_cleanup_entropy(provctx, p, n); + return r != 0; } + if (n != 0) + ossl_prov_cleanup_entropy(provctx, p, n); return 0; } @@ -61,31 +56,30 @@ static void rand_crng_ossl_ctx_free(void *vcrngt_glob) { CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob; - rand_pool_free(crngt_glob->crngt_pool); + CRYPTO_THREAD_lock_free(crngt_glob->lock); + EVP_MD_free(crngt_glob->md); OPENSSL_free(crngt_glob); } static void *rand_crng_ossl_ctx_new(OSSL_LIB_CTX *ctx) { - unsigned char buf[CRNGT_BUFSIZ]; CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob)); if (crngt_glob == NULL) return NULL; - if ((crngt_glob->crngt_pool - = rand_pool_new(0, 1, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL) { + if ((crngt_glob->md = EVP_MD_fetch(ctx, "SHA256", "")) == NULL) { OPENSSL_free(crngt_glob); return NULL; } - if (crngt_get_entropy(ctx, crngt_glob->crngt_pool, buf, - crngt_glob->crngt_prev, NULL)) { - OPENSSL_cleanse(buf, sizeof(buf)); - return crngt_glob; + + if ((crngt_glob->lock = CRYPTO_THREAD_lock_new()) == NULL) { + EVP_MD_free(crngt_glob->md); + OPENSSL_free(crngt_glob); + return NULL; } - rand_pool_free(crngt_glob->crngt_pool); - OPENSSL_free(crngt_glob); - return NULL; + + return crngt_glob; } static const OSSL_LIB_CTX_METHOD rand_crng_ossl_ctx_method = { @@ -109,12 +103,14 @@ size_t ossl_crngt_get_entropy(PROV_DRBG *drbg, int entropy, size_t min_len, size_t max_len, int prediction_resistance) { - unsigned char buf[CRNGT_BUFSIZ], md[EVP_MAX_MD_SIZE]; + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned char buf[CRNGT_BUFSIZ]; + unsigned char *ent, *entp, *entbuf; unsigned int sz; - RAND_POOL *pool; - size_t q, r = 0, s, t = 0; - int attempts = 3, crng_test_pass = 1; - OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(drbg->provctx); + size_t bytes_needed; + size_t r = 0, s, t; + int crng_test_pass = 1; + OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx); CRNG_TEST_GLOBAL *crngt_glob = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_RAND_CRNGT_INDEX, &rand_crng_ossl_ctx_method); @@ -125,9 +121,32 @@ size_t ossl_crngt_get_entropy(PROV_DRBG *drbg, if (crngt_glob == NULL) return 0; - if ((pool = rand_pool_new(entropy, 1, min_len, max_len)) == NULL) + if (!CRYPTO_THREAD_write_lock(crngt_glob->lock)) return 0; + if (!crngt_glob->preloaded) { + if (!crngt_get_entropy(drbg->provctx, crngt_glob->md, buf, + crngt_glob->crngt_prev, NULL)) { + OPENSSL_cleanse(buf, sizeof(buf)); + goto unlock_return; + } + crngt_glob->preloaded = 1; + } + + /* + * Calculate how many bytes of seed material we require, rounded up + * to the nearest byte. If the entropy is of less than full quality, + * the amount required should be scaled up appropriately here. + */ + bytes_needed = (entropy + 7) / 8; + if (bytes_needed < min_len) + bytes_needed = min_len; + if (bytes_needed > max_len) + goto unlock_return; + entp = ent = OPENSSL_secure_malloc(bytes_needed); + if (ent == NULL) + goto unlock_return; + OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg); if (stcb != NULL) { st = OSSL_SELF_TEST_new(stcb, stcbarg); @@ -137,10 +156,14 @@ size_t ossl_crngt_get_entropy(PROV_DRBG *drbg, OSSL_SELF_TEST_DESC_RNG); } - while ((q = rand_pool_bytes_needed(pool, 1)) > 0 && attempts-- > 0) { - s = q > sizeof(buf) ? sizeof(buf) : q; - if (!crngt_get_entropy(libctx, crngt_glob->crngt_pool, buf, md, &sz)) + for (t = bytes_needed; t > 0;) { + /* Care needs to be taken to avoid overrunning the buffer */ + s = t >= CRNGT_BUFSIZ ? CRNGT_BUFSIZ : t; + entbuf = t >= CRNGT_BUFSIZ ? entp : buf; + if (!crngt_get_entropy(drbg->provctx, crngt_glob->md, entbuf, md, &sz)) goto err; + if (t < CRNGT_BUFSIZ) + memcpy(entp, buf, t); /* Force a failure here if the callback returns 1 */ if (OSSL_SELF_TEST_oncorrupt_byte(st, md)) memcpy(md, crngt_glob->crngt_prev, sz); @@ -148,23 +171,26 @@ size_t ossl_crngt_get_entropy(PROV_DRBG *drbg, crng_test_pass = 0; goto err; } - if (!rand_pool_add(pool, buf, s, s * 8)) - goto err; + /* Update for next block */ memcpy(crngt_glob->crngt_prev, md, sz); - t += s; - attempts++; + entp += s; + t -= s; } - r = t; - *pout = rand_pool_detach(pool); -err: + r = bytes_needed; + *pout = ent; + ent = NULL; + + err: OSSL_SELF_TEST_onend(st, crng_test_pass); OSSL_SELF_TEST_free(st); - OPENSSL_cleanse(buf, sizeof(buf)); - rand_pool_free(pool); + OPENSSL_secure_clear_free(ent, bytes_needed); + + unlock_return: + CRYPTO_THREAD_unlock(crngt_glob->lock); return r; } -void ossl_crngt_cleanup_entropy(PROV_DRBG *drbg, +void ossl_crngt_cleanup_entropy(ossl_unused PROV_DRBG *drbg, unsigned char *out, size_t outlen) { OPENSSL_secure_clear_free(out, outlen); diff --git a/providers/implementations/rands/drbg.c b/providers/implementations/rands/drbg.c index a294ed7f1d..cc965c9bc0 100644 --- a/providers/implementations/rands/drbg.c +++ b/providers/implementations/rands/drbg.c @@ -17,7 +17,7 @@ #include "internal/thread_once.h" #include "crypto/cryptlib.h" #include "prov/seeding.h" -#include "prov/rand_pool.h" +#include "crypto/rand_pool.h" #include "prov/provider_ctx.h" #include "prov/providercommonerr.h" #include "prov/providercommon.h" @@ -110,18 +110,15 @@ static unsigned int get_parent_reseed_count(PROV_DRBG *drbg) { OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; void *parent = drbg->parent; - unsigned int r; + unsigned int r = 0; *params = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_COUNTER, &r); if (!ossl_drbg_lock_parent(drbg)) { ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOCK_PARENT); goto err; } - if (!drbg->parent_get_ctx_params(parent, params)) { - ossl_drbg_unlock_parent(drbg); - ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_RESEED_PROP_CTR); - goto err; - } + if (!drbg->parent_get_ctx_params(parent, params)) + r = 0; ossl_drbg_unlock_parent(drbg); return r; @@ -148,106 +145,90 @@ static size_t prov_drbg_get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy, size_t min_len, size_t max_len, int prediction_resistance) { - size_t ret = 0; - size_t entropy_available = 0; - RAND_POOL *pool; unsigned int p_str; + size_t r, bytes_needed; + unsigned char *buffer; - if (drbg->parent != NULL) { - if (!get_parent_strength(drbg, &p_str)) - return 0; - if (drbg->strength > p_str) { - /* - * We currently don't support the algorithm from NIST SP 800-90C - * 10.1.2 to use a weaker DRBG as source - */ - ERR_raise(ERR_LIB_RAND, PROV_R_PARENT_STRENGTH_TOO_WEAK); - return 0; - } + if (!get_parent_strength(drbg, &p_str)) + return 0; + if (drbg->strength > p_str) { + /* + * We currently don't support the algorithm from NIST SP 800-90C + * 10.1.2 to use a weaker DRBG as source + */ + ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK); + return 0; } - if (drbg->seed_pool != NULL) { - pool = drbg->seed_pool; - pool->entropy_requested = entropy; - } else { - pool = rand_pool_new(entropy, 1, min_len, max_len); - if (pool == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return 0; - } + if (drbg->parent_generate == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS); + return 0; } - if (drbg->parent != NULL) { - size_t bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); - unsigned char *buffer = rand_pool_add_begin(pool, bytes_needed); + /* Figure out how many bytes we need */ + bytes_needed = entropy >= 0 ? (entropy + 7) / 8 : 0; + if (bytes_needed < min_len) + bytes_needed = min_len; + if (bytes_needed > max_len) + bytes_needed = max_len; - if (buffer != NULL) { - size_t bytes = 0; - - if (drbg->parent_generate == NULL) - goto err; - /* - * Our lock is already held, but we need to lock our parent before - * generating bits from it. (Note: taking the lock will be a no-op - * if locking if drbg->parent->lock == NULL.) - */ - ossl_drbg_lock_parent(drbg); - /* - * Get random data from parent. Include our DRBG address as - * additional input, in order to provide a distinction between - * different DRBG child instances. - * - * Note: using the sizeof() operator on a pointer triggers - * a warning in some static code analyzers, but it's - * intentional and correct here. - */ - if (drbg->parent_generate(drbg->parent, buffer, bytes_needed, - drbg->strength, prediction_resistance, - (unsigned char *)&drbg, - sizeof(drbg)) != 0) - bytes = bytes_needed; - ossl_drbg_unlock_parent(drbg); - drbg->parent_reseed_counter = get_parent_reseed_count(drbg); - - rand_pool_add_end(pool, bytes, 8 * bytes); - entropy_available = rand_pool_entropy_available(pool); - } - } else { - /* Get entropy by polling system entropy sources. */ - entropy_available = ossl_pool_acquire_entropy(pool); + /* Allocate storage */ + buffer = OPENSSL_secure_malloc(bytes_needed); + if (buffer == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return 0; } - if (entropy_available > 0) { - ret = rand_pool_length(pool); - *pout = rand_pool_detach(pool); + /* + * Our lock is already held, but we need to lock our parent before + * generating bits from it. Note: taking the lock will be a no-op + * if locking is not required (while drbg->parent->lock == NULL). + */ + ossl_drbg_lock_parent(drbg); + /* + * Get random data from parent. Include our DRBG address as + * additional input, in order to provide a distinction between + * different DRBG child instances. + * + * Note: using the sizeof() operator on a pointer triggers + * a warning in some static code analyzers, but it's + * intentional and correct here. + */ + r = drbg->parent_generate(drbg->parent, buffer, bytes_needed, + drbg->strength, prediction_resistance, + (unsigned char *)&drbg, + sizeof(drbg)); + ossl_drbg_unlock_parent(drbg); + if (r == 0) { + OPENSSL_secure_clear_free(buffer, bytes_needed); + ERR_raise(ERR_LIB_PROV, PROV_R_GENERATE_ERROR); + return 0; } - -err: - if (drbg->seed_pool == NULL) - rand_pool_free(pool); - return ret; + *pout = buffer; + return bytes_needed; } /* * Implements the cleanup_entropy() callback * */ -static void prov_drbg_cleanup_entropy(PROV_DRBG *drbg, +static void prov_drbg_cleanup_entropy(ossl_unused PROV_DRBG *drbg, unsigned char *out, size_t outlen) { - if (drbg->seed_pool == NULL) { - OPENSSL_secure_clear_free(out, outlen); - } + OPENSSL_secure_clear_free(out, outlen); } static size_t get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy, size_t min_len, size_t max_len, int prediction_resistance) { -#ifdef FIPS_MODULE if (drbg->parent == NULL) +#ifdef FIPS_MODULE return ossl_crngt_get_entropy(drbg, pout, entropy, min_len, max_len, prediction_resistance); +#else + return ossl_prov_get_entropy(drbg->provctx, pout, entropy, min_len, + max_len); #endif return prov_drbg_get_entropy(drbg, pout, entropy, min_len, max_len, @@ -256,12 +237,15 @@ static size_t get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy, static void cleanup_entropy(PROV_DRBG *drbg, unsigned char *out, size_t outlen) { + if (drbg->parent == NULL) { #ifdef FIPS_MODULE - if (drbg->parent == NULL) ossl_crngt_cleanup_entropy(drbg, out, outlen); - else +#else + ossl_prov_cleanup_entropy(drbg->provctx, out, outlen); #endif + } else { prov_drbg_cleanup_entropy(drbg, out, outlen); + } } #ifndef PROV_RAND_GET_RANDOM_NONCE @@ -311,75 +295,45 @@ static const OSSL_LIB_CTX_METHOD drbg_nonce_ossl_ctx_method = { }; /* Get a nonce from the operating system */ -static size_t prov_drbg_get_nonce(PROV_DRBG *drbg, - unsigned char **pout, - int entropy, size_t min_len, size_t max_len) +static size_t prov_drbg_get_nonce(PROV_DRBG *drbg, unsigned char **pout, + size_t min_len, size_t max_len) { size_t ret = 0, n; - RAND_POOL *pool; unsigned char *buf = NULL; - OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(drbg->provctx); + OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx); PROV_DRBG_NONCE_GLOBAL *dngbl = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_NONCE_INDEX, &drbg_nonce_ossl_ctx_method); struct { - void *instance; + void *drbg; int count; } data; - + if (dngbl == NULL) return 0; - if (drbg->parent != NULL) { - if (drbg->parent_nonce != NULL) { - n = drbg->parent_nonce(drbg->parent, NULL, 0, drbg->min_noncelen, - drbg->max_noncelen); - if (n > 0 && (buf = OPENSSL_malloc(n)) != NULL) { - ret = drbg->parent_nonce(drbg->parent, buf, 0, - drbg->min_noncelen, - drbg->max_noncelen); - if (ret == n) { - *pout = buf; - return ret; - } - OPENSSL_free(buf); + if (drbg->parent != NULL && drbg->parent_nonce != NULL) { + n = drbg->parent_nonce(drbg->parent, NULL, 0, drbg->min_noncelen, + drbg->max_noncelen); + if (n > 0 && (buf = OPENSSL_malloc(n)) != NULL) { + ret = drbg->parent_nonce(drbg->parent, buf, 0, + drbg->min_noncelen, drbg->max_noncelen); + if (ret == n) { + *pout = buf; + return ret; } + OPENSSL_free(buf); } } - /* Use the built in nonce source */ + /* Use the built in nonce source plus some of our specifics */ memset(&data, 0, sizeof(data)); - pool = rand_pool_new(0, 0, min_len, max_len); - if (pool == NULL) - return 0; - - if (ossl_pool_add_nonce_data(pool) == 0) - goto err; - - data.instance = drbg; + data.drbg = drbg; CRYPTO_atomic_add(&dngbl->rand_nonce_count, 1, &data.count, dngbl->rand_nonce_lock); - - if (rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0) == 0) - goto err; - - ret = rand_pool_length(pool); - *pout = rand_pool_detach(pool); - - err: - rand_pool_free(pool); - - return ret; + return ossl_prov_get_nonce(drbg->provctx, pout, min_len, max_len, + &data, sizeof(data)); } - -static void prov_drbg_clear_nonce(PROV_DRBG *drbg, unsigned char *nonce, - size_t noncelen) -{ - OPENSSL_clear_free(nonce, noncelen); -} -#else -# define prov_drbg_clear_nonce(drbg, nonce, len) \ - OPENSSL_clear_free((nonce), (len)) #endif /* PROV_RAND_GET_RANDOM_NONCE */ /* @@ -465,8 +419,7 @@ int ossl_prov_drbg_instantiate(PROV_DRBG *drbg, unsigned int strength, } #ifndef PROV_RAND_GET_RANDOM_NONCE else { /* parent == NULL */ - noncelen = prov_drbg_get_nonce(drbg, &nonce, drbg->strength / 2, - drbg->min_noncelen, + noncelen = prov_drbg_get_nonce(drbg, &nonce, drbg->min_noncelen, drbg->max_noncelen); if (noncelen < drbg->min_noncelen || noncelen > drbg->max_noncelen) { @@ -507,7 +460,8 @@ int ossl_prov_drbg_instantiate(PROV_DRBG *drbg, unsigned int strength, end: if (entropy != NULL) cleanup_entropy(drbg, entropy, entropylen); - prov_drbg_clear_nonce(drbg, nonce, noncelen); + if (nonce != NULL) + ossl_prov_cleanup_nonce(drbg->provctx, nonce, noncelen); if (drbg->state == EVP_RAND_STATE_READY) return 1; return 0; @@ -745,14 +699,6 @@ int ossl_prov_drbg_generate(PROV_DRBG *drbg, unsigned char *out, size_t outlen, */ static int rand_drbg_restart(PROV_DRBG *drbg) { - if (drbg->seed_pool != NULL) { - drbg->state = EVP_RAND_STATE_ERROR; - rand_pool_free(drbg->seed_pool); - drbg->seed_pool = NULL; - ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR); - return 0; - } - /* repair error state */ if (drbg->state == EVP_RAND_STATE_ERROR) drbg->uninstantiate(drbg); @@ -762,8 +708,6 @@ static int rand_drbg_restart(PROV_DRBG *drbg) /* reinstantiate drbg */ ossl_prov_drbg_instantiate(drbg, drbg->strength, 0, NULL, 0); - rand_pool_free(drbg->seed_pool); - drbg->seed_pool = NULL; return drbg->state == EVP_RAND_STATE_READY; } @@ -892,7 +836,6 @@ void ossl_rand_drbg_free(PROV_DRBG *drbg) if (drbg == NULL) return; - rand_pool_free(drbg->adin_pool); CRYPTO_THREAD_lock_free(drbg->lock); OPENSSL_free(drbg); } @@ -909,7 +852,7 @@ 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_DRBG_PARAM_MAX_REQUEST); + p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST); if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_request)) return 0; diff --git a/providers/implementations/rands/drbg_local.h b/providers/implementations/rands/drbg_local.h index 1877dce44f..fbae882535 100644 --- a/providers/implementations/rands/drbg_local.h +++ b/providers/implementations/rands/drbg_local.h @@ -17,6 +17,7 @@ # include "internal/tsan_assist.h" # include "internal/nelem.h" # include "internal/numbers.h" +# include "prov/provider_ctx.h" /* How many times to read the TSC as a randomness source. */ # define TSC_READ_COUNT 4 @@ -71,7 +72,7 @@ typedef enum drbg_status_e { */ struct prov_drbg_st { CRYPTO_RWLOCK *lock; - void *provctx; + PROV_CTX *provctx; /* Virtual functions are cache here */ int (*instantiate)(PROV_DRBG *drbg, @@ -104,21 +105,6 @@ struct prov_drbg_st { int fork_id; unsigned short flags; /* various external flags */ - /* - * The random_data is used by PROV_add()/drbg_add() to attach random - * data to the global drbg, such that the rand_drbg_get_entropy() callback - * can pull it during instantiation and reseeding. This is necessary to - * reconcile the different philosophies of the PROV and the PROV_DRBG - * with respect to how randomness is added to the RNG during reseeding - * (see PR #4328). - */ - struct rand_pool_st *seed_pool; - - /* - * Auxiliary pool for additional data. - */ - struct rand_pool_st *adin_pool; - /* * The following parameters are setup by the per-type "init" function. * @@ -242,17 +228,17 @@ int ossl_drbg_set_ctx_params(PROV_DRBG *drbg, const OSSL_PARAM params[]); OSSL_PARAM_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS, NULL), \ OSSL_PARAM_uint64(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, NULL) -#define OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON \ +#define OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON \ OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL), \ OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL), \ - OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_REQUEST, NULL), \ + OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL), \ OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MIN_ENTROPYLEN, NULL), \ OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_ENTROPYLEN, NULL), \ OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MIN_NONCELEN, NULL), \ OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_NONCELEN, NULL), \ OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_PERSLEN, NULL), \ OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_ADINLEN, NULL), \ - OSSL_PARAM_uint(OSSL_DRBG_PARAM_RESEED_COUNTER, NULL), \ + OSSL_PARAM_uint(OSSL_DRBG_PARAM_RESEED_COUNTER, NULL), \ OSSL_PARAM_time_t(OSSL_DRBG_PARAM_RESEED_TIME, NULL), \ OSSL_PARAM_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS, NULL), \ OSSL_PARAM_uint64(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, NULL) diff --git a/providers/implementations/rands/seeding/build.info b/providers/implementations/rands/seeding/build.info index e75a941098..58c5be3daf 100644 --- a/providers/implementations/rands/seeding/build.info +++ b/providers/implementations/rands/seeding/build.info @@ -6,6 +6,5 @@ IF[{- $config{target} =~ /vms/i -}] $COMMON=$COMMON rand_vms.c ENDIF -SOURCE[../../../libfips.a]=$COMMON SOURCE[../../../libnonfips.a]=$COMMON diff --git a/providers/implementations/rands/seeding/rand_cpu_x86.c b/providers/implementations/rands/seeding/rand_cpu_x86.c index 46ced51af2..0b163571f1 100644 --- a/providers/implementations/rands/seeding/rand_cpu_x86.c +++ b/providers/implementations/rands/seeding/rand_cpu_x86.c @@ -9,7 +9,7 @@ #include "internal/cryptlib.h" #include -#include "prov/rand_pool.h" +#include "crypto/rand_pool.h" #include "prov/seeding.h" #ifdef OPENSSL_RAND_SEED_RDCPU diff --git a/providers/implementations/rands/seeding/rand_tsc.c b/providers/implementations/rands/seeding/rand_tsc.c index 520f140fdf..2777335469 100644 --- a/providers/implementations/rands/seeding/rand_tsc.c +++ b/providers/implementations/rands/seeding/rand_tsc.c @@ -9,7 +9,7 @@ #include "internal/cryptlib.h" #include -#include "prov/rand_pool.h" +#include "crypto/rand_pool.h" #include "prov/seeding.h" #ifdef OPENSSL_RAND_SEED_RDTSC diff --git a/providers/implementations/rands/seeding/rand_unix.c b/providers/implementations/rands/seeding/rand_unix.c index 35d2878d5c..81fd50c430 100644 --- a/providers/implementations/rands/seeding/rand_unix.c +++ b/providers/implementations/rands/seeding/rand_unix.c @@ -15,7 +15,7 @@ #include "internal/cryptlib.h" #include #include -#include "prov/rand_pool.h" +#include "crypto/rand_pool.h" #include "crypto/rand.h" #include #include "internal/dso.h" diff --git a/providers/implementations/rands/seeding/rand_vms.c b/providers/implementations/rands/seeding/rand_vms.c index da143f3dbe..3a91d24405 100644 --- a/providers/implementations/rands/seeding/rand_vms.c +++ b/providers/implementations/rands/seeding/rand_vms.c @@ -14,7 +14,7 @@ #include "internal/cryptlib.h" #include #include "crypto/rand.h" -#include "prov/rand_pool.h" +#include "crypto/rand_pool.h" #include "prov/seeding.h" #include #include diff --git a/providers/implementations/rands/seeding/rand_vxworks.c b/providers/implementations/rands/seeding/rand_vxworks.c index 70b4c7b677..2629346e62 100644 --- a/providers/implementations/rands/seeding/rand_vxworks.c +++ b/providers/implementations/rands/seeding/rand_vxworks.c @@ -10,7 +10,7 @@ #include #include -#include "prov/rand_pool.h" +#include "crypto/rand_pool.h" #include "crypto/rand.h" #include "internal/cryptlib.h" #include "prov/seeding.h" diff --git a/providers/implementations/rands/seeding/rand_win.c b/providers/implementations/rands/seeding/rand_win.c index bac6b5723e..39b0902e55 100644 --- a/providers/implementations/rands/seeding/rand_win.c +++ b/providers/implementations/rands/seeding/rand_win.c @@ -9,7 +9,7 @@ #include "internal/cryptlib.h" #include -#include "prov/rand_pool.h" +#include "crypto/rand_pool.h" #include "crypto/rand.h" #include "prov/seeding.h" diff --git a/providers/implementations/rands/test_rng.c b/providers/implementations/rands/test_rng.c index 68aedda344..e35554b56b 100644 --- a/providers/implementations/rands/test_rng.c +++ b/providers/implementations/rands/test_rng.c @@ -247,7 +247,7 @@ static int test_rng_set_ctx_params(void *vdrbg, const OSSL_PARAM params[]) if (p != NULL && !OSSL_PARAM_get_time_t(p, &drbg->reseed_time)) return 0; - if (!set_size_t(params, OSSL_DRBG_PARAM_MAX_REQUEST, &drbg->max_request) + if (!set_size_t(params, OSSL_RAND_PARAM_MAX_REQUEST, &drbg->max_request) || !set_size_t(params, OSSL_DRBG_PARAM_MIN_ENTROPYLEN, &drbg->min_entropylen) || !set_size_t(params, OSSL_DRBG_PARAM_MAX_ENTROPYLEN, @@ -270,7 +270,7 @@ static const OSSL_PARAM *test_rng_settable_ctx_params(ossl_unused void *provctx) OSSL_PARAM_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY, NULL, 0), OSSL_PARAM_octet_string(OSSL_RAND_PARAM_TEST_NONCE, NULL, 0), OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL), - OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_REQUEST, NULL), + OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL), OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MIN_ENTROPYLEN, NULL), OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_ENTROPYLEN, NULL), OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MIN_NONCELEN, NULL), -- cgit v1.2.3