RAND_POOL *RAND_POOL_new(int entropy, size_t min_len, size_t max_len) { RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool)); if (pool == NULL) { RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE); goto err; } pool->min_len = min_len; pool->max_len = max_len; pool->buffer = OPENSSL_secure_zalloc(pool->max_len); if (pool->buffer == NULL) { RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE); goto err; } pool->requested_entropy = entropy; return pool; err: OPENSSL_free(pool); return NULL; }
/* * Allocate memory and initialize a new DRBG. The DRBG is allocated on * the secure heap if |secure| is nonzero and the secure heap is enabled. * The |parent|, if not NULL, will be used as random source for reseeding. * * Returns a pointer to the new DRBG instance on success, NULL on failure. */ static RAND_DRBG *rand_drbg_new(int secure, int type, unsigned int flags, RAND_DRBG *parent) { RAND_DRBG *drbg = secure ? OPENSSL_secure_zalloc(sizeof(*drbg)) : OPENSSL_zalloc(sizeof(*drbg)); if (drbg == NULL) { RANDerr(RAND_F_RAND_DRBG_NEW, ERR_R_MALLOC_FAILURE); return NULL; } drbg->secure = secure && CRYPTO_secure_allocated(drbg); drbg->fork_count = rand_fork_count; drbg->parent = parent; if (parent == NULL) { drbg->reseed_interval = master_reseed_interval; drbg->reseed_time_interval = master_reseed_time_interval; } else { drbg->reseed_interval = slave_reseed_interval; drbg->reseed_time_interval = slave_reseed_time_interval; } if (RAND_DRBG_set(drbg, type, flags) == 0) goto err; if (parent != NULL) { rand_drbg_lock(parent); if (drbg->strength > parent->strength) { /* * We currently don't support the algorithm from NIST SP 800-90C * 10.1.2 to use a weaker DRBG as source */ rand_drbg_unlock(parent); RANDerr(RAND_F_RAND_DRBG_NEW, RAND_R_PARENT_STRENGTH_TOO_WEAK); goto err; } rand_drbg_unlock(parent); } if (!RAND_DRBG_set_callbacks(drbg, rand_drbg_get_entropy, rand_drbg_cleanup_entropy, NULL, NULL)) goto err; return drbg; err: if (drbg->secure) OPENSSL_secure_free(drbg); else OPENSSL_free(drbg); return NULL; }
/* * Allocates a new global DRBG on the secure heap (if enabled) and * initializes it with default settings. * A global lock for the DRBG is created with the given name. * * Returns a pointer to the new DRBG instance on success, NULL on failure. */ static RAND_DRBG *drbg_setup(const char *name, RAND_DRBG *parent) { RAND_DRBG *drbg; if (name == NULL) { RANDerr(RAND_F_DRBG_SETUP, ERR_R_INTERNAL_ERROR); return NULL; } drbg = OPENSSL_secure_zalloc(sizeof(RAND_DRBG)); if (drbg == NULL) return NULL; drbg->lock = CRYPTO_THREAD_glock_new(name); if (drbg->lock == NULL) { RANDerr(RAND_F_DRBG_SETUP, RAND_R_FAILED_TO_CREATE_LOCK); goto err; } if (RAND_DRBG_set(drbg, RAND_DRBG_NID, RAND_DRBG_FLAG_CTR_USE_DF) != 1) goto err; if (RAND_DRBG_set_callbacks(drbg, rand_drbg_get_entropy, rand_drbg_cleanup_entropy, NULL, NULL) != 1) goto err; if (parent == NULL) { drbg->reseed_interval = MASTER_RESEED_INTERVAL; drbg->reseed_time_interval = MASTER_RESEED_TIME_INTERVAL; } else { drbg->parent = parent; drbg->reseed_interval = SLAVE_RESEED_INTERVAL; drbg->reseed_time_interval = SLAVE_RESEED_TIME_INTERVAL; } /* enable seed propagation */ drbg->reseed_counter = 1; /* * Ignore instantiation error so support just-in-time instantiation. * * The state of the drbg will be checked in RAND_DRBG_generate() and * an automatic recovery is attempted. */ RAND_DRBG_instantiate(drbg, (const unsigned char *) ossl_pers_string, sizeof(ossl_pers_string) - 1); return drbg; err: drbg_cleanup(drbg); return NULL; }
/* * Allocate memory and initialize a new DRBG. The DRBG is allocated on * the secure heap if |secure| is nonzero and the secure heap is enabled. * The |parent|, if not NULL, will be used as random source for reseeding. * * Returns a pointer to the new DRBG instance on success, NULL on failure. */ static RAND_DRBG *rand_drbg_new(int secure, int type, unsigned int flags, RAND_DRBG *parent) { RAND_DRBG *drbg = secure ? OPENSSL_secure_zalloc(sizeof(*drbg)) : OPENSSL_zalloc(sizeof(*drbg)); if (drbg == NULL) { RANDerr(RAND_F_RAND_DRBG_NEW, ERR_R_MALLOC_FAILURE); return NULL; } drbg->secure = secure && CRYPTO_secure_allocated(drbg); drbg->fork_count = rand_fork_count; drbg->parent = parent; if (parent == NULL) { drbg->get_entropy = rand_drbg_get_entropy; drbg->cleanup_entropy = rand_drbg_cleanup_entropy; #ifndef RAND_DRBG_GET_RANDOM_NONCE drbg->get_nonce = rand_drbg_get_nonce; drbg->cleanup_nonce = rand_drbg_cleanup_nonce; #endif drbg->reseed_interval = master_reseed_interval; drbg->reseed_time_interval = master_reseed_time_interval; } else { drbg->get_entropy = rand_drbg_get_entropy; drbg->cleanup_entropy = rand_drbg_cleanup_entropy; /* * Do not provide nonce callbacks, the child DRBGs will * obtain their nonce using random bits from the parent. */ drbg->reseed_interval = slave_reseed_interval; drbg->reseed_time_interval = slave_reseed_time_interval; } if (RAND_DRBG_set(drbg, type, flags) == 0) goto err; if (parent != NULL) { rand_drbg_lock(parent); if (drbg->strength > parent->strength) { /* * We currently don't support the algorithm from NIST SP 800-90C * 10.1.2 to use a weaker DRBG as source */ rand_drbg_unlock(parent); RANDerr(RAND_F_RAND_DRBG_NEW, RAND_R_PARENT_STRENGTH_TOO_WEAK); goto err; } rand_drbg_unlock(parent); } return drbg; err: if (drbg->secure) OPENSSL_secure_free(drbg); else OPENSSL_free(drbg); return NULL; }