xref: /freebsd-src/crypto/openssl/providers/implementations/rands/drbg.c (revision a7148ab39c03abd4d1a84997c70bf96f15dd2a09)
1b077aed3SPierre Pronchery /*
244096ebdSEnji Cooper  * Copyright 2011-2024 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8b077aed3SPierre Pronchery  */
9b077aed3SPierre Pronchery 
10b077aed3SPierre Pronchery #include <string.h>
11b077aed3SPierre Pronchery #include <openssl/crypto.h>
12b077aed3SPierre Pronchery #include <openssl/err.h>
13b077aed3SPierre Pronchery #include <openssl/rand.h>
14b077aed3SPierre Pronchery #include <openssl/evp.h>
15b077aed3SPierre Pronchery #include "crypto/rand.h"
16b077aed3SPierre Pronchery #include <openssl/proverr.h>
17b077aed3SPierre Pronchery #include "drbg_local.h"
18b077aed3SPierre Pronchery #include "internal/thread_once.h"
19b077aed3SPierre Pronchery #include "crypto/cryptlib.h"
20b077aed3SPierre Pronchery #include "prov/seeding.h"
21b077aed3SPierre Pronchery #include "crypto/rand_pool.h"
22b077aed3SPierre Pronchery #include "prov/provider_ctx.h"
23b077aed3SPierre Pronchery #include "prov/providercommon.h"
24b077aed3SPierre Pronchery 
25b077aed3SPierre Pronchery /*
26b077aed3SPierre Pronchery  * Support framework for NIST SP 800-90A DRBG
27b077aed3SPierre Pronchery  *
28b077aed3SPierre Pronchery  * See manual page PROV_DRBG(7) for a general overview.
29b077aed3SPierre Pronchery  *
30b077aed3SPierre Pronchery  * The OpenSSL model is to have new and free functions, and that new
31b077aed3SPierre Pronchery  * does all initialization.  That is not the NIST model, which has
32b077aed3SPierre Pronchery  * instantiation and un-instantiate, and re-use within a new/free
33b077aed3SPierre Pronchery  * lifecycle.  (No doubt this comes from the desire to support hardware
34b077aed3SPierre Pronchery  * DRBG, where allocation of resources on something like an HSM is
35b077aed3SPierre Pronchery  * a much bigger deal than just re-setting an allocated resource.)
36b077aed3SPierre Pronchery  */
37b077aed3SPierre Pronchery 
38b077aed3SPierre Pronchery /* NIST SP 800-90A DRBG recommends the use of a personalization string. */
39b077aed3SPierre Pronchery static const char ossl_pers_string[] = DRBG_DEFAULT_PERS_STRING;
40b077aed3SPierre Pronchery 
41b077aed3SPierre Pronchery static const OSSL_DISPATCH *find_call(const OSSL_DISPATCH *dispatch,
42b077aed3SPierre Pronchery                                       int function);
43b077aed3SPierre Pronchery 
44b077aed3SPierre Pronchery static int rand_drbg_restart(PROV_DRBG *drbg);
45b077aed3SPierre Pronchery 
46b077aed3SPierre Pronchery int ossl_drbg_lock(void *vctx)
47b077aed3SPierre Pronchery {
48b077aed3SPierre Pronchery     PROV_DRBG *drbg = vctx;
49b077aed3SPierre Pronchery 
50b077aed3SPierre Pronchery     if (drbg == NULL || drbg->lock == NULL)
51b077aed3SPierre Pronchery         return 1;
52b077aed3SPierre Pronchery     return CRYPTO_THREAD_write_lock(drbg->lock);
53b077aed3SPierre Pronchery }
54b077aed3SPierre Pronchery 
55b077aed3SPierre Pronchery void ossl_drbg_unlock(void *vctx)
56b077aed3SPierre Pronchery {
57b077aed3SPierre Pronchery     PROV_DRBG *drbg = vctx;
58b077aed3SPierre Pronchery 
59b077aed3SPierre Pronchery     if (drbg != NULL && drbg->lock != NULL)
60b077aed3SPierre Pronchery         CRYPTO_THREAD_unlock(drbg->lock);
61b077aed3SPierre Pronchery }
62b077aed3SPierre Pronchery 
63b077aed3SPierre Pronchery static int ossl_drbg_lock_parent(PROV_DRBG *drbg)
64b077aed3SPierre Pronchery {
65b077aed3SPierre Pronchery     void *parent = drbg->parent;
66b077aed3SPierre Pronchery 
67b077aed3SPierre Pronchery     if (parent != NULL
68b077aed3SPierre Pronchery             && drbg->parent_lock != NULL
69b077aed3SPierre Pronchery             && !drbg->parent_lock(parent)) {
70b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED);
71b077aed3SPierre Pronchery         return 0;
72b077aed3SPierre Pronchery     }
73b077aed3SPierre Pronchery     return 1;
74b077aed3SPierre Pronchery }
75b077aed3SPierre Pronchery 
76b077aed3SPierre Pronchery static void ossl_drbg_unlock_parent(PROV_DRBG *drbg)
77b077aed3SPierre Pronchery {
78b077aed3SPierre Pronchery     void *parent = drbg->parent;
79b077aed3SPierre Pronchery 
80b077aed3SPierre Pronchery     if (parent != NULL && drbg->parent_unlock != NULL)
81b077aed3SPierre Pronchery         drbg->parent_unlock(parent);
82b077aed3SPierre Pronchery }
83b077aed3SPierre Pronchery 
84b077aed3SPierre Pronchery static int get_parent_strength(PROV_DRBG *drbg, unsigned int *str)
85b077aed3SPierre Pronchery {
86b077aed3SPierre Pronchery     OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
87b077aed3SPierre Pronchery     void *parent = drbg->parent;
88b077aed3SPierre Pronchery     int res;
89b077aed3SPierre Pronchery 
90b077aed3SPierre Pronchery     if (drbg->parent_get_ctx_params == NULL) {
91b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH);
92b077aed3SPierre Pronchery         return 0;
93b077aed3SPierre Pronchery     }
94b077aed3SPierre Pronchery 
95b077aed3SPierre Pronchery     *params = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, str);
96b077aed3SPierre Pronchery     if (!ossl_drbg_lock_parent(drbg)) {
97b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOCK_PARENT);
98b077aed3SPierre Pronchery         return 0;
99b077aed3SPierre Pronchery     }
100b077aed3SPierre Pronchery     res = drbg->parent_get_ctx_params(parent, params);
101b077aed3SPierre Pronchery     ossl_drbg_unlock_parent(drbg);
102b077aed3SPierre Pronchery     if (!res) {
103b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH);
104b077aed3SPierre Pronchery         return 0;
105b077aed3SPierre Pronchery     }
106b077aed3SPierre Pronchery     return 1;
107b077aed3SPierre Pronchery }
108b077aed3SPierre Pronchery 
109b077aed3SPierre Pronchery static unsigned int get_parent_reseed_count(PROV_DRBG *drbg)
110b077aed3SPierre Pronchery {
111b077aed3SPierre Pronchery     OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
112b077aed3SPierre Pronchery     void *parent = drbg->parent;
113b077aed3SPierre Pronchery     unsigned int r = 0;
114b077aed3SPierre Pronchery 
115b077aed3SPierre Pronchery     *params = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_COUNTER, &r);
116b077aed3SPierre Pronchery     if (!ossl_drbg_lock_parent(drbg)) {
117b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOCK_PARENT);
118b077aed3SPierre Pronchery         goto err;
119b077aed3SPierre Pronchery     }
120b077aed3SPierre Pronchery     if (!drbg->parent_get_ctx_params(parent, params))
121b077aed3SPierre Pronchery         r = 0;
122b077aed3SPierre Pronchery     ossl_drbg_unlock_parent(drbg);
123b077aed3SPierre Pronchery     return r;
124b077aed3SPierre Pronchery 
125b077aed3SPierre Pronchery  err:
126b077aed3SPierre Pronchery     r = tsan_load(&drbg->reseed_counter) - 2;
127b077aed3SPierre Pronchery     if (r == 0)
128b077aed3SPierre Pronchery         r = UINT_MAX;
129b077aed3SPierre Pronchery     return r;
130b077aed3SPierre Pronchery }
131b077aed3SPierre Pronchery 
132b077aed3SPierre Pronchery /*
133b077aed3SPierre Pronchery  * Implements the get_entropy() callback
134b077aed3SPierre Pronchery  *
135b077aed3SPierre Pronchery  * If the DRBG has a parent, then the required amount of entropy input
136b077aed3SPierre Pronchery  * is fetched using the parent's ossl_prov_drbg_generate().
137b077aed3SPierre Pronchery  *
138b077aed3SPierre Pronchery  * Otherwise, the entropy is polled from the system entropy sources
139b077aed3SPierre Pronchery  * using ossl_pool_acquire_entropy().
140b077aed3SPierre Pronchery  *
141b077aed3SPierre Pronchery  * If a random pool has been added to the DRBG using RAND_add(), then
142b077aed3SPierre Pronchery  * its entropy will be used up first.
143b077aed3SPierre Pronchery  */
144b077aed3SPierre Pronchery size_t ossl_drbg_get_seed(void *vdrbg, unsigned char **pout,
145b077aed3SPierre Pronchery                           int entropy, size_t min_len,
146b077aed3SPierre Pronchery                           size_t max_len, int prediction_resistance,
147b077aed3SPierre Pronchery                           const unsigned char *adin, size_t adin_len)
148b077aed3SPierre Pronchery {
149b077aed3SPierre Pronchery     PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
150b077aed3SPierre Pronchery     size_t bytes_needed;
151b077aed3SPierre Pronchery     unsigned char *buffer;
152b077aed3SPierre Pronchery 
153b077aed3SPierre Pronchery     /* Figure out how many bytes we need */
154b077aed3SPierre Pronchery     bytes_needed = entropy >= 0 ? (entropy + 7) / 8 : 0;
155b077aed3SPierre Pronchery     if (bytes_needed < min_len)
156b077aed3SPierre Pronchery         bytes_needed = min_len;
157b077aed3SPierre Pronchery     if (bytes_needed > max_len)
158b077aed3SPierre Pronchery         bytes_needed = max_len;
159b077aed3SPierre Pronchery 
160b077aed3SPierre Pronchery     /* Allocate storage */
161b077aed3SPierre Pronchery     buffer = OPENSSL_secure_malloc(bytes_needed);
162b077aed3SPierre Pronchery     if (buffer == NULL) {
163b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
164b077aed3SPierre Pronchery         return 0;
165b077aed3SPierre Pronchery     }
166b077aed3SPierre Pronchery 
167b077aed3SPierre Pronchery     /*
168b077aed3SPierre Pronchery      * Get random data.  Include our DRBG address as
169b077aed3SPierre Pronchery      * additional input, in order to provide a distinction between
170b077aed3SPierre Pronchery      * different DRBG child instances.
171b077aed3SPierre Pronchery      *
172b077aed3SPierre Pronchery      * Note: using the sizeof() operator on a pointer triggers
173b077aed3SPierre Pronchery      *       a warning in some static code analyzers, but it's
174b077aed3SPierre Pronchery      *       intentional and correct here.
175b077aed3SPierre Pronchery      */
176b077aed3SPierre Pronchery     if (!ossl_prov_drbg_generate(drbg, buffer, bytes_needed,
177b077aed3SPierre Pronchery                                  drbg->strength, prediction_resistance,
178b077aed3SPierre Pronchery                                  (unsigned char *)&drbg, sizeof(drbg))) {
179b077aed3SPierre Pronchery         OPENSSL_secure_clear_free(buffer, bytes_needed);
180b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_GENERATE_ERROR);
181b077aed3SPierre Pronchery         return 0;
182b077aed3SPierre Pronchery     }
183b077aed3SPierre Pronchery     *pout = buffer;
184b077aed3SPierre Pronchery     return bytes_needed;
185b077aed3SPierre Pronchery }
186b077aed3SPierre Pronchery 
187b077aed3SPierre Pronchery /* Implements the cleanup_entropy() callback */
188b077aed3SPierre Pronchery void ossl_drbg_clear_seed(ossl_unused void *vdrbg,
189b077aed3SPierre Pronchery                           unsigned char *out, size_t outlen)
190b077aed3SPierre Pronchery {
191b077aed3SPierre Pronchery     OPENSSL_secure_clear_free(out, outlen);
192b077aed3SPierre Pronchery }
193b077aed3SPierre Pronchery 
194b077aed3SPierre Pronchery static size_t get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy,
195b077aed3SPierre Pronchery                           size_t min_len, size_t max_len,
196b077aed3SPierre Pronchery                           int prediction_resistance)
197b077aed3SPierre Pronchery {
198b077aed3SPierre Pronchery     size_t bytes;
199b077aed3SPierre Pronchery     unsigned int p_str;
200b077aed3SPierre Pronchery 
201b077aed3SPierre Pronchery     if (drbg->parent == NULL)
202b077aed3SPierre Pronchery #ifdef FIPS_MODULE
203b077aed3SPierre Pronchery         return ossl_crngt_get_entropy(drbg, pout, entropy, min_len, max_len,
204b077aed3SPierre Pronchery                                       prediction_resistance);
205b077aed3SPierre Pronchery #else
206*a7148ab3SEnji Cooper         /*
207*a7148ab3SEnji Cooper          * In normal use (i.e. OpenSSL's own uses), this is never called.
208*a7148ab3SEnji Cooper          * Outside of the FIPS provider, OpenSSL sets its DRBGs up so that
209*a7148ab3SEnji Cooper          * they always have a parent.  This remains purely for legacy reasons.
210*a7148ab3SEnji Cooper          */
211b077aed3SPierre Pronchery         return ossl_prov_get_entropy(drbg->provctx, pout, entropy, min_len,
212b077aed3SPierre Pronchery                                      max_len);
213b077aed3SPierre Pronchery #endif
214b077aed3SPierre Pronchery 
215b077aed3SPierre Pronchery     if (drbg->parent_get_seed == NULL) {
216b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED);
217b077aed3SPierre Pronchery         return 0;
218b077aed3SPierre Pronchery     }
219b077aed3SPierre Pronchery     if (!get_parent_strength(drbg, &p_str))
220b077aed3SPierre Pronchery         return 0;
221b077aed3SPierre Pronchery     if (drbg->strength > p_str) {
222b077aed3SPierre Pronchery         /*
223b077aed3SPierre Pronchery          * We currently don't support the algorithm from NIST SP 800-90C
224b077aed3SPierre Pronchery          * 10.1.2 to use a weaker DRBG as source
225b077aed3SPierre Pronchery          */
226b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK);
227b077aed3SPierre Pronchery         return 0;
228b077aed3SPierre Pronchery     }
229b077aed3SPierre Pronchery 
230b077aed3SPierre Pronchery     /*
231b077aed3SPierre Pronchery      * Our lock is already held, but we need to lock our parent before
232b077aed3SPierre Pronchery      * generating bits from it.  Note: taking the lock will be a no-op
233b077aed3SPierre Pronchery      * if locking is not required (while drbg->parent->lock == NULL).
234b077aed3SPierre Pronchery      */
235b077aed3SPierre Pronchery     if (!ossl_drbg_lock_parent(drbg))
236b077aed3SPierre Pronchery         return 0;
237b077aed3SPierre Pronchery     /*
238b077aed3SPierre Pronchery      * Get random data from parent.  Include our DRBG address as
239b077aed3SPierre Pronchery      * additional input, in order to provide a distinction between
240b077aed3SPierre Pronchery      * different DRBG child instances.
241b077aed3SPierre Pronchery      *
242b077aed3SPierre Pronchery      * Note: using the sizeof() operator on a pointer triggers
243b077aed3SPierre Pronchery      *       a warning in some static code analyzers, but it's
244b077aed3SPierre Pronchery      *       intentional and correct here.
245b077aed3SPierre Pronchery      */
246b077aed3SPierre Pronchery     bytes = drbg->parent_get_seed(drbg->parent, pout, drbg->strength,
247b077aed3SPierre Pronchery                                   min_len, max_len, prediction_resistance,
248b077aed3SPierre Pronchery                                   (unsigned char *)&drbg, sizeof(drbg));
249b077aed3SPierre Pronchery     ossl_drbg_unlock_parent(drbg);
250b077aed3SPierre Pronchery     return bytes;
251b077aed3SPierre Pronchery }
252b077aed3SPierre Pronchery 
253b077aed3SPierre Pronchery static void cleanup_entropy(PROV_DRBG *drbg, unsigned char *out, size_t outlen)
254b077aed3SPierre Pronchery {
255b077aed3SPierre Pronchery     if (drbg->parent == NULL) {
256b077aed3SPierre Pronchery #ifdef FIPS_MODULE
257b077aed3SPierre Pronchery         ossl_crngt_cleanup_entropy(drbg, out, outlen);
258b077aed3SPierre Pronchery #else
259b077aed3SPierre Pronchery         ossl_prov_cleanup_entropy(drbg->provctx, out, outlen);
260b077aed3SPierre Pronchery #endif
261b077aed3SPierre Pronchery     } else if (drbg->parent_clear_seed != NULL) {
262b077aed3SPierre Pronchery         if (!ossl_drbg_lock_parent(drbg))
263b077aed3SPierre Pronchery             return;
264b077aed3SPierre Pronchery         drbg->parent_clear_seed(drbg->parent, out, outlen);
265b077aed3SPierre Pronchery         ossl_drbg_unlock_parent(drbg);
266b077aed3SPierre Pronchery     }
267b077aed3SPierre Pronchery }
268b077aed3SPierre Pronchery 
269b077aed3SPierre Pronchery #ifndef PROV_RAND_GET_RANDOM_NONCE
270b077aed3SPierre Pronchery typedef struct prov_drbg_nonce_global_st {
271b077aed3SPierre Pronchery     CRYPTO_RWLOCK *rand_nonce_lock;
272b077aed3SPierre Pronchery     int rand_nonce_count;
273b077aed3SPierre Pronchery } PROV_DRBG_NONCE_GLOBAL;
274b077aed3SPierre Pronchery 
275b077aed3SPierre Pronchery /*
276b077aed3SPierre Pronchery  * drbg_ossl_ctx_new() calls drgb_setup() which calls rand_drbg_get_nonce()
277b077aed3SPierre Pronchery  * which needs to get the rand_nonce_lock out of the OSSL_LIB_CTX...but since
278b077aed3SPierre Pronchery  * drbg_ossl_ctx_new() hasn't finished running yet we need the rand_nonce_lock
279b077aed3SPierre Pronchery  * to be in a different global data object. Otherwise we will go into an
280b077aed3SPierre Pronchery  * infinite recursion loop.
281b077aed3SPierre Pronchery  */
282b077aed3SPierre Pronchery static void *prov_drbg_nonce_ossl_ctx_new(OSSL_LIB_CTX *libctx)
283b077aed3SPierre Pronchery {
284b077aed3SPierre Pronchery     PROV_DRBG_NONCE_GLOBAL *dngbl = OPENSSL_zalloc(sizeof(*dngbl));
285b077aed3SPierre Pronchery 
286b077aed3SPierre Pronchery     if (dngbl == NULL)
287b077aed3SPierre Pronchery         return NULL;
288b077aed3SPierre Pronchery 
289b077aed3SPierre Pronchery     dngbl->rand_nonce_lock = CRYPTO_THREAD_lock_new();
290b077aed3SPierre Pronchery     if (dngbl->rand_nonce_lock == NULL) {
291b077aed3SPierre Pronchery         OPENSSL_free(dngbl);
292b077aed3SPierre Pronchery         return NULL;
293b077aed3SPierre Pronchery     }
294b077aed3SPierre Pronchery 
295b077aed3SPierre Pronchery     return dngbl;
296b077aed3SPierre Pronchery }
297b077aed3SPierre Pronchery 
298b077aed3SPierre Pronchery static void prov_drbg_nonce_ossl_ctx_free(void *vdngbl)
299b077aed3SPierre Pronchery {
300b077aed3SPierre Pronchery     PROV_DRBG_NONCE_GLOBAL *dngbl = vdngbl;
301b077aed3SPierre Pronchery 
302b077aed3SPierre Pronchery     if (dngbl == NULL)
303b077aed3SPierre Pronchery         return;
304b077aed3SPierre Pronchery 
305b077aed3SPierre Pronchery     CRYPTO_THREAD_lock_free(dngbl->rand_nonce_lock);
306b077aed3SPierre Pronchery 
307b077aed3SPierre Pronchery     OPENSSL_free(dngbl);
308b077aed3SPierre Pronchery }
309b077aed3SPierre Pronchery 
310b077aed3SPierre Pronchery static const OSSL_LIB_CTX_METHOD drbg_nonce_ossl_ctx_method = {
311b077aed3SPierre Pronchery     OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
312b077aed3SPierre Pronchery     prov_drbg_nonce_ossl_ctx_new,
313b077aed3SPierre Pronchery     prov_drbg_nonce_ossl_ctx_free,
314b077aed3SPierre Pronchery };
315b077aed3SPierre Pronchery 
316b077aed3SPierre Pronchery /* Get a nonce from the operating system */
317b077aed3SPierre Pronchery static size_t prov_drbg_get_nonce(PROV_DRBG *drbg, unsigned char **pout,
318b077aed3SPierre Pronchery                                   size_t min_len, size_t max_len)
319b077aed3SPierre Pronchery {
320b077aed3SPierre Pronchery     size_t ret = 0, n;
321b077aed3SPierre Pronchery     unsigned char *buf = NULL;
322b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx);
323b077aed3SPierre Pronchery     PROV_DRBG_NONCE_GLOBAL *dngbl
324b077aed3SPierre Pronchery         = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_NONCE_INDEX,
325b077aed3SPierre Pronchery                                 &drbg_nonce_ossl_ctx_method);
326b077aed3SPierre Pronchery     struct {
327b077aed3SPierre Pronchery         void *drbg;
328b077aed3SPierre Pronchery         int count;
329b077aed3SPierre Pronchery     } data;
330b077aed3SPierre Pronchery 
331b077aed3SPierre Pronchery     if (dngbl == NULL)
332b077aed3SPierre Pronchery         return 0;
333b077aed3SPierre Pronchery 
334b077aed3SPierre Pronchery     if (drbg->parent != NULL && drbg->parent_nonce != NULL) {
335b077aed3SPierre Pronchery         n = drbg->parent_nonce(drbg->parent, NULL, 0, drbg->min_noncelen,
336b077aed3SPierre Pronchery                                drbg->max_noncelen);
337b077aed3SPierre Pronchery         if (n > 0 && (buf = OPENSSL_malloc(n)) != NULL) {
338b077aed3SPierre Pronchery             ret = drbg->parent_nonce(drbg->parent, buf, 0,
339b077aed3SPierre Pronchery                                      drbg->min_noncelen, drbg->max_noncelen);
340b077aed3SPierre Pronchery             if (ret == n) {
341b077aed3SPierre Pronchery                 *pout = buf;
342b077aed3SPierre Pronchery                 return ret;
343b077aed3SPierre Pronchery             }
344b077aed3SPierre Pronchery             OPENSSL_free(buf);
345b077aed3SPierre Pronchery         }
346b077aed3SPierre Pronchery     }
347b077aed3SPierre Pronchery 
348b077aed3SPierre Pronchery     /* Use the built in nonce source plus some of our specifics */
349b077aed3SPierre Pronchery     memset(&data, 0, sizeof(data));
350b077aed3SPierre Pronchery     data.drbg = drbg;
351b077aed3SPierre Pronchery     CRYPTO_atomic_add(&dngbl->rand_nonce_count, 1, &data.count,
352b077aed3SPierre Pronchery                       dngbl->rand_nonce_lock);
353b077aed3SPierre Pronchery     return ossl_prov_get_nonce(drbg->provctx, pout, min_len, max_len,
354b077aed3SPierre Pronchery                                &data, sizeof(data));
355b077aed3SPierre Pronchery }
356b077aed3SPierre Pronchery #endif /* PROV_RAND_GET_RANDOM_NONCE */
357b077aed3SPierre Pronchery 
358b077aed3SPierre Pronchery /*
359b077aed3SPierre Pronchery  * Instantiate |drbg|, after it has been initialized.  Use |pers| and
360b077aed3SPierre Pronchery  * |perslen| as prediction-resistance input.
361b077aed3SPierre Pronchery  *
362b077aed3SPierre Pronchery  * Requires that drbg->lock is already locked for write, if non-null.
363b077aed3SPierre Pronchery  *
364b077aed3SPierre Pronchery  * Returns 1 on success, 0 on failure.
365b077aed3SPierre Pronchery  */
366b077aed3SPierre Pronchery int ossl_prov_drbg_instantiate(PROV_DRBG *drbg, unsigned int strength,
367b077aed3SPierre Pronchery                                int prediction_resistance,
368b077aed3SPierre Pronchery                                const unsigned char *pers, size_t perslen)
369b077aed3SPierre Pronchery {
370b077aed3SPierre Pronchery     unsigned char *nonce = NULL, *entropy = NULL;
371b077aed3SPierre Pronchery     size_t noncelen = 0, entropylen = 0;
372b077aed3SPierre Pronchery     size_t min_entropy, min_entropylen, max_entropylen;
373b077aed3SPierre Pronchery 
374b077aed3SPierre Pronchery     if (strength > drbg->strength) {
375b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_INSUFFICIENT_DRBG_STRENGTH);
376b077aed3SPierre Pronchery         goto end;
377b077aed3SPierre Pronchery     }
378b077aed3SPierre Pronchery     min_entropy = drbg->strength;
379b077aed3SPierre Pronchery     min_entropylen = drbg->min_entropylen;
380b077aed3SPierre Pronchery     max_entropylen = drbg->max_entropylen;
381b077aed3SPierre Pronchery 
382b077aed3SPierre Pronchery     if (pers == NULL) {
383b077aed3SPierre Pronchery         pers = (const unsigned char *)ossl_pers_string;
384b077aed3SPierre Pronchery         perslen = sizeof(ossl_pers_string);
385b077aed3SPierre Pronchery     }
386b077aed3SPierre Pronchery     if (perslen > drbg->max_perslen) {
387b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_PERSONALISATION_STRING_TOO_LONG);
388b077aed3SPierre Pronchery         goto end;
389b077aed3SPierre Pronchery     }
390b077aed3SPierre Pronchery 
391b077aed3SPierre Pronchery     if (drbg->state != EVP_RAND_STATE_UNINITIALISED) {
392b077aed3SPierre Pronchery         if (drbg->state == EVP_RAND_STATE_ERROR)
393b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);
394b077aed3SPierre Pronchery         else
395b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_ALREADY_INSTANTIATED);
396b077aed3SPierre Pronchery         goto end;
397b077aed3SPierre Pronchery     }
398b077aed3SPierre Pronchery 
399b077aed3SPierre Pronchery     drbg->state = EVP_RAND_STATE_ERROR;
400b077aed3SPierre Pronchery 
401b077aed3SPierre Pronchery     if (drbg->min_noncelen > 0) {
402b077aed3SPierre Pronchery         if (drbg->parent_nonce != NULL) {
403b077aed3SPierre Pronchery             noncelen = drbg->parent_nonce(drbg->parent, NULL, drbg->strength,
404b077aed3SPierre Pronchery                                           drbg->min_noncelen,
405b077aed3SPierre Pronchery                                           drbg->max_noncelen);
406b077aed3SPierre Pronchery             if (noncelen == 0) {
407b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
408b077aed3SPierre Pronchery                 goto end;
409b077aed3SPierre Pronchery             }
410b077aed3SPierre Pronchery             nonce = OPENSSL_malloc(noncelen);
411b077aed3SPierre Pronchery             if (nonce == NULL) {
412b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
413b077aed3SPierre Pronchery                 goto end;
414b077aed3SPierre Pronchery             }
415b077aed3SPierre Pronchery             if (noncelen != drbg->parent_nonce(drbg->parent, nonce,
416b077aed3SPierre Pronchery                                                drbg->strength,
417b077aed3SPierre Pronchery                                                drbg->min_noncelen,
418b077aed3SPierre Pronchery                                                drbg->max_noncelen)) {
419b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
420b077aed3SPierre Pronchery                 goto end;
421b077aed3SPierre Pronchery             }
422b077aed3SPierre Pronchery #ifndef PROV_RAND_GET_RANDOM_NONCE
423b077aed3SPierre Pronchery         } else if (drbg->parent != NULL) {
424b077aed3SPierre Pronchery #endif
425b077aed3SPierre Pronchery             /*
426b077aed3SPierre Pronchery              * NIST SP800-90Ar1 section 9.1 says you can combine getting
427b077aed3SPierre Pronchery              * the entropy and nonce in 1 call by increasing the entropy
428b077aed3SPierre Pronchery              * with 50% and increasing the minimum length to accommodate
429b077aed3SPierre Pronchery              * the length of the nonce. We do this in case a nonce is
430b077aed3SPierre Pronchery              * required and there is no parental nonce capability.
431b077aed3SPierre Pronchery              */
432b077aed3SPierre Pronchery             min_entropy += drbg->strength / 2;
433b077aed3SPierre Pronchery             min_entropylen += drbg->min_noncelen;
434b077aed3SPierre Pronchery             max_entropylen += drbg->max_noncelen;
435b077aed3SPierre Pronchery         }
436b077aed3SPierre Pronchery #ifndef PROV_RAND_GET_RANDOM_NONCE
437b077aed3SPierre Pronchery         else { /* parent == NULL */
438b077aed3SPierre Pronchery             noncelen = prov_drbg_get_nonce(drbg, &nonce, drbg->min_noncelen,
439b077aed3SPierre Pronchery                                            drbg->max_noncelen);
440b077aed3SPierre Pronchery             if (noncelen < drbg->min_noncelen
441b077aed3SPierre Pronchery                     || noncelen > drbg->max_noncelen) {
442b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
443b077aed3SPierre Pronchery                 goto end;
444b077aed3SPierre Pronchery             }
445b077aed3SPierre Pronchery         }
446b077aed3SPierre Pronchery #endif
447b077aed3SPierre Pronchery     }
448b077aed3SPierre Pronchery 
449b077aed3SPierre Pronchery     drbg->reseed_next_counter = tsan_load(&drbg->reseed_counter);
450b077aed3SPierre Pronchery     if (drbg->reseed_next_counter) {
451b077aed3SPierre Pronchery         drbg->reseed_next_counter++;
452b077aed3SPierre Pronchery         if (!drbg->reseed_next_counter)
453b077aed3SPierre Pronchery             drbg->reseed_next_counter = 1;
454b077aed3SPierre Pronchery     }
455b077aed3SPierre Pronchery 
456b077aed3SPierre Pronchery     entropylen = get_entropy(drbg, &entropy, min_entropy,
457b077aed3SPierre Pronchery                              min_entropylen, max_entropylen,
458b077aed3SPierre Pronchery                              prediction_resistance);
459b077aed3SPierre Pronchery     if (entropylen < min_entropylen
460b077aed3SPierre Pronchery             || entropylen > max_entropylen) {
461b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY);
462b077aed3SPierre Pronchery         goto end;
463b077aed3SPierre Pronchery     }
464b077aed3SPierre Pronchery 
465b077aed3SPierre Pronchery     if (!drbg->instantiate(drbg, entropy, entropylen, nonce, noncelen,
466b077aed3SPierre Pronchery                            pers, perslen)) {
467b077aed3SPierre Pronchery         cleanup_entropy(drbg, entropy, entropylen);
468b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_INSTANTIATING_DRBG);
469b077aed3SPierre Pronchery         goto end;
470b077aed3SPierre Pronchery     }
471b077aed3SPierre Pronchery     cleanup_entropy(drbg, entropy, entropylen);
472b077aed3SPierre Pronchery 
473b077aed3SPierre Pronchery     drbg->state = EVP_RAND_STATE_READY;
474b077aed3SPierre Pronchery     drbg->generate_counter = 1;
475b077aed3SPierre Pronchery     drbg->reseed_time = time(NULL);
476b077aed3SPierre Pronchery     tsan_store(&drbg->reseed_counter, drbg->reseed_next_counter);
477b077aed3SPierre Pronchery 
478b077aed3SPierre Pronchery  end:
479b077aed3SPierre Pronchery     if (nonce != NULL)
480b077aed3SPierre Pronchery         ossl_prov_cleanup_nonce(drbg->provctx, nonce, noncelen);
481b077aed3SPierre Pronchery     if (drbg->state == EVP_RAND_STATE_READY)
482b077aed3SPierre Pronchery         return 1;
483b077aed3SPierre Pronchery     return 0;
484b077aed3SPierre Pronchery }
485b077aed3SPierre Pronchery 
486b077aed3SPierre Pronchery /*
487b077aed3SPierre Pronchery  * Uninstantiate |drbg|. Must be instantiated before it can be used.
488b077aed3SPierre Pronchery  *
489b077aed3SPierre Pronchery  * Requires that drbg->lock is already locked for write, if non-null.
490b077aed3SPierre Pronchery  *
491b077aed3SPierre Pronchery  * Returns 1 on success, 0 on failure.
492b077aed3SPierre Pronchery  */
493b077aed3SPierre Pronchery int ossl_prov_drbg_uninstantiate(PROV_DRBG *drbg)
494b077aed3SPierre Pronchery {
495b077aed3SPierre Pronchery     drbg->state = EVP_RAND_STATE_UNINITIALISED;
496b077aed3SPierre Pronchery     return 1;
497b077aed3SPierre Pronchery }
498b077aed3SPierre Pronchery 
499b077aed3SPierre Pronchery /*
500b077aed3SPierre Pronchery  * Reseed |drbg|, mixing in the specified data
501b077aed3SPierre Pronchery  *
502b077aed3SPierre Pronchery  * Requires that drbg->lock is already locked for write, if non-null.
503b077aed3SPierre Pronchery  *
504b077aed3SPierre Pronchery  * Returns 1 on success, 0 on failure.
505b077aed3SPierre Pronchery  */
506b077aed3SPierre Pronchery int ossl_prov_drbg_reseed(PROV_DRBG *drbg, int prediction_resistance,
507b077aed3SPierre Pronchery                           const unsigned char *ent, size_t ent_len,
508b077aed3SPierre Pronchery                           const unsigned char *adin, size_t adinlen)
509b077aed3SPierre Pronchery {
510b077aed3SPierre Pronchery     unsigned char *entropy = NULL;
511b077aed3SPierre Pronchery     size_t entropylen = 0;
512b077aed3SPierre Pronchery 
513b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
514b077aed3SPierre Pronchery         return 0;
515b077aed3SPierre Pronchery 
516b077aed3SPierre Pronchery     if (drbg->state != EVP_RAND_STATE_READY) {
517b077aed3SPierre Pronchery         /* try to recover from previous errors */
518b077aed3SPierre Pronchery         rand_drbg_restart(drbg);
519b077aed3SPierre Pronchery 
520b077aed3SPierre Pronchery         if (drbg->state == EVP_RAND_STATE_ERROR) {
521b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);
522b077aed3SPierre Pronchery             return 0;
523b077aed3SPierre Pronchery         }
524b077aed3SPierre Pronchery         if (drbg->state == EVP_RAND_STATE_UNINITIALISED) {
525b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED);
526b077aed3SPierre Pronchery             return 0;
527b077aed3SPierre Pronchery         }
528b077aed3SPierre Pronchery     }
529b077aed3SPierre Pronchery 
530b077aed3SPierre Pronchery     if (ent != NULL) {
531b077aed3SPierre Pronchery         if (ent_len < drbg->min_entropylen) {
532b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RAND, RAND_R_ENTROPY_OUT_OF_RANGE);
533b077aed3SPierre Pronchery             drbg->state = EVP_RAND_STATE_ERROR;
534b077aed3SPierre Pronchery             return 0;
535b077aed3SPierre Pronchery         }
536b077aed3SPierre Pronchery         if (ent_len > drbg->max_entropylen) {
537b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RAND, RAND_R_ENTROPY_INPUT_TOO_LONG);
538b077aed3SPierre Pronchery             drbg->state = EVP_RAND_STATE_ERROR;
539b077aed3SPierre Pronchery             return 0;
540b077aed3SPierre Pronchery         }
541b077aed3SPierre Pronchery     }
542b077aed3SPierre Pronchery 
543b077aed3SPierre Pronchery     if (adin == NULL) {
544b077aed3SPierre Pronchery         adinlen = 0;
545b077aed3SPierre Pronchery     } else if (adinlen > drbg->max_adinlen) {
546b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG);
547b077aed3SPierre Pronchery         return 0;
548b077aed3SPierre Pronchery     }
549b077aed3SPierre Pronchery 
550b077aed3SPierre Pronchery     drbg->state = EVP_RAND_STATE_ERROR;
551b077aed3SPierre Pronchery 
552b077aed3SPierre Pronchery     drbg->reseed_next_counter = tsan_load(&drbg->reseed_counter);
553b077aed3SPierre Pronchery     if (drbg->reseed_next_counter) {
554b077aed3SPierre Pronchery         drbg->reseed_next_counter++;
555b077aed3SPierre Pronchery         if (!drbg->reseed_next_counter)
556b077aed3SPierre Pronchery             drbg->reseed_next_counter = 1;
557b077aed3SPierre Pronchery     }
558b077aed3SPierre Pronchery 
559b077aed3SPierre Pronchery     if (ent != NULL) {
560b077aed3SPierre Pronchery #ifdef FIPS_MODULE
561b077aed3SPierre Pronchery         /*
562b077aed3SPierre Pronchery          * NIST SP-800-90A mandates that entropy *shall not* be provided
563b077aed3SPierre Pronchery          * by the consuming application. Instead the data is added as additional
564b077aed3SPierre Pronchery          * input.
565b077aed3SPierre Pronchery          *
566b077aed3SPierre Pronchery          * (NIST SP-800-90Ar1, Sections 9.1 and 9.2)
567b077aed3SPierre Pronchery          */
568b077aed3SPierre Pronchery         if (!drbg->reseed(drbg, NULL, 0, ent, ent_len)) {
569b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED);
570b077aed3SPierre Pronchery             return 0;
571b077aed3SPierre Pronchery         }
572b077aed3SPierre Pronchery #else
573b077aed3SPierre Pronchery         if (!drbg->reseed(drbg, ent, ent_len, adin, adinlen)) {
574b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED);
575b077aed3SPierre Pronchery             return 0;
576b077aed3SPierre Pronchery         }
577b077aed3SPierre Pronchery         /* There isn't much point adding the same additional input twice */
578b077aed3SPierre Pronchery         adin = NULL;
579b077aed3SPierre Pronchery         adinlen = 0;
580b077aed3SPierre Pronchery #endif
581b077aed3SPierre Pronchery     }
582b077aed3SPierre Pronchery 
583b077aed3SPierre Pronchery     /* Reseed using our sources in addition */
584b077aed3SPierre Pronchery     entropylen = get_entropy(drbg, &entropy, drbg->strength,
585b077aed3SPierre Pronchery                              drbg->min_entropylen, drbg->max_entropylen,
586b077aed3SPierre Pronchery                              prediction_resistance);
587b077aed3SPierre Pronchery     if (entropylen < drbg->min_entropylen
588b077aed3SPierre Pronchery             || entropylen > drbg->max_entropylen) {
589b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY);
590b077aed3SPierre Pronchery         goto end;
591b077aed3SPierre Pronchery     }
592b077aed3SPierre Pronchery 
593b077aed3SPierre Pronchery     if (!drbg->reseed(drbg, entropy, entropylen, adin, adinlen))
594b077aed3SPierre Pronchery         goto end;
595b077aed3SPierre Pronchery 
596b077aed3SPierre Pronchery     drbg->state = EVP_RAND_STATE_READY;
597b077aed3SPierre Pronchery     drbg->generate_counter = 1;
598b077aed3SPierre Pronchery     drbg->reseed_time = time(NULL);
599b077aed3SPierre Pronchery     tsan_store(&drbg->reseed_counter, drbg->reseed_next_counter);
600b077aed3SPierre Pronchery     if (drbg->parent != NULL)
601b077aed3SPierre Pronchery         drbg->parent_reseed_counter = get_parent_reseed_count(drbg);
602b077aed3SPierre Pronchery 
603b077aed3SPierre Pronchery  end:
604b077aed3SPierre Pronchery     cleanup_entropy(drbg, entropy, entropylen);
605b077aed3SPierre Pronchery     if (drbg->state == EVP_RAND_STATE_READY)
606b077aed3SPierre Pronchery         return 1;
607b077aed3SPierre Pronchery     return 0;
608b077aed3SPierre Pronchery }
609b077aed3SPierre Pronchery 
610b077aed3SPierre Pronchery /*
611b077aed3SPierre Pronchery  * Generate |outlen| bytes into the buffer at |out|.  Reseed if we need
612b077aed3SPierre Pronchery  * to or if |prediction_resistance| is set.  Additional input can be
613b077aed3SPierre Pronchery  * sent in |adin| and |adinlen|.
614b077aed3SPierre Pronchery  *
615b077aed3SPierre Pronchery  * Requires that drbg->lock is already locked for write, if non-null.
616b077aed3SPierre Pronchery  *
617b077aed3SPierre Pronchery  * Returns 1 on success, 0 on failure.
618b077aed3SPierre Pronchery  *
619b077aed3SPierre Pronchery  */
620b077aed3SPierre Pronchery int ossl_prov_drbg_generate(PROV_DRBG *drbg, unsigned char *out, size_t outlen,
621b077aed3SPierre Pronchery                             unsigned int strength, int prediction_resistance,
622b077aed3SPierre Pronchery                             const unsigned char *adin, size_t adinlen)
623b077aed3SPierre Pronchery {
624b077aed3SPierre Pronchery     int fork_id;
625b077aed3SPierre Pronchery     int reseed_required = 0;
626b077aed3SPierre Pronchery 
627b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
628b077aed3SPierre Pronchery         return 0;
629b077aed3SPierre Pronchery 
630b077aed3SPierre Pronchery     if (drbg->state != EVP_RAND_STATE_READY) {
631b077aed3SPierre Pronchery         /* try to recover from previous errors */
632b077aed3SPierre Pronchery         rand_drbg_restart(drbg);
633b077aed3SPierre Pronchery 
634b077aed3SPierre Pronchery         if (drbg->state == EVP_RAND_STATE_ERROR) {
635b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);
636b077aed3SPierre Pronchery             return 0;
637b077aed3SPierre Pronchery         }
638b077aed3SPierre Pronchery         if (drbg->state == EVP_RAND_STATE_UNINITIALISED) {
639b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED);
640b077aed3SPierre Pronchery             return 0;
641b077aed3SPierre Pronchery         }
642b077aed3SPierre Pronchery     }
643b077aed3SPierre Pronchery     if (strength > drbg->strength) {
644b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_INSUFFICIENT_DRBG_STRENGTH);
645b077aed3SPierre Pronchery         return 0;
646b077aed3SPierre Pronchery     }
647b077aed3SPierre Pronchery 
648b077aed3SPierre Pronchery     if (outlen > drbg->max_request) {
649b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_REQUEST_TOO_LARGE_FOR_DRBG);
650b077aed3SPierre Pronchery         return 0;
651b077aed3SPierre Pronchery     }
652b077aed3SPierre Pronchery     if (adinlen > drbg->max_adinlen) {
653b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG);
654b077aed3SPierre Pronchery         return 0;
655b077aed3SPierre Pronchery     }
656b077aed3SPierre Pronchery 
657b077aed3SPierre Pronchery     fork_id = openssl_get_fork_id();
658b077aed3SPierre Pronchery 
659b077aed3SPierre Pronchery     if (drbg->fork_id != fork_id) {
660b077aed3SPierre Pronchery         drbg->fork_id = fork_id;
661b077aed3SPierre Pronchery         reseed_required = 1;
662b077aed3SPierre Pronchery     }
663b077aed3SPierre Pronchery 
664b077aed3SPierre Pronchery     if (drbg->reseed_interval > 0) {
665b077aed3SPierre Pronchery         if (drbg->generate_counter >= drbg->reseed_interval)
666b077aed3SPierre Pronchery             reseed_required = 1;
667b077aed3SPierre Pronchery     }
668b077aed3SPierre Pronchery     if (drbg->reseed_time_interval > 0) {
669b077aed3SPierre Pronchery         time_t now = time(NULL);
670b077aed3SPierre Pronchery         if (now < drbg->reseed_time
671b077aed3SPierre Pronchery             || now - drbg->reseed_time >= drbg->reseed_time_interval)
672b077aed3SPierre Pronchery             reseed_required = 1;
673b077aed3SPierre Pronchery     }
674b077aed3SPierre Pronchery     if (drbg->parent != NULL
675b077aed3SPierre Pronchery             && get_parent_reseed_count(drbg) != drbg->parent_reseed_counter)
676b077aed3SPierre Pronchery         reseed_required = 1;
677b077aed3SPierre Pronchery 
678b077aed3SPierre Pronchery     if (reseed_required || prediction_resistance) {
679b077aed3SPierre Pronchery         if (!ossl_prov_drbg_reseed(drbg, prediction_resistance, NULL, 0,
680b077aed3SPierre Pronchery                                    adin, adinlen)) {
681b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_RESEED_ERROR);
682b077aed3SPierre Pronchery             return 0;
683b077aed3SPierre Pronchery         }
684b077aed3SPierre Pronchery         adin = NULL;
685b077aed3SPierre Pronchery         adinlen = 0;
686b077aed3SPierre Pronchery     }
687b077aed3SPierre Pronchery 
688b077aed3SPierre Pronchery     if (!drbg->generate(drbg, out, outlen, adin, adinlen)) {
689b077aed3SPierre Pronchery         drbg->state = EVP_RAND_STATE_ERROR;
690b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_GENERATE_ERROR);
691b077aed3SPierre Pronchery         return 0;
692b077aed3SPierre Pronchery     }
693b077aed3SPierre Pronchery 
694b077aed3SPierre Pronchery     drbg->generate_counter++;
695b077aed3SPierre Pronchery 
696b077aed3SPierre Pronchery     return 1;
697b077aed3SPierre Pronchery }
698b077aed3SPierre Pronchery 
699b077aed3SPierre Pronchery /*
700b077aed3SPierre Pronchery  * Restart |drbg|, using the specified entropy or additional input
701b077aed3SPierre Pronchery  *
702b077aed3SPierre Pronchery  * Tries its best to get the drbg instantiated by all means,
703b077aed3SPierre Pronchery  * regardless of its current state.
704b077aed3SPierre Pronchery  *
705b077aed3SPierre Pronchery  * Optionally, a |buffer| of |len| random bytes can be passed,
706b077aed3SPierre Pronchery  * which is assumed to contain at least |entropy| bits of entropy.
707b077aed3SPierre Pronchery  *
708b077aed3SPierre Pronchery  * If |entropy| > 0, the buffer content is used as entropy input.
709b077aed3SPierre Pronchery  *
710b077aed3SPierre Pronchery  * If |entropy| == 0, the buffer content is used as additional input
711b077aed3SPierre Pronchery  *
712b077aed3SPierre Pronchery  * Returns 1 on success, 0 on failure.
713b077aed3SPierre Pronchery  *
714b077aed3SPierre Pronchery  * This function is used internally only.
715b077aed3SPierre Pronchery  */
716b077aed3SPierre Pronchery static int rand_drbg_restart(PROV_DRBG *drbg)
717b077aed3SPierre Pronchery {
718b077aed3SPierre Pronchery     /* repair error state */
719b077aed3SPierre Pronchery     if (drbg->state == EVP_RAND_STATE_ERROR)
720b077aed3SPierre Pronchery         drbg->uninstantiate(drbg);
721b077aed3SPierre Pronchery 
722b077aed3SPierre Pronchery     /* repair uninitialized state */
723b077aed3SPierre Pronchery     if (drbg->state == EVP_RAND_STATE_UNINITIALISED)
724b077aed3SPierre Pronchery         /* reinstantiate drbg */
725b077aed3SPierre Pronchery         ossl_prov_drbg_instantiate(drbg, drbg->strength, 0, NULL, 0);
726b077aed3SPierre Pronchery 
727b077aed3SPierre Pronchery     return drbg->state == EVP_RAND_STATE_READY;
728b077aed3SPierre Pronchery }
729b077aed3SPierre Pronchery 
730b077aed3SPierre Pronchery /* Provider support from here down */
731b077aed3SPierre Pronchery static const OSSL_DISPATCH *find_call(const OSSL_DISPATCH *dispatch,
732b077aed3SPierre Pronchery                                       int function)
733b077aed3SPierre Pronchery {
734b077aed3SPierre Pronchery     if (dispatch != NULL)
735b077aed3SPierre Pronchery         while (dispatch->function_id != 0) {
736b077aed3SPierre Pronchery             if (dispatch->function_id == function)
737b077aed3SPierre Pronchery                 return dispatch;
738b077aed3SPierre Pronchery             dispatch++;
739b077aed3SPierre Pronchery         }
740b077aed3SPierre Pronchery     return NULL;
741b077aed3SPierre Pronchery }
742b077aed3SPierre Pronchery 
743b077aed3SPierre Pronchery int ossl_drbg_enable_locking(void *vctx)
744b077aed3SPierre Pronchery {
745b077aed3SPierre Pronchery     PROV_DRBG *drbg = vctx;
746b077aed3SPierre Pronchery 
747b077aed3SPierre Pronchery     if (drbg != NULL && drbg->lock == NULL) {
748b077aed3SPierre Pronchery         if (drbg->parent_enable_locking != NULL)
749b077aed3SPierre Pronchery             if (!drbg->parent_enable_locking(drbg->parent)) {
750b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED);
751b077aed3SPierre Pronchery                 return 0;
752b077aed3SPierre Pronchery             }
753b077aed3SPierre Pronchery         drbg->lock = CRYPTO_THREAD_lock_new();
754b077aed3SPierre Pronchery         if (drbg->lock == NULL) {
755b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_CREATE_LOCK);
756b077aed3SPierre Pronchery             return 0;
757b077aed3SPierre Pronchery         }
758b077aed3SPierre Pronchery     }
759b077aed3SPierre Pronchery     return 1;
760b077aed3SPierre Pronchery }
761b077aed3SPierre Pronchery 
762b077aed3SPierre Pronchery /*
763b077aed3SPierre Pronchery  * Allocate memory and initialize a new DRBG. The DRBG is allocated on
764b077aed3SPierre Pronchery  * the secure heap if |secure| is nonzero and the secure heap is enabled.
765b077aed3SPierre Pronchery  * The |parent|, if not NULL, will be used as random source for reseeding.
766b077aed3SPierre Pronchery  * This also requires the parent's provider context and the parent's lock.
767b077aed3SPierre Pronchery  *
768b077aed3SPierre Pronchery  * Returns a pointer to the new DRBG instance on success, NULL on failure.
769b077aed3SPierre Pronchery  */
770b077aed3SPierre Pronchery PROV_DRBG *ossl_rand_drbg_new
771b077aed3SPierre Pronchery     (void *provctx, void *parent, const OSSL_DISPATCH *p_dispatch,
772b077aed3SPierre Pronchery      int (*dnew)(PROV_DRBG *ctx),
77344096ebdSEnji Cooper      void (*dfree)(void *vctx),
774b077aed3SPierre Pronchery      int (*instantiate)(PROV_DRBG *drbg,
775b077aed3SPierre Pronchery                         const unsigned char *entropy, size_t entropylen,
776b077aed3SPierre Pronchery                         const unsigned char *nonce, size_t noncelen,
777b077aed3SPierre Pronchery                         const unsigned char *pers, size_t perslen),
778b077aed3SPierre Pronchery      int (*uninstantiate)(PROV_DRBG *ctx),
779b077aed3SPierre Pronchery      int (*reseed)(PROV_DRBG *drbg, const unsigned char *ent, size_t ent_len,
780b077aed3SPierre Pronchery                    const unsigned char *adin, size_t adin_len),
781b077aed3SPierre Pronchery      int (*generate)(PROV_DRBG *, unsigned char *out, size_t outlen,
782b077aed3SPierre Pronchery                      const unsigned char *adin, size_t adin_len))
783b077aed3SPierre Pronchery {
784b077aed3SPierre Pronchery     PROV_DRBG *drbg;
785b077aed3SPierre Pronchery     unsigned int p_str;
786b077aed3SPierre Pronchery     const OSSL_DISPATCH *pfunc;
787b077aed3SPierre Pronchery 
788b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
789b077aed3SPierre Pronchery         return NULL;
790b077aed3SPierre Pronchery 
791b077aed3SPierre Pronchery     drbg = OPENSSL_zalloc(sizeof(*drbg));
792b077aed3SPierre Pronchery     if (drbg == NULL) {
793b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
794b077aed3SPierre Pronchery         return NULL;
795b077aed3SPierre Pronchery     }
796b077aed3SPierre Pronchery 
797b077aed3SPierre Pronchery     drbg->provctx = provctx;
798b077aed3SPierre Pronchery     drbg->instantiate = instantiate;
799b077aed3SPierre Pronchery     drbg->uninstantiate = uninstantiate;
800b077aed3SPierre Pronchery     drbg->reseed = reseed;
801b077aed3SPierre Pronchery     drbg->generate = generate;
802b077aed3SPierre Pronchery     drbg->fork_id = openssl_get_fork_id();
803b077aed3SPierre Pronchery 
804b077aed3SPierre Pronchery     /* Extract parent's functions */
805b077aed3SPierre Pronchery     drbg->parent = parent;
806b077aed3SPierre Pronchery     if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_ENABLE_LOCKING)) != NULL)
807b077aed3SPierre Pronchery         drbg->parent_enable_locking = OSSL_FUNC_rand_enable_locking(pfunc);
808b077aed3SPierre Pronchery     if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_LOCK)) != NULL)
809b077aed3SPierre Pronchery         drbg->parent_lock = OSSL_FUNC_rand_lock(pfunc);
810b077aed3SPierre Pronchery     if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_UNLOCK)) != NULL)
811b077aed3SPierre Pronchery         drbg->parent_unlock = OSSL_FUNC_rand_unlock(pfunc);
812b077aed3SPierre Pronchery     if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_CTX_PARAMS)) != NULL)
813b077aed3SPierre Pronchery         drbg->parent_get_ctx_params = OSSL_FUNC_rand_get_ctx_params(pfunc);
814b077aed3SPierre Pronchery     if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_NONCE)) != NULL)
815b077aed3SPierre Pronchery         drbg->parent_nonce = OSSL_FUNC_rand_nonce(pfunc);
816b077aed3SPierre Pronchery     if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_SEED)) != NULL)
817b077aed3SPierre Pronchery         drbg->parent_get_seed = OSSL_FUNC_rand_get_seed(pfunc);
818b077aed3SPierre Pronchery     if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_CLEAR_SEED)) != NULL)
819b077aed3SPierre Pronchery         drbg->parent_clear_seed = OSSL_FUNC_rand_clear_seed(pfunc);
820b077aed3SPierre Pronchery 
821b077aed3SPierre Pronchery     /* Set some default maximums up */
822b077aed3SPierre Pronchery     drbg->max_entropylen = DRBG_MAX_LENGTH;
823b077aed3SPierre Pronchery     drbg->max_noncelen = DRBG_MAX_LENGTH;
824b077aed3SPierre Pronchery     drbg->max_perslen = DRBG_MAX_LENGTH;
825b077aed3SPierre Pronchery     drbg->max_adinlen = DRBG_MAX_LENGTH;
826b077aed3SPierre Pronchery     drbg->generate_counter = 1;
827b077aed3SPierre Pronchery     drbg->reseed_counter = 1;
828b077aed3SPierre Pronchery     drbg->reseed_interval = RESEED_INTERVAL;
829b077aed3SPierre Pronchery     drbg->reseed_time_interval = TIME_INTERVAL;
830b077aed3SPierre Pronchery 
831b077aed3SPierre Pronchery     if (!dnew(drbg))
832b077aed3SPierre Pronchery         goto err;
833b077aed3SPierre Pronchery 
834b077aed3SPierre Pronchery     if (parent != NULL) {
835b077aed3SPierre Pronchery         if (!get_parent_strength(drbg, &p_str))
836b077aed3SPierre Pronchery             goto err;
837b077aed3SPierre Pronchery         if (drbg->strength > p_str) {
838b077aed3SPierre Pronchery             /*
839b077aed3SPierre Pronchery              * We currently don't support the algorithm from NIST SP 800-90C
840b077aed3SPierre Pronchery              * 10.1.2 to use a weaker DRBG as source
841b077aed3SPierre Pronchery              */
842b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK);
843b077aed3SPierre Pronchery             goto err;
844b077aed3SPierre Pronchery         }
845b077aed3SPierre Pronchery     }
846b077aed3SPierre Pronchery #ifdef TSAN_REQUIRES_LOCKING
847b077aed3SPierre Pronchery     if (!ossl_drbg_enable_locking(drbg))
848b077aed3SPierre Pronchery         goto err;
849b077aed3SPierre Pronchery #endif
850b077aed3SPierre Pronchery     return drbg;
851b077aed3SPierre Pronchery 
852b077aed3SPierre Pronchery  err:
85344096ebdSEnji Cooper     dfree(drbg);
854b077aed3SPierre Pronchery     return NULL;
855b077aed3SPierre Pronchery }
856b077aed3SPierre Pronchery 
857b077aed3SPierre Pronchery void ossl_rand_drbg_free(PROV_DRBG *drbg)
858b077aed3SPierre Pronchery {
859b077aed3SPierre Pronchery     if (drbg == NULL)
860b077aed3SPierre Pronchery         return;
861b077aed3SPierre Pronchery 
862b077aed3SPierre Pronchery     CRYPTO_THREAD_lock_free(drbg->lock);
863b077aed3SPierre Pronchery     OPENSSL_free(drbg);
864b077aed3SPierre Pronchery }
865b077aed3SPierre Pronchery 
866b077aed3SPierre Pronchery int ossl_drbg_get_ctx_params(PROV_DRBG *drbg, OSSL_PARAM params[])
867b077aed3SPierre Pronchery {
868b077aed3SPierre Pronchery     OSSL_PARAM *p;
869b077aed3SPierre Pronchery 
870b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);
871b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_int(p, drbg->state))
872b077aed3SPierre Pronchery         return 0;
873b077aed3SPierre Pronchery 
874b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);
875b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_int(p, drbg->strength))
876b077aed3SPierre Pronchery         return 0;
877b077aed3SPierre Pronchery 
878b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
879b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_request))
880b077aed3SPierre Pronchery         return 0;
881b077aed3SPierre Pronchery 
882b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MIN_ENTROPYLEN);
883b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->min_entropylen))
884b077aed3SPierre Pronchery         return 0;
885b077aed3SPierre Pronchery 
886b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_ENTROPYLEN);
887b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_entropylen))
888b077aed3SPierre Pronchery         return 0;
889b077aed3SPierre Pronchery 
890b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MIN_NONCELEN);
891b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->min_noncelen))
892b077aed3SPierre Pronchery         return 0;
893b077aed3SPierre Pronchery 
894b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_NONCELEN);
895b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_noncelen))
896b077aed3SPierre Pronchery         return 0;
897b077aed3SPierre Pronchery 
898b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_PERSLEN);
899b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_perslen))
900b077aed3SPierre Pronchery         return 0;
901b077aed3SPierre Pronchery 
902b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_ADINLEN);
903b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_adinlen))
904b077aed3SPierre Pronchery         return 0;
905b077aed3SPierre Pronchery 
906b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_REQUESTS);
907b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_uint(p, drbg->reseed_interval))
908b077aed3SPierre Pronchery         return 0;
909b077aed3SPierre Pronchery 
910b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_TIME);
911b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time))
912b077aed3SPierre Pronchery         return 0;
913b077aed3SPierre Pronchery 
914b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL);
915b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time_interval))
916b077aed3SPierre Pronchery         return 0;
917b077aed3SPierre Pronchery 
918b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_COUNTER);
919b077aed3SPierre Pronchery     if (p != NULL
920b077aed3SPierre Pronchery             && !OSSL_PARAM_set_uint(p, tsan_load(&drbg->reseed_counter)))
921b077aed3SPierre Pronchery         return 0;
922b077aed3SPierre Pronchery     return 1;
923b077aed3SPierre Pronchery }
924b077aed3SPierre Pronchery 
925b077aed3SPierre Pronchery int ossl_drbg_set_ctx_params(PROV_DRBG *drbg, const OSSL_PARAM params[])
926b077aed3SPierre Pronchery {
927b077aed3SPierre Pronchery     const OSSL_PARAM *p;
928b077aed3SPierre Pronchery 
929b077aed3SPierre Pronchery     if (params == NULL)
930b077aed3SPierre Pronchery         return 1;
931b077aed3SPierre Pronchery 
932b077aed3SPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RESEED_REQUESTS);
933b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_get_uint(p, &drbg->reseed_interval))
934b077aed3SPierre Pronchery         return 0;
935b077aed3SPierre Pronchery 
936b077aed3SPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL);
937b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_get_time_t(p, &drbg->reseed_time_interval))
938b077aed3SPierre Pronchery         return 0;
939b077aed3SPierre Pronchery     return 1;
940b077aed3SPierre Pronchery }
941