示例#1
0
/* Read in a seed from the random_seed file and return true if this
   was successful.

   Note: Multiple instances of applications sharing the same random
   seed file can be started in parallel, in which case they will read
   out the same pool and then race for updating it (the last update
   overwrites earlier updates).  They will differentiate only by the
   weak entropy that is added in read_seed_file based on the PID and
   clock, and up to 16 bytes of weak random non-blockingly.  The
   consequence is that the output of these different instances is
   correlated to some extent.  In the perfect scenario, the attacker
   can control (or at least guess) the PID and clock of the
   application, and drain the system's entropy pool to reduce the "up
   to 16 bytes" above to 0.  Then the dependencies of the inital
   states of the pools are completely known.  */
static int
read_seed_file (void)
{
  int fd;
  struct stat sb;
  unsigned char buffer[POOLSIZE];
  int n;

  gcry_assert (pool_is_locked);

  if (!seed_file_name)
	return 0;
  
#ifdef HAVE_DOSISH_SYSTEM
  fd = open( seed_file_name, O_RDONLY | O_BINARY );
#else
  fd = open( seed_file_name, O_RDONLY );
#endif
  if( fd == -1 && errno == ENOENT)
	{
	  allow_seed_file_update = 1;
	  return 0;
	}

  if (fd == -1 )
	{
	  log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) );
	  return 0;
	}
  if (lock_seed_file (fd, seed_file_name, 0))
	{
	  close (fd);
	  return 0;
	}
  if (fstat( fd, &sb ) )
	{
	  log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) );
	  close(fd);
	  return 0;
	}
  if (!S_ISREG(sb.st_mode) )
	{
	  log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name );
	  close(fd);
	  return 0;
	}
  if (!sb.st_size )
	{
	  log_info(_("note: random_seed file is empty\n") );
	  close(fd);
	  allow_seed_file_update = 1;
	  return 0;
	}
  if (sb.st_size != POOLSIZE ) 
	{
	  log_info(_("warning: invalid size of random_seed file - not used\n") );
	  close(fd);
	  return 0;
	}

  do
	{
	  n = read( fd, buffer, POOLSIZE );
	} 
  while (n == -1 && errno == EINTR );

  if (n != POOLSIZE)
	{
	  log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) );
	  close(fd);/*NOTREACHED*/
	  return 0;
	}
  
  close(fd);

  add_randomness( buffer, POOLSIZE, RANDOM_ORIGIN_INIT );
  /* add some minor entropy to the pool now (this will also force a mixing) */
  {	
	pid_t x = getpid();
	add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
  }
  {
	time_t x = time(NULL);
	add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
  }
  {	
	clock_t x = clock();
	add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
  }

  /* And read a few bytes from our entropy source.  By using a level
   * of 0 this will not block and might not return anything with some
   * entropy drivers, however the rndlinux driver will use
   * /dev/urandom and return some stuff - Do not read too much as we
   * want to be friendly to the scare system entropy resource. */
  read_random_source ( RANDOM_ORIGIN_INIT, 16, GCRY_WEAK_RANDOM );

  allow_seed_file_update = 1;
  return 1;
}
示例#2
0
void
_gcry_rngcsprng_update_seed_file (void)
{
  unsigned long *sp, *dp;
  int fd, i;

  /* We do only a basic initialization so that we can lock the pool.
	 This is required to cope with the case that this function is
	 called by some cleanup code at a point where the RNG has never
	 been initialized.  */
  initialize_basics ();
  lock_pool ();

  if ( !seed_file_name || !rndpool || !pool_filled )
	{
	  unlock_pool ();
	  return;
	}
  if ( !allow_seed_file_update )
	{
	  unlock_pool ();
	  log_info(_("note: random_seed file not updated\n"));
	  return;
	}

  /* At this point we know that there is something in the pool and
	 thus we can conclude that the pool has been fully initialized.  */


  /* Copy the entropy pool to a scratch pool and mix both of them. */
  for (i=0,dp=(unsigned long*)keypool, sp=(unsigned long*)rndpool;
	   i < POOLWORDS; i++, dp++, sp++ ) 
	{
	  *dp = *sp + ADD_VALUE;
	}
  mix_pool(rndpool); rndstats.mixrnd++;
  mix_pool(keypool); rndstats.mixkey++;

#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
  fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
			 S_IRUSR|S_IWUSR );
#else
# if LOCK_SEED_FILE
	fd = open (seed_file_name, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR );
# else
	fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
# endif
#endif

  if (fd == -1 )
	log_info (_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
  else if (lock_seed_file (fd, seed_file_name, 1))
	{
	  close (fd);
	}
#if LOCK_SEED_FILE
  else if (ftruncate (fd, 0))
	{
	  log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno));
	  close (fd);
	}
#endif /*LOCK_SEED_FILE*/
  else 
	{
	  do
		{
		  i = write (fd, keypool, POOLSIZE );
		} 
	  while (i == -1 && errno == EINTR);
	  if (i != POOLSIZE) 
		log_info (_("can't write `%s': %s\n"),seed_file_name, strerror(errno));
	  if (close(fd))
		log_info (_("can't close `%s': %s\n"),seed_file_name, strerror(errno));
	}
  
  unlock_pool ();
}
示例#3
0
void
update_random_seed_file()
{
    ulong *sp, *dp;
    int fd, i;

    if( !seed_file_name || !is_initialized || !pool_filled )
        return;
    if( !allow_seed_file_update ) {
        log_info(_("note: random_seed file not updated\n"));
        return;
    }


    /* copy the entropy pool to a scratch pool and mix both of them */
    for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
            i < POOLWORDS; i++, dp++, sp++ ) {
        *dp = *sp + ADD_VALUE;
    }
    mix_pool(rndpool);
    rndstats.mixrnd++;
    mix_pool(keypool);
    rndstats.mixkey++;

#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
    fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
               S_IRUSR|S_IWUSR );
#else
# if LOCK_SEED_FILE
    fd = open( seed_file_name, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR );
# else
    fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
# endif
#endif
    if( fd == -1 ) {
        log_info(_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
        return;
    }

    if (lock_seed_file (fd, seed_file_name, 1))
    {
        close (fd);
        return;
    }
#if LOCK_SEED_FILE
    if (ftruncate (fd, 0))
    {
        log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno));
        close (fd);
        return;
    }
#endif /*LOCK_SEED_FILE*/

    do {
        i = write( fd, keypool, POOLSIZE );
    } while( i == -1 && errno == EINTR );
    if( i != POOLSIZE ) {
        log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno) );
    }
    if( close(fd) )
        log_info(_("can't close `%s': %s\n"), seed_file_name, strerror(errno) );
}