memzero_explicit(first_block, sizeof(first_block));
}
+/*
+ * Return whether the crng seed is considered to be sufficiently
+ * old that a reseeding might be attempted. This happens if the last
+ * reseeding was CRNG_RESEED_INTERVAL ago, or during early boot, at
+ * an interval proportional to the uptime.
+ */
+static bool crng_has_old_seed(void)
+{
+ static bool early_boot = true;
+ unsigned long interval = CRNG_RESEED_INTERVAL;
+
+ if (unlikely(READ_ONCE(early_boot))) {
+ time64_t uptime = ktime_get_seconds();
+ if (uptime >= CRNG_RESEED_INTERVAL / HZ * 2)
+ WRITE_ONCE(early_boot, false);
+ else
+ interval = max_t(unsigned int, 5 * HZ,
+ (unsigned int)uptime / 2 * HZ);
+ }
+ return time_after(jiffies, READ_ONCE(base_crng.birth) + interval);
+}
+
/*
* This function returns a ChaCha state that you may use for generating
* random data. It also returns up to 32 bytes on its own of random data
}
/*
- * If the base_crng is more than 5 minutes old, we reseed, which
- * in turn bumps the generation counter that we check below.
+ * If the base_crng is old enough, we try to reseed, which in turn
+ * bumps the generation counter that we check below.
*/
- if (unlikely(time_after(jiffies, READ_ONCE(base_crng.birth) + CRNG_RESEED_INTERVAL)))
+ if (unlikely(crng_has_old_seed()))
crng_reseed();
local_lock_irqsave(&crngs.lock, flags);