2 * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 * RAND_DRBG_set is deprecated for public use, but still ok for
14 #include "internal/deprecated.h"
17 #include <openssl/crypto.h>
18 #include <openssl/err.h>
19 #include <openssl/rand.h>
20 #include <openssl/core_names.h>
21 #include "rand_local.h"
22 #include "internal/thread_once.h"
23 #include "crypto/rand.h"
24 #include "crypto/cryptlib.h"
27 * Support framework for NIST SP 800-90A DRBG
29 * See manual page RAND_DRBG(7) for a general overview.
31 * The OpenSSL model is to have new and free functions, and that new
32 * does all initialization. That is not the NIST model, which has
33 * instantiation and un-instantiate, and re-use within a new/free
34 * lifecycle. (No doubt this comes from the desire to support hardware
35 * DRBG, where allocation of resources on something like an HSM is
36 * a much bigger deal than just re-setting an allocated resource.)
40 typedef struct drbg_global_st {
42 * The three shared DRBG instances
44 * There are three shared DRBG instances: <master>, <public>, and <private>.
51 * Not used directly by the application, only for reseeding the two other
52 * DRBGs. It reseeds itself by pulling either randomness from os entropy
53 * sources or by consuming randomness which was added by RAND_add().
55 * The <master> DRBG is a global instance which is accessed concurrently by
56 * all threads. The necessary locking is managed automatically by its child
57 * DRBG instances during reseeding.
59 RAND_DRBG *master_drbg;
63 * Used by default for generating random bytes using RAND_bytes().
65 * The <public> DRBG is thread-local, i.e., there is one instance per
68 CRYPTO_THREAD_LOCAL public_drbg;
72 * Used by default for generating private keys using RAND_priv_bytes()
74 * The <private> DRBG is thread-local, i.e., there is one instance per
77 CRYPTO_THREAD_LOCAL private_drbg;
80 #define RAND_DRBG_TYPE_FLAGS ( \
81 RAND_DRBG_FLAG_MASTER | RAND_DRBG_FLAG_PUBLIC | RAND_DRBG_FLAG_PRIVATE )
83 #define RAND_DRBG_TYPE_MASTER 0
84 #define RAND_DRBG_TYPE_PUBLIC 1
85 #define RAND_DRBG_TYPE_PRIVATE 2
88 static int rand_drbg_type[3] = {
89 RAND_DRBG_TYPE, /* Master */
90 RAND_DRBG_TYPE, /* Public */
91 RAND_DRBG_TYPE /* Private */
93 static unsigned int rand_drbg_flags[3] = {
94 RAND_DRBG_FLAGS | RAND_DRBG_FLAG_MASTER, /* Master */
95 RAND_DRBG_FLAGS | RAND_DRBG_FLAG_PUBLIC, /* Public */
96 RAND_DRBG_FLAGS | RAND_DRBG_FLAG_PRIVATE /* Private */
99 static unsigned int master_reseed_interval = MASTER_RESEED_INTERVAL;
100 static unsigned int slave_reseed_interval = SLAVE_RESEED_INTERVAL;
102 static time_t master_reseed_time_interval = MASTER_RESEED_TIME_INTERVAL;
103 static time_t slave_reseed_time_interval = SLAVE_RESEED_TIME_INTERVAL;
105 /* A logical OR of all used DRBG flag bits (currently there is only one) */
106 static const unsigned int rand_drbg_used_flags =
107 RAND_DRBG_FLAG_CTR_NO_DF | RAND_DRBG_FLAG_HMAC | RAND_DRBG_TYPE_FLAGS;
110 static RAND_DRBG *drbg_setup(OPENSSL_CTX *ctx, RAND_DRBG *parent, int drbg_type);
112 static int get_drbg_params(int type, unsigned int flags, const char **name,
113 OSSL_PARAM params[3])
115 OSSL_PARAM *p = params;
124 *name = "CTR-DRBG"; \
125 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER, v, 0)
127 case NID_aes_128_ctr:
130 case NID_aes_192_ctr:
133 case NID_aes_256_ctr:
138 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST, v, 0); \
139 if ((flags & RAND_DRBG_FLAG_HMAC) == 0) { \
140 *name = "HASH-DRBG"; \
142 *name = "HMAC-DRBG"; \
143 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_MAC, \
180 *p = OSSL_PARAM_construct_end();
185 * Initialize the OPENSSL_CTX global DRBGs on first use.
186 * Returns the allocated global data on success or NULL on failure.
188 static void *drbg_ossl_ctx_new(OPENSSL_CTX *libctx)
190 DRBG_GLOBAL *dgbl = OPENSSL_zalloc(sizeof(*dgbl));
197 * We need to ensure that base libcrypto thread handling has been
200 OPENSSL_init_crypto(0, NULL);
203 dgbl->lock = CRYPTO_THREAD_lock_new();
204 if (dgbl->lock == NULL)
207 if (!CRYPTO_THREAD_init_local(&dgbl->private_drbg, NULL))
210 if (!CRYPTO_THREAD_init_local(&dgbl->public_drbg, NULL))
216 CRYPTO_THREAD_cleanup_local(&dgbl->private_drbg);
218 CRYPTO_THREAD_lock_free(dgbl->lock);
224 static void drbg_ossl_ctx_free(void *vdgbl)
226 DRBG_GLOBAL *dgbl = vdgbl;
231 CRYPTO_THREAD_lock_free(dgbl->lock);
232 RAND_DRBG_free(dgbl->master_drbg);
233 CRYPTO_THREAD_cleanup_local(&dgbl->private_drbg);
234 CRYPTO_THREAD_cleanup_local(&dgbl->public_drbg);
239 static const OPENSSL_CTX_METHOD drbg_ossl_ctx_method = {
244 static DRBG_GLOBAL *drbg_get_global(OPENSSL_CTX *libctx)
246 return openssl_ctx_get_data(libctx, OPENSSL_CTX_DRBG_INDEX,
247 &drbg_ossl_ctx_method);
251 * Set the |drbg|'s callback data pointer for the entropy and nonce callbacks
253 * The ownership of the context data remains with the caller,
254 * i.e., it is the caller's responsibility to keep it available as long
255 * as it is need by the callbacks and free it after use.
257 * Setting the callback data is allowed only if the drbg has not been
258 * initialized yet. Otherwise, the operation will fail.
260 * Returns 1 on success, 0 on failure.
262 int RAND_DRBG_set_callback_data(RAND_DRBG *drbg, void *data)
264 if (EVP_RAND_state(drbg->rand) != EVP_RAND_STATE_UNINITIALISED
265 || drbg->parent != NULL)
268 drbg->callback_data = data;
272 /* Retrieve the callback data pointer */
273 void *RAND_DRBG_get_callback_data(RAND_DRBG *drbg)
275 return drbg->callback_data;
279 * Set/initialize |drbg| to be of type |type|, with optional |flags|.
281 * If |type| and |flags| are zero, use the defaults
283 * Returns 1 on success, 0 on failure.
285 int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags)
287 OSSL_PARAM params[6], *p = params;
288 unsigned int reseed_interval;
289 time_t reseed_time_interval;
290 const char *name = NULL;
295 if (type == 0 && flags == 0) {
296 type = rand_drbg_type[RAND_DRBG_TYPE_MASTER];
297 flags = rand_drbg_flags[RAND_DRBG_TYPE_MASTER];
300 if (drbg->parent == NULL) {
301 reseed_interval = master_reseed_interval;
302 reseed_time_interval = master_reseed_time_interval;
304 reseed_interval = slave_reseed_interval;
305 reseed_time_interval = slave_reseed_time_interval;
307 *p++ = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS,
309 *p++ = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL,
310 &reseed_time_interval);
311 use_df = (flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0;
312 *p++ = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_USE_DF, &use_df);
314 if (!get_drbg_params(type, flags, &name, p)) {
315 RANDerr(0, RAND_R_UNSUPPORTED_DRBG_TYPE);
319 rand = EVP_RAND_fetch(drbg->libctx, name, NULL);
321 RANDerr(0, RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED);
325 EVP_RAND_CTX_free(drbg->rand);
331 pctx = drbg->parent != NULL ? drbg->parent->rand : NULL;
332 drbg->rand = EVP_RAND_CTX_new(rand, pctx);
334 if (drbg->rand == NULL) {
335 RANDerr(0, RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED);
339 if (!EVP_RAND_set_ctx_params(drbg->rand, params)) {
340 RANDerr(0, RAND_R_ERROR_INITIALISING_DRBG);
345 EVP_RAND_CTX_free(drbg->rand);
353 * Set/initialize default |type| and |flag| for new drbg instances.
355 * Returns 1 on success, 0 on failure.
357 int RAND_DRBG_set_defaults(int type, unsigned int flags)
361 OSSL_PARAM params[3];
363 if (!get_drbg_params(type, flags, &name, params)) {
364 RANDerr(RAND_F_RAND_DRBG_SET_DEFAULTS, RAND_R_UNSUPPORTED_DRBG_TYPE);
368 if ((flags & ~rand_drbg_used_flags) != 0) {
369 RANDerr(RAND_F_RAND_DRBG_SET_DEFAULTS, RAND_R_UNSUPPORTED_DRBG_FLAGS);
373 all = ((flags & RAND_DRBG_TYPE_FLAGS) == 0);
374 if (all || (flags & RAND_DRBG_FLAG_MASTER) != 0) {
375 rand_drbg_type[RAND_DRBG_TYPE_MASTER] = type;
376 rand_drbg_flags[RAND_DRBG_TYPE_MASTER] = flags | RAND_DRBG_FLAG_MASTER;
378 if (all || (flags & RAND_DRBG_FLAG_PUBLIC) != 0) {
379 rand_drbg_type[RAND_DRBG_TYPE_PUBLIC] = type;
380 rand_drbg_flags[RAND_DRBG_TYPE_PUBLIC] = flags | RAND_DRBG_FLAG_PUBLIC;
382 if (all || (flags & RAND_DRBG_FLAG_PRIVATE) != 0) {
383 rand_drbg_type[RAND_DRBG_TYPE_PRIVATE] = type;
384 rand_drbg_flags[RAND_DRBG_TYPE_PRIVATE] = flags | RAND_DRBG_FLAG_PRIVATE;
391 * Allocate memory and initialize a new DRBG.
392 * The |parent|, if not NULL, will be used as random source for reseeding.
394 * Returns a pointer to the new DRBG instance on success, NULL on failure.
396 static RAND_DRBG *rand_drbg_new(OPENSSL_CTX *ctx,
401 RAND_DRBG *drbg = OPENSSL_zalloc(sizeof(*drbg));
404 RANDerr(RAND_F_RAND_DRBG_NEW, ERR_R_MALLOC_FAILURE);
409 drbg->parent = parent;
411 if (RAND_DRBG_set(drbg, type, flags) == 0)
417 RAND_DRBG_free(drbg);
422 RAND_DRBG *RAND_DRBG_new_ex(OPENSSL_CTX *ctx, int type, unsigned int flags,
425 return rand_drbg_new(ctx, type, flags, parent);
428 RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent)
430 return RAND_DRBG_new_ex(NULL, type, flags, parent);
434 * Uninstantiate |drbg| and free all memory.
436 void RAND_DRBG_free(RAND_DRBG *drbg)
441 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RAND_DRBG, drbg, &drbg->ex_data);
442 EVP_RAND_CTX_free(drbg->rand);
447 * Instantiate |drbg|, after it has been initialized. Use |pers| and
448 * |perslen| as prediction-resistance input.
450 * Requires that drbg->lock is already locked for write, if non-null.
452 * Returns 1 on success, 0 on failure.
454 int RAND_DRBG_instantiate(RAND_DRBG *drbg,
455 const unsigned char *pers, size_t perslen)
457 return EVP_RAND_instantiate(drbg->rand, EVP_RAND_strength(drbg->rand), 0,
462 * Uninstantiate |drbg|. Must be instantiated before it can be used.
464 * Requires that drbg->lock is already locked for write, if non-null.
466 * Returns 1 on success, 0 on failure.
468 int RAND_DRBG_uninstantiate(RAND_DRBG *drbg)
470 int index = -1, type, flags;
472 if (!EVP_RAND_uninstantiate(drbg->rand))
475 /* The reset uses the default values for type and flags */
476 if (drbg->flags & RAND_DRBG_FLAG_MASTER)
477 index = RAND_DRBG_TYPE_MASTER;
478 else if (drbg->flags & RAND_DRBG_FLAG_PRIVATE)
479 index = RAND_DRBG_TYPE_PRIVATE;
480 else if (drbg->flags & RAND_DRBG_FLAG_PUBLIC)
481 index = RAND_DRBG_TYPE_PUBLIC;
484 flags = rand_drbg_flags[index];
485 type = rand_drbg_type[index];
490 return RAND_DRBG_set(drbg, type, flags);
494 * Reseed |drbg|, mixing in the specified data
496 * Requires that drbg->lock is already locked for write, if non-null.
498 * Returns 1 on success, 0 on failure.
500 int RAND_DRBG_reseed(RAND_DRBG *drbg,
501 const unsigned char *adin, size_t adinlen,
502 int prediction_resistance)
504 return EVP_RAND_reseed(drbg->rand, prediction_resistance, NULL, 0,
509 * Generate |outlen| bytes into the buffer at |out|. Reseed if we need
510 * to or if |prediction_resistance| is set. Additional input can be
511 * sent in |adin| and |adinlen|.
513 * Requires that drbg->lock is already locked for write, if non-null.
515 * Returns 1 on success, 0 on failure.
518 int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
519 int prediction_resistance,
520 const unsigned char *adin, size_t adinlen)
522 return EVP_RAND_generate(drbg->rand, out, outlen, 0,
523 prediction_resistance, adin, adinlen);
527 * Generates |outlen| random bytes and stores them in |out|. It will
528 * using the given |drbg| to generate the bytes.
530 * Requires that drbg->lock is already locked for write, if non-null.
532 * Returns 1 on success 0 on failure.
534 int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen)
536 return EVP_RAND_generate(drbg->rand, out, outlen, 0, 0, NULL, 0);
539 /* DRBG call back shims */
540 static int rand_drbg_get_entroy_cb(const OSSL_PARAM *params, OSSL_PARAM *out,
543 RAND_DRBG *drbg = (RAND_DRBG *)vdrbg;
544 int entropy = 0, prediction_resistance = 0;
545 size_t min_len = 0, max_len = 2048;
549 if (drbg->get_entropy == NULL)
552 p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_ENTROPY_REQUIRED);
553 if (p == NULL || !OSSL_PARAM_get_int(p, &entropy))
556 p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_PREDICTION_RESISTANCE);
557 if (p == NULL || !OSSL_PARAM_get_int(p, &prediction_resistance))
560 p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_MAX_LENGTH);
561 if (p == NULL || !OSSL_PARAM_get_size_t(p, &max_len))
564 p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_MIN_LENGTH);
565 if (p == NULL || !OSSL_PARAM_get_size_t(p, &min_len))
568 q = OSSL_PARAM_locate(out, OSSL_DRBG_PARAM_RANDOM_DATA);
569 if (q == NULL || q->data_type != OSSL_PARAM_OCTET_PTR || q->data == NULL)
572 q->return_size = drbg->get_entropy(drbg, (unsigned char **)q->data, entropy,
573 min_len, max_len, prediction_resistance);
577 static int rand_drbg_cleanup_entropy_cb(const OSSL_PARAM *params, void *vdrbg)
579 RAND_DRBG *drbg = (RAND_DRBG *)vdrbg;
583 if (drbg->cleanup_entropy == NULL)
586 p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_SIZE);
587 if (p == NULL || !OSSL_PARAM_get_size_t(p, &sz))
590 p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RANDOM_DATA);
591 if (p == NULL || p->data_type != OSSL_PARAM_OCTET_PTR)
594 drbg->cleanup_entropy(drbg, p->data, sz);
598 static int rand_drbg_get_nonce_cb(const OSSL_PARAM *params, OSSL_PARAM *out,
601 RAND_DRBG *drbg = (RAND_DRBG *)vdrbg;
603 size_t min_len = 0, max_len = 10240;
607 if (drbg->get_nonce == NULL)
610 p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_ENTROPY_REQUIRED);
611 if (p == NULL || !OSSL_PARAM_get_int(p, &entropy))
614 p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_MAX_LENGTH);
615 if (p == NULL || !OSSL_PARAM_get_size_t(p, &max_len))
618 p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_MIN_LENGTH);
619 if (p == NULL || !OSSL_PARAM_get_size_t(p, &min_len))
622 q = OSSL_PARAM_locate(out, OSSL_DRBG_PARAM_RANDOM_DATA);
623 if (q == NULL || q->data_type != OSSL_PARAM_OCTET_PTR || q->data == NULL)
626 q->return_size = drbg->get_nonce(drbg, (unsigned char **)q->data, entropy,
631 static int rand_drbg_cleanup_nonce_cb(const OSSL_PARAM *params, void *vdrbg)
633 RAND_DRBG *drbg = (RAND_DRBG *)vdrbg;
637 if (drbg->cleanup_nonce == NULL)
640 p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_SIZE);
641 if (p == NULL || !OSSL_PARAM_get_size_t(p, &sz))
644 p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RANDOM_DATA);
645 if (p == NULL || p->data_type != OSSL_PARAM_OCTET_PTR)
648 drbg->cleanup_nonce(drbg, p->data, sz);
653 * Set the RAND_DRBG callbacks for obtaining entropy and nonce.
655 * Setting the callbacks is allowed only if the drbg has not been
656 * initialized yet. Otherwise, the operation will fail.
658 * Returns 1 on success, 0 on failure.
660 int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
661 RAND_DRBG_get_entropy_fn get_entropy,
662 RAND_DRBG_cleanup_entropy_fn cleanup_entropy,
663 RAND_DRBG_get_nonce_fn get_nonce,
664 RAND_DRBG_cleanup_nonce_fn cleanup_nonce)
666 EVP_RAND_CTX *rand = drbg->rand;
667 OSSL_INOUT_CALLBACK *g_ent = NULL, *g_nonce = NULL;
668 OSSL_CALLBACK *c_ent = NULL, *c_nonce = NULL;
670 if (get_entropy != NULL) {
671 g_ent = &rand_drbg_get_entroy_cb;
672 c_ent = &rand_drbg_cleanup_entropy_cb;
674 if (get_nonce != NULL) {
675 g_nonce = rand_drbg_get_nonce_cb;
676 c_nonce = rand_drbg_cleanup_nonce_cb;
678 if (!EVP_RAND_set_callbacks(rand, g_ent, c_ent, g_nonce, c_nonce, drbg))
681 drbg->get_entropy = g_ent != NULL ? get_entropy : NULL;
682 drbg->cleanup_entropy = c_ent != NULL ? cleanup_entropy : NULL;
683 drbg->get_nonce = g_nonce != NULL ? get_nonce : NULL;
684 drbg->cleanup_nonce = c_nonce != NULL ? cleanup_nonce : NULL;
689 * Set the reseed interval.
691 * The drbg will reseed automatically whenever the number of generate
692 * requests exceeds the given reseed interval. If the reseed interval
693 * is 0, then this feature is disabled.
695 * Returns 1 on success, 0 on failure.
697 int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, unsigned int interval)
699 OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
701 if (interval > MAX_RESEED_INTERVAL)
703 params[0] = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS,
705 return EVP_RAND_set_ctx_params(drbg->rand, params);
709 * Set the reseed time interval.
711 * The drbg will reseed automatically whenever the time elapsed since
712 * the last reseeding exceeds the given reseed time interval. For safety,
713 * a reseeding will also occur if the clock has been reset to a smaller
716 * Returns 1 on success, 0 on failure.
718 int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg, time_t interval)
720 OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
722 if (interval > MAX_RESEED_TIME_INTERVAL)
725 OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL,
727 return EVP_RAND_set_ctx_params(drbg->rand, params);
731 * Set the default values for reseed (time) intervals of new DRBG instances
733 * The default values can be set independently for master DRBG instances
734 * (without a parent) and slave DRBG instances (with parent).
736 * Returns 1 on success, 0 on failure.
739 int RAND_DRBG_set_reseed_defaults(
740 unsigned int _master_reseed_interval,
741 unsigned int _slave_reseed_interval,
742 time_t _master_reseed_time_interval,
743 time_t _slave_reseed_time_interval
746 if (_master_reseed_interval > MAX_RESEED_INTERVAL
747 || _slave_reseed_interval > MAX_RESEED_INTERVAL)
750 if (_master_reseed_time_interval > MAX_RESEED_TIME_INTERVAL
751 || _slave_reseed_time_interval > MAX_RESEED_TIME_INTERVAL)
754 master_reseed_interval = _master_reseed_interval;
755 slave_reseed_interval = _slave_reseed_interval;
757 master_reseed_time_interval = _master_reseed_time_interval;
758 slave_reseed_time_interval = _slave_reseed_time_interval;
764 * Get and set the EXDATA
766 int RAND_DRBG_set_ex_data(RAND_DRBG *drbg, int idx, void *arg)
768 return CRYPTO_set_ex_data(&drbg->ex_data, idx, arg);
771 void *RAND_DRBG_get_ex_data(const RAND_DRBG *drbg, int idx)
773 return CRYPTO_get_ex_data(&drbg->ex_data, idx);
777 * The following functions provide a RAND_METHOD that works on the
778 * global DRBG. They lock.
782 * Allocates a new global DRBG on the secure heap (if enabled) and
783 * initializes it with default settings.
785 * Returns a pointer to the new DRBG instance on success, NULL on failure.
787 static RAND_DRBG *drbg_setup(OPENSSL_CTX *ctx, RAND_DRBG *parent, int drbg_type)
791 drbg = RAND_DRBG_new_ex(ctx, rand_drbg_type[drbg_type],
792 rand_drbg_flags[drbg_type], parent);
796 /* Only the master DRBG needs to have a lock */
797 if (parent == NULL && EVP_RAND_enable_locking(drbg->rand) == 0)
801 * Ignore instantiation error to support just-in-time instantiation.
803 * The state of the drbg will be checked in RAND_DRBG_generate() and
804 * an automatic recovery is attempted.
806 (void)RAND_DRBG_instantiate(drbg, NULL, 0);
810 RAND_DRBG_free(drbg);
814 static void drbg_delete_thread_state(void *arg)
816 OPENSSL_CTX *ctx = arg;
817 DRBG_GLOBAL *dgbl = drbg_get_global(ctx);
822 drbg = CRYPTO_THREAD_get_local(&dgbl->public_drbg);
823 CRYPTO_THREAD_set_local(&dgbl->public_drbg, NULL);
824 RAND_DRBG_free(drbg);
826 drbg = CRYPTO_THREAD_get_local(&dgbl->private_drbg);
827 CRYPTO_THREAD_set_local(&dgbl->private_drbg, NULL);
828 RAND_DRBG_free(drbg);
831 /* Implements the default OpenSSL RAND_bytes() method */
832 static int drbg_bytes(unsigned char *out, int count)
835 RAND_DRBG *drbg = RAND_DRBG_get0_public();
840 ret = RAND_DRBG_bytes(drbg, out, count);
845 /* Implements the default OpenSSL RAND_add() method */
846 static int drbg_add(const void *buf, int num, double randomness)
848 RAND_DRBG *drbg = RAND_DRBG_get0_master();
850 if (drbg == NULL || num <= 0)
853 return EVP_RAND_reseed(drbg->rand, 0, NULL, 0, buf, num);
856 /* Implements the default OpenSSL RAND_seed() method */
857 static int drbg_seed(const void *buf, int num)
859 return drbg_add(buf, num, num);
862 /* Implements the default OpenSSL RAND_status() method */
863 static int drbg_status(void)
866 RAND_DRBG *drbg = RAND_DRBG_get0_master();
871 ret = EVP_RAND_state(drbg->rand) == EVP_RAND_STATE_READY ? 1 : 0;
875 int RAND_DRBG_verify_zeroization(RAND_DRBG *drbg)
877 return EVP_RAND_verify_zeroization(drbg->rand);
881 * Get the master DRBG.
882 * Returns pointer to the DRBG on success, NULL on failure.
885 RAND_DRBG *OPENSSL_CTX_get0_master_drbg(OPENSSL_CTX *ctx)
887 DRBG_GLOBAL *dgbl = drbg_get_global(ctx);
892 if (dgbl->master_drbg == NULL) {
893 if (!CRYPTO_THREAD_write_lock(dgbl->lock))
895 if (dgbl->master_drbg == NULL)
896 dgbl->master_drbg = drbg_setup(ctx, NULL, RAND_DRBG_TYPE_MASTER);
897 CRYPTO_THREAD_unlock(dgbl->lock);
899 return dgbl->master_drbg;
902 RAND_DRBG *RAND_DRBG_get0_master(void)
904 return OPENSSL_CTX_get0_master_drbg(NULL);
908 * Get the public DRBG.
909 * Returns pointer to the DRBG on success, NULL on failure.
911 RAND_DRBG *OPENSSL_CTX_get0_public_drbg(OPENSSL_CTX *ctx)
913 DRBG_GLOBAL *dgbl = drbg_get_global(ctx);
914 RAND_DRBG *drbg, *master;
919 drbg = CRYPTO_THREAD_get_local(&dgbl->public_drbg);
921 master = OPENSSL_CTX_get0_master_drbg(ctx);
925 ctx = openssl_ctx_get_concrete(ctx);
927 * If the private_drbg is also NULL then this is the first time we've
930 if (CRYPTO_THREAD_get_local(&dgbl->private_drbg) == NULL
931 && !ossl_init_thread_start(NULL, ctx, drbg_delete_thread_state))
933 drbg = drbg_setup(ctx, master, RAND_DRBG_TYPE_PUBLIC);
934 CRYPTO_THREAD_set_local(&dgbl->public_drbg, drbg);
939 RAND_DRBG *RAND_DRBG_get0_public(void)
941 return OPENSSL_CTX_get0_public_drbg(NULL);
945 * Get the private DRBG.
946 * Returns pointer to the DRBG on success, NULL on failure.
948 RAND_DRBG *OPENSSL_CTX_get0_private_drbg(OPENSSL_CTX *ctx)
950 DRBG_GLOBAL *dgbl = drbg_get_global(ctx);
951 RAND_DRBG *drbg, *master;
956 drbg = CRYPTO_THREAD_get_local(&dgbl->private_drbg);
958 master = OPENSSL_CTX_get0_master_drbg(ctx);
962 ctx = openssl_ctx_get_concrete(ctx);
964 * If the public_drbg is also NULL then this is the first time we've
967 if (CRYPTO_THREAD_get_local(&dgbl->public_drbg) == NULL
968 && !ossl_init_thread_start(NULL, ctx, drbg_delete_thread_state))
970 drbg = drbg_setup(ctx, master, RAND_DRBG_TYPE_PRIVATE);
971 CRYPTO_THREAD_set_local(&dgbl->private_drbg, drbg);
976 RAND_DRBG *RAND_DRBG_get0_private(void)
978 return OPENSSL_CTX_get0_private_drbg(NULL);
981 RAND_METHOD rand_meth = {
990 RAND_METHOD *RAND_OpenSSL(void)