Exemplo 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);
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
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);
}
Exemplo n.º 7
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);
}