Coverage Report

Created: 2024-11-21 07:03

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