Line data Source code
1 : /* rndlinux.c - raw random number for OSes with /dev/random
2 : * Copyright (C) 1998, 2001, 2002, 2003, 2007,
3 : * 2009 Free Software Foundation, Inc.
4 : *
5 : * This file is part of Libgcrypt.
6 : *
7 : * Libgcrypt is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU Lesser General Public License as
9 : * published by the Free Software Foundation; either version 2.1 of
10 : * the License, or (at your option) any later version.
11 : *
12 : * Libgcrypt is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU Lesser General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU Lesser General Public
18 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 :
22 : #include <config.h>
23 : #include <stdio.h>
24 : #include <stdlib.h>
25 : #include <errno.h>
26 : #include <sys/time.h>
27 : #include <sys/types.h>
28 : #include <sys/stat.h>
29 : #ifdef HAVE_GETTIMEOFDAY
30 : # include <sys/times.h>
31 : #endif
32 : #include <string.h>
33 : #include <unistd.h>
34 : #include <fcntl.h>
35 : #if defined(__linux__) && defined(HAVE_SYSCALL)
36 : # include <sys/syscall.h>
37 : #endif
38 :
39 : #include "types.h"
40 : #include "g10lib.h"
41 : #include "rand-internal.h"
42 :
43 : static int open_device (const char *name, int retry);
44 :
45 :
46 : static int
47 20 : set_cloexec_flag (int fd)
48 : {
49 : int oldflags;
50 :
51 20 : oldflags= fcntl (fd, F_GETFD, 0);
52 20 : if (oldflags < 0)
53 0 : return oldflags;
54 20 : oldflags |= FD_CLOEXEC;
55 20 : return fcntl (fd, F_SETFD, oldflags);
56 : }
57 :
58 :
59 :
60 : /*
61 : * Used to open the /dev/random devices (Linux, xBSD, Solaris (if it
62 : * exists)). If RETRY is true, the function does not terminate with
63 : * a fatal error but retries until it is able to reopen the device.
64 : */
65 : static int
66 20 : open_device (const char *name, int retry)
67 : {
68 : int fd;
69 :
70 20 : if (retry)
71 0 : _gcry_random_progress ("open_dev_random", 'X', 1, 0);
72 : again:
73 20 : fd = open (name, O_RDONLY);
74 20 : if (fd == -1 && retry)
75 : {
76 : struct timeval tv;
77 :
78 0 : tv.tv_sec = 5;
79 0 : tv.tv_usec = 0;
80 0 : _gcry_random_progress ("wait_dev_random", 'X', 0, (int)tv.tv_sec);
81 0 : select (0, NULL, NULL, NULL, &tv);
82 0 : goto again;
83 : }
84 20 : if (fd == -1)
85 0 : log_fatal ("can't open %s: %s\n", name, strerror(errno) );
86 :
87 20 : if (set_cloexec_flag (fd))
88 0 : log_error ("error setting FD_CLOEXEC on fd %d: %s\n",
89 0 : fd, strerror (errno));
90 :
91 : /* We used to do the following check, however it turned out that this
92 : is not portable since more OSes provide a random device which is
93 : sometimes implemented as another device type.
94 :
95 : struct stat sb;
96 :
97 : if( fstat( fd, &sb ) )
98 : log_fatal("stat() off %s failed: %s\n", name, strerror(errno) );
99 : if( (!S_ISCHR(sb.st_mode)) && (!S_ISFIFO(sb.st_mode)) )
100 : log_fatal("invalid random device!\n" );
101 : */
102 20 : return fd;
103 : }
104 :
105 :
106 : /* Note that the caller needs to make sure that this function is only
107 : called by one thread at a time. The function returns 0 on success
108 : or true on failure (in which case the caller will signal a fatal
109 : error). */
110 : int
111 458 : _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
112 : enum random_origins),
113 : enum random_origins origin,
114 : size_t length, int level )
115 : {
116 : static int fd_urandom = -1;
117 : static int fd_random = -1;
118 : static unsigned char ever_opened;
119 : int fd;
120 : int n;
121 : byte buffer[768];
122 : size_t n_hw;
123 458 : size_t want = length;
124 458 : size_t last_so_far = 0;
125 458 : int any_need_entropy = 0;
126 : int delay;
127 :
128 458 : if (!add)
129 : {
130 : /* Special mode to close the descriptors. */
131 0 : if (fd_random != -1)
132 : {
133 0 : close (fd_random);
134 0 : fd_random = -1;
135 : }
136 0 : if (fd_urandom != -1)
137 : {
138 0 : close (fd_urandom);
139 0 : fd_urandom = -1;
140 : }
141 0 : return 0;
142 : }
143 :
144 :
145 : /* First read from a hardware source. However let it account only
146 : for up to 50% (or 25% for RDRAND) of the requested bytes. */
147 458 : n_hw = _gcry_rndhw_poll_slow (add, origin);
148 458 : if ((_gcry_get_hw_features () & HWF_INTEL_RDRAND))
149 : {
150 0 : if (n_hw > length/4)
151 0 : n_hw = length/4;
152 : }
153 : else
154 : {
155 458 : if (n_hw > length/2)
156 0 : n_hw = length/2;
157 : }
158 458 : if (length > 1)
159 458 : length -= n_hw;
160 :
161 : /* Open the requested device. The first time a device is to be
162 : opened we fail with a fatal error if the device does not exists.
163 : In case the device has ever been closed, further open requests
164 : will however retry indefinitely. The rationale for this behaviour is
165 : that we always require the device to be existent but want a more
166 : graceful behaviour if the rarely needed close operation has been
167 : used and the device needs to be re-opened later. */
168 458 : if (level >= 2)
169 : {
170 2 : if (fd_random == -1)
171 : {
172 2 : fd_random = open_device (NAME_OF_DEV_RANDOM, (ever_opened & 1));
173 2 : ever_opened |= 1;
174 : }
175 2 : fd = fd_random;
176 : }
177 : else
178 : {
179 456 : if (fd_urandom == -1)
180 : {
181 18 : fd_urandom = open_device (NAME_OF_DEV_URANDOM, (ever_opened & 2));
182 18 : ever_opened |= 2;
183 : }
184 456 : fd = fd_urandom;
185 : }
186 :
187 : /* Enter the read loop. */
188 458 : delay = 0; /* Start with 0 seconds so that we do no block on the
189 : first iteration and in turn call the progress function
190 : before blocking. To give the OS a better chance to
191 : return with something we will actually use 100ms. */
192 1374 : while (length)
193 : {
194 : fd_set rfds;
195 : struct timeval tv;
196 : int rc;
197 :
198 : /* If we have a modern Linux kernel and we want to read from the
199 : * the non-blocking /dev/urandom, we first try to use the new
200 : * getrandom syscall. That call guarantees that the kernel's
201 : * RNG has been properly seeded before returning any data. This
202 : * is different from /dev/urandom which may, due to its
203 : * non-blocking semantics, return data even if the kernel has
204 : * not been properly seeded. Unfortunately we need to use a
205 : * syscall and not a new device and thus we are not able to use
206 : * select(2) to have a timeout. */
207 : #if defined(__linux__) && defined(HAVE_SYSCALL) && defined(__NR_getrandom)
208 458 : if (fd == fd_urandom)
209 : {
210 : long ret;
211 : size_t nbytes;
212 :
213 : do
214 : {
215 456 : nbytes = length < sizeof(buffer)? length : sizeof(buffer);
216 456 : if (nbytes > 256)
217 0 : nbytes = 256;
218 456 : _gcry_pre_syscall ();
219 456 : ret = syscall (__NR_getrandom,
220 : (void*)buffer, (size_t)nbytes, (unsigned int)0);
221 456 : _gcry_post_syscall ();
222 : }
223 456 : while (ret == -1 && errno == EINTR);
224 456 : if (ret == -1 && errno == ENOSYS)
225 : ; /* The syscall is not supported - fallback to /dev/urandom. */
226 : else
227 : { /* The syscall is supported. Some sanity checks. */
228 456 : if (ret == -1)
229 0 : log_fatal ("unexpected error from getrandom: %s\n",
230 0 : strerror (errno));
231 456 : else if (ret != nbytes)
232 0 : log_fatal ("getrandom returned only"
233 : " %ld of %zu requested bytes\n", ret, nbytes);
234 :
235 456 : (*add)(buffer, nbytes, origin);
236 456 : length -= nbytes;
237 912 : continue; /* until LENGTH is zero. */
238 : }
239 : }
240 : #endif
241 :
242 : /* If we collected some bytes update the progress indicator. We
243 : do this always and not just if the select timed out because
244 : often just a few bytes are gathered within the timeout
245 : period. */
246 2 : if (any_need_entropy || last_so_far != (want - length) )
247 : {
248 0 : last_so_far = want - length;
249 0 : _gcry_random_progress ("need_entropy", 'X',
250 : (int)last_so_far, (int)want);
251 0 : any_need_entropy = 1;
252 : }
253 :
254 : /* If the system has no limit on the number of file descriptors
255 : and we encounter an fd which is larger than the fd_set size,
256 : we don't use the select at all. The select code is only used
257 : to emit progress messages. A better solution would be to
258 : fall back to poll() if available. */
259 : #ifdef FD_SETSIZE
260 2 : if (fd < FD_SETSIZE)
261 : #endif
262 : {
263 2 : FD_ZERO(&rfds);
264 2 : FD_SET(fd, &rfds);
265 2 : tv.tv_sec = delay;
266 2 : tv.tv_usec = delay? 0 : 100000;
267 2 : _gcry_pre_syscall ();
268 2 : rc = select (fd+1, &rfds, NULL, NULL, &tv);
269 2 : _gcry_post_syscall ();
270 2 : if (!rc)
271 : {
272 0 : any_need_entropy = 1;
273 0 : delay = 3; /* Use 3 seconds henceforth. */
274 0 : continue;
275 : }
276 2 : else if( rc == -1 )
277 : {
278 0 : log_error ("select() error: %s\n", strerror(errno));
279 0 : if (!delay)
280 0 : delay = 1; /* Use 1 second if we encounter an error before
281 : we have ever blocked. */
282 0 : continue;
283 : }
284 : }
285 :
286 : do
287 : {
288 : size_t nbytes;
289 :
290 2 : nbytes = length < sizeof(buffer)? length : sizeof(buffer);
291 2 : n = read (fd, buffer, nbytes);
292 2 : if (n >= 0 && n > nbytes)
293 : {
294 0 : log_error("bogus read from random device (n=%d)\n", n );
295 0 : n = nbytes;
296 : }
297 : }
298 2 : while (n == -1 && errno == EINTR);
299 2 : if (n == -1)
300 0 : log_fatal("read error on random device: %s\n", strerror(errno));
301 2 : (*add)(buffer, n, origin);
302 2 : length -= n;
303 : }
304 458 : wipememory (buffer, sizeof buffer);
305 :
306 458 : if (any_need_entropy)
307 0 : _gcry_random_progress ("need_entropy", 'X', (int)want, (int)want);
308 :
309 458 : return 0; /* success */
310 : }
|