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