Skip to content

Commit fd75e5d

Browse files
kerneltoastPlaidCat
authored andcommitted
crypto: rng - Only allow the DRBG to register as "stdrng" in FIPS mode
In FIPS mode, the DRBG must take precedence over all stdrng algorithms. The only problem standing in the way of this is that a different stdrng algorithm could get registered and utilized before the DRBG is registered, and since crypto_alloc_rng() only allocates an stdrng algorithm when there's no existing allocation, this means that it's possible for the wrong stdrng algorithm to remain in use indefinitely. This issue is also often impossible to observe from userspace; an RNG other than the DRBG could be used somewhere in the kernel and userspace would be none the wiser. To ensure this can never happen, only allow stdrng instances from the DRBG to be registered when running in FIPS mode. This works since the previous commit forces the DRBG to be built into the kernel when CONFIG_CRYPTO_FIPS is enabled, so the DRBG's presence is guaranteed when fips_enabled is true. Signed-off-by: Sultan Alsawaf <sultan@ciq.com> Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent 35f544c commit fd75e5d

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

crypto/rng.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ static ____cacheline_aligned_in_smp DEFINE_MUTEX(crypto_default_rng_lock);
3232
struct crypto_rng *crypto_default_rng;
3333
EXPORT_SYMBOL_GPL(crypto_default_rng);
3434
static unsigned int crypto_default_rng_refcnt;
35+
static bool drbg_registered __ro_after_init;
3536

3637
int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
3738
{
@@ -201,6 +202,19 @@ int crypto_register_rng(struct rng_alg *alg)
201202
if (alg->seedsize > PAGE_SIZE / 8)
202203
return -EINVAL;
203204

205+
/*
206+
* In FIPS mode, the DRBG must take precedence over all other "stdrng"
207+
* algorithms. Therefore, forbid registration of a non-DRBG stdrng in
208+
* FIPS mode. All of the DRBG's driver names are prefixed with "drbg_".
209+
* This also stops new stdrng instances from getting registered after it
210+
* is known that the DRBG is registered, so a new module can't come in
211+
* and pretend to be the DRBG. And when CONFIG_CRYPTO_FIPS is enabled,
212+
* the DRBG is built into the kernel directly; it can't be a module.
213+
*/
214+
if (fips_enabled && !strcmp(base->cra_name, "stdrng") &&
215+
(drbg_registered || strncmp(base->cra_driver_name, "drbg_", 5)))
216+
return -EINVAL;
217+
204218
base->cra_type = &crypto_rng_type;
205219
base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
206220
base->cra_flags |= CRYPTO_ALG_TYPE_RNG;
@@ -225,6 +239,18 @@ int crypto_register_rngs(struct rng_alg *algs, int count)
225239
goto err;
226240
}
227241

242+
/*
243+
* Track when the DRBG is registered in FIPS mode. The DRBG calls
244+
* crypto_register_rngs() to register its stdrng instances, and since
245+
* crypto_register_rng() only allows stdrng instances from the DRBG in
246+
* FIPS mode, a successful stdrng registration means it was the DRBG.
247+
* Just check the first alg in the array to see if it's called "stdrng",
248+
* since all of the DRBG's algorithms are named "stdrng". Once
249+
* drbg_registered is set to true, this if-statement is always false.
250+
*/
251+
if (fips_enabled && !strcmp(algs->base.cra_name, "stdrng"))
252+
drbg_registered = true;
253+
228254
return 0;
229255

230256
err:

0 commit comments

Comments
 (0)