Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
/**
  * gnutls_openpgp_key_get_key_usage - This function returns the key's usage
  * @key: should contain a gnutls_openpgp_key_t structure
  * @key_usage: where the key usage bits will be stored
  *
  * This function will return certificate's key usage, by checking the
  * key algorithm. The key usage value will ORed values of the:
  * GNUTLS_KEY_DIGITAL_SIGNATURE, GNUTLS_KEY_KEY_ENCIPHERMENT.
  *
  * A negative value may be returned in case of parsing error.
  *
  **/
int
gnutls_openpgp_key_get_key_usage (gnutls_openpgp_key_t key,
				  unsigned int *key_usage)
{
  cdk_packet_t pkt;
  int algo = 0;

  if (!key)
    return GNUTLS_E_INVALID_REQUEST;

  *key_usage = 0;

  pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
  if (pkt && pkt->pkttype == CDK_PKT_PUBLIC_KEY)
    {
      algo = pkt->pkt.public_key->pubkey_algo;

      if (is_DSA (algo) || algo == GCRY_PK_RSA_S)
	*key_usage |= KEY_DIGITAL_SIGNATURE;
      else if (algo == GCRY_PK_RSA_E)
	*key_usage |= KEY_KEY_ENCIPHERMENT;
      else if (algo == GCRY_PK_RSA)
	*key_usage |= KEY_DIGITAL_SIGNATURE | KEY_KEY_ENCIPHERMENT;
    }

  return 0;
}
Exemplo n.º 3
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;
}
Exemplo n.º 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;
}
Exemplo n.º 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;
}
Exemplo n.º 6
0
/**
  * 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;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
/**
 * 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;
}
Exemplo n.º 9
0
/**
 * 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;
}
Exemplo n.º 10
0
/**
 * 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;
	}
}
Exemplo n.º 11
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;
}
Exemplo n.º 12
0
/**
 * 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;
}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
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;
}
Exemplo n.º 15
0
/* Encode the given digest into a pkcs#1 compatible format. */
cdk_error_t
_cdk_digest_encode_pkcs1 (byte ** r_md, size_t * r_mdlen, int pk_algo,
                          const byte * md, int digest_algo, unsigned nbits)
{
  size_t dlen;

  if (!md || !r_md || !r_mdlen)
    return CDK_Inv_Value;

  dlen = _gnutls_hash_get_algo_len (digest_algo);
  if (dlen <= 0)
    return CDK_Inv_Algo;
  if (is_DSA (pk_algo))
    {                           /* DSS does not use a special encoding. */
      *r_md = cdk_malloc (dlen + 1);
      if (!*r_md)
        return CDK_Out_Of_Core;
      *r_mdlen = dlen;
      memcpy (*r_md, md, dlen);
      return 0;
    }
  else
    {
      const byte *asn;
      int asnlen;
      cdk_error_t rc;

      asnlen = _gnutls_get_digest_oid (digest_algo, &asn);
      if (asnlen < 0)
        return asnlen;

      rc = do_encode_md (r_md, r_mdlen, md, digest_algo, dlen,
                         nbits, asn, asnlen);
      return rc;
    }
  return 0;
}
Exemplo n.º 16
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;
}
Exemplo n.º 17
0
static int
xml_add_key (gnutls_string * xmlkey, int ext, cdk_pkt_pubkey_t pk, int sub)
{
  const char *algo, *s;
  char keyid[16], fpr[41], tmp[32];
  uint8_t fingerpr[20];
  unsigned int kid[2];
  int i = 0, rc = 0;

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

  s = sub ? "  <SUBKEY>\n" : "  <MAINKEY>\n";
  _gnutls_string_append_str (xmlkey, s);

  cdk_pk_get_keyid (pk, kid);
  snprintf (keyid, 16, "%08lX%08lX", kid[0], kid[1]);
  rc = xml_add_tag (xmlkey, "KEYID", keyid);
  if (rc)
    return rc;

  cdk_pk_get_fingerprint (pk, fingerpr);
  for (i = 0; i < 20; i++)
    sprintf (fpr + 2 * i, "%02X", fingerpr[i]);
  fpr[40] = '\0';
  rc = xml_add_tag (xmlkey, "FINGERPRINT", fpr);
  if (rc)
    return rc;

  if (is_DSA (pk->pubkey_algo))
    algo = "DSA";
  else if (is_RSA (pk->pubkey_algo))
    algo = "RSA";
  else if (is_ELG (pk->pubkey_algo))
    algo = "ELG";
  else
    algo = "???";
  rc = xml_add_tag (xmlkey, "PKALGO", algo);
  if (rc)
    return rc;

  sprintf (tmp, "%d", cdk_pk_get_nbits (pk));
  rc = xml_add_tag (xmlkey, "KEYLEN", tmp);
  if (rc)
    return rc;

  sprintf (tmp, "%lu", pk->timestamp);
  rc = xml_add_tag (xmlkey, "CREATED", tmp);
  if (rc)
    return rc;

  if (pk->expiredate > 0)
    {
      sprintf (tmp, "%lu", (unsigned long) pk->expiredate);
      rc = xml_add_tag (xmlkey, "EXPIREDATE", tmp);
      if (rc)
	return rc;
    }

  sprintf (tmp, "%d", pk->is_revoked);
  rc = xml_add_tag (xmlkey, "REVOKED", tmp);
  if (rc)
    return rc;

  if (ext)
    {
      rc = xml_add_key_mpi (xmlkey, pk);
      if (rc)
	return rc;
    }

  s = sub ? "  </SUBKEY>\n" : "  </MAINKEY>\n";
  _gnutls_string_append_str (xmlkey, s);

  return 0;
}
Exemplo n.º 18
0
/**
 * cdk_pk_verify:
 * @pk: the public key
 * @sig: signature
 * @md: the message digest
 *
 * Verify the signature in @sig and compare it with the message digest in @md.
 **/
cdk_error_t
cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md)
{
    gnutls_datum_t s_sig;
    byte *encmd = NULL;
    size_t enclen;
    cdk_error_t rc;
    int ret, algo;
    unsigned int i;
    gnutls_datum_t data;
    gnutls_pk_params_st params;

    if (!pk || !sig || !md)
    {
        gnutls_assert ();
        return CDK_Inv_Value;
    }

    if (is_DSA (pk->pubkey_algo))
        algo = GNUTLS_PK_DSA;
    else if (is_RSA (pk->pubkey_algo))
        algo = GNUTLS_PK_RSA;
    else
    {
        gnutls_assert ();
        return CDK_Inv_Value;
    }

    rc = sig_to_datum (&s_sig, sig);
    if (rc)
    {
        gnutls_assert ();
        goto leave;
    }

    rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, pk->pubkey_algo, md,
                                   sig->digest_algo, cdk_pk_get_nbits (pk));
    if (rc)
    {
        gnutls_assert ();
        goto leave;
    }

    data.data = encmd;
    data.size = enclen;

    params.params_nr = cdk_pk_get_npkey (pk->pubkey_algo);
    for (i = 0; i < params.params_nr; i++)
        params.params[i] = pk->mpi[i];
    params.flags = 0;
    ret = _gnutls_pk_verify (algo, &data, &s_sig, &params);

    if (ret < 0)
    {
        gnutls_assert ();
        rc = map_gnutls_error (ret);
        goto leave;
    }

    rc = 0;

leave:
    _gnutls_free_datum (&s_sig);
    cdk_free (encmd);
    return rc;
}
Exemplo n.º 19
0
/**
 * cdk_pk_verify:
 * @pk: the public key
 * @sig: signature
 * @md: the message digest
 *
 * Verify the signature in @sig and compare it with the message digest in @md.
 **/
cdk_error_t
cdk_pk_verify(cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md)
{
	gnutls_datum_t s_sig = { NULL, 0 }, di = {
	NULL, 0};
	byte *encmd = NULL;
	cdk_error_t rc;
	int ret, algo;
	unsigned int i;
	gnutls_pk_params_st params;
	const mac_entry_st *me;

	if (!pk || !sig || !md) {
		gnutls_assert();
		return CDK_Inv_Value;
	}

	if (is_DSA(pk->pubkey_algo))
		algo = GNUTLS_PK_DSA;
	else if (is_RSA(pk->pubkey_algo))
		algo = GNUTLS_PK_RSA;
	else {
		gnutls_assert();
		return CDK_Inv_Value;
	}

	rc = sig_to_datum(&s_sig, sig);
	if (rc) {
		gnutls_assert();
		goto leave;
	}

	me = mac_to_entry(sig->digest_algo);
	rc = _gnutls_set_datum(&di, md, _gnutls_hash_get_algo_len(me));
	if (rc < 0) {
		rc = gnutls_assert_val(CDK_Out_Of_Core);
		goto leave;
	}

	rc = pk_prepare_hash(algo, me, &di);
	if (rc < 0) {
		rc = gnutls_assert_val(CDK_General_Error);
		goto leave;
	}

	params.params_nr = cdk_pk_get_npkey(pk->pubkey_algo);
	for (i = 0; i < params.params_nr; i++)
		params.params[i] = pk->mpi[i];
	params.flags = 0;
	ret = _gnutls_pk_verify(algo, &di, &s_sig, &params);

	if (ret < 0) {
		gnutls_assert();
		rc = map_gnutls_error(ret);
		goto leave;
	}

	rc = 0;

      leave:
	_gnutls_free_datum(&s_sig);
	_gnutls_free_datum(&di);
	cdk_free(encmd);
	return rc;
}