Patchwork [4/8] rng-random: add an RNG backend that uses /dev/random (v2)

login
register
mail settings
Submitter Anthony Liguori
Date Oct. 30, 2012, 11:02 p.m.
Message ID <1351638178-15056-5-git-send-email-aliguori@us.ibm.com>
Download mbox | patch
Permalink /patch/195651/
State New
Headers show

Comments

Anthony Liguori - Oct. 30, 2012, 11:02 p.m.
The filename can be overridden but it expects a non-blocking source of entropy.
A typical invocation would be:

qemu -object rng-random,id=rng0 -device virtio-rng-pci,rng=rng0

This can also be used with /dev/urandom by using the command line:

qemu -object rng-random,filename=/dev/urandom,id=rng0 \
     -device virtio-rng-pci,rng=rng0

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
v1 -> v2
 - merged header split patch into this one
---
 backends/Makefile.objs    |   2 +-
 backends/rng-random.c     | 161 ++++++++++++++++++++++++++++++++++++++++++++++
 include/qemu/rng-random.h |  22 +++++++
 3 files changed, 184 insertions(+), 1 deletion(-)
 create mode 100644 backends/rng-random.c
 create mode 100644 include/qemu/rng-random.h
Paolo Bonzini - Oct. 31, 2012, 7:36 a.m.
Il 31/10/2012 00:02, Anthony Liguori ha scritto:
> The filename can be overridden but it expects a non-blocking source of entropy.
> A typical invocation would be:
> 
> qemu -object rng-random,id=rng0 -device virtio-rng-pci,rng=rng0
> 
> This can also be used with /dev/urandom by using the command line:
> 
> qemu -object rng-random,filename=/dev/urandom,id=rng0 \
>      -device virtio-rng-pci,rng=rng0
> 
> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
> ---
> v1 -> v2
>  - merged header split patch into this one
> ---
>  backends/Makefile.objs    |   2 +-
>  backends/rng-random.c     | 161 ++++++++++++++++++++++++++++++++++++++++++++++
>  include/qemu/rng-random.h |  22 +++++++
>  3 files changed, 184 insertions(+), 1 deletion(-)
>  create mode 100644 backends/rng-random.c
>  create mode 100644 include/qemu/rng-random.h
> 
> diff --git a/backends/Makefile.objs b/backends/Makefile.objs
> index 06e08c7..23ca19b 100644
> --- a/backends/Makefile.objs
> +++ b/backends/Makefile.objs
> @@ -1 +1 @@
> -common-obj-y += rng.o
> +common-obj-y += rng.o rng-random.o
> diff --git a/backends/rng-random.c b/backends/rng-random.c
> new file mode 100644
> index 0000000..8325686
> --- /dev/null
> +++ b/backends/rng-random.c
> @@ -0,0 +1,161 @@
> +/*
> + * QEMU Random Number Generator Backend
> + *
> + * Copyright IBM, Corp. 2012
> + *
> + * Authors:
> + *  Anthony Liguori   <aliguori@us.ibm.com>
> + *
> + * 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/rng-random.h"
> +#include "qemu/rng.h"
> +#include "qerror.h"
> +#include "main-loop.h"
> +
> +struct RndRandom
> +{
> +    RngBackend parent;
> +
> +    int fd;
> +    char *filename;
> +
> +    EntropyReceiveFunc *receive_func;
> +    void *opaque;
> +    size_t size;
> +};
> +
> +/**
> + * A simple and incomplete backend to request entropy from /dev/random.
> + *
> + * This backend exposes an additional "filename" property that can be used to
> + * set the filename to use to open the backend.
> + */
> +
> +static void entropy_available(void *opaque)
> +{
> +    RndRandom *s = RNG_RANDOM(opaque);
> +    uint8_t buffer[s->size];
> +    ssize_t len;
> +
> +    len = read(s->fd, buffer, s->size);
> +    g_assert(len != -1);
> +
> +    s->receive_func(s->opaque, buffer, s->size);

Should be len here, not s->size.

Otherwise looks good.

Paolo

> +    s->receive_func = NULL;
> +
> +    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
> +}
> +
> +static void rng_random_request_entropy(RngBackend *b, size_t size,
> +                                        EntropyReceiveFunc *receive_entropy,
> +                                        void *opaque)
> +{
> +    RndRandom *s = RNG_RANDOM(b);
> +
> +    if (s->receive_func) {
> +        s->receive_func(s->opaque, NULL, 0);
> +    }
> +
> +    s->receive_func = receive_entropy;
> +    s->opaque = opaque;
> +    s->size = size;
> +
> +    qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
> +}
> +
> +static void rng_random_opened(RngBackend *b, Error **errp)
> +{
> +    RndRandom *s = RNG_RANDOM(b);
> +
> +    if (s->filename == NULL) {
> +        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
> +                  "filename", "a valid filename");
> +    } else {
> +        s->fd = open(s->filename, O_RDONLY | O_NONBLOCK);
> +
> +        if (s->fd == -1) {
> +            error_set(errp, QERR_OPEN_FILE_FAILED, s->filename);
> +        }
> +    }
> +}
> +
> +static char *rng_random_get_filename(Object *obj, Error **errp)
> +{
> +    RndRandom *s = RNG_RANDOM(obj);
> +
> +    if (s->filename) {
> +        return g_strdup(s->filename);
> +    }
> +
> +    return NULL;
> +}
> +
> +static void rng_random_set_filename(Object *obj, const char *filename,
> +                                 Error **errp)
> +{
> +    RngBackend *b = RNG_BACKEND(obj);
> +    RndRandom *s = RNG_RANDOM(obj);
> +
> +    if (b->opened) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    if (s->filename) {
> +        g_free(s->filename);
> +    }
> +
> +    s->filename = g_strdup(filename);
> +}
> +
> +static void rng_random_init(Object *obj)
> +{
> +    RndRandom *s = RNG_RANDOM(obj);
> +
> +    object_property_add_str(obj, "filename",
> +                            rng_random_get_filename,
> +                            rng_random_set_filename,
> +                            NULL);
> +
> +    s->filename = g_strdup("/dev/random");
> +}
> +
> +static void rng_random_finalize(Object *obj)
> +{
> +    RndRandom *s = RNG_RANDOM(obj);
> +
> +    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
> +
> +    if (s->fd != -1) {
> +        close(s->fd);
> +    }
> +
> +    g_free(s->filename);
> +}
> +
> +static void rng_random_class_init(ObjectClass *klass, void *data)
> +{
> +    RngBackendClass *rbc = RNG_BACKEND_CLASS(klass);
> +
> +    rbc->request_entropy = rng_random_request_entropy;
> +    rbc->opened = rng_random_opened;
> +}
> +
> +static TypeInfo rng_random_info = {
> +    .name = TYPE_RNG_RANDOM,
> +    .parent = TYPE_RNG_BACKEND,
> +    .instance_size = sizeof(RndRandom),
> +    .class_init = rng_random_class_init,
> +    .instance_init = rng_random_init,
> +    .instance_finalize = rng_random_finalize,
> +};
> +
> +static void register_types(void)
> +{
> +    type_register_static(&rng_random_info);
> +}
> +
> +type_init(register_types);
> diff --git a/include/qemu/rng-random.h b/include/qemu/rng-random.h
> new file mode 100644
> index 0000000..6249290
> --- /dev/null
> +++ b/include/qemu/rng-random.h
> @@ -0,0 +1,22 @@
> +/*
> + * QEMU Random Number Generator Backend
> + *
> + * Copyright IBM, Corp. 2012
> + *
> + * Authors:
> + *  Anthony Liguori   <aliguori@us.ibm.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +#ifndef QEMU_RNG_RANDOM_H
> +#define QEMU_RNG_RANDOM_H
> +
> +#include "qemu/object.h"
> +
> +#define TYPE_RNG_RANDOM "rng-random"
> +#define RNG_RANDOM(obj) OBJECT_CHECK(RndRandom, (obj), TYPE_RNG_RANDOM)
> +
> +typedef struct RndRandom RndRandom;
> +
> +#endif
> -- 1.8.0
>

Patch

diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 06e08c7..23ca19b 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -1 +1 @@ 
-common-obj-y += rng.o
+common-obj-y += rng.o rng-random.o
diff --git a/backends/rng-random.c b/backends/rng-random.c
new file mode 100644
index 0000000..8325686
--- /dev/null
+++ b/backends/rng-random.c
@@ -0,0 +1,161 @@ 
+/*
+ * QEMU Random Number Generator Backend
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * 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/rng-random.h"
+#include "qemu/rng.h"
+#include "qerror.h"
+#include "main-loop.h"
+
+struct RndRandom
+{
+    RngBackend parent;
+
+    int fd;
+    char *filename;
+
+    EntropyReceiveFunc *receive_func;
+    void *opaque;
+    size_t size;
+};
+
+/**
+ * A simple and incomplete backend to request entropy from /dev/random.
+ *
+ * This backend exposes an additional "filename" property that can be used to
+ * set the filename to use to open the backend.
+ */
+
+static void entropy_available(void *opaque)
+{
+    RndRandom *s = RNG_RANDOM(opaque);
+    uint8_t buffer[s->size];
+    ssize_t len;
+
+    len = read(s->fd, buffer, s->size);
+    g_assert(len != -1);
+
+    s->receive_func(s->opaque, buffer, s->size);
+    s->receive_func = NULL;
+
+    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+}
+
+static void rng_random_request_entropy(RngBackend *b, size_t size,
+                                        EntropyReceiveFunc *receive_entropy,
+                                        void *opaque)
+{
+    RndRandom *s = RNG_RANDOM(b);
+
+    if (s->receive_func) {
+        s->receive_func(s->opaque, NULL, 0);
+    }
+
+    s->receive_func = receive_entropy;
+    s->opaque = opaque;
+    s->size = size;
+
+    qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
+}
+
+static void rng_random_opened(RngBackend *b, Error **errp)
+{
+    RndRandom *s = RNG_RANDOM(b);
+
+    if (s->filename == NULL) {
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
+                  "filename", "a valid filename");
+    } else {
+        s->fd = open(s->filename, O_RDONLY | O_NONBLOCK);
+
+        if (s->fd == -1) {
+            error_set(errp, QERR_OPEN_FILE_FAILED, s->filename);
+        }
+    }
+}
+
+static char *rng_random_get_filename(Object *obj, Error **errp)
+{
+    RndRandom *s = RNG_RANDOM(obj);
+
+    if (s->filename) {
+        return g_strdup(s->filename);
+    }
+
+    return NULL;
+}
+
+static void rng_random_set_filename(Object *obj, const char *filename,
+                                 Error **errp)
+{
+    RngBackend *b = RNG_BACKEND(obj);
+    RndRandom *s = RNG_RANDOM(obj);
+
+    if (b->opened) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    if (s->filename) {
+        g_free(s->filename);
+    }
+
+    s->filename = g_strdup(filename);
+}
+
+static void rng_random_init(Object *obj)
+{
+    RndRandom *s = RNG_RANDOM(obj);
+
+    object_property_add_str(obj, "filename",
+                            rng_random_get_filename,
+                            rng_random_set_filename,
+                            NULL);
+
+    s->filename = g_strdup("/dev/random");
+}
+
+static void rng_random_finalize(Object *obj)
+{
+    RndRandom *s = RNG_RANDOM(obj);
+
+    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+
+    if (s->fd != -1) {
+        close(s->fd);
+    }
+
+    g_free(s->filename);
+}
+
+static void rng_random_class_init(ObjectClass *klass, void *data)
+{
+    RngBackendClass *rbc = RNG_BACKEND_CLASS(klass);
+
+    rbc->request_entropy = rng_random_request_entropy;
+    rbc->opened = rng_random_opened;
+}
+
+static TypeInfo rng_random_info = {
+    .name = TYPE_RNG_RANDOM,
+    .parent = TYPE_RNG_BACKEND,
+    .instance_size = sizeof(RndRandom),
+    .class_init = rng_random_class_init,
+    .instance_init = rng_random_init,
+    .instance_finalize = rng_random_finalize,
+};
+
+static void register_types(void)
+{
+    type_register_static(&rng_random_info);
+}
+
+type_init(register_types);
diff --git a/include/qemu/rng-random.h b/include/qemu/rng-random.h
new file mode 100644
index 0000000..6249290
--- /dev/null
+++ b/include/qemu/rng-random.h
@@ -0,0 +1,22 @@ 
+/*
+ * QEMU Random Number Generator Backend
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef QEMU_RNG_RANDOM_H
+#define QEMU_RNG_RANDOM_H
+
+#include "qemu/object.h"
+
+#define TYPE_RNG_RANDOM "rng-random"
+#define RNG_RANDOM(obj) OBJECT_CHECK(RndRandom, (obj), TYPE_RNG_RANDOM)
+
+typedef struct RndRandom RndRandom;
+
+#endif