Ejemplo n.º 1
0
/* Run the selftests for cipher algorithm ALGO with optional reporting
   function REPORT.  */
gpg_error_t
_gcry_cipher_selftest (int algo, int extended, selftest_report_func_t report)
{
  gcry_module_t module = NULL;
  cipher_extra_spec_t *extraspec = NULL;
  gcry_err_code_t ec = 0;

  REGISTER_DEFAULT_CIPHERS;

  ath_mutex_lock (&ciphers_registered_lock);
  module = _gcry_module_lookup_id (ciphers_registered, algo);
  if (module && !(module->flags & FLAG_MODULE_DISABLED))
    extraspec = module->extraspec;
  ath_mutex_unlock (&ciphers_registered_lock);
  if (extraspec && extraspec->selftest)
    ec = extraspec->selftest (algo, extended, report);
  else
    {
      ec = GPG_ERR_CIPHER_ALGO;
      if (report)
        report ("cipher", algo, "module",
                module && !(module->flags & FLAG_MODULE_DISABLED)?
                "no selftest available" :
                module? "algorithm disabled" : "algorithm not found");
    }

  if (module)
    {
      ath_mutex_lock (&ciphers_registered_lock);
      _gcry_module_release (module);
      ath_mutex_unlock (&ciphers_registered_lock);
    }
  return gpg_error (ec);
}
Ejemplo n.º 2
0
/* Release all resources associated with the cipher handle H. H may be
   NULL in which case this is a no-operation. */
void
gcry_cipher_close (gcry_cipher_hd_t h)
{
  size_t off;

  if (!h)
    return;

  if ((h->magic != CTX_MAGIC_SECURE)
      && (h->magic != CTX_MAGIC_NORMAL))
    _gcry_fatal_error(GPG_ERR_INTERNAL,
		      "gcry_cipher_close: already closed/invalid handle");
  else
    h->magic = 0;

  /* Release module.  */
  ath_mutex_lock (&ciphers_registered_lock);
  _gcry_module_release (h->module);
  ath_mutex_unlock (&ciphers_registered_lock);

  /* We always want to wipe out the memory even when the context has
     been allocated in secure memory.  The user might have disabled
     secure memory or is using his own implementation which does not
     do the wiping.  To accomplish this we need to keep track of the
     actual size of this structure because we have no way to known
     how large the allocated area was when using a standard malloc. */
  off = h->handle_offset;
  wipememory (h, h->actual_handle_size);

  gcry_free ((char*)h - off);
}
Ejemplo n.º 3
0
/* Map STRING to the cipher algorithm identifier.  Returns the
   algorithm ID of the cipher for the given name or 0 if the name is
   not known.  It is valid to pass NULL for STRING which results in a
   return value of 0. */
int
gcry_cipher_map_name (const char *string)
{
  gcry_module_t cipher;
  int ret, algorithm = 0;

  if (! string)
    return 0;

  REGISTER_DEFAULT_CIPHERS;

  /* If the string starts with a digit (optionally prefixed with
     either "OID." or "oid."), we first look into our table of ASN.1
     object identifiers to figure out the algorithm */

  ath_mutex_lock (&ciphers_registered_lock);

  ret = search_oid (string, &algorithm, NULL);
  if (! ret)
    {
      cipher = gcry_cipher_lookup_name (string);
      if (cipher)
	{
	  algorithm = cipher->mod_id;
	  _gcry_module_release (cipher);
	}
    }

  ath_mutex_unlock (&ciphers_registered_lock);

  return algorithm;
}
Ejemplo n.º 4
0
/* Unregister the cipher identified by MODULE, which must have been
   registered with gcry_cipher_register.  */
void
_gcry_cipher_unregister (gcry_module_t module)
{
  ath_mutex_lock (&ciphers_registered_lock);
  _gcry_module_release (module);
  ath_mutex_unlock (&ciphers_registered_lock);
}
Ejemplo n.º 5
0
/* Register a new cipher module whose specification can be found in
   CIPHER.  On success, a new algorithm ID is stored in ALGORITHM_ID
   and a pointer representhing this module is stored in MODULE.  */
gcry_error_t
_gcry_cipher_register (gcry_cipher_spec_t *cipher,
                       cipher_extra_spec_t *extraspec,
                       int *algorithm_id,
                       gcry_module_t *module)
{
  gcry_err_code_t err = 0;
  gcry_module_t mod;

  /* We do not support module loading in fips mode.  */
  if (fips_mode ())
    return gpg_error (GPG_ERR_NOT_SUPPORTED);

  ath_mutex_lock (&ciphers_registered_lock);
  err = _gcry_module_add (&ciphers_registered, 0,
			  (void *)cipher,
			  (void *)(extraspec? extraspec : &dummy_extra_spec),
                          &mod);
  ath_mutex_unlock (&ciphers_registered_lock);

  if (! err)
    {
      *module = mod;
      *algorithm_id = mod->mod_id;
    }

  return gcry_error (err);
}
Ejemplo n.º 6
0
/* Take the pool lock. */
static void
lock_pool (void)
{
  int err; 

  err = ath_mutex_lock (&pool_lock);
  if (err)
	log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
  pool_is_locked = 1;
}
Ejemplo n.º 7
0
/*
 * Return a pointer to a randomized buffer of LEVEL and NBYTES length.
 * Caller must free the buffer.
 */
static byte *
get_random_bytes ( size_t nbytes, int level, int secure)
{
    byte *buf, *p;
    int err;

    /* First a hack toavoid the strong random using our regression test suite. */
    if (quick_test && level > 1)
        level = 1;

    /* Make sure the requested level is in range. */
    MASK_LEVEL(level);

    /* Lock the pool. */
    err = ath_mutex_lock (&pool_lock);
    if (err)
        log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
    pool_is_locked = 1;

    /* Keep some statistics. */
    if (level >= 2)
    {
        rndstats.getbytes2 += nbytes;
        rndstats.ngetbytes2++;
    }
    else
    {
        rndstats.getbytes1 += nbytes;
        rndstats.ngetbytes1++;
    }

    /* Allocate the return buffer. */
    buf = secure && secure_alloc ? gcry_xmalloc_secure( nbytes )
          : gcry_xmalloc( nbytes );

    /* Fill that buffer with random. */
    for (p = buf; nbytes > 0; )
    {
        size_t n;

        n = nbytes > POOLSIZE? POOLSIZE : nbytes;
        read_pool( p, n, level );
        nbytes -= n;
        p += n;
    }

    /* Release the pool lock. */
    pool_is_locked = 0;
    err = ath_mutex_unlock (&pool_lock);
    if (err)
        log_fatal ("failed to release the pool lock: %s\n", strerror (err));

    /* Return the buffer. */
    return buf;
}
Ejemplo n.º 8
0
/* Acquire the system_rng_lock.  */
static void
lock_rng (void)
{
    int my_errno;

    my_errno = ath_mutex_lock (&system_rng_lock);
    if (my_errno)
        log_fatal ("failed to acquire the System RNG lock: %s\n",
                   strerror (my_errno));
    system_rng_is_locked = 1;
}
Ejemplo n.º 9
0
/* Get a list consisting of the IDs of the loaded cipher modules.  If
   LIST is zero, write the number of loaded cipher modules to
   LIST_LENGTH and return.  If LIST is non-zero, the first
   *LIST_LENGTH algorithm IDs are stored in LIST, which must be of
   according size.  In case there are less cipher modules than
   *LIST_LENGTH, *LIST_LENGTH is updated to the correct number.  */
gcry_error_t
gcry_cipher_list (int *list, int *list_length)
{
  gcry_err_code_t err = GPG_ERR_NO_ERROR;

  ath_mutex_lock (&ciphers_registered_lock);
  err = _gcry_module_list (ciphers_registered, list, list_length);
  ath_mutex_unlock (&ciphers_registered_lock);

  return err;
}
Ejemplo n.º 10
0
/* Public function to fill the buffer with LENGTH bytes of
   cryptographically strong random bytes. level 0 is not very strong,
   1 is strong enough for most usage, 2 is good for key generation
   stuff but may be very slow.  */
void
gcry_randomize (void *buffer, size_t length, enum gcry_random_level level)
{
    byte *p;
    int err;

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

    /* Handle our hack used for regression tests of Libgcrypt. */
    if( quick_test && level > 1 )
        level = 1;

    /* Make sure the level is okay. */
    MASK_LEVEL(level);

    /* Acquire the pool lock. */
    err = ath_mutex_lock (&pool_lock);
    if (err)
        log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
    pool_is_locked = 1;

    /* Update the statistics. */
    if (level >= 2)
    {
        rndstats.getbytes2 += length;
        rndstats.ngetbytes2++;
    }
    else
    {
        rndstats.getbytes1 += length;
        rndstats.ngetbytes1++;
    }

    /* Read the random into the provided buffer. */
    for (p = buffer; length > 0;)
    {
        size_t n;

        n = length > POOLSIZE? POOLSIZE : length;
        read_pool (p, n, level);
        length -= n;
        p += n;
    }

    /* Release the pool lock. */
    pool_is_locked = 0;
    err = ath_mutex_unlock (&pool_lock);
    if (err)
        log_fatal ("failed to release the pool lock: %s\n", strerror (err));

}
Ejemplo n.º 11
0
/* Flag the cipher algorithm with the identifier ALGORITHM as
   disabled.  There is no error return, the function does nothing for
   unknown algorithms.  Disabled algorithms are vitually not available
   in Libgcrypt. */
static void
disable_cipher_algo (int algorithm)
{
  gcry_module_t cipher;

  REGISTER_DEFAULT_CIPHERS;

  ath_mutex_lock (&ciphers_registered_lock);
  cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
  if (cipher)
    {
      if (! (cipher->flags & FLAG_MODULE_DISABLED))
	cipher->flags |= FLAG_MODULE_DISABLED;
      _gcry_module_release (cipher);
    }
  ath_mutex_unlock (&ciphers_registered_lock);
}
Ejemplo n.º 12
0
/* Given a STRING with an OID in dotted decimal notation, this
   function returns the cipher mode (GCRY_CIPHER_MODE_*) associated
   with that OID or 0 if no mode is known.  Passing NULL for string
   yields a return value of 0. */
int
gcry_cipher_mode_from_oid (const char *string)
{
  gcry_cipher_oid_spec_t oid_spec;
  int ret = 0, mode = 0;

  if (!string)
    return 0;

  ath_mutex_lock (&ciphers_registered_lock);
  ret = search_oid (string, NULL, &oid_spec);
  if (ret)
    mode = oid_spec.mode;
  ath_mutex_unlock (&ciphers_registered_lock);

  return mode;
}
Ejemplo n.º 13
0
static void
lock_fsm (void)
{
  gpg_error_t err;

  err = ath_mutex_lock (&fsm_lock);
  if (err)
    {
      log_info ("FATAL: failed to acquire the FSM lock in libgrypt: %s\n",
                strerror (err));
#ifdef HAVE_SYSLOG
      syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
              "acquiring FSM lock failed: %s - abort",
              strerror (err));
#endif /*HAVE_SYSLOG*/
      abort ();
    }
}
Ejemplo n.º 14
0
/* Map the cipher algorithm identifier ALGORITHM to a string
   representing this algorithm.  This string is the default name as
   used by Libgcrypt.  NULL is returned for an unknown algorithm.  */
static const char *
cipher_algo_to_string (int algorithm)
{
  gcry_module_t cipher;
  const char *name = NULL;

  REGISTER_DEFAULT_CIPHERS;

  ath_mutex_lock (&ciphers_registered_lock);
  cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
  if (cipher)
    {
      name = ((gcry_cipher_spec_t *) cipher->spec)->name;
      _gcry_module_release (cipher);
    }
  ath_mutex_unlock (&ciphers_registered_lock);

  return name;
}
Ejemplo n.º 15
0
/* Register a new cipher module whose specification can be found in
   CIPHER.  On success, a new algorithm ID is stored in ALGORITHM_ID
   and a pointer representhing this module is stored in MODULE.  */
gcry_error_t
gcry_cipher_register (gcry_cipher_spec_t *cipher,
		      int *algorithm_id,
		      gcry_module_t *module)
{
  gcry_err_code_t err = 0;
  gcry_module_t mod;

  ath_mutex_lock (&ciphers_registered_lock);
  err = _gcry_module_add (&ciphers_registered, 0,
			  (void *) cipher, &mod);
  ath_mutex_unlock (&ciphers_registered_lock);

  if (! err)
    {
      *module = mod;
      *algorithm_id = mod->mod_id;
    }

  return gcry_error (err);
}
Ejemplo n.º 16
0
/* Return the block length of the cipher algorithm with the identifier
   ALGORITHM.  This function return 0 for an invalid algorithm.  */
static unsigned int
cipher_get_blocksize (int algorithm)
{
  gcry_module_t cipher;
  unsigned len = 0;

  REGISTER_DEFAULT_CIPHERS;

  ath_mutex_lock (&ciphers_registered_lock);
  cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
  if (cipher)
    {
      len = ((gcry_cipher_spec_t *) cipher->spec)->blocksize;
      if (! len)
	  log_bug ("cipher %d w/o blocksize\n", algorithm);
      _gcry_module_release (cipher);
    }
  ath_mutex_unlock (&ciphers_registered_lock);

  return len;
}
Ejemplo n.º 17
0
/* 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));

}
Ejemplo n.º 18
0
/* Return 0 if the cipher algorithm with identifier ALGORITHM is
   available. Returns a basic error code value if it is not
   available.  */
static gcry_err_code_t
check_cipher_algo (int algorithm)
{
  gcry_err_code_t err = GPG_ERR_NO_ERROR;
  gcry_module_t cipher;

  REGISTER_DEFAULT_CIPHERS;

  ath_mutex_lock (&ciphers_registered_lock);
  cipher = _gcry_module_lookup_id (ciphers_registered, algorithm);
  if (cipher)
    {
      if (cipher->flags & FLAG_MODULE_DISABLED)
	err = GPG_ERR_CIPHER_ALGO;
      _gcry_module_release (cipher);
    }
  else
    err = GPG_ERR_CIPHER_ALGO;
  ath_mutex_unlock (&ciphers_registered_lock);

  return err;
}
Ejemplo n.º 19
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));
}
Ejemplo n.º 20
0
void
_gcry_update_random_seed_file()
{
    unsigned long *sp, *dp;
    int fd, i;
    int err;

    if ( !seed_file_name || !is_initialized || !pool_filled )
        return;
    if ( !allow_seed_file_update )
    {
        log_info(_("note: random_seed file not updated\n"));
        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;

    /* 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++;

#ifdef HAVE_DOSISH_SYSTEM
    fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
               S_IRUSR|S_IWUSR );
#else
    fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
#endif

    if (fd == -1 )
        log_info (_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
    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) );
    }

    pool_is_locked = 0;
    err = ath_mutex_unlock (&pool_lock);
    if (err)
        log_fatal ("failed to release the pool lock: %s\n", strerror (err));

}
Ejemplo n.º 21
0
/*
   Open a cipher handle for use with cipher algorithm ALGORITHM, using
   the cipher mode MODE (one of the GCRY_CIPHER_MODE_*) and return a
   handle in HANDLE.  Put NULL into HANDLE and return an error code if
   something goes wrong.  FLAGS may be used to modify the
   operation.  The defined flags are:

   GCRY_CIPHER_SECURE:  allocate all internal buffers in secure memory.
   GCRY_CIPHER_ENABLE_SYNC:  Enable the sync operation as used in OpenPGP.
   GCRY_CIPHER_CBC_CTS:  Enable CTS mode.
   GCRY_CIPHER_CBC_MAC:  Enable MAC mode.

   Values for these flags may be combined using OR.
 */
gcry_error_t
gcry_cipher_open (gcry_cipher_hd_t *handle,
		  int algo, int mode, unsigned int flags)
{
  int secure = (flags & GCRY_CIPHER_SECURE);
  gcry_cipher_spec_t *cipher = NULL;
  gcry_module_t module = NULL;
  gcry_cipher_hd_t h = NULL;
  gcry_err_code_t err = 0;

  /* If the application missed to call the random poll function, we do
     it here to ensure that it is used once in a while. */
  _gcry_fast_random_poll ();
  
  REGISTER_DEFAULT_CIPHERS;

  /* Fetch the according module and check wether the cipher is marked
     available for use.  */
  ath_mutex_lock (&ciphers_registered_lock);
  module = _gcry_module_lookup_id (ciphers_registered, algo);
  if (module)
    {
      /* Found module.  */

      if (module->flags & FLAG_MODULE_DISABLED)
	{
	  /* Not available for use.  */
	  err = GPG_ERR_CIPHER_ALGO;
	  _gcry_module_release (module);
	}
      else
	cipher = (gcry_cipher_spec_t *) module->spec;
    }
  else
    err = GPG_ERR_CIPHER_ALGO;
  ath_mutex_unlock (&ciphers_registered_lock);

  /* check flags */
  if ((! err)
      && ((flags & ~(0 
		     | GCRY_CIPHER_SECURE
		     | GCRY_CIPHER_ENABLE_SYNC
		     | GCRY_CIPHER_CBC_CTS
		     | GCRY_CIPHER_CBC_MAC))
	  || (flags & GCRY_CIPHER_CBC_CTS & GCRY_CIPHER_CBC_MAC)))
    err = GPG_ERR_CIPHER_ALGO;

  /* check that a valid mode has been requested */
  if (! err)
    switch (mode)
      {
      case GCRY_CIPHER_MODE_ECB:
      case GCRY_CIPHER_MODE_CBC:
      case GCRY_CIPHER_MODE_CFB:
      case GCRY_CIPHER_MODE_CTR:
	if ((cipher->encrypt == dummy_encrypt_block)
	    || (cipher->decrypt == dummy_decrypt_block))
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_STREAM:
	if ((cipher->stencrypt == dummy_encrypt_stream)
	    || (cipher->stdecrypt == dummy_decrypt_stream))
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_NONE:
	/* FIXME: issue a warning when this mode is used */
	break;

      default:
	err = GPG_ERR_INV_CIPHER_MODE;
      }

  /* ? FIXME: perform selftest here and mark this with a flag in
     cipher_table ? */

  if (! err)
    {
      size_t size = (sizeof (*h)
                     + 2 * cipher->contextsize
                     - sizeof (PROPERLY_ALIGNED_TYPE));

      if (secure)
	h = gcry_calloc_secure (1, size);
      else
	h = gcry_calloc (1, size);

      if (! h)
	err = gpg_err_code_from_errno (errno);
      else
	{
	  h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
          h->actual_handle_size = size;
	  h->cipher = cipher;
	  h->module = module;
	  h->mode = mode;
	  h->flags = flags;
	}
    }

  /* Done.  */

  if (err)
    {
      if (module)
	{
	  /* Release module.  */
	  ath_mutex_lock (&ciphers_registered_lock);
	  _gcry_module_release (module);
	  ath_mutex_unlock (&ciphers_registered_lock);
	}
    }

  *handle = err ? NULL : h;

  return gcry_error (err);
}
Ejemplo n.º 22
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));

}
Ejemplo n.º 23
0
/*
   Open a cipher handle for use with cipher algorithm ALGORITHM, using
   the cipher mode MODE (one of the GCRY_CIPHER_MODE_*) and return a
   handle in HANDLE.  Put NULL into HANDLE and return an error code if
   something goes wrong.  FLAGS may be used to modify the
   operation.  The defined flags are:

   GCRY_CIPHER_SECURE:  allocate all internal buffers in secure memory.
   GCRY_CIPHER_ENABLE_SYNC:  Enable the sync operation as used in OpenPGP.
   GCRY_CIPHER_CBC_CTS:  Enable CTS mode.
   GCRY_CIPHER_CBC_MAC:  Enable MAC mode.

   Values for these flags may be combined using OR.
 */
gcry_error_t
gcry_cipher_open (gcry_cipher_hd_t *handle,
		  int algo, int mode, unsigned int flags)
{
  int secure = (flags & GCRY_CIPHER_SECURE);
  gcry_cipher_spec_t *cipher = NULL;
  cipher_extra_spec_t *extraspec = NULL;
  gcry_module_t module = NULL;
  gcry_cipher_hd_t h = NULL;
  gcry_err_code_t err = 0;

  /* If the application missed to call the random poll function, we do
     it here to ensure that it is used once in a while. */
  _gcry_fast_random_poll ();

  REGISTER_DEFAULT_CIPHERS;

  /* Fetch the according module and check whether the cipher is marked
     available for use.  */
  ath_mutex_lock (&ciphers_registered_lock);
  module = _gcry_module_lookup_id (ciphers_registered, algo);
  if (module)
    {
      /* Found module.  */

      if (module->flags & FLAG_MODULE_DISABLED)
	{
	  /* Not available for use.  */
	  err = GPG_ERR_CIPHER_ALGO;
	}
      else
        {
          cipher = (gcry_cipher_spec_t *) module->spec;
          extraspec = module->extraspec;
        }
    }
  else
    err = GPG_ERR_CIPHER_ALGO;
  ath_mutex_unlock (&ciphers_registered_lock);

  /* check flags */
  if ((! err)
      && ((flags & ~(0
		     | GCRY_CIPHER_SECURE
		     | GCRY_CIPHER_ENABLE_SYNC
		     | GCRY_CIPHER_CBC_CTS
		     | GCRY_CIPHER_CBC_MAC))
	  || (flags & GCRY_CIPHER_CBC_CTS & GCRY_CIPHER_CBC_MAC)))
    err = GPG_ERR_CIPHER_ALGO;

  /* check that a valid mode has been requested */
  if (! err)
    switch (mode)
      {
      case GCRY_CIPHER_MODE_ECB:
      case GCRY_CIPHER_MODE_CBC:
      case GCRY_CIPHER_MODE_CFB:
      case GCRY_CIPHER_MODE_OFB:
      case GCRY_CIPHER_MODE_CTR:
      case GCRY_CIPHER_MODE_AESWRAP:
	if ((cipher->encrypt == dummy_encrypt_block)
	    || (cipher->decrypt == dummy_decrypt_block))
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_STREAM:
	if ((cipher->stencrypt == dummy_encrypt_stream)
	    || (cipher->stdecrypt == dummy_decrypt_stream))
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_NONE:
        /* This mode may be used for debugging.  It copies the main
           text verbatim to the ciphertext.  We do not allow this in
           fips mode or if no debug flag has been set.  */
	if (fips_mode () || !_gcry_get_debug_flag (0))
          err = GPG_ERR_INV_CIPHER_MODE;
	break;

      default:
	err = GPG_ERR_INV_CIPHER_MODE;
      }

  /* Perform selftest here and mark this with a flag in cipher_table?
     No, we should not do this as it takes too long.  Further it does
     not make sense to exclude algorithms with failing selftests at
     runtime: If a selftest fails there is something seriously wrong
     with the system and thus we better die immediately. */

  if (! err)
    {
      size_t size = (sizeof (*h)
                     + 2 * cipher->contextsize
                     - sizeof (cipher_context_alignment_t)
#ifdef NEED_16BYTE_ALIGNED_CONTEXT
                     + 15  /* Space for leading alignment gap.  */
#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/
                     );

      if (secure)
	h = gcry_calloc_secure (1, size);
      else
	h = gcry_calloc (1, size);

      if (! h)
	err = gpg_err_code_from_syserror ();
      else
	{
          size_t off = 0;

#ifdef NEED_16BYTE_ALIGNED_CONTEXT
          if ( ((unsigned long)h & 0x0f) )
            {
              /* The malloced block is not aligned on a 16 byte
                 boundary.  Correct for this.  */
              off = 16 - ((unsigned long)h & 0x0f);
              h = (void*)((char*)h + off);
            }
#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/

	  h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
          h->actual_handle_size = size - off;
          h->handle_offset = off;
	  h->cipher = cipher;
	  h->extraspec = extraspec;
	  h->module = module;
          h->algo = algo;
	  h->mode = mode;
	  h->flags = flags;

          /* Setup bulk encryption routines.  */
          switch (algo)
            {
#ifdef USE_AES
            case GCRY_CIPHER_AES128:
            case GCRY_CIPHER_AES192:
            case GCRY_CIPHER_AES256:
              h->bulk.cfb_enc = _gcry_aes_cfb_enc;
              h->bulk.cfb_dec = _gcry_aes_cfb_dec;
              h->bulk.cbc_enc = _gcry_aes_cbc_enc;
              h->bulk.cbc_dec = _gcry_aes_cbc_dec;
              h->bulk.ctr_enc = _gcry_aes_ctr_enc;
              break;
#endif /*USE_AES*/
#ifdef USE_BLOWFISH
	    case GCRY_CIPHER_BLOWFISH:
              h->bulk.cfb_dec = _gcry_blowfish_cfb_dec;
              h->bulk.cbc_dec = _gcry_blowfish_cbc_dec;
              h->bulk.ctr_enc = _gcry_blowfish_ctr_enc;
              break;
#endif /*USE_BLOWFISH*/
#ifdef USE_CAST5
	    case GCRY_CIPHER_CAST5:
              h->bulk.cfb_dec = _gcry_cast5_cfb_dec;
              h->bulk.cbc_dec = _gcry_cast5_cbc_dec;
              h->bulk.ctr_enc = _gcry_cast5_ctr_enc;
              break;
#endif /*USE_CAMELLIA*/
#ifdef USE_CAMELLIA
	    case GCRY_CIPHER_CAMELLIA128:
	    case GCRY_CIPHER_CAMELLIA192:
	    case GCRY_CIPHER_CAMELLIA256:
              h->bulk.cbc_dec = _gcry_camellia_cbc_dec;
              h->bulk.cfb_dec = _gcry_camellia_cfb_dec;
              h->bulk.ctr_enc = _gcry_camellia_ctr_enc;
              break;
#endif /*USE_CAMELLIA*/
#ifdef USE_SERPENT
	    case GCRY_CIPHER_SERPENT128:
	    case GCRY_CIPHER_SERPENT192:
	    case GCRY_CIPHER_SERPENT256:
              h->bulk.cbc_dec = _gcry_serpent_cbc_dec;
              h->bulk.cfb_dec = _gcry_serpent_cfb_dec;
              h->bulk.ctr_enc = _gcry_serpent_ctr_enc;
              break;
#endif /*USE_SERPENT*/
#ifdef USE_TWOFISH
	    case GCRY_CIPHER_TWOFISH:
	    case GCRY_CIPHER_TWOFISH128:
              h->bulk.cbc_dec = _gcry_twofish_cbc_dec;
              h->bulk.cfb_dec = _gcry_twofish_cfb_dec;
              h->bulk.ctr_enc = _gcry_twofish_ctr_enc;
              break;
#endif /*USE_TWOFISH*/

            default:
              break;
            }
	}
    }

  /* Done.  */

  if (err)
    {
      if (module)
	{
	  /* Release module.  */
	  ath_mutex_lock (&ciphers_registered_lock);
	  _gcry_module_release (module);
	  ath_mutex_unlock (&ciphers_registered_lock);
	}
    }

  *handle = err ? NULL : h;

  return gcry_error (err);
}