Added virtioRNG support for windows in Qemu 77/281977/1
authorVarinder Pratap <varinder.p@samsung.com>
Sun, 25 Sep 2022 17:08:08 +0000 (22:38 +0530)
committerVarinder Pratap <varinder.p@samsung.com>
Sun, 25 Sep 2022 17:08:08 +0000 (22:38 +0530)
Change-Id: Icbc5307fe60a207d6a632ec550c8b2b01fcae322
Signed-off-by: Varinder Pratap <varinder.p@samsung.com>
backends/Makefile.objs
backends/rng-builtin.c [new file with mode: 0644]
crypto/random-platform.c
hw/virtio/virtio-rng.c
include/sysemu/rng.h

index 1846998..b305a7b 100644 (file)
@@ -1,4 +1,4 @@
-common-obj-y += rng.o rng-egd.o
+common-obj-y += rng.o rng-egd.o rng-builtin.o
 common-obj-$(CONFIG_POSIX) += rng-random.o
 
 common-obj-y += msmouse.o testdev.o
diff --git a/backends/rng-builtin.c b/backends/rng-builtin.c
new file mode 100644 (file)
index 0000000..fe3dbe9
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * QEMU Builtin Random Number Generator Backend
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "sysemu/rng.h"
+#include "qemu/main-loop.h"
+
+#define RNG_BUILTIN(obj) OBJECT_CHECK(RngBuiltin, (obj), TYPE_RNG_BUILTIN)
+
+typedef struct RngBuiltin {
+    RngBackend parent;
+    QEMUBH *bh;
+} RngBuiltin;
+
+
+static int qemu_guest_getrandom_nofail(void *buf, size_t len)
+{
+    /* Non-deterministic implementation using crypto routines.  */
+    return qcrypto_random_bytes(buf, len, NULL);
+}
+
+
+static void rng_builtin_receive_entropy_bh(void *opaque)
+{
+    RngBuiltin *s = opaque;
+
+    while (!QSIMPLEQ_EMPTY(&s->parent.requests)) {
+        RngRequest *req = QSIMPLEQ_FIRST(&s->parent.requests);
+
+        qemu_guest_getrandom_nofail(req->data, req->size);
+
+        req->receive_entropy(req->opaque, req->data, req->size);
+
+        rng_backend_finalize_request(&s->parent, req);
+    }
+}
+
+static void rng_builtin_request_entropy(RngBackend *b, RngRequest *req)
+{
+    RngBuiltin *s = RNG_BUILTIN(b);
+
+    qemu_bh_schedule(s->bh);
+}
+
+static void rng_builtin_init(Object *obj)
+{
+    RngBuiltin *s = RNG_BUILTIN(obj);
+
+    s->bh = qemu_bh_new(rng_builtin_receive_entropy_bh, s);
+}
+
+static void rng_builtin_finalize(Object *obj)
+{
+    RngBuiltin *s = RNG_BUILTIN(obj);
+
+    qemu_bh_delete(s->bh);
+}
+
+static void rng_builtin_class_init(ObjectClass *klass, void *data)
+{
+    RngBackendClass *rbc = RNG_BACKEND_CLASS(klass);
+
+    rbc->request_entropy = rng_builtin_request_entropy;
+}
+
+static const TypeInfo rng_builtin_info = {
+    .name = TYPE_RNG_BUILTIN,
+    .parent = TYPE_RNG_BACKEND,
+    .instance_size = sizeof(RngBuiltin),
+    .instance_init = rng_builtin_init,
+    .instance_finalize = rng_builtin_finalize,
+    .class_init = rng_builtin_class_init,
+};
+
+static void register_types(void)
+{
+    type_register_static(&rng_builtin_info);
+}
+
+type_init(register_types);
index 82b755a..d5d755f 100644 (file)
  */
 
 #include "qemu/osdep.h"
-
 #include "crypto/random.h"
 
+#ifdef _WIN32
+#include <wincrypt.h>
+
+int qcrypto_random_bytes(uint8_t *buf G_GNUC_UNUSED,
+                         size_t buflen G_GNUC_UNUSED,
+                         Error **errp)
+{
+
+    static HCRYPTPROV hCryptProv = (HCRYPTPROV) -1;
+    if (hCryptProv == -1) {
+        if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
+                                CRYPT_SILENT | CRYPT_VERIFYCONTEXT)) {
+            error_setg_win32(errp, GetLastError(),
+                            "Unable to create cryptographic provider");
+           hCryptProv = (HCRYPTPROV) -1;
+           return -1;
+        }
+    }
+
+    if (!CryptGenRandom(hCryptProv, buflen, buf)) {
+        error_setg_win32(errp, GetLastError(),
+                            "Unable to read random bytes");
+        return -1;
+    }
+
+    return 0;
+
+}
+
+#else //_WIN32
 int qcrypto_random_bytes(uint8_t *buf G_GNUC_UNUSED,
                          size_t buflen G_GNUC_UNUSED,
                          Error **errp)
@@ -62,3 +91,4 @@ int qcrypto_random_bytes(uint8_t *buf G_GNUC_UNUSED,
     close(fd);
     return ret;
 }
+#endif //_WIN32
index 9639f4e..966bde4 100644 (file)
@@ -162,8 +162,11 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
     }
 
     if (vrng->conf.rng == NULL) {
+#ifdef _WIN32
+        vrng->conf.default_backend = object_new(TYPE_RNG_BUILTIN);
+#else
         vrng->conf.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
-
+#endif
         user_creatable_complete(OBJECT(vrng->conf.default_backend),
                                 &local_err);
         if (local_err) {
index 45629c4..2378db7 100644 (file)
@@ -24,6 +24,8 @@
 #define RNG_BACKEND_CLASS(klass) \
     OBJECT_CLASS_CHECK(RngBackendClass, (klass), TYPE_RNG_BACKEND)
 
+#define TYPE_RNG_BUILTIN "rng-builtin"
+
 typedef struct RngRequest RngRequest;
 typedef struct RngBackendClass RngBackendClass;
 typedef struct RngBackend RngBackend;