lkml.org 
[lkml]   [2022]   [Jun]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 20/66] crypto: drbg - prepare for more fine-grained tracking of seeding state
    Date
    From: Nicolai Stange <nstange@suse.de>

    commit ce8ce31b2c5c8b18667784b8c515650c65d57b4e 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>
    ---
    crypto/drbg.c | 19 ++++++++++---------
    include/crypto/drbg.h | 7 ++++++-
    2 files changed, 16 insertions(+), 10 deletions(-)

    --- a/crypto/drbg.c
    +++ b/crypto/drbg.c
    @@ -1043,7 +1043,7 @@ static inline int __drbg_seed(struct drb
    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;

    @@ -1088,14 +1088,14 @@ static void drbg_async_seed(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:
    @@ -1386,13 +1386,14 @@ static int drbg_generate(struct drbg_sta
    * 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)
    @@ -1577,7 +1578,7 @@ static int drbg_instantiate(struct drbg_
    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);
    --- a/include/crypto/drbg.h
    +++ b/include/crypto/drbg.h
    @@ -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) */
    @@ -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 */

    \
     
     \ /
      Last update: 2022-06-03 20:01    [W:4.732 / U:0.000 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site