Latest update
This commit is contained in:
+102
-39
@@ -374,6 +374,13 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
|
||||
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);
|
||||
@@ -401,27 +408,13 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
|
||||
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;
|
||||
@@ -498,6 +491,14 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg,
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -515,12 +516,7 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg,
|
||||
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)
|
||||
@@ -625,14 +621,8 @@ int rand_drbg_restart(RAND_DRBG *drbg,
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
@@ -691,8 +681,11 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
|
||||
|| 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;
|
||||
}
|
||||
|
||||
@@ -764,7 +757,8 @@ int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
|
||||
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;
|
||||
@@ -942,7 +936,7 @@ static RAND_DRBG *drbg_setup(RAND_DRBG *parent, int drbg_type)
|
||||
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.
|
||||
@@ -1031,11 +1025,53 @@ static int drbg_bytes(unsigned char *out, int count)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculates the minimum length of a full entropy buffer
|
||||
* which is necessary to seed (i.e. instantiate) the DRBG
|
||||
* successfully.
|
||||
*
|
||||
* NOTE: There is a copy of this function in drbgtest.c.
|
||||
* If you change anything here, you need to update
|
||||
* the copy accordingly.
|
||||
*/
|
||||
static size_t rand_drbg_seedlen(RAND_DRBG *drbg)
|
||||
{
|
||||
/*
|
||||
* If no os entropy source is available then RAND_seed(buffer, bufsize)
|
||||
* is expected to succeed if and only if the buffer length satisfies
|
||||
* the following requirements, which follow from the calculations
|
||||
* in RAND_DRBG_instantiate().
|
||||
*/
|
||||
size_t min_entropy = drbg->strength;
|
||||
size_t min_entropylen = drbg->min_entropylen;
|
||||
|
||||
/*
|
||||
* Extra entropy for the random nonce in the absence of a
|
||||
* get_nonce callback, see comment in RAND_DRBG_instantiate().
|
||||
*/
|
||||
if (drbg->min_noncelen > 0 && drbg->get_nonce == NULL) {
|
||||
min_entropy += drbg->strength / 2;
|
||||
min_entropylen += drbg->min_noncelen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert entropy requirement from bits to bytes
|
||||
* (dividing by 8 without rounding upwards, because
|
||||
* all entropy requirements are divisible by 8).
|
||||
*/
|
||||
min_entropy >>= 3;
|
||||
|
||||
/* Return a value that satisfies both requirements */
|
||||
return min_entropy > min_entropylen ? min_entropy : min_entropylen;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
@@ -1043,7 +1079,37 @@ static int drbg_add(const void *buf, int num, double randomness)
|
||||
if (num < 0 || randomness < 0.0)
|
||||
return 0;
|
||||
|
||||
if (randomness > (double)RAND_DRBG_STRENGTH) {
|
||||
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
|
||||
@@ -1052,13 +1118,10 @@ static int drbg_add(const void *buf, int num, double randomness)
|
||||
* not bits, so this value corresponds to eight times the
|
||||
* security strength.
|
||||
*/
|
||||
randomness = (double)RAND_DRBG_STRENGTH;
|
||||
randomness = (double)seedlen;
|
||||
}
|
||||
|
||||
rand_drbg_lock(drbg);
|
||||
ret = rand_drbg_restart(drbg, buf,
|
||||
(size_t)(unsigned int)num,
|
||||
(size_t)(8*randomness));
|
||||
ret = rand_drbg_restart(drbg, buf, buflen, (size_t)(8 * randomness));
|
||||
rand_drbg_unlock(drbg);
|
||||
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user