* LOCKING
*
* The three shared DRBGs are intended to be used concurrently, so they
- * support locking by default. It is the callers responsibility to wrap
- * calls to functions like RAND_DRBG_generate() which modify the DRBGs
- * internal state with calls to RAND_DRBG_lock() and RAND_DRBG_unlock().
- * The functions RAND_bytes() and RAND_priv_bytes() take the locks
- * automatically, so using the RAND api is thread safe as before.
- *
- * All other DRBG instances don't have locking enabled by default, because
- * they are intendended to be used by a single thread. If it is desired,
- * locking can be enabled using RAND_DRBG_enable_locking(). However, instead
- * of accessing a single DRBG instance concurrently from different threads,
- * it is recommended to instantiate a separate DRBG instance per thread.
+ * support locking. The RAND methods take the locks automatically, so using
+ * the RAND api (in particular RAND_bytes() and RAND_priv_bytes()) is
+ * thread-safe. Note however that accessing the shared DRBGs directly via
+ * the RAND_DRBG interface is *not* thread-safe.
+ *
+ * All other DRBG instances don't support locking, because they are
+ * intendended to be used by a single thread. Instead of accessing a single
+ * DRBG instance concurrently from different threads, it is recommended to
+ * instantiate a separate DRBG instance per thread. Using the same shared
+ * DRBG (preferrably the public DRBG) as parent of DRBG instances on
+ * different threads is safe.
*/
static CRYPTO_ONCE rand_drbg_init = CRYPTO_ONCE_STATIC_INIT;
+static unsigned int master_reseed_interval = MASTER_RESEED_INTERVAL;
+static unsigned int slave_reseed_interval = SLAVE_RESEED_INTERVAL;
+
+static time_t master_reseed_time_interval = MASTER_RESEED_TIME_INTERVAL;
+static time_t slave_reseed_time_interval = SLAVE_RESEED_TIME_INTERVAL;
+
static RAND_DRBG *drbg_setup(RAND_DRBG *parent);
static RAND_DRBG *rand_drbg_new(int secure,
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 && 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
+ */
+ RANDerr(RAND_F_RAND_DRBG_NEW, RAND_R_PARENT_STRENGTH_TOO_WEAK);
+ goto err;
+ }
+
if (!RAND_DRBG_set_callbacks(drbg, rand_drbg_get_entropy,
rand_drbg_cleanup_entropy,
NULL, NULL))
RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED);
drbg->state = DRBG_ERROR;
}
- RAND_POOL_free(drbg->pool);
+ rand_pool_free(drbg->pool);
drbg->pool = NULL;
}
if (drbg->state == DRBG_READY)
if (drbg->pool != NULL) {
RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR);
- RAND_POOL_free(drbg->pool);
+ rand_pool_free(drbg->pool);
drbg->pool = NULL;
}
}
/* will be picked up by the rand_drbg_get_entropy() callback */
- drbg->pool = RAND_POOL_new(entropy, len, len);
+ drbg->pool = rand_pool_new(entropy, len, len);
if (drbg->pool == NULL)
return 0;
- RAND_POOL_add(drbg->pool, buffer, len, entropy);
+ rand_pool_add(drbg->pool, buffer, len, entropy);
} else {
if (drbg->max_adinlen < len) {
RANDerr(RAND_F_RAND_DRBG_RESTART,
if (drbg->pool != NULL) {
drbg->state = DRBG_ERROR;
RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR);
- RAND_POOL_free(drbg->pool);
+ rand_pool_free(drbg->pool);
drbg->pool = NULL;
return 0;
}
return 1;
}
+/*
+ * Set the default values for reseed (time) intervals of new DRBG instances
+ *
+ * The default values can be set independently for master DRBG instances
+ * (without a parent) and slave DRBG instances (with parent).
+ *
+ * Returns 1 on success, 0 on failure.
+ */
+
+int RAND_DRBG_set_reseed_defaults(
+ unsigned int _master_reseed_interval,
+ unsigned int _slave_reseed_interval,
+ time_t _master_reseed_time_interval,
+ time_t _slave_reseed_time_interval
+ )
+{
+ if (_master_reseed_interval > MAX_RESEED_INTERVAL
+ || _slave_reseed_interval > MAX_RESEED_INTERVAL)
+ return 0;
+
+ if (_master_reseed_time_interval > MAX_RESEED_TIME_INTERVAL
+ || _slave_reseed_time_interval > MAX_RESEED_TIME_INTERVAL)
+ return 0;
+
+ master_reseed_interval = _master_reseed_interval;
+ slave_reseed_interval = _slave_reseed_interval;
+
+ master_reseed_time_interval = _master_reseed_time_interval;
+ slave_reseed_time_interval = _slave_reseed_time_interval;
+
+ return 1;
+}
/*
* Locks the given drbg. Locking a drbg which does not have locking
*
* Returns 1 on success, 0 on failure.
*/
-int RAND_DRBG_lock(RAND_DRBG *drbg)
+int rand_drbg_lock(RAND_DRBG *drbg)
{
if (drbg->lock != NULL)
return CRYPTO_THREAD_write_lock(drbg->lock);
*
* Returns 1 on success, 0 on failure.
*/
-int RAND_DRBG_unlock(RAND_DRBG *drbg)
+int rand_drbg_unlock(RAND_DRBG *drbg)
{
if (drbg->lock != NULL)
return CRYPTO_THREAD_unlock(drbg->lock);
*
* Returns 1 on success, 0 on failure.
*/
-int RAND_DRBG_enable_locking(RAND_DRBG *drbg)
+int rand_drbg_enable_locking(RAND_DRBG *drbg)
{
if (drbg->state != DRBG_UNINITIALISED) {
RANDerr(RAND_F_RAND_DRBG_ENABLE_LOCKING,
{
RAND_DRBG *drbg;
- drbg = RAND_DRBG_secure_new(RAND_DRBG_NID, RAND_DRBG_FLAG_CTR_USE_DF, parent);
+ drbg = RAND_DRBG_secure_new(RAND_DRBG_NID, 0, parent);
if (drbg == NULL)
return NULL;
- if (RAND_DRBG_enable_locking(drbg) == 0)
+ if (rand_drbg_enable_locking(drbg) == 0)
goto err;
- 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;
- }
-
/* enable seed propagation */
drbg->reseed_counter = 1;
if (drbg == NULL)
return 0;
- RAND_DRBG_lock(drbg);
+ rand_drbg_lock(drbg);
ret = RAND_DRBG_bytes(drbg, out, count);
- RAND_DRBG_unlock(drbg);
+ rand_drbg_unlock(drbg);
return ret;
}
return 0;
}
- RAND_DRBG_lock(drbg);
+ rand_drbg_lock(drbg);
ret = rand_drbg_restart(drbg, buf,
(size_t)(unsigned int)num,
(size_t)(8*randomness));
- RAND_DRBG_unlock(drbg);
+ rand_drbg_unlock(drbg);
return ret;
}
if (drbg == NULL)
return 0;
- RAND_DRBG_lock(drbg);
+ rand_drbg_lock(drbg);
ret = drbg->state == DRBG_READY ? 1 : 0;
- RAND_DRBG_unlock(drbg);
+ rand_drbg_unlock(drbg);
return ret;
}