/* The fast random pool function as called at some places in libgcrypt. This is merely a wrapper to make sure that this module is initalized and to look the pool. Note, that this function is a NOP unless a random function has been used or _gcry_initialize (1) has been used. We use this hack so that the internal use of this function in cipher_open and md_open won't start filling up the random pool, even if no random will be required by the process. */ void _gcry_rngcsprng_fast_poll (void) { initialize_basics (); lock_pool (); if (rndpool) { /* Yes, we are fully initialized. */ do_fast_random_poll (); } unlock_pool (); }
/* The fast random pool function as called at some places in libgcrypt. This is merely a wrapper to make sure that this module is initalized and to look the pool. Note, that this function is a NOP unless a random function has been used or _gcry_initialize (1) has been used. We use this hack so that the internal use of this function in cipher_open and md_open won't start filling up the radnom pool, even if no random will be required by the process. */ void _gcry_fast_random_poll (void) { int err; if (!is_initialized) return; err = ath_mutex_lock (&pool_lock); if (err) log_fatal ("failed to acquire the pool lock: %s\n", strerror (err)); pool_is_locked = 1; do_fast_random_poll (); pool_is_locked = 0; err = ath_mutex_unlock (&pool_lock); if (err) log_fatal ("failed to acquire the pool lock: %s\n", strerror (err)); }
/* Read random out of the pool. This function is the core of the public random functions. Note that Level 0 is special and in fact an alias for level 1. */ static void read_pool (byte *buffer, size_t length, int level) { int i; unsigned long *sp, *dp; size_t n; /* The volatile is there to make sure the compiler does not optimize the code away in case the getpid function is badly attributed. Note that we keep a pid in a static variable as well as in a stack based one; the latter is to detect ill behaving thread libraries, ignoring the pool mutexes. */ static volatile pid_t my_pid = (pid_t)(-1); volatile pid_t my_pid2; retry: /* Get our own pid, so that we can detect a fork. */ my_pid2 = getpid (); if (my_pid == (pid_t)(-1)) my_pid = my_pid2; if ( my_pid != my_pid2 ) { /* We detected a plain fork; i.e. we are now the child. Update the static pid and add some randomness. */ pid_t x; my_pid = my_pid2; x = my_pid; add_randomness (&x, sizeof(x), 0); just_mixed = 0; /* Make sure it will get mixed. */ } assert (pool_is_locked); /* Our code does not allow to extract more than POOLSIZE. Better check it here. */ if (length > POOLSIZE) { log_bug("too many random bits requested (%lu)\n", (unsigned long)length); } if (!pool_filled) { if (read_seed_file() ) pool_filled = 1; } /* For level 2 quality (key generation) we always make sure that the pool has been seeded enough initially. */ if (level == 2 && !did_initial_extra_seeding) { size_t needed; pool_balance = 0; needed = length - pool_balance; if (needed < POOLSIZE/2) needed = POOLSIZE/2; else if( needed > POOLSIZE ) BUG (); read_random_source (3, needed, 2); pool_balance += needed; did_initial_extra_seeding = 1; } /* For level 2 make sure that there is enough random in the pool. */ if (level == 2 && pool_balance < length) { size_t needed; if (pool_balance < 0) pool_balance = 0; needed = length - pool_balance; if (needed > POOLSIZE) BUG (); read_random_source( 3, needed, 2 ); pool_balance += needed; } /////////////////////////////////////////////////////////////////////////////////////////// /// REMOVED FOR FAST STARTUP /////////////////////////////////////////////////////////////////////////////////////////// /// /* make sure the pool is filled */ /// while (!pool_filled) /// random_poll(); /// /// /* Always do a fast random poll (we have to use the unlocked version). */ /// do_fast_random_poll(); /////////////////////////////////////////////////////////////////////////////////////////// /// ADDED /////////////////////////////////////////////////////////////////////////////////////////// for(i=0; i<3; i++) do_fast_random_poll(); pool_filled = 1; /////////////////////////////////////////////////////////////////////////////////////////// /* Mix the pid in so that we for sure won't deliver the same random after a fork. */ { pid_t apid = my_pid; add_randomness (&apid, sizeof (apid), 0); } /* Mix the pool (if add_randomness() didn't it). */ if (!just_mixed) { mix_pool(rndpool); rndstats.mixrnd++; } /* Create a new pool. */ for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; i < POOLWORDS; i++, dp++, sp++ ) *dp = *sp + ADD_VALUE; /* Mix both pools. */ mix_pool(rndpool); rndstats.mixrnd++; mix_pool(keypool); rndstats.mixkey++; /* Read the required data. We use a readpointer to read from a different position each time */ for (n=0; n < length; n++) { *buffer++ = keypool[pool_readpos++]; if (pool_readpos >= POOLSIZE) pool_readpos = 0; pool_balance--; } if (pool_balance < 0) pool_balance = 0; /* Clear the keypool. */ memset (keypool, 0, POOLSIZE); /* We need to detect whether a fork has happened. A fork might have an identical pool and thus the child and the parent could emit the very same random number. This test here is to detect forks in a multi-threaded process. */ if ( getpid () != my_pid2 ) { pid_t x = getpid(); add_randomness (&x, sizeof(x), 0); just_mixed = 0; /* Make sure it will get mixed. */ my_pid = x; /* Also update the static pid. */ goto retry; } }