/* Implements the default OpenSSL RAND_add() method */ static int drbg_add(const void *buf, int num, double randomness) { int ret = 0; RAND_DRBG *drbg = RAND_DRBG_get0_master(); if (drbg == NULL) return 0; if (num < 0 || randomness < 0.0) return 0; if (randomness > (double)drbg->max_entropylen) { /* * The purpose of this check is to bound |randomness| by a * relatively small value in order to prevent an integer * overflow when multiplying by 8 in the rand_drbg_restart() * call below. */ return 0; } rand_drbg_lock(drbg); ret = rand_drbg_restart(drbg, buf, (size_t)(unsigned int)num, (size_t)(8*randomness)); rand_drbg_unlock(drbg); return ret; }
/* Implements the default OpenSSL RAND_add() method */ static int drbg_add(const void *buf, int num, double randomness) { int ret = 0; RAND_DRBG *drbg = RAND_DRBG_get0_master(); size_t buflen; size_t seedlen; if (drbg == NULL) return 0; if (num < 0 || randomness < 0.0) return 0; rand_drbg_lock(drbg); seedlen = rand_drbg_seedlen(drbg); buflen = (size_t)num; if (buflen < seedlen || randomness < (double) seedlen) { #if defined(OPENSSL_RAND_SEED_NONE) /* * If no os entropy source is available, a reseeding will fail * inevitably. So we use a trick to mix the buffer contents into * the DRBG state without forcing a reseeding: we generate a * dummy random byte, using the buffer content as additional data. * Note: This won't work with RAND_DRBG_FLAG_CTR_NO_DF. */ unsigned char dummy[1]; ret = RAND_DRBG_generate(drbg, dummy, sizeof(dummy), 0, buf, buflen); rand_drbg_unlock(drbg); return ret; #else /* * If an os entropy source is avaible then we declare the buffer content * as additional data by setting randomness to zero and trigger a regular * reseeding. */ randomness = 0.0; #endif } if (randomness > (double)seedlen) { /* * The purpose of this check is to bound |randomness| by a * relatively small value in order to prevent an integer * overflow when multiplying by 8 in the rand_drbg_restart() * call below. Note that randomness is measured in bytes, * not bits, so this value corresponds to eight times the * security strength. */ randomness = (double)seedlen; } ret = rand_drbg_restart(drbg, buf, buflen, (size_t)(8 * randomness)); rand_drbg_unlock(drbg); return ret; }
/* Implements the default OpenSSL RAND_status() method */ static int drbg_status(void) { int ret; RAND_DRBG *drbg = RAND_DRBG_get0_master(); if (drbg == NULL) return 0; rand_drbg_lock(drbg); ret = drbg->state == DRBG_READY ? 1 : 0; rand_drbg_unlock(drbg); return ret; }
/* Implements the default OpenSSL RAND_status() method */ static int drbg_status(void) { int ret; RAND_DRBG *drbg = RAND_DRBG_get0_master(); if (drbg == NULL) return 0; CRYPTO_THREAD_write_lock(drbg->lock); ret = drbg->state == DRBG_READY ? 1 : 0; CRYPTO_THREAD_unlock(drbg->lock); 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; }