+ unsigned char buf[32];
+
+ debug("Seeding random number generator");
+
+ if (!get_random_bytes(buf, sizeof(buf))) {
+ if (!RAND_status())
+ fatal("Entropy collection failed and entropy exhausted");
+ } else {
+ RAND_add(buf, sizeof(buf), sizeof(buf));
+ }
+
+ memset(buf, '\0', sizeof(buf));
+}
+
+void
+init_rng(void)
+{
+ check_openssl_version();
+}
+
+#else /* defined(USE_PRNGD) || defined(RANDOM_POOL) */
+
+/*
+ * FIXME: proper entropy estimations. All current values are guesses
+ * FIXME: (ATL) do estimates at compile time?
+ * FIXME: More entropy sources
+ */
+
+/* slow command timeouts (all in milliseconds) */
+/* static int entropy_timeout_default = ENTROPY_TIMEOUT_MSEC; */
+static int entropy_timeout_current = ENTROPY_TIMEOUT_MSEC;
+
+static int prng_seed_saved = 0;
+static int prng_initialised = 0;
+uid_t original_uid;
+
+typedef struct
+{
+ /* Proportion of data that is entropy */
+ double rate;
+ /* Counter goes positive if this command times out */
+ unsigned int badness;
+ /* Increases by factor of two each timeout */
+ unsigned int sticky_badness;
+ /* Path to executable */
+ char *path;
+ /* argv to pass to executable */
+ char *args[5];
+ /* full command string (debug) */
+ char *cmdstring;
+} entropy_source_t;
+
+double stir_from_system(void);
+double stir_from_programs(void);
+double stir_gettimeofday(double entropy_estimate);
+double stir_clock(double entropy_estimate);
+double stir_rusage(int who, double entropy_estimate);
+double hash_output_from_command(entropy_source_t *src, char *hash);
+
+/* this is initialised from a file, by prng_read_commands() */
+entropy_source_t *entropy_sources = NULL;
+
+double
+stir_from_system(void)
+{
+ double total_entropy_estimate;
+ long int i;
+
+ total_entropy_estimate = 0;
+
+ i = getpid();
+ RAND_add(&i, sizeof(i), 0.5);
+ total_entropy_estimate += 0.1;
+
+ i = getppid();
+ RAND_add(&i, sizeof(i), 0.5);
+ total_entropy_estimate += 0.1;
+
+ i = getuid();
+ RAND_add(&i, sizeof(i), 0.0);
+ i = getgid();
+ RAND_add(&i, sizeof(i), 0.0);
+
+ total_entropy_estimate += stir_gettimeofday(1.0);
+ total_entropy_estimate += stir_clock(0.5);
+ total_entropy_estimate += stir_rusage(RUSAGE_SELF, 2.0);
+
+ return(total_entropy_estimate);
+}
+
+double
+stir_from_programs(void)
+{
+ int i;
+ int c;
+ double entropy_estimate;
+ double total_entropy_estimate;
+ char hash[SHA_DIGEST_LENGTH];
+
+ total_entropy_estimate = 0;
+ for(i = 0; i < NUM_ENTROPY_RUNS; i++) {
+ c = 0;
+ while (entropy_sources[c].path != NULL) {
+
+ if (!entropy_sources[c].badness) {
+ /* Hash output from command */
+ entropy_estimate = hash_output_from_command(&entropy_sources[c], hash);
+
+ /* Scale back entropy estimate according to command's rate */
+ entropy_estimate *= entropy_sources[c].rate;
+
+ /* Upper bound of entropy estimate is SHA_DIGEST_LENGTH */
+ if (entropy_estimate > SHA_DIGEST_LENGTH)
+ entropy_estimate = SHA_DIGEST_LENGTH;
+
+ /* Scale back estimates for subsequent passes through list */
+ entropy_estimate /= SCALE_PER_RUN * (i + 1.0);
+
+ /* Stir it in */
+ RAND_add(hash, sizeof(hash), entropy_estimate);
+
+ debug3("Got %0.2f bytes of entropy from '%s'", entropy_estimate,
+ entropy_sources[c].cmdstring);
+
+ total_entropy_estimate += entropy_estimate;
+
+ /* Execution times should be a little unpredictable */
+ total_entropy_estimate += stir_gettimeofday(0.05);
+ total_entropy_estimate += stir_clock(0.05);
+ total_entropy_estimate += stir_rusage(RUSAGE_SELF, 0.1);
+ total_entropy_estimate += stir_rusage(RUSAGE_CHILDREN, 0.1);
+ } else {
+ debug2("Command '%s' disabled (badness %d)",
+ entropy_sources[c].cmdstring, entropy_sources[c].badness);
+
+ if (entropy_sources[c].badness > 0)
+ entropy_sources[c].badness--;
+ }
+
+ c++;
+ }
+ }
+
+ return(total_entropy_estimate);
+}
+
+double
+stir_gettimeofday(double entropy_estimate)
+{
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL) == -1)
+ fatal("Couldn't gettimeofday: %s", strerror(errno));
+
+ RAND_add(&tv, sizeof(tv), entropy_estimate);
+
+ return(entropy_estimate);
+}
+
+double
+stir_clock(double entropy_estimate)
+{
+#ifdef HAVE_CLOCK
+ clock_t c;
+
+ c = clock();
+ RAND_add(&c, sizeof(c), entropy_estimate);
+
+ return(entropy_estimate);
+#else /* _HAVE_CLOCK */
+ return(0);
+#endif /* _HAVE_CLOCK */
+}
+
+double
+stir_rusage(int who, double entropy_estimate)
+{
+#ifdef HAVE_GETRUSAGE
+ struct rusage ru;
+
+ if (getrusage(who, &ru) == -1)
+ return(0);
+
+ RAND_add(&ru, sizeof(ru), entropy_estimate);
+
+ return(entropy_estimate);
+#else /* _HAVE_GETRUSAGE */
+ return(0);
+#endif /* _HAVE_GETRUSAGE */
+}
+
+
+static int
+_get_timeval_msec_difference(struct timeval *t1, struct timeval *t2) {
+ int secdiff, usecdiff;
+
+ secdiff = t2->tv_sec - t1->tv_sec;
+ usecdiff = (secdiff*1000000) + (t2->tv_usec - t1->tv_usec);
+ return (int)(usecdiff / 1000);
+}
+
+double
+hash_output_from_command(entropy_source_t *src, char *hash)
+{
+ static int devnull = -1;