Exemple #1
0
/* Turn VALUE into an octet string and store it in an allocated buffer
   at R_FRAME.  If the resulting octet string is shorter than NBYTES
   the result will be left padded with zeroes.  If VALUE does not fit
   into NBYTES an error code is returned.  */
static gpg_err_code_t
int2octets (unsigned char **r_frame, gcry_mpi_t value, size_t nbytes)
{
  gpg_err_code_t rc;
  size_t nframe, noff, n;
  unsigned char *frame;

  rc = _gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &nframe, value);
  if (rc)
    return rc;
  if (nframe > nbytes)
    return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES.  */

  noff = (nframe < nbytes)? nbytes - nframe : 0;
  n = nframe + noff;
  frame = mpi_is_secure (value)? xtrymalloc_secure (n) : xtrymalloc (n);
  if (!frame)
    return gpg_err_code_from_syserror ();
  if (noff)
    memset (frame, 0, noff);
  nframe += noff;
  rc = _gcry_mpi_print (GCRYMPI_FMT_USG, frame+noff, nframe-noff, NULL, value);
  if (rc)
    {
      xfree (frame);
      return rc;
    }

  *r_frame = frame;
  return 0;
}
Exemple #2
0
/* Return a new malloced string by unescaping the string S.  Escaping
   is percent escaping and '+'/space mapping.  A binary Nul will
   silently be replaced by a 0xFF.  Function returns NULL to indicate
   an out of memory status.  PArsing stops at the end of the string or
   a white space character. */
static char *
unescape_passphrase_string (const unsigned char *s)
{
  char *buffer, *d;

  buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
  if (!buffer)
    return NULL;
  while (*s && !spacep (s))
    {
      if (*s == '%' && s[1] && s[2])
        {
          s++;
          *d = xtoi_2 (s);
          if (!*d)
            *d = '\xff';
          d++;
          s += 2;
        }
      else if (*s == '+')
        {
          *d++ = ' ';
          s++;
        }
      else
        *d++ = *s++;
    }
  *d = 0;
  return buffer;
}
Exemple #3
0
static gpg_error_t
new_data (const char *string, struct secret_data_s **r_data)
{
  gpg_error_t err;
  struct secret_data_s *d, *d_enc;
  size_t length;
  int total;
  int res;

  *r_data = NULL;

  err = init_encryption ();
  if (err)
    return err;

  length = strlen (string) + 1;

  /* We pad the data to 32 bytes so that it get more complicated
     finding something out by watching allocation patterns.  This is
     usally not possible but we better assume nothing about our secure
     storage provider.  To support the AESWRAP mode we need to add 8
     extra bytes as well. */
  total = (length + 8) + 32 - ((length+8) % 32);

  d = xtrymalloc_secure (sizeof *d + total - 1);
  if (!d)
    return gpg_error_from_syserror ();
  memcpy (d->data, string, length);

  d_enc = xtrymalloc (sizeof *d_enc + total - 1);
  if (!d_enc)
    {
      err = gpg_error_from_syserror ();
      xfree (d);
      return err;
    }

  d_enc->totallen = total;
  res = npth_mutex_lock (&encryption_lock);
  if (res)
    log_fatal ("failed to acquire cache encryption mutex: %s\n",
               strerror (res));

  err = gcry_cipher_encrypt (encryption_handle, d_enc->data, total,
                             d->data, total - 8);
  xfree (d);
  res = npth_mutex_unlock (&encryption_lock);
  if (res)
    log_fatal ("failed to release cache encryption mutex: %s\n", strerror (res));
  if (err)
    {
      xfree (d_enc);
      return err;
    }
  *r_data = d_enc;
  return 0;
}
Exemple #4
0
gcry_mpi_t
_gcry_mpi_set_opaque_copy (gcry_mpi_t a, const void *p, unsigned int nbits)
{
  void *d;
  unsigned int n;

  n = (nbits+7)/8;
  d = _gcry_is_secure (p)? xtrymalloc_secure (n) : xtrymalloc (n);
  if (!d)
    return NULL;
  memcpy (d, p, n);
  return mpi_set_opaque (a, d, nbits);
}
Exemple #5
0
void *
_gcry_mpi_get_opaque_copy (gcry_mpi_t a, unsigned int *nbits)
{
  const void *s;
  void *d;
  unsigned int n;

  s = mpi_get_opaque (a, nbits);
  if (!s && nbits)
    return NULL;
  n = (*nbits+7)/8;
  d = _gcry_is_secure (s)? xtrymalloc_secure (n) : xtrymalloc (n);
  if (d)
    memcpy (d, s, n);
  return d;
}
Exemple #6
0
/* Create a new session key and append it as a tuple to the memory
   buffer MB.

   The EncFS daemon takes a passphrase from stdin and internally
   mangles it by means of some KDF from OpenSSL.  We want to store a
   binary key but we need to make sure that certain characters are not
   used because the EncFS utility reads it from stdin and obviously
   acts on some of the characters.  This we replace CR (in case of an
   MSDOS version of EncFS), LF (the delimiter used by EncFS) and Nul
   (because it is unlikely to work).  We use 32 bytes (256 bit)
   because that is sufficient for the largest cipher (AES-256) and in
   addition gives enough margin for a possible entropy degradation by
   the KDF.  */
gpg_error_t
be_encfs_create_new_keys (membuf_t *mb)
{
  char *buffer;
  int i, j;

  /* Allocate a buffer of 32 bytes plus 8 spare bytes we may need to
     replace the unwanted values.  */
  buffer = xtrymalloc_secure (32+8);
  if (!buffer)
    return gpg_error_from_syserror ();

  /* Randomize the buffer.  STRONG random should be enough as it is a
     good compromise between security and performance.  The
     anticipated usage of this tool is the quite often creation of new
     containers and thus this should not deplete the system's entropy
     tool too much.  */
  gcry_randomize (buffer, 32+8, GCRY_STRONG_RANDOM);
  for (i=j=0; i < 32; i++)
    {
      if (buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == 0 )
        {
          /* Replace.  */
          if (j == 8)
            {
              /* Need to get more random.  */
              gcry_randomize (buffer+32, 8, GCRY_STRONG_RANDOM);
              j = 0;
            }
          buffer[i] = buffer[32+j];
          j++;
        }
    }

  /* Store the key.  */
  append_tuple (mb, KEYBLOB_TAG_ENCKEY, buffer, 32);

  /* Free the temporary buffer.  */
  wipememory (buffer, 32+8);  /*  A failsafe extra wiping.  */
  xfree (buffer);

  return 0;
}
Exemple #7
0
/****************
 * This function allocates an MPI which is optimized to hold
 * a value as large as the one given in the argument and allocates it
 * with the same flags as A.
 */
gcry_mpi_t
_gcry_mpi_alloc_like( gcry_mpi_t a )
{
    gcry_mpi_t b;

    if( a && (a->flags & 4) ) {
	int n = (a->sign+7)/8;
	void *p = _gcry_is_secure(a->d)? xtrymalloc_secure (n)
                                       : xtrymalloc (n);
	memcpy( p, a->d, n );
	b = mpi_set_opaque( NULL, p, a->sign );
    }
    else if( a ) {
	b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
			    : mpi_alloc( a->nlimbs );
	b->nlimbs = 0;
	b->sign = 0;
	b->flags = a->flags;
    }
    else
	b = NULL;
    return b;
}
Exemple #8
0
/* Try to find an item in the cache.  Note that we currently don't
   make use of CACHE_MODE except for CACHE_MODE_NONCE and
   CACHE_MODE_USER.  */
char *
agent_get_cache (const char *key, cache_mode_t cache_mode)
{
  gpg_error_t err;
  ITEM r;
  char *value = NULL;
  int res;
  int last_stored = 0;

  if (cache_mode == CACHE_MODE_IGNORE)
    return NULL;

  if (!key)
    {
      key = last_stored_cache_key;
      if (!key)
        return NULL;
      last_stored = 1;
    }


  if (DBG_CACHE)
    log_debug ("agent_get_cache '%s' (mode %d)%s ...\n",
               key, cache_mode,
               last_stored? " (stored cache key)":"");
  housekeeping ();

  for (r=thecache; r; r = r->next)
    {
      if (r->pw
          && ((cache_mode != CACHE_MODE_USER
               && cache_mode != CACHE_MODE_NONCE)
              || r->cache_mode == cache_mode)
          && !strcmp (r->key, key))
        {
          /* Note: To avoid races KEY may not be accessed anymore below.  */
          r->accessed = gnupg_get_time ();
          if (DBG_CACHE)
            log_debug ("... hit\n");
          if (r->pw->totallen < 32)
            err = gpg_error (GPG_ERR_INV_LENGTH);
          else if ((err = init_encryption ()))
            ;
          else if (!(value = xtrymalloc_secure (r->pw->totallen - 8)))
            err = gpg_error_from_syserror ();
          else
            {
              res = npth_mutex_lock (&encryption_lock);
              if (res)
                log_fatal ("failed to acquire cache encryption mutex: %s\n",
			   strerror (res));
              err = gcry_cipher_decrypt (encryption_handle,
                                         value, r->pw->totallen - 8,
                                         r->pw->data, r->pw->totallen);
              res = npth_mutex_unlock (&encryption_lock);
              if (res)
                log_fatal ("failed to release cache encryption mutex: %s\n",
			   strerror (res));
            }
          if (err)
            {
              xfree (value);
              value = NULL;
              log_error ("retrieving cache entry '%s' failed: %s\n",
                         key, gpg_strerror (err));
            }
          return value;
        }
    }
  if (DBG_CACHE)
    log_debug ("... miss\n");

  return NULL;
}
Exemple #9
0
/* Encrypt a session key using DEK and store a pointer to the result
 * at R_ENCKEY and its length at R_ENCKEYLEN.
 *
 * R_SESKEY points to the unencrypted session key (.KEY, .KEYLEN) and
 * the algorithm that will be used to encrypt the contents of the
 * SKESK packet (.ALGO).  If R_SESKEY points to NULL, then a random
 * session key that is appropriate for DEK->ALGO is generated and
 * stored at R_SESKEY.  If AEAD_ALGO is not 0 the given AEAD algorithm
 * is used for encryption.
 */
gpg_error_t
encrypt_seskey (DEK *dek, aead_algo_t aead_algo,
                DEK **r_seskey, void **r_enckey, size_t *r_enckeylen)
{
  gpg_error_t err;
  gcry_cipher_hd_t hd = NULL;
  byte *buf = NULL;
  DEK *seskey;

  *r_enckey = NULL;
  *r_enckeylen = 0;

  if (*r_seskey)
    seskey = *r_seskey;
  else
    {
      seskey = xtrycalloc (1, sizeof(DEK));
      if (!seskey)
        {
          err = gpg_error_from_syserror ();
          goto leave;
        }
      seskey->algo = dek->algo;
      make_session_key (seskey);
      /*log_hexdump( "thekey", c->key, c->keylen );*/
    }


  if (aead_algo)
    {
      unsigned int noncelen;
      enum gcry_cipher_modes ciphermode;
      byte ad[4];

      err = openpgp_aead_algo_info (aead_algo, &ciphermode, &noncelen);
      if (err)
        goto leave;

      /* Allocate space for the nonce, the key, and the authentication
       * tag (16).  */
      buf = xtrymalloc_secure (noncelen + seskey->keylen + 16);
      if (!buf)
        {
          err = gpg_error_from_syserror ();
          goto leave;
        }

      gcry_randomize (buf, noncelen, GCRY_STRONG_RANDOM);

      err = openpgp_cipher_open (&hd, dek->algo,
                                 ciphermode, GCRY_CIPHER_SECURE);
      if (!err)
        err = gcry_cipher_setkey (hd, dek->key, dek->keylen);
      if (!err)
        err = gcry_cipher_setiv (hd, buf, noncelen);
      if (err)
        goto leave;

      ad[0] = (0xc0 | PKT_SYMKEY_ENC);
      ad[1] = 5;
      ad[2] = dek->algo;
      ad[3] = aead_algo;
      err = gcry_cipher_authenticate (hd, ad, 4);
      if (err)
        goto leave;

      memcpy (buf + noncelen, seskey->key, seskey->keylen);
      gcry_cipher_final (hd);
      err = gcry_cipher_encrypt (hd, buf + noncelen, seskey->keylen, NULL,0);
      if (err)
        goto leave;
      err = gcry_cipher_gettag (hd, buf + noncelen + seskey->keylen, 16);
      if (err)
        goto leave;
      *r_enckeylen = noncelen + seskey->keylen + 16;
      *r_enckey = buf;
      buf = NULL;
    }
  else
    {
      /* In the old version 4 SKESK the encrypted session key is
       * prefixed with a one-octet algorithm id.  */
      buf = xtrymalloc_secure (1 + seskey->keylen);
      if (!buf)
        {
          err = gpg_error_from_syserror ();
          goto leave;
        }
      buf[0] = seskey->algo;
      memcpy (buf + 1, seskey->key, seskey->keylen);

      err = openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1);
      if (!err)
        err = gcry_cipher_setkey (hd, dek->key, dek->keylen);
      if (!err)
        err = gcry_cipher_setiv (hd, NULL, 0);
      if (!err)
        err = gcry_cipher_encrypt (hd, buf, seskey->keylen + 1, NULL, 0);
      if (err)
        goto leave;
      *r_enckeylen = seskey->keylen + 1;
      *r_enckey = buf;
      buf = NULL;
    }

  /* Return the session key in case we allocated it.  */
  *r_seskey = seskey;
  seskey = NULL;

 leave:
  gcry_cipher_close (hd);
  if (seskey != *r_seskey)
    xfree (seskey);
  xfree (buf);
  return err;
}
Exemple #10
0
/**
 * _gcry_ecc_eddsa_genkey - EdDSA version of the key generation.
 *
 * @sk:  A struct to receive the secret key.
 * @E:   Parameters of the curve.
 * @ctx: Elliptic curve computation context.
 * @flags: Flags controlling aspects of the creation.
 *
 * Return: An error code.
 *
 * The only @flags bit used by this function is %PUBKEY_FLAG_TRANSIENT
 * to use a faster RNG.
 */
gpg_err_code_t
_gcry_ecc_eddsa_genkey (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
                        int flags)
{
  gpg_err_code_t rc;
  int b = 256/8;             /* The only size we currently support.  */
  gcry_mpi_t a, x, y;
  mpi_point_struct Q;
  gcry_random_level_t random_level;
  char *dbuf;
  size_t dlen;
  gcry_buffer_t hvec[1];
  unsigned char *hash_d = NULL;

  point_init (&Q);
  memset (hvec, 0, sizeof hvec);

  if ((flags & PUBKEY_FLAG_TRANSIENT_KEY))
    random_level = GCRY_STRONG_RANDOM;
  else
    random_level = GCRY_VERY_STRONG_RANDOM;

  a = mpi_snew (0);
  x = mpi_new (0);
  y = mpi_new (0);

  /* Generate a secret.  */
  hash_d = xtrymalloc_secure (2*b);
  if (!hash_d)
    {
      rc = gpg_error_from_syserror ();
      goto leave;
    }
  dlen = b;
  dbuf = _gcry_random_bytes_secure (dlen, random_level);

  /* Compute the A value.  */
  hvec[0].data = dbuf;
  hvec[0].len = dlen;
  rc = _gcry_md_hash_buffers (GCRY_MD_SHA512, 0, hash_d, hvec, 1);
  if (rc)
    goto leave;
  sk->d = _gcry_mpi_set_opaque (NULL, dbuf, dlen*8);
  dbuf = NULL;
  reverse_buffer (hash_d, 32);  /* Only the first half of the hash.  */
  hash_d[0] = (hash_d[0] & 0x7f) | 0x40;
  hash_d[31] &= 0xf8;
  _gcry_mpi_set_buffer (a, hash_d, 32, 0);
  xfree (hash_d); hash_d = NULL;
  /* log_printmpi ("ecgen         a", a); */

  /* Compute Q.  */
  _gcry_mpi_ec_mul_point (&Q, a, &E->G, ctx);
  if (DBG_CIPHER)
    log_printpnt ("ecgen      pk", &Q, ctx);

  /* Copy the stuff to the key structures. */
  sk->E.model = E->model;
  sk->E.dialect = E->dialect;
  sk->E.p = mpi_copy (E->p);
  sk->E.a = mpi_copy (E->a);
  sk->E.b = mpi_copy (E->b);
  point_init (&sk->E.G);
  point_set (&sk->E.G, &E->G);
  sk->E.n = mpi_copy (E->n);
  point_init (&sk->Q);
  point_set (&sk->Q, &Q);

 leave:
  point_free (&Q);
  _gcry_mpi_release (a);
  _gcry_mpi_release (x);
  _gcry_mpi_release (y);
  xfree (hash_d);
  return rc;
}
Exemple #11
0
static gpg_error_t
export_p12 (ctrl_t ctrl, const unsigned char *certimg, size_t certimglen,
            const char *prompt, const char *keygrip,
            void **r_result, size_t *r_resultlen)
{
  gpg_error_t err = 0;
  void *kek = NULL;
  size_t keklen;
  unsigned char *wrappedkey = NULL;
  size_t wrappedkeylen;
  gcry_cipher_hd_t cipherhd = NULL;
  gcry_sexp_t s_skey = NULL;
  gcry_mpi_t *kparms = NULL;
  unsigned char *key = NULL;
  size_t keylen;
  char *passphrase = NULL;
  unsigned char *result = NULL;
  size_t resultlen;
  int i;

  *r_result = NULL;

  /* Get the current KEK.  */
  err = gpgsm_agent_keywrap_key (ctrl, 1, &kek, &keklen);
  if (err)
    {
      log_error ("error getting the KEK: %s\n", gpg_strerror (err));
      goto leave;
    }

  /* Receive the wrapped key from the agent.  */
  err = gpgsm_agent_export_key (ctrl, keygrip, prompt,
                                &wrappedkey, &wrappedkeylen);
  if (err)
    goto leave;


  /* Unwrap the key.  */
  err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
                          GCRY_CIPHER_MODE_AESWRAP, 0);
  if (err)
    goto leave;
  err = gcry_cipher_setkey (cipherhd, kek, keklen);
  if (err)
    goto leave;
  xfree (kek);
  kek = NULL;

  if (wrappedkeylen < 24)
    {
      err = gpg_error (GPG_ERR_INV_LENGTH);
      goto leave;
    }
  keylen = wrappedkeylen - 8;
  key = xtrymalloc_secure (keylen);
  if (!key)
    {
      err = gpg_error_from_syserror ();
      goto leave;
    }
  err = gcry_cipher_decrypt (cipherhd, key, keylen, wrappedkey, wrappedkeylen);
  if (err)
    goto leave;
  xfree (wrappedkey);
  wrappedkey = NULL;
  gcry_cipher_close (cipherhd);
  cipherhd = NULL;


  /* Convert to a gcrypt S-expression.  */
  err = gcry_sexp_create (&s_skey, key, keylen, 0, xfree_fnc);
  if (err)
    goto leave;
  key = NULL; /* Key is now owned by S_KEY.  */

  /* Get the parameters from the S-expression.  */
  kparms = sexp_to_kparms (s_skey);
  gcry_sexp_release (s_skey);
  s_skey = NULL;
  if (!kparms)
    {
      log_error ("error converting key parameters\n");
      err = GPG_ERR_BAD_SECKEY;
      goto leave;
    }

  err = gpgsm_agent_ask_passphrase
    (ctrl,
     i18n_utf8 ("Please enter the passphrase to protect the "
                "new PKCS#12 object."),
     1, &passphrase);
  if (err)
    goto leave;

  result = p12_build (kparms, certimg, certimglen, passphrase,
                      opt.p12_charset, &resultlen);
  xfree (passphrase);
  passphrase = NULL;
  if (!result)
    err = gpg_error (GPG_ERR_GENERAL);

 leave:
  xfree (key);
  gcry_sexp_release (s_skey);
  if (kparms)
    {
      for (i=0; kparms[i]; i++)
        gcry_mpi_release (kparms[i]);
      xfree (kparms);
    }
  gcry_cipher_close (cipherhd);
  xfree (wrappedkey);
  xfree (kek);

  if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
    {
      /* During export this is the passphrase used to unprotect the
         key and not the pkcs#12 thing as in export.  Therefore we can
         issue the regular passphrase status.  FIXME: replace the all
         zero keyid by a regular one. */
      gpgsm_status (ctrl, STATUS_BAD_PASSPHRASE, "0000000000000000");
    }

  if (err)
    {
      xfree (result);
    }
  else
    {
      *r_result = result;
      *r_resultlen = resultlen;
    }
  return err;
}