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