Beispiel #1
0
/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
void
gcry_create_nonce (void *buffer, size_t length)
{
    static unsigned char nonce_buffer[20+8];
    static int nonce_buffer_initialized = 0;
    static volatile pid_t my_pid; /* The volatile is there to make sure the
                                   compiler does not optimize the code away
                                   in case the getpid function is badly
                                   attributed. */
    volatile pid_t apid;
    unsigned char *p;
    size_t n;
    int err;

    /* Make sure we are initialized. */
    if (!is_initialized)
        initialize ();

    /* Acquire the nonce buffer lock. */
    err = ath_mutex_lock (&nonce_buffer_lock);
    if (err)
        log_fatal ("failed to acquire the nonce buffer lock: %s\n",
                   strerror (err));

    apid = getpid ();
    /* The first time intialize our buffer. */
    if (!nonce_buffer_initialized)
    {
        time_t atime = time (NULL);
        pid_t xpid = apid;

        my_pid = apid;

        if ((sizeof apid + sizeof atime) > sizeof nonce_buffer)
            BUG ();

        /* Initialize the first 20 bytes with a reasonable value so that
           a failure of gcry_randomize won't affect us too much.  Don't
           care about the uninitialized remaining bytes. */
        p = nonce_buffer;
        memcpy (p, &xpid, sizeof xpid);
        p += sizeof xpid;
        memcpy (p, &atime, sizeof atime);

        /* Initialize the never changing private part of 64 bits. */
        gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);

        nonce_buffer_initialized = 1;
    }
    else if ( my_pid != apid )
    {
        /* We forked. Need to reseed the buffer - doing this for the
           private part should be sufficient. */
        gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
        /* Update the pid so that we won't run into here again and
           again. */
        my_pid = apid;
    }

    /* Create the nonce by hashing the entire buffer, returning the hash
       and updating the first 20 bytes of the buffer with this hash. */
    for (p = buffer; length > 0; length -= n, p += n)
    {
        _gcry_sha1_hash_buffer ((char*)nonce_buffer,
                                (char*)nonce_buffer, sizeof nonce_buffer);
        n = length > 20? 20 : length;
        memcpy (p, nonce_buffer, n);
    }


    /* Release the nonce buffer lock. */
    err = ath_mutex_unlock (&nonce_buffer_lock);
    if (err)
        log_fatal ("failed to release the nonce buffer lock: %s\n",
                   strerror (err));

}
Beispiel #2
0
/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
void
gcry_create_nonce (void *buffer, size_t length)
{
  static unsigned char nonce_buffer[20+8];
  static int nonce_buffer_initialized = 0;
  static volatile pid_t my_pid; /* The volatile is there to make sure the
                                   compiler does not optimize the code away
                                   in case the getpid function is badly
                                   attributed. */
  volatile pid_t apid;
  unsigned char *p;
  size_t n;
  int err;

  /* First check whether we shall use the FIPS nonce generator.  This
     is only done in FIPS mode, in all other modes, we use our own
     nonce generator which is seeded by the RNG actual in use.  */
  if (fips_mode ())
    {
      _gcry_rngfips_create_nonce (buffer, length);
      return;
    }

  /* This is the nonce generator, which formerly lived in
     random-csprng.c.  It is now used by all RNG types except when in
     FIPS mode (not that this means it is also used if the FIPS RNG
     has been selected but we are not in fips mode).  */

  /* Make sure we are initialized. */
  _gcry_random_initialize (1);

  /* Acquire the nonce buffer lock. */
  err = ath_mutex_lock (&nonce_buffer_lock);
  if (err)
    log_fatal ("failed to acquire the nonce buffer lock: %s\n",
               strerror (err));

  apid = getpid ();
  /* The first time initialize our buffer. */
  if (!nonce_buffer_initialized)
    {
      time_t atime = time (NULL);
      pid_t xpid = apid;

      my_pid = apid;

      if ((sizeof apid + sizeof atime) > sizeof nonce_buffer)
        BUG ();

      /* Initialize the first 20 bytes with a reasonable value so that
         a failure of gcry_randomize won't affect us too much.  Don't
         care about the uninitialized remaining bytes. */
      p = nonce_buffer;
      memcpy (p, &xpid, sizeof xpid);
      p += sizeof xpid;
      memcpy (p, &atime, sizeof atime);

      /* Initialize the never changing private part of 64 bits. */
      gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);

      nonce_buffer_initialized = 1;
    }
  else if ( my_pid != apid )
    {
      /* We forked. Need to reseed the buffer - doing this for the
         private part should be sufficient. */
      do_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
      /* Update the pid so that we won't run into here again and
         again. */
      my_pid = apid;
    }

  /* Create the nonce by hashing the entire buffer, returning the hash
     and updating the first 20 bytes of the buffer with this hash. */
  for (p = buffer; length > 0; length -= n, p += n)
    {
      _gcry_sha1_hash_buffer (nonce_buffer,
                              nonce_buffer, sizeof nonce_buffer);
      n = length > 20? 20 : length;
      memcpy (p, nonce_buffer, n);
    }

  /* Release the nonce buffer lock. */
  err = ath_mutex_unlock (&nonce_buffer_lock);
  if (err)
    log_fatal ("failed to release the nonce buffer lock: %s\n",
               strerror (err));
}
Beispiel #3
0
/*
   Mix the pool:

   |........blocks*20byte........|20byte|..44byte..|
   <..44byte..>           <20byte>
        |                    |
        |                    +------+
        +---------------------------|----------+
                                    v          v
   |........blocks*20byte........|20byte|..44byte..|
                                 <.....64bytes.....>
                                         |
      +----------------------------------+
     Hash
      v
   |.............................|20byte|..44byte..|
   <20byte><20byte><..44byte..>
      |                |
      |                +---------------------+
      +-----------------------------+        |
                                    v        v
   |.............................|20byte|..44byte..|
                                 <.....64byte......>
                                        |
              +-------------------------+
             Hash
              v
   |.............................|20byte|..44byte..|
   <20byte><20byte><..44byte..>

   and so on until we did this for all blocks.

   To better protect against implementation errors in this code, we
   xor a digest of the entire pool into the pool before mixing.

   Note: this function must only be called with a locked pool.
 */
static void
mix_pool(unsigned char *pool)
{
  static unsigned char failsafe_digest[DIGESTLEN];
  static int failsafe_digest_valid;

  unsigned char *hashbuf = pool + POOLSIZE;
  unsigned char *p, *pend;
  int i, n;
  SHA1_CONTEXT md;
  unsigned int nburn;

#if DIGESTLEN != 20
#error must have a digest length of 20 for SHA-1
#endif

  gcry_assert (pool_is_locked);
  _gcry_sha1_mixblock_init (&md);

  /* Loop over the pool.  */
  pend = pool + POOLSIZE;
  memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN );
  memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN);
  nburn = _gcry_sha1_mixblock (&md, hashbuf);
  memcpy(pool, hashbuf, 20 );

  if (failsafe_digest_valid && pool == rndpool)
    {
      for (i=0; i < 20; i++)
        pool[i] ^= failsafe_digest[i];
    }

  p = pool;
  for (n=1; n < POOLBLOCKS; n++)
    {
      memcpy (hashbuf, p, DIGESTLEN);

      p += DIGESTLEN;
      if (p+DIGESTLEN+BLOCKLEN < pend)
        memcpy (hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN);
      else
        {
          unsigned char *pp = p + DIGESTLEN;

          for (i=DIGESTLEN; i < BLOCKLEN; i++ )
            {
              if ( pp >= pend )
                pp = pool;
              hashbuf[i] = *pp++;
	    }
	}

      _gcry_sha1_mixblock (&md, hashbuf);
      memcpy(p, hashbuf, 20 );
    }

  /* Our hash implementation does only leave small parts (64 bytes)
     of the pool on the stack, so it is okay not to require secure
     memory here.  Before we use this pool, it will be copied to the
     help buffer anyway. */
  if ( pool == rndpool)
    {
      _gcry_sha1_hash_buffer (failsafe_digest, pool, POOLSIZE);
      failsafe_digest_valid = 1;
    }

  _gcry_burn_stack (nburn);
}