Exemple #1
0
static int
ssl3_md5(int i, uint8_t * secret, int secret_len,
	 uint8_t * rnd, int rnd_len, void *digest)
{
	uint8_t tmp[MAX_HASH_SIZE];
	digest_hd_st td;
	int ret;

	ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_hash(&td, secret, secret_len);

	ret = ssl3_sha(i, secret, secret_len, rnd, rnd_len, tmp);
	if (ret < 0) {
		gnutls_assert();
		_gnutls_hash_deinit(&td, digest);
		return ret;
	}

	_gnutls_hash(&td, tmp, SHA1_DIGEST_OUTPUT);

	_gnutls_hash_deinit(&td, digest);
	return 0;
}
Exemple #2
0
/* generate x = SHA(s | SHA(U | ":" | p))
 * The output is exactly 20 bytes
 */
int
_gnutls_calc_srp_sha (const char *username, const char *password,
		      opaque * salt, int salt_size, size_t * size,
		      void *digest)
{
  GNUTLS_HASH_HANDLE td;
  opaque res[MAX_HASH_SIZE];

  *size = 20;

  td = _gnutls_hash_init (GNUTLS_MAC_SHA1);
  if (td == NULL)
    {
      return GNUTLS_E_MEMORY_ERROR;
    }
  _gnutls_hash (td, username, strlen (username));
  _gnutls_hash (td, ":", 1);
  _gnutls_hash (td, password, strlen (password));

  _gnutls_hash_deinit (td, res);

  td = _gnutls_hash_init (GNUTLS_MAC_SHA1);
  if (td == NULL)
    {
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_hash (td, salt, salt_size);
  _gnutls_hash (td, res, 20);	/* 20 bytes is the output of sha1 */

  _gnutls_hash_deinit (td, digest);

  return 0;
}
Exemple #3
0
/* generate x = SHA(s | SHA(U | ":" | p))
 * The output is exactly 20 bytes
 */
static int
_gnutls_calc_srp_sha(const char *username, const char *password,
		     uint8_t * salt, int salt_size, size_t * size,
		     void *digest)
{
	digest_hd_st td;
	uint8_t res[MAX_HASH_SIZE];
	int ret;
	const mac_entry_st *me = mac_to_entry(GNUTLS_MAC_SHA1);

	*size = 20;

	ret = _gnutls_hash_init(&td, me);
	if (ret < 0) {
		return GNUTLS_E_MEMORY_ERROR;
	}
	_gnutls_hash(&td, username, strlen(username));
	_gnutls_hash(&td, ":", 1);
	_gnutls_hash(&td, password, strlen(password));

	_gnutls_hash_deinit(&td, res);

	ret = _gnutls_hash_init(&td, me);
	if (ret < 0) {
		return GNUTLS_E_MEMORY_ERROR;
	}

	_gnutls_hash(&td, salt, salt_size);
	_gnutls_hash(&td, res, 20);	/* 20 bytes is the output of sha1 */

	_gnutls_hash_deinit(&td, digest);

	return 0;
}
static int
openssl_hash_password(const char *pass, gnutls_datum_t * key,
		      gnutls_datum_t * salt)
{
	unsigned char md5[16];
	digest_hd_st hd;
	unsigned int count = 0;
	int err;

	while (count < key->size) {
		err = _gnutls_hash_init(&hd, mac_to_entry(GNUTLS_MAC_MD5));
		if (err) {
			gnutls_assert();
			return err;
		}
		if (count) {
			err = _gnutls_hash(&hd, md5, sizeof(md5));
			if (err) {
			      hash_err:
				_gnutls_hash_deinit(&hd, NULL);
				gnutls_assert();
				return err;
			}
		}
		if (pass) {
			err = _gnutls_hash(&hd, pass, strlen(pass));
			if (err) {
				gnutls_assert();
				goto hash_err;
			}
		}
		err = _gnutls_hash(&hd, salt->data, 8);
		if (err) {
			gnutls_assert();
			goto hash_err;
		}

		_gnutls_hash_deinit(&hd, md5);

		if (key->size - count <= sizeof(md5)) {
			memcpy(&key->data[count], md5, key->size - count);
			break;
		}

		memcpy(&key->data[count], md5, sizeof(md5));
		count += sizeof(md5);
	}

	return 0;
}
Exemple #5
0
int
_gnutls_mac_deinit_ssl3_handshake(digest_hd_st * handle,
				  void *digest, uint8_t * key,
				  uint32_t key_size)
{
	uint8_t ret[MAX_HASH_SIZE];
	digest_hd_st td;
	uint8_t opad[48];
	uint8_t ipad[48];
	int padsize;
	int block, rc;

	padsize = get_padsize(handle->e->id);
	if (padsize == 0) {
		gnutls_assert();
		rc = GNUTLS_E_INTERNAL_ERROR;
		goto cleanup;
	}

	memset(opad, 0x5C, padsize);
	memset(ipad, 0x36, padsize);

	rc = _gnutls_hash_init(&td, handle->e);
	if (rc < 0) {
		gnutls_assert();
		goto cleanup;
	}

	if (key_size > 0)
		_gnutls_hash(&td, key, key_size);

	_gnutls_hash(&td, opad, padsize);
	block = _gnutls_mac_get_algo_len(handle->e);

	if (key_size > 0)
		_gnutls_hash(handle, key, key_size);
	_gnutls_hash(handle, ipad, padsize);
	_gnutls_hash_deinit(handle, ret);	/* get the previous hash */

	_gnutls_hash(&td, ret, block);

	_gnutls_hash_deinit(&td, digest);

	return 0;

      cleanup:
	_gnutls_hash_deinit(handle, NULL);
	return rc;
}
Exemple #6
0
/* Hashes input data and verifies a DSA signature.
 */
static int
dsa_verify_sig (const gnutls_datum_t * text,
		const gnutls_datum_t * hash,
		const gnutls_datum_t * signature, bigint_t * params,
		int params_len)
{
  int ret;
  opaque _digest[MAX_HASH_SIZE];
  gnutls_datum_t digest;
  digest_hd_st hd;

  if (hash && hash->data && hash->size == 20)
    {
      digest = *hash;
    }
  else
    {
      ret = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

      _gnutls_hash (&hd, text->data, text->size);
      _gnutls_hash_deinit (&hd, _digest);

      digest.data = _digest;
      digest.size = 20;
    }

  ret = _gnutls_dsa_verify (&digest, signature, params, params_len);

  return ret;
}
Exemple #7
0
static int
dsa_sign (const gnutls_datum_t * text,
	  bigint_t * params, int params_len, gnutls_datum_t * signature)
{
  int ret;
  opaque _digest[MAX_HASH_SIZE];
  digest_hd_st hd;
  gnutls_datum_t digest;
  gnutls_digest_algorithm_t hash = _gnutls_dsa_q_to_hash (params[1]);

  ret = _gnutls_hash_init (&hd, hash);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  _gnutls_hash (&hd, text->data, text->size);
  _gnutls_hash_deinit (&hd, _digest);

  digest.data = _digest;
  digest.size = _gnutls_hash_get_algo_len (hash);

  if ((ret =
       _gnutls_sign (GNUTLS_PK_DSA, params, params_len, &digest,
		     signature)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return 0;
}
Exemple #8
0
static int
ssl3_sha(int i, uint8_t * secret, int secret_len,
	 uint8_t * rnd, int rnd_len, void *digest)
{
	int j, ret;
	uint8_t text1[26];

	digest_hd_st td;

	for (j = 0; j < i + 1; j++) {
		text1[j] = 65 + i;	/* A==65 */
	}

	ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_SHA1));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_hash(&td, text1, i + 1);
	_gnutls_hash(&td, secret, secret_len);
	_gnutls_hash(&td, rnd, rnd_len);

	_gnutls_hash_deinit(&td, digest);
	return 0;
}
Exemple #9
0
int
_gnutls_ssl3_hash_md5(const void *first, int first_len,
		      const void *second, int second_len,
		      int ret_len, uint8_t * ret)
{
	uint8_t digest[MAX_HASH_SIZE];
	digest_hd_st td;
	int block = MD5_DIGEST_OUTPUT;
	int rc;

	rc = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5));
	if (rc < 0) {
		gnutls_assert();
		return rc;
	}

	_gnutls_hash(&td, first, first_len);
	_gnutls_hash(&td, second, second_len);

	_gnutls_hash_deinit(&td, digest);

	if (ret_len > block) {
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	memcpy(ret, digest, ret_len);

	return 0;

}
Exemple #10
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;
}
Exemple #11
0
static int
dsa_sign (const gnutls_datum_t * text,
	  mpi_t * params, int params_len, gnutls_datum_t * signature)
{
  int ret;
  opaque _digest[MAX_HASH_SIZE];
  GNUTLS_HASH_HANDLE hd;
  gnutls_datum_t digest;

  hd = _gnutls_hash_init (GNUTLS_MAC_SHA1);
  if (hd == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_HASH_FAILED;
    }

  _gnutls_hash (hd, text->data, text->size);
  _gnutls_hash_deinit (hd, _digest);

  digest.data = _digest;
  digest.size = 20;

  if ((ret =
       _gnutls_sign (GNUTLS_PK_DSA, params, params_len, &digest,
		     signature)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return 0;
}
Exemple #12
0
/* this is _gnutls_handshake_verify_cert_vrfy for TLS 1.2
 */
static int
_gnutls_handshake_verify_cert_vrfy12 (gnutls_session_t session,
                                      gnutls_pcert_st*  cert,
                                      gnutls_datum_t * signature,
                                      gnutls_sign_algorithm_t sign_algo)
{
  int ret;
  opaque concat[MAX_SIG_SIZE];
  digest_hd_st td;
  gnutls_datum_t dconcat;
  gnutls_sign_algorithm_t _sign_algo;
  gnutls_digest_algorithm_t hash_algo;
  digest_hd_st *handshake_td;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
  gnutls_pk_algorithm_t pk = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);

  handshake_td = &session->internals.handshake_mac_handle.tls12.sha1;
  hash_algo = handshake_td->algorithm;
  _sign_algo =
    _gnutls_x509_pk_to_sign (pk, hash_algo);

  if (_sign_algo != sign_algo)
    {
      handshake_td = &session->internals.handshake_mac_handle.tls12.sha256;
      hash_algo = handshake_td->algorithm;
      _sign_algo =
        _gnutls_x509_pk_to_sign (pk, hash_algo);
      if (sign_algo != _sign_algo)
        {
          gnutls_assert ();
          return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
        }
    }

  ret = _gnutls_hash_copy (&td, handshake_td);
  if (ret < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_HASH_FAILED;
    }

  _gnutls_hash_deinit (&td, concat);

  dconcat.data = concat;
  dconcat.size = _gnutls_hash_get_algo_len (hash_algo);

  ret =
    verify_tls_hash (ver, cert, &dconcat, signature, 0, pk);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return ret;

}
Exemple #13
0
int _gnutls_mac_deinit_ssl3(digest_hd_st * handle, void *digest)
{
	int ret = 0;

	if (digest != NULL)
		ret = _gnutls_mac_output_ssl3(handle, digest);
	_gnutls_hash_deinit(handle, NULL);

	return ret;
}
Exemple #14
0
/* the same as _gnutls_handshake_sign_cert_vrfy except that it is made for TLS 1.2
 */
static int
_gnutls_handshake_sign_cert_vrfy12 (gnutls_session_t session,
                                    gnutls_pcert_st* cert, gnutls_privkey_t pkey,
                                    gnutls_datum_t * signature)
{
  gnutls_datum_t dconcat;
  int ret;
  opaque concat[MAX_SIG_SIZE];
  digest_hd_st td;
  gnutls_sign_algorithm_t sign_algo;
  gnutls_digest_algorithm_t hash_algo;
  digest_hd_st *handshake_td;

  sign_algo =
    _gnutls_session_get_sign_algo (session, cert);
  if (sign_algo == GNUTLS_SIGN_UNKNOWN)
    {
      gnutls_assert ();
      return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
    }

  hash_algo = _gnutls_sign_get_hash_algorithm (sign_algo);

  _gnutls_debug_log ("sign handshake cert vrfy: picked %s with %s\n",
                    gnutls_sign_algorithm_get_name (sign_algo),
                    gnutls_mac_get_name (hash_algo));

  if ((gnutls_mac_algorithm_t)hash_algo == session->internals.handshake_mac_handle.tls12.sha1.algorithm)
    handshake_td = &session->internals.handshake_mac_handle.tls12.sha1;
  else if ((gnutls_mac_algorithm_t)hash_algo == session->internals.handshake_mac_handle.tls12.sha256.algorithm)
    handshake_td = &session->internals.handshake_mac_handle.tls12.sha256;
  else
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); /* too bad we only support SHA1 and SHA256 */

  ret = _gnutls_hash_copy (&td, handshake_td);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  _gnutls_hash_deinit (&td, concat);

  dconcat.data = concat;
  dconcat.size = _gnutls_hash_get_algo_len (hash_algo);

  ret = sign_tls_hash (session, hash_algo, cert, pkey, &dconcat, signature);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return sign_algo;
}
Exemple #15
0
/* This calculates the SHA1(A | B)
 * A and B will be left-padded with zeros to fill n_size.
 */
mpi_t
_gnutls_calc_srp_u (mpi_t A, mpi_t B, mpi_t n)
{
  size_t b_size, a_size;
  opaque *holder, hd[MAX_HASH_SIZE];
  size_t holder_size, hash_size, n_size;
  GNUTLS_HASH_HANDLE td;
  int ret;
  mpi_t res;

  /* get the size of n in bytes */
  _gnutls_mpi_print (NULL, &n_size, n);

  _gnutls_mpi_print (NULL, &a_size, A);
  _gnutls_mpi_print (NULL, &b_size, B);

  if (a_size > n_size || b_size > n_size)
    {
      gnutls_assert ();
      return NULL;		/* internal error */
    }

  holder_size = n_size + n_size;

  holder = gnutls_calloc (1, holder_size);
  if (holder == NULL)
    return NULL;

  _gnutls_mpi_print (&holder[n_size - a_size], &a_size, A);
  _gnutls_mpi_print (&holder[n_size + n_size - b_size], &b_size, B);

  td = _gnutls_hash_init (GNUTLS_MAC_SHA1);
  if (td == NULL)
    {
      gnutls_free (holder);
      gnutls_assert ();
      return NULL;
    }
  _gnutls_hash (td, holder, holder_size);
  _gnutls_hash_deinit (td, hd);

  /* convert the bytes of hd to integer
   */
  hash_size = 20;		/* SHA */
  ret = _gnutls_mpi_scan_nz (&res, hd, &hash_size);
  gnutls_free (holder);

  if (ret < 0)
    {
      gnutls_assert ();
      return NULL;
    }

  return res;
}
Exemple #16
0
/* Hashes input data and verifies a DSA signature.
 */
static int
dsa_verify_sig (const gnutls_datum_t * text,
                const gnutls_datum_t * hash,
                const gnutls_datum_t * signature, bigint_t * params,
                int params_len)
{
  int ret;
  opaque _digest[MAX_HASH_SIZE];
  gnutls_datum_t digest;
  digest_hd_st hd;
  gnutls_digest_algorithm_t algo;
  unsigned int hash_len;

  algo = _gnutls_dsa_q_to_hash (params[1], &hash_len);
  if (hash)
    {
      /* SHA1 or better allowed */
      if (!hash->data || hash->size < hash_len)
        {
          gnutls_assert();
          _gnutls_debug_log("Hash size (%d) does not correspond to hash %s", (int)hash->size, gnutls_mac_get_name(algo));
          
          if (hash->size != 20)
            return GNUTLS_E_PK_SIG_VERIFY_FAILED;
        }
      digest = *hash;
    }
  else
    {

      ret = _gnutls_hash_init (&hd, algo);
      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }

      _gnutls_hash (&hd, text->data, text->size);
      _gnutls_hash_deinit (&hd, _digest);

      digest.data = _digest;
      digest.size = _gnutls_hash_get_algo_len(algo);
    }

  ret = _gnutls_dsa_verify (&digest, signature, params, params_len);

  return ret;
}
Exemple #17
0
/* if hash==MD5 then we do RSA-MD5
 * if hash==SHA then we do RSA-SHA
 * params[0] is modulus
 * params[1] is public key
 */
static int
pkcs1_rsa_sign (gnutls_digest_algorithm_t hash, const gnutls_datum_t * text,
		bigint_t * params, int params_len, gnutls_datum_t * signature)
{
  int ret;
  opaque _digest[MAX_HASH_SIZE];
  digest_hd_st hd;
  gnutls_datum_t digest, info;

  ret = _gnutls_hash_init (&hd, HASH2MAC (hash));
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  _gnutls_hash (&hd, text->data, text->size);
  _gnutls_hash_deinit (&hd, _digest);

  digest.data = _digest;
  digest.size = _gnutls_hash_get_algo_len (HASH2MAC (hash));

  /* Encode the digest as a DigestInfo
   */
  if ((ret = encode_ber_digest_info (hash, &digest, &info)) != 0)
    {
      gnutls_assert ();
      return ret;
    }

  if ((ret =
       _gnutls_sign (GNUTLS_PK_RSA, params, params_len, &info,
		     signature)) < 0)
    {
      gnutls_assert ();
      _gnutls_free_datum (&info);
      return ret;
    }

  _gnutls_free_datum (&info);

  return 0;
}
Exemple #18
0
cdk_error_t
_cdk_filter_hash (void *data, int ctl, FILE * in, FILE * out)
{
  if (ctl == STREAMCTL_READ)
    return hash_encode (data, in, out);
  else if (ctl == STREAMCTL_FREE)
    {
      md_filter_t *mfx = data;
      if (mfx)
        {
          _cdk_log_debug ("free hash filter\n");
          _gnutls_hash_deinit (&mfx->md, NULL);
          mfx->md_initialized = 0;
          return 0;
        }
    }

  gnutls_assert ();
  return CDK_Inv_Mode;
}
Exemple #19
0
int _gnutls_mac_output_ssl3(digest_hd_st * handle, void *digest)
{
	uint8_t ret[MAX_HASH_SIZE];
	digest_hd_st td;
	uint8_t opad[48];
	int padsize;
	int block, rc;

	padsize = get_padsize(handle->e->id);
	if (padsize == 0) {
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	memset(opad, 0x5C, padsize);

	rc = _gnutls_hash_init(&td, handle->e);
	if (rc < 0) {
		gnutls_assert();
		return rc;
	}

	if (handle->keysize > 0)
		_gnutls_hash(&td, handle->key, handle->keysize);

	_gnutls_hash(&td, opad, padsize);
	block = _gnutls_mac_get_algo_len(handle->e);
	_gnutls_hash_output(handle, ret);	/* get the previous hash */
	_gnutls_hash(&td, ret, block);

	_gnutls_hash_deinit(&td, digest);

	/* reset handle */
	memset(opad, 0x36, padsize);

	if (handle->keysize > 0)
		_gnutls_hash(handle, handle->key, handle->keysize);
	_gnutls_hash(handle, opad, padsize);

	return 0;
}
Exemple #20
0
/* Generates a signature of all the random data and the parameters.
 * Used in DHE_* ciphersuites.
 */
int
_gnutls_verify_sig_params (gnutls_session_t session, gnutls_cert * cert,
			   const gnutls_datum_t * params,
			   gnutls_datum_t * signature)
{
  gnutls_datum_t dconcat;
  int ret;
  digest_hd_st td_md5;
  digest_hd_st td_sha;
  opaque concat[36];
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

  if (ver < GNUTLS_TLS1_2)
    {
      ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

      _gnutls_hash (&td_md5, session->security_parameters.client_random,
		    GNUTLS_RANDOM_SIZE);
      _gnutls_hash (&td_md5, session->security_parameters.server_random,
		    GNUTLS_RANDOM_SIZE);
      _gnutls_hash (&td_md5, params->data, params->size);
    }

  ret = _gnutls_hash_init (&td_sha, GNUTLS_MAC_SHA1);
  if (ret < 0)
    {
      gnutls_assert ();
      if (ver < GNUTLS_TLS1_2)
	_gnutls_hash_deinit (&td_md5, NULL);
      return ret;
    }

  _gnutls_hash (&td_sha, session->security_parameters.client_random,
		GNUTLS_RANDOM_SIZE);
  _gnutls_hash (&td_sha, session->security_parameters.server_random,
		GNUTLS_RANDOM_SIZE);
  _gnutls_hash (&td_sha, params->data, params->size);

  if (ver < GNUTLS_TLS1_2)
    {
      _gnutls_hash_deinit (&td_md5, concat);
      _gnutls_hash_deinit (&td_sha, &concat[16]);
      dconcat.size = 36;
    }
  else
    {
#if 1
      /* Use NULL parameters. */
      memcpy (concat,
	      "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14",
	      15);
      _gnutls_hash_deinit (&td_sha, &concat[15]);
      dconcat.size = 35;
#else
      /* No parameters field. */
      memcpy (concat,
	      "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14", 13);
      _gnutls_hash_deinit (&td_sha, &concat[13]);
      dconcat.size = 33;
#endif
    }

  dconcat.data = concat;

  ret = _gnutls_verify_sig (cert, &dconcat, signature, dconcat.size - 20);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return ret;

}
Exemple #21
0
/* Generates a signature of all the previous sent packets in the 
 * handshake procedure. (20040227: now it works for SSL 3.0 as well)
 */
int
_gnutls_tls_sign_hdata (gnutls_session_t session,
			gnutls_cert * cert, gnutls_privkey * pkey,
			gnutls_datum_t * signature)
{
  gnutls_datum_t dconcat;
  int ret;
  opaque concat[36];
  digest_hd_st td_md5;
  digest_hd_st td_sha;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

  ret =
    _gnutls_hash_copy (&td_sha, &session->internals.handshake_mac_handle_sha);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  if (ver == GNUTLS_SSL3)
    {
      ret = _gnutls_generate_master (session, 1);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

      _gnutls_mac_deinit_ssl3_handshake (&td_sha, &concat[16],
					 session->security_parameters.
					 master_secret, GNUTLS_MASTER_SIZE);
    }
  else
    _gnutls_hash_deinit (&td_sha, &concat[16]);

  switch (cert->subject_pk_algorithm)
    {
    case GNUTLS_PK_RSA:
      ret =
	_gnutls_hash_copy (&td_md5,
			   &session->internals.handshake_mac_handle_md5);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

      if (ver == GNUTLS_SSL3)
	_gnutls_mac_deinit_ssl3_handshake (&td_md5, concat,
					   session->security_parameters.
					   master_secret, GNUTLS_MASTER_SIZE);
      else
	_gnutls_hash_deinit (&td_md5, concat);

      dconcat.data = concat;
      dconcat.size = 36;
      break;
    case GNUTLS_PK_DSA:
      dconcat.data = &concat[16];
      dconcat.size = 20;
      break;

    default:
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }
  ret = _gnutls_tls_sign (session, cert, pkey, &dconcat, signature);
  if (ret < 0)
    {
      gnutls_assert ();
    }

  return ret;
}
void
RIPEMD160_Final (unsigned char *md, RIPEMD160_CTX * ctx)
{
  _gnutls_hash_deinit (ctx->handle, md);
  gnutls_free (ctx->handle);
}
void
MD5_Final (unsigned char *md, MD5_CTX * ctx)
{
  _gnutls_hash_deinit (ctx->handle, md);
  gnutls_free (ctx->handle);
}
Exemple #24
0
/**
  * gnutls_x509_privkey_get_key_id - Return unique ID of the key's parameters
  * @key: Holds the key
  * @flags: should be 0 for now
  * @output_data: will contain the key ID
  * @output_data_size: holds the size of output_data (and will be
  *   replaced by the actual size of parameters)
  *
  * This function will return a unique ID the depends on the public key
  * parameters. This ID can be used in checking whether a certificate
  * corresponds to the given key.
  *
  * If the buffer provided is not long enough to hold the output, then
  * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
  * be returned.  The output will normally be a SHA-1 hash output,
  * which is 20 bytes.
  *
  * Return value: In case of failure a negative value will be
  *   returned, and 0 on success.
  *
  **/
int
gnutls_x509_privkey_get_key_id (gnutls_x509_privkey_t key,
				unsigned int flags,
				unsigned char *output_data,
				size_t * output_data_size)
{
  int result;
  GNUTLS_HASH_HANDLE hd;
  gnutls_datum_t der = { NULL, 0 };

  if (key == NULL || key->crippled)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (*output_data_size < 20)
    {
      gnutls_assert ();
      *output_data_size = 20;
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
    }

  if (key->pk_algorithm == GNUTLS_PK_RSA)
    {
      result =
	_gnutls_x509_write_rsa_params (key->params, key->params_size, &der);
      if (result < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
    }
  else if (key->pk_algorithm == GNUTLS_PK_DSA)
    {
      result =
	_gnutls_x509_write_dsa_public_key (key->params,
					   key->params_size, &der);
      if (result < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
    }
  else
    return GNUTLS_E_INTERNAL_ERROR;

  hd = _gnutls_hash_init (GNUTLS_MAC_SHA1);
  if (hd == GNUTLS_HASH_FAILED)
    {
      gnutls_assert ();
      result = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  _gnutls_hash (hd, der.data, der.size);

  _gnutls_hash_deinit (hd, output_data);
  *output_data_size = 20;

  result = 0;

cleanup:

  _gnutls_free_datum (&der);
  return result;
}
Exemple #25
0
/* ID should be:
 * 3 for MAC
 * 2 for IV
 * 1 for encryption key
 *
 * Note that this function produces different key for the
 * NULL password, and for the password with zero length.
 */
int
_gnutls_pkcs12_string_to_key(const mac_entry_st * me,
			     unsigned int id, const uint8_t * salt,
			     unsigned int salt_size, unsigned int iter,
			     const char *pw, unsigned int req_keylen,
			     uint8_t * keybuf)
{
	int rc;
	unsigned int i, j;
	digest_hd_st md;
	bigint_t num_b1 = NULL, num_ij = NULL;
	bigint_t mpi512 = NULL;
	unsigned int pwlen;
	uint8_t hash[MAX_HASH_SIZE], buf_b[64], buf_i[MAX_PASS_LEN * 2 + 64], *p;
	uint8_t d[64];
	size_t cur_keylen;
	size_t n, m, p_size, i_size;
	unsigned mac_len;
	const uint8_t buf_512[] =	/* 2^64 */
	{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00
	};

	cur_keylen = 0;

	if (pw == NULL)
		pwlen = 0;
	else
		pwlen = strlen(pw);

	if (pwlen > MAX_PASS_LEN) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	if ((rc = _pkcs12_check_pass(pw, pwlen)) < 0) {
		gnutls_assert();
		return rc;
	}

	rc = _gnutls_mpi_init_scan(&mpi512, buf_512, sizeof(buf_512));
	if (rc < 0) {
		gnutls_assert();
		return rc;
	}

	/* Store salt and password in BUF_I */
	p_size = ((pwlen / 64) * 64) + 64;

	if (p_size > sizeof(buf_i) - 64)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	p = buf_i;
	for (i = 0; i < 64; i++)
		*p++ = salt[i % salt_size];
	if (pw) {
		for (i = j = 0; i < p_size; i += 2) {
			*p++ = 0;
			*p++ = pw[j];
			if (++j > pwlen)	/* Note, that we include the trailing (0) */
				j = 0;
		}
	} else
		memset(p, 0, p_size);

	i_size = 64 + p_size;
	mac_len = _gnutls_mac_get_algo_len(me);

	for (;;) {
		rc = _gnutls_hash_init(&md, me);
		if (rc < 0) {
			gnutls_assert();
			goto cleanup;
		}
		memset(d, id & 0xff, 64);
		_gnutls_hash(&md, d, 64);
		_gnutls_hash(&md, buf_i, pw ? i_size : 64);
		_gnutls_hash_deinit(&md, hash);
		for (i = 1; i < iter; i++) {
			rc = _gnutls_hash_fast(me->id, hash, mac_len,
					       hash);
			if (rc < 0) {
				gnutls_assert();
				goto cleanup;
			}
		}
		for (i = 0; i < mac_len && cur_keylen < req_keylen; i++)
			keybuf[cur_keylen++] = hash[i];
		if (cur_keylen == req_keylen) {
			rc = 0;	/* ready */
			goto cleanup;
		}

		/* need more bytes. */
		for (i = 0; i < 64; i++)
			buf_b[i] = hash[i % mac_len];
		n = 64;
		rc = _gnutls_mpi_init_scan(&num_b1, buf_b, n);
		if (rc < 0) {
			gnutls_assert();
			goto cleanup;
		}

		rc = _gnutls_mpi_add_ui(num_b1, num_b1, 1);
		if (rc < 0) {
			gnutls_assert();
			goto cleanup;
		}
		
		for (i = 0; i < 128; i += 64) {
			n = 64;
			rc = _gnutls_mpi_init_scan(&num_ij, buf_i + i, n);
			if (rc < 0) {
				gnutls_assert();
				goto cleanup;
			}

			rc = _gnutls_mpi_addm(num_ij, num_ij, num_b1, mpi512);
			if (rc < 0) {
				gnutls_assert();
				goto cleanup;
			}

			n = 64;
#ifndef PKCS12_BROKEN_KEYGEN
			m = (_gnutls_mpi_get_nbits(num_ij) + 7) / 8;
#else
			m = n;
#endif
			memset(buf_i + i, 0, n - m);
			rc = _gnutls_mpi_print(num_ij, buf_i + i + n - m,
					       &n);
			if (rc < 0) {
				gnutls_assert();
				goto cleanup;
			}
			_gnutls_mpi_release(&num_ij);
		}
	}
      cleanup:
	_gnutls_mpi_release(&num_ij);
	_gnutls_mpi_release(&num_b1);
	_gnutls_mpi_release(&mpi512);

	return rc;
}
Exemple #26
0
/* Generates a signature of all the random data and the parameters.
 * Used in DHE_* ciphersuites.
 */
int
_gnutls_tls_sign_params (gnutls_session_t session, gnutls_cert * cert,
			 gnutls_privkey * pkey, gnutls_datum_t * params,
			 gnutls_datum_t * signature)
{
  gnutls_datum_t dconcat;
  int ret;
  digest_hd_st td_sha;
  opaque concat[36];
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

  ret = _gnutls_hash_init (&td_sha, GNUTLS_MAC_SHA1);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  _gnutls_hash (&td_sha, session->security_parameters.client_random,
		GNUTLS_RANDOM_SIZE);
  _gnutls_hash (&td_sha, session->security_parameters.server_random,
		GNUTLS_RANDOM_SIZE);
  _gnutls_hash (&td_sha, params->data, params->size);

  switch (cert->subject_pk_algorithm)
    {
    case GNUTLS_PK_RSA:
      if (ver < GNUTLS_TLS1_2)
	{
	  digest_hd_st td_md5;

	  ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
	  if (ret < 0)
	    {
	      gnutls_assert ();
	      return ret;
	    }

	  _gnutls_hash (&td_md5, session->security_parameters.client_random,
			GNUTLS_RANDOM_SIZE);
	  _gnutls_hash (&td_md5, session->security_parameters.server_random,
			GNUTLS_RANDOM_SIZE);
	  _gnutls_hash (&td_md5, params->data, params->size);

	  _gnutls_hash_deinit (&td_md5, concat);
	  _gnutls_hash_deinit (&td_sha, &concat[16]);

	  dconcat.size = 36;
	}
      else
	{
#if 1
	  /* Use NULL parameters. */
	  memcpy (concat,
		  "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14",
		  15);
	  _gnutls_hash_deinit (&td_sha, &concat[15]);
	  dconcat.size = 35;
#else
	  /* No parameters field. */
	  memcpy (concat,
		  "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14", 13);
	  _gnutls_hash_deinit (&td_sha, &concat[13]);
	  dconcat.size = 33;
#endif
	}
      dconcat.data = concat;
      break;
    case GNUTLS_PK_DSA:
      _gnutls_hash_deinit (&td_sha, concat);
      dconcat.data = concat;
      dconcat.size = 20;
      break;

    default:
      gnutls_assert ();
      _gnutls_hash_deinit (&td_sha, NULL);
      return GNUTLS_E_INTERNAL_ERROR;
    }
  ret = _gnutls_tls_sign (session, cert, pkey, &dconcat, signature);
  if (ret < 0)
    {
      gnutls_assert ();
    }

  return ret;

}
Exemple #27
0
/* if hash==MD5 then we do RSA-MD5
 * if hash==SHA then we do RSA-SHA
 * params[0] is modulus
 * params[1] is public key
 */
static int
_pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
                       const gnutls_datum_t * prehash,
                       const gnutls_datum_t * signature, bigint_t * params,
                       int params_len)
{
  gnutls_mac_algorithm_t hash = GNUTLS_MAC_UNKNOWN;
  int ret;
  opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE], *cmp;
  int digest_size;
  digest_hd_st hd;
  gnutls_datum_t decrypted;

  ret =
    _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, params, params_len, 1);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  /* decrypted is a BER encoded data of type DigestInfo
   */

  digest_size = sizeof (digest);
  if ((ret =
       decode_ber_digest_info (&decrypted, &hash, digest, &digest_size)) != 0)
    {
      gnutls_assert ();
      _gnutls_free_datum (&decrypted);
      return ret;
    }

  _gnutls_free_datum (&decrypted);

  if (digest_size != _gnutls_hash_get_algo_len (hash))
    {
      gnutls_assert ();
      return GNUTLS_E_ASN1_GENERIC_ERROR;
    }

  if (prehash && prehash->data && prehash->size == digest_size)
    {
      cmp = prehash->data;
    }
  else
    {
      if (!text)
        {
          gnutls_assert ();
          return GNUTLS_E_INVALID_REQUEST;
        }

      ret = _gnutls_hash_init (&hd, hash);
      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }

      _gnutls_hash (&hd, text->data, text->size);
      _gnutls_hash_deinit (&hd, md);

      cmp = md;
    }

  if (memcmp (cmp, digest, digest_size) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_PK_SIG_VERIFY_FAILED;
    }

  return 0;
}
Exemple #28
0
/* ID should be:
 * 3 for MAC
 * 2 for IV
 * 1 for encryption key
 */
int
_gnutls_pkcs12_string_to_key (unsigned int id, const opaque * salt,
			      unsigned int salt_size, unsigned int iter,
			      const char *pw, unsigned int req_keylen,
			      opaque * keybuf)
{
  int rc;
  unsigned int i, j;
  digest_hd_st md;
  bigint_t num_b1 = NULL, num_ij = NULL;
  bigint_t mpi512 = NULL;
  unsigned int pwlen;
  opaque hash[20], buf_b[64], buf_i[128], *p;
  size_t cur_keylen;
  size_t n;
  const opaque buf_512[] =	/* 2^64 */
  { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };

  cur_keylen = 0;

  if (pw == NULL)
    pwlen = 0;
  else
    pwlen = strlen (pw);

  if (pwlen > 63 / 2)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if ((rc = _pkcs12_check_pass (pw, pwlen)) < 0)
    {
      gnutls_assert ();
      return rc;
    }

  rc = _gnutls_mpi_scan (&mpi512, buf_512, sizeof (buf_512));
  if (rc < 0)
    {
      gnutls_assert ();
      return rc;
    }

  /* Store salt and password in BUF_I */
  p = buf_i;
  for (i = 0; i < 64; i++)
    *p++ = salt[i % salt_size];
  if (pw)
    {
      for (i = j = 0; i < 64; i += 2)
	{
	  *p++ = 0;
	  *p++ = pw[j];
	  if (++j > pwlen)	/* Note, that we include the trailing zero */
	    j = 0;
	}
    }
  else
    memset (p, 0, 64);

  for (;;)
    {
      rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1);
      if (rc < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
      for (i = 0; i < 64; i++)
	{
	  unsigned char lid = id & 0xFF;
	  _gnutls_hash (&md, &lid, 1);
	}
      _gnutls_hash (&md, buf_i, pw ? 128 : 64);
      _gnutls_hash_deinit (&md, hash);
      for (i = 1; i < iter; i++)
	{
	  rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1);
	  if (rc < 0)
	    {
	      gnutls_assert ();
	      goto cleanup;
	    }
	  _gnutls_hash (&md, hash, 20);
	  _gnutls_hash_deinit (&md, hash);
	}
      for (i = 0; i < 20 && cur_keylen < req_keylen; i++)
	keybuf[cur_keylen++] = hash[i];
      if (cur_keylen == req_keylen)
	{
	  rc = 0;		/* ready */
	  goto cleanup;
	}

      /* need more bytes. */
      for (i = 0; i < 64; i++)
	buf_b[i] = hash[i % 20];
      n = 64;
      rc = _gnutls_mpi_scan (&num_b1, buf_b, n);
      if (rc < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
      _gnutls_mpi_add_ui (num_b1, num_b1, 1);
      for (i = 0; i < 128; i += 64)
	{
	  n = 64;
	  rc = _gnutls_mpi_scan (&num_ij, buf_i + i, n);
	  if (rc < 0)
	    {
	      gnutls_assert ();
	      goto cleanup;
	    }
	  _gnutls_mpi_addm (num_ij, num_ij, num_b1, mpi512);
	  n = 64;
	  rc = _gnutls_mpi_print (num_ij, buf_i + i, &n);
	  if (rc < 0)
	    {
	      gnutls_assert ();
	      goto cleanup;
	    }
	  _gnutls_mpi_release (&num_ij);
	}
    }
cleanup:
  _gnutls_mpi_release (&num_ij);
  _gnutls_mpi_release (&num_b1);
  _gnutls_mpi_release (&mpi512);

  return rc;
}
Exemple #29
0
/* Verifies a TLS signature (like the one in the client certificate
 * verify message). 
 */
int
_gnutls_verify_sig_hdata (gnutls_session_t session, gnutls_cert * cert,
			  gnutls_datum_t * signature)
{
  int ret;
  opaque concat[36];
  digest_hd_st td_md5;
  digest_hd_st td_sha;
  gnutls_datum_t dconcat;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

  ret =
    _gnutls_hash_copy (&td_md5, &session->internals.handshake_mac_handle_md5);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  ret =
    _gnutls_hash_copy (&td_sha, &session->internals.handshake_mac_handle_sha);
  if (ret < 0)
    {
      gnutls_assert ();
      _gnutls_hash_deinit (&td_md5, NULL);
      return GNUTLS_E_HASH_FAILED;
    }

  if (ver == GNUTLS_SSL3)
    {
      ret = _gnutls_generate_master (session, 1);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

      _gnutls_mac_deinit_ssl3_handshake (&td_md5, concat,
					 session->security_parameters.
					 master_secret, GNUTLS_MASTER_SIZE);
      _gnutls_mac_deinit_ssl3_handshake (&td_sha, &concat[16],
					 session->security_parameters.
					 master_secret, GNUTLS_MASTER_SIZE);
    }
  else
    {
      _gnutls_hash_deinit (&td_md5, concat);
      _gnutls_hash_deinit (&td_sha, &concat[16]);
    }

  dconcat.data = concat;
  dconcat.size = 20 + 16;	/* md5+ sha */

  ret = _gnutls_verify_sig (cert, &dconcat, signature, 16);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return ret;

}
Exemple #30
0
static cdk_error_t
file_verify_clearsign (cdk_ctx_t hd, const char *file, const char *output)
{
  cdk_stream_t inp = NULL, out = NULL, tmp = NULL;
  digest_hd_st md;
  char buf[512], chk[512];
  const char *s;
  int i, is_signed = 0, nbytes;
  int digest_algo = 0;
  int err;
  cdk_error_t rc;

  memset(&md, 0, sizeof(md));

  if (output)
    {
      rc = cdk_stream_create (output, &out);
      if (rc)
	return rc;
    }

  rc = cdk_stream_open (file, &inp);
  if (rc)
    {
      if (output)
	cdk_stream_close (out);
      return rc;
    }

  s = "-----BEGIN PGP SIGNED MESSAGE-----";
  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (!strncmp (buf, s, strlen (s)))
	{
	  is_signed = 1;
	  break;
	}
    }

  if (cdk_stream_eof (inp) && !is_signed)
    {
      rc = CDK_Armor_Error;
      goto leave;
    }

  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (nbytes == 1)		/* Empty line */
	break;
      else if (!strncmp (buf, "Hash: ", 6))
	{
	  for (i = 0; digest_table[i].name; i++)
	    {
	      if (!strcmp (buf + 6, digest_table[i].name))
		{
		  digest_algo = digest_table[i].algo;
		  break;
		}
	    }
	}
    }

  if (digest_algo && _gnutls_hash_get_algo_len (digest_algo) <= 0)
    {
      rc = CDK_Inv_Algo;
      goto leave;
    }

  if (!digest_algo)
    digest_algo = GNUTLS_DIG_MD5;

  err = _gnutls_hash_init (&md, digest_algo);
  if (err < 0)
    {
      rc = map_gnutls_error (err);
      goto leave;
    }

  s = "-----BEGIN PGP SIGNATURE-----";
  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (!strncmp (buf, s, strlen (s)))
	break;
      else
	{
	  cdk_stream_peek (inp, (byte *) chk, DIM (chk) - 1);
	  i = strncmp (chk, s, strlen (s));
	  if (strlen (buf) == 0 && i == 0)
	    continue;		/* skip last '\n' */
	  _cdk_trim_string (buf, i == 0 ? 0 : 1);
	  _gnutls_hash (&md, buf, strlen (buf));
	}
      if (!strncmp (buf, "- ", 2))	/* FIXME: handle it recursive. */
	memmove (buf, buf + 2, nbytes - 2);
      if (out)
	{
	  if (strstr (buf, "\r\n"))
	    buf[strlen (buf) - 2] = '\0';
	  cdk_stream_write (out, buf, strlen (buf));
	  _cdk_stream_puts (out, _cdk_armor_get_lineend ());
	}
    }

  /* We create a temporary stream object to store the
     signature data in there. */
  rc = cdk_stream_tmp_new (&tmp);
  if (rc)
    goto leave;

  s = "-----BEGIN PGP SIGNATURE-----\n";
  _cdk_stream_puts (tmp, s);
  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (nbytes < (int) (DIM (buf) - 3))
	{
	  buf[nbytes - 1] = '\n';
	  buf[nbytes] = '\0';
	}
      cdk_stream_write (tmp, buf, nbytes);
    }

  /* FIXME: This code is not very elegant. */
  cdk_stream_tmp_set_mode (tmp, STREAMCTL_READ);
  cdk_stream_seek (tmp, 0);
  cdk_stream_set_armor_flag (tmp, 0);
  cdk_stream_read (tmp, NULL, 0);

  /* the digest handle will be closed there. */
  rc = _cdk_proc_packets (hd, tmp, NULL, NULL, NULL, &md);

leave:
  _gnutls_hash_deinit (&md, NULL);
  cdk_stream_close (out);
  cdk_stream_close (tmp);
  cdk_stream_close (inp);
  return rc;
}