diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2017-03-15 14:21:43 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2017-03-16 10:46:46 +0000 |
commit | d51cf4283f8fbe2acc6e7b6b3b1dec86f10f0d5a (patch) | |
tree | 308674bf659c1cffba33911f4d45259af60eb3c6 /lib/nettle | |
parent | 591a082c6deaa469bb192eaaf83b632046cf46e1 (diff) | |
download | gnutls-d51cf4283f8fbe2acc6e7b6b3b1dec86f10f0d5a.tar.gz |
nettle/rnd: introduced time limit for key generator
That is, force re-key of the KEY and RANDOM PRNG after 2 hours
of operation, irrespective of the amount of data having been output.
At the same time, increase limits for key and nonce generators,
to prevent a large amount of system calls in busy servers.
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
Diffstat (limited to 'lib/nettle')
-rw-r--r-- | lib/nettle/rnd.c | 43 |
1 files changed, 34 insertions, 9 deletions
diff --git a/lib/nettle/rnd.c b/lib/nettle/rnd.c index 71390645ea..b7d53b69ca 100644 --- a/lib/nettle/rnd.c +++ b/lib/nettle/rnd.c @@ -39,22 +39,33 @@ * 'Using GnuTLS as a cryptographic library'. */ -/* after this number of bytes PRNG will rekey */ +/* We have two "refresh" operations for the PRNG: + * re-seed: the random generator obtains a new key from the system or another PRNG + * (occurs when a time or data-based limit is reached for the GNUTLS_RND_RANDOM + * and GNUTLS_RND_KEY levels and data-based for the nonce level) + * re-key: the random generator obtains a new key by utilizing its own output. + * This only happens for the GNUTLS_RND_KEY level, on every operation. + */ + +/* after this number of bytes PRNG will rekey using the system RNG */ static const unsigned prng_reseed_limits[] = { - [GNUTLS_RND_NONCE] = 1024*1024, /* 1 MB */ - [GNUTLS_RND_RANDOM] = 16*1024, /* 16 kb */ - [GNUTLS_RND_KEY] = 16*1024 /* same as GNUTLS_RND_RANDOM */ + [GNUTLS_RND_NONCE] = 16*1024*1024, /* 16 MB - we re-seed using the GNUTLS_RND_RANDOM output */ + [GNUTLS_RND_RANDOM] = 2*1024*1024, /* 2MB - we re-seed by time as well */ + [GNUTLS_RND_KEY] = 2*1024*1024 /* same as GNUTLS_RND_RANDOM - but we re-key on every operation */ }; +#define NON_NONCE_PRNG_RESEED_TIME 7200 + struct prng_ctx_st { struct chacha_ctx ctx; size_t counter; unsigned int forkid; + time_t last_reseed; }; struct generators_ctx_st { struct prng_ctx_st nonce; /* GNUTLS_RND_NONCE */ - struct prng_ctx_st normal; /* GNUTLS_RND_RANDOM */ + struct prng_ctx_st normal; /* GNUTLS_RND_RANDOM, GNUTLS_RND_KEY */ }; @@ -93,6 +104,7 @@ static int single_prng_init(struct prng_ctx_st *ctx, gettime(&now); memcpy(nonce, &now, MIN(sizeof(nonce), sizeof(now))); + ctx->last_reseed = now.tv_sec; } chacha_set_key(&ctx->ctx, new_key); @@ -161,20 +173,33 @@ wrap_nettle_rnd(void *_ctx, int level, void *data, size_t datasize) return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED); - /* we don't really need memset here, but otherwise we - * get filled with valgrind warnings */ + /* Two reasons for this memset(): + * 1. avoid getting filled with valgrind warnings + * 2. avoid a cipher/PRNG failure to expose stack data + */ memset(data, 0, datasize); if (_gnutls_detect_fork(prng_ctx->forkid)) { reseed = 1; + + } else if (level != GNUTLS_RND_NONCE) { + /* for KEY and RANDOM levels we re-seed based on time in + * addition to data. That is, to prevent a temporal state + * compromise to become permanent for low traffic sites */ + time_t now = gnutls_time(0); + if (now > prng_ctx->last_reseed + NON_NONCE_PRNG_RESEED_TIME) { + reseed = 1; + prng_ctx->last_reseed = now; + } } if (reseed != 0 || prng_ctx->counter > prng_reseed_limits[level]) { if (level == GNUTLS_RND_NONCE) { ret = wrap_nettle_rnd(_ctx, GNUTLS_RND_RANDOM, new_key, sizeof(new_key)); } else { - /* we use the system entropy for KEY and RANDOM to reduce - * the impact of a temporal state compromise for these two levels. */ + + /* we also use the system entropy to reduce the impact + * of a temporal state compromise for these two levels. */ ret = _rnd_get_system_entropy(new_key, sizeof(new_key)); } |