]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
crypto: drbg - Consolidate "instantiate" logic and remove drbg_state::C
authorEric Biggers <ebiggers@kernel.org>
Mon, 20 Apr 2026 06:34:10 +0000 (23:34 -0700)
committerHerbert Xu <herbert@gondor.apana.org.au>
Thu, 7 May 2026 08:10:01 +0000 (16:10 +0800)
Currently some of the steps of "Instantiate the DRBG" occur in a
convoluted way in different places in the call stack:

drbg_instantiate()

    => drbg_seed(reseed=0) sets the raw HMAC key drbg_state::C to its
       correct initial value, and it sets the state value
       drbg_state::V to an *incorrect* initial value.

        => drbg_hmac_update(reseed=0) overwrites drbg_state::V with the
           correct initial value, then prepares the hmac_sha512_key
           drbg_state::key from the initial raw HMAC key drbg_state::C.

Later, each time the HMAC key is updated, drbg_hmac_update() also uses
drbg_state::C to temporarily store the new raw key.

Simplify all of this by:

    - Making drbg_instantiate() set the correct initial values of
      drbg_state::V and drbg_state::key.

    - Converting drbg_hmac_update() to generate the raw key in a
      temporary on-stack array instead of drbg_state::C.

    - Removing drbg_state::C.

Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
crypto/drbg.c

index 439581d7bb83d8ce8e0b88c36e51a9595da135d3..7e3ab2f811b6071b51e1a2b88bf9357cabc01c05 100644 (file)
@@ -136,7 +136,6 @@ struct drbg_state {
        struct mutex drbg_mutex;        /* lock around DRBG */
        u8 V[DRBG_STATE_LEN];           /* internal state -- 10.1.2.1 1a */
        struct hmac_sha512_key key;     /* current key -- 10.1.2.1 1b */
-       u8 C[DRBG_STATE_LEN];           /* current key -- 10.1.2.1 1b */
        /* Number of RNG requests since last reseed -- 10.1.2.1 1c */
        size_t reseed_ctr;
        size_t reseed_threshold;
@@ -160,17 +159,11 @@ static int drbg_uninstantiate(struct drbg_state *drbg);
  ******************************************************************/
 
 /* update function of HMAC DRBG as defined in 10.1.2.2 */
-static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
-                            int reseed)
+static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed)
 {
        int i = 0;
        struct hmac_sha512_ctx hmac_ctx;
-
-       if (!reseed) {
-               /* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */
-               memset(drbg->V, 1, DRBG_STATE_LEN);
-               hmac_sha512_preparekey(&drbg->key, drbg->C, DRBG_STATE_LEN);
-       }
+       u8 new_key[DRBG_STATE_LEN];
 
        for (i = 2; 0 < i; i--) {
                /* first round uses 0x0, second 0x1 */
@@ -188,8 +181,8 @@ static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
                                hmac_sha512_update(&hmac_ctx, input->buf,
                                                   input->len);
                }
-               hmac_sha512_final(&hmac_ctx, drbg->C);
-               hmac_sha512_preparekey(&drbg->key, drbg->C, DRBG_STATE_LEN);
+               hmac_sha512_final(&hmac_ctx, new_key);
+               hmac_sha512_preparekey(&drbg->key, new_key, DRBG_STATE_LEN);
 
                /* 10.1.2.2 step 2 and 5 -- HMAC for V */
                hmac_sha512(&drbg->key, drbg->V, DRBG_STATE_LEN, drbg->V);
@@ -198,6 +191,7 @@ static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
                if (!seed)
                        break;
        }
+       memzero_explicit(new_key, sizeof(new_key));
 }
 
 /* generate function of HMAC DRBG as defined in 10.1.2.5 */
@@ -210,7 +204,7 @@ static void drbg_hmac_generate(struct drbg_state *drbg,
 
        /* 10.1.2.5 step 2 */
        if (addtl && !list_empty(addtl))
-               drbg_hmac_update(drbg, addtl, 1);
+               drbg_hmac_update(drbg, addtl);
 
        while (len < buflen) {
                unsigned int outlen = 0;
@@ -227,15 +221,15 @@ static void drbg_hmac_generate(struct drbg_state *drbg,
 
        /* 10.1.2.5 step 6 */
        if (addtl && !list_empty(addtl))
-               drbg_hmac_update(drbg, addtl, 1);
+               drbg_hmac_update(drbg, addtl);
        else
-               drbg_hmac_update(drbg, NULL, 1);
+               drbg_hmac_update(drbg, NULL);
 }
 
 static inline void __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
-                              int reseed, enum drbg_seed_state new_seed_state)
+                              enum drbg_seed_state new_seed_state)
 {
-       drbg_hmac_update(drbg, seed, reseed);
+       drbg_hmac_update(drbg, seed);
 
        drbg->seeded = new_seed_state;
        drbg->last_seed_time = jiffies;
@@ -275,7 +269,7 @@ static void drbg_seed_from_random(struct drbg_state *drbg)
 
        get_random_bytes(entropy, DRBG_SEC_STRENGTH);
 
-       __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL);
+       __drbg_seed(drbg, &seedlist, DRBG_SEED_STATE_FULL);
 
        memzero_explicit(entropy, DRBG_SEC_STRENGTH);
 }
@@ -404,12 +398,8 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
                pr_devel("DRBG: using personalization string\n");
        }
 
-       if (!reseed) {
-               memset(drbg->V, 0, DRBG_STATE_LEN);
-               memset(drbg->C, 0, DRBG_STATE_LEN);
-       }
 
-       __drbg_seed(drbg, &seedlist, reseed, new_seed_state);
+       __drbg_seed(drbg, &seedlist, new_seed_state);
        ret = 0;
 out:
        memzero_explicit(entropy, sizeof(entropy));
@@ -424,7 +414,6 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
                return;
        memzero_explicit(&drbg->key, sizeof(drbg->key));
        memzero_explicit(drbg->V, sizeof(drbg->V));
-       memzero_explicit(drbg->C, sizeof(drbg->C));
        drbg->reseed_ctr = 0;
        drbg->instantiated = false;
 }
@@ -605,6 +594,7 @@ static int drbg_prepare_hrng(struct drbg_state *drbg)
 static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
                            bool pr)
 {
+       static const u8 initial_key[DRBG_STATE_LEN]; /* all zeroes */
        int ret;
        bool reseed = true;
 
@@ -627,6 +617,8 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
                drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
                drbg->last_seed_time = 0;
                drbg->reseed_threshold = DRBG_MAX_REQUESTS;
+               memset(drbg->V, 1, DRBG_STATE_LEN);
+               hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN);
 
                ret = drbg_prepare_hrng(drbg);
                if (ret)