]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/rand/rand_lib.c
fips selftest: avoid relying on a real RNG for self tests
[thirdparty/openssl.git] / crypto / rand / rand_lib.c
CommitLineData
b1322259 1/*
da1c088f 2 * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
dfeab068 3 *
0db63de9 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
b1322259
RS
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
dfeab068
RE
8 */
9
e4468e6d
P
10/* We need to use some engine deprecated APIs */
11#define OPENSSL_SUPPRESS_DEPRECATED
12
44d2482b 13#include <openssl/err.h>
98186eb4 14#include <openssl/opensslconf.h>
7d615e21 15#include <openssl/core_names.h>
dce7272d 16#include "internal/cryptlib.h"
87975cfa 17#include "internal/thread_once.h"
dce7272d
TM
18#include "crypto/rand.h"
19#include "crypto/cryptlib.h"
706457b7 20#include "rand_local.h"
927d0566 21#include "crypto/context.h"
dfeab068 22
f844f9eb 23#ifndef FIPS_MODULE
dce7272d
TM
24# include <stdio.h>
25# include <time.h>
26# include <limits.h>
27# include <openssl/conf.h>
28# include <openssl/trace.h>
29# include <openssl/engine.h>
03bede0c 30# include "crypto/rand_pool.h"
f000e828 31# include "prov/seeding.h"
d5f9166b 32# include "internal/e_os.h"
f000e828 33
a2f27fd7 34# ifndef OPENSSL_NO_ENGINE
cb78486d 35/* non-NULL if default_RAND_meth is ENGINE-provided */
da8fc25a
RS
36static ENGINE *funct_ref;
37static CRYPTO_RWLOCK *rand_engine_lock;
a2f27fd7 38# endif
786b13fa 39# ifndef OPENSSL_NO_DEPRECATED_3_0
da8fc25a
RS
40static CRYPTO_RWLOCK *rand_meth_lock;
41static const RAND_METHOD *default_RAND_meth;
786b13fa 42# endif
da8fc25a 43static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;
c16de9d8 44
e2d227bb 45static int rand_inited = 0;
ddc6a5c8 46
da8fc25a 47DEFINE_RUN_ONCE_STATIC(do_rand_init)
87975cfa 48{
a2f27fd7 49# ifndef OPENSSL_NO_ENGINE
63ab5ea1 50 rand_engine_lock = CRYPTO_THREAD_lock_new();
0e5c1a66
BE
51 if (rand_engine_lock == NULL)
52 return 0;
a2f27fd7 53# endif
0e5c1a66 54
786b13fa 55# ifndef OPENSSL_NO_DEPRECATED_3_0
63ab5ea1 56 rand_meth_lock = CRYPTO_THREAD_lock_new();
0e5c1a66 57 if (rand_meth_lock == NULL)
a2f27fd7 58 goto err;
786b13fa 59# endif
5bc6bcf8 60
1335ca4b 61 if (!ossl_rand_pool_init())
a2f27fd7 62 goto err;
c7504aeb 63
e2d227bb 64 rand_inited = 1;
0e5c1a66
BE
65 return 1;
66
a2f27fd7 67 err:
786b13fa 68# ifndef OPENSSL_NO_DEPRECATED_3_0
0e5c1a66
BE
69 CRYPTO_THREAD_lock_free(rand_meth_lock);
70 rand_meth_lock = NULL;
786b13fa 71# endif
a2f27fd7 72# ifndef OPENSSL_NO_ENGINE
0e5c1a66
BE
73 CRYPTO_THREAD_lock_free(rand_engine_lock);
74 rand_engine_lock = NULL;
a2f27fd7 75# endif
0e5c1a66 76 return 0;
87975cfa 77}
dfeab068 78
1335ca4b 79void ossl_rand_cleanup_int(void)
da8fc25a 80{
786b13fa 81# ifndef OPENSSL_NO_DEPRECATED_3_0
da8fc25a
RS
82 const RAND_METHOD *meth = default_RAND_meth;
83
e2d227bb
BE
84 if (!rand_inited)
85 return;
bc420ebe 86
da8fc25a
RS
87 if (meth != NULL && meth->cleanup != NULL)
88 meth->cleanup();
89 RAND_set_rand_method(NULL);
786b13fa 90# endif
1335ca4b 91 ossl_rand_pool_cleanup();
a2f27fd7 92# ifndef OPENSSL_NO_ENGINE
da8fc25a 93 CRYPTO_THREAD_lock_free(rand_engine_lock);
0e5c1a66 94 rand_engine_lock = NULL;
a2f27fd7 95# endif
786b13fa 96# ifndef OPENSSL_NO_DEPRECATED_3_0
da8fc25a 97 CRYPTO_THREAD_lock_free(rand_meth_lock);
0e5c1a66 98 rand_meth_lock = NULL;
786b13fa 99# endif
a88e97fc 100 ossl_release_default_drbg_ctx();
e2d227bb 101 rand_inited = 0;
75e2c877
RS
102}
103
c7504aeb 104/*
c2969ff6 105 * RAND_close_seed_files() ensures that any seed file descriptors are
f000e828
P
106 * closed after use. This only applies to libcrypto/default provider,
107 * it does not apply to other providers.
c7504aeb
P
108 */
109void RAND_keep_random_devices_open(int keep)
110{
ac765685 111 if (RUN_ONCE(&rand_init, do_rand_init))
1335ca4b 112 ossl_rand_pool_keep_random_devices_open(keep);
c7504aeb
P
113}
114
75e2c877 115/*
c16de9d8
DMSP
116 * RAND_poll() reseeds the default RNG using random input
117 *
118 * The random input is obtained from polling various entropy
119 * sources which depend on the operating system and are
120 * configurable via the --with-rand-seed configure option.
121 */
122int RAND_poll(void)
123{
cc343d04
MK
124 static const char salt[] = "polling";
125
786b13fa 126# ifndef OPENSSL_NO_DEPRECATED_3_0
c16de9d8 127 const RAND_METHOD *meth = RAND_get_rand_method();
f000e828 128 int ret = meth == RAND_OpenSSL();
c16de9d8 129
0402c90f
DMSP
130 if (meth == NULL)
131 return 0;
132
f000e828 133 if (!ret) {
c16de9d8 134 /* fill random pool and seed the current legacy RNG */
1335ca4b
SL
135 RAND_POOL *pool = ossl_rand_pool_new(RAND_DRBG_STRENGTH, 1,
136 (RAND_DRBG_STRENGTH + 7) / 8,
137 RAND_POOL_MAX_LENGTH);
7d615e21 138
c16de9d8
DMSP
139 if (pool == NULL)
140 return 0;
f000e828 141
1dc188ba 142 if (ossl_pool_acquire_entropy(pool) == 0)
c16de9d8 143 goto err;
f000e828 144
c16de9d8 145 if (meth->add == NULL
1335ca4b
SL
146 || meth->add(ossl_rand_pool_buffer(pool),
147 ossl_rand_pool_length(pool),
148 (ossl_rand_pool_entropy(pool) / 8.0)) == 0)
c16de9d8
DMSP
149 goto err;
150
151 ret = 1;
a2f27fd7 152 err:
1335ca4b 153 ossl_rand_pool_free(pool);
cc343d04 154 return ret;
c16de9d8 155 }
cc343d04 156# endif
786b13fa
P
157
158 RAND_seed(salt, sizeof(salt));
159 return 1;
c16de9d8 160}
c16de9d8 161
786b13fa 162# ifndef OPENSSL_NO_DEPRECATED_3_0
8f4cddbc
P
163static int rand_set_rand_method_internal(const RAND_METHOD *meth,
164 ossl_unused ENGINE *e)
0f113f3e 165{
da8fc25a 166 if (!RUN_ONCE(&rand_init, do_rand_init))
87975cfa
RL
167 return 0;
168
cd3f8c1b
RS
169 if (!CRYPTO_THREAD_write_lock(rand_meth_lock))
170 return 0;
786b13fa 171# ifndef OPENSSL_NO_ENGINE
7c96dbcd 172 ENGINE_finish(funct_ref);
8f4cddbc 173 funct_ref = e;
786b13fa 174# endif
0f113f3e 175 default_RAND_meth = meth;
87975cfa 176 CRYPTO_THREAD_unlock(rand_meth_lock);
0f113f3e
MC
177 return 1;
178}
dfeab068 179
8f4cddbc
P
180int RAND_set_rand_method(const RAND_METHOD *meth)
181{
182 return rand_set_rand_method_internal(meth, NULL);
183}
184
a4a9d97a 185const RAND_METHOD *RAND_get_rand_method(void)
0f113f3e 186{
87975cfa
RL
187 const RAND_METHOD *tmp_meth = NULL;
188
da8fc25a 189 if (!RUN_ONCE(&rand_init, do_rand_init))
87975cfa
RL
190 return NULL;
191
7f2c22c1
MC
192 if (!CRYPTO_THREAD_read_lock(rand_meth_lock))
193 return NULL;
194 tmp_meth = default_RAND_meth;
195 CRYPTO_THREAD_unlock(rand_meth_lock);
196 if (tmp_meth != NULL)
197 return tmp_meth;
198
cd3f8c1b
RS
199 if (!CRYPTO_THREAD_write_lock(rand_meth_lock))
200 return NULL;
da8fc25a 201 if (default_RAND_meth == NULL) {
786b13fa 202# ifndef OPENSSL_NO_ENGINE
da8fc25a
RS
203 ENGINE *e;
204
205 /* If we have an engine that can do RAND, use it. */
206 if ((e = ENGINE_get_default_RAND()) != NULL
207 && (tmp_meth = ENGINE_get_RAND(e)) != NULL) {
0f113f3e 208 funct_ref = e;
da8fc25a
RS
209 default_RAND_meth = tmp_meth;
210 } else {
211 ENGINE_finish(e);
1335ca4b 212 default_RAND_meth = &ossl_rand_meth;
da8fc25a 213 }
786b13fa 214# else
1335ca4b 215 default_RAND_meth = &ossl_rand_meth;
786b13fa 216# endif
0f113f3e 217 }
87975cfa
RL
218 tmp_meth = default_RAND_meth;
219 CRYPTO_THREAD_unlock(rand_meth_lock);
220 return tmp_meth;
0f113f3e 221}
cb78486d 222
786b13fa 223# if !defined(OPENSSL_NO_ENGINE)
cb78486d 224int RAND_set_rand_engine(ENGINE *engine)
0f113f3e
MC
225{
226 const RAND_METHOD *tmp_meth = NULL;
87975cfa 227
da8fc25a 228 if (!RUN_ONCE(&rand_init, do_rand_init))
87975cfa
RL
229 return 0;
230
da8fc25a 231 if (engine != NULL) {
0f113f3e
MC
232 if (!ENGINE_init(engine))
233 return 0;
234 tmp_meth = ENGINE_get_RAND(engine);
7c96dbcd 235 if (tmp_meth == NULL) {
0f113f3e
MC
236 ENGINE_finish(engine);
237 return 0;
238 }
239 }
cd3f8c1b
RS
240 if (!CRYPTO_THREAD_write_lock(rand_engine_lock)) {
241 ENGINE_finish(engine);
242 return 0;
243 }
244
0f113f3e 245 /* This function releases any prior ENGINE so call it first */
8f4cddbc 246 rand_set_rand_method_internal(tmp_meth, engine);
87975cfa 247 CRYPTO_THREAD_unlock(rand_engine_lock);
0f113f3e
MC
248 return 1;
249}
786b13fa
P
250# endif
251# endif /* OPENSSL_NO_DEPRECATED_3_0 */
dfeab068 252
6343829a 253void RAND_seed(const void *buf, int num)
0f113f3e 254{
786b13fa
P
255 EVP_RAND_CTX *drbg;
256# ifndef OPENSSL_NO_DEPRECATED_3_0
0f113f3e 257 const RAND_METHOD *meth = RAND_get_rand_method();
da8fc25a 258
786b13fa 259 if (meth != NULL && meth->seed != NULL) {
0f113f3e 260 meth->seed(buf, num);
786b13fa
P
261 return;
262 }
263# endif
264
265 drbg = RAND_get0_primary(NULL);
266 if (drbg != NULL && num > 0)
267 EVP_RAND_reseed(drbg, 0, NULL, 0, buf, num);
0f113f3e 268}
dfeab068 269
da8fc25a 270void RAND_add(const void *buf, int num, double randomness)
0f113f3e 271{
786b13fa
P
272 EVP_RAND_CTX *drbg;
273# ifndef OPENSSL_NO_DEPRECATED_3_0
0f113f3e 274 const RAND_METHOD *meth = RAND_get_rand_method();
da8fc25a 275
786b13fa 276 if (meth != NULL && meth->add != NULL) {
da8fc25a 277 meth->add(buf, num, randomness);
786b13fa
P
278 return;
279 }
280# endif
281 drbg = RAND_get0_primary(NULL);
282 if (drbg != NULL && num > 0)
56547da9
P
283# ifdef OPENSSL_RAND_SEED_NONE
284 /* Without an entropy source, we have to rely on the user */
285 EVP_RAND_reseed(drbg, 0, buf, num, NULL, 0);
286# else
287 /* With an entropy source, we downgrade this to additional input */
786b13fa 288 EVP_RAND_reseed(drbg, 0, NULL, 0, buf, num);
56547da9 289# endif
0f113f3e 290}
eb952088 291
f000e828
P
292# if !defined(OPENSSL_NO_DEPRECATED_1_1_0)
293int RAND_pseudo_bytes(unsigned char *buf, int num)
294{
295 const RAND_METHOD *meth = RAND_get_rand_method();
296
297 if (meth != NULL && meth->pseudorand != NULL)
298 return meth->pseudorand(buf, num);
9311d0c4 299 ERR_raise(ERR_LIB_RAND, RAND_R_FUNC_NOT_IMPLEMENTED);
f000e828
P
300 return -1;
301}
302# endif
303
304int RAND_status(void)
305{
7d615e21 306 EVP_RAND_CTX *rand;
786b13fa 307# ifndef OPENSSL_NO_DEPRECATED_3_0
f000e828
P
308 const RAND_METHOD *meth = RAND_get_rand_method();
309
310 if (meth != NULL && meth != RAND_OpenSSL())
311 return meth->status != NULL ? meth->status() : 0;
786b13fa 312# endif
f000e828 313
7d615e21 314 if ((rand = RAND_get0_primary(NULL)) == NULL)
4516bf74 315 return 0;
ed576acd 316 return EVP_RAND_get_state(rand) == EVP_RAND_STATE_READY;
f000e828 317}
786b13fa 318# else /* !FIPS_MODULE */
f000e828 319
786b13fa 320# ifndef OPENSSL_NO_DEPRECATED_3_0
f000e828
P
321const RAND_METHOD *RAND_get_rand_method(void)
322{
323 return NULL;
324}
786b13fa 325# endif
f000e828
P
326#endif /* !FIPS_MODULE */
327
ddc6a5c8
RS
328/*
329 * This function is not part of RAND_METHOD, so if we're not using
330 * the default method, then just call RAND_bytes(). Otherwise make
331 * sure we're instantiated and use the private DRBG.
332 */
528685fe 333int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
508258ca 334 unsigned int strength)
ddc6a5c8 335{
7d615e21 336 EVP_RAND_CTX *rand;
dce7272d 337#if !defined(OPENSSL_NO_DEPRECATED_3_0) && !defined(FIPS_MODULE)
a2f27fd7 338 const RAND_METHOD *meth = RAND_get_rand_method();
ddc6a5c8 339
0402c90f
DMSP
340 if (meth != NULL && meth != RAND_OpenSSL()) {
341 if (meth->bytes != NULL)
342 return meth->bytes(buf, num);
9311d0c4 343 ERR_raise(ERR_LIB_RAND, RAND_R_FUNC_NOT_IMPLEMENTED);
0402c90f
DMSP
344 return -1;
345 }
786b13fa 346#endif
ddc6a5c8 347
fffa78c2
P
348 if (num < 0)
349 return 0;
7d615e21
P
350 rand = RAND_get0_private(ctx);
351 if (rand != NULL)
508258ca 352 return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0);
ddc6a5c8 353
0402c90f 354 return 0;
ddc6a5c8
RS
355}
356
6694e51d 357int RAND_priv_bytes(unsigned char *buf, int num)
0f113f3e 358{
528685fe 359 return RAND_priv_bytes_ex(NULL, buf, (size_t)num, 0);
6694e51d
MC
360}
361
528685fe 362int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
508258ca 363 unsigned int strength)
6694e51d 364{
7d615e21 365 EVP_RAND_CTX *rand;
dce7272d 366#if !defined(OPENSSL_NO_DEPRECATED_3_0) && !defined(FIPS_MODULE)
0f113f3e 367 const RAND_METHOD *meth = RAND_get_rand_method();
da8fc25a 368
0402c90f 369 if (meth != NULL && meth != RAND_OpenSSL()) {
6694e51d
MC
370 if (meth->bytes != NULL)
371 return meth->bytes(buf, num);
9311d0c4 372 ERR_raise(ERR_LIB_RAND, RAND_R_FUNC_NOT_IMPLEMENTED);
6694e51d
MC
373 return -1;
374 }
786b13fa 375#endif
6694e51d 376
fffa78c2
P
377 if (num < 0)
378 return 0;
7d615e21
P
379 rand = RAND_get0_public(ctx);
380 if (rand != NULL)
508258ca 381 return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0);
6694e51d 382
0402c90f 383 return 0;
6694e51d
MC
384}
385
386int RAND_bytes(unsigned char *buf, int num)
387{
528685fe 388 return RAND_bytes_ex(NULL, buf, (size_t)num, 0);
0f113f3e 389}
7d615e21
P
390
391typedef struct rand_global_st {
392 /*
393 * The three shared DRBG instances
394 *
395 * There are three shared DRBG instances: <primary>, <public>, and
396 * <private>. The <public> and <private> DRBGs are secondary ones.
397 * These are used for non-secret (e.g. nonces) and secret
398 * (e.g. private keys) data respectively.
399 */
400 CRYPTO_RWLOCK *lock;
401
81aef6ba
P
402 EVP_RAND_CTX *seed;
403
7d615e21
P
404 /*
405 * The <primary> DRBG
406 *
407 * Not used directly by the application, only for reseeding the two other
408 * DRBGs. It reseeds itself by pulling either randomness from os entropy
409 * sources or by consuming randomness which was added by RAND_add().
410 *
411 * The <primary> DRBG is a global instance which is accessed concurrently by
412 * all threads. The necessary locking is managed automatically by its child
413 * DRBG instances during reseeding.
414 */
415 EVP_RAND_CTX *primary;
416
417 /*
418 * The <public> DRBG
419 *
420 * Used by default for generating random bytes using RAND_bytes().
421 *
422 * The <public> secondary DRBG is thread-local, i.e., there is one instance
423 * per thread.
424 */
425 CRYPTO_THREAD_LOCAL public;
426
427 /*
428 * The <private> DRBG
429 *
430 * Used by default for generating private keys using RAND_priv_bytes()
431 *
432 * The <private> secondary DRBG is thread-local, i.e., there is one
433 * instance per thread.
434 */
435 CRYPTO_THREAD_LOCAL private;
44d2482b
P
436
437 /* Which RNG is being used by default and it's configuration settings */
438 char *rng_name;
439 char *rng_cipher;
440 char *rng_digest;
441 char *rng_propq;
81aef6ba
P
442
443 /* Allow the randomness source to be changed */
444 char *seed_name;
445 char *seed_propq;
7d615e21
P
446} RAND_GLOBAL;
447
448/*
b4250010 449 * Initialize the OSSL_LIB_CTX global DRBGs on first use.
7d615e21
P
450 * Returns the allocated global data on success or NULL on failure.
451 */
927d0566 452void *ossl_rand_ctx_new(OSSL_LIB_CTX *libctx)
7d615e21
P
453{
454 RAND_GLOBAL *dgbl = OPENSSL_zalloc(sizeof(*dgbl));
455
456 if (dgbl == NULL)
457 return NULL;
458
459#ifndef FIPS_MODULE
460 /*
461 * We need to ensure that base libcrypto thread handling has been
462 * initialised.
463 */
12b4e582 464 OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL);
7d615e21
P
465#endif
466
467 dgbl->lock = CRYPTO_THREAD_lock_new();
468 if (dgbl->lock == NULL)
469 goto err1;
470
471 if (!CRYPTO_THREAD_init_local(&dgbl->private, NULL))
472 goto err1;
473
474 if (!CRYPTO_THREAD_init_local(&dgbl->public, NULL))
475 goto err2;
476
477 return dgbl;
478
479 err2:
480 CRYPTO_THREAD_cleanup_local(&dgbl->private);
481 err1:
482 CRYPTO_THREAD_lock_free(dgbl->lock);
483 OPENSSL_free(dgbl);
484 return NULL;
485}
486
927d0566 487void ossl_rand_ctx_free(void *vdgbl)
7d615e21
P
488{
489 RAND_GLOBAL *dgbl = vdgbl;
490
491 if (dgbl == NULL)
492 return;
493
494 CRYPTO_THREAD_lock_free(dgbl->lock);
7d615e21
P
495 CRYPTO_THREAD_cleanup_local(&dgbl->private);
496 CRYPTO_THREAD_cleanup_local(&dgbl->public);
81aef6ba
P
497 EVP_RAND_CTX_free(dgbl->primary);
498 EVP_RAND_CTX_free(dgbl->seed);
44d2482b
P
499 OPENSSL_free(dgbl->rng_name);
500 OPENSSL_free(dgbl->rng_cipher);
501 OPENSSL_free(dgbl->rng_digest);
502 OPENSSL_free(dgbl->rng_propq);
81aef6ba
P
503 OPENSSL_free(dgbl->seed_name);
504 OPENSSL_free(dgbl->seed_propq);
7d615e21
P
505
506 OPENSSL_free(dgbl);
507}
508
b4250010 509static RAND_GLOBAL *rand_get_global(OSSL_LIB_CTX *libctx)
7d615e21 510{
927d0566 511 return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_INDEX);
7d615e21
P
512}
513
514static void rand_delete_thread_state(void *arg)
515{
b4250010 516 OSSL_LIB_CTX *ctx = arg;
7d615e21
P
517 RAND_GLOBAL *dgbl = rand_get_global(ctx);
518 EVP_RAND_CTX *rand;
519
520 if (dgbl == NULL)
521 return;
522
523 rand = CRYPTO_THREAD_get_local(&dgbl->public);
524 CRYPTO_THREAD_set_local(&dgbl->public, NULL);
525 EVP_RAND_CTX_free(rand);
526
527 rand = CRYPTO_THREAD_get_local(&dgbl->private);
528 CRYPTO_THREAD_set_local(&dgbl->private, NULL);
529 EVP_RAND_CTX_free(rand);
530}
531
81aef6ba
P
532#ifndef FIPS_MODULE
533static EVP_RAND_CTX *rand_new_seed(OSSL_LIB_CTX *libctx)
534{
535 EVP_RAND *rand;
536 RAND_GLOBAL *dgbl = rand_get_global(libctx);
537 EVP_RAND_CTX *ctx;
538 char *name;
539
09dca557
JJ
540 if (dgbl == NULL)
541 return NULL;
81aef6ba
P
542 name = dgbl->seed_name != NULL ? dgbl->seed_name : "SEED-SRC";
543 rand = EVP_RAND_fetch(libctx, name, dgbl->seed_propq);
544 if (rand == NULL) {
545 ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG);
546 return NULL;
547 }
548 ctx = EVP_RAND_CTX_new(rand, NULL);
549 EVP_RAND_free(rand);
550 if (ctx == NULL) {
551 ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_CREATE_DRBG);
552 return NULL;
553 }
d5a936c5 554 if (!EVP_RAND_instantiate(ctx, 0, 0, NULL, 0, NULL)) {
81aef6ba
P
555 ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_INSTANTIATING_DRBG);
556 EVP_RAND_CTX_free(ctx);
557 return NULL;
558 }
559 return ctx;
560}
561#endif
562
b4250010 563static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent,
7d615e21 564 unsigned int reseed_interval,
505d44c6 565 time_t reseed_time_interval, int use_df)
7d615e21 566{
44d2482b
P
567 EVP_RAND *rand;
568 RAND_GLOBAL *dgbl = rand_get_global(libctx);
7d615e21 569 EVP_RAND_CTX *ctx;
505d44c6
P
570 OSSL_PARAM params[8], *p = params;
571 const OSSL_PARAM *settables;
44d2482b
P
572 char *name, *cipher;
573
09dca557
JJ
574 if (dgbl == NULL)
575 return NULL;
44d2482b
P
576 name = dgbl->rng_name != NULL ? dgbl->rng_name : "CTR-DRBG";
577 rand = EVP_RAND_fetch(libctx, name, dgbl->rng_propq);
7d615e21 578 if (rand == NULL) {
9311d0c4 579 ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG);
7d615e21
P
580 return NULL;
581 }
582 ctx = EVP_RAND_CTX_new(rand, parent);
583 EVP_RAND_free(rand);
584 if (ctx == NULL) {
9311d0c4 585 ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_CREATE_DRBG);
7d615e21
P
586 return NULL;
587 }
588
505d44c6
P
589 settables = EVP_RAND_CTX_settable_params(ctx);
590 if (OSSL_PARAM_locate_const(settables, OSSL_DRBG_PARAM_CIPHER)) {
591 cipher = dgbl->rng_cipher != NULL ? dgbl->rng_cipher : "AES-256-CTR";
592 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER,
593 cipher, 0);
594 }
595 if (dgbl->rng_digest != NULL
596 && OSSL_PARAM_locate_const(settables, OSSL_DRBG_PARAM_DIGEST))
44d2482b
P
597 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST,
598 dgbl->rng_digest, 0);
599 if (dgbl->rng_propq != NULL)
600 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_PROPERTIES,
601 dgbl->rng_propq, 0);
505d44c6
P
602 if (OSSL_PARAM_locate_const(settables, OSSL_ALG_PARAM_MAC))
603 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_MAC, "HMAC", 0);
604 if (OSSL_PARAM_locate_const(settables, OSSL_DRBG_PARAM_USE_DF))
605 *p++ = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_USE_DF, &use_df);
7d615e21
P
606 *p++ = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS,
607 &reseed_interval);
608 *p++ = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL,
609 &reseed_time_interval);
610 *p = OSSL_PARAM_construct_end();
d5a936c5 611 if (!EVP_RAND_instantiate(ctx, 0, 0, NULL, 0, params)) {
9311d0c4 612 ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_INSTANTIATING_DRBG);
4516bf74
P
613 EVP_RAND_CTX_free(ctx);
614 return NULL;
7d615e21
P
615 }
616 return ctx;
617}
618
619/*
620 * Get the primary random generator.
621 * Returns pointer to its EVP_RAND_CTX on success, NULL on failure.
622 *
623 */
b4250010 624EVP_RAND_CTX *RAND_get0_primary(OSSL_LIB_CTX *ctx)
7d615e21
P
625{
626 RAND_GLOBAL *dgbl = rand_get_global(ctx);
cd4e6a35 627 EVP_RAND_CTX *ret;
7d615e21
P
628
629 if (dgbl == NULL)
630 return NULL;
631
cd4e6a35
MC
632 if (!CRYPTO_THREAD_read_lock(dgbl->lock))
633 return NULL;
634
635 ret = dgbl->primary;
636 CRYPTO_THREAD_unlock(dgbl->lock);
637
638 if (ret != NULL)
639 return ret;
640
641 if (!CRYPTO_THREAD_write_lock(dgbl->lock))
642 return NULL;
643
644 ret = dgbl->primary;
645 if (ret != NULL) {
646 CRYPTO_THREAD_unlock(dgbl->lock);
647 return ret;
648 }
649
81aef6ba 650#ifndef FIPS_MODULE
cd4e6a35
MC
651 if (dgbl->seed == NULL) {
652 ERR_set_mark();
653 dgbl->seed = rand_new_seed(ctx);
654 ERR_pop_to_mark();
655 }
81aef6ba 656#endif
cd4e6a35
MC
657
658 ret = dgbl->primary = rand_new_drbg(ctx, dgbl->seed,
659 PRIMARY_RESEED_INTERVAL,
505d44c6 660 PRIMARY_RESEED_TIME_INTERVAL, 1);
cd4e6a35
MC
661 /*
662 * The primary DRBG may be shared between multiple threads so we must
663 * enable locking.
664 */
665 if (ret != NULL && !EVP_RAND_enable_locking(ret)) {
666 ERR_raise(ERR_LIB_EVP, EVP_R_UNABLE_TO_ENABLE_LOCKING);
667 EVP_RAND_CTX_free(ret);
668 ret = dgbl->primary = NULL;
7d615e21 669 }
cd4e6a35
MC
670 CRYPTO_THREAD_unlock(dgbl->lock);
671
672 return ret;
7d615e21
P
673}
674
675/*
676 * Get the public random generator.
677 * Returns pointer to its EVP_RAND_CTX on success, NULL on failure.
678 */
b4250010 679EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx)
7d615e21
P
680{
681 RAND_GLOBAL *dgbl = rand_get_global(ctx);
682 EVP_RAND_CTX *rand, *primary;
683
684 if (dgbl == NULL)
685 return NULL;
686
687 rand = CRYPTO_THREAD_get_local(&dgbl->public);
688 if (rand == NULL) {
689 primary = RAND_get0_primary(ctx);
690 if (primary == NULL)
691 return NULL;
692
b4250010 693 ctx = ossl_lib_ctx_get_concrete(ctx);
7d615e21
P
694 /*
695 * If the private is also NULL then this is the first time we've
696 * used this thread.
697 */
698 if (CRYPTO_THREAD_get_local(&dgbl->private) == NULL
699 && !ossl_init_thread_start(NULL, ctx, rand_delete_thread_state))
700 return NULL;
701 rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL,
505d44c6 702 SECONDARY_RESEED_TIME_INTERVAL, 0);
7d615e21
P
703 CRYPTO_THREAD_set_local(&dgbl->public, rand);
704 }
705 return rand;
706}
707
708/*
709 * Get the private random generator.
710 * Returns pointer to its EVP_RAND_CTX on success, NULL on failure.
711 */
b4250010 712EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx)
7d615e21
P
713{
714 RAND_GLOBAL *dgbl = rand_get_global(ctx);
715 EVP_RAND_CTX *rand, *primary;
716
717 if (dgbl == NULL)
718 return NULL;
719
720 rand = CRYPTO_THREAD_get_local(&dgbl->private);
721 if (rand == NULL) {
722 primary = RAND_get0_primary(ctx);
723 if (primary == NULL)
724 return NULL;
725
b4250010 726 ctx = ossl_lib_ctx_get_concrete(ctx);
7d615e21
P
727 /*
728 * If the public is also NULL then this is the first time we've
729 * used this thread.
730 */
731 if (CRYPTO_THREAD_get_local(&dgbl->public) == NULL
732 && !ossl_init_thread_start(NULL, ctx, rand_delete_thread_state))
733 return NULL;
734 rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL,
505d44c6 735 SECONDARY_RESEED_TIME_INTERVAL, 0);
7d615e21
P
736 CRYPTO_THREAD_set_local(&dgbl->private, rand);
737 }
738 return rand;
739}
44d2482b 740
fffa78c2
P
741#ifdef FIPS_MODULE
742EVP_RAND_CTX *ossl_rand_get0_private_noncreating(OSSL_LIB_CTX *ctx)
743{
744 RAND_GLOBAL *dgbl = rand_get_global(ctx);
745
746 if (dgbl == NULL)
747 return NULL;
748
749 return CRYPTO_THREAD_get_local(&dgbl->private);
750}
751#endif
752
7c8187d4
P
753int RAND_set0_public(OSSL_LIB_CTX *ctx, EVP_RAND_CTX *rand)
754{
755 RAND_GLOBAL *dgbl = rand_get_global(ctx);
756 EVP_RAND_CTX *old;
757 int r;
758
759 if (dgbl == NULL)
760 return 0;
761 old = CRYPTO_THREAD_get_local(&dgbl->public);
762 if ((r = CRYPTO_THREAD_set_local(&dgbl->public, rand)) > 0)
763 EVP_RAND_CTX_free(old);
764 return r;
765}
766
767int RAND_set0_private(OSSL_LIB_CTX *ctx, EVP_RAND_CTX *rand)
768{
769 RAND_GLOBAL *dgbl = rand_get_global(ctx);
770 EVP_RAND_CTX *old;
771 int r;
772
773 if (dgbl == NULL)
774 return 0;
775 old = CRYPTO_THREAD_get_local(&dgbl->private);
776 if ((r = CRYPTO_THREAD_set_local(&dgbl->private, rand)) > 0)
777 EVP_RAND_CTX_free(old);
778 return r;
779}
780
44d2482b
P
781#ifndef FIPS_MODULE
782static int random_set_string(char **p, const char *s)
783{
786b13fa 784 char *d = NULL;
44d2482b 785
786b13fa
P
786 if (s != NULL) {
787 d = OPENSSL_strdup(s);
e077455e 788 if (d == NULL)
786b13fa 789 return 0;
44d2482b
P
790 }
791 OPENSSL_free(*p);
792 *p = d;
793 return 1;
794}
795
796/*
797 * Load the DRBG definitions from a configuration file.
798 */
799static int random_conf_init(CONF_IMODULE *md, const CONF *cnf)
800{
801 STACK_OF(CONF_VALUE) *elist;
802 CONF_VALUE *cval;
6b750b89 803 RAND_GLOBAL *dgbl = rand_get_global(NCONF_get0_libctx((CONF *)cnf));
44d2482b
P
804 int i, r = 1;
805
806 OSSL_TRACE1(CONF, "Loading random module: section %s\n",
807 CONF_imodule_get_value(md));
808
809 /* Value is a section containing RANDOM configuration */
810 elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));
811 if (elist == NULL) {
9311d0c4 812 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_RANDOM_SECTION_ERROR);
44d2482b
P
813 return 0;
814 }
815
09dca557
JJ
816 if (dgbl == NULL)
817 return 0;
818
44d2482b
P
819 for (i = 0; i < sk_CONF_VALUE_num(elist); i++) {
820 cval = sk_CONF_VALUE_value(elist, i);
fba140c7 821 if (OPENSSL_strcasecmp(cval->name, "random") == 0) {
44d2482b
P
822 if (!random_set_string(&dgbl->rng_name, cval->value))
823 return 0;
fba140c7 824 } else if (OPENSSL_strcasecmp(cval->name, "cipher") == 0) {
44d2482b
P
825 if (!random_set_string(&dgbl->rng_cipher, cval->value))
826 return 0;
fba140c7 827 } else if (OPENSSL_strcasecmp(cval->name, "digest") == 0) {
44d2482b
P
828 if (!random_set_string(&dgbl->rng_digest, cval->value))
829 return 0;
fba140c7 830 } else if (OPENSSL_strcasecmp(cval->name, "properties") == 0) {
44d2482b
P
831 if (!random_set_string(&dgbl->rng_propq, cval->value))
832 return 0;
fba140c7 833 } else if (OPENSSL_strcasecmp(cval->name, "seed") == 0) {
81aef6ba
P
834 if (!random_set_string(&dgbl->seed_name, cval->value))
835 return 0;
fba140c7 836 } else if (OPENSSL_strcasecmp(cval->name, "seed_properties") == 0) {
81aef6ba
P
837 if (!random_set_string(&dgbl->seed_propq, cval->value))
838 return 0;
44d2482b 839 } else {
a150f8e1
RL
840 ERR_raise_data(ERR_LIB_CRYPTO,
841 CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION,
842 "name=%s, value=%s", cval->name, cval->value);
44d2482b
P
843 r = 0;
844 }
845 }
846 return r;
847}
848
849
850static void random_conf_deinit(CONF_IMODULE *md)
851{
852 OSSL_TRACE(CONF, "Cleaned up random\n");
853}
854
855void ossl_random_add_conf_module(void)
856{
857 OSSL_TRACE(CONF, "Adding config module 'random'\n");
858 CONF_module_add("random", random_conf_init, random_conf_deinit);
859}
786b13fa
P
860
861int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq,
862 const char *cipher, const char *digest)
863{
864 RAND_GLOBAL *dgbl = rand_get_global(ctx);
865
866 if (dgbl == NULL)
867 return 0;
868 if (dgbl->primary != NULL) {
869 ERR_raise(ERR_LIB_CRYPTO, RAND_R_ALREADY_INSTANTIATED);
870 return 0;
871 }
872 return random_set_string(&dgbl->rng_name, drbg)
873 && random_set_string(&dgbl->rng_propq, propq)
874 && random_set_string(&dgbl->rng_cipher, cipher)
875 && random_set_string(&dgbl->rng_digest, digest);
876}
877
878int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed,
879 const char *propq)
880{
881 RAND_GLOBAL *dgbl = rand_get_global(ctx);
882
883 if (dgbl == NULL)
884 return 0;
885 if (dgbl->primary != NULL) {
886 ERR_raise(ERR_LIB_CRYPTO, RAND_R_ALREADY_INSTANTIATED);
887 return 0;
888 }
889 return random_set_string(&dgbl->seed_name, seed)
890 && random_set_string(&dgbl->seed_propq, propq);
891}
892
44d2482b 893#endif