bool got_some = false;
int r;
- /* Gathers some randomness from the kernel (or the CPU if the RANDOM_ALLOW_RDRAND flag is set). This call won't
- * block, unless the RANDOM_BLOCK flag is set. If RANDOM_DONT_DRAIN is set, an error is returned if the random
- * pool is not initialized. Otherwise it will always return some data from the kernel, regardless of whether
- * the random pool is fully initialized or not. */
+ /* Gathers some randomness from the kernel (or the CPU if the RANDOM_ALLOW_RDRAND flag is set). This
+ * call won't block, unless the RANDOM_BLOCK flag is set. If RANDOM_MAY_FAIL is set, an error is
+ * returned if the random pool is not initialized. Otherwise it will always return some data from the
+ * kernel, regardless of whether the random pool is fully initialized or not. */
if (n == 0)
return 0;
if (FLAGS_SET(flags, RANDOM_ALLOW_RDRAND))
- /* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality randomness is not
- * required, as we don't trust it (who does?). Note that we only do a single iteration of RDRAND here,
- * even though the Intel docs suggest calling this in a tight loop of 10 invocations or so. That's
- * because we don't really care about the quality here. We generally prefer using RDRAND if the caller
- * allows us too, since this way we won't drain the kernel randomness pool if we don't need it, as the
- * pool's entropy is scarce. */
+ /* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality randomness is
+ * not required, as we don't trust it (who does?). Note that we only do a single iteration of
+ * RDRAND here, even though the Intel docs suggest calling this in a tight loop of 10
+ * invocations or so. That's because we don't really care about the quality here. We
+ * generally prefer using RDRAND if the caller allows us to, since this way we won't upset
+ * the kernel's random subsystem by accessing it before the pool is initialized (after all it
+ * will kmsg log about every attempt to do so)..*/
for (;;) {
unsigned long u;
size_t m;
break;
} else if (errno == EAGAIN) {
- /* The kernel has no entropy whatsoever. Let's remember to use the syscall the next
- * time again though.
+ /* The kernel has no entropy whatsoever. Let's remember to use the syscall
+ * the next time again though.
*
- * If RANDOM_DONT_DRAIN is set, return an error so that random_bytes() can produce some
- * pseudo-random bytes instead. Otherwise, fall back to /dev/urandom, which we know is empty,
- * but the kernel will produce some bytes for us on a best-effort basis. */
+ * If RANDOM_MAY_FAIL is set, return an error so that random_bytes() can
+ * produce some pseudo-random bytes instead. Otherwise, fall back to
+ * /dev/urandom, which we know is empty, but the kernel will produce some
+ * bytes for us on a best-effort basis. */
have_syscall = true;
if (got_some && FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) {
return 0;
}
- if (FLAGS_SET(flags, RANDOM_DONT_DRAIN))
+ if (FLAGS_SET(flags, RANDOM_MAY_FAIL))
return -ENODATA;
/* Use /dev/urandom instead */
void random_bytes(void *p, size_t n) {
- if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_DONT_DRAIN|RANDOM_ALLOW_RDRAND) >= 0)
+ if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_MAY_FAIL|RANDOM_ALLOW_RDRAND) >= 0)
return;
/* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */
typedef enum RandomFlags {
RANDOM_EXTEND_WITH_PSEUDO = 1 << 0, /* If we can't get enough genuine randomness, but some, fill up the rest with pseudo-randomness */
RANDOM_BLOCK = 1 << 1, /* Rather block than return crap randomness (only if the kernel supports that) */
- RANDOM_DONT_DRAIN = 1 << 2, /* If we can't get any randomness at all, return early with -EAGAIN */
+ RANDOM_MAY_FAIL = 1 << 2, /* If we can't get any randomness at all, return early with -ENODATA */
RANDOM_ALLOW_RDRAND = 1 << 3, /* Allow usage of the CPU RNG */
} RandomFlags;
-int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled upwith pseudo random, if not enough is available */
+int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled up with pseudo random, if not enough is available */
void pseudo_random_bytes(void *p, size_t n); /* returns only pseudo-randommess (but possibly seeded from something better) */
void random_bytes(void *p, size_t n); /* returns genuine randomness if cheaply available, and pseudo randomness if not. */