예제 #1
0
파일: keygen.c 프로젝트: uvbs/SupportCenter
static int
generate_subkey( cdk_keygen_ctx_t hd )
{
    gcry_sexp_t s_params = NULL, s_key;
    size_t n = hd->key[1].len;
    int rc;

    if( !hd )
        return CDK_Inv_Value;
  
    if( is_DSA( hd->key[1].algo) )
        rc = gcry_sexp_build( &s_params, NULL, "(genkey(dsa(nbits %d)))", n );
    else if( is_ELG( hd->key[1].algo) )
        rc = gcry_sexp_build( &s_params, NULL, "(genkey(elg(nbits %d)))", n );
    else if( is_RSA( hd->key[1].algo) )
        rc = gcry_sexp_build( &s_params, NULL, "(genkey(rsa(nbits %d)))", n );
    else
        rc = CDK_Inv_Algo;
    if( !rc )
        rc = gcry_pk_genkey( &s_key, s_params );
    gcry_sexp_release( s_params );
    if( !rc ) {
        if( is_DSA( hd->key[1].algo) )
            rc = read_dsa_key( s_key, hd->key[1].resarr );
        else if( is_ELG( hd->key[1].algo) )
            rc = read_elg_key( s_key, hd->key[1].resarr );
        else if( is_RSA( hd->key[1].algo) )
            rc = read_rsa_key( s_key, hd->key[1].resarr );
    }
    hd->key[1].n = cdk_pk_get_npkey( hd->key[1].algo );
    gcry_sexp_release( s_key );
    return rc;
}
예제 #2
0
/**
 * cdk_pk_get_keyid:
 * @pk: the public key
 * @keyid: buffer to store the key ID
 * 
 * Calculate the key ID of the given public key.
 **/
u32
cdk_pk_get_keyid (cdk_pubkey_t pk, u32 *keyid)
{
  u32 lowbits = 0;
  byte buf[24];
  
  if (pk && (!pk->keyid[0] || !pk->keyid[1])) 
    {
      if (pk->version < 4 && is_RSA (pk->pubkey_algo)) 
	{
	  byte p[MAX_MPI_BYTES];
	  size_t n;
	  
	  gcry_mpi_print (GCRYMPI_FMT_USG, p, MAX_MPI_BYTES, &n, pk->mpi[0]);
	  pk->keyid[0] = p[n-8] << 24 | p[n-7] << 16 | p[n-6] << 8 | p[n-5];
	  pk->keyid[1] = p[n-4] << 24 | p[n-3] << 16 | p[n-2] << 8 | p[n-1];
	}
      else if (pk->version == 4)
	{
	  cdk_pk_get_fingerprint (pk, buf);
	  pk->keyid[0] = _cdk_buftou32 (buf + 12);
	  pk->keyid[1] = _cdk_buftou32 (buf + 16);
	}
    }
  lowbits = pk ? pk->keyid[1] : 0;
  if (keyid && pk)
    {
      keyid[0] = pk->keyid[0];
      keyid[1] = pk->keyid[1];
    }
  
  return lowbits;
}
예제 #3
0
/**
 * cdk_pk_get_fingerprint:
 * @pk: the public key
 * @fpr: the buffer to hold the fingerprint
 *
 * Return the fingerprint of the given public key.
 * The buffer must be at least 20 octets.
 * This function should be considered deprecated and
 * the new cdk_pk_to_fingerprint() should be used whenever
 * possible to avoid overflows.
 **/
cdk_error_t
cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte * fpr)
{
    digest_hd_st hd;
    int md_algo;
    int dlen = 0;
    int err;

    if (!pk || !fpr)
        return CDK_Inv_Value;

    if (pk->version < 4 && is_RSA (pk->pubkey_algo))
        md_algo = GNUTLS_DIG_MD5;   /* special */
    else
        md_algo = GNUTLS_DIG_SHA1;
    dlen = _gnutls_hash_get_algo_len (md_algo);
    err = _gnutls_hash_init (&hd, md_algo);
    if (err < 0)
    {
        gnutls_assert ();
        return map_gnutls_error (err);
    }
    _cdk_hash_pubkey (pk, &hd, 1);
    _gnutls_hash_deinit (&hd, fpr);
    if (dlen == 16)
        memset (fpr + 16, 0, 4);
    return 0;
}
예제 #4
0
/* This function gets the signature parameters and encodes
 * them into a way for _gnutls_pk_verify to use.
 */
static cdk_error_t
sig_to_datum (gnutls_datum_t * r_sig, cdk_pkt_signature_t sig)
{
    int err;
    cdk_error_t rc;

    if (!r_sig || !sig)
        return CDK_Inv_Value;

    rc = 0;
    if (is_RSA (sig->pubkey_algo))
    {
        err = _gnutls_mpi_dprint (sig->mpi[0], r_sig);
        if (err < 0)
            rc = map_gnutls_error (err);
    }
    else if (is_DSA (sig->pubkey_algo))
    {
        err = _gnutls_encode_ber_rs (r_sig, sig->mpi[0], sig->mpi[1]);
        if (err < 0)
            rc = map_gnutls_error (err);
    }
    else
        rc = CDK_Inv_Algo;
    return rc;
}
예제 #5
0
/**
 * gnutls_openpgp_privkey_get_subkey_pk_algorithm:
 * @key: is an OpenPGP key
 * @idx: is the subkey index
 * @bits: if bits is non null it will hold the size of the parameters' in bits
 *
 * This function will return the public key algorithm of a subkey of an OpenPGP
 * certificate.
 *
 * If bits is non null, it should have enough size to hold the parameters
 * size in bits. For RSA the bits returned is the modulus.
 * For DSA the bits returned are of the public exponent.
 *
 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
 *   success, or a negative error code on error.
 *
 * Since: 2.4.0
 **/
gnutls_pk_algorithm_t
gnutls_openpgp_privkey_get_subkey_pk_algorithm(gnutls_openpgp_privkey_t
					       key, unsigned int idx,
					       unsigned int *bits)
{
	cdk_packet_t pkt;
	int algo;

	if (!key) {
		gnutls_assert();
		return GNUTLS_PK_UNKNOWN;
	}

	if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
		return gnutls_openpgp_privkey_get_pk_algorithm(key, bits);

	pkt = _get_secret_subkey(key, idx);

	algo = 0;
	if (pkt) {
		if (bits)
			*bits = cdk_pk_get_nbits(pkt->pkt.secret_key->pk);
		algo = pkt->pkt.secret_key->pubkey_algo;
		if (is_RSA(algo))
			algo = GNUTLS_PK_RSA;
		else if (is_DSA(algo))
			algo = GNUTLS_PK_DSA;
		else
			algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM;
	}

	return algo;
}
예제 #6
0
/**
 * gnutls_openpgp_privkey_get_fingerprint:
 * @key: the raw data that contains the OpenPGP secret key.
 * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes.
 * @fprlen: the integer to save the length of the fingerprint.
 *
 * Get the fingerprint of the OpenPGP key. Depends on the
 * algorithm, the fingerprint can be 16 or 20 bytes.
 *
 * Returns: On success, 0 is returned, or an error code.
 *
 * Since: 2.4.0
 **/
int
gnutls_openpgp_privkey_get_fingerprint(gnutls_openpgp_privkey_t key,
				       void *fpr, size_t * fprlen)
{
	cdk_packet_t pkt;
	cdk_pkt_pubkey_t pk = NULL;

	if (!fpr || !fprlen) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	*fprlen = 0;

	pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_SECRET_KEY);
	if (!pkt) {
		gnutls_assert();
		return GNUTLS_E_OPENPGP_GETKEY_FAILED;
	}

	pk = pkt->pkt.secret_key->pk;
	*fprlen = 20;

	if (is_RSA(pk->pubkey_algo) && pk->version < 4)
		*fprlen = 16;

	cdk_pk_get_fingerprint(pk, fpr);

	return 0;
}
예제 #7
0
static cdk_error_t
pubenc_to_sexp (gcry_sexp_t * r_sexp, cdk_pkt_pubkey_enc_t enc)
{
  gcry_sexp_t sexp = NULL;
  gcry_error_t err;
  const char *fmt;
  
  if (!r_sexp || !enc)
    return CDK_Inv_Value;
  
  *r_sexp = NULL;
  if (is_RSA (enc->pubkey_algo))
    {
      fmt = "(enc-val(openpgp-rsa((a%m))))";
      err = gcry_sexp_build (&sexp, NULL, fmt, enc->mpi[0]);
    }
  else if (is_ELG (enc->pubkey_algo))
    {
      fmt = "(enc-val(openpgp-elg((a%m)(b%m))))";
      err = gcry_sexp_build (&sexp, NULL, fmt, enc->mpi[0], enc->mpi[1]);      
    }
  else
    return CDK_Inv_Algo;
  if (err)
    return map_gcry_error (err);
  *r_sexp = sexp;
  return 0;
}
예제 #8
0
/**
 * gnutls_openpgp_privkey_get_subkey_fingerprint:
 * @key: the raw data that contains the OpenPGP secret key.
 * @idx: the subkey index
 * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes.
 * @fprlen: the integer to save the length of the fingerprint.
 *
 * Get the fingerprint of an OpenPGP subkey.  Depends on the
 * algorithm, the fingerprint can be 16 or 20 bytes.
 *
 * Returns: On success, 0 is returned, or an error code.
 *
 * Since: 2.4.0
 **/
int
gnutls_openpgp_privkey_get_subkey_fingerprint(gnutls_openpgp_privkey_t key,
					      unsigned int idx,
					      void *fpr, size_t * fprlen)
{
	cdk_packet_t pkt;
	cdk_pkt_pubkey_t pk = NULL;

	if (!fpr || !fprlen) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
		return gnutls_openpgp_privkey_get_fingerprint(key, fpr,
							      fprlen);

	*fprlen = 0;

	pkt = _get_secret_subkey(key, idx);
	if (!pkt)
		return GNUTLS_E_OPENPGP_GETKEY_FAILED;


	pk = pkt->pkt.secret_key->pk;
	*fprlen = 20;

	if (is_RSA(pk->pubkey_algo) && pk->version < 4)
		*fprlen = 16;

	cdk_pk_get_fingerprint(pk, fpr);

	return 0;
}
예제 #9
0
static cdk_error_t
write_v3_sig (cdk_stream_t out, cdk_pkt_signature_t sig, int nsig)
{
  size_t size;
  cdk_error_t rc;

  size = 19 + calc_mpisize (sig->mpi, nsig);
  if (is_RSA (sig->pubkey_algo))
    rc = pkt_write_head2 (out, size, CDK_PKT_SIGNATURE);
  else
    rc = pkt_write_head (out, 1, size, CDK_PKT_SIGNATURE);
  if (!rc)
    rc = stream_putc (out, sig->version);
  if (!rc)
    rc = stream_putc (out, 5);
  if (!rc)
    rc = stream_putc (out, sig->sig_class);
  if (!rc)
    rc = write_32 (out, sig->timestamp);
  if (!rc)
    rc = write_32 (out, sig->keyid[0]);
  if (!rc)
    rc = write_32 (out, sig->keyid[1]);
  if (!rc)
    rc = stream_putc (out, _cdk_pub_algo_to_pgp (sig->pubkey_algo));
  if (!rc)
    rc = stream_putc (out, _gnutls_hash_algo_to_pgp (sig->digest_algo));
  if (!rc)
    rc = stream_putc (out, sig->digest_start[0]);
  if (!rc)
    rc = stream_putc (out, sig->digest_start[1]);
  if (!rc)
    rc = write_mpibuf (out, sig->mpi, nsig);
  return rc;
}
예제 #10
0
static cdk_error_t
sig_to_sexp (gcry_sexp_t *r_sig_sexp, cdk_pkt_signature_t sig)
{
  gcry_error_t err;
  cdk_error_t rc;
  const char *fmt;
  
  if (!r_sig_sexp || !sig)
    return CDK_Inv_Value;  
  if (is_ELG (sig->pubkey_algo))
    return CDK_Not_Implemented;
  
  rc = 0;
  if (is_RSA (sig->pubkey_algo)) 
    {
      fmt = "(sig-val(openpgp-rsa(s%m)))";
      err = gcry_sexp_build (r_sig_sexp, NULL, fmt, sig->mpi[0]);
      if (err)
	rc = map_gcry_error (err);
    }
  else if (is_DSA (sig->pubkey_algo))
    {
      fmt = "(sig-val(openpgp-dsa(r%m)(s%m)))";
      err = gcry_sexp_build (r_sig_sexp, NULL, fmt, sig->mpi[0], sig->mpi[1]);
      if (err)
	rc = map_gcry_error (err);
    }
  else
    rc = CDK_Inv_Algo;
  return rc;
}
예제 #11
0
static cdk_error_t
sexp_to_sig (cdk_pkt_signature_t sig, gcry_sexp_t sexp)
{
  if (!sig || !sexp)
    return CDK_Inv_Value;

  /* ElGamal signatures are not supported any longer. */
  if (is_ELG (sig->pubkey_algo))
    {
      _cdk_log_debug ("sexp_to_sig: unsupported signature type (ElGamal)\n");
      return CDK_Not_Implemented;
    }  
  
  if (is_RSA (sig->pubkey_algo))
    return sexp_to_mpi (sexp, "s", &sig->mpi[0]);
  else if (is_DSA (sig->pubkey_algo))
    {
      cdk_error_t rc;
      
      rc = sexp_to_mpi (sexp, "r", &sig->mpi[0]);
      if (!rc)
	rc = sexp_to_mpi (sexp, "s", &sig->mpi[1]);
      return rc;
    }
  return CDK_Inv_Algo;
}
예제 #12
0
파일: pgp.c 프로젝트: uvbs/SupportCenter
/**
  * gnutls_openpgp_key_get_pk_algorithm - This function returns the key's PublicKey algorithm
  * @key: is an OpenPGP key
  * @bits: if bits is non null it will hold the size of the parameters' in bits
  *
  * This function will return the public key algorithm of an OpenPGP
  * certificate.
  *
  * If bits is non null, it should have enough size to hold the parameters
  * size in bits. For RSA the bits returned is the modulus. 
  * For DSA the bits returned are of the public exponent.
  *
  * Returns a member of the GNUTLS_PKAlgorithm enumeration on success,
  * or a negative value on error.
  *
  **/
int
gnutls_openpgp_key_get_pk_algorithm (gnutls_openpgp_key_t key,
				     unsigned int *bits)
{
  cdk_packet_t pkt;
  int algo = 0;

  if (!key)
    return GNUTLS_E_INVALID_REQUEST;

  pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
  if (pkt && pkt->pkttype == CDK_PKT_PUBLIC_KEY)
    {
      if (bits)
	*bits = cdk_pk_get_nbits (pkt->pkt.public_key);
      algo = pkt->pkt.public_key->pubkey_algo;
      if (is_RSA (algo))
	algo = GNUTLS_PK_RSA;
      else if (is_DSA (algo))
	algo = GNUTLS_PK_DSA;
      else
	algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM;
    }

  return algo;
}
예제 #13
0
/**
 * cdk_pk_get_fingerprint:
 * @pk: the public key
 * @fpr: the buffer to hold the fingerprint
 * 
 * Return the fingerprint of the given public key.
 * The buffer must be at least 20 octets.
 * This function should be considered deprecated and
 * the new cdk_pk_to_fingerprint() should be used whenever
 * possible to avoid overflows.
 **/
cdk_error_t
cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte *fpr)
{
  gcry_md_hd_t hd;
  int md_algo;
  int dlen = 0;
  gcry_error_t err;

  if (!pk || !fpr)
    return CDK_Inv_Value;
  
  if (pk->version < 4 && is_RSA (pk->pubkey_algo))
    md_algo = GCRY_MD_MD5; /* special */
  else
    md_algo = GCRY_MD_SHA1;
  dlen = gcry_md_get_algo_dlen (md_algo);
  err = gcry_md_open (&hd, md_algo, 0);
  if (err)
    return map_gcry_error (err);
  _cdk_hash_pubkey (pk, hd, 1);
  gcry_md_final (hd);
  memcpy (fpr, gcry_md_read (hd, md_algo), dlen);
  gcry_md_close (hd);
  if (dlen == 16)
    memset (fpr + 16, 0, 4);
  return 0;
}
예제 #14
0
파일: keygen.c 프로젝트: uvbs/SupportCenter
/**
 * cdk_keygen_start: kick off the key generation
 * @hd: the keygen object
 *
 **/
cdk_error_t
cdk_keygen_start( cdk_keygen_ctx_t hd )
{
    gcry_sexp_t s_params = NULL, s_key = NULL;
    size_t n;
    int rc = 0;
  
    if( !hd || !hd->user_id )
        return CDK_Inv_Value;
    if( is_ELG( hd->key[0].algo ) )
        return CDK_Inv_Mode;
    if( !hd->key[0].len )
        hd->key[0].len = 1024;
    n = hd->key[0].len;

    if( !hd->sym_prefs )
        cdk_keygen_set_prefs( hd, CDK_PREFTYPE_SYM, NULL, 0 );
    if( !hd->hash_prefs )
        cdk_keygen_set_prefs( hd, CDK_PREFTYPE_HASH, NULL, 0 );
    if( !hd->zip_prefs )
        cdk_keygen_set_prefs( hd, CDK_PREFTYPE_ZIP, NULL, 0 );

    if( is_DSA( hd->key[0].algo ) )
        rc = gcry_sexp_build( &s_params, NULL, "(genkey(dsa(nbits %d)))", n );
    else if( is_RSA( hd->key[0].algo ) )
        rc = gcry_sexp_build( &s_params, NULL, "(genkey(rsa(nbits %d)))", n );
    else
        rc = CDK_Inv_Algo;
    if( !rc )
        rc = gcry_pk_genkey( &s_key, s_params );
    gcry_sexp_release( s_params );
    if( !rc ) {
        if( is_DSA( hd->key[0].algo ) )
            rc = read_dsa_key( s_key, hd->key[0].resarr );
        else if( is_RSA( hd->key[0].algo ) )
            rc = read_rsa_key( s_key, hd->key[0].resarr );
        hd->key[0].n = cdk_pk_get_npkey( hd->key[0].algo );
    }
    gcry_sexp_release( s_key );
    if( !rc ) {
        if( hd->key[1].algo && hd->key[1].len )
            rc = generate_subkey( hd );
    }
    return rc;
}
예제 #15
0
파일: pubkey.c 프로젝트: GostCrypt/GnuTLS
/**
 * cdk_pk_get_nbits:
 * @algo: the public key algorithm
 * 
 * Return the number of MPIs a signature consists of.
 **/
int cdk_pk_get_nsig(int algo)
{
	if (is_RSA(algo))
		return 1;
	else if (is_DSA(algo))
		return 2;
	else
		return 0;
}
예제 #16
0
파일: pubkey.c 프로젝트: GostCrypt/GnuTLS
/**
 * cdk_pk_get_nenc: 
 * @algo: the public key algorithm
 * 
 * Return the number of MPI's the encrypted data consists of.
 **/
int cdk_pk_get_nenc(int algo)
{
	if (is_RSA(algo))
		return 1;
	else if (is_ELG(algo))
		return 2;
	else
		return 0;
}
예제 #17
0
파일: pubkey.c 프로젝트: BridgeNY/purdue
/****************
 * Return the number of encryption material numbers
 */
int
pubkey_get_nenc( int algo )
{
    int i;
    do {
	for(i=0; pubkey_table[i].name; i++ )
	    if( pubkey_table[i].algo == algo )
		return pubkey_table[i].nenc;
    } while( load_pubkey_modules() );
    if( is_RSA(algo) )	  /* special hack, so that we are able to */
	return 1;	  /* see the RSA keyids */
    return 0;
}
예제 #18
0
파일: pubkey.c 프로젝트: GostCrypt/GnuTLS
/**
 * cdk_pk_get_npkey:
 * @algo: The public key algorithm.
 * 
 * Return the number of multiprecison integer forming an public
 * key with the given algorithm.
 */
int cdk_pk_get_npkey(int algo)
{
	if (is_RSA(algo))
		return RSA_PUBLIC_PARAMS;
	else if (is_DSA(algo))
		return DSA_PUBLIC_PARAMS;
	else if (is_ELG(algo))
		return 3;
	else {
		gnutls_assert();
		return 0;
	}
}
예제 #19
0
파일: pubkey.c 프로젝트: BridgeNY/purdue
/****************
 * Get the number of nbits from the public key
 */
unsigned
pubkey_nbits( int algo, MPI *pkey )
{
    int i;

    do {
	for(i=0; pubkey_table[i].name; i++ )
	    if( pubkey_table[i].algo == algo )
		return (*pubkey_table[i].get_nbits)( algo, pkey );
    } while( load_pubkey_modules() );
    if( is_RSA(algo) )	/* we always wanna see the length of a key :-) */
	return mpi_get_nbits( pkey[0] );
    return 0;
}
예제 #20
0
int _gnutls_openpgp_get_algo(int cdk_algo)
{
	int algo;

	if (is_RSA(cdk_algo))
		algo = GNUTLS_PK_RSA;
	else if (is_DSA(cdk_algo))
		algo = GNUTLS_PK_DSA;
	else {
		_gnutls_debug_log("Unknown OpenPGP algorithm %d\n",
				  cdk_algo);
		algo = GNUTLS_PK_UNKNOWN;
	}

	return algo;
}
예제 #21
0
static cdk_error_t
sexp_to_pubenc (cdk_pkt_pubkey_enc_t enc, gcry_sexp_t sexp)
{
  if (!sexp || !enc)
    return CDK_Inv_Value;
  
  if (is_RSA (enc->pubkey_algo))
    return sexp_to_mpi (sexp, "a", &enc->mpi[0]);
  else if (is_ELG (enc->pubkey_algo))
    {
      cdk_error_t rc = sexp_to_mpi (sexp, "a", &enc->mpi[0]);
      if (!rc)
	rc = sexp_to_mpi (sexp, "b", &enc->mpi[1]);
      return rc;
    }
  return CDK_Inv_Algo;
}
예제 #22
0
파일: pubkey.c 프로젝트: GostCrypt/GnuTLS
/**
 * cdk_pk_get_nskey:
 * @algo: the public key algorithm
 * 
 * Return the number of multiprecision integers forming an
 * secret key with the given algorithm.
 **/
int cdk_pk_get_nskey(int algo)
{
	int ret;

	if (is_RSA(algo))
		ret = RSA_PRIVATE_PARAMS - 2;	/* we don't have exp1 and exp2 */
	else if (is_DSA(algo))
		ret = DSA_PRIVATE_PARAMS;
	else if (is_ELG(algo))
		ret = 4;
	else {
		gnutls_assert();
		return 0;
	}

	ret -= cdk_pk_get_npkey(algo);
	return ret;
}
예제 #23
0
파일: xml.c 프로젝트: uvbs/SupportCenter
static int
xml_add_key_mpi (gnutls_string * xmlkey, cdk_pkt_pubkey_t pk)
{
  const char *s = "    <KEY ENCODING=\"HEX\"/>\n";
  int rc = 0;

  if (!xmlkey || !pk)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  _gnutls_string_append_str (xmlkey, s);

  if (is_RSA (pk->pubkey_algo))
    {
      rc = xml_add_mpi (xmlkey, pk, 0, "RSA-N");
      if (!rc)
	rc = xml_add_mpi (xmlkey, pk, 1, "RSA-E");
    }
  else if (is_DSA (pk->pubkey_algo))
    {
      rc = xml_add_mpi (xmlkey, pk, 0, "DSA-P");
      if (!rc)
	rc = xml_add_mpi (xmlkey, pk, 1, "DSA-Q");
      if (!rc)
	rc = xml_add_mpi (xmlkey, pk, 2, "DSA-G");
      if (!rc)
	rc = xml_add_mpi (xmlkey, pk, 3, "DSA-Y");
    }
  else if (is_ELG (pk->pubkey_algo))
    {
      rc = xml_add_mpi (xmlkey, pk, 0, "ELG-P");
      if (!rc)
	rc = xml_add_mpi (xmlkey, pk, 1, "ELG-G");
      if (!rc)
	rc = xml_add_mpi (xmlkey, pk, 2, "ELG-Y");
    }
  else
    return GNUTLS_E_UNWANTED_ALGORITHM;

  return 0;
}
예제 #24
0
/* Convert the given secret key into a gcrypt SEXP object. */
static int
seckey_to_sexp (gcry_sexp_t *r_skey, cdk_seckey_t sk)
{
  gcry_sexp_t sexp = NULL;
  gcry_mpi_t *mpk = NULL, *msk = NULL;
  gcry_error_t err;
  cdk_pubkey_t pk;
  const char *fmt;

  if (!r_skey || !sk || !sk->pk)
    return CDK_Inv_Value;

  pk = sk->pk;
  mpk = pk->mpi;
  msk = sk->mpi;
  
  *r_skey = NULL;
  if (is_RSA (sk->pubkey_algo))
    {      
      fmt = "(private-key(openpgp-rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))";
      err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1],
			     msk[0], msk[1], msk[2], msk[3]);      
    }
  else if (is_ELG (sk->pubkey_algo))
    {
      fmt = "(private-key(openpgp-elg(p%m)(g%m)(y%m)(x%m)))";
      err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1],
			     mpk[2], msk[0]);
    }
  else if (is_DSA (sk->pubkey_algo))
    {
      fmt = "(private-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)(x%m)))";
      err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1], mpk[2],
			     mpk[3], msk[0]);
    }
  else
    return CDK_Inv_Algo;
  if (err)
    return map_gcry_error (err);
  *r_skey = sexp;
  return 0;
}
예제 #25
0
파일: pubkey.c 프로젝트: GostCrypt/GnuTLS
/**
 * cdk_pk_get_keyid:
 * @pk: the public key
 * @keyid: buffer to store the key ID
 * 
 * Calculate the key ID of the given public key.
 **/
u32 cdk_pk_get_keyid(cdk_pubkey_t pk, u32 * keyid)
{
	u32 lowbits = 0;
	byte buf[24];
	int rc;

	if (pk && (!pk->keyid[0] || !pk->keyid[1])) {
		if (pk->version < 4 && is_RSA(pk->pubkey_algo)) {
			byte p[MAX_MPI_BYTES];
			size_t n;

			n = MAX_MPI_BYTES;
			rc = _gnutls_mpi_print(pk->mpi[0], p, &n);
			if (rc < 0 || n < 8) {
				keyid[0] = keyid[1] = (u32)-1;
				return (u32)-1;
			}

			pk->keyid[0] =
			    p[n - 8] << 24 | p[n - 7] << 16 | p[n -
								6] << 8 |
			    p[n - 5];
			pk->keyid[1] =
			    p[n - 4] << 24 | p[n - 3] << 16 | p[n -
								2] << 8 |
			    p[n - 1];
		} else if (pk->version == 4) {
			cdk_pk_get_fingerprint(pk, buf);
			pk->keyid[0] = _cdk_buftou32(buf + 12);
			pk->keyid[1] = _cdk_buftou32(buf + 16);
		}
	}
	lowbits = pk ? pk->keyid[1] : 0;
	if (keyid && pk) {
		keyid[0] = pk->keyid[0];
		keyid[1] = pk->keyid[1];
	}

	return lowbits;
}
예제 #26
0
파일: sig-check.c 프로젝트: bf4/pidgin-mac
/* Hash an entire public key PK with the given message digest context
   MD. The @usefpr param is only valid for version 3 keys because of
   the different way to calculate the fingerprint. */
cdk_error_t
_cdk_hash_pubkey (cdk_pubkey_t pk, digest_hd_st * md, int usefpr)
{
  byte buf[12];
  size_t i, n, npkey;

  if (!pk || !md)
    return CDK_Inv_Value;

  if (usefpr && pk->version < 4 && is_RSA (pk->pubkey_algo))
    return hash_mpibuf (pk, md, 1);

  /* The version 4 public key packet does not have the 2 octets for
     the expiration date. */
  n = pk->version < 4 ? 8 : 6;
  npkey = cdk_pk_get_npkey (pk->pubkey_algo);
  for (i = 0; i < npkey; i++)
    n = n + (_gnutls_mpi_get_nbits (pk->mpi[i]) + 7) / 8 + 2;

  i = 0;
  buf[i++] = 0x99;
  buf[i++] = n >> 8;
  buf[i++] = n >> 0;
  buf[i++] = pk->version;
  buf[i++] = pk->timestamp >> 24;
  buf[i++] = pk->timestamp >> 16;
  buf[i++] = pk->timestamp >> 8;
  buf[i++] = pk->timestamp >> 0;

  if (pk->version < 4)
    {
      u16 a = 0;

      /* Convert the expiration date into days. */
      if (pk->expiredate)
	a = (u16) ((pk->expiredate - pk->timestamp) / 86400L);
      buf[i++] = a >> 8;
      buf[i++] = a;
    }
예제 #27
0
/* Convert the given public key to a gcrypt SEXP object. */
static cdk_error_t
pubkey_to_sexp (gcry_sexp_t *r_key_sexp, cdk_pubkey_t pk)
{
  gcry_mpi_t *m;
  gcry_error_t err;
  const char *fmt = NULL;
  cdk_error_t rc = 0;
  
  if (!r_key_sexp || !pk)
    return CDK_Inv_Value;

  m = pk->mpi;
  if (is_RSA (pk->pubkey_algo))
    {
      fmt = "(public-key(openpgp-rsa(n%m)(e%m)))";
      err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1]);
      if (err)
	rc = map_gcry_error (err);
    }
  else if (is_ELG (pk->pubkey_algo)) 
    {
      fmt = "(public-key(openpgp-elg(p%m)(g%m)(y%m)))";
      err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1], m[2]);
      if (err)
	rc = map_gcry_error (err);
    }
  else if (is_DSA (pk->pubkey_algo)) 
    {
      fmt = "(public-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)))";
      err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1], m[2], m[3]);
      if (err)
	rc = map_gcry_error (err);
    }
  else
    rc = CDK_Inv_Algo;
  return rc;
}
예제 #28
0
static int
do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
{
  int rc = 0;
  int i, nskey, npkey;
  IOBUF a = iobuf_temp(); /* Build in a self-enlarging buffer.  */

  /* Write the version number - if none is specified, use 3 */
  if ( !sk->version )
    iobuf_put ( a, 3 );
  else
    iobuf_put ( a, sk->version );
  write_32 (a, sk->timestamp );

  /* v3 needs the expiration time. */
  if ( sk->version < 4 )
    {
      u16 ndays;
      if ( sk->expiredate )
        ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L);
      else
        ndays = 0;
      write_16(a, ndays);
    }
  
  iobuf_put (a, sk->pubkey_algo );
  
  /* Get number of secret and public parameters.  They are held in one
     array first the public ones, then the secret ones.  */
  nskey = pubkey_get_nskey ( sk->pubkey_algo );
  npkey = pubkey_get_npkey ( sk->pubkey_algo );
  
  /* If we don't have any public parameters - which is the case if we
     don't know the algorithm used - the parameters are stored as one
     blob in a faked (opaque) MPI. */
  if ( !npkey ) 
    {
      write_fake_data( a, sk->skey[0] );
      goto leave;
    }
  assert ( npkey < nskey );

  /* Writing the public parameters is easy. */
  for (i=0; i < npkey; i++ )
    if ((rc = mpi_write (a, sk->skey[i])))
      goto leave;
  
  /* Build the header for protected (encrypted) secret parameters.  */
  if ( sk->is_protected ) 
    {
      if ( is_RSA(sk->pubkey_algo) 
           && sk->version < 4
           && !sk->protect.s2k.mode )
        {
          /* The simple rfc1991 (v3) way. */
          iobuf_put (a, sk->protect.algo );
          iobuf_write (a, sk->protect.iv, sk->protect.ivlen );
	}
      else
        {
          /* OpenPGP protection according to rfc2440. */
          iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff );
          iobuf_put(a, sk->protect.algo );
          if ( sk->protect.s2k.mode >= 1000 )
            {
              /* These modes are not possible in OpenPGP, we use them
                 to implement our extensions, 101 can be seen as a
                 private/experimental extension (this is not specified
                 in rfc2440 but the same scheme is used for all other
                 algorithm identifiers) */
              iobuf_put(a, 101 ); 
              iobuf_put(a, sk->protect.s2k.hash_algo );
              iobuf_write(a, "GNU", 3 );
              iobuf_put(a, sk->protect.s2k.mode - 1000 );
	    }
          else 
            {
              iobuf_put(a, sk->protect.s2k.mode );
              iobuf_put(a, sk->protect.s2k.hash_algo );
	    }
          if ( sk->protect.s2k.mode == 1
               || sk->protect.s2k.mode == 3 )
            iobuf_write (a, sk->protect.s2k.salt, 8 );

          if ( sk->protect.s2k.mode == 3 )
            iobuf_put (a, sk->protect.s2k.count ); 

          /* For our special modes 1001, 1002 we do not need an IV. */
          if ( sk->protect.s2k.mode != 1001 
               && sk->protect.s2k.mode != 1002 )
            iobuf_write (a, sk->protect.iv, sk->protect.ivlen );
	}
    }
  else
    iobuf_put (a, 0 );

  if ( sk->protect.s2k.mode == 1001 )
    ; /* GnuPG extension - don't write a secret key at all. */ 
  else if ( sk->protect.s2k.mode == 1002 )
    { 
      /* GnuPG extension - divert to OpenPGP smartcard. */ 
      iobuf_put(a, sk->protect.ivlen ); /* Length of the serial number
                                           or 0 for no serial
                                           number. */
      /* The serial number gets stored in the IV field. */
      iobuf_write(a, sk->protect.iv, sk->protect.ivlen);
    }
  else if ( sk->is_protected && sk->version >= 4 )
    {
      /* The secret key is protected - write it out as it is.  */
      byte *p;
      unsigned int ndatabits;
      
      assert (gcry_mpi_get_flag (sk->skey[npkey], GCRYMPI_FLAG_OPAQUE));
      p = gcry_mpi_get_opaque (sk->skey[npkey], &ndatabits );
      iobuf_write (a, p, (ndatabits+7)/8 );
    }
  else if ( sk->is_protected ) 
    {
      /* The secret key is protected the old v4 way. */
      for ( ; i < nskey; i++ ) 
        {
          byte *p;
          unsigned int ndatabits;
          
          assert (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE));
          p = gcry_mpi_get_opaque (sk->skey[i], &ndatabits);
          iobuf_write (a, p, (ndatabits+7)/8);
        }
      write_16(a, sk->csum );
    }
  else
    {
      /* Non-protected key. */
      for ( ; i < nskey; i++ )
        if ( (rc = mpi_write (a, sk->skey[i])))
          goto leave;
      write_16 (a, sk->csum );
    }

 leave:
  if (!rc)
    {
      /* Build the header of the packet - which we must do after
         writing all the other stuff, so that we know the length of
         the packet */
      write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes);
      /* And finally write it out the real stream */
      rc = iobuf_write_temp( out, a );
    }

  iobuf_close(a); /* Close the remporary buffer */
  return rc;
}
예제 #29
0
static cdk_error_t
write_secret_key (cdk_stream_t out, cdk_pkt_seckey_t sk,
		  int is_subkey, int old_ctb)
{
  cdk_pkt_pubkey_t pk = NULL;
  size_t size = 6, npkey, nskey;
  int pkttype, s2k_mode;
  cdk_error_t rc;

  assert (out);
  assert (sk);

  if (!sk->pk)
    return CDK_Inv_Value;
  pk = sk->pk;
  if (pk->version < 2 || pk->version > 4)
    return CDK_Inv_Packet;

  if (DEBUG_PKT)
    _cdk_log_debug ("write_secret_key:\n");

  npkey = cdk_pk_get_npkey (pk->pubkey_algo);
  nskey = cdk_pk_get_nskey (pk->pubkey_algo);
  if (!npkey || !nskey)
    {
      gnutls_assert ();
      return CDK_Inv_Algo;
    }
  if (pk->version < 4)
    size += 2;
  /* If the key is unprotected, the 1 extra byte:
     1 octet  - cipher algorithm byte (0x00)
     the other bytes depend on the mode:
     a) simple checksum -  2 octets
     b) sha-1 checksum  - 20 octets */
  size = !sk->is_protected ? size + 1 : size + 1 + calc_s2ksize (sk);
  size += calc_mpisize (pk->mpi, npkey);
  if (sk->version == 3 || !sk->is_protected)
    {
      if (sk->version == 3)
	{
	  size += 2;		/* force simple checksum */
	  sk->protect.sha1chk = 0;
	}
      else
	size += sk->protect.sha1chk ? 20 : 2;
      size += calc_mpisize (sk->mpi, nskey);
    }
  else				/* We do not know anything about the encrypted mpi's so we
				   treat the data as opaque. */
    size += sk->enclen;

  pkttype = is_subkey ? CDK_PKT_SECRET_SUBKEY : CDK_PKT_SECRET_KEY;
  rc = pkt_write_head (out, old_ctb, size, pkttype);
  if (!rc)
    rc = stream_putc (out, pk->version);
  if (!rc)
    rc = write_32 (out, pk->timestamp);
  if (!rc && pk->version < 4)
    {
      u16 ndays = 0;
      if (pk->expiredate)
	ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L);
      rc = write_16 (out, ndays);
    }
  if (!rc)
    rc = stream_putc (out, _cdk_pub_algo_to_pgp (pk->pubkey_algo));

  if (!rc)
    rc = write_mpibuf (out, pk->mpi, npkey);

  if (!rc) 
    {
      if (sk->is_protected == 0)
        rc = stream_putc (out, 0x00);
      else
        {
          if (is_RSA (pk->pubkey_algo) && pk->version < 4)
   	    rc = stream_putc (out, _gnutls_cipher_to_pgp (sk->protect.algo));
          else if (sk->protect.s2k)
            {
              s2k_mode = sk->protect.s2k->mode;
              rc = stream_putc (out, sk->protect.sha1chk ? 0xFE : 0xFF);
              if (!rc)
                rc = stream_putc (out, _gnutls_cipher_to_pgp (sk->protect.algo));
              if (!rc)
                rc = stream_putc (out, sk->protect.s2k->mode);
              if (!rc)
                rc = stream_putc (out, sk->protect.s2k->hash_algo);
              if (!rc && (s2k_mode == 1 || s2k_mode == 3))
                {
                  rc = stream_write (out, sk->protect.s2k->salt, 8);
                  if (!rc && s2k_mode == 3)
                    rc = stream_putc (out, sk->protect.s2k->count);
                }
            }
          else
            return CDK_Inv_Value;
          if (!rc)
          rc = stream_write (out, sk->protect.iv, sk->protect.ivlen);
        }
    }
  if (!rc && sk->is_protected && pk->version == 4)
    {
      if (sk->encdata && sk->enclen)
	rc = stream_write (out, sk->encdata, sk->enclen);
    }
  else
    {
      if (!rc)
	rc = write_mpibuf (out, sk->mpi, nskey);
      if (!rc)
	{
	  if (!sk->csum)
	    sk->csum = _cdk_sk_get_csum (sk);
	  rc = write_16 (out, sk->csum);
	}
    }

  return rc;
}
/****************
 * Encrypt the file with the given userids (or ask if none
 * is supplied).
 */
int
encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
{
    IOBUF inp = NULL, out = NULL;
    PACKET pkt;
    PKT_plaintext *pt = NULL;
    DEK *symkey_dek = NULL;
    STRING2KEY *symkey_s2k = NULL;
    int rc = 0, rc2 = 0;
    u32 filesize;
    cipher_filter_context_t cfx;
    armor_filter_context_t afx;
    compress_filter_context_t zfx;
    text_filter_context_t tfx;
    progress_filter_context_t pfx;
    PK_LIST pk_list,work_list;
    int do_compress = opt.compress_algo && !RFC1991;

    memset( &cfx, 0, sizeof cfx);
    memset( &afx, 0, sizeof afx);
    memset( &zfx, 0, sizeof zfx);
    memset( &tfx, 0, sizeof tfx);
    init_packet(&pkt);

    if(use_symkey
       && (rc=setup_symkey(&symkey_s2k,&symkey_dek)))
      return rc;

    if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
	return rc;

    if(PGP2) {
      for(work_list=pk_list; work_list; work_list=work_list->next)
	if(!(is_RSA(work_list->pk->pubkey_algo) &&
	     nbits_from_pk(work_list->pk)<=2048))
	  {
	    log_info(_("you can only encrypt to RSA keys of 2048 bits or "
		       "less in --pgp2 mode\n"));
	    compliance_failure();
	    break;
	  }
    }

    /* prepare iobufs */
    inp = iobuf_open(filename);
    if (inp)
      iobuf_ioctl (inp,3,1,NULL); /* disable fd caching */
    if (inp && is_secured_file (iobuf_get_fd (inp)))
      {
        iobuf_close (inp);
        inp = NULL;
        errno = EPERM;
      }
    if( !inp ) {
	log_error(_("can't open `%s': %s\n"), filename? filename: "[stdin]",
					strerror(errno) );
	rc = G10ERR_OPEN_FILE;
	goto leave;
    }
    else if( opt.verbose )
	log_info(_("reading from `%s'\n"), filename? filename: "[stdin]");

    handle_progress (&pfx, inp, filename);

    if( opt.textmode )
	iobuf_push_filter( inp, text_filter, &tfx );

    if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
	goto leave;

    if( opt.armor )
	iobuf_push_filter( out, armor_filter, &afx );

    /* create a session key */
    cfx.dek = xmalloc_secure_clear (sizeof *cfx.dek);
    if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
	cfx.dek->algo = select_algo_from_prefs(pk_list,PREFTYPE_SYM,-1,NULL);
	/* The only way select_algo_from_prefs can fail here is when
           mixing v3 and v4 keys, as v4 keys have an implicit
           preference entry for 3DES, and the pk_list cannot be empty.
           In this case, use 3DES anyway as it's the safest choice -
           perhaps the v3 key is being used in an OpenPGP
           implementation and we know that the implementation behind
           any v4 key can handle 3DES. */
	if( cfx.dek->algo == -1 ) {
	    cfx.dek->algo = CIPHER_ALGO_3DES;

	    if( PGP2 ) {
	      log_info(_("unable to use the IDEA cipher for all of the keys "
			 "you are encrypting to.\n"));
	      compliance_failure();
	    }
	}
    }
    else {
      if(!opt.expert &&
	 select_algo_from_prefs(pk_list,PREFTYPE_SYM,
				opt.def_cipher_algo,NULL)!=opt.def_cipher_algo)
	log_info(_("WARNING: forcing symmetric cipher %s (%d)"
		   " violates recipient preferences\n"),
		 cipher_algo_to_string(opt.def_cipher_algo),
		 opt.def_cipher_algo);

      cfx.dek->algo = opt.def_cipher_algo;
    }

    cfx.dek->use_mdc=use_mdc(pk_list,cfx.dek->algo);

    /* Only do the is-file-already-compressed check if we are using a
       MDC.  This forces compressed files to be re-compressed if we do
       not have a MDC to give some protection against chosen
       ciphertext attacks. */

    if (do_compress && cfx.dek->use_mdc && is_file_compressed(filename, &rc2) )
      {
        if (opt.verbose)
          log_info(_("`%s' already compressed\n"), filename);
        do_compress = 0;        
      }
    if (rc2)
      {
        rc = rc2;
        goto leave;
      }

    make_session_key( cfx.dek );
    if( DBG_CIPHER )
	log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );

    rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out );
    if( rc  )
	goto leave;

    /* We put the passphrase (if any) after any public keys as this
       seems to be the most useful on the recipient side - there is no
       point in prompting a user for a passphrase if they have the
       secret key needed to decrypt. */
    if(use_symkey && (rc=write_symkey_enc(symkey_s2k,symkey_dek,cfx.dek,out)))
      goto leave;

    if (!opt.no_literal) {
	/* setup the inner packet */
	if( filename || opt.set_filename ) {
	    char *s = make_basename( opt.set_filename ? opt.set_filename
						      : filename,
				     iobuf_get_real_fname( inp ) );
	    pt = xmalloc( sizeof *pt + strlen(s) - 1 );
	    pt->namelen = strlen(s);
	    memcpy(pt->name, s, pt->namelen );
	    xfree(s);
	}
	else { /* no filename */
	    pt = xmalloc( sizeof *pt - 1 );
	    pt->namelen = 0;
	}
    }

    if (!iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
      {
        off_t tmpsize;
        int overflow;

	if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
             && !overflow )
          log_info(_("WARNING: `%s' is an empty file\n"), filename );
        /* We can't encode the length of very large files because
           OpenPGP uses only 32 bit for file sizes.  So if the the
           size of a file is larger than 2^32 minus some bytes for
           packet headers, we switch to partial length encoding. */
        if (tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
          filesize = tmpsize;
        else
          filesize = 0;
      }
    else
      filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */

    if (!opt.no_literal) {
	pt->timestamp = make_timestamp();
	pt->mode = opt.textmode ? 't' : 'b';
	pt->len = filesize;
	pt->new_ctb = !pt->len && !RFC1991;
	pt->buf = inp;
	pkt.pkttype = PKT_PLAINTEXT;
	pkt.pkt.plaintext = pt;
	cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0;
    }
    else
	cfx.datalen = filesize && !do_compress ? filesize : 0;

    /* register the cipher filter */
    iobuf_push_filter( out, cipher_filter, &cfx );

    /* register the compress filter */
    if( do_compress ) {
	int compr_algo = opt.compress_algo;

	if(compr_algo==-1)
	  {
	    if((compr_algo=
		select_algo_from_prefs(pk_list,PREFTYPE_ZIP,-1,NULL))==-1)
	      compr_algo=DEFAULT_COMPRESS_ALGO;
	    /* Theoretically impossible to get here since uncompressed
	       is implicit. */
	  }
	else if(!opt.expert &&
		select_algo_from_prefs(pk_list,PREFTYPE_ZIP,
				       compr_algo,NULL)!=compr_algo)
	  log_info(_("WARNING: forcing compression algorithm %s (%d)"
		     " violates recipient preferences\n"),
		   compress_algo_to_string(compr_algo),compr_algo);

	/* algo 0 means no compression */
	if( compr_algo )
	  {
            if (cfx.dek && cfx.dek->use_mdc)
              zfx.new_ctb = 1;
	    push_compress_filter(out,&zfx,compr_algo);
	  }
    }

    /* do the work */
    if (!opt.no_literal) {
	if( (rc = build_packet( out, &pkt )) )
	    log_error("build_packet failed: %s\n", g10_errstr(rc) );
    }
    else {
	/* user requested not to create a literal packet, so we copy
           the plain data */
	byte copy_buffer[4096];
	int  bytes_copied;
	while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
	    if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
		rc = G10ERR_WRITE_FILE;
		log_error("copying input to output failed: %s\n",
                          g10_errstr(rc) );
		break;
	    }
	wipememory(copy_buffer, 4096); /* burn buffer */
    }

    /* finish the stuff */
  leave:
    iobuf_close(inp);
    if( rc )
	iobuf_cancel(out);
    else {
	iobuf_close(out); /* fixme: check returncode */
        write_status( STATUS_END_ENCRYPTION );
    }
    if( pt )
	pt->buf = NULL;
    free_packet(&pkt);
    xfree(cfx.dek);
    xfree(symkey_dek);
    xfree(symkey_s2k);
    release_pk_list( pk_list );
    return rc;
}