/* Make a copy of the source s2k into R_DST. */
cdk_error_t
_cdk_s2k_copy (cdk_s2k_t * r_dst, cdk_s2k_t src)
{
  cdk_s2k_t dst;
  cdk_error_t err;

  err = cdk_s2k_new (&dst, src->mode, src->hash_algo, src->salt);
  if (err)
    return err;
  dst->count = src->count;
  *r_dst = dst;

  return 0;
}
Exemple #2
0
/**
 * cdk_sk_protect:
 * @sk: the secret key
 * @pw: the passphrase to use
 * 
 * Protect the given secret key with a passphrase.
 **/
cdk_error_t
cdk_sk_protect (cdk_pkt_seckey_t sk, const char *pw)
{
  gcry_cipher_hd_t hd = NULL;
  cdk_dek_t dek = NULL;
  cdk_s2k_t s2k;
  byte *p = NULL, buf[MAX_MPI_BYTES+2];
  size_t enclen = 0, nskey, i, nbytes;
  size_t dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
  gcry_error_t err;
  cdk_error_t rc;
  
  nskey = cdk_pk_get_nskey (sk->pubkey_algo);
  if (!nskey)
    return CDK_Inv_Algo;
  
  rc = cdk_s2k_new (&s2k, CDK_S2K_ITERSALTED, GCRY_MD_SHA256, NULL);
  if (!rc)
    rc = cdk_dek_from_passphrase (&dek, GCRY_CIPHER_AES, s2k, 1, pw);
  if (rc) 
    {
      cdk_s2k_free (s2k);
      return rc;
    }
  
  for (i = 0; i < nskey; i++)
    {
      enclen += 2;
      enclen += (gcry_mpi_get_nbits (sk->mpi[i])+7)/8;
    }
  p = sk->encdata = cdk_calloc (1, enclen + dlen + 1);
  if (!p)
    {
      cdk_s2k_free (s2k);
      return CDK_Out_Of_Core;
    }
  
  enclen = 0;
  for (i = 0; i < nskey; i++) 
    {
      if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, 
			  DIM (buf), &nbytes, sk->mpi[i]))
	{
	  cdk_free (p);
	  cdk_s2k_free (s2k);
	  return CDK_Wrong_Format;
	}     
      memcpy (p + enclen, buf, nbytes);
      enclen += nbytes;
    }
  
  enclen += dlen;
  sk->enclen = enclen;
  sk->protect.s2k = s2k;
  sk->protect.algo = GCRY_CIPHER_AES;
  sk->protect.ivlen = gcry_cipher_get_algo_blklen (sk->protect.algo);
  gcry_randomize (sk->protect.iv, sk->protect.ivlen, GCRY_STRONG_RANDOM);
  err = gcry_cipher_open (&hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB, 
			  GCRY_CIPHER_ENABLE_SYNC);
  if (err)
    {
      cdk_dek_free (dek);
      rc = map_gcry_error (err);
      goto leave;
    }
  
  err = gcry_cipher_setkey (hd, dek->key, dek->keylen);
  if (!err)
    err = gcry_cipher_setiv (hd, sk->protect.iv, sk->protect.ivlen);
  cdk_dek_free (dek);
  if (err)
    {
      rc = map_gcry_error (err);
      goto leave;
    }
  
  sk->protect.sha1chk = 1;
  sk->is_protected = 1;
  sk->csum = 0;
  
  gcry_md_hash_buffer (GCRY_MD_SHA1, buf, p, enclen-dlen);
  memcpy (p + enclen - dlen, buf, dlen);
  gcry_cipher_encrypt (hd, p, enclen, NULL, 0);
  
  /* FIXME: We should release all MPI's and set the elements to NULL. */
  
  leave:
  gcry_cipher_close (hd);
  return rc;
}