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