From: Herbert Xu herbert.xu@redhat.com
Upstream: RHEL only Bugzilla: 1984784
This patch overrides the drivers/char/random RNGs with the FIPS RNG from Crypto API when FIPS mode is enabled.
Cc: stable@vger.kernel.org Signed-off-by: Herbert Xu herbert.xu@redhat.com (cherry picked from commit 37e0042aaf43d4494bcbea2113605366d0fe6187) Signed-off-by: Samuel Mendoza-Jonas samjonas@amazon.com [6.12: Resolve minor merge conflicts] Signed-off-by: Elena Avila ellavila@amazon.com --- crypto/rng.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+)
diff --git a/crypto/rng.c b/crypto/rng.c index 9d8804e46422..cdba806846e2 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -12,11 +12,14 @@ #include <linux/atomic.h> #include <linux/cryptouser.h> #include <linux/err.h> +#include <linux/fips.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/random.h> #include <linux/seq_file.h> +#include <linux/sched.h> +#include <linux/sched/signal.h> #include <linux/slab.h> #include <linux/string.h> #include <net/netlink.h> @@ -217,5 +220,73 @@ void crypto_unregister_rngs(struct rng_alg *algs, int count) } EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
+static ssize_t crypto_devrandom_read(void __user *buf, size_t buflen) +{ + u8 tmp[256]; + ssize_t ret; + + if (!buflen) + return 0; + + ret = crypto_get_default_rng(); + if (ret) + return ret; + + for (;;) { + int err; + int i; + + i = min_t(int, buflen, sizeof(tmp)); + err = crypto_rng_get_bytes(crypto_default_rng, tmp, i); + if (err) { + ret = err; + break; + } + + if (copy_to_user(buf, tmp, i)) { + ret = -EFAULT; + break; + } + + buflen -= i; + buf += i; + ret += i; + + if (!buflen) + break; + + if (need_resched()) { + if (signal_pending(current)) + break; + schedule(); + } + } + + crypto_put_default_rng(); + memzero_explicit(tmp, sizeof(tmp)); + + return ret; +} + +static const struct random_extrng crypto_devrandom_rng = { + .extrng_read = crypto_devrandom_read, + .owner = THIS_MODULE, +}; + +static int __init crypto_rng_init(void) +{ + if (fips_enabled) + random_register_extrng(&crypto_devrandom_rng); + return 0; +} + +static void __exit crypto_rng_exit(void) +{ + random_unregister_extrng(); +} + +late_initcall(crypto_rng_init); +module_exit(crypto_rng_exit); + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Random Number Generator");