crypto: rng - Override drivers/char/random in FIPS mode

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.

Signed-off-by: Herbert Xu <herbert.xu@redhat.com>
This commit is contained in:
Herbert Xu 2021-08-10 17:56:42 +08:00 committed by Justin M. Forbes
parent 9c99e63401
commit fb46f3370e
No known key found for this signature in database
GPG Key ID: B8FA7924A4B1C140
1 changed files with 72 additions and 1 deletions

View File

@ -11,14 +11,17 @@
#include <linux/atomic.h>
#include <crypto/internal/rng.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 <linux/cryptouser.h>
#include <linux/compiler.h>
#include <net/netlink.h>
#include "internal.h"
@ -224,5 +227,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");