summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorDr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>2017-11-24 15:24:51 +0100
committerDr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>2017-12-17 23:12:10 +0100
commit08a65d9686b131cb4193feaaf1d5cef941fa349c (patch)
tree6467db5ba5045774298f462969fb139489953793 /crypto
parenta93ba405b0327db9106f8f224112a2b64fb264e7 (diff)
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)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/rand/drbg_lib.c59
-rw-r--r--crypto/rand/rand_lcl.h14
2 files changed, 58 insertions, 15 deletions
diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c
index 67a79d4efe..13dce3057c 100644
--- a/crypto/rand/drbg_lib.c
+++ b/crypto/rand/drbg_lib.c
@@ -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.
*/
@@ -572,6 +583,24 @@ int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, unsigned int interval)
}
/*
+ * 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
*/
int RAND_DRBG_set_ex_data(RAND_DRBG *drbg, int idx, void *arg)
@@ -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 */
diff --git a/crypto/rand/rand_lcl.h b/crypto/rand/rand_lcl.h
index ad79434ec4..9044981bbb 100644
--- a/crypto/rand/rand_lcl.h
+++ b/crypto/rand/rand_lcl.h
@@ -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.