Line data Source code
1 : /* Generate buffers of random data.
2 :
3 : Copyright (C) 2006, 2008 Free Software Foundation, Inc.
4 :
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.
9 :
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.
14 :
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/>. */
17 :
18 : /* Written by Paul Eggert. */
19 :
20 : #include <config.h>
21 :
22 : #include "randread.h"
23 :
24 : #include <errno.h>
25 : #include <error.h>
26 : #include <exitfail.h>
27 : #include <quotearg.h>
28 : #include <stdbool.h>
29 : #include <stdint.h>
30 : #include <stdio.h>
31 : #include <stdlib.h>
32 : #include <string.h>
33 :
34 : #include "gettext.h"
35 : #define _(msgid) gettext (msgid)
36 :
37 : #include "rand-isaac.h"
38 : #include "stdio-safer.h"
39 : #include "unlocked-io.h"
40 : #include "xalloc.h"
41 :
42 : #ifndef MIN
43 : # define MIN(a, b) ((a) < (b) ? (a) : (b))
44 : #endif
45 :
46 : #ifndef __attribute__
47 : # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
48 : # define __attribute__(x)
49 : # endif
50 : #endif
51 :
52 : #ifndef ATTRIBUTE_UNUSED
53 : # define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
54 : #endif
55 :
56 : #if _STRING_ARCH_unaligned
57 : # define ALIGNED_POINTER(ptr, type) true
58 : #else
59 : # define alignof(type) offsetof (struct { char c; type x; }, x)
60 : # define ALIGNED_POINTER(ptr, type) ((size_t) (ptr) % alignof (type) == 0)
61 : #endif
62 :
63 : #ifndef DEFAULT_RANDOM_FILE
64 : # define DEFAULT_RANDOM_FILE "/dev/urandom"
65 : #endif
66 :
67 : /* The maximum buffer size used for reads of random data. Using the
68 : value 2 * ISAAC_BYTES makes this the largest power of two that
69 : would not otherwise cause struct randread_source to grow. */
70 : #define RANDREAD_BUFFER_SIZE (2 * ISAAC_BYTES)
71 :
72 : /* A source of random data for generating random buffers. */
73 : struct randread_source
74 : {
75 : /* Stream to read random bytes from. If null, the behavior is
76 : undefined; the current implementation uses ISAAC in this case,
77 : but this is for old-fashioned implementations that lack
78 : /dev/urandom and callers should not rely on this. */
79 : FILE *source;
80 :
81 : /* Function to call, and its argument, if there is an input error or
82 : end of file when reading from the stream; errno is nonzero if
83 : there was an error. If this function returns, it should fix the
84 : problem before returning. The default handler assumes that
85 : handler_arg is the file name of the source. */
86 : void (*handler) (void const *);
87 : void const *handler_arg;
88 :
89 : /* The buffer for SOURCE. It's kept here to simplify storage
90 : allocation and to make it easier to clear out buffered random
91 : data. */
92 : union
93 : {
94 : /* The stream buffer, if SOURCE is not null. */
95 : char c[RANDREAD_BUFFER_SIZE];
96 :
97 : /* The buffered ISAAC pseudorandom buffer, if SOURCE is null. */
98 : struct isaac
99 : {
100 : /* The number of bytes that are buffered at the end of data.b. */
101 : size_t buffered;
102 :
103 : /* State of the ISAAC generator. */
104 : struct isaac_state state;
105 :
106 : /* Up to a buffer's worth of pseudorandom data. */
107 : union
108 : {
109 : uint32_t w[ISAAC_WORDS];
110 : unsigned char b[ISAAC_BYTES];
111 : } data;
112 : } isaac;
113 : } buf;
114 : };
115 :
116 :
117 : /* The default error handler. */
118 :
119 : static void
120 1 : randread_error (void const *file_name)
121 : {
122 1 : if (file_name)
123 2 : error (exit_failure, errno,
124 1 : _(errno == 0 ? "%s: end of file" : "%s: read error"),
125 : quotearg_colon (file_name));
126 0 : abort ();
127 : }
128 :
129 : /* Simply return a new randread_source object with the default error
130 : handler. */
131 :
132 : static struct randread_source *
133 103 : simple_new (FILE *source, void const *handler_arg)
134 : {
135 103 : struct randread_source *s = xmalloc (sizeof *s);
136 103 : s->source = source;
137 103 : s->handler = randread_error;
138 103 : s->handler_arg = handler_arg;
139 103 : return s;
140 : }
141 :
142 : /* Create and initialize a random data source from NAME, or use a
143 : reasonable default source if NAME is null. BYTES_BOUND is an upper
144 : bound on the number of bytes that will be needed. If zero, it is a
145 : hard bound; otherwise it is just an estimate.
146 :
147 : If NAME is not null, NAME is saved for use as the argument of the
148 : default handler. Unless a non-default handler is used, NAME's
149 : lifetime should be at least that of the returned value.
150 :
151 : Return NULL (setting errno) on failure. */
152 :
153 : struct randread_source *
154 105 : randread_new (char const *name, size_t bytes_bound)
155 : {
156 105 : if (bytes_bound == 0)
157 10 : return simple_new (NULL, NULL);
158 : else
159 : {
160 95 : char const *file_name = (name ? name : DEFAULT_RANDOM_FILE);
161 95 : FILE *source = fopen_safer (file_name, "rb");
162 : struct randread_source *s;
163 :
164 95 : if (! source)
165 : {
166 2 : if (name)
167 2 : return NULL;
168 0 : file_name = NULL;
169 : }
170 :
171 93 : s = simple_new (source, file_name);
172 :
173 93 : if (source)
174 93 : setvbuf (source, s->buf.c, _IOFBF, MIN (sizeof s->buf.c, bytes_bound));
175 : else
176 : {
177 0 : s->buf.isaac.buffered = 0;
178 0 : isaac_seed (&s->buf.isaac.state);
179 : }
180 :
181 93 : return s;
182 : }
183 : }
184 :
185 :
186 : /* Set S's handler and its argument. HANDLER (HANDLER_ARG) is called
187 : when there is a read error or end of file from the random data
188 : source; errno is nonzero if there was an error. If HANDLER
189 : returns, it should fix the problem before returning. The default
190 : handler assumes that handler_arg is the file name of the source; it
191 : does not return. */
192 :
193 : void
194 0 : randread_set_handler (struct randread_source *s, void (*handler) (void const *))
195 : {
196 0 : s->handler = handler;
197 0 : }
198 :
199 : void
200 0 : randread_set_handler_arg (struct randread_source *s, void const *handler_arg)
201 : {
202 0 : s->handler_arg = handler_arg;
203 0 : }
204 :
205 :
206 : /* Place SIZE random bytes into the buffer beginning at P, using
207 : the stream in S. */
208 :
209 : static void
210 452 : readsource (struct randread_source *s, unsigned char *p, size_t size)
211 : {
212 : for (;;)
213 0 : {
214 452 : size_t inbytes = fread (p, sizeof *p, size, s->source);
215 452 : int fread_errno = errno;
216 452 : p += inbytes;
217 452 : size -= inbytes;
218 452 : if (size == 0)
219 451 : break;
220 1 : errno = (ferror (s->source) ? fread_errno : 0);
221 1 : s->handler (s->handler_arg);
222 : }
223 451 : }
224 :
225 :
226 : /* Place SIZE pseudorandom bytes into the buffer beginning at P, using
227 : the buffered ISAAC generator in ISAAC. */
228 :
229 : static void
230 0 : readisaac (struct isaac *isaac, unsigned char *p, size_t size)
231 : {
232 0 : size_t inbytes = isaac->buffered;
233 :
234 : for (;;)
235 : {
236 0 : if (size <= inbytes)
237 : {
238 0 : memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, size);
239 0 : isaac->buffered = inbytes - size;
240 0 : return;
241 : }
242 :
243 0 : memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, inbytes);
244 0 : p += inbytes;
245 0 : size -= inbytes;
246 :
247 : /* If P is aligned, write to *P directly to avoid the overhead
248 : of copying from the buffer. */
249 0 : if (ALIGNED_POINTER (p, uint32_t))
250 : {
251 0 : uint32_t *wp = (uint32_t *) p;
252 0 : while (ISAAC_BYTES <= size)
253 : {
254 0 : isaac_refill (&isaac->state, wp);
255 0 : wp += ISAAC_WORDS;
256 0 : size -= ISAAC_BYTES;
257 0 : if (size == 0)
258 : {
259 0 : isaac->buffered = 0;
260 0 : return;
261 : }
262 : }
263 0 : p = (unsigned char *) wp;
264 : }
265 :
266 0 : isaac_refill (&isaac->state, isaac->data.w);
267 0 : inbytes = ISAAC_BYTES;
268 : }
269 : }
270 :
271 :
272 : /* Consume random data from *S to generate a random buffer BUF of size
273 : SIZE. */
274 :
275 : void
276 452 : randread (struct randread_source *s, void *buf, size_t size)
277 : {
278 452 : if (s->source)
279 452 : readsource (s, buf, size);
280 : else
281 0 : readisaac (&s->buf.isaac, buf, size);
282 451 : }
283 :
284 :
285 : /* Clear *S so that it no longer contains undelivered random data, and
286 : deallocate any system resources associated with *S. Return 0 if
287 : successful, a negative number (setting errno) if not (this is rare,
288 : but can occur in theory if there is an input error). */
289 :
290 : int
291 76 : randread_free (struct randread_source *s)
292 : {
293 76 : FILE *source = s->source;
294 76 : memset (s, 0, sizeof *s);
295 76 : free (s);
296 76 : return (source ? fclose (source) : 0);
297 : }
|