lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20250630180312.24627-3-wanjay@amazon.com>
Date: Mon, 30 Jun 2025 18:03:12 +0000
From: Jay Wang <wanjay@...zon.com>
To: <herbert@...dor.apana.org.au>, <davem@...emloft.net>
CC: <linux-crypto@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
	<wanjay@...zon.com>
Subject: [PATCH v6.12 2/2] crypto: rng - Override drivers/char/random only after FIPS RNGs available

This commit overrides the drivers/char/random RNGs with the FIPS RNG
from Crypto API when FIPS mode is enabled. This commit is developed
based on a previous commit "crypto: rng - Override drivers/char/random
in FIPS mode", but it has a timing issue where the crypto RNG was
attempting to override the drivers/char/random interface before the
default RNG became available. The previous implementation would
immediately register the external RNG during module initialization,
which could fail if the default RNG wasn't ready.

Changes compared to previous commit:
- Introduce workqueue-based initialization for FIPS mode
- Add crypto_rng_register_work_func() to wait for default RNG
  availability
- Move random_register_extrng() call to the work function with proper
  error handling

This ensures the crypto ext RNG is properly registered only after all
dependencies are satisfied, preventing potential boot failures in
FIPS-enabled environments.

Cc: stable@...r.kernel.org
Signed-off-by: Jay Wang <wanjay@...zon.com>
---
 crypto/rng.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)

diff --git a/crypto/rng.c b/crypto/rng.c
index 9d8804e46422..250166d67fd0 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -12,13 +12,17 @@
 #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 <linux/workqueue.h>
 #include <net/netlink.h>

 #include "internal.h"
@@ -217,5 +221,93 @@ 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 struct work_struct crypto_rng_register_work;
+
+static void crypto_rng_register_work_func(struct work_struct *work)
+{
+	/* Wait until default rng becomes avaiable, then
+		Overwrite the extrng.
+	*/
+	int ret = crypto_get_default_rng();
+	if (ret){
+		printk(KERN_ERR "crypto_rng: Failed to get default RNG (error %d)\n", ret);
+		return;
+	}
+	printk(KERN_INFO "Overwrite extrng\n");
+	random_register_extrng(&crypto_devrandom_rng);
+}
+
+static int __init crypto_rng_init(void)
+{
+	if (fips_enabled) {
+		INIT_WORK(&crypto_rng_register_work, crypto_rng_register_work_func);
+		schedule_work(&crypto_rng_register_work);
+	}
+
+	return 0;
+}
+
+static void __exit crypto_rng_exit(void)
+{
+	cancel_work_sync(&crypto_rng_register_work);
+	random_unregister_extrng();
+}
+
+late_initcall(crypto_rng_init);
+module_exit(crypto_rng_exit);
+
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Random Number Generator");
--
2.47.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ