root / backends / rng-random.c @ 7f9c9d12
History | View | Annotate | Download (3.6 kB)
1 |
/*
|
---|---|
2 |
* QEMU Random Number Generator Backend
|
3 |
*
|
4 |
* Copyright IBM, Corp. 2012
|
5 |
*
|
6 |
* Authors:
|
7 |
* Anthony Liguori <aliguori@us.ibm.com>
|
8 |
*
|
9 |
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
10 |
* See the COPYING file in the top-level directory.
|
11 |
*/
|
12 |
|
13 |
#include "qemu/rng-random.h" |
14 |
#include "qemu/rng.h" |
15 |
#include "qapi/qmp/qerror.h" |
16 |
#include "qemu/main-loop.h" |
17 |
|
18 |
struct RndRandom
|
19 |
{ |
20 |
RngBackend parent; |
21 |
|
22 |
int fd;
|
23 |
char *filename;
|
24 |
|
25 |
EntropyReceiveFunc *receive_func; |
26 |
void *opaque;
|
27 |
size_t size; |
28 |
}; |
29 |
|
30 |
/**
|
31 |
* A simple and incomplete backend to request entropy from /dev/random.
|
32 |
*
|
33 |
* This backend exposes an additional "filename" property that can be used to
|
34 |
* set the filename to use to open the backend.
|
35 |
*/
|
36 |
|
37 |
static void entropy_available(void *opaque) |
38 |
{ |
39 |
RndRandom *s = RNG_RANDOM(opaque); |
40 |
uint8_t buffer[s->size]; |
41 |
ssize_t len; |
42 |
|
43 |
len = read(s->fd, buffer, s->size); |
44 |
g_assert(len != -1);
|
45 |
|
46 |
s->receive_func(s->opaque, buffer, len); |
47 |
s->receive_func = NULL;
|
48 |
|
49 |
qemu_set_fd_handler(s->fd, NULL, NULL, NULL); |
50 |
} |
51 |
|
52 |
static void rng_random_request_entropy(RngBackend *b, size_t size, |
53 |
EntropyReceiveFunc *receive_entropy, |
54 |
void *opaque)
|
55 |
{ |
56 |
RndRandom *s = RNG_RANDOM(b); |
57 |
|
58 |
if (s->receive_func) {
|
59 |
s->receive_func(s->opaque, NULL, 0); |
60 |
} |
61 |
|
62 |
s->receive_func = receive_entropy; |
63 |
s->opaque = opaque; |
64 |
s->size = size; |
65 |
|
66 |
qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
|
67 |
} |
68 |
|
69 |
static void rng_random_opened(RngBackend *b, Error **errp) |
70 |
{ |
71 |
RndRandom *s = RNG_RANDOM(b); |
72 |
|
73 |
if (s->filename == NULL) { |
74 |
error_set(errp, QERR_INVALID_PARAMETER_VALUE, |
75 |
"filename", "a valid filename"); |
76 |
} else {
|
77 |
s->fd = qemu_open(s->filename, O_RDONLY | O_NONBLOCK); |
78 |
|
79 |
if (s->fd == -1) { |
80 |
error_set(errp, QERR_OPEN_FILE_FAILED, s->filename); |
81 |
} |
82 |
} |
83 |
} |
84 |
|
85 |
static char *rng_random_get_filename(Object *obj, Error **errp) |
86 |
{ |
87 |
RndRandom *s = RNG_RANDOM(obj); |
88 |
|
89 |
if (s->filename) {
|
90 |
return g_strdup(s->filename);
|
91 |
} |
92 |
|
93 |
return NULL; |
94 |
} |
95 |
|
96 |
static void rng_random_set_filename(Object *obj, const char *filename, |
97 |
Error **errp) |
98 |
{ |
99 |
RngBackend *b = RNG_BACKEND(obj); |
100 |
RndRandom *s = RNG_RANDOM(obj); |
101 |
|
102 |
if (b->opened) {
|
103 |
error_set(errp, QERR_PERMISSION_DENIED); |
104 |
return;
|
105 |
} |
106 |
|
107 |
if (s->filename) {
|
108 |
g_free(s->filename); |
109 |
} |
110 |
|
111 |
s->filename = g_strdup(filename); |
112 |
} |
113 |
|
114 |
static void rng_random_init(Object *obj) |
115 |
{ |
116 |
RndRandom *s = RNG_RANDOM(obj); |
117 |
|
118 |
object_property_add_str(obj, "filename",
|
119 |
rng_random_get_filename, |
120 |
rng_random_set_filename, |
121 |
NULL);
|
122 |
|
123 |
s->filename = g_strdup("/dev/random");
|
124 |
} |
125 |
|
126 |
static void rng_random_finalize(Object *obj) |
127 |
{ |
128 |
RndRandom *s = RNG_RANDOM(obj); |
129 |
|
130 |
qemu_set_fd_handler(s->fd, NULL, NULL, NULL); |
131 |
|
132 |
if (s->fd != -1) { |
133 |
qemu_close(s->fd); |
134 |
} |
135 |
|
136 |
g_free(s->filename); |
137 |
} |
138 |
|
139 |
static void rng_random_class_init(ObjectClass *klass, void *data) |
140 |
{ |
141 |
RngBackendClass *rbc = RNG_BACKEND_CLASS(klass); |
142 |
|
143 |
rbc->request_entropy = rng_random_request_entropy; |
144 |
rbc->opened = rng_random_opened; |
145 |
} |
146 |
|
147 |
static const TypeInfo rng_random_info = { |
148 |
.name = TYPE_RNG_RANDOM, |
149 |
.parent = TYPE_RNG_BACKEND, |
150 |
.instance_size = sizeof(RndRandom),
|
151 |
.class_init = rng_random_class_init, |
152 |
.instance_init = rng_random_init, |
153 |
.instance_finalize = rng_random_finalize, |
154 |
}; |
155 |
|
156 |
static void register_types(void) |
157 |
{ |
158 |
type_register_static(&rng_random_info); |
159 |
} |
160 |
|
161 |
type_init(register_types); |