Path: blob/main/crypto/openssl/providers/implementations/rands/drbg.c
106879 views
/*1* Copyright 2011-2025 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#include <string.h>10#include <openssl/crypto.h>11#include <openssl/err.h>12#include <openssl/rand.h>13#include <openssl/evp.h>14#include "crypto/rand.h"15#include <openssl/proverr.h>16#include "drbg_local.h"17#include "internal/thread_once.h"18#include "crypto/cryptlib.h"19#include "prov/seeding.h"20#include "crypto/rand_pool.h"21#include "prov/provider_ctx.h"22#include "prov/providercommon.h"23#include "crypto/context.h"2425/*26* Support framework for NIST SP 800-90A DRBG27*28* See manual page PROV_DRBG(7) for a general overview.29*30* The OpenSSL model is to have new and free functions, and that new31* does all initialization. That is not the NIST model, which has32* instantiation and un-instantiate, and reuse within a new/free33* lifecycle. (No doubt this comes from the desire to support hardware34* DRBG, where allocation of resources on something like an HSM is35* a much bigger deal than just re-setting an allocated resource.)36*/3738/* NIST SP 800-90A DRBG recommends the use of a personalization string. */39static const char ossl_pers_string[] = DRBG_DEFAULT_PERS_STRING;4041static const OSSL_DISPATCH *find_call(const OSSL_DISPATCH *dispatch,42int function);4344static int rand_drbg_restart(PROV_DRBG *drbg);4546/*47* We interpret a call to this function as a hint only and ignore it. This48* occurs when the EVP layer thinks we should do some locking. In practice49* however we manage for ourselves when we take a lock or not on the basis50* of whether drbg->lock is present or not.51*/52int ossl_drbg_lock(void *vctx)53{54return 1;55}5657/* Interpreted as a hint only and ignored as for ossl_drbg_lock() */58void ossl_drbg_unlock(void *vctx)59{60}6162static int ossl_drbg_lock_parent(PROV_DRBG *drbg)63{64void *parent = drbg->parent;6566if (parent != NULL67&& drbg->parent_lock != NULL68&& !drbg->parent_lock(parent)) {69ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED);70return 0;71}72return 1;73}7475static void ossl_drbg_unlock_parent(PROV_DRBG *drbg)76{77void *parent = drbg->parent;7879if (parent != NULL && drbg->parent_unlock != NULL)80drbg->parent_unlock(parent);81}8283static int get_parent_strength(PROV_DRBG *drbg, unsigned int *str)84{85OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };86void *parent = drbg->parent;87int res;8889if (drbg->parent_get_ctx_params == NULL) {90ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH);91return 0;92}9394*params = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, str);95if (!ossl_drbg_lock_parent(drbg)) {96ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOCK_PARENT);97return 0;98}99res = drbg->parent_get_ctx_params(parent, params);100ossl_drbg_unlock_parent(drbg);101if (!res) {102ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH);103return 0;104}105return 1;106}107108static unsigned int get_parent_reseed_count(PROV_DRBG *drbg)109{110OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };111void *parent = drbg->parent;112unsigned int r = 0;113114*params = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_COUNTER, &r);115if (!ossl_drbg_lock_parent(drbg)) {116ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOCK_PARENT);117goto err;118}119if (!drbg->parent_get_ctx_params(parent, params))120r = 0;121ossl_drbg_unlock_parent(drbg);122return r;123124err:125r = tsan_load(&drbg->reseed_counter) - 2;126if (r == 0)127r = UINT_MAX;128return r;129}130131/*132* Implements the get_entropy() callback133*134* If the DRBG has a parent, then the required amount of entropy input135* is fetched using the parent's ossl_prov_drbg_generate().136*137* Otherwise, the entropy is polled from the system entropy sources138* using ossl_pool_acquire_entropy().139*140* If a random pool has been added to the DRBG using RAND_add(), then141* its entropy will be used up first.142*/143size_t ossl_drbg_get_seed(void *vdrbg, unsigned char **pout,144int entropy, size_t min_len,145size_t max_len, int prediction_resistance,146const unsigned char *adin, size_t adin_len)147{148PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;149size_t bytes_needed;150unsigned char *buffer;151152/* Figure out how many bytes we need */153bytes_needed = entropy >= 0 ? (entropy + 7) / 8 : 0;154if (bytes_needed < min_len)155bytes_needed = min_len;156if (bytes_needed > max_len)157bytes_needed = max_len;158159/* Allocate storage */160buffer = OPENSSL_secure_malloc(bytes_needed);161if (buffer == NULL)162return 0;163164/*165* Get random data. Include our DRBG address as166* additional input, in order to provide a distinction between167* different DRBG child instances.168*169* Note: using the sizeof() operator on a pointer triggers170* a warning in some static code analyzers, but it's171* intentional and correct here.172*/173if (!ossl_prov_drbg_generate(drbg, buffer, bytes_needed,174drbg->strength, prediction_resistance,175(unsigned char *)&drbg, sizeof(drbg))) {176OPENSSL_secure_clear_free(buffer, bytes_needed);177ERR_raise(ERR_LIB_PROV, PROV_R_GENERATE_ERROR);178return 0;179}180*pout = buffer;181return bytes_needed;182}183184/* Implements the cleanup_entropy() callback */185void ossl_drbg_clear_seed(ossl_unused void *vdrbg,186unsigned char *out, size_t outlen)187{188OPENSSL_secure_clear_free(out, outlen);189}190191static size_t get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy,192size_t min_len, size_t max_len,193int prediction_resistance)194{195size_t bytes;196unsigned int p_str;197198if (drbg->parent == NULL)199/*200* In normal use (i.e. OpenSSL's own uses), this is never called.201* This remains purely for legacy reasons.202*/203return ossl_prov_get_entropy(drbg->provctx, pout, entropy, min_len,204max_len);205206if (drbg->parent_get_seed == NULL) {207ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED);208return 0;209}210if (!get_parent_strength(drbg, &p_str))211return 0;212if (drbg->strength > p_str) {213/*214* We currently don't support the algorithm from NIST SP 800-90C215* 10.1.2 to use a weaker DRBG as source216*/217ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK);218return 0;219}220221/*222* Our lock is already held, but we need to lock our parent before223* generating bits from it. Note: taking the lock will be a no-op224* if locking is not required (while drbg->parent->lock == NULL).225*/226if (!ossl_drbg_lock_parent(drbg))227return 0;228/*229* Get random data from parent. Include our DRBG address as230* additional input, in order to provide a distinction between231* different DRBG child instances.232*233* Note: using the sizeof() operator on a pointer triggers234* a warning in some static code analyzers, but it's235* intentional and correct here.236*/237bytes = drbg->parent_get_seed(drbg->parent, pout,238entropy > 0 ? entropy : (int)drbg->strength,239min_len, max_len, prediction_resistance,240(unsigned char *)&drbg, sizeof(drbg));241ossl_drbg_unlock_parent(drbg);242return bytes;243}244245static void cleanup_entropy(PROV_DRBG *drbg, unsigned char *out, size_t outlen)246{247if (drbg->parent == NULL) {248ossl_prov_cleanup_entropy(drbg->provctx, out, outlen);249} else if (drbg->parent_clear_seed != NULL) {250if (!ossl_drbg_lock_parent(drbg))251return;252drbg->parent_clear_seed(drbg->parent, out, outlen);253ossl_drbg_unlock_parent(drbg);254}255}256257#ifndef PROV_RAND_GET_RANDOM_NONCE258typedef struct prov_drbg_nonce_global_st {259CRYPTO_RWLOCK *rand_nonce_lock;260int rand_nonce_count;261} PROV_DRBG_NONCE_GLOBAL;262263/*264* drbg_ossl_ctx_new() calls drgb_setup() which calls rand_drbg_get_nonce()265* which needs to get the rand_nonce_lock out of the OSSL_LIB_CTX...but since266* drbg_ossl_ctx_new() hasn't finished running yet we need the rand_nonce_lock267* to be in a different global data object. Otherwise we will go into an268* infinite recursion loop.269*/270void *ossl_prov_drbg_nonce_ctx_new(OSSL_LIB_CTX *libctx)271{272PROV_DRBG_NONCE_GLOBAL *dngbl = OPENSSL_zalloc(sizeof(*dngbl));273274if (dngbl == NULL)275return NULL;276277dngbl->rand_nonce_lock = CRYPTO_THREAD_lock_new();278if (dngbl->rand_nonce_lock == NULL) {279OPENSSL_free(dngbl);280return NULL;281}282283return dngbl;284}285286void ossl_prov_drbg_nonce_ctx_free(void *vdngbl)287{288PROV_DRBG_NONCE_GLOBAL *dngbl = vdngbl;289290if (dngbl == NULL)291return;292293CRYPTO_THREAD_lock_free(dngbl->rand_nonce_lock);294295OPENSSL_free(dngbl);296}297298/* Get a nonce from the operating system */299static size_t prov_drbg_get_nonce(PROV_DRBG *drbg, unsigned char **pout,300size_t min_len, size_t max_len)301{302size_t ret = 0, n;303unsigned char *buf = NULL;304OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx);305PROV_DRBG_NONCE_GLOBAL *dngbl306= ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_NONCE_INDEX);307struct {308void *drbg;309int count;310} data;311312if (dngbl == NULL)313return 0;314315if (drbg->parent != NULL && drbg->parent_nonce != NULL) {316n = drbg->parent_nonce(drbg->parent, NULL, 0, drbg->min_noncelen,317drbg->max_noncelen);318if (n > 0 && (buf = OPENSSL_malloc(n)) != NULL) {319ret = drbg->parent_nonce(drbg->parent, buf, 0,320drbg->min_noncelen, drbg->max_noncelen);321if (ret == n) {322*pout = buf;323return ret;324}325OPENSSL_free(buf);326}327}328329/* Use the built in nonce source plus some of our specifics */330memset(&data, 0, sizeof(data));331data.drbg = drbg;332if (!CRYPTO_atomic_add(&dngbl->rand_nonce_count, 1, &data.count,333dngbl->rand_nonce_lock))334return 0;335return ossl_prov_get_nonce(drbg->provctx, pout, min_len, max_len,336&data, sizeof(data));337}338#endif /* PROV_RAND_GET_RANDOM_NONCE */339340/*341* Instantiate |drbg|, after it has been initialized. Use |pers| and342* |perslen| as prediction-resistance input.343*344* Requires that drbg->lock is already locked for write, if non-null.345*346* Returns 1 on success, 0 on failure.347*/348int ossl_prov_drbg_instantiate(PROV_DRBG *drbg, unsigned int strength,349int prediction_resistance,350const unsigned char *pers, size_t perslen)351{352unsigned char *nonce = NULL, *entropy = NULL;353size_t noncelen = 0, entropylen = 0;354size_t min_entropy, min_entropylen, max_entropylen;355356if (strength > drbg->strength) {357ERR_raise(ERR_LIB_PROV, PROV_R_INSUFFICIENT_DRBG_STRENGTH);358goto end;359}360min_entropy = drbg->strength;361min_entropylen = drbg->min_entropylen;362max_entropylen = drbg->max_entropylen;363364if (pers == NULL) {365pers = (const unsigned char *)ossl_pers_string;366perslen = sizeof(ossl_pers_string);367}368if (perslen > drbg->max_perslen) {369ERR_raise(ERR_LIB_PROV, PROV_R_PERSONALISATION_STRING_TOO_LONG);370goto end;371}372373if (drbg->state != EVP_RAND_STATE_UNINITIALISED) {374if (drbg->state == EVP_RAND_STATE_ERROR)375ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);376else377ERR_raise(ERR_LIB_PROV, PROV_R_ALREADY_INSTANTIATED);378goto end;379}380381drbg->state = EVP_RAND_STATE_ERROR;382383if (drbg->min_noncelen > 0) {384if (drbg->parent_nonce != NULL) {385noncelen = drbg->parent_nonce(drbg->parent, NULL, drbg->strength,386drbg->min_noncelen,387drbg->max_noncelen);388if (noncelen == 0) {389ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);390goto end;391}392nonce = OPENSSL_malloc(noncelen);393if (nonce == NULL) {394ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);395goto end;396}397if (noncelen != drbg->parent_nonce(drbg->parent, nonce, drbg->strength, drbg->min_noncelen, drbg->max_noncelen)) {398ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);399goto end;400}401#ifndef PROV_RAND_GET_RANDOM_NONCE402} else if (drbg->parent != NULL) {403#endif404/*405* NIST SP800-90Ar1 section 9.1 says you can combine getting406* the entropy and nonce in 1 call by increasing the entropy407* with 50% and increasing the minimum length to accommodate408* the length of the nonce. We do this in case a nonce is409* required and there is no parental nonce capability.410*/411min_entropy += drbg->strength / 2;412min_entropylen += drbg->min_noncelen;413max_entropylen += drbg->max_noncelen;414}415#ifndef PROV_RAND_GET_RANDOM_NONCE416else { /* parent == NULL */417noncelen = prov_drbg_get_nonce(drbg, &nonce, drbg->min_noncelen,418drbg->max_noncelen);419if (noncelen < drbg->min_noncelen420|| noncelen > drbg->max_noncelen) {421ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);422goto end;423}424}425#endif426}427428drbg->reseed_next_counter = tsan_load(&drbg->reseed_counter);429if (drbg->reseed_next_counter) {430drbg->reseed_next_counter++;431if (!drbg->reseed_next_counter)432drbg->reseed_next_counter = 1;433}434435entropylen = get_entropy(drbg, &entropy, min_entropy,436min_entropylen, max_entropylen,437prediction_resistance);438if (entropylen < min_entropylen439|| entropylen > max_entropylen) {440ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY);441goto end;442}443444if (!drbg->instantiate(drbg, entropy, entropylen, nonce, noncelen,445pers, perslen)) {446cleanup_entropy(drbg, entropy, entropylen);447ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_INSTANTIATING_DRBG);448goto end;449}450cleanup_entropy(drbg, entropy, entropylen);451452drbg->state = EVP_RAND_STATE_READY;453drbg->generate_counter = 1;454drbg->reseed_time = time(NULL);455tsan_store(&drbg->reseed_counter, drbg->reseed_next_counter);456457end:458if (nonce != NULL)459ossl_prov_cleanup_nonce(drbg->provctx, nonce, noncelen);460if (drbg->state == EVP_RAND_STATE_READY)461return 1;462return 0;463}464465/*466* Uninstantiate |drbg|. Must be instantiated before it can be used.467*468* Requires that drbg->lock is already locked for write, if non-null.469*470* Returns 1 on success, 0 on failure.471*/472int ossl_prov_drbg_uninstantiate(PROV_DRBG *drbg)473{474drbg->state = EVP_RAND_STATE_UNINITIALISED;475return 1;476}477478static int ossl_prov_drbg_reseed_unlocked(PROV_DRBG *drbg,479int prediction_resistance,480const unsigned char *ent,481size_t ent_len,482const unsigned char *adin,483size_t adinlen)484{485unsigned char *entropy = NULL;486size_t entropylen = 0;487488if (!ossl_prov_is_running())489return 0;490491if (drbg->state != EVP_RAND_STATE_READY) {492/* try to recover from previous errors */493rand_drbg_restart(drbg);494495if (drbg->state == EVP_RAND_STATE_ERROR) {496ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);497return 0;498}499if (drbg->state == EVP_RAND_STATE_UNINITIALISED) {500ERR_raise(ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED);501return 0;502}503}504505if (ent != NULL) {506if (ent_len < drbg->min_entropylen) {507ERR_raise(ERR_LIB_RAND, RAND_R_ENTROPY_OUT_OF_RANGE);508drbg->state = EVP_RAND_STATE_ERROR;509return 0;510}511if (ent_len > drbg->max_entropylen) {512ERR_raise(ERR_LIB_RAND, RAND_R_ENTROPY_INPUT_TOO_LONG);513drbg->state = EVP_RAND_STATE_ERROR;514return 0;515}516}517518if (adin == NULL) {519adinlen = 0;520} else if (adinlen > drbg->max_adinlen) {521ERR_raise(ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG);522return 0;523}524525drbg->state = EVP_RAND_STATE_ERROR;526527drbg->reseed_next_counter = tsan_load(&drbg->reseed_counter);528if (drbg->reseed_next_counter) {529drbg->reseed_next_counter++;530if (!drbg->reseed_next_counter)531drbg->reseed_next_counter = 1;532}533534if (ent != NULL) {535#ifdef FIPS_MODULE536/*537* NIST SP-800-90A mandates that entropy *shall not* be provided538* by the consuming application. Instead the data is added as additional539* input.540*541* (NIST SP-800-90Ar1, Sections 9.1 and 9.2)542*/543if (!drbg->reseed(drbg, NULL, 0, ent, ent_len)) {544ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED);545return 0;546}547#else548if (!drbg->reseed(drbg, ent, ent_len, adin, adinlen)) {549ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED);550return 0;551}552/* There isn't much point adding the same additional input twice */553adin = NULL;554adinlen = 0;555#endif556}557558/* Reseed using our sources in addition */559entropylen = get_entropy(drbg, &entropy, drbg->strength,560drbg->min_entropylen, drbg->max_entropylen,561prediction_resistance);562if (entropylen < drbg->min_entropylen563|| entropylen > drbg->max_entropylen) {564ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY);565goto end;566}567568if (!drbg->reseed(drbg, entropy, entropylen, adin, adinlen))569goto end;570571drbg->state = EVP_RAND_STATE_READY;572drbg->generate_counter = 1;573drbg->reseed_time = time(NULL);574tsan_store(&drbg->reseed_counter, drbg->reseed_next_counter);575if (drbg->parent != NULL)576drbg->parent_reseed_counter = get_parent_reseed_count(drbg);577578end:579cleanup_entropy(drbg, entropy, entropylen);580if (drbg->state == EVP_RAND_STATE_READY)581return 1;582return 0;583}584585/*586* Reseed |drbg|, mixing in the specified data587*588* Acquires the drbg->lock for writing, if non-null.589*590* Returns 1 on success, 0 on failure.591*/592int ossl_prov_drbg_reseed(PROV_DRBG *drbg, int prediction_resistance,593const unsigned char *ent, size_t ent_len,594const unsigned char *adin, size_t adinlen)595{596int ret;597598if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))599return 0;600601ret = ossl_prov_drbg_reseed_unlocked(drbg, prediction_resistance, ent,602ent_len, adin, adinlen);603604if (drbg->lock != NULL)605CRYPTO_THREAD_unlock(drbg->lock);606607return ret;608}609610/*611* Generate |outlen| bytes into the buffer at |out|. Reseed if we need612* to or if |prediction_resistance| is set. Additional input can be613* sent in |adin| and |adinlen|.614*615* Acquires the drbg->lock for writing if available616*617* Returns 1 on success, 0 on failure.618*619*/620int ossl_prov_drbg_generate(PROV_DRBG *drbg, unsigned char *out, size_t outlen,621unsigned int strength, int prediction_resistance,622const unsigned char *adin, size_t adinlen)623{624int fork_id;625int reseed_required = 0;626int ret = 0;627628if (!ossl_prov_is_running())629return 0;630631if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))632return 0;633634if (drbg->state != EVP_RAND_STATE_READY) {635/* try to recover from previous errors */636rand_drbg_restart(drbg);637638if (drbg->state == EVP_RAND_STATE_ERROR) {639ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);640goto err;641}642if (drbg->state == EVP_RAND_STATE_UNINITIALISED) {643ERR_raise(ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED);644goto err;645}646}647if (strength > drbg->strength) {648ERR_raise(ERR_LIB_PROV, PROV_R_INSUFFICIENT_DRBG_STRENGTH);649goto err;650}651652if (outlen > drbg->max_request) {653ERR_raise(ERR_LIB_PROV, PROV_R_REQUEST_TOO_LARGE_FOR_DRBG);654goto err;655}656if (adinlen > drbg->max_adinlen) {657ERR_raise(ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG);658goto err;659}660661fork_id = openssl_get_fork_id();662663if (drbg->fork_id != fork_id) {664drbg->fork_id = fork_id;665reseed_required = 1;666}667668if (drbg->reseed_interval > 0) {669if (drbg->generate_counter >= drbg->reseed_interval)670reseed_required = 1;671}672if (drbg->reseed_time_interval > 0) {673time_t now = time(NULL);674if (now < drbg->reseed_time675|| now - drbg->reseed_time >= drbg->reseed_time_interval)676reseed_required = 1;677}678if (drbg->parent != NULL679&& get_parent_reseed_count(drbg) != drbg->parent_reseed_counter)680reseed_required = 1;681682if (reseed_required || prediction_resistance) {683if (!ossl_prov_drbg_reseed_unlocked(drbg, prediction_resistance, NULL,6840, adin, adinlen)) {685ERR_raise(ERR_LIB_PROV, PROV_R_RESEED_ERROR);686goto err;687}688adin = NULL;689adinlen = 0;690}691692if (!drbg->generate(drbg, out, outlen, adin, adinlen)) {693drbg->state = EVP_RAND_STATE_ERROR;694ERR_raise(ERR_LIB_PROV, PROV_R_GENERATE_ERROR);695goto err;696}697698drbg->generate_counter++;699700ret = 1;701err:702if (drbg->lock != NULL)703CRYPTO_THREAD_unlock(drbg->lock);704705return ret;706}707708/*709* Restart |drbg|, using the specified entropy or additional input710*711* Tries its best to get the drbg instantiated by all means,712* regardless of its current state.713*714* Optionally, a |buffer| of |len| random bytes can be passed,715* which is assumed to contain at least |entropy| bits of entropy.716*717* If |entropy| > 0, the buffer content is used as entropy input.718*719* If |entropy| == 0, the buffer content is used as additional input720*721* Returns 1 on success, 0 on failure.722*723* This function is used internally only.724*/725static int rand_drbg_restart(PROV_DRBG *drbg)726{727/* repair error state */728if (drbg->state == EVP_RAND_STATE_ERROR)729drbg->uninstantiate(drbg);730731/* repair uninitialized state */732if (drbg->state == EVP_RAND_STATE_UNINITIALISED)733/* reinstantiate drbg */734ossl_prov_drbg_instantiate(drbg, drbg->strength, 0, NULL, 0);735736return drbg->state == EVP_RAND_STATE_READY;737}738739/* Provider support from here down */740static const OSSL_DISPATCH *find_call(const OSSL_DISPATCH *dispatch,741int function)742{743if (dispatch != NULL)744while (dispatch->function_id != 0) {745if (dispatch->function_id == function)746return dispatch;747dispatch++;748}749return NULL;750}751752int ossl_drbg_enable_locking(void *vctx)753{754PROV_DRBG *drbg = vctx;755756if (drbg != NULL && drbg->lock == NULL) {757if (drbg->parent_enable_locking != NULL)758if (!drbg->parent_enable_locking(drbg->parent)) {759ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED);760return 0;761}762drbg->lock = CRYPTO_THREAD_lock_new();763if (drbg->lock == NULL) {764ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_CREATE_LOCK);765return 0;766}767}768return 1;769}770771/*772* Allocate memory and initialize a new DRBG. The DRBG is allocated on773* the secure heap if |secure| is nonzero and the secure heap is enabled.774* The |parent|, if not NULL, will be used as random source for reseeding.775* This also requires the parent's provider context and the parent's lock.776*777* Returns a pointer to the new DRBG instance on success, NULL on failure.778*/779PROV_DRBG *ossl_rand_drbg_new(void *provctx, void *parent, const OSSL_DISPATCH *p_dispatch,780int (*dnew)(PROV_DRBG *ctx),781void (*dfree)(void *vctx),782int (*instantiate)(PROV_DRBG *drbg,783const unsigned char *entropy, size_t entropylen,784const unsigned char *nonce, size_t noncelen,785const unsigned char *pers, size_t perslen),786int (*uninstantiate)(PROV_DRBG *ctx),787int (*reseed)(PROV_DRBG *drbg, const unsigned char *ent, size_t ent_len,788const unsigned char *adin, size_t adin_len),789int (*generate)(PROV_DRBG *, unsigned char *out, size_t outlen,790const unsigned char *adin, size_t adin_len))791{792PROV_DRBG *drbg;793unsigned int p_str;794const OSSL_DISPATCH *pfunc;795796if (!ossl_prov_is_running())797return NULL;798799drbg = OPENSSL_zalloc(sizeof(*drbg));800if (drbg == NULL)801return NULL;802803drbg->provctx = provctx;804drbg->instantiate = instantiate;805drbg->uninstantiate = uninstantiate;806drbg->reseed = reseed;807drbg->generate = generate;808drbg->fork_id = openssl_get_fork_id();809810/* Extract parent's functions */811drbg->parent = parent;812if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_ENABLE_LOCKING)) != NULL)813drbg->parent_enable_locking = OSSL_FUNC_rand_enable_locking(pfunc);814if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_LOCK)) != NULL)815drbg->parent_lock = OSSL_FUNC_rand_lock(pfunc);816if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_UNLOCK)) != NULL)817drbg->parent_unlock = OSSL_FUNC_rand_unlock(pfunc);818if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_CTX_PARAMS)) != NULL)819drbg->parent_get_ctx_params = OSSL_FUNC_rand_get_ctx_params(pfunc);820if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_NONCE)) != NULL)821drbg->parent_nonce = OSSL_FUNC_rand_nonce(pfunc);822if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_SEED)) != NULL)823drbg->parent_get_seed = OSSL_FUNC_rand_get_seed(pfunc);824if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_CLEAR_SEED)) != NULL)825drbg->parent_clear_seed = OSSL_FUNC_rand_clear_seed(pfunc);826827/* Set some default maximums up */828drbg->max_entropylen = DRBG_MAX_LENGTH;829drbg->max_noncelen = DRBG_MAX_LENGTH;830drbg->max_perslen = DRBG_MAX_LENGTH;831drbg->max_adinlen = DRBG_MAX_LENGTH;832drbg->generate_counter = 1;833drbg->reseed_counter = 1;834drbg->reseed_interval = RESEED_INTERVAL;835drbg->reseed_time_interval = TIME_INTERVAL;836837if (!dnew(drbg))838goto err;839840if (parent != NULL) {841if (!get_parent_strength(drbg, &p_str))842goto err;843if (drbg->strength > p_str) {844/*845* We currently don't support the algorithm from NIST SP 800-90C846* 10.1.2 to use a weaker DRBG as source847*/848ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK);849goto err;850}851}852#ifdef TSAN_REQUIRES_LOCKING853if (!ossl_drbg_enable_locking(drbg))854goto err;855#endif856return drbg;857858err:859dfree(drbg);860return NULL;861}862863void ossl_rand_drbg_free(PROV_DRBG *drbg)864{865if (drbg == NULL)866return;867868CRYPTO_THREAD_lock_free(drbg->lock);869OPENSSL_free(drbg);870}871872/*873* Helper function called by internal DRBG implementations. Assumes that at874* least a read lock has been taken on drbg->lock875*/876int ossl_drbg_get_ctx_params(PROV_DRBG *drbg, OSSL_PARAM params[])877{878OSSL_PARAM *p;879880p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);881if (p != NULL && !OSSL_PARAM_set_int(p, drbg->state))882return 0;883884p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);885if (p != NULL && !OSSL_PARAM_set_int(p, drbg->strength))886return 0;887888p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MIN_ENTROPYLEN);889if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->min_entropylen))890return 0;891892p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_ENTROPYLEN);893if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_entropylen))894return 0;895896p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MIN_NONCELEN);897if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->min_noncelen))898return 0;899900p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_NONCELEN);901if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_noncelen))902return 0;903904p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_PERSLEN);905if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_perslen))906return 0;907908p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_ADINLEN);909if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_adinlen))910return 0;911912p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_REQUESTS);913if (p != NULL && !OSSL_PARAM_set_uint(p, drbg->reseed_interval))914return 0;915916p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_TIME);917if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time))918return 0;919920p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL);921if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time_interval))922return 0;923if (!OSSL_FIPS_IND_GET_CTX_PARAM(drbg, params))924return 0;925return 1;926}927928/*929* Helper function to get certain params that require no lock to obtain. Sets930* *complete to 1 if all the params were processed, or 0 otherwise931*/932int ossl_drbg_get_ctx_params_no_lock(PROV_DRBG *drbg, OSSL_PARAM params[],933int *complete)934{935size_t cnt = 0;936OSSL_PARAM *p;937938/* This value never changes once set */939p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);940if (p != NULL) {941if (!OSSL_PARAM_set_size_t(p, drbg->max_request))942return 0;943cnt++;944}945946/*947* Can be changed by multiple threads, but we tolerate inaccuracies in this948* value.949*/950p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_COUNTER);951if (p != NULL) {952if (!OSSL_PARAM_set_uint(p, tsan_load(&drbg->reseed_counter)))953return 0;954cnt++;955}956957if (params[cnt].key == NULL)958*complete = 1;959else960*complete = 0;961962return 1;963}964965int ossl_drbg_set_ctx_params(PROV_DRBG *drbg, const OSSL_PARAM params[])966{967const OSSL_PARAM *p;968969if (ossl_param_is_empty(params))970return 1;971972p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RESEED_REQUESTS);973if (p != NULL && !OSSL_PARAM_get_uint(p, &drbg->reseed_interval))974return 0;975976p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL);977if (p != NULL && !OSSL_PARAM_get_time_t(p, &drbg->reseed_time_interval))978return 0;979980return 1;981}982983#ifdef FIPS_MODULE984static int digest_allowed(const EVP_MD *md)985{986/* FIPS 140-3 IG D.R limited DRBG digests to a specific set */987static const char *const allowed_digests[] = {988"SHA1", /* SHA 1 allowed */989"SHA2-256",990"SHA2-512", /* non-truncated SHA2 allowed */991"SHA3-256",992"SHA3-512", /* non-truncated SHA3 allowed */993};994size_t i;995996for (i = 0; i < OSSL_NELEM(allowed_digests); i++) {997if (EVP_MD_is_a(md, allowed_digests[i]))998return 1;999}1000return 0;1001}1002#endif10031004/* Confirm digest is allowed to be used with a DRBG */1005int ossl_drbg_verify_digest(PROV_DRBG *drbg, OSSL_LIB_CTX *libctx,1006const EVP_MD *md)1007{1008#ifdef FIPS_MODULE1009int approved = digest_allowed(md);10101011if (!approved) {1012if (!OSSL_FIPS_IND_ON_UNAPPROVED(drbg, OSSL_FIPS_IND_SETTABLE0,1013libctx, "DRBG", "Digest",1014ossl_fips_config_restricted_drbg_digests)) {1015ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);1016return 0;1017}1018}1019#else /* FIPS_MODULE */1020/* Outside of FIPS, any digests that are not XOF are allowed */1021if (EVP_MD_xof(md)) {1022ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);1023return 0;1024}1025#endif /* FIPS_MODULE */1026return 1;1027}102810291030