random-util: introduce RANDOM_DONT_DRAIN

Originally, the high_quality_required boolean argument controlled two
things: whether to extend any random data we successfully read with
pseudo-random data, and whether to return -ENODATA if we couldn't read
any data at all.

The boolean got replaced by RANDOM_EXTEND_WITH_PSEUDO, but this name
doesn't really cover the second part nicely. Moreover hiding both
changes of behaviour under a single flag is confusing. Hence, let's
split this part off under a new flag, and use it from random_bytes().
This commit is contained in:
Lennart Poettering 2018-11-07 19:31:39 +01:00
parent 776cf7461f
commit 6fb6f13896
2 changed files with 13 additions and 11 deletions

View File

@ -72,9 +72,9 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
int r;
/* Gathers some randomness from the kernel. This call won't block, unless the RANDOM_BLOCK flag is set. If
* RANDOM_EXTEND_WITH_PSEUDO is unset, it will always return some data from the kernel, regardless of whether
* the random pool is fully initialized or not. Otherwise, it will return success if at least some random
* bytes were successfully acquired, and an error if the kernel has no entropy whatsover for us. */
* 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. */
if (n == 0)
return 0;
@ -117,16 +117,17 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
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 high_quality_required is false, return an error so that
* random_bytes() can produce some pseudorandom
* bytes. 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_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. */
have_syscall = true;
if (FLAGS_SET(flags, RANDOM_DONT_DRAIN))
return -ENODATA;
if (FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) {
uint64_t u;
size_t k;
@ -228,7 +229,7 @@ void pseudo_random_bytes(void *p, size_t n) {
void random_bytes(void *p, size_t n) {
if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO) >= 0)
if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_DONT_DRAIN) >= 0)
return;
/* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */

View File

@ -8,6 +8,7 @@
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 */
} 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 */