summaryrefslogtreecommitdiff
path: root/entropy.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2000-05-17 21:34:07 +1000
committerDamien Miller <djm@mindrot.org>2000-05-17 21:34:07 +1000
commit8d1fd57a971159c828ab778136ca6332f0ba8f34 (patch)
treeabf87d7010d72962088ba0e11f0d4f257e8c5a41 /entropy.c
parent95fe91bd84d7613ce37cb8b38212c4301610639f (diff)
- Fix from Andre Lucas <andre.lucas@dial.pipex.com>
- Fixes command line printing segfaults (spotter: Bladt Norbert) - Fixes erroneous printing of debug messages to syslog - Fixes utmp for MacOS X (spotter: Aristedes Maniatis) - Gives useful error message if PRNG initialisation fails - Reduced ssh startup delay - Measures cumulative command time rather than the time between reads after select() - 'fixprogs' perl script to eliminate non-working entropy commands, and optionally run 'ent' to measure command entropy
Diffstat (limited to 'entropy.c')
-rw-r--r--entropy.c79
1 files changed, 58 insertions, 21 deletions
diff --git a/entropy.c b/entropy.c
index 2a1db4202..79ef93ac6 100644
--- a/entropy.c
+++ b/entropy.c
@@ -35,7 +35,7 @@
35#include <openssl/rand.h> 35#include <openssl/rand.h>
36#include <openssl/sha.h> 36#include <openssl/sha.h>
37 37
38RCSID("$Id: entropy.c,v 1.9 2000/05/11 09:10:58 damien Exp $"); 38RCSID("$Id: entropy.c,v 1.10 2000/05/17 11:34:08 damien Exp $");
39 39
40#ifdef EGD_SOCKET 40#ifdef EGD_SOCKET
41#ifndef offsetof 41#ifndef offsetof
@@ -133,6 +133,8 @@ typedef struct
133 char *path; 133 char *path;
134 /* argv to pass to executable */ 134 /* argv to pass to executable */
135 char *args[5]; 135 char *args[5];
136 /* full command string (debug) */
137 char *cmdstring;
136} entropy_source_t; 138} entropy_source_t;
137 139
138double stir_from_system(void); 140double stir_from_system(void);
@@ -211,8 +213,8 @@ stir_from_programs(void)
211 213
212/* FIXME: turn this off later */ 214/* FIXME: turn this off later */
213#if 1 215#if 1
214 debug("Got %0.2f bytes of entropy from %s", entropy_estimate, 216 debug("Got %0.2f bytes of entropy from '%s'", entropy_estimate,
215 entropy_sources[c].path); 217 entropy_sources[c].cmdstring);
216#endif 218#endif
217 219
218 total_entropy_estimate += entropy_estimate; 220 total_entropy_estimate += entropy_estimate;
@@ -225,9 +227,8 @@ stir_from_programs(void)
225 } else { 227 } else {
226/* FIXME: turn this off later */ 228/* FIXME: turn this off later */
227#if 1 229#if 1
228 debug("Command '%s %s %s' disabled (badness %d)", 230 debug("Command '%s' disabled (badness %d)",
229 entropy_sources[c].path, entropy_sources[c].args[1], 231 entropy_sources[c].cmdstring, entropy_sources[c].badness);
230 entropy_sources[c].args[2], entropy_sources[c].badness);
231#endif 232#endif
232 233
233 if (entropy_sources[c].badness > 0) 234 if (entropy_sources[c].badness > 0)
@@ -286,6 +287,17 @@ stir_rusage(int who, double entropy_estimate)
286#endif /* _HAVE_GETRUSAGE */ 287#endif /* _HAVE_GETRUSAGE */
287} 288}
288 289
290
291static
292int
293_get_timeval_msec_difference(struct timeval *t1, struct timeval *t2) {
294 int secdiff, usecdiff;
295
296 secdiff = t2->tv_sec - t1->tv_sec;
297 usecdiff = (secdiff*1000000) + (t2->tv_usec - t1->tv_usec);
298 return (int)(usecdiff / 1000);
299}
300
289double 301double
290hash_output_from_command(entropy_source_t *src, char *hash) 302hash_output_from_command(entropy_source_t *src, char *hash)
291{ 303{
@@ -293,9 +305,11 @@ hash_output_from_command(entropy_source_t *src, char *hash)
293 int p[2]; 305 int p[2];
294 fd_set rdset; 306 fd_set rdset;
295 int cmd_eof = 0, error_abort = 0; 307 int cmd_eof = 0, error_abort = 0;
308 struct timeval tv_start, tv_current;
309 int msec_elapsed = 0;
296 pid_t pid; 310 pid_t pid;
297 int status; 311 int status;
298 char buf[2048]; 312 char buf[16384];
299 int bytes_read; 313 int bytes_read;
300 int total_bytes_read; 314 int total_bytes_read;
301 SHA_CTX sha; 315 SHA_CTX sha;
@@ -309,6 +323,8 @@ hash_output_from_command(entropy_source_t *src, char *hash)
309 if (pipe(p) == -1) 323 if (pipe(p) == -1)
310 fatal("Couldn't open pipe: %s", strerror(errno)); 324 fatal("Couldn't open pipe: %s", strerror(errno));
311 325
326 (void)gettimeofday(&tv_start, NULL); /* record start time */
327
312 switch (pid = fork()) { 328 switch (pid = fork()) {
313 case -1: /* Error */ 329 case -1: /* Error */
314 close(p[0]); 330 close(p[0]);
@@ -324,8 +340,8 @@ hash_output_from_command(entropy_source_t *src, char *hash)
324 close(devnull); 340 close(devnull);
325 341
326 execv(src->path, (char**)(src->args)); 342 execv(src->path, (char**)(src->args));
327 debug("(child) Couldn't exec '%s %s %s': %s", src->path, 343 debug("(child) Couldn't exec '%s': %s", src->cmdstring,
328 src->args[1], src->args[2], strerror(errno)); 344 strerror(errno));
329 src->badness = src->sticky_badness = 128; 345 src->badness = src->sticky_badness = 128;
330 _exit(-1); 346 _exit(-1);
331 default: /* Parent */ 347 default: /* Parent */
@@ -343,13 +359,24 @@ hash_output_from_command(entropy_source_t *src, char *hash)
343 while (!error_abort && !cmd_eof) { 359 while (!error_abort && !cmd_eof) {
344 int ret; 360 int ret;
345 struct timeval tv; 361 struct timeval tv;
362 int msec_remaining;
363
364 (void) gettimeofday(&tv_current, 0);
365 msec_elapsed = _get_timeval_msec_difference(
366 &tv_start, &tv_current);
367 if (msec_elapsed >= entropy_timeout_current) {
368 error_abort=1;
369 continue;
370 }
371 msec_remaining = entropy_timeout_current - msec_elapsed;
346 372
347 FD_ZERO(&rdset); 373 FD_ZERO(&rdset);
348 FD_SET(p[0], &rdset); 374 FD_SET(p[0], &rdset);
349 tv.tv_sec = entropy_timeout_current / 1000; 375 tv.tv_sec = msec_remaining / 1000;
350 tv.tv_usec = (entropy_timeout_current % 1000) * 1000; 376 tv.tv_usec = (msec_remaining % 1000) * 1000;
351 377
352 ret = select(p[0]+1, &rdset, NULL, NULL, &tv); 378 ret = select(p[0]+1, &rdset, NULL, NULL, &tv);
379
353 switch (ret) { 380 switch (ret) {
354 case 0: 381 case 0:
355 /* timer expired */ 382 /* timer expired */
@@ -363,17 +390,19 @@ hash_output_from_command(entropy_source_t *src, char *hash)
363 error_abort = 1; 390 error_abort = 1;
364 break; 391 break;
365 } 392 }
366 SHA1_Update(&sha, buf, bytes_read); 393 if (bytes_read) {
367 total_bytes_read += bytes_read; 394 SHA1_Update(&sha, buf, bytes_read);
368 RAND_add(&bytes_read, sizeof(&bytes_read), 0.0); 395 total_bytes_read += bytes_read;
369 cmd_eof = bytes_read ? 0 : 1; 396 RAND_add(&bytes_read, sizeof(&bytes_read), 0.0);
397 } else
398 cmd_eof = 1;
370 399
371 break; 400 break;
372 401
373 case -1: 402 case -1:
374 default: 403 default:
375 error("Command '%s %s': select() failed: %s", src->path, src->args[1], 404 debug("Command '%s': select() failed: %s", src->cmdstring,
376 strerror(errno)); 405 strerror(errno));
377 error_abort = 1; 406 error_abort = 1;
378 break; 407 break;
379 } /* switch ret */ 408 } /* switch ret */
@@ -384,11 +413,12 @@ hash_output_from_command(entropy_source_t *src, char *hash)
384 SHA1_Final(hash, &sha); 413 SHA1_Final(hash, &sha);
385 414
386 close(p[0]); 415 close(p[0]);
416
417 debug("Time elapsed: %d msec", msec_elapsed);
387 418
388 if (waitpid(pid, &status, 0) == -1) { 419 if (waitpid(pid, &status, 0) == -1) {
389 error("Couldn't wait for child '%s %s' completion: %s", src->path, 420 debug("Couldn't wait for child '%s' completion: %s", src->cmdstring,
390 src->args[1], strerror(errno)); 421 strerror(errno));
391 /* return(-1); */ /* FIXME: (ATL) this doesn't feel right */
392 return(0.0); 422 return(0.0);
393 } 423 }
394 424
@@ -398,7 +428,7 @@ hash_output_from_command(entropy_source_t *src, char *hash)
398 /* closing p[0] on timeout causes the entropy command to 428 /* closing p[0] on timeout causes the entropy command to
399 * SIGPIPE. Take whatever output we got, and mark this command 429 * SIGPIPE. Take whatever output we got, and mark this command
400 * as slow */ 430 * as slow */
401 debug("Command %s %s timed out", src->path, src->args[1]); 431 debug("Command '%s' timed out", src->cmdstring);
402 src->sticky_badness *= 2; 432 src->sticky_badness *= 2;
403 src->badness = src->sticky_badness; 433 src->badness = src->sticky_badness;
404 return(total_bytes_read); 434 return(total_bytes_read);
@@ -615,6 +645,10 @@ prng_read_commands(char *cmdfilename)
615 continue; 645 continue;
616 } 646 }
617 647
648 /* save the command for debug messages */
649 entcmd[cur_cmd].cmdstring = (char*) xmalloc(strlen(cmd)+1);
650 strncpy(entcmd[cur_cmd].cmdstring, cmd, strlen(cmd)+1);
651
618 /* split the command args */ 652 /* split the command args */
619 cp = strtok(cmd, WHITESPACE); 653 cp = strtok(cmd, WHITESPACE);
620 arg = 0; argv = NULL; 654 arg = 0; argv = NULL;
@@ -713,6 +747,9 @@ seed_rng(void)
713 debug("%i bytes from programs", (int)stir_from_programs()); 747 debug("%i bytes from programs", (int)stir_from_programs());
714 debug("OpenSSL random status is now %i\n", RAND_status()); 748 debug("OpenSSL random status is now %i\n", RAND_status());
715 749
750 if (!RAND_status())
751 fatal("Couldn't initialise builtin random number generator -- exiting.");
752
716 if (!prng_seed_loaded) 753 if (!prng_seed_loaded)
717 { 754 {
718 prng_seed_loaded = 1; 755 prng_seed_loaded = 1;