diff options
Diffstat (limited to 'entropy.c')
-rw-r--r-- | entropy.c | 79 |
1 files changed, 58 insertions, 21 deletions
@@ -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 | ||
38 | RCSID("$Id: entropy.c,v 1.9 2000/05/11 09:10:58 damien Exp $"); | 38 | RCSID("$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 | ||
138 | double stir_from_system(void); | 140 | double 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 | |||
291 | static | ||
292 | int | ||
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 | |||
289 | double | 301 | double |
290 | hash_output_from_command(entropy_source_t *src, char *hash) | 302 | hash_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; |