1 /* Generate buffers of random data.
2 
3    Copyright (C) 2006-2020 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 <https://www.gnu.org/licenses/>.  */
17 
18 /* Written by Paul Eggert.  */
19 
20 /* FIXME: Improve performance by adding support for the RDRAND machine
21    instruction if available (e.g., Ivy Bridge processors).  */
22 
23 #include <config.h>
24 
25 #include "randread.h"
26 
27 #include <errno.h>
28 #include <error.h>
29 #include <exitfail.h>
30 #include <fcntl.h>
31 #include <quote.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>
40 
41 #include "gettext.h"
42 #define _(msgid) gettext (msgid)
43 
44 #include "rand-isaac.h"
45 #include "stdio-safer.h"
46 #include "unlocked-io.h"
47 #include "xalloc.h"
48 
49 #ifndef __attribute__
50 # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
51 #  define __attribute__(x) /* empty */
52 # endif
53 #endif
54 
55 #ifndef ATTRIBUTE_NORETURN
56 # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
57 #endif
58 
59 #ifndef MIN
60 # define MIN(a, b) ((a) < (b) ? (a) : (b))
61 #endif
62 
63 #if _STRING_ARCH_unaligned || _STRING_INLINE_unaligned
64 # define ALIGNED_POINTER(ptr, type) true
65 #else
66 # define ALIGNED_POINTER(ptr, type) ((size_t) (ptr) % alignof (type) == 0)
67 #endif
68 
69 #ifndef NAME_OF_NONCE_DEVICE
70 # define NAME_OF_NONCE_DEVICE "/dev/urandom"
71 #endif
72 
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)
77 
78 /* A source of random data for generating random buffers.  */
79 struct randread_source
80 {
81   /* Stream to read random bytes from.  If null, the current
82      implementation uses an internal PRNG (ISAAC).  */
83   FILE *source;
84 
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;
92 
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
97   {
98     /* The stream buffer, if SOURCE is not null.  */
99     char c[RANDREAD_BUFFER_SIZE];
100 
101     /* The buffered ISAAC pseudorandom buffer, if SOURCE is null.  */
102     struct isaac
103     {
104       /* The number of bytes that are buffered at the end of data.b.  */
105       size_t buffered;
106 
107       /* State of the ISAAC generator.  */
108       struct isaac_state state;
109 
110       /* Up to a buffer's worth of pseudorandom data.  */
111       union
112       {
113         isaac_word w[ISAAC_WORDS];
114         unsigned char b[ISAAC_BYTES];
115       } data;
116     } isaac;
117   } buf;
118 };
119 
120 
121 /* The default error handler.  */
122 
123 static void ATTRIBUTE_NORETURN
randread_error(void const * file_name)124 randread_error (void const *file_name)
125 {
126   if (file_name)
127     error (exit_failure, errno,
128            errno == 0 ? _("%s: end of file") : _("%s: read error"),
129            quote (file_name));
130   abort ();
131 }
132 
133 /* Simply return a new randread_source object with the default error
134    handler.  */
135 
136 static struct randread_source *
simple_new(FILE * source,void const * handler_arg)137 simple_new (FILE *source, void const *handler_arg)
138 {
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;
144 }
145 
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.  */
149 
150 static void
get_nonce(void * buffer,size_t bufsize,size_t bytes_bound)151 get_nonce (void *buffer, size_t bufsize, size_t bytes_bound)
152 {
153   char *buf = buffer;
154   ssize_t seeded = 0;
155 
156   /* Get some data from FD if available.  */
157   int fd = open (NAME_OF_NONCE_DEVICE, O_RDONLY | O_BINARY);
158   if (0 <= fd)
159     {
160       seeded = read (fd, buf, MIN (bufsize, bytes_bound));
161       if (seeded < 0)
162         seeded = 0;
163       close (fd);
164     }
165 
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)                                     \
170     {                                                       \
171       type v;                                               \
172       size_t nbytes = MIN (sizeof v, bufsize - seeded);     \
173       initialize_v;                                         \
174       memcpy (buf + seeded, &v, nbytes);                    \
175       seeded += nbytes;                                     \
176     }
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 ());
182 
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
189 }
190 
191 
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.
196 
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.
200 
201    Return NULL (setting errno) on failure.  */
202 
203 struct randread_source *
randread_new(char const * name,size_t bytes_bound)204 randread_new (char const *name, size_t bytes_bound)
205 {
206   if (bytes_bound == 0)
207     return simple_new (NULL, NULL);
208   else
209     {
210       FILE *source = NULL;
211       struct randread_source *s;
212 
213       if (name)
214         if (! (source = fopen_safer (name, "rb")))
215           return NULL;
216 
217       s = simple_new (source, name);
218 
219       if (source)
220         setvbuf (source, s->buf.c, _IOFBF, MIN (sizeof s->buf.c, bytes_bound));
221       else
222         {
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);
227         }
228 
229       return s;
230     }
231 }
232 
233 
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.  */
240 
241 void
randread_set_handler(struct randread_source * s,void (* handler)(void const *))242 randread_set_handler (struct randread_source *s, void (*handler) (void const *))
243 {
244   s->handler = handler;
245 }
246 
247 void
randread_set_handler_arg(struct randread_source * s,void const * handler_arg)248 randread_set_handler_arg (struct randread_source *s, void const *handler_arg)
249 {
250   s->handler_arg = handler_arg;
251 }
252 
253 
254 /* Place SIZE random bytes into the buffer beginning at P, using
255    the stream in S.  */
256 
257 static void
readsource(struct randread_source * s,unsigned char * p,size_t size)258 readsource (struct randread_source *s, unsigned char *p, size_t size)
259 {
260   while (true)
261     {
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);
270     }
271 }
272 
273 
274 /* Place SIZE pseudorandom bytes into the buffer beginning at P, using
275    the buffered ISAAC generator in ISAAC.  */
276 
277 static void
readisaac(struct isaac * isaac,void * p,size_t size)278 readisaac (struct isaac *isaac, void *p, size_t size)
279 {
280   size_t inbytes = isaac->buffered;
281 
282   while (true)
283     {
284       char *char_p = p;
285 
286       if (size <= inbytes)
287         {
288           memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, size);
289           isaac->buffered = inbytes - size;
290           return;
291         }
292 
293       memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, inbytes);
294       p = char_p + inbytes;
295       size -= inbytes;
296 
297       /* If P is aligned, write to *P directly to avoid the overhead
298          of copying from the buffer.  */
299       if (ALIGNED_POINTER (p, isaac_word))
300         {
301           isaac_word *wp = p;
302           while (ISAAC_BYTES <= size)
303             {
304               isaac_refill (&isaac->state, wp);
305               wp += ISAAC_WORDS;
306               size -= ISAAC_BYTES;
307               if (size == 0)
308                 {
309                   isaac->buffered = 0;
310                   return;
311                 }
312             }
313           p = wp;
314         }
315 
316       isaac_refill (&isaac->state, isaac->data.w);
317       inbytes = ISAAC_BYTES;
318     }
319 }
320 
321 
322 /* Consume random data from *S to generate a random buffer BUF of size
323    SIZE.  */
324 
325 void
randread(struct randread_source * s,void * buf,size_t size)326 randread (struct randread_source *s, void *buf, size_t size)
327 {
328   if (s->source)
329     readsource (s, buf, size);
330   else
331     readisaac (&s->buf.isaac, buf, size);
332 }
333 
334 
335 /* Clear *S so that it no longer contains undelivered random data, and
336    deallocate any system resources associated with *S.  Return 0 if
337    successful, a negative number (setting errno) if not (this is rare,
338    but can occur in theory if there is an input error).  */
339 
340 int
randread_free(struct randread_source * s)341 randread_free (struct randread_source *s)
342 {
343   FILE *source = s->source;
344   explicit_bzero (s, sizeof *s);
345   free (s);
346   return (source ? fclose (source) : 0);
347 }
348