When not requesting deterministic bytes, use our existing crypto. Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- util/random.c | 61 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 13 deletions(-)
diff --git a/util/random.c b/util/random.c index 467c987a66..c2628ace80 100644 --- a/util/random.c +++ b/util/random.c @@ -14,19 +14,20 @@ #include "qemu/cutils.h" #include "qapi/error.h" #include "qemu/random.h" +#include "crypto/random.h" + static __thread GRand *thread_rand; +static bool deterministic; + /* Deterministic implementation using Glib's Mersenne Twister. */ -bool qemu_getrandom(void *buf, size_t len, bool nonblock) +static bool do_glib(void *buf, size_t len, bool nonblock) { - GRand *rand; + GRand *rand = thread_rand; size_t i; uint32_t x; - g_assert(len <= 256); - - rand = thread_rand; if (unlikely(rand == NULL)) { /* Thread not initialized for a cpu, or main w/o -seed. */ thread_rand = rand = g_rand_new(); @@ -44,18 +45,53 @@ bool qemu_getrandom(void *buf, size_t len, bool nonblock) return true; } +/* Non-deterministic implementation using crypto routines. */ +static bool do_qcrypt(void *buf, size_t len, bool nonblock) +{ + if (nonblock) { + /* + * ??? This is not non-blocking; report failure as "would block". + * That said, what does "failure" really mean, and can we in fact + * reasonably recover from it? + */ + if (qcrypto_random_bytes(buf, len, NULL) < 0) { + return false; + } + } else { + int ret = qcrypto_random_bytes(buf, len, &error_fatal); + g_assert(ret == 0); + } + return true; +} + +bool qemu_getrandom(void *buf, size_t len, bool nonblock) +{ + g_assert(len <= 256); + if (unlikely(deterministic)) { + return do_glib(buf, len, nonblock); + } else { + return do_qcrypt(buf, len, nonblock); + } +} + uint64_t qemu_seedrandom_thread_part1(void) { - uint64_t ret; - qemu_getrandom(&ret, sizeof(ret), false); - return ret; + if (deterministic) { + uint64_t ret; + do_glib(&ret, sizeof(ret), false); + return ret; + } + return 0; } void qemu_seedrandom_thread_part2(uint64_t seed) { g_assert(thread_rand == NULL); - thread_rand = g_rand_new_with_seed_array((const guint32 *)&seed, - sizeof(seed) / sizeof(guint32)); + if (deterministic) { + thread_rand = + g_rand_new_with_seed_array((const guint32 *)&seed, + sizeof(seed) / sizeof(guint32)); + } } void qemu_seedrandom_main(const char *optarg, Error **errp) @@ -64,8 +100,7 @@ void qemu_seedrandom_main(const char *optarg, Error **errp) if (parse_uint_full(optarg, &seed, 0)) { error_setg(errp, "Invalid seed number: %s", optarg); } else { - g_assert(thread_rand != NULL); - g_rand_set_seed_array(thread_rand, (const guint32 *)&seed, - sizeof(seed) / sizeof(guint32)); + deterministic = true; + qemu_seedrandom_thread_part2(seed); } } -- 2.17.1