maint: adjust the URL that will appear in the generated announcement
[coreutils/ericb.git] / gl / lib / randread.c
blobb2a3ce6e41be60f79ea0784b75dfe6b996c1d189
1 /* Generate buffers of random data.
3 Copyright (C) 2006, 2008-2011 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* Written by Paul Eggert. */
20 /* FIXME: Improve performance by adding support for the RDRAND machine
21 instruction if available (e.g., Ivy Bridge processors). */
23 #include <config.h>
25 #include "randread.h"
27 #include <errno.h>
28 #include <error.h>
29 #include <exitfail.h>
30 #include <fcntl.h>
31 #include <quotearg.h>
32 #include <stdalign.h>
33 #include <stdbool.h>
34 #include <stdint.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/time.h>
39 #include <unistd.h>
41 #include "gettext.h"
42 #define _(msgid) gettext (msgid)
44 #include "rand-isaac.h"
45 #include "stdio-safer.h"
46 #include "unlocked-io.h"
47 #include "xalloc.h"
49 #ifndef __attribute__
50 # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
51 # define __attribute__(x) /* empty */
52 # endif
53 #endif
55 #ifndef ATTRIBUTE_NORETURN
56 # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
57 #endif
59 #ifndef MIN
60 # define MIN(a, b) ((a) < (b) ? (a) : (b))
61 #endif
63 #if _STRING_ARCH_unaligned
64 # define ALIGNED_POINTER(ptr, type) true
65 #else
66 # define ALIGNED_POINTER(ptr, type) ((size_t) (ptr) % alignof (type) == 0)
67 #endif
69 #ifndef NAME_OF_NONCE_DEVICE
70 # define NAME_OF_NONCE_DEVICE "/dev/urandom"
71 #endif
73 /* The maximum buffer size used for reads of random data. Using the
74 value 2 * ISAAC_BYTES makes this the largest power of two that
75 would not otherwise cause struct randread_source to grow. */
76 #define RANDREAD_BUFFER_SIZE (2 * ISAAC_BYTES)
78 /* A source of random data for generating random buffers. */
79 struct randread_source
81 /* Stream to read random bytes from. If null, the current
82 implementation uses an internal PRNG (ISAAC). */
83 FILE *source;
85 /* Function to call, and its argument, if there is an input error or
86 end of file when reading from the stream; errno is nonzero if
87 there was an error. If this function returns, it should fix the
88 problem before returning. The default handler assumes that
89 handler_arg is the file name of the source. */
90 void (*handler) (void const *);
91 void const *handler_arg;
93 /* The buffer for SOURCE. It's kept here to simplify storage
94 allocation and to make it easier to clear out buffered random
95 data. */
96 union
98 /* The stream buffer, if SOURCE is not null. */
99 char c[RANDREAD_BUFFER_SIZE];
101 /* The buffered ISAAC pseudorandom buffer, if SOURCE is null. */
102 struct isaac
104 /* The number of bytes that are buffered at the end of data.b. */
105 size_t buffered;
107 /* State of the ISAAC generator. */
108 struct isaac_state state;
110 /* Up to a buffer's worth of pseudorandom data. */
111 union
113 isaac_word w[ISAAC_WORDS];
114 unsigned char b[ISAAC_BYTES];
115 } data;
116 } isaac;
117 } buf;
121 /* The default error handler. */
123 static void ATTRIBUTE_NORETURN
124 randread_error (void const *file_name)
126 if (file_name)
127 error (exit_failure, errno,
128 _(errno == 0 ? "%s: end of file" : "%s: read error"),
129 quotearg_colon (file_name));
130 abort ();
133 /* Simply return a new randread_source object with the default error
134 handler. */
136 static struct randread_source *
137 simple_new (FILE *source, void const *handler_arg)
139 struct randread_source *s = xmalloc (sizeof *s);
140 s->source = source;
141 s->handler = randread_error;
142 s->handler_arg = handler_arg;
143 return s;
146 /* Put a nonce value into BUFFER, with size BUFSIZE, but do not get
147 more than BYTES_BOUND bytes' worth of random information from any
148 nonce device. */
150 static void
151 get_nonce (void *buffer, size_t bufsize, size_t bytes_bound)
153 char *buf = buffer;
154 ssize_t seeded = 0;
156 /* Get some data from FD if available. */
157 int fd = open (NAME_OF_NONCE_DEVICE, O_RDONLY | O_BINARY);
158 if (0 <= fd)
160 seeded = read (fd, buf, MIN (bufsize, bytes_bound));
161 if (seeded < 0)
162 seeded = 0;
163 close (fd);
166 /* If there's no nonce device, use a poor approximation
167 by getting the time of day, etc. */
168 #define ISAAC_SEED(type, initialize_v) \
169 if (seeded < bufsize) \
171 type v; \
172 size_t nbytes = MIN (sizeof v, bufsize - seeded); \
173 initialize_v; \
174 memcpy (buf + seeded, &v, nbytes); \
175 seeded += nbytes; \
177 ISAAC_SEED (struct timeval, gettimeofday (&v, NULL));
178 ISAAC_SEED (pid_t, v = getpid ());
179 ISAAC_SEED (pid_t, v = getppid ());
180 ISAAC_SEED (uid_t, v = getuid ());
181 ISAAC_SEED (uid_t, v = getgid ());
183 #ifdef lint
184 /* Normally we like having the extra randomness from uninitialized
185 parts of BUFFER. However, omit this randomness if we want to
186 avoid false-positives from memory-checking debugging tools. */
187 memset (buf + seeded, 0, bufsize - seeded);
188 #endif
192 /* Create and initialize a random data source from NAME, or use a
193 reasonable default source if NAME is null. BYTES_BOUND is an upper
194 bound on the number of bytes that will be needed. If zero, it is a
195 hard bound; otherwise it is just an estimate.
197 If NAME is not null, NAME is saved for use as the argument of the
198 default handler. Unless a non-default handler is used, NAME's
199 lifetime should be at least that of the returned value.
201 Return NULL (setting errno) on failure. */
203 struct randread_source *
204 randread_new (char const *name, size_t bytes_bound)
206 if (bytes_bound == 0)
207 return simple_new (NULL, NULL);
208 else
210 FILE *source = NULL;
211 struct randread_source *s;
213 if (name)
214 if (! (source = fopen_safer (name, "rb")))
215 return NULL;
217 s = simple_new (source, name);
219 if (source)
220 setvbuf (source, s->buf.c, _IOFBF, MIN (sizeof s->buf.c, bytes_bound));
221 else
223 s->buf.isaac.buffered = 0;
224 get_nonce (s->buf.isaac.state.m, sizeof s->buf.isaac.state.m,
225 bytes_bound);
226 isaac_seed (&s->buf.isaac.state);
229 return s;
234 /* Set S's handler and its argument. HANDLER (HANDLER_ARG) is called
235 when there is a read error or end of file from the random data
236 source; errno is nonzero if there was an error. If HANDLER
237 returns, it should fix the problem before returning. The default
238 handler assumes that handler_arg is the file name of the source; it
239 does not return. */
241 void
242 randread_set_handler (struct randread_source *s, void (*handler) (void const *))
244 s->handler = handler;
247 void
248 randread_set_handler_arg (struct randread_source *s, void const *handler_arg)
250 s->handler_arg = handler_arg;
254 /* Place SIZE random bytes into the buffer beginning at P, using
255 the stream in S. */
257 static void
258 readsource (struct randread_source *s, unsigned char *p, size_t size)
260 while (true)
262 size_t inbytes = fread (p, sizeof *p, size, s->source);
263 int fread_errno = errno;
264 p += inbytes;
265 size -= inbytes;
266 if (size == 0)
267 break;
268 errno = (ferror (s->source) ? fread_errno : 0);
269 s->handler (s->handler_arg);
274 /* Place SIZE pseudorandom bytes into the buffer beginning at P, using
275 the buffered ISAAC generator in ISAAC. */
277 static void
278 readisaac (struct isaac *isaac, unsigned char *p, size_t size)
280 size_t inbytes = isaac->buffered;
282 while (true)
284 if (size <= inbytes)
286 memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, size);
287 isaac->buffered = inbytes - size;
288 return;
291 memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, inbytes);
292 p += inbytes;
293 size -= inbytes;
295 /* If P is aligned, write to *P directly to avoid the overhead
296 of copying from the buffer. */
297 if (ALIGNED_POINTER (p, isaac_word))
299 isaac_word *wp = (isaac_word *) p;
300 while (ISAAC_BYTES <= size)
302 isaac_refill (&isaac->state, wp);
303 wp += ISAAC_WORDS;
304 size -= ISAAC_BYTES;
305 if (size == 0)
307 isaac->buffered = 0;
308 return;
311 p = (unsigned char *) wp;
314 isaac_refill (&isaac->state, isaac->data.w);
315 inbytes = ISAAC_BYTES;
320 /* Consume random data from *S to generate a random buffer BUF of size
321 SIZE. */
323 void
324 randread (struct randread_source *s, void *buf, size_t size)
326 if (s->source)
327 readsource (s, buf, size);
328 else
329 readisaac (&s->buf.isaac, buf, size);
333 /* Clear *S so that it no longer contains undelivered random data, and
334 deallocate any system resources associated with *S. Return 0 if
335 successful, a negative number (setting errno) if not (this is rare,
336 but can occur in theory if there is an input error). */
339 randread_free (struct randread_source *s)
341 FILE *source = s->source;
342 memset (s, 0, sizeof *s);
343 free (s);
344 return (source ? fclose (source) : 0);