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