[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 09/14] util: Use qcrypto_random_bytes for qemu_ge
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH v2 09/14] util: Use qcrypto_random_bytes for qemu_getrandom |
Date: |
Wed, 13 Mar 2019 21:55:21 -0700 |
When not requesting deterministic bytes, use our existing crypto.
Signed-off-by: Richard Henderson <address@hidden>
---
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
[Qemu-devel] [PATCH v2 08/14] util: Add qemu_getrandom and support functions, Richard Henderson, 2019/03/14