hwrng: core - start hwrng kthread also for untrusted sources
authorDominik Brodowski <linux@dominikbrodowski.net>
Thu, 22 Sep 2022 13:59:31 +0000 (15:59 +0200)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 30 Sep 2022 05:59:12 +0000 (13:59 +0800)
Start the hwrng kthread even if the hwrng source has a quality setting
of zero. Then, every crng reseed interval, one batch of data from this
zero-quality hwrng source will be mixed into the CRNG pool.

This patch is based on the assumption that data from a hwrng source
will not actively harm the CRNG state. Instead, many hwrng sources
(such as TPM devices), even though they are assigend a quality level of
zero, actually provide some entropy, which is good enough to mix into
the CRNG pool every once in a while.

Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/char/hw_random/core.c

index d7045df..cc002b0 100644 (file)
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(default_quality,
 
 static void drop_current_rng(void);
 static int hwrng_init(struct hwrng *rng);
-static void hwrng_manage_rngd(struct hwrng *rng);
+static int hwrng_fillfn(void *unused);
 
 static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
                               int wait);
@@ -96,6 +96,15 @@ static int set_current_rng(struct hwrng *rng)
        drop_current_rng();
        current_rng = rng;
 
+       /* if necessary, start hwrng thread */
+       if (!hwrng_fill) {
+               hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng");
+               if (IS_ERR(hwrng_fill)) {
+                       pr_err("hwrng_fill thread creation failed\n");
+                       hwrng_fill = NULL;
+               }
+       }
+
        return 0;
 }
 
@@ -167,8 +176,6 @@ skip_init:
                rng->quality = 1024;
        current_quality = rng->quality; /* obsolete */
 
-       hwrng_manage_rngd(rng);
-
        return 0;
 }
 
@@ -454,10 +461,6 @@ static ssize_t rng_quality_store(struct device *dev,
        /* the best available RNG may have changed */
        ret = enable_best_rng();
 
-       /* start/stop rngd if necessary */
-       if (current_rng)
-               hwrng_manage_rngd(current_rng);
-
 out:
        mutex_unlock(&rng_mutex);
        return ret ? ret : len;
@@ -513,9 +516,6 @@ static int hwrng_fillfn(void *unused)
 
                put_rng(rng);
 
-               if (!quality)
-                       break;
-
                if (rc <= 0)
                        continue;
 
@@ -534,22 +534,6 @@ static int hwrng_fillfn(void *unused)
        return 0;
 }
 
-static void hwrng_manage_rngd(struct hwrng *rng)
-{
-       if (WARN_ON(!mutex_is_locked(&rng_mutex)))
-               return;
-
-       if (rng->quality == 0 && hwrng_fill)
-               kthread_stop(hwrng_fill);
-       if (rng->quality > 0 && !hwrng_fill) {
-               hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng");
-               if (IS_ERR(hwrng_fill)) {
-                       pr_err("hwrng_fill thread creation failed\n");
-                       hwrng_fill = NULL;
-               }
-       }
-}
-
 int hwrng_register(struct hwrng *rng)
 {
        int err = -EINVAL;