示例#1
0
/* Returns a requested by the peer signature algorithm that
 * matches the given certificate's public key algorithm. 
 */
gnutls_sign_algorithm_t
_gnutls_session_get_sign_algo(gnutls_session_t session,
			      gnutls_pcert_st * cert)
{
	unsigned i;
	int ret;
	const version_entry_st *ver = get_version(session);
	sig_ext_st *priv;
	extension_priv_data_t epriv;
	unsigned int cert_algo;

	if (unlikely(ver == NULL))
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	cert_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
					 &epriv);
	priv = epriv;

	if (ret < 0 || !_gnutls_version_has_selectable_sighash(ver)
	    || priv->sign_algorithms_size == 0)
		/* none set, allow SHA-1 only */
	{
		ret = gnutls_pk_to_sign(cert_algo, GNUTLS_DIG_SHA1);
		if (_gnutls_session_sign_algo_enabled(session, ret) < 0)
			goto fail;
		return ret;
	}

	for (i = 0; i < priv->sign_algorithms_size; i++) {
		if (gnutls_sign_get_pk_algorithm(priv->sign_algorithms[i])
		    == cert_algo) {
			if (_gnutls_pubkey_compatible_with_sig
			    (session, cert->pubkey, ver,
			     priv->sign_algorithms[i]) < 0)
				continue;

			if (_gnutls_session_sign_algo_enabled
			    (session, priv->sign_algorithms[i]) < 0)
				continue;

			return priv->sign_algorithms[i];
		}
	}

 fail:
	return GNUTLS_SIGN_UNKNOWN;
}
示例#2
0
/* this is _gnutls_handshake_verify_crt_vrfy for TLS 1.2
 */
static int
_gnutls_handshake_verify_crt_vrfy12(gnutls_session_t session,
				    gnutls_pcert_st * cert,
				    gnutls_datum_t * signature,
				    gnutls_sign_algorithm_t sign_algo)
{
	int ret;
	uint8_t concat[MAX_HASH_SIZE];
	gnutls_datum_t dconcat;
	const version_entry_st *ver = get_version(session);
	gnutls_pk_algorithm_t pk =
	    gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
	const mac_entry_st *me;

	ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
	if (ret < 0)
		return gnutls_assert_val(ret);

	gnutls_sign_algorithm_set_client(session, sign_algo);

	me = hash_to_entry(gnutls_sign_get_hash_algorithm(sign_algo));

	ret =
	    _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
			      session->internals.handshake_hash_buffer.
			      data,
			      session->internals.
			      handshake_hash_buffer_prev_len, concat);
	if (ret < 0)
		return gnutls_assert_val(ret);

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

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

	return ret;

}
/* Returns a requested by the peer signature algorithm that
 * matches the given certificate's public key algorithm. 
 */
gnutls_sign_algorithm_t
_gnutls_session_get_sign_algo (gnutls_session_t session, gnutls_pcert_st* cert)
{
  unsigned i;
  int ret;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
  sig_ext_st *priv;
  extension_priv_data_t epriv;
  unsigned int cert_algo;
  
  cert_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);

  ret =
    _gnutls_ext_get_session_data (session,
                                  GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
                                  &epriv);
  priv = epriv.ptr;

  if (ret < 0 || !_gnutls_version_has_selectable_sighash (ver)
      || priv->sign_algorithms_size == 0)
    /* none set, allow SHA-1 only */
    {
      return gnutls_pk_to_sign (cert_algo, GNUTLS_DIG_SHA1);
    }

  for (i = 0; i < priv->sign_algorithms_size; i++)
    {
      if (_gnutls_sign_get_pk_algorithm (priv->sign_algorithms[i]) == cert_algo)
        {
          if (_gnutls_pubkey_compatible_with_sig(cert->pubkey, ver, priv->sign_algorithms[i]) < 0)
            continue;

          if (_gnutls_session_sign_algo_enabled(session, priv->sign_algorithms[i]) < 0)
            continue;

          return priv->sign_algorithms[i];
        }
    }

  return GNUTLS_SIGN_UNKNOWN;
}
示例#4
0
/* Generates a signature of all the random data and the parameters.
 * Used in DHE_* ciphersuites.
 */
int
_gnutls_handshake_verify_data(gnutls_session_t session,
			      gnutls_pcert_st * cert,
			      const gnutls_datum_t * params,
			      gnutls_datum_t * signature,
			      gnutls_sign_algorithm_t sign_algo)
{
	gnutls_datum_t dconcat;
	int ret;
	digest_hd_st td_md5;
	digest_hd_st td_sha;
	uint8_t concat[MAX_SIG_SIZE];
	const version_entry_st *ver = get_version(session);
	gnutls_digest_algorithm_t hash_algo;
	const mac_entry_st *me;

	if (_gnutls_version_has_selectable_sighash(ver)) {
		_gnutls_handshake_log
		    ("HSK[%p]: verify handshake data: using %s\n", session,
		     gnutls_sign_algorithm_get_name(sign_algo));

		ret =
		    _gnutls_pubkey_compatible_with_sig(session,
						       cert->pubkey, ver,
						       sign_algo);
		if (ret < 0)
			return gnutls_assert_val(ret);

		ret =
		    _gnutls_session_sign_algo_enabled(session, sign_algo);
		if (ret < 0)
			return gnutls_assert_val(ret);

		hash_algo = gnutls_sign_get_hash_algorithm(sign_algo);
		me = hash_to_entry(hash_algo);
	} else {
		me = hash_to_entry(GNUTLS_DIG_MD5);
		ret = _gnutls_hash_init(&td_md5, me);
		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);

		me = hash_to_entry(GNUTLS_DIG_SHA1);
	}

	ret = _gnutls_hash_init(&td_sha, me);
	if (ret < 0) {
		gnutls_assert();
		if (!_gnutls_version_has_selectable_sighash(ver))
			_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 (!_gnutls_version_has_selectable_sighash(ver)) {
		_gnutls_hash_deinit(&td_md5, concat);
		_gnutls_hash_deinit(&td_sha, &concat[16]);
		dconcat.data = concat;
		dconcat.size = 36;
	} else {
		_gnutls_hash_deinit(&td_sha, concat);

		dconcat.data = concat;
		dconcat.size = _gnutls_hash_get_algo_len(me);
	}

	ret = verify_tls_hash(session, ver, cert, &dconcat, signature,
			      dconcat.size - _gnutls_hash_get_algo_len(me),
			      sign_algo,
			      gnutls_sign_get_pk_algorithm(sign_algo));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	return ret;

}
示例#5
0
/* Generates a signature of all the random data and the parameters.
 * Used in DHE_* ciphersuites.
 */
int
_gnutls_handshake_verify_data (gnutls_session_t session, gnutls_cert * cert,
			       const gnutls_datum_t * params,
			       gnutls_datum_t * signature,
			       gnutls_sign_algorithm_t algo)
{
  gnutls_datum_t dconcat;
  int ret;
  digest_hd_st td_md5;
  digest_hd_st td_sha;
  opaque concat[MAX_SIG_SIZE];
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
  gnutls_digest_algorithm_t hash_algo = GNUTLS_DIG_SHA1;

  ret = _gnutls_session_sign_algo_enabled (session, algo);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  if (!_gnutls_version_has_selectable_prf (ver))
    {
      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);
    }

  if (algo != GNUTLS_SIGN_UNKNOWN)
    hash_algo = _gnutls_sign_get_hash_algorithm (algo);

  ret = _gnutls_hash_init (&td_sha, hash_algo);
  if (ret < 0)
    {
      gnutls_assert ();
      if (!_gnutls_version_has_selectable_prf (ver))
	_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 (!_gnutls_version_has_selectable_prf (ver))
    {
      _gnutls_hash_deinit (&td_md5, concat);
      _gnutls_hash_deinit (&td_sha, &concat[16]);
      dconcat.data = concat;
      dconcat.size = 36;
    }
  else
    {
      gnutls_datum_t hash;

      _gnutls_hash_deinit (&td_sha, concat);

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

      _gnutls_rsa_encode_sig (hash_algo, &hash, &dconcat);
    }

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

  return ret;

}