xref: /freebsd/crypto/openssl/crypto/rand/rand_lib.c (revision aa7957345732816fb0ba8308798d2f79f45597f9)
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