7964f3f274ce97f473a965048514478462c2f0a4
[libgcrypt.git] / cipher / rndunix.c
1 /****************************************************************************
2  *                                                                          *
3  *                                                                          *
4  *   Unix Randomness-Gathering Code                                         *
5  *                                                                          *
6  *   Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999.   *
7  *   Heavily modified for GnuPG by Werner Koch                              *
8  *                                                                          *
9  *                                                                          *
10  ****************************************************************************/
11
12 /* This module is part of the cryptlib continuously seeded pseudorandom
13    number generator.  For usage conditions, see lib_rand.c
14
15    [Here is the notice from lib_rand.c:]
16
17    This module and the misc/rnd*.c modules represent the cryptlib
18    continuously seeded pseudorandom number generator (CSPRNG) as described in
19    my 1998 Usenix Security Symposium paper "The generation of random numbers
20    for cryptographic purposes".
21
22    The CSPRNG code is copyright Peter Gutmann (and various others) 1996,
23    1997, 1998, 1999, all rights reserved.  Redistribution of the CSPRNG
24    modules and use in source and binary forms, with or without modification,
25    are permitted provided that the following conditions are met:
26
27    1. Redistributions of source code must retain the above copyright notice
28       and this permission notice in its entirety.
29
30    2. Redistributions in binary form must reproduce the copyright notice in
31       the documentation and/or other materials provided with the distribution.
32
33    3. A copy of any bugfixes or enhancements made must be provided to the
34       author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the
35       baseline version of the code.
36
37   ALTERNATIVELY, the code may be distributed under the terms of the GNU
38   General Public License, version 2 or any later version published by the
39   Free Software Foundation, in which case the provisions of the GNU GPL are
40   required INSTEAD OF the above restrictions.
41
42   Although not required under the terms of the GPL, it would still be nice if
43   you could make any changes available to the author to allow a consistent
44   code base to be maintained */
45
46
47 /* Fixme: We use plain mallocs here beucase it may be used as a module
48  * should be changed. */
49
50 /* General includes */
51
52 #include <config.h>
53 #include <stdlib.h>
54 #include <stdio.h>
55 #include <string.h>
56
57 /* OS-specific includes */
58
59 #ifdef __osf__
60   /* Somewhere in the morass of system-specific cruft which OSF/1 pulls in
61    * via the following includes are various endianness defines, so we
62    * undefine the cryptlib ones, which aren't really needed for this module
63    * anyway */
64 #undef BIG_ENDIAN
65 #undef LITTLE_ENDIAN
66 #endif                          /* __osf__ */
67
68 #include <unistd.h>
69 #include <fcntl.h>
70 #include <pwd.h>
71 #ifndef __QNX__
72 #include <sys/errno.h>
73 #include <sys/ipc.h>
74 #endif                          /* __QNX__ */
75 #include <sys/time.h>           /* SCO and SunOS need this before resource.h */
76 #ifndef __QNX__
77 #include <sys/resource.h>
78 #endif                          /* __QNX__ */
79 #if defined( _AIX ) || defined( __QNX__ )
80 #include <sys/select.h>
81 #endif                          /* _AIX */
82 #ifndef __QNX__
83 #include <sys/shm.h>
84 #include <signal.h>
85 #include <sys/signal.h>
86 #endif                          /* __QNX__ */
87 #include <sys/stat.h>
88 #include <sys/types.h>          /* Verschiedene komische Typen */
89 #if defined( __hpux ) && ( OS_VERSION == 9 )
90 #include <vfork.h>
91 #endif                          /* __hpux 9.x, after that it's in unistd.h */
92 #include <sys/wait.h>
93 /* #include <kitchensink.h> */
94 #ifdef __QNX__
95 #include <signal.h>
96 #include <process.h>
97 #endif                /* __QNX__ */
98 #include <errno.h>
99
100 #include "types.h"  /* for byte and u32 typedefs */
101 #include "g10lib.h"
102 #include "rand-internal.h"
103
104 #ifndef EAGAIN
105 #define EAGAIN  EWOULDBLOCK
106 #endif
107 #ifndef STDIN_FILENO
108 #define STDIN_FILENO 0
109 #endif
110 #ifndef STDOUT_FILENO
111 #define STDOUT_FILENO 1
112 #endif
113
114 #define GATHER_BUFSIZE          49152   /* Usually about 25K are filled */
115
116 /* The structure containing information on random-data sources.  Each
117  * record contains the source and a relative estimate of its usefulness
118  * (weighting) which is used to scale the number of kB of output from the
119  * source (total = data_bytes / usefulness).  Usually the weighting is in the
120  * range 1-3 (or 0 for especially useless sources), resulting in a usefulness
121  * rating of 1...3 for each kB of source output (or 0 for the useless
122  * sources).
123  *
124  * If the source is constantly changing (certain types of network statistics
125  * have this characteristic) but the amount of output is small, the weighting
126  * is given as a negative value to indicate that the output should be treated
127  * as if a minimum of 1K of output had been obtained.  If the source produces
128  * a lot of output then the scale factor is fractional, resulting in a
129  * usefulness rating of < 1 for each kB of source output.
130  *
131  * In order to provide enough randomness to satisfy the requirements for a
132  * slow poll, we need to accumulate at least 20 points of usefulness (a
133  * typical system should get about 30 points).
134  *
135  * Some potential options are missed out because of special considerations.
136  * pstat -i and pstat -f can produce amazing amounts of output (the record
137  * is 600K on an Oracle server) which floods the buffer and doesn't yield
138  * anything useful (apart from perhaps increasing the entropy of the vmstat
139  * output a bit), so we don't bother with this.  pstat in general produces
140  * quite a bit of output, but it doesn't change much over time, so it gets
141  * very low weightings.  netstat -s produces constantly-changing output but
142  * also produces quite a bit of it, so it only gets a weighting of 2 rather
143  * than 3.  The same holds for netstat -in, which gets 1 rather than 2.
144  *
145  * Some binaries are stored in different locations on different systems so
146  * alternative paths are given for them.  The code sorts out which one to
147  * run by itself, once it finds an exectable somewhere it moves on to the
148  * next source.  The sources are arranged roughly in their order of
149  * usefulness, occasionally sources which provide a tiny amount of
150  * relatively useless data are placed ahead of ones which provide a large
151  * amount of possibly useful data because another 100 bytes can't hurt, and
152  * it means the buffer won't be swamped by one or two high-output sources.
153  * All the high-output sources are clustered towards the end of the list
154  * for this reason.  Some binaries are checked for in a certain order, for
155  * example under Slowaris /usr/ucb/ps understands aux as an arg, but the
156  * others don't.  Some systems have conditional defines enabling alternatives
157  * to commands which don't understand the usual options but will provide
158  * enough output (in the form of error messages) to look like they're the
159  * real thing, causing alternative options to be skipped (we can't check the
160  * return either because some commands return peculiar, non-zero status even
161  * when they're working correctly).
162  *
163  * In order to maximise use of the buffer, the code performs a form of run-
164  * length compression on its input where a repeated sequence of bytes is
165  * replaced by the occurrence count mod 256.  Some commands output an awful
166  * lot of whitespace, this measure greatly increases the amount of data we
167  * can fit in the buffer.
168  *
169  * When we scale the weighting using the SC() macro, some preprocessors may
170  * give a division by zero warning for the most obvious expression
171  * 'weight ? 1024 / weight : 0' (and gcc 2.7.2.2 dies with a division by zero
172  * trap), so we define a value SC_0 which evaluates to zero when fed to
173  * '1024 / SC_0' */
174
175 #define SC( weight )    ( 1024 / weight )       /* Scale factor */
176 #define SC_0                    16384   /* SC( SC_0 ) evalutes to 0 */
177
178 static struct RI {
179     const char *path;           /* Path to check for existence of source */
180     const char *arg;            /* Args for source */
181     const int usefulness;       /* Usefulness of source */
182     FILE *pipe;                 /* Pipe to source as FILE * */
183     int pipeFD;                 /* Pipe to source as FD */
184     pid_t pid;                  /* pid of child for waitpid() */
185     int length;                 /* Quantity of output produced */
186     const int hasAlternative;       /* Whether source has alt.location */
187 } dataSources[] = {
188
189     {   "/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 1    },
190     {   "/usr/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 0},
191     {   "/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 1     },
192     {   "/usr/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 0},
193     {   "/usr/bin/pfstat", NULL, SC(-2), NULL, 0, 0, 0, 0},
194     {   "/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 1     },
195     {   "/usr/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 0},
196     {   "/usr/ucb/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
197     {   "/usr/bin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
198     {   "/usr/sbin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1},
199     {   "/usr/etc/netstat", "-s", SC(2), NULL, 0, 0, 0, 0},
200     {   "/usr/bin/nfsstat", NULL, SC(2), NULL, 0, 0, 0, 0},
201     {   "/usr/ucb/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1  },
202     {   "/usr/bin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1  },
203     {   "/usr/sbin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
204     {   "/usr/etc/netstat", "-m", SC(-1), NULL, 0, 0, 0, 0 },
205     {   "/bin/netstat",     "-in", SC(-1), NULL, 0, 0, 0, 1 },
206     {   "/usr/ucb/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
207     {   "/usr/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
208     {   "/usr/sbin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1},
209     {   "/usr/etc/netstat", "-in", SC(-1), NULL, 0, 0, 0, 0},
210     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.1.0",
211                                     SC(-1), NULL, 0, 0, 0, 0 }, /* UDP in */
212     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.4.0",
213                                     SC(-1), NULL, 0, 0, 0, 0 },  /* UDP out */
214     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.4.3.0",
215                                     SC(-1), NULL, 0, 0, 0, 0 }, /* IP ? */
216     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.10.0",
217                                     SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
218     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.11.0",
219                                     SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
220     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.13.0",
221                                     SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
222     {   "/usr/bin/mpstat", NULL, SC(1), NULL, 0, 0, 0, 0     },
223     {   "/usr/bin/w", NULL, SC(1), NULL, 0, 0, 0, 1           },
224     {   "/usr/bsd/w", NULL, SC(1), NULL, 0, 0, 0, 0          },
225     {   "/usr/bin/df", NULL, SC(1), NULL, 0, 0, 0, 1          },
226     {   "/bin/df", NULL, SC(1), NULL, 0, 0, 0, 0             },
227     {   "/usr/sbin/portstat", NULL, SC(1), NULL, 0, 0, 0, 0  },
228     {   "/usr/bin/iostat", NULL, SC(SC_0), NULL, 0, 0, 0, 0  },
229     {   "/usr/bin/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 1   },
230     {   "/usr/bsd/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 0  },
231     {   "/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 1       },
232     {   "/usr/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 0  },
233     {   "/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 1       },
234     {   "/usr/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 0  },
235     {   "/usr/ucb/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1   },
236     {   "/usr/bin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1   },
237     {   "/usr/sbin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1  },
238     {   "/usr/etc/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 0  },
239 #if defined( __sgi ) || defined( __hpux )
240     {   "/bin/ps", "-el", SC(0.3), NULL, 0, 0, 0, 1           },
241 #endif                          /* __sgi || __hpux */
242     {   "/usr/ucb/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1       },
243     {   "/usr/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1       },
244     {   "/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 0          },
245     {   "/bin/ps", "-A", SC(0.3), NULL, 0, 0, 0, 0           }, /*QNX*/
246     {   "/usr/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 1      },
247     {   "/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 0         },
248     /* Unreliable source, depends on system usage */
249     {   "/etc/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 1         },
250     {   "/bin/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 0        },
251     {   "/etc/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 1         },
252     {   "/bin/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 0        },
253     {   "/etc/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 1         },
254     {   "/bin/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 0        },
255     {   "/etc/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 1         },
256     {   "/bin/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 0        },
257     {   "/etc/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 1         },
258     {   "/bin/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 0        },
259     /* pstat is your friend */
260     {   "/usr/bin/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 1   },
261 #ifdef __sgi
262     {   "/usr/bsd/last", "-50", SC(0.3), NULL, 0, 0, 0, 0    },
263 #endif                          /* __sgi */
264 #ifdef __hpux
265     {   "/etc/last", "-50", SC(0.3), NULL, 0, 0, 0, 0        },
266 #endif                          /* __hpux */
267     {   "/usr/bsd/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 0  },
268     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.1.0",
269                                 SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */
270     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.3.0",
271                                 SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */
272     {   "/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1  },
273     {   "/usr/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1  },
274     {   "/usr/bin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1  },
275     {   "/usr/sbin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 0 },
276     {   "/usr/sbin/ripquery", "-nw 1 127.0.0.1",
277                                 SC(0.1), NULL, 0, 0, 0, 0 },
278     {   "/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1     },
279     {   "/usr/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
280     {   "/usr/ucb/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 },
281     {   "/usr/bin/tcpdump", "-c 5 -efvvx", SC(1), NULL, 0, 0, 0, 0 },
282     /* This is very environment-dependant.  If network traffic is low, it'll
283      * probably time out before delivering 5 packets, which is OK because
284      * it'll probably be fixed stuff like ARP anyway */
285     {   "/usr/sbin/advfsstat", "-b usr_domain",
286                                 SC(SC_0), NULL, 0, 0, 0, 0},
287     {   "/usr/sbin/advfsstat", "-l 2 usr_domain",
288                                 SC(0.5), NULL, 0, 0, 0, 0},
289     {   "/usr/sbin/advfsstat", "-p usr_domain",
290                                 SC(SC_0), NULL, 0, 0, 0, 0},
291     /* This is a complex and screwball program.  Some systems have things
292      * like rX_dmn, x = integer, for RAID systems, but the statistics are
293      * pretty dodgy */
294 #ifdef __QNXNTO__                                                             
295     { "/bin/pidin", "-F%A%B%c%d%E%I%J%K%m%M%n%N%p%P%S%s%T", SC(0.3),
296              NULL, 0, 0, 0, 0       },
297 #endif     
298 #if 0
299     /* The following aren't enabled since they're somewhat slow and not very
300      * unpredictable, however they give an indication of the sort of sources
301      * you can use (for example the finger might be more useful on a
302      * firewalled internal network) */
303     {   "/usr/bin/finger", "@ml.media.mit.edu", SC(0.9), NULL, 0, 0, 0, 0 },
304     {   "/usr/local/bin/wget", "-O - http://lavarand.sgi.com/block.html",
305                                 SC(0.9), NULL, 0, 0, 0, 0 },
306     {   "/bin/cat", "/usr/spool/mqueue/syslog", SC(0.9), NULL, 0, 0, 0, 0 },
307 #endif                          /* 0 */
308     {   NULL, NULL, 0, NULL, 0, 0, 0, 0 }
309 };
310
311 static byte *gather_buffer;         /* buffer for gathering random noise */
312 static int gather_buffer_size;      /* size of the memory buffer */
313 static uid_t gatherer_uid;
314
315 /* The message structure used to communicate with the parent */
316 typedef struct {
317     int  usefulness;    /* usefulness of data */
318     int  ndata;         /* valid bytes in data */
319     char data[500];     /* gathered data */
320 } GATHER_MSG;
321
322 #ifndef HAVE_WAITPID
323 static pid_t
324 waitpid(pid_t pid, int *statptr, int options)
325 {
326 #ifdef HAVE_WAIT4
327         return wait4(pid, statptr, options, NULL);
328 #else
329         /* If wait4 is also not available, try wait3 for SVR3 variants */
330         /* Less ideal because can't actually request a specific pid */
331         /* For that reason, first check to see if pid is for an */
332         /*   existing process. */
333         int tmp_pid, dummystat;;
334         if (kill(pid, 0) == -1) {
335                 errno = ECHILD;
336                 return -1;
337         }
338         if (statptr == NULL)
339                 statptr = &dummystat;
340         while (((tmp_pid = wait3(statptr, options, 0)) != pid) &&
341                     (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
342             ;
343         return tmp_pid;
344 #endif
345 }
346 #endif
347
348 /* Under SunOS popen() doesn't record the pid of the child process.  When
349  * pclose() is called, instead of calling waitpid() for the correct child, it
350  * calls wait() repeatedly until the right child is reaped.  The problem is
351  * that this reaps any other children that happen to have died at that
352  * moment, and when their pclose() comes along, the process hangs forever.
353  * The fix is to use a wrapper for popen()/pclose() which saves the pid in
354  * the dataSources structure (code adapted from GNU-libc's popen() call).
355  *
356  * Aut viam inveniam aut faciam */
357
358 static FILE *
359 my_popen(struct RI *entry)
360 {
361     int pipedes[2];
362     FILE *stream;
363
364     /* Create the pipe */
365     if (pipe(pipedes) < 0)
366         return (NULL);
367
368     /* Fork off the child ("vfork() is like an OS orgasm.  All OS's want to
369      * do it, but most just end up faking it" - Chris Wedgwood).  If your OS
370      * supports it, you should try to use vfork() here because it's somewhat
371      * more efficient */
372 #if defined( sun ) || defined( __ultrix__ ) || defined( __osf__ ) || \
373         defined(__hpux)
374     entry->pid = vfork();
375 #else                           /*  */
376     entry->pid = fork();
377 #endif                          /* Unixen which have vfork() */
378     if (entry->pid == (pid_t) - 1) {
379         /* The fork failed */
380         close(pipedes[0]);
381         close(pipedes[1]);
382         return (NULL);
383     }
384
385     if (entry->pid == (pid_t) 0) {
386         struct passwd *passwd;
387
388         /* We are the child.  Make the read side of the pipe be stdout */
389         if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
390             exit(127);
391
392         /* Now that everything is set up, give up our permissions to make
393          * sure we don't read anything sensitive.  If the getpwnam() fails,
394          * we default to -1, which is usually nobody */
395         if (gatherer_uid == (uid_t)-1 && \
396             (passwd = getpwnam("nobody")) != NULL)
397             gatherer_uid = passwd->pw_uid;
398
399         setuid(gatherer_uid);
400
401         /* Close the pipe descriptors */
402         close(pipedes[STDIN_FILENO]);
403         close(pipedes[STDOUT_FILENO]);
404
405         /* Try and exec the program */
406         execl(entry->path, entry->path, entry->arg, NULL);
407
408         /* Die if the exec failed */
409         exit(127);
410     }
411
412     /* We are the parent.  Close the irrelevant side of the pipe and open
413      * the relevant side as a new stream.  Mark our side of the pipe to
414      * close on exec, so new children won't see it */
415     close(pipedes[STDOUT_FILENO]);
416
417 #ifdef FD_CLOEXEC
418     fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
419 #endif
420
421     stream = fdopen(pipedes[STDIN_FILENO], "r");
422
423     if (stream == NULL) {
424         int savedErrno = errno;
425
426         /* The stream couldn't be opened or the child structure couldn't be
427          * allocated.  Kill the child and close the other side of the pipe */
428         kill(entry->pid, SIGKILL);
429         if (stream == NULL)
430             close(pipedes[STDOUT_FILENO]);
431         else
432             fclose(stream);
433
434         waitpid(entry->pid, NULL, 0);
435
436         entry->pid = 0;
437         errno = savedErrno;
438         return (NULL);
439     }
440
441     return (stream);
442 }
443
444 static int
445 my_pclose(struct RI *entry)
446 {
447     int status = 0;
448
449     if (fclose(entry->pipe))
450         return (-1);
451
452     /* We ignore the return value from the process because some programs
453      * return funny values which would result in the input being discarded
454      * even if they executed successfully.  This isn't a problem because the
455      * result data size threshold will filter out any programs which exit
456      * with a usage message without producing useful output */
457     if (waitpid(entry->pid, NULL, 0) != entry->pid)
458         status = -1;
459
460     entry->pipe = NULL;
461     entry->pid = 0;
462     return (status);
463 }
464
465
466 /* Unix slow poll (without special support for Linux)
467  *
468  * If a few of the randomness sources create a large amount of output then
469  * the slowPoll() stops once the buffer has been filled (but before all the
470  * randomness sources have been sucked dry) so that the 'usefulness' factor
471  * remains below the threshold.  For this reason the gatherer buffer has to
472  * be fairly sizeable on moderately loaded systems.  This is something of a
473  * bug since the usefulness should be influenced by the amount of output as
474  * well as the source type */
475
476
477 static int
478 slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes )
479 {
480     int moreSources;
481     struct timeval tv;
482     fd_set fds;
483 #if defined( __hpux )
484     size_t maxFD = 0;
485 #else
486     int maxFD = 0;
487 #endif /* OS-specific brokenness */
488     int bufPos, i, usefulness = 0;
489
490
491     /* Fire up each randomness source */
492     FD_ZERO(&fds);
493     for (i = 0; dataSources[i].path != NULL; i++) {
494         /* Since popen() is a fairly heavy function, we check to see whether
495          * the executable exists before we try to run it */
496         if (access(dataSources[i].path, X_OK)) {
497             if( dbgfp && dbgall )
498                 fprintf(dbgfp, "%s not present%s\n", dataSources[i].path,
499                                dataSources[i].hasAlternative ?
500                                         ", has alternatives" : "");
501             dataSources[i].pipe = NULL;
502         }
503         else
504             dataSources[i].pipe = my_popen(&dataSources[i]);
505
506         if (dataSources[i].pipe != NULL) {
507             dataSources[i].pipeFD = fileno(dataSources[i].pipe);
508             if (dataSources[i].pipeFD > maxFD)
509                 maxFD = dataSources[i].pipeFD;
510
511 #ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */
512             fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK);
513 #else
514 #error O_NONBLOCK is missing
515 #endif
516
517             FD_SET(dataSources[i].pipeFD, &fds);
518             dataSources[i].length = 0;
519
520             /* If there are alternatives for this command, don't try and
521              * execute them */
522             while (dataSources[i].hasAlternative) {
523                 if( dbgfp && dbgall )
524                     fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path);
525                 i++;
526             }
527         }
528     }
529
530
531     /* Suck all the data we can get from each of the sources */
532     bufPos = 0;
533     moreSources = 1;
534     while (moreSources && bufPos <= gather_buffer_size) {
535         /* Wait for data to become available from any of the sources, with a
536          * timeout of 10 seconds.  This adds even more randomness since data
537          * becomes available in a nondeterministic fashion.  Kudos to HP's QA
538          * department for managing to ship a select() which breaks its own
539          * prototype */
540         tv.tv_sec = 10;
541         tv.tv_usec = 0;
542
543 #if defined( __hpux ) && ( OS_VERSION == 9 )
544         if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1)
545 #else  /*  */
546         if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1)
547 #endif /* __hpux */
548             break;
549
550         /* One of the sources has data available, read it into the buffer */
551         for (i = 0; dataSources[i].path != NULL; i++) {
552             if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) {
553                 size_t noBytes;
554
555                 if ((noBytes = fread(gather_buffer + bufPos, 1,
556                                      gather_buffer_size - bufPos,
557                                      dataSources[i].pipe)) == 0) {
558                     if (my_pclose(&dataSources[i]) == 0) {
559                         int total = 0;
560
561                         /* Try and estimate how much entropy we're getting
562                          * from a data source */
563                         if (dataSources[i].usefulness) {
564                             if (dataSources[i].usefulness < 0)
565                                 total = (dataSources[i].length + 999)
566                                         / -dataSources[i].usefulness;
567                             else
568                                 total = dataSources[i].length
569                                         / dataSources[i].usefulness;
570                         }
571                         if( dbgfp )
572                             fprintf(dbgfp,
573                                "%s %s contributed %d bytes, "
574                                "usefulness = %d\n", dataSources[i].path,
575                                (dataSources[i].arg != NULL) ?
576                                        dataSources[i].arg : "",
577                                       dataSources[i].length, total);
578                         if( dataSources[i].length )
579                             usefulness += total;
580                     }
581                     dataSources[i].pipe = NULL;
582                 }
583                 else {
584                     int currPos = bufPos;
585                     int endPos = bufPos + noBytes;
586
587                     /* Run-length compress the input byte sequence */
588                     while (currPos < endPos) {
589                         int ch = gather_buffer[currPos];
590
591                         /* If it's a single byte, just copy it over */
592                         if (ch != gather_buffer[currPos + 1]) {
593                             gather_buffer[bufPos++] = ch;
594                             currPos++;
595                         }
596                         else {
597                             int count = 0;
598
599                             /* It's a run of repeated bytes, replace them
600                              * with the byte count mod 256 */
601                             while ((ch == gather_buffer[currPos])
602                                     && currPos < endPos) {
603                                 count++;
604                                 currPos++;
605                             }
606                             gather_buffer[bufPos++] = count;
607                             noBytes -= count - 1;
608                         }
609                     }
610
611                     /* Remember the number of (compressed) bytes of input we
612                      * obtained */
613                     dataSources[i].length += noBytes;
614                 }
615             }
616         }
617
618         /* Check if there is more input available on any of the sources */
619         moreSources = 0;
620         FD_ZERO(&fds);
621         for (i = 0; dataSources[i].path != NULL; i++) {
622             if (dataSources[i].pipe != NULL) {
623                 FD_SET(dataSources[i].pipeFD, &fds);
624                 moreSources = 1;
625             }
626         }
627     }
628
629     if( dbgfp ) {
630         fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness);
631         fflush(dbgfp);
632     }
633     *nbytes = bufPos;
634     return usefulness;
635 }
636
637 /****************
638  * Start the gatherer process which writes messages of
639  * type GATHERER_MSG to pipedes
640  */
641 static void
642 start_gatherer( int pipefd )
643 {
644     FILE *dbgfp = NULL;
645     int dbgall;
646
647     {
648         const char *s = getenv("GNUPG_RNDUNIX_DBG");
649         if( s ) {
650             dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a");
651             if( !dbgfp )
652                 log_info("can't open debug file `%s': %s\n",
653                              s, strerror(errno) );
654             else
655                 fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid());
656         }
657         dbgall = !!getenv("GNUPG_RNDUNIX_DBGALL");
658     }
659     /* close all files but the ones we need */
660     {   int nmax, n1, n2, i;
661 #ifdef _SC_OPEN_MAX
662         if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) {
663 #ifdef _POSIX_OPEN_MAX
664             nmax = _POSIX_OPEN_MAX;
665 #else
666             nmax = 20; /* assume a reasonable value */
667 #endif
668         }
669 #else /*!_SC_OPEN_MAX*/
670         nmax = 20; /* assume a reasonable value */
671 #endif /*!_SC_OPEN_MAX*/
672         n1 = fileno( stderr );
673         n2 = dbgfp? fileno( dbgfp ) : -1;
674         for(i=0; i < nmax; i++ ) {
675             if( i != n1 && i != n2 && i != pipefd )
676                 close(i);
677         }
678         errno = 0;
679     }
680
681
682     /* Set up the buffer */
683     gather_buffer_size = GATHER_BUFSIZE;
684     gather_buffer = malloc( gather_buffer_size );
685     if( !gather_buffer ) {
686         log_error("out of core while allocating the gatherer buffer\n");
687         exit(2);
688     }
689
690     /* Reset the SIGC(H)LD handler to the system default.  This is necessary
691      * because if the program which cryptlib is a part of installs its own
692      * SIGC(H)LD handler, it will end up reaping the cryptlib children before
693      * cryptlib can.  As a result, my_pclose() will call waitpid() on a
694      * process which has already been reaped by the installed handler and
695      * return an error, so the read data won't be added to the randomness
696      * pool.  There are two types of SIGC(H)LD naming, the SysV SIGCLD and
697      * the BSD/Posix SIGCHLD, so we need to handle either possibility */
698 #ifdef SIGCLD
699     signal(SIGCLD, SIG_DFL);
700 #else
701     signal(SIGCHLD, SIG_DFL);
702 #endif
703
704     fclose(stderr);             /* Arrghh!!  It's Stuart code!! */
705
706     for(;;) {
707         GATHER_MSG msg;
708         size_t nbytes;
709         const char *p;
710
711         msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes );
712         p = gather_buffer;
713         while( nbytes ) {
714             msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes;
715             memcpy( msg.data, p, msg.ndata );
716             nbytes -= msg.ndata;
717             p += msg.ndata;
718
719             while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) {
720                 if( errno == EINTR )
721                     continue;
722                 if( errno == EAGAIN ) {
723                     struct timeval tv;
724                     tv.tv_sec = 0;
725                     tv.tv_usec = 50000;
726                     select(0, NULL, NULL, NULL, &tv);
727                     continue;
728                 }
729                 if( errno == EPIPE ) /* parent has exited, so give up */
730                    exit(0);
731
732                 /* we can't do very much here because stderr is closed */
733                 if( dbgfp )
734                     fprintf(dbgfp, "gatherer can't write to pipe: %s\n",
735                                     strerror(errno) );
736                 /* we start a new poll to give the system some time */
737                 nbytes = 0;
738                 break;
739             }
740         }
741     }
742     /* we are killed when the parent dies */
743 }
744
745
746 static int
747 read_a_msg( int fd, GATHER_MSG *msg )
748 {
749     char *buffer = (char*)msg;
750     size_t length = sizeof( *msg );
751     int n;
752
753     do {
754         do {
755             n = read(fd, buffer, length );
756         } while( n == -1 && errno == EINTR );
757         if( n == -1 )
758             return -1;
759         buffer += n;
760         length -= n;
761     } while( length );
762     return 0;
763 }
764
765
766 /****************
767  * Using a level of 0 should never block and better add nothing
768  * to the pool.  So this is just a dummy for this gatherer.
769  */
770 int
771 _gcry_rndunix_gather_random (void (*add)(const void*, size_t, int),
772                              int requester,
773                              size_t length, int level )
774 {
775     static pid_t gatherer_pid = 0;
776     static int pipedes[2];
777     GATHER_MSG msg;
778     size_t n;
779
780     if( !level )
781         return 0;
782
783     if( !gatherer_pid ) {
784         /* make sure we are not setuid */
785         if( getuid() != geteuid() )
786             BUG();
787         /* time to start the gatherer process */
788         if( pipe( pipedes ) ) {
789             log_error("pipe() failed: %s\n", strerror(errno));
790             return -1;
791         }
792         gatherer_pid = fork();
793         if( gatherer_pid == -1 ) {
794             log_error("can't for gatherer process: %s\n", strerror(errno));
795             return -1;
796         }
797         if( !gatherer_pid ) {
798             start_gatherer( pipedes[1] );
799             /* oops, can't happen */
800             return -1;
801         }
802     }
803
804     /* now read from the gatherer */
805     while( length ) {
806         int goodness;
807         ulong subtract;
808
809         if( read_a_msg( pipedes[0], &msg ) ) {
810             log_error("reading from gatherer pipe failed: %s\n",
811                                                             strerror(errno));
812             return -1;
813         }
814
815
816         if( level > 1 ) {
817             if( msg.usefulness > 30 )
818                 goodness = 100;
819             else if ( msg.usefulness )
820                 goodness = msg.usefulness * 100 / 30;
821             else
822                 goodness = 0;
823         }
824         else if( level ) {
825             if( msg.usefulness > 15 )
826                 goodness = 100;
827             else if ( msg.usefulness )
828                 goodness = msg.usefulness * 100 / 15;
829             else
830                 goodness = 0;
831         }
832         else
833             goodness = 100; /* goodness of level 0 is always 100 % */
834
835         n = msg.ndata;
836         if( n > length )
837             n = length;
838         (*add)( msg.data, n, requester );
839
840         /* this is the trick how we cope with the goodness */
841         subtract = (ulong)n * goodness / 100;
842         /* subtract at least 1 byte to avoid infinite loops */
843         length -= subtract ? subtract : 1;
844     }
845
846     return 0;
847 }