1
/****************************************************************************
4
* Unix Randomness-Gathering Code *
6
* Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. *
7
* Heavily modified for GnuPG by Werner Koch *
10
****************************************************************************/
12
/* This module is part of the cryptlib continuously seeded pseudorandom
13
number generator. For usage conditions, see lib_rand.c
15
[Here is the notice from lib_rand.c:]
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".
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:
27
1. Redistributions of source code must retain the above copyright notice
28
and this permission notice in its entirety.
30
2. Redistributions in binary form must reproduce the copyright notice in
31
the documentation and/or other materials provided with the distribution.
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.
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.
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 */
48
/* General includes */
59
/* OS-specific includes */
62
/* Somewhere in the morass of system-specific cruft which OSF/1 pulls in
63
* via the following includes are various endianness defines, so we
64
* undefine the cryptlib ones, which aren't really needed for this module
74
#include <sys/errno.h>
77
#include <sys/time.h> /* SCO and SunOS need this before resource.h */
79
#include <sys/resource.h>
81
#if defined( _AIX ) || defined( __QNX__ )
82
#include <sys/select.h>
83
#endif /* _AIX || __QNX__ */
87
#include <sys/signal.h>
90
#include <sys/types.h> /* Verschiedene komische Typen */
91
#if defined( __hpux ) && ( OS_VERSION == 9 )
93
#endif /* __hpux 9.x, after that it's in unistd.h */
95
/* #include <kitchensink.h> */
102
#include "types.h" /* for byte and u32 typedefs */
103
#include "algorithms.h"
107
#define EAGAIN EWOULDBLOCK
110
#define STDIN_FILENO 0
112
#ifndef STDOUT_FILENO
113
#define STDOUT_FILENO 1
116
#define GATHER_BUFSIZE 49152 /* Usually about 25K are filled */
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
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.
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).
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.
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).
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.
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
177
#define SC( weight ) ( 1024 / weight ) /* Scale factor */
178
#define SC_0 16384 /* SC( SC_0 ) evalutes to 0 */
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 */
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 },
264
{ "/usr/bsd/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 },
267
{ "/etc/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 },
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
297
{ "/bin/pidin", "-F%A%B%c%d%E%I%J%K%m%M%n%N%p%P%S%s%T", SC(0.3),
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 },
310
{ NULL, NULL, 0, NULL, 0, 0, 0, 0 }
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;
317
/* The message structure used to communicate with the parent */
319
int usefulness; /* usefulness of data */
320
int ndata; /* valid bytes in data */
321
char data[500]; /* gathered data */
327
waitpid(pid_t pid, int *statptr, int options)
330
return wait4(pid, statptr, options, NULL);
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) {
342
statptr = &dummystat;
343
while (((tmp_pid = wait3(statptr, options, 0)) != pid) &&
344
(tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
352
/* Under SunOS popen() doesn't record the pid of the child process. When
353
* pclose() is called, instead of calling waitpid() for the correct child, it
354
* calls wait() repeatedly until the right child is reaped. The problem is
355
* that this reaps any other children that happen to have died at that
356
* moment, and when their pclose() comes along, the process hangs forever.
357
* The fix is to use a wrapper for popen()/pclose() which saves the pid in
358
* the dataSources structure (code adapted from GNU-libc's popen() call).
360
* Aut viam inveniam aut faciam */
363
my_popen(struct RI *entry)
369
/* Create the pipe */
370
if (pipe(pipedes) < 0)
373
/* Fork off the child ("vfork() is like an OS orgasm. All OS's want to
374
* do it, but most just end up faking it" - Chris Wedgwood). If your OS
375
* supports it, you should try to use vfork() here because it's somewhat
377
#if defined( sun ) || defined( __ultrix__ ) || defined( __osf__ ) || \
379
entry->pid = vfork();
382
#endif /* Unixen which have vfork() */
383
if (entry->pid == (pid_t) - 1) {
384
/* The fork failed */
390
if (entry->pid == (pid_t) 0) {
391
struct passwd *passwd;
394
/* We are the child. Make the read side of the pipe be stdout */
395
if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
397
/* Connect the other standard handles to the bit bucket. */
398
if ((fd = open ("/dev/null", O_RDWR)) != -1) {
399
dup2 (fd, STDIN_FILENO);
400
dup2 (fd, STDERR_FILENO);
404
/* Now that everything is set up, give up our permissions to make
405
* sure we don't read anything sensitive. If the getpwnam() fails,
406
* we default to -1, which is usually nobody */
407
if (gatherer_uid == (uid_t)-1 && \
408
(passwd = getpwnam("nobody")) != NULL)
409
gatherer_uid = passwd->pw_uid;
411
setuid(gatherer_uid);
413
/* Close the pipe descriptors. */
414
close(pipedes[STDIN_FILENO]);
415
close(pipedes[STDOUT_FILENO]);
417
/* Try and exec the program */
418
execl(entry->path, entry->path, entry->arg, NULL);
420
/* Die if the exec failed */
424
/* We are the parent. Close the irrelevant side of the pipe and open
425
* the relevant side as a new stream. Mark our side of the pipe to
426
* close on exec, so new children won't see it */
427
close(pipedes[STDOUT_FILENO]);
430
fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
433
stream = fdopen(pipedes[STDIN_FILENO], "r");
435
if (stream == NULL) {
436
int savedErrno = errno;
438
/* The stream couldn't be opened or the child structure couldn't be
439
* allocated. Kill the child and close the other side of the pipe */
440
kill(entry->pid, SIGKILL);
442
close(pipedes[STDOUT_FILENO]);
446
waitpid(entry->pid, NULL, 0);
457
my_pclose(struct RI *entry)
461
if (fclose(entry->pipe))
464
/* We ignore the return value from the process because some programs
465
* return funny values which would result in the input being discarded
466
* even if they executed successfully. This isn't a problem because the
467
* result data size threshold will filter out any programs which exit
468
* with a usage message without producing useful output */
469
if (waitpid(entry->pid, NULL, 0) != entry->pid)
478
/* Unix slow poll (without special support for Linux)
480
* If a few of the randomness sources create a large amount of output then
481
* the slowPoll() stops once the buffer has been filled (but before all the
482
* randomness sources have been sucked dry) so that the 'usefulness' factor
483
* remains below the threshold. For this reason the gatherer buffer has to
484
* be fairly sizeable on moderately loaded systems. This is something of a
485
* bug since the usefulness should be influenced by the amount of output as
486
* well as the source type */
490
slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes )
495
#if defined( __hpux )
499
#endif /* OS-specific brokenness */
500
int bufPos, i, usefulness = 0;
503
/* Fire up each randomness source */
505
for (i = 0; dataSources[i].path != NULL; i++) {
506
/* Since popen() is a fairly heavy function, we check to see whether
507
* the executable exists before we try to run it */
508
if (access(dataSources[i].path, X_OK)) {
509
if( dbgfp && dbgall )
510
fprintf(dbgfp, "%s not present%s\n", dataSources[i].path,
511
dataSources[i].hasAlternative ?
512
", has alternatives" : "");
513
dataSources[i].pipe = NULL;
516
dataSources[i].pipe = my_popen(&dataSources[i]);
518
if (dataSources[i].pipe != NULL) {
519
dataSources[i].pipeFD = fileno(dataSources[i].pipe);
520
if (dataSources[i].pipeFD > maxFD)
521
maxFD = dataSources[i].pipeFD;
522
#ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */
523
fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK);
525
FD_SET(dataSources[i].pipeFD, &fds);
526
dataSources[i].length = 0;
528
/* If there are alternatives for this command, don't try and
530
while (dataSources[i].hasAlternative) {
531
if( dbgfp && dbgall )
532
fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path);
539
/* Suck all the data we can get from each of the sources */
542
while (moreSources && bufPos <= gather_buffer_size) {
543
/* Wait for data to become available from any of the sources, with a
544
* timeout of 10 seconds. This adds even more randomness since data
545
* becomes available in a nondeterministic fashion. Kudos to HP's QA
546
* department for managing to ship a select() which breaks its own
551
#if defined( __hpux ) && ( OS_VERSION == 9 )
552
if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1)
554
if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1)
558
/* One of the sources has data available, read it into the buffer */
559
for (i = 0; dataSources[i].path != NULL; i++) {
560
if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) {
563
if ((noBytes = fread(gather_buffer + bufPos, 1,
564
gather_buffer_size - bufPos,
565
dataSources[i].pipe)) == 0) {
566
if (my_pclose(&dataSources[i]) == 0) {
569
/* Try and estimate how much entropy we're getting
570
* from a data source */
571
if (dataSources[i].usefulness) {
572
if (dataSources[i].usefulness < 0)
573
total = (dataSources[i].length + 999)
574
/ -dataSources[i].usefulness;
576
total = dataSources[i].length
577
/ dataSources[i].usefulness;
581
"%s %s contributed %d bytes, "
582
"usefulness = %d\n", dataSources[i].path,
583
(dataSources[i].arg != NULL) ?
584
dataSources[i].arg : "",
585
dataSources[i].length, total);
586
if( dataSources[i].length )
589
dataSources[i].pipe = NULL;
592
int currPos = bufPos;
593
int endPos = bufPos + noBytes;
595
/* Run-length compress the input byte sequence */
596
while (currPos < endPos) {
597
int ch = gather_buffer[currPos];
599
/* If it's a single byte, just copy it over */
600
if (ch != gather_buffer[currPos + 1]) {
601
gather_buffer[bufPos++] = ch;
607
/* It's a run of repeated bytes, replace them
608
* with the byte count mod 256 */
609
while ((ch == gather_buffer[currPos])
610
&& currPos < endPos) {
614
gather_buffer[bufPos++] = count;
615
noBytes -= count - 1;
619
/* Remember the number of (compressed) bytes of input we
621
dataSources[i].length += noBytes;
626
/* Check if there is more input available on any of the sources */
629
for (i = 0; dataSources[i].path != NULL; i++) {
630
if (dataSources[i].pipe != NULL) {
631
FD_SET(dataSources[i].pipeFD, &fds);
638
fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness);
646
* Start the gatherer process which writes messages of
647
* type GATHERER_MSG to pipedes
650
start_gatherer( int pipefd )
655
#ifdef ENABLE_SELINUX_HACKS
656
/* We don't allow writing to the log file because this might be
657
sued to corrupt a secured file. Given that this is used as a
658
library by the ../g10/ code, we can't access the check function
659
from ../g10/misc.c. */
663
const char *s = getenv("GNUPG_RNDUNIX_DBG");
665
dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a");
667
g10_log_info("can't open debug file `%s': %s\n",
668
s, strerror(errno) );
670
fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid());
672
dbgall = !!getenv("GNUPG_RNDUNIX_DBGALL");
676
/* Set up the buffer */
677
gather_buffer_size = GATHER_BUFSIZE;
678
gather_buffer = malloc( gather_buffer_size );
679
if( !gather_buffer ) {
680
g10_log_error("out of core while allocating the gatherer buffer\n");
684
/* Reset the SIGC(H)LD handler to the system default. This is necessary
685
* because if the program which cryptlib is a part of installs its own
686
* SIGC(H)LD handler, it will end up reaping the cryptlib children before
687
* cryptlib can. As a result, my_pclose() will call waitpid() on a
688
* process which has already been reaped by the installed handler and
689
* return an error, so the read data won't be added to the randomness
690
* pool. There are two types of SIGC(H)LD naming, the SysV SIGCLD and
691
* the BSD/Posix SIGCHLD, so we need to handle either possibility */
693
signal(SIGCLD, SIG_DFL);
695
signal(SIGCHLD, SIG_DFL);
699
/* Arrghh!! It's Stuart code!! */
700
/* (close all files but the ones we need) */
703
if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) {
704
#ifdef _POSIX_OPEN_MAX
705
nmax = _POSIX_OPEN_MAX;
707
nmax = 20; /* assume a reasonable value */
711
nmax = 20; /* assume a reasonable value */
715
if ((fd = open ("/dev/null", O_RDWR)) != -1) {
716
dup2 (fd, STDIN_FILENO);
717
dup2 (fd, STDOUT_FILENO);
718
dup2 (fd, STDERR_FILENO);
722
n1 = dbgfp? fileno (dbgfp) : -1;
723
for(i=0; i < nmax; i++ ) {
724
if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO
725
&& i != n1 && i != pipefd )
737
msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes );
740
msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes;
741
memcpy( msg.data, p, msg.ndata );
745
while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) {
748
if( errno == EAGAIN ) {
752
select(0, NULL, NULL, NULL, &tv);
755
if( errno == EPIPE ) /* parent has exited, so give up */
758
/* we can't do very much here because stderr is closed */
760
fprintf(dbgfp, "gatherer can't write to pipe: %s\n",
762
/* we start a new poll to give the system some time */
768
/* we are killed when the parent dies */
773
read_a_msg( int fd, GATHER_MSG *msg )
775
char *buffer = (char*)msg;
776
size_t length = sizeof( *msg );
781
n = read(fd, buffer, length );
782
} while( n == -1 && errno == EINTR );
793
* Using a level of 0 should never block and better add nothing
794
* to the pool. So this is just a dummy for this gatherer.
797
rndunix_gather_random( void (*add)(const void*, size_t, int), int requester,
798
size_t length, int level )
800
static pid_t gatherer_pid = 0;
801
static int pipedes[2];
808
if( !gatherer_pid ) {
809
/* make sure we are not setuid */
810
if( getuid() != geteuid() )
812
/* time to start the gatherer process */
813
if( pipe( pipedes ) ) {
814
g10_log_error("pipe() failed: %s\n", strerror(errno));
817
gatherer_pid = fork();
818
if( gatherer_pid == -1 ) {
819
g10_log_error("can't for gatherer process: %s\n", strerror(errno));
822
if( !gatherer_pid ) {
823
start_gatherer( pipedes[1] );
824
/* oops, can't happen */
829
/* now read from the gatherer */
834
if( read_a_msg( pipedes[0], &msg ) ) {
835
g10_log_error("reading from gatherer pipe failed: %s\n",
842
if( msg.usefulness > 30 )
844
else if ( msg.usefulness )
845
goodness = msg.usefulness * 100 / 30;
850
if( msg.usefulness > 15 )
852
else if ( msg.usefulness )
853
goodness = msg.usefulness * 100 / 15;
858
goodness = 100; /* goodness of level 0 is always 100 % */
863
(*add)( msg.data, n, requester );
865
/* this is the trick how e cope with the goodness */
866
subtract = (ulong)n * goodness / 100;
867
/* subtract at least 1 byte to avoid infinite loops */
868
length -= subtract ? subtract : 1;
874
#endif /*USE_RNDUNIX*/