Ejemplo n.º 1
0
/* Run the selftests for pubkey algorithm ALGO with optional reporting
   function REPORT.  */
gpg_error_t
_gcry_pk_selftest (int algo, int extended, selftest_report_func_t report)
{
  gcry_err_code_t ec;
  gcry_pk_spec_t *spec;

  algo = map_algo (algo);
  spec = spec_from_algo (algo);
  if (spec && !spec->flags.disabled && spec->selftest)
    ec = spec->selftest (algo, extended, report);
  else
    {
      ec = GPG_ERR_PUBKEY_ALGO;
      /* Fixme: We need to change the report fucntion to allow passing
         of an encryption mode (e.g. pkcs1, ecdsa, or ecdh).  */
      if (report)
        report ("pubkey", algo, "module",
                spec && !spec->flags.disabled?
                "no selftest available" :
                spec? "algorithm disabled" :
                "algorithm not found");
    }

  return gpg_error (ec);
}
Ejemplo n.º 2
0
/****************
 * Return the number of encryption material numbers
 */
static int
pubkey_get_nenc (int algo)
{
  gcry_pk_spec_t *spec = spec_from_algo (algo);

  return spec? strlen (spec->elements_enc) : 0;
}
Ejemplo n.º 3
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 virtually not
   available in Libgcrypt.  This is not thread safe and should thus be
   called early. */
static void
disable_cipher_algo (int algo)
{
  gcry_cipher_spec_t *spec = spec_from_algo (algo);

  if (spec)
    spec->flags.disabled = 1;
}
Ejemplo n.º 4
0
/* Map the cipher algorithm identifier ALGORITHM to a string
   representing this algorithm.  This string is the default name as
   used by Libgcrypt.  A "?" is returned for an unknown algorithm.
   NULL is never returned. */
const char *
_gcry_cipher_algo_name (int algorithm)
{
  gcry_cipher_spec_t *spec;

  spec = spec_from_algo (algorithm);
  return spec? spec->name : "?";
}
Ejemplo n.º 5
0
/* Disable the use of the algorithm ALGO.  This is not thread safe and
   should thus be called early.  */
static void
disable_pubkey_algo (int algo)
{
  gcry_pk_spec_t *spec = spec_from_algo (algo);

  if (spec)
    spec->flags.disabled = 1;
}
Ejemplo n.º 6
0
/* Map the public key algorithm whose ID is contained in ALGORITHM to
   a string representation of the algorithm name.  For unknown
   algorithm IDs this functions returns "?". */
const char *
_gcry_pk_algo_name (int algo)
{
  gcry_pk_spec_t *spec;

  spec = spec_from_algo (algo);
  if (spec)
    return spec->name;
  return "?";
}
Ejemplo n.º 7
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_cipher_spec_t *spec;

  spec = spec_from_algo (algorithm);
  if (spec && !spec->flags.disabled)
    return 0;

  return GPG_ERR_CIPHER_ALGO;
}
Ejemplo n.º 8
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_cipher_spec_t *spec;
  unsigned len = 0;

  spec = spec_from_algo (algorithm);
  if (spec)
    {
      len = spec->blocksize;
      if (!len)
        log_bug ("cipher %d w/o blocksize\n", algorithm);
    }

  return len;
}
Ejemplo n.º 9
0
/* Return the standard length in bits of the key for the cipher
   algorithm with the identifier ALGORITHM.  */
static unsigned int
cipher_get_keylen (int algorithm)
{
  gcry_cipher_spec_t *spec;
  unsigned len = 0;

  spec = spec_from_algo (algorithm);
  if (spec)
    {
      len = spec->keylen;
      if (!len)
	log_bug ("cipher %d w/o key length\n", algorithm);
    }

  return len;
}
Ejemplo n.º 10
0
/****************
 * A USE of 0 means: don't care.
 */
static gcry_err_code_t
check_pubkey_algo (int algo, unsigned use)
{
  gcry_err_code_t err = 0;
  gcry_pk_spec_t *spec;

  spec = spec_from_algo (algo);
  if (spec)
    {
      if (((use & GCRY_PK_USAGE_SIGN)
	   && (! (spec->use & GCRY_PK_USAGE_SIGN)))
	  || ((use & GCRY_PK_USAGE_ENCR)
	      && (! (spec->use & GCRY_PK_USAGE_ENCR))))
	err = GPG_ERR_WRONG_PUBKEY_ALGO;
    }
  else
    err = GPG_ERR_PUBKEY_ALGO;

  return err;
}
Ejemplo n.º 11
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_err_code_t ec = 0;
  gcry_cipher_spec_t *spec;

  spec = spec_from_algo (algo);
  if (spec && !spec->flags.disabled && spec->selftest)
    ec = spec->selftest (algo, extended, report);
  else
    {
      ec = GPG_ERR_CIPHER_ALGO;
      if (report)
        report ("cipher", algo, "module",
                (spec && !spec->flags.disabled)?
                "no selftest available" :
                spec? "algorithm disabled" : "algorithm not found");
    }

  return gpg_error (ec);
}
Ejemplo n.º 12
0
gcry_err_code_t
_gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
			    int algo, int mode, unsigned int flags)
{
  int secure = (flags & GCRY_CIPHER_SECURE);
  gcry_cipher_spec_t *spec;
  gcry_cipher_hd_t h = NULL;
  gcry_err_code_t err;

  /* 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 ();

  spec = spec_from_algo (algo);
  if (!spec)
    err = GPG_ERR_CIPHER_ALGO;
  else if (spec->flags.disabled)
    err = GPG_ERR_CIPHER_ALGO;
  else
    err = 0;

  /* 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_CCM:
#ifdef HAVE_U64_TYPEDEF
	if (spec->blocksize != GCRY_CCM_BLOCK_LEN)
	  err = GPG_ERR_INV_CIPHER_MODE;
	if (!spec->encrypt || !spec->decrypt)
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;
#else
        err = GPG_ERR_NOT_SUPPORTED;
#endif

      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:
      case GCRY_CIPHER_MODE_CMAC:
      case GCRY_CIPHER_MODE_GCM:
	if (!spec->encrypt || !spec->decrypt)
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_POLY1305:
	if (!spec->stencrypt || !spec->stdecrypt || !spec->setiv)
	  err = GPG_ERR_INV_CIPHER_MODE;
	else if (spec->algo != GCRY_CIPHER_CHACHA20)
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_OCB:
        /* Note that our implementation allows only for 128 bit block
           length algorithms.  Lower block lengths would be possible
           but we do not implement them because they limit the
           security too much.  */
	if (!spec->encrypt || !spec->decrypt)
	  err = GPG_ERR_INV_CIPHER_MODE;
	else if (spec->blocksize != (128/8))
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_STREAM:
	if (!spec->stencrypt || !spec->stdecrypt)
	  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 * spec->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 = xtrycalloc_secure (1, size);
      else
	h = xtrycalloc (1, size);

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

#ifdef NEED_16BYTE_ALIGNED_CONTEXT
          if ( ((uintptr_t)h & 0x0f) )
            {
              /* The malloced block is not aligned on a 16 byte
                 boundary.  Correct for this.  */
              off = 16 - ((uintptr_t)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->spec = spec;
          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;
              h->bulk.ocb_crypt = _gcry_aes_ocb_crypt;
              h->bulk.ocb_auth  = _gcry_aes_ocb_auth;
              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;
              h->bulk.ocb_crypt = _gcry_camellia_ocb_crypt;
              h->bulk.ocb_auth  = _gcry_camellia_ocb_auth;
              break;
#endif /*USE_CAMELLIA*/
#ifdef USE_DES
            case GCRY_CIPHER_3DES:
              h->bulk.cbc_dec =  _gcry_3des_cbc_dec;
              h->bulk.cfb_dec =  _gcry_3des_cfb_dec;
              h->bulk.ctr_enc =  _gcry_3des_ctr_enc;
              break;
#endif /*USE_DES*/
#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;
              h->bulk.ocb_crypt = _gcry_serpent_ocb_crypt;
              h->bulk.ocb_auth  = _gcry_serpent_ocb_auth;
              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;
              h->bulk.ocb_crypt = _gcry_twofish_ocb_crypt;
              h->bulk.ocb_auth  = _gcry_twofish_ocb_auth;
              break;
#endif /*USE_TWOFISH*/

            default:
              break;
            }

          /* Setup defaults depending on the mode.  */
          switch (mode)
            {
            case GCRY_CIPHER_MODE_OCB:
              h->u_mode.ocb.taglen = 16; /* Bytes.  */
              break;

            default:
              break;
            }

	}
    }

  /* Done.  */

  *handle = err ? NULL : h;

  return err;
}
Ejemplo n.º 13
0
/* Return information about the given algorithm

   WHAT selects the kind of information returned:

    GCRYCTL_TEST_ALGO:
        Returns 0 when the specified algorithm is available for use.
        Buffer must be NULL, nbytes  may have the address of a variable
        with the required usage of the algorithm. It may be 0 for don't
        care or a combination of the GCRY_PK_USAGE_xxx flags;

    GCRYCTL_GET_ALGO_USAGE:
        Return the usage flags for the given algo.  An invalid algo
        returns 0.  Disabled algos are ignored here because we
        only want to know whether the algo is at all capable of
        the usage.

   Note: Because this function is in most cases used to return an
   integer value, we can make it easier for the caller to just look at
   the return value.  The caller will in all cases consult the value
   and thereby detecting whether a error occurred or not (i.e. while
   checking the block size) */
gcry_err_code_t
_gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes)
{
  gcry_err_code_t rc = 0;

  switch (what)
    {
    case GCRYCTL_TEST_ALGO:
      {
	int use = nbytes ? *nbytes : 0;
	if (buffer)
	  rc = GPG_ERR_INV_ARG;
	else if (check_pubkey_algo (algorithm, use))
	  rc = GPG_ERR_PUBKEY_ALGO;
	break;
      }

    case GCRYCTL_GET_ALGO_USAGE:
      {
	gcry_pk_spec_t *spec;

	spec = spec_from_algo (algorithm);
        *nbytes = spec? spec->use : 0;
	break;
      }

    case GCRYCTL_GET_ALGO_NPKEY:
      {
	/* FIXME?  */
	int npkey = pubkey_get_npkey (algorithm);
	*nbytes = npkey;
	break;
      }
    case GCRYCTL_GET_ALGO_NSKEY:
      {
	/* FIXME?  */
	int nskey = pubkey_get_nskey (algorithm);
	*nbytes = nskey;
	break;
      }
    case GCRYCTL_GET_ALGO_NSIGN:
      {
	/* FIXME?  */
	int nsign = pubkey_get_nsig (algorithm);
	*nbytes = nsign;
	break;
      }
    case GCRYCTL_GET_ALGO_NENCR:
      {
	/* FIXME?  */
	int nencr = pubkey_get_nenc (algorithm);
	*nbytes = nencr;
	break;
      }

    default:
      rc = GPG_ERR_INV_OP;
    }

  return rc;
}