Implement automatic reseeding of DRBG after a specified time interval
Every DRBG now supports automatic reseeding not only after a given number of generate requests, but also after a specified time interval. Signed-off-by: Dr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com> Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> (Merged from https://github.com/openssl/openssl/pull/4402)
This commit is contained in:
parent
a93ba405b0
commit
08a65d9686
5 changed files with 73 additions and 15 deletions
|
@ -72,18 +72,24 @@ static RAND_DRBG drbg_private;
|
|||
*
|
||||
* AUTOMATIC RESEEDING
|
||||
*
|
||||
* Before satisfying a generate request, a DRBG reseeds itself automatically
|
||||
* if the number of generate requests since the last reseeding exceeds a
|
||||
* certain threshold, the so called |reseed_interval|. This automatic
|
||||
* reseeding can be disabled by setting the |reseed_interval| to 0.
|
||||
* Before satisfying a generate request, a DRBG reseeds itself automatically,
|
||||
* if one of the following two conditions holds:
|
||||
*
|
||||
* - the number of generate requests since the last reseeding exceeds a
|
||||
* certain threshold, the so called |reseed_interval|. This behaviour
|
||||
* can be disabled by setting the |reseed_interval| to 0.
|
||||
*
|
||||
* - the time elapsed since the last reseeding exceeds a certain time
|
||||
* interval, the so called |reseed_time_interval|. This behaviour
|
||||
* can be disabled by setting the |reseed_time_interval| to 0.
|
||||
*
|
||||
* MANUAL RESEEDING
|
||||
*
|
||||
* For the three shared DRBGs (and only for these) there is a way to reseed
|
||||
* them manually by calling RAND_seed() (or RAND_add() with a positive
|
||||
* For the three shared DRBGs (and only for these) there is another way to
|
||||
* reseed them manually by calling RAND_seed() (or RAND_add() with a positive
|
||||
* |randomness| argument). This will immediately reseed the <master> DRBG.
|
||||
* Its immediate children (<public> and <private> DRBG) will detect this
|
||||
* on their next generate call and reseed, pulling randomness from <master>.
|
||||
* The <public> and <private> DRBG will detect this on their next generate
|
||||
* call and reseed, pulling randomness from <master>.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -222,7 +228,7 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
|
|||
|
||||
drbg->state = DRBG_READY;
|
||||
drbg->generate_counter = 0;
|
||||
|
||||
drbg->reseed_time = time(NULL);
|
||||
if (drbg->reseed_counter > 0) {
|
||||
if (drbg->parent == NULL)
|
||||
drbg->reseed_counter++;
|
||||
|
@ -304,7 +310,7 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg,
|
|||
|
||||
drbg->state = DRBG_READY;
|
||||
drbg->generate_counter = 0;
|
||||
|
||||
drbg->reseed_time = time(NULL);
|
||||
if (drbg->reseed_counter > 0) {
|
||||
if (drbg->parent == NULL)
|
||||
drbg->reseed_counter++;
|
||||
|
@ -475,7 +481,12 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
|
|||
if (drbg->generate_counter >= drbg->reseed_interval)
|
||||
reseed_required = 1;
|
||||
}
|
||||
|
||||
if (drbg->reseed_time_interval > 0) {
|
||||
time_t now = time(NULL);
|
||||
if (now < drbg->reseed_time
|
||||
|| now - drbg->reseed_time >= drbg->reseed_time_interval)
|
||||
reseed_required = 1;
|
||||
}
|
||||
if (drbg->reseed_counter > 0 && drbg->parent != NULL) {
|
||||
if (drbg->reseed_counter != drbg->parent->reseed_counter)
|
||||
reseed_required = 1;
|
||||
|
@ -559,7 +570,7 @@ int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
|
|||
*
|
||||
* The drbg will reseed automatically whenever the number of generate
|
||||
* requests exceeds the given reseed interval. If the reseed interval
|
||||
* is 0, then this automatic reseeding is disabled.
|
||||
* is 0, then this feature is disabled.
|
||||
*
|
||||
* Returns 1 on success, 0 on failure.
|
||||
*/
|
||||
|
@ -571,6 +582,24 @@ int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, unsigned int interval)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the reseed time interval.
|
||||
*
|
||||
* The drbg will reseed automatically whenever the time elapsed since
|
||||
* the last reseeding exceeds the given reseed time interval. For safety,
|
||||
* a reseeding will also occur if the clock has been reset to a smaller
|
||||
* value.
|
||||
*
|
||||
* Returns 1 on success, 0 on failure.
|
||||
*/
|
||||
int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg, time_t interval)
|
||||
{
|
||||
if (interval > MAX_RESEED_TIME_INTERVAL)
|
||||
return 0;
|
||||
drbg->reseed_time_interval = interval;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get and set the EXDATA
|
||||
*/
|
||||
|
@ -616,11 +645,13 @@ static int drbg_setup(RAND_DRBG *drbg, const char *name, RAND_DRBG *parent)
|
|||
ret &= RAND_DRBG_set_callbacks(drbg, rand_drbg_get_entropy,
|
||||
rand_drbg_cleanup_entropy, NULL, NULL) == 1;
|
||||
|
||||
if (parent == NULL)
|
||||
if (parent == NULL) {
|
||||
drbg->reseed_interval = MASTER_RESEED_INTERVAL;
|
||||
else {
|
||||
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 */
|
||||
|
|
|
@ -20,12 +20,17 @@
|
|||
/* How many times to read the TSC as a randomness source. */
|
||||
# define TSC_READ_COUNT 4
|
||||
|
||||
/* Maximum reseed interval */
|
||||
/* Maximum reseed intervals */
|
||||
# define MAX_RESEED_INTERVAL (1 << 24)
|
||||
# define MAX_RESEED_TIME_INTERVAL (1 << 20) /* approx. 12 days */
|
||||
|
||||
/* Default reseed intervals */
|
||||
# define MASTER_RESEED_INTERVAL (1 << 8)
|
||||
# define SLAVE_RESEED_INTERVAL (1 << 16)
|
||||
# define MASTER_RESEED_TIME_INTERVAL (60*60) /* 1 hour */
|
||||
# define SLAVE_RESEED_TIME_INTERVAL (7*60) /* 7 minutes */
|
||||
|
||||
|
||||
|
||||
/* Max size of additional input and personalization string. */
|
||||
# define DRBG_MAX_LENGTH 4096
|
||||
|
@ -118,6 +123,13 @@ struct rand_drbg_st {
|
|||
* This value is ignored if it is zero.
|
||||
*/
|
||||
unsigned int reseed_interval;
|
||||
/* Stores the time when the last reseeding occurred */
|
||||
time_t reseed_time;
|
||||
/*
|
||||
* Specifies the maximum time interval (in seconds) between reseeds.
|
||||
* This value is ignored if it is zero.
|
||||
*/
|
||||
time_t reseed_time_interval;
|
||||
/*
|
||||
* Counts the number of reseeds since instantiation.
|
||||
* This value is ignored if it is zero.
|
||||
|
|
|
@ -43,6 +43,7 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
|
|||
int prediction_resistance,
|
||||
const unsigned char *adin, size_t adinlen);
|
||||
int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, unsigned int interval);
|
||||
int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg, time_t interval);
|
||||
|
||||
RAND_DRBG *RAND_DRBG_get0_master(void);
|
||||
RAND_DRBG *RAND_DRBG_get0_public(void);
|
||||
|
|
|
@ -573,6 +573,7 @@ static int test_drbg_reseed(int expect_success,
|
|||
)
|
||||
{
|
||||
unsigned char buf[32];
|
||||
time_t before_reseed, after_reseed;
|
||||
int expected_state = (expect_success ? DRBG_READY : DRBG_ERROR);
|
||||
|
||||
/*
|
||||
|
@ -595,9 +596,11 @@ static int test_drbg_reseed(int expect_success,
|
|||
*/
|
||||
|
||||
/* Generate random output from the public and private DRBG */
|
||||
before_reseed = expect_master_reseed == 1 ? time(NULL) : 0;
|
||||
if (!TEST_int_eq(RAND_bytes(buf, sizeof(buf)), expect_success)
|
||||
|| !TEST_int_eq(RAND_priv_bytes(buf, sizeof(buf)), expect_success))
|
||||
return 0;
|
||||
after_reseed = time(NULL);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -633,6 +636,16 @@ static int test_drbg_reseed(int expect_success,
|
|||
if (!TEST_int_eq(public->reseed_counter, master->reseed_counter)
|
||||
|| !TEST_int_eq(private->reseed_counter, master->reseed_counter))
|
||||
return 0;
|
||||
|
||||
/* Test whether reseed time of master DRBG is set correctly */
|
||||
if (!TEST_time_t_le(before_reseed, master->reseed_time)
|
||||
|| !TEST_time_t_le(master->reseed_time, after_reseed))
|
||||
return 0;
|
||||
|
||||
/* Test whether reseed times of child DRBGs are synchronized with master */
|
||||
if (!TEST_time_t_ge(public->reseed_time, master->reseed_time)
|
||||
|| !TEST_time_t_ge(private->reseed_time, master->reseed_time))
|
||||
return 0;
|
||||
} else {
|
||||
ERR_clear_error();
|
||||
}
|
||||
|
|
|
@ -4447,3 +4447,4 @@ RSA_get_version 4391 1_1_1 EXIST::FUNCTION:RSA
|
|||
RSA_meth_get_multi_prime_keygen 4392 1_1_1 EXIST::FUNCTION:RSA
|
||||
RSA_meth_set_multi_prime_keygen 4393 1_1_1 EXIST::FUNCTION:RSA
|
||||
RAND_DRBG_get0_master 4394 1_1_1 EXIST::FUNCTION:
|
||||
RAND_DRBG_set_reseed_time_interval 4395 1_1_1 EXIST::FUNCTION:
|
||||
|
|
Loading…
Reference in a new issue