Skip to content

Commit

Permalink
crypto: drbg - prepare for more fine-grained tracking of seeding state
Browse files Browse the repository at this point in the history
commit ce8ce31 upstream.

There are two different randomness sources the DRBGs are getting seeded
from, namely the jitterentropy source (if enabled) and get_random_bytes().
At initial DRBG seeding time during boot, the latter might not have
collected sufficient entropy for seeding itself yet and thus, the DRBG
implementation schedules a reseed work from a random_ready_callback once
that has happened. This is particularly important for the !->pr DRBG
instances, for which (almost) no further reseeds are getting triggered
during their lifetime.

Because collecting data from the jitterentropy source is a rather expensive
operation, the aforementioned asynchronously scheduled reseed work
restricts itself to get_random_bytes() only. That is, it in some sense
amends the initial DRBG seed derived from jitterentropy output at full
(estimated) entropy with fresh randomness obtained from get_random_bytes()
once that has been seeded with sufficient entropy itself.

With the advent of rng_is_initialized(), there is no real need for doing
the reseed operation from an asynchronously scheduled work anymore and a
subsequent patch will make it synchronous by moving it next to related
logic already present in drbg_generate().

However, for tracking whether a full reseed including the jitterentropy
source is required or a "partial" reseed involving only get_random_bytes()
would be sufficient already, the boolean struct drbg_state's ->seeded
member must become a tristate value.

Prepare for this by introducing the new enum drbg_seed_state and change
struct drbg_state's ->seeded member's type from bool to that type.

For facilitating review, enum drbg_seed_state is made to only contain
two members corresponding to the former ->seeded values of false and true
resp. at this point: DRBG_SEED_STATE_UNSEEDED and DRBG_SEED_STATE_FULL. A
third one for tracking the intermediate state of "seeded from jitterentropy
only" will be introduced with a subsequent patch.

There is no change in behaviour at this point.

Signed-off-by: Nicolai Stange <nstange@suse.de>
Reviewed-by: Stephan Müller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
nicstange authored and gregkh committed Jun 6, 2022
1 parent e16cc79 commit fa99680
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 10 deletions.
19 changes: 10 additions & 9 deletions crypto/drbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1043,7 +1043,7 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
if (ret)
return ret;

drbg->seeded = true;
drbg->seeded = DRBG_SEED_STATE_FULL;
/* 10.1.1.2 / 10.1.1.3 step 5 */
drbg->reseed_ctr = 1;

Expand Down Expand Up @@ -1088,14 +1088,14 @@ static void drbg_async_seed(struct work_struct *work)
if (ret)
goto unlock;

/* Set seeded to false so that if __drbg_seed fails the
* next generate call will trigger a reseed.
/* Reset ->seeded so that if __drbg_seed fails the next
* generate call will trigger a reseed.
*/
drbg->seeded = false;
drbg->seeded = DRBG_SEED_STATE_UNSEEDED;

__drbg_seed(drbg, &seedlist, true);

if (drbg->seeded)
if (drbg->seeded == DRBG_SEED_STATE_FULL)
drbg->reseed_threshold = drbg_max_requests(drbg);

unlock:
Expand Down Expand Up @@ -1386,13 +1386,14 @@ static int drbg_generate(struct drbg_state *drbg,
* here. The spec is a bit convoluted here, we make it simpler.
*/
if (drbg->reseed_threshold < drbg->reseed_ctr)
drbg->seeded = false;
drbg->seeded = DRBG_SEED_STATE_UNSEEDED;

if (drbg->pr || !drbg->seeded) {
if (drbg->pr || drbg->seeded == DRBG_SEED_STATE_UNSEEDED) {
pr_devel("DRBG: reseeding before generation (prediction "
"resistance: %s, state %s)\n",
drbg->pr ? "true" : "false",
drbg->seeded ? "seeded" : "unseeded");
(drbg->seeded == DRBG_SEED_STATE_FULL ?
"seeded" : "unseeded"));
/* 9.3.1 steps 7.1 through 7.3 */
len = drbg_seed(drbg, addtl, true);
if (len)
Expand Down Expand Up @@ -1577,7 +1578,7 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
if (!drbg->core) {
drbg->core = &drbg_cores[coreref];
drbg->pr = pr;
drbg->seeded = false;
drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
drbg->reseed_threshold = drbg_max_requests(drbg);

ret = drbg_alloc_state(drbg);
Expand Down
7 changes: 6 additions & 1 deletion include/crypto/drbg.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ struct drbg_test_data {
struct drbg_string *testentropy; /* TEST PARAMETER: test entropy */
};

enum drbg_seed_state {
DRBG_SEED_STATE_UNSEEDED,
DRBG_SEED_STATE_FULL,
};

struct drbg_state {
struct mutex drbg_mutex; /* lock around DRBG */
unsigned char *V; /* internal state 10.1.1.1 1a) */
Expand All @@ -127,7 +132,7 @@ struct drbg_state {
struct crypto_wait ctr_wait; /* CTR mode async wait obj */
struct scatterlist sg_in, sg_out; /* CTR mode SGLs */

bool seeded; /* DRBG fully seeded? */
enum drbg_seed_state seeded; /* DRBG fully seeded? */
bool pr; /* Prediction resistance enabled? */
bool fips_primed; /* Continuous test primed? */
unsigned char *prev; /* FIPS 140-2 continuous test value */
Expand Down

0 comments on commit fa99680

Please sign in to comment.