Path: blob/main/crypto/openssl/providers/implementations/rands/drbg.c
48383 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,398drbg->strength,399drbg->min_noncelen,400drbg->max_noncelen)) {401ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);402goto end;403}404#ifndef PROV_RAND_GET_RANDOM_NONCE405} else if (drbg->parent != NULL) {406#endif407/*408* NIST SP800-90Ar1 section 9.1 says you can combine getting409* the entropy and nonce in 1 call by increasing the entropy410* with 50% and increasing the minimum length to accommodate411* the length of the nonce. We do this in case a nonce is412* required and there is no parental nonce capability.413*/414min_entropy += drbg->strength / 2;415min_entropylen += drbg->min_noncelen;416max_entropylen += drbg->max_noncelen;417}418#ifndef PROV_RAND_GET_RANDOM_NONCE419else { /* parent == NULL */420noncelen = prov_drbg_get_nonce(drbg, &nonce, drbg->min_noncelen,421drbg->max_noncelen);422if (noncelen < drbg->min_noncelen423|| noncelen > drbg->max_noncelen) {424ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);425goto end;426}427}428#endif429}430431drbg->reseed_next_counter = tsan_load(&drbg->reseed_counter);432if (drbg->reseed_next_counter) {433drbg->reseed_next_counter++;434if (!drbg->reseed_next_counter)435drbg->reseed_next_counter = 1;436}437438entropylen = get_entropy(drbg, &entropy, min_entropy,439min_entropylen, max_entropylen,440prediction_resistance);441if (entropylen < min_entropylen442|| entropylen > max_entropylen) {443ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY);444goto end;445}446447if (!drbg->instantiate(drbg, entropy, entropylen, nonce, noncelen,448pers, perslen)) {449cleanup_entropy(drbg, entropy, entropylen);450ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_INSTANTIATING_DRBG);451goto end;452}453cleanup_entropy(drbg, entropy, entropylen);454455drbg->state = EVP_RAND_STATE_READY;456drbg->generate_counter = 1;457drbg->reseed_time = time(NULL);458tsan_store(&drbg->reseed_counter, drbg->reseed_next_counter);459460end:461if (nonce != NULL)462ossl_prov_cleanup_nonce(drbg->provctx, nonce, noncelen);463if (drbg->state == EVP_RAND_STATE_READY)464return 1;465return 0;466}467468/*469* Uninstantiate |drbg|. Must be instantiated before it can be used.470*471* Requires that drbg->lock is already locked for write, if non-null.472*473* Returns 1 on success, 0 on failure.474*/475int ossl_prov_drbg_uninstantiate(PROV_DRBG *drbg)476{477drbg->state = EVP_RAND_STATE_UNINITIALISED;478return 1;479}480481static int ossl_prov_drbg_reseed_unlocked(PROV_DRBG *drbg,482int prediction_resistance,483const unsigned char *ent,484size_t ent_len,485const unsigned char *adin,486size_t adinlen)487{488unsigned char *entropy = NULL;489size_t entropylen = 0;490491if (!ossl_prov_is_running())492return 0;493494if (drbg->state != EVP_RAND_STATE_READY) {495/* try to recover from previous errors */496rand_drbg_restart(drbg);497498if (drbg->state == EVP_RAND_STATE_ERROR) {499ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);500return 0;501}502if (drbg->state == EVP_RAND_STATE_UNINITIALISED) {503ERR_raise(ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED);504return 0;505}506}507508if (ent != NULL) {509if (ent_len < drbg->min_entropylen) {510ERR_raise(ERR_LIB_RAND, RAND_R_ENTROPY_OUT_OF_RANGE);511drbg->state = EVP_RAND_STATE_ERROR;512return 0;513}514if (ent_len > drbg->max_entropylen) {515ERR_raise(ERR_LIB_RAND, RAND_R_ENTROPY_INPUT_TOO_LONG);516drbg->state = EVP_RAND_STATE_ERROR;517return 0;518}519}520521if (adin == NULL) {522adinlen = 0;523} else if (adinlen > drbg->max_adinlen) {524ERR_raise(ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG);525return 0;526}527528drbg->state = EVP_RAND_STATE_ERROR;529530drbg->reseed_next_counter = tsan_load(&drbg->reseed_counter);531if (drbg->reseed_next_counter) {532drbg->reseed_next_counter++;533if (!drbg->reseed_next_counter)534drbg->reseed_next_counter = 1;535}536537if (ent != NULL) {538#ifdef FIPS_MODULE539/*540* NIST SP-800-90A mandates that entropy *shall not* be provided541* by the consuming application. Instead the data is added as additional542* input.543*544* (NIST SP-800-90Ar1, Sections 9.1 and 9.2)545*/546if (!drbg->reseed(drbg, NULL, 0, ent, ent_len)) {547ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED);548return 0;549}550#else551if (!drbg->reseed(drbg, ent, ent_len, adin, adinlen)) {552ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED);553return 0;554}555/* There isn't much point adding the same additional input twice */556adin = NULL;557adinlen = 0;558#endif559}560561/* Reseed using our sources in addition */562entropylen = get_entropy(drbg, &entropy, drbg->strength,563drbg->min_entropylen, drbg->max_entropylen,564prediction_resistance);565if (entropylen < drbg->min_entropylen566|| entropylen > drbg->max_entropylen) {567ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY);568goto end;569}570571if (!drbg->reseed(drbg, entropy, entropylen, adin, adinlen))572goto end;573574drbg->state = EVP_RAND_STATE_READY;575drbg->generate_counter = 1;576drbg->reseed_time = time(NULL);577tsan_store(&drbg->reseed_counter, drbg->reseed_next_counter);578if (drbg->parent != NULL)579drbg->parent_reseed_counter = get_parent_reseed_count(drbg);580581end:582cleanup_entropy(drbg, entropy, entropylen);583if (drbg->state == EVP_RAND_STATE_READY)584return 1;585return 0;586}587588/*589* Reseed |drbg|, mixing in the specified data590*591* Acquires the drbg->lock for writing, if non-null.592*593* Returns 1 on success, 0 on failure.594*/595int ossl_prov_drbg_reseed(PROV_DRBG *drbg, int prediction_resistance,596const unsigned char *ent, size_t ent_len,597const unsigned char *adin, size_t adinlen)598{599int ret;600601if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))602return 0;603604ret = ossl_prov_drbg_reseed_unlocked(drbg, prediction_resistance, ent,605ent_len, adin, adinlen);606607if (drbg->lock != NULL)608CRYPTO_THREAD_unlock(drbg->lock);609610return ret;611}612613/*614* Generate |outlen| bytes into the buffer at |out|. Reseed if we need615* to or if |prediction_resistance| is set. Additional input can be616* sent in |adin| and |adinlen|.617*618* Acquires the drbg->lock for writing if available619*620* Returns 1 on success, 0 on failure.621*622*/623int ossl_prov_drbg_generate(PROV_DRBG *drbg, unsigned char *out, size_t outlen,624unsigned int strength, int prediction_resistance,625const unsigned char *adin, size_t adinlen)626{627int fork_id;628int reseed_required = 0;629int ret = 0;630631if (!ossl_prov_is_running())632return 0;633634if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))635return 0;636637if (drbg->state != EVP_RAND_STATE_READY) {638/* try to recover from previous errors */639rand_drbg_restart(drbg);640641if (drbg->state == EVP_RAND_STATE_ERROR) {642ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);643goto err;644}645if (drbg->state == EVP_RAND_STATE_UNINITIALISED) {646ERR_raise(ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED);647goto err;648}649}650if (strength > drbg->strength) {651ERR_raise(ERR_LIB_PROV, PROV_R_INSUFFICIENT_DRBG_STRENGTH);652goto err;653}654655if (outlen > drbg->max_request) {656ERR_raise(ERR_LIB_PROV, PROV_R_REQUEST_TOO_LARGE_FOR_DRBG);657goto err;658}659if (adinlen > drbg->max_adinlen) {660ERR_raise(ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG);661goto err;662}663664fork_id = openssl_get_fork_id();665666if (drbg->fork_id != fork_id) {667drbg->fork_id = fork_id;668reseed_required = 1;669}670671if (drbg->reseed_interval > 0) {672if (drbg->generate_counter >= drbg->reseed_interval)673reseed_required = 1;674}675if (drbg->reseed_time_interval > 0) {676time_t now = time(NULL);677if (now < drbg->reseed_time678|| now - drbg->reseed_time >= drbg->reseed_time_interval)679reseed_required = 1;680}681if (drbg->parent != NULL682&& get_parent_reseed_count(drbg) != drbg->parent_reseed_counter)683reseed_required = 1;684685if (reseed_required || prediction_resistance) {686if (!ossl_prov_drbg_reseed_unlocked(drbg, prediction_resistance, NULL,6870, adin, adinlen)) {688ERR_raise(ERR_LIB_PROV, PROV_R_RESEED_ERROR);689goto err;690}691adin = NULL;692adinlen = 0;693}694695if (!drbg->generate(drbg, out, outlen, adin, adinlen)) {696drbg->state = EVP_RAND_STATE_ERROR;697ERR_raise(ERR_LIB_PROV, PROV_R_GENERATE_ERROR);698goto err;699}700701drbg->generate_counter++;702703ret = 1;704err:705if (drbg->lock != NULL)706CRYPTO_THREAD_unlock(drbg->lock);707708return ret;709}710711/*712* Restart |drbg|, using the specified entropy or additional input713*714* Tries its best to get the drbg instantiated by all means,715* regardless of its current state.716*717* Optionally, a |buffer| of |len| random bytes can be passed,718* which is assumed to contain at least |entropy| bits of entropy.719*720* If |entropy| > 0, the buffer content is used as entropy input.721*722* If |entropy| == 0, the buffer content is used as additional input723*724* Returns 1 on success, 0 on failure.725*726* This function is used internally only.727*/728static int rand_drbg_restart(PROV_DRBG *drbg)729{730/* repair error state */731if (drbg->state == EVP_RAND_STATE_ERROR)732drbg->uninstantiate(drbg);733734/* repair uninitialized state */735if (drbg->state == EVP_RAND_STATE_UNINITIALISED)736/* reinstantiate drbg */737ossl_prov_drbg_instantiate(drbg, drbg->strength, 0, NULL, 0);738739return drbg->state == EVP_RAND_STATE_READY;740}741742/* Provider support from here down */743static const OSSL_DISPATCH *find_call(const OSSL_DISPATCH *dispatch,744int function)745{746if (dispatch != NULL)747while (dispatch->function_id != 0) {748if (dispatch->function_id == function)749return dispatch;750dispatch++;751}752return NULL;753}754755int ossl_drbg_enable_locking(void *vctx)756{757PROV_DRBG *drbg = vctx;758759if (drbg != NULL && drbg->lock == NULL) {760if (drbg->parent_enable_locking != NULL)761if (!drbg->parent_enable_locking(drbg->parent)) {762ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED);763return 0;764}765drbg->lock = CRYPTO_THREAD_lock_new();766if (drbg->lock == NULL) {767ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_CREATE_LOCK);768return 0;769}770}771return 1;772}773774/*775* Allocate memory and initialize a new DRBG. The DRBG is allocated on776* the secure heap if |secure| is nonzero and the secure heap is enabled.777* The |parent|, if not NULL, will be used as random source for reseeding.778* This also requires the parent's provider context and the parent's lock.779*780* Returns a pointer to the new DRBG instance on success, NULL on failure.781*/782PROV_DRBG *ossl_rand_drbg_new783(void *provctx, void *parent, const OSSL_DISPATCH *p_dispatch,784int (*dnew)(PROV_DRBG *ctx),785void (*dfree)(void *vctx),786int (*instantiate)(PROV_DRBG *drbg,787const unsigned char *entropy, size_t entropylen,788const unsigned char *nonce, size_t noncelen,789const unsigned char *pers, size_t perslen),790int (*uninstantiate)(PROV_DRBG *ctx),791int (*reseed)(PROV_DRBG *drbg, const unsigned char *ent, size_t ent_len,792const unsigned char *adin, size_t adin_len),793int (*generate)(PROV_DRBG *, unsigned char *out, size_t outlen,794const unsigned char *adin, size_t adin_len))795{796PROV_DRBG *drbg;797unsigned int p_str;798const OSSL_DISPATCH *pfunc;799800if (!ossl_prov_is_running())801return NULL;802803drbg = OPENSSL_zalloc(sizeof(*drbg));804if (drbg == NULL)805return NULL;806807drbg->provctx = provctx;808drbg->instantiate = instantiate;809drbg->uninstantiate = uninstantiate;810drbg->reseed = reseed;811drbg->generate = generate;812drbg->fork_id = openssl_get_fork_id();813814/* Extract parent's functions */815drbg->parent = parent;816if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_ENABLE_LOCKING)) != NULL)817drbg->parent_enable_locking = OSSL_FUNC_rand_enable_locking(pfunc);818if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_LOCK)) != NULL)819drbg->parent_lock = OSSL_FUNC_rand_lock(pfunc);820if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_UNLOCK)) != NULL)821drbg->parent_unlock = OSSL_FUNC_rand_unlock(pfunc);822if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_CTX_PARAMS)) != NULL)823drbg->parent_get_ctx_params = OSSL_FUNC_rand_get_ctx_params(pfunc);824if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_NONCE)) != NULL)825drbg->parent_nonce = OSSL_FUNC_rand_nonce(pfunc);826if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_SEED)) != NULL)827drbg->parent_get_seed = OSSL_FUNC_rand_get_seed(pfunc);828if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_CLEAR_SEED)) != NULL)829drbg->parent_clear_seed = OSSL_FUNC_rand_clear_seed(pfunc);830831/* Set some default maximums up */832drbg->max_entropylen = DRBG_MAX_LENGTH;833drbg->max_noncelen = DRBG_MAX_LENGTH;834drbg->max_perslen = DRBG_MAX_LENGTH;835drbg->max_adinlen = DRBG_MAX_LENGTH;836drbg->generate_counter = 1;837drbg->reseed_counter = 1;838drbg->reseed_interval = RESEED_INTERVAL;839drbg->reseed_time_interval = TIME_INTERVAL;840841if (!dnew(drbg))842goto err;843844if (parent != NULL) {845if (!get_parent_strength(drbg, &p_str))846goto err;847if (drbg->strength > p_str) {848/*849* We currently don't support the algorithm from NIST SP 800-90C850* 10.1.2 to use a weaker DRBG as source851*/852ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK);853goto err;854}855}856#ifdef TSAN_REQUIRES_LOCKING857if (!ossl_drbg_enable_locking(drbg))858goto err;859#endif860return drbg;861862err:863dfree(drbg);864return NULL;865}866867void ossl_rand_drbg_free(PROV_DRBG *drbg)868{869if (drbg == NULL)870return;871872CRYPTO_THREAD_lock_free(drbg->lock);873OPENSSL_free(drbg);874}875876/*877* Helper function called by internal DRBG implementations. Assumes that at878* least a read lock has been taken on drbg->lock879*/880int ossl_drbg_get_ctx_params(PROV_DRBG *drbg, OSSL_PARAM params[])881{882OSSL_PARAM *p;883884p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);885if (p != NULL && !OSSL_PARAM_set_int(p, drbg->state))886return 0;887888p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);889if (p != NULL && !OSSL_PARAM_set_int(p, drbg->strength))890return 0;891892p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MIN_ENTROPYLEN);893if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->min_entropylen))894return 0;895896p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_ENTROPYLEN);897if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_entropylen))898return 0;899900p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MIN_NONCELEN);901if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->min_noncelen))902return 0;903904p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_NONCELEN);905if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_noncelen))906return 0;907908p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_PERSLEN);909if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_perslen))910return 0;911912p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_ADINLEN);913if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_adinlen))914return 0;915916p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_REQUESTS);917if (p != NULL && !OSSL_PARAM_set_uint(p, drbg->reseed_interval))918return 0;919920p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_TIME);921if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time))922return 0;923924p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL);925if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time_interval))926return 0;927if (!OSSL_FIPS_IND_GET_CTX_PARAM(drbg, params))928return 0;929return 1;930}931932/*933* Helper function to get certain params that require no lock to obtain. Sets934* *complete to 1 if all the params were processed, or 0 otherwise935*/936int ossl_drbg_get_ctx_params_no_lock(PROV_DRBG *drbg, OSSL_PARAM params[],937int *complete)938{939size_t cnt = 0;940OSSL_PARAM *p;941942/* This value never changes once set */943p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);944if (p != NULL) {945if (!OSSL_PARAM_set_size_t(p, drbg->max_request))946return 0;947cnt++;948}949950/*951* Can be changed by multiple threads, but we tolerate inaccuracies in this952* value.953*/954p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_COUNTER);955if (p != NULL) {956if (!OSSL_PARAM_set_uint(p, tsan_load(&drbg->reseed_counter)))957return 0;958cnt++;959}960961if (params[cnt].key == NULL)962*complete = 1;963else964*complete = 0;965966return 1;967}968969int ossl_drbg_set_ctx_params(PROV_DRBG *drbg, const OSSL_PARAM params[])970{971const OSSL_PARAM *p;972973if (ossl_param_is_empty(params))974return 1;975976p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RESEED_REQUESTS);977if (p != NULL && !OSSL_PARAM_get_uint(p, &drbg->reseed_interval))978return 0;979980p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL);981if (p != NULL && !OSSL_PARAM_get_time_t(p, &drbg->reseed_time_interval))982return 0;983984return 1;985}986987#ifdef FIPS_MODULE988static int digest_allowed(const EVP_MD *md)989{990/* FIPS 140-3 IG D.R limited DRBG digests to a specific set */991static const char *const allowed_digests[] = {992"SHA1", /* SHA 1 allowed */993"SHA2-256", "SHA2-512", /* non-truncated SHA2 allowed */994"SHA3-256", "SHA3-512", /* non-truncated SHA3 allowed */995};996size_t i;997998for (i = 0; i < OSSL_NELEM(allowed_digests); i++) {999if (EVP_MD_is_a(md, allowed_digests[i]))1000return 1;1001}1002return 0;1003}1004#endif10051006/* Confirm digest is allowed to be used with a DRBG */1007int ossl_drbg_verify_digest(PROV_DRBG *drbg, OSSL_LIB_CTX *libctx,1008const EVP_MD *md)1009{1010#ifdef FIPS_MODULE1011int approved = digest_allowed(md);10121013if (!approved) {1014if (!OSSL_FIPS_IND_ON_UNAPPROVED(drbg, OSSL_FIPS_IND_SETTABLE0,1015libctx, "DRBG", "Digest",1016ossl_fips_config_restricted_drbg_digests)) {1017ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);1018return 0;1019}1020}1021#else /* FIPS_MODULE */1022/* Outside of FIPS, any digests that are not XOF are allowed */1023if (EVP_MD_xof(md)) {1024ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);1025return 0;1026}1027#endif /* FIPS_MODULE */1028return 1;1029}103010311032