const RAND_METHOD *RAND_get_rand_method(void) { const RAND_METHOD *tmp_meth = NULL; if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init)) return NULL; CRYPTO_THREAD_write_lock(rand_meth_lock); if (!default_RAND_meth) { #ifndef OPENSSL_NO_ENGINE ENGINE *e = ENGINE_get_default_RAND(); if (e) { default_RAND_meth = ENGINE_get_RAND(e); if (default_RAND_meth == NULL) { ENGINE_finish(e); e = NULL; } } if (e) funct_ref = e; else #endif default_RAND_meth = RAND_OpenSSL(); } tmp_meth = default_RAND_meth; CRYPTO_THREAD_unlock(rand_meth_lock); return tmp_meth; }
/* * This function is not part of RAND_METHOD, so if we're not using * the default method, then just call RAND_bytes(). Otherwise make * sure we're instantiated and use the private DRBG. */ int RAND_priv_bytes(unsigned char *buf, int num) { const RAND_METHOD *meth = RAND_get_rand_method(); if (meth != RAND_OpenSSL()) return RAND_bytes(buf, num); if (priv_drbg.state == DRBG_UNINITIALISED && RAND_DRBG_instantiate(&priv_drbg, NULL, 0) == 0) return 0; return RAND_DRBG_generate(&priv_drbg, buf, num, 0, NULL, 0); }
/* * OpenSSL random should re-feeded occasionally. From /dev/urandom * preferably. */ static void init_openssl_rand(void) { if (RAND_get_rand_method() == NULL) { #ifdef HAVE_RAND_OPENSSL RAND_set_rand_method(RAND_OpenSSL()); #else RAND_set_rand_method(RAND_SSLeay()); #endif } openssl_random_init = 1; }
/* * This function is not part of RAND_METHOD, so if we're not using * the default method, then just call RAND_bytes(). Otherwise make * sure we're instantiated and use the private DRBG. */ int RAND_priv_bytes(unsigned char *buf, int num) { const RAND_METHOD *meth = RAND_get_rand_method(); RAND_DRBG *drbg; if (meth != RAND_OpenSSL()) return RAND_bytes(buf, num); drbg = RAND_DRBG_get0_priv_global(); if (drbg == NULL) return 0; return RAND_DRBG_generate(drbg, buf, num, 0, NULL, 0); }
static int ubsec_rand_bytes(unsigned char *buf, int num) { int ret = 0, fd; if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { const RAND_METHOD *meth; UBSECerr(UBSEC_F_UBSEC_RAND_BYTES, UBSEC_R_UNIT_FAILURE); num = p_UBSEC_ubsec_bits_to_bytes(num); meth = RAND_OpenSSL(); meth->seed(buf, num); ret = meth->bytes(buf, num); goto err; } num *= 8; /* bytes to bits */ if (p_UBSEC_rng_ioctl(fd, UBSEC_RNG_DIRECT, buf, &num) != 0) { /* Hardware's a no go, failover to software */ const RAND_METHOD *meth; UBSECerr(UBSEC_F_UBSEC_RAND_BYTES, UBSEC_R_REQUEST_FAILED); p_UBSEC_ubsec_close(fd); num = p_UBSEC_ubsec_bits_to_bytes(num); meth = RAND_OpenSSL(); meth->seed(buf, num); ret = meth->bytes(buf, num); goto err; } p_UBSEC_ubsec_close(fd); ret = 1; err: return (ret); }
/* * RAND_poll() reseeds the default RNG using random input * * The random input is obtained from polling various entropy * sources which depend on the operating system and are * configurable via the --with-rand-seed configure option. */ int RAND_poll(void) { int ret = 0; RAND_POOL *pool = NULL; const RAND_METHOD *meth = RAND_get_rand_method(); if (meth == RAND_OpenSSL()) { /* fill random pool and seed the master DRBG */ RAND_DRBG *drbg = RAND_DRBG_get0_master(); if (drbg == NULL) return 0; CRYPTO_THREAD_write_lock(drbg->lock); ret = rand_drbg_restart(drbg, NULL, 0, 0); CRYPTO_THREAD_unlock(drbg->lock); return ret; } else { /* fill random pool and seed the current legacy RNG */ pool = RAND_POOL_new(RAND_DRBG_STRENGTH, RAND_DRBG_STRENGTH / 8, DRBG_MINMAX_FACTOR * (RAND_DRBG_STRENGTH / 8)); if (pool == NULL) return 0; if (RAND_POOL_acquire_entropy(pool) == 0) goto err; if (meth->add == NULL || meth->add(RAND_POOL_buffer(pool), RAND_POOL_length(pool), (RAND_POOL_entropy(pool) / 8.0)) == 0) goto err; ret = 1; } err: RAND_POOL_free(pool); return ret; }
/* * This function is not part of RAND_METHOD, so if we're not using * the default method, then just call RAND_bytes(). Otherwise make * sure we're instantiated and use the private DRBG. */ int RAND_priv_bytes(unsigned char *buf, int num) { const RAND_METHOD *meth = RAND_get_rand_method(); RAND_DRBG *drbg; int ret; if (meth != RAND_OpenSSL()) return RAND_bytes(buf, num); drbg = RAND_DRBG_get0_private(); if (drbg == NULL) return 0; /* We have to lock the DRBG before generating bits from it. */ CRYPTO_THREAD_write_lock(drbg->lock); ret = RAND_DRBG_generate(drbg, buf, num, 0, NULL, 0); CRYPTO_THREAD_unlock(drbg->lock); return ret; }
/* * This internal function is used by ENGINE_openssl() and possibly by the * "dynamic" ENGINE support too */ static int bind_helper(ENGINE *e) { if (!ENGINE_set_id(e, engine_openssl_id) || !ENGINE_set_name(e, engine_openssl_name) || !ENGINE_set_destroy_function(e, openssl_destroy) #ifndef TEST_ENG_OPENSSL_NO_ALGORITHMS # ifndef OPENSSL_NO_RSA || !ENGINE_set_RSA(e, RSA_get_default_method()) # endif # ifndef OPENSSL_NO_DSA || !ENGINE_set_DSA(e, DSA_get_default_method()) # endif # ifndef OPENSSL_NO_EC || !ENGINE_set_EC(e, EC_KEY_OpenSSL()) # endif # ifndef OPENSSL_NO_DH || !ENGINE_set_DH(e, DH_get_default_method()) # endif || !ENGINE_set_RAND(e, RAND_OpenSSL()) # ifdef TEST_ENG_OPENSSL_RC4 || !ENGINE_set_ciphers(e, openssl_ciphers) # endif # ifdef TEST_ENG_OPENSSL_SHA || !ENGINE_set_digests(e, openssl_digests) # endif #endif #ifdef TEST_ENG_OPENSSL_PKEY || !ENGINE_set_load_privkey_function(e, openssl_load_privkey) #endif #ifdef TEST_ENG_OPENSSL_HMAC || !ossl_register_hmac_meth() || !ENGINE_set_pkey_meths(e, ossl_pkey_meths) #endif ) return 0; /* * If we add errors to this ENGINE, ensure the error handling is setup * here */ /* openssl_load_error_strings(); */ return 1; }
const RAND_METHOD *RAND_get_rand_method(void) { if (!default_RAND_meth) { #ifndef OPENSSL_NO_ENGINE ENGINE *e = ENGINE_get_default_RAND(); if (e) { default_RAND_meth = ENGINE_get_RAND(e); if (!default_RAND_meth) { ENGINE_finish(e); e = NULL; } } if (e) funct_ref = e; else #endif default_RAND_meth = RAND_OpenSSL(); } return default_RAND_meth; }