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