Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[sfrench/cifs-2.6.git] / drivers / char / random.c
index 5d5ea4ce144293e3e99cc7b7bcc68250cf12df5b..01b8868b9bed2583ab7bcb8c3a6c727737e02628 100644 (file)
@@ -1731,6 +1731,56 @@ void get_random_bytes(void *buf, int nbytes)
 }
 EXPORT_SYMBOL(get_random_bytes);
 
+
+/*
+ * Each time the timer fires, we expect that we got an unpredictable
+ * jump in the cycle counter. Even if the timer is running on another
+ * CPU, the timer activity will be touching the stack of the CPU that is
+ * generating entropy..
+ *
+ * Note that we don't re-arm the timer in the timer itself - we are
+ * happy to be scheduled away, since that just makes the load more
+ * complex, but we do not want the timer to keep ticking unless the
+ * entropy loop is running.
+ *
+ * So the re-arming always happens in the entropy loop itself.
+ */
+static void entropy_timer(struct timer_list *t)
+{
+       credit_entropy_bits(&input_pool, 1);
+}
+
+/*
+ * If we have an actual cycle counter, see if we can
+ * generate enough entropy with timing noise
+ */
+static void try_to_generate_entropy(void)
+{
+       struct {
+               unsigned long now;
+               struct timer_list timer;
+       } stack;
+
+       stack.now = random_get_entropy();
+
+       /* Slow counter - or none. Don't even bother */
+       if (stack.now == random_get_entropy())
+               return;
+
+       timer_setup_on_stack(&stack.timer, entropy_timer, 0);
+       while (!crng_ready()) {
+               if (!timer_pending(&stack.timer))
+                       mod_timer(&stack.timer, jiffies+1);
+               mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now));
+               schedule();
+               stack.now = random_get_entropy();
+       }
+
+       del_timer_sync(&stack.timer);
+       destroy_timer_on_stack(&stack.timer);
+       mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now));
+}
+
 /*
  * Wait for the urandom pool to be seeded and thus guaranteed to supply
  * cryptographically secure random numbers. This applies to: the /dev/urandom
@@ -1745,7 +1795,17 @@ int wait_for_random_bytes(void)
 {
        if (likely(crng_ready()))
                return 0;
-       return wait_event_interruptible(crng_init_wait, crng_ready());
+
+       do {
+               int ret;
+               ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready(), HZ);
+               if (ret)
+                       return ret > 0 ? 0 : ret;
+
+               try_to_generate_entropy();
+       } while (!crng_ready());
+
+       return 0;
 }
 EXPORT_SYMBOL(wait_for_random_bytes);
 
@@ -2445,3 +2505,17 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
        credit_entropy_bits(poolp, entropy);
 }
 EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
+
+/* Handle random seed passed by bootloader.
+ * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise
+ * it would be regarded as device data.
+ * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER.
+ */
+void add_bootloader_randomness(const void *buf, unsigned int size)
+{
+       if (IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER))
+               add_hwgenerator_randomness(buf, size, size * 8);
+       else
+               add_device_randomness(buf, size);
+}
+EXPORT_SYMBOL_GPL(add_bootloader_randomness);