qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]