Exemplo n.º 1
0
static ssize_t enc_read(io_private_t *f, void *d, size_t l)
{
	f->buffer_crypt->offset[1] = l;
	f->buffer_crypt->offset[2] = 0;
	while (true)
	{
		if (f->buffer_crypt->offset[0] >= f->buffer_crypt->offset[1])
		{
			memcpy(d + f->buffer_crypt->offset[2], f->buffer_crypt->stream, f->buffer_crypt->offset[1]);
			f->buffer_crypt->offset[0] -= f->buffer_crypt->offset[1];
			uint8_t *x = gcry_calloc_secure(f->buffer_crypt->block, sizeof( uint8_t ));
			if (!x)
				die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, f->buffer_crypt->block * sizeof( uint8_t ));
			memcpy(x, f->buffer_crypt->stream + f->buffer_crypt->offset[1], f->buffer_crypt->offset[0]);
			memset(f->buffer_crypt->stream, 0x00, f->buffer_crypt->block);
			memcpy(f->buffer_crypt->stream, x, f->buffer_crypt->offset[0]);
			gcry_free(x);
			return l;
		}

		memcpy(d + f->buffer_crypt->offset[2], f->buffer_crypt->stream, f->buffer_crypt->offset[0]);
		f->buffer_crypt->offset[2] += f->buffer_crypt->offset[0];
		f->buffer_crypt->offset[1] -= f->buffer_crypt->offset[0];
		f->buffer_crypt->offset[0] = 0;

		ssize_t e = EXIT_SUCCESS;
		if ((e = ecc_read(f, f->buffer_crypt->stream, f->buffer_crypt->block)) < 0)
			return e;
#if !defined(__DEBUG__) || defined(__DEBUG_WITH_ENCRYPTION__)
		gcry_cipher_decrypt(f->cipher_handle, f->buffer_crypt->stream, f->buffer_crypt->block, NULL, 0);
#endif
		f->buffer_crypt->offset[0] = f->buffer_crypt->block;
	}
}
Exemplo n.º 2
0
extern IO_HANDLE io_dummy_handle(void)
{

	io_private_t *io_ptr = gcry_calloc_secure(1, sizeof( io_private_t ));
	io_ptr->fd = -IO_DUMMY_FD;
	return io_ptr;
}
Exemplo n.º 3
0
extern void execute(crypto_t *c)
{
    if (!c || c->status != STATUS_INIT)
        return;
    pthread_t *t = gcry_calloc_secure(1, sizeof( pthread_t ));
    pthread_attr_t a;
    pthread_attr_init(&a);
    pthread_attr_setdetachstate(&a, PTHREAD_CREATE_JOINABLE);
    pthread_create(t, &a, c->process, c);
    c->thread = t;
    pthread_attr_destroy(&a);
    return;
}
Exemplo n.º 4
0
extern version_e is_encrypted_aux(bool b, const char *n, char **c, char **h, char **m)
{
    struct stat s;
    stat(n, &s);
    if (S_ISDIR(s.st_mode))
        return VERSION_UNKNOWN;
    int64_t f = open(n, O_RDONLY | F_RDLCK | O_BINARY, S_IRUSR | S_IWUSR);
    if (f < 0)
        return VERSION_UNKNOWN;
    uint64_t head[3] = { 0x0 };
    if ((read(f, head, sizeof head)) < 0)
        return close(f) , VERSION_UNKNOWN;
    if (head[0] != htonll(HEADER_0) && head[1] != htonll(HEADER_1))
        return close(f) , VERSION_UNKNOWN;

    version_e version = check_version(ntohll(head[2]));
    if (b)
    {
        if (version >= VERSION_2015_10)
        {
            /* skips past ECC length byte */
            uint8_t b;
            read(f, &b, sizeof b);
        }
        uint8_t l;
        read(f, &l, sizeof l);
        char *a = gcry_calloc_secure(l + sizeof( char ), sizeof( char ));
        read(f, a, l);
        char *s = strchr(a, '/');
        *s = '\0';
        s++;
        char *d = strrchr(s, '/');
        if (d)
        {
            *d = '\0';
            d++;
        }
        else
            d = "CBC";
        if (*c)
            *c = strdup(a);
        if (*h)
            *h = strdup(s);
        if (*m)
            *m = strdup(d);
        gcry_free(a);
    }
    close(f);

    return version;
}
Exemplo n.º 5
0
extern IO_HANDLE io_open(const char *n, int f, mode_t m)
{
#ifndef _WIN32
	int64_t fd = open(n, f, m);
#else
	int64_t fd = open(n, f);
#endif
	if (fd < 0)
		return NULL;
	io_private_t *io_ptr = gcry_calloc_secure(1, sizeof( io_private_t ));
	io_ptr->fd = fd;
	io_ptr->eof = EOF_NO;
	return io_ptr;
}
gboolean
gkm_data_asn1_write_mpi (GNode *asn, gcry_mpi_t mpi)
{
	gcry_error_t gcry;
	gsize len;
	guchar *buf;

	g_return_val_if_fail (asn, FALSE);
	g_return_val_if_fail (mpi, FALSE);

	/* Get the size */
	gcry = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &len, mpi);
	g_return_val_if_fail (gcry == 0, FALSE);
	g_return_val_if_fail (len > 0, FALSE);

	buf = gcry_calloc_secure (len, 1);

	gcry = gcry_mpi_print (GCRYMPI_FMT_STD, buf, len, &len, mpi);
	g_return_val_if_fail (gcry == 0, FALSE);

	return egg_asn1x_set_integer_as_raw (asn, buf, len, gcry_free);
}
Exemplo n.º 7
0
/* Unprotect the canconical encoded S-expression key in KEYBUF.  GRIP
   should be the hex encoded keygrip of that key to be used with the
   caching mechanism. DESC_TEXT may be set to override the default
   description used for the pinentry.  If LOOKUP_TTL is given this
   function is used to lookup the default ttl. */
static int
unprotect (ctrl_t ctrl, const char *desc_text,
           unsigned char **keybuf, const unsigned char *grip,
           cache_mode_t cache_mode, lookup_ttl_t lookup_ttl)
{
  struct pin_entry_info_s *pi;
  struct try_unprotect_arg_s arg;
  int rc;
  unsigned char *result;
  size_t resultlen;
  char hexgrip[40+1];

  bin2hex (grip, 20, hexgrip);

  /* First try to get it from the cache - if there is none or we can't
     unprotect it, we fall back to ask the user */
  if (cache_mode != CACHE_MODE_IGNORE)
    {
      void *cache_marker;
      const char *pw;

    retry:
      pw = agent_get_cache (hexgrip, cache_mode, &cache_marker);
      if (pw)
        {
          rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen);
          agent_unlock_cache_entry (&cache_marker);
          if (!rc)
            {
              xfree (*keybuf);
              *keybuf = result;
              return 0;
            }
          rc  = 0;
        }

      /* If the pinentry is currently in use, we wait up to 60 seconds
         for it to close and check the cache again.  This solves a common
         situation where several requests for unprotecting a key have
         been made but the user is still entering the passphrase for
         the first request.  Because all requests to agent_askpin are
         serialized they would then pop up one after the other to
         request the passphrase - despite that the user has already
         entered it and is then available in the cache.  This
         implementation is not race free but in the worst case the
         user has to enter the passphrase only once more. */
      if (pinentry_active_p (ctrl, 0))
        {
          /* Active - wait */
          if (!pinentry_active_p (ctrl, 60))
            {
              /* We need to give the other thread a chance to actually put
                 it into the cache. */
              pth_sleep (1);
              goto retry;
            }
          /* Timeout - better call pinentry now the plain way. */
        }
    }

  pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
  if (!pi)
    return gpg_error_from_syserror ();
  pi->max_length = 100;
  pi->min_digits = 0;  /* we want a real passphrase */
  pi->max_digits = 16;
  pi->max_tries = 3;
  pi->check_cb = try_unprotect_cb;
  arg.ctrl = ctrl;
  arg.protected_key = *keybuf;
  arg.unprotected_key = NULL;
  arg.change_required = 0;
  pi->check_cb_arg = &arg;

  rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
  if (!rc)
    {
      assert (arg.unprotected_key);
      if (arg.change_required)
        {
          size_t canlen, erroff;
          gcry_sexp_t s_skey;

          assert (arg.unprotected_key);
          canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
          rc = gcry_sexp_sscan (&s_skey, &erroff,
                                (char*)arg.unprotected_key, canlen);
          if (rc)
            {
              log_error ("failed to build S-Exp (off=%u): %s\n",
                         (unsigned int)erroff, gpg_strerror (rc));
              wipememory (arg.unprotected_key, canlen);
              xfree (arg.unprotected_key);
              xfree (pi);
              return rc;
            }
          rc = agent_protect_and_store (ctrl, s_skey);
          gcry_sexp_release (s_skey);
          if (rc)
            {
              log_error ("changing the passphrase failed: %s\n",
                         gpg_strerror (rc));
              wipememory (arg.unprotected_key, canlen);
              xfree (arg.unprotected_key);
              xfree (pi);
              return rc;
            }
        }
      else
        agent_put_cache (hexgrip, cache_mode, pi->pin,
                         lookup_ttl? lookup_ttl (hexgrip) : 0);
      xfree (*keybuf);
      *keybuf = arg.unprotected_key;
    }
  xfree (pi);
  return rc;
}
/* Callback used to ask for the PIN which should be set into BUF.  The
   buf has been allocated by the caller and is of size MAXBUF which
   includes the terminating null.  The function should return an UTF-8
   string with the passphrase, the buffer may optionally be padded
   with arbitrary characters.

   INFO gets displayed as part of a generic string.  However if the
   first character of INFO is a vertical bar all up to the next
   verical bar are considered flags and only everything after the
   second vertical bar gets displayed as the full prompt.

   Flags:

      'N' = New PIN, this requests a second prompt to repeat the
            PIN.  If the PIN is not correctly repeated it starts from
            all over.
      'A' = The PIN is an Admin PIN, SO-PIN or alike.
      'P' = The PIN is a PUK (Personal Unblocking Key).
      'R' = The PIN is a Reset Code.

   Example:

     "|AN|Please enter the new security officer's PIN"
     
   The text "Please ..." will get displayed and the flags 'A' and 'N'
   are considered.
 */
static int 
getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
{
  struct pin_entry_info_s *pi;
  int rc;
  ctrl_t ctrl = opaque;
  const char *ends, *s;
  int any_flags = 0;
  int newpin = 0;
  int resetcode = 0;
  int is_puk = 0;
  const char *again_text = NULL;
  const char *prompt = "PIN";

  if (buf && maxbuf < 2)
    return gpg_error (GPG_ERR_INV_VALUE);

  /* Parse the flags. */
  if (info && *info =='|' && (ends=strchr (info+1, '|')))
    {
      for (s=info+1; s < ends; s++)
        {
          if (*s == 'A')
            prompt = _("Admin PIN");
          else if (*s == 'P')
            {
              /* TRANSLATORS: A PUK is the Personal Unblocking Code
                 used to unblock a PIN. */
              prompt = _("PUK");
              is_puk = 1;
            }
          else if (*s == 'N')
            newpin = 1;
          else if (*s == 'R')
            {
              prompt = _("Reset Code");
              resetcode = 1;
            }
        }
      info = ends+1;
      any_flags = 1;
    }
  else if (info && *info == '|')
    log_debug ("pin_cb called without proper PIN info hack\n");

  /* If BUF has been passed as NULL, we are in pinpad mode: The
     callback opens the popup and immediatley returns. */
  if (!buf)
    {
      if (maxbuf == 0) /* Close the pinentry. */
        {
          agent_popup_message_stop (ctrl);
          rc = 0;
        }
      else if (maxbuf == 1)  /* Open the pinentry. */
        {
          if (info)
            {
              char *desc;

              if ( asprintf (&desc,
                             _("%s%%0A%%0AUse the reader's pinpad for input."),
                             info) < 0 )
                rc = gpg_error_from_syserror ();
              else
                {
                  rc = agent_popup_message_start (ctrl, desc, NULL);
                  xfree (desc);
                }
            }
          else
            rc = agent_popup_message_start (ctrl, NULL, NULL);
        }
      else
        rc = gpg_error (GPG_ERR_INV_VALUE);
      return rc;
    }

  /* FIXME: keep PI and TRIES in OPAQUE.  Frankly this is a whole
     mess because we should call the card's verify function from the
     pinentry check pin CB. */
 again:
  pi = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
  if (!pi)
    return gpg_error_from_syserror ();
  pi->max_length = maxbuf-1;
  pi->min_digits = 0;  /* we want a real passphrase */
  pi->max_digits = 16;
  pi->max_tries = 3;

  if (any_flags)
    {
      rc = agent_askpin (ctrl, info, prompt, again_text, pi, NULL, 0);
      again_text = NULL;
      if (!rc && newpin)
        {
          struct pin_entry_info_s *pi2;
          pi2 = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
          if (!pi2)
            {
              rc = gpg_error_from_syserror ();
              xfree (pi);
              return rc;
            }
          pi2->max_length = maxbuf-1;
          pi2->min_digits = 0;
          pi2->max_digits = 16;
          pi2->max_tries = 1;
          rc = agent_askpin (ctrl,
                             (resetcode?
                              _("Repeat this Reset Code"):
                              is_puk?
                              _("Repeat this PUK"):
                              _("Repeat this PIN")),
                             prompt, NULL, pi2, NULL, 0);
          if (!rc && strcmp (pi->pin, pi2->pin))
            {
              again_text = (resetcode? 
                            N_("Reset Code not correctly repeated; try again"):
                            is_puk?
                            N_("PUK not correctly repeated; try again"):
                            N_("PIN not correctly repeated; try again"));
              xfree (pi2);
              xfree (pi);
              goto again;
            }
          xfree (pi2);
        }
    }
  else
    {
      char *desc;
      if ( asprintf (&desc,
                     _("Please enter the PIN%s%s%s to unlock the card"), 
                     info? " (`":"",
                     info? info:"",
                     info? "')":"") < 0)
        desc = NULL;
      rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi, NULL, 0);
      xfree (desc);
    }

  if (!rc)
    {
      strncpy (buf, pi->pin, maxbuf-1);
      buf[maxbuf-1] = 0;
    }
  xfree (pi);
  return rc;
}
Exemplo n.º 9
0
extern void io_encryption_init(IO_HANDLE ptr, enum gcry_cipher_algos c, enum gcry_md_algos h, enum gcry_cipher_modes m, const uint8_t *k, size_t l, io_extra_t x)
{
	io_private_t *io_ptr = ptr;
	if (!io_ptr || io_ptr->fd < 0)
		return errno = EBADF , (void)NULL;
	/*
	 * start setting up the encryption buffer
	 */
	if (!(io_ptr->buffer_crypt = gcry_malloc_secure(sizeof( buffer_t ))))
		die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, sizeof( buffer_t ));

	gcry_md_open(&io_ptr->hash_handle, h, GCRY_MD_FLAG_SECURE);
	gcry_cipher_open(&io_ptr->cipher_handle, c, m, GCRY_CIPHER_SECURE);
	/*
	 * generate a hash of the supplied key data
	 */
	size_t hash_length = gcry_md_get_algo_dlen(h);
	uint8_t *hash = gcry_malloc_secure(hash_length);
	if (!hash)
		die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, hash_length);
	gcry_md_hash_buffer(gcry_md_get_algo(io_ptr->hash_handle), hash, k, l);
	/*
	 * set the key as the hash of supplied data
	 */
	size_t key_length = gcry_cipher_get_algo_keylen(c);
	uint8_t *key = gcry_calloc_secure(key_length, sizeof( byte_t ));
	if (!key)
		die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, key_length);
	memcpy(key, hash, key_length < hash_length ? key_length : hash_length);
	gcry_cipher_setkey(io_ptr->cipher_handle, key, key_length); /* here is where it blows-up on Windows 8, using AES */
	gcry_free(key);
	/*
	 * the 2011.* versions (incorrectly) used key length instead of block
	 * length; versions after 2014.06 randomly generate the IV instead
	 */
	io_ptr->buffer_crypt->block = gcry_cipher_get_algo_blklen(c);
	uint8_t *iv = gcry_calloc_secure(x.x_iv == IV_BROKEN ? key_length : io_ptr->buffer_crypt->block, sizeof( byte_t ));
	if (!iv)
	   die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, io_ptr->buffer_crypt->block);
	if (x.x_iv == IV_RANDOM)
	{
		if (x.x_encrypt)
		{
			gcry_create_nonce(iv, io_ptr->buffer_crypt->block);
			io_write(ptr, iv, io_ptr->buffer_crypt->block);
		}
		else
			io_read(ptr, iv, io_ptr->buffer_crypt->block);
	}
	else
	{
		uint8_t *iv_hash = gcry_malloc_secure(hash_length);
		if (!iv_hash)
			die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, hash_length);
		/*
		 * set the IV as the hash of the hash
		 */
		gcry_md_hash_buffer(gcry_md_get_algo(io_ptr->hash_handle), iv_hash, hash, hash_length);
		memcpy(iv, iv_hash, io_ptr->buffer_crypt->block < hash_length ? io_ptr->buffer_crypt->block : hash_length);
		gcry_free(iv_hash);
	}
	gcry_free(hash);

	if (m == GCRY_CIPHER_MODE_CTR)
		gcry_cipher_setctr(io_ptr->cipher_handle, iv, io_ptr->buffer_crypt->block);
	else
		gcry_cipher_setiv(io_ptr->cipher_handle, iv, io_ptr->buffer_crypt->block);
	gcry_free(iv);
	/*
	 * set the rest of the buffer
	 */
	if (!(io_ptr->buffer_crypt->stream = gcry_malloc_secure(io_ptr->buffer_crypt->block)))
		die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, io_ptr->buffer_crypt->block);
	/*
	 * when encrypting/writing data:
	 *   0: length of data buffered so far (in stream)
	 *   1: length of data processed (from d)
	 * when decrypting/reading data:
	 *   0: length of available data in input buffer (stream)
	 *   1: available space in read buffer (d)
	 *   2: next available memory location for data (from d)
	 */
	for (unsigned i = 0; i < OFFSET_SLOTS; i++)
		io_ptr->buffer_crypt->offset[i] = 0;
	io_ptr->cipher_init = true;
	io_ptr->hash_init = true;
	io_ptr->operation = IO_ENCRYPT;
	return;
}
Exemplo n.º 10
0
extern IO_HANDLE io_use_stdout(void)
{
	io_private_t *io_ptr = gcry_calloc_secure(1, sizeof( io_private_t ));
	io_ptr->fd = STDOUT_FILENO;
	return io_ptr;
}
Exemplo n.º 11
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.º 12
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);
}
Exemplo n.º 13
0
/* Unprotect the canconical encoded S-expression key in KEYBUF.  GRIP
   should be the hex encoded keygrip of that key to be used with the
   caching mechanism. DESC_TEXT may be set to override the default
   description used for the pinentry.  If LOOKUP_TTL is given this
   function is used to lookup the default ttl.  If R_PASSPHRASE is not
   NULL, the function succeeded and the key was protected the used
   passphrase (entered or from the cache) is stored there; if not NULL
   will be stored.  The caller needs to free the returned
   passphrase. */
static int
unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
           unsigned char **keybuf, const unsigned char *grip,
           cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
           char **r_passphrase)
{
  struct pin_entry_info_s *pi;
  struct try_unprotect_arg_s arg;
  int rc;
  unsigned char *result;
  size_t resultlen;
  char hexgrip[40+1];

  if (r_passphrase)
    *r_passphrase = NULL;

  bin2hex (grip, 20, hexgrip);

  /* Initially try to get it using a cache nonce.  */
  if (cache_nonce)
    {
      char *pw;

      pw = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
      if (pw)
        {
          rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
          if (!rc)
            {
              if (r_passphrase)
                *r_passphrase = pw;
              else
                xfree (pw);
              xfree (*keybuf);
              *keybuf = result;
              return 0;
            }
          xfree (pw);
        }
    }

  /* First try to get it from the cache - if there is none or we can't
     unprotect it, we fall back to ask the user */
  if (cache_mode != CACHE_MODE_IGNORE)
    {
      char *pw;

    retry:
      pw = agent_get_cache (hexgrip, cache_mode);
      if (pw)
        {
          rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
          if (!rc)
            {
              if (cache_mode == CACHE_MODE_NORMAL)
                agent_store_cache_hit (hexgrip);
              if (r_passphrase)
                *r_passphrase = pw;
              else
                xfree (pw);
              xfree (*keybuf);
              *keybuf = result;
              return 0;
            }
          xfree (pw);
          rc  = 0;
        }
      else if (cache_mode == CACHE_MODE_NORMAL)
        {
          /* The standard use of GPG keys is to have a signing and an
             encryption subkey.  Commonly both use the same
             passphrase.  We try to help the user to enter the
             passphrase only once by silently trying the last
             correctly entered passphrase.  Checking one additional
             passphrase should be acceptable; despite the S2K
             introduced delays. The assumed workflow is:

               1. Read encrypted message in a MUA and thus enter a
                  passphrase for the encryption subkey.

               2. Reply to that mail with an encrypted and signed
                  mail, thus entering the passphrase for the signing
                  subkey.

             We can often avoid the passphrase entry in the second
             step.  We do this only in normal mode, so not to
             interfere with unrelated cache entries.  */
          pw = agent_get_cache (NULL, cache_mode);
          if (pw)
            {
              rc = agent_unprotect (ctrl, *keybuf, pw, NULL,
                                    &result, &resultlen);
              if (!rc)
                {
                  if (r_passphrase)
                    *r_passphrase = pw;
                  else
                    xfree (pw);
                  xfree (*keybuf);
                  *keybuf = result;
                  return 0;
                }
              xfree (pw);
              rc  = 0;
            }
        }

      /* If the pinentry is currently in use, we wait up to 60 seconds
         for it to close and check the cache again.  This solves a common
         situation where several requests for unprotecting a key have
         been made but the user is still entering the passphrase for
         the first request.  Because all requests to agent_askpin are
         serialized they would then pop up one after the other to
         request the passphrase - despite that the user has already
         entered it and is then available in the cache.  This
         implementation is not race free but in the worst case the
         user has to enter the passphrase only once more. */
      if (pinentry_active_p (ctrl, 0))
        {
          /* Active - wait */
          if (!pinentry_active_p (ctrl, 60))
            {
              /* We need to give the other thread a chance to actually put
                 it into the cache. */
              npth_sleep (1);
              goto retry;
            }
          /* Timeout - better call pinentry now the plain way. */
        }
    }

  pi = gcry_calloc_secure (1, sizeof (*pi) + MAX_PASSPHRASE_LEN + 1);
  if (!pi)
    return gpg_error_from_syserror ();
  pi->max_length = MAX_PASSPHRASE_LEN + 1;
  pi->min_digits = 0;  /* we want a real passphrase */
  pi->max_digits = 16;
  pi->max_tries = 3;
  pi->check_cb = try_unprotect_cb;
  arg.ctrl = ctrl;
  arg.protected_key = *keybuf;
  arg.unprotected_key = NULL;
  arg.change_required = 0;
  pi->check_cb_arg = &arg;

  rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi, hexgrip, cache_mode);
  if (!rc)
    {
      assert (arg.unprotected_key);
      if (arg.change_required)
        {
          /* The callback told as that the user should change their
             passphrase.  Present the dialog to do.  */
          size_t canlen, erroff;
          gcry_sexp_t s_skey;

          assert (arg.unprotected_key);
          canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
          rc = gcry_sexp_sscan (&s_skey, &erroff,
                                (char*)arg.unprotected_key, canlen);
          if (rc)
            {
              log_error ("failed to build S-Exp (off=%u): %s\n",
                         (unsigned int)erroff, gpg_strerror (rc));
              wipememory (arg.unprotected_key, canlen);
              xfree (arg.unprotected_key);
              xfree (pi);
              return rc;
            }
          rc = agent_protect_and_store (ctrl, s_skey, NULL);
          gcry_sexp_release (s_skey);
          if (rc)
            {
              log_error ("changing the passphrase failed: %s\n",
                         gpg_strerror (rc));
              wipememory (arg.unprotected_key, canlen);
              xfree (arg.unprotected_key);
              xfree (pi);
              return rc;
            }
        }
      else
        {
          /* Passphrase is fine.  */
          agent_put_cache (hexgrip, cache_mode, pi->pin,
                           lookup_ttl? lookup_ttl (hexgrip) : 0);
          agent_store_cache_hit (hexgrip);
          if (r_passphrase && *pi->pin)
            *r_passphrase = xtrystrdup (pi->pin);
        }
      xfree (*keybuf);
      *keybuf = arg.unprotected_key;
    }
  xfree (pi);
  return rc;
}
Exemplo n.º 14
0
int main (int argc, char **argv) {
	/*
		Parse arguments
	*/
	if(opt_parse("usage: %s < filename > [options]", options, argv) == 0) {
		opt_help(0, NULL);
	}
		
	/*
		Read in password
	*/
	char *pass = NULL;
	size_t passLen = 0;
	ssize_t passRead;
	
	char *fileName;
		
	printf("Password: "******"libgcrypt version mismatch\n", stderr);
		exit (2);
	}

	gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN);
	gcry_control(GCRYCTL_INIT_SECMEM, 131072, 0);
	gcry_control(GCRYCTL_RESUME_SECMEM_WARN);
	gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);

	/*
		Key Generation
	*/
	char key[16] = "";
	size_t keyLength = gcry_cipher_get_algo_keylen(GCRY_CIPHER);

	const char *salt = "NaCl";
	size_t saltLen = sizeof(salt);
	unsigned long iterations = 4096;
	gpg_error_t errStatus;
		
	errStatus = gcry_kdf_derive(pass, passLen, GCRY_KDF_PBKDF2, GCRY_MD_SHA512, salt, saltLen, iterations, keyLength, key);
			
	/*
		Cipher Setup
	*/
//	printf("Key: %X\n", key);
	puts(key);
	
	const char* IV = "5844"; // const int IV = 5844;
	const char *name = "aes128";
	int algorithm = gcry_cipher_map_name(name);
	size_t blockLength = gcry_cipher_get_algo_blklen(GCRY_CIPHER);
	gcry_cipher_hd_t hand;

	gcry_cipher_open(&hand, algorithm, GCRY_CIPHER_MODE_CBC, 0);
	gcry_cipher_setkey(hand, key, keyLength);
	gcry_cipher_setiv(hand, IV, blockLength);
	
	char *buffer;
	long len;
	size_t macLen = 0;
	
	/*
		If the local flag is set then we encrypt the file locally
		instead of sending it over the network
		Otherwise we send the file over the network
	*/
	if (local == 1) {
	
		/* 
			Open the file for reading and then copy to a buffer
		*/	
		FILE *ifp = fopen(argv[1], "rb");
		if(ifp == 0) {
			printf("%s", "Could not open file");
			return 1;
		}
		
		// Lets figure out how big the file is
		fseek(ifp, 0L, SEEK_END);
		len = ftell(ifp);
		rewind(ifp);
		
		// Allocate secure RAM for the buffer
		buffer = gcry_calloc_secure(len, sizeof(char));

		// Copy the input file to the buffer
		fread(buffer, 1, len, ifp);
		
		// Since we're running locally, the name of the output file is the same as the argument
		// without the .gt
		fileName = argv[1];
		size_t inLen = strlen(fileName);

		// End the filename by replacing the "." with a NULL char
		fileName[inLen-3] = '\0';
	
		fclose(ifp);
		
	} else {
		/*
			Retrieve file from remote computer
			Open a socket and listen for communication
		*/
		int sock;
		int localSock;
		struct sockaddr_in inPort;
		
		inPort.sin_family = AF_INET;
		inPort.sin_addr.s_addr = INADDR_ANY;
		inPort.sin_port = htons(port);
	
		sock = socket(AF_INET, SOCK_STREAM, 0);

		if (sock == -1) {
			printf("%s", "Could not open socket");
			exit(1);
		}
		
		bind(sock, (struct sockaddr *) &inPort, sizeof(inPort));
		listen(sock, 0);
		
		printf("%s", "Waiting for connection...\n");
		
		// Accepting the connection
		localSock = accept(sock, NULL, NULL);
		printf("%s", "Inbound file...\n");
		
		// Allocate some memory for the buffer
		// len+(160(len%16)) is so that the memory we allocate is divisible 
		// by the blocklength, which is 16
        len = 4096L;
		buffer = gcry_calloc_secure(len+(16-(len%16)), sizeof(char));
        long dataRead = 0L;
        int keepReading = 1;
		
		// Let's figure out how much data we're getting
		// If I were to do this part over, I would instead open two connections
		// from techrypt- where the first connection sends the 
		// amount of data to be transmitted in the second connection
        while (keepReading) {
            dataRead = recv(localSock, buffer, len, MSG_PEEK);
            if (dataRead == len) {
                len = len * 2;
				sleep(.5);
                buffer = gcry_realloc(buffer, len);
                keepReading = 1;
            } else {
                keepReading = 0;
            }
        }
		// How much data did we read?
        len = dataRead;
		
		// Now lets actually store it in the buffer
        dataRead = recv(localSock, buffer, len, 0);
		
		// Output file name is the command line argument
		fileName = argv[1];
			
		close(sock);
		
		/*
			Setup the HMAC
		*/
		gcry_md_hd_t macHand;
	
		macLen = gcry_md_get_algo_dlen(GCRY_MD_SHA512);
		char *mac = gcry_calloc_secure(macLen, sizeof(char));
		
		gcry_md_open(&macHand, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC);
		gcry_md_setkey(macHand, key, keyLength);
		
		// Generate the HMAC for the message we received
		// Since we know there's a MAC of size macLen at the end
		// we will only generate the hash based on the first
		// len-macLen bytes
		gcry_md_write(macHand, buffer, len-macLen);
		mac = gcry_md_read(macHand, 0);
		
		/*
			Strip HMAC from buffer
		*/
		char *exMac = buffer+(len-macLen);
		
		/*
			Check HMAC against our HMAC
		*/
		// I think this may be exploitable with a strategically placed NULL
		// The use of memcmp could fix this...if I have time I will replace and check
		if(strncmp(mac, exMac, macLen) != 0) {
			exit(62);
		}
								
	}	
	

	/*
		Decrypt the buffer
	*/
	gcry_cipher_decrypt(hand, buffer, len, NULL, 0);
	
	
	/*
		Reverse padding algorithm
		Strip the amount of bytes from the end of the file
		determined by the contents of the last byte
		This is why using PKCS7 was so useful
	*/
	char *padPtr = buffer+len-macLen-1;
	int writeLen = len-macLen-(*padPtr);
	
	/*
		Write the buffer to a file
	*/
	FILE *ofp = fopen(fileName, "wb");
	fwrite(buffer, 1, writeLen, ofp);
	
	fclose(ofp);
		
	return 0;
}