}
/* If set is called multiple times - clear the old one */
- if (type != drbg->type && drbg->type != 0 && drbg->meth != NULL) {
+ if (drbg->type != 0 && (type != drbg->type || flags != drbg->flags)) {
drbg->meth->uninstantiate(drbg);
+ rand_pool_free(drbg->adin_pool);
+ drbg->adin_pool = NULL;
}
drbg->state = DRBG_UNINITIALISED;
if (type == 0) {
/* Uninitialized; that's okay. */
+ drbg->meth = NULL;
return 1;
} else if (is_ctr(type)) {
ret = drbg_ctr_init(drbg);
else
ret = drbg_hash_init(drbg);
} else {
+ drbg->type = 0;
+ drbg->flags = 0;
+ drbg->meth = NULL;
RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_UNSUPPORTED_DRBG_TYPE);
return 0;
}
- if (ret == 0)
+ if (ret == 0) {
+ drbg->state = DRBG_ERROR;
RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_ERROR_INITIALISING_DRBG);
+ }
return ret;
}
if (drbg->meth != NULL)
drbg->meth->uninstantiate(drbg);
+ rand_pool_free(drbg->adin_pool);
CRYPTO_THREAD_lock_free(drbg->lock);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG, drbg, &drbg->ex_data);
max_entropylen += drbg->max_noncelen;
}
+ drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter);
+ if (drbg->reseed_next_counter) {
+ drbg->reseed_next_counter++;
+ if(!drbg->reseed_next_counter)
+ drbg->reseed_next_counter = 1;
+ }
+
if (drbg->get_entropy != NULL)
entropylen = drbg->get_entropy(drbg, &entropy, min_entropy,
min_entropylen, max_entropylen, 0);
drbg->state = DRBG_READY;
drbg->reseed_gen_counter = 1;
drbg->reseed_time = time(NULL);
- if (drbg->reseed_prop_counter > 0) {
- if (drbg->parent == NULL)
- drbg->reseed_prop_counter++;
- else
- drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter;
- }
+ tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);
end:
if (entropy != NULL && drbg->cleanup_entropy != NULL)
drbg->cleanup_entropy(drbg, entropy, entropylen);
if (nonce != NULL && drbg->cleanup_nonce != NULL)
drbg->cleanup_nonce(drbg, nonce, noncelen);
- if (drbg->pool != NULL) {
- if (drbg->state == DRBG_READY) {
- RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
- RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED);
- drbg->state = DRBG_ERROR;
- }
- rand_pool_free(drbg->pool);
- drbg->pool = NULL;
- }
if (drbg->state == DRBG_READY)
return 1;
return 0;
}
drbg->state = DRBG_ERROR;
+
+ drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter);
+ if (drbg->reseed_next_counter) {
+ drbg->reseed_next_counter++;
+ if(!drbg->reseed_next_counter)
+ drbg->reseed_next_counter = 1;
+ }
+
if (drbg->get_entropy != NULL)
entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength,
drbg->min_entropylen,
drbg->state = DRBG_READY;
drbg->reseed_gen_counter = 1;
drbg->reseed_time = time(NULL);
- if (drbg->reseed_prop_counter > 0) {
- if (drbg->parent == NULL)
- drbg->reseed_prop_counter++;
- else
- drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter;
- }
+ tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);
end:
if (entropy != NULL && drbg->cleanup_entropy != NULL)
}
}
- /* check whether a given entropy pool was cleared properly during reseed */
- if (drbg->pool != NULL) {
- drbg->state = DRBG_ERROR;
- RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR);
- rand_pool_free(drbg->pool);
- drbg->pool = NULL;
- return 0;
- }
+ rand_pool_free(drbg->pool);
+ drbg->pool = NULL;
return drbg->state == DRBG_READY;
}
|| now - drbg->reseed_time >= drbg->reseed_time_interval)
reseed_required = 1;
}
- if (drbg->reseed_prop_counter > 0 && drbg->parent != NULL) {
- if (drbg->reseed_prop_counter != drbg->parent->reseed_prop_counter)
+ if (drbg->parent != NULL) {
+ unsigned int reseed_counter = tsan_load(&drbg->reseed_prop_counter);
+ if (reseed_counter > 0
+ && tsan_load(&drbg->parent->reseed_prop_counter)
+ != reseed_counter)
reseed_required = 1;
}
unsigned char *additional = NULL;
size_t additional_len;
size_t chunk;
- size_t ret;
+ size_t ret = 0;
+
+ if (drbg->adin_pool == NULL) {
+ if (drbg->type == 0)
+ goto err;
+ drbg->adin_pool = rand_pool_new(0, 0, drbg->max_adinlen);
+ if (drbg->adin_pool == NULL)
+ goto err;
+ }
- additional_len = rand_drbg_get_additional_data(&additional, drbg->max_adinlen);
+ additional_len = rand_drbg_get_additional_data(drbg->adin_pool,
+ &additional);
for ( ; outlen > 0; outlen -= chunk, out += chunk) {
chunk = outlen;
}
ret = 1;
-err:
- if (additional_len != 0)
- OPENSSL_secure_clear_free(additional, additional_len);
+ err:
+ if (additional != NULL)
+ rand_drbg_cleanup_additional_data(drbg->adin_pool, additional);
return ret;
}
RAND_DRBG_get_nonce_fn get_nonce,
RAND_DRBG_cleanup_nonce_fn cleanup_nonce)
{
- if (drbg->state != DRBG_UNINITIALISED)
+ if (drbg->state != DRBG_UNINITIALISED
+ || drbg->parent != NULL)
return 0;
drbg->get_entropy = get_entropy;
drbg->cleanup_entropy = cleanup_entropy;
goto err;
/* enable seed propagation */
- drbg->reseed_prop_counter = 1;
+ tsan_store(&drbg->reseed_prop_counter, 1);
/*
* Ignore instantiation error to support just-in-time instantiation.
int ret = 0;
RAND_DRBG *drbg = RAND_DRBG_get0_master();
size_t buflen;
- size_t seedlen = rand_drbg_seedlen(drbg);
+ 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) {
* 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];
- return RAND_DRBG_generate(drbg, dummy, sizeof(dummy), 0, buf, buflen);
+ 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
randomness = (double)seedlen;
}
- rand_drbg_lock(drbg);
ret = rand_drbg_restart(drbg, buf, buflen, (size_t)(8 * randomness));
rand_drbg_unlock(drbg);