示例#1
0
/* Returns a requested by the peer signature algorithm that
 * matches the given public key algorithm. Index can be increased
 * to return the second choice etc.
 */
gnutls_sign_algorithm_t
_gnutls_session_get_sign_algo (gnutls_session_t session,
			       gnutls_pk_algorithm_t pk,
			       gnutls_digest_algorithm_t * hash)
{
  unsigned i;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);


  if (!_gnutls_version_has_selectable_sighash (ver)
      || session->security_parameters.extensions.sign_algorithms_size == 0)
    /* none set, allow all */
    {
      *hash = GNUTLS_DIG_SHA1;
      return _gnutls_x509_pk_to_sign (pk, *hash);
    }

  for (i = 0;
       i < session->security_parameters.extensions.sign_algorithms_size; i++)
    {
      if (_gnutls_sign_get_pk_algorithm
	  (session->security_parameters.extensions.sign_algorithms[i]) == pk)
	{
	  *hash =
	    _gnutls_sign_get_hash_algorithm (session->security_parameters.
					     extensions.sign_algorithms[i]);
	  return session->security_parameters.extensions.sign_algorithms[i];
	}
    }

  return GNUTLS_SIGN_UNKNOWN;
}
/* 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;
}
示例#3
0
/* Returns a requested by the peer signature algorithm that
 * matches the given public key algorithm. Index can be increased
 * to return the second choice etc.
 */
gnutls_sign_algorithm_t
_gnutls_session_get_sign_algo (gnutls_session_t session,
                               gnutls_pk_algorithm_t pk,
                               gnutls_digest_algorithm_t * hash)
{
    unsigned i;
    int ret;
    gnutls_protocol_t ver = gnutls_protocol_get_version (session);
    sig_ext_st *priv;
    extension_priv_data_t epriv;

    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 all */
    {
        *hash = GNUTLS_DIG_SHA1;
        return _gnutls_x509_pk_to_sign (pk, *hash);
    }

    for (i = 0; i < priv->sign_algorithms_size; i++)
    {
        if (_gnutls_sign_get_pk_algorithm (priv->sign_algorithms[i]) == pk)
        {
            *hash = _gnutls_sign_get_hash_algorithm (priv->sign_algorithms[i]);
            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_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;

}
示例#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_pcert_st* 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;

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

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

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

      hash_algo = _gnutls_sign_get_hash_algorithm (algo);
    }
  else
    {
      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);

      hash_algo = GNUTLS_DIG_SHA1;
    }

  ret = _gnutls_hash_init (&td_sha, hash_algo);
  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 (hash_algo);
    }

  ret = verify_tls_hash (ver, 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;

}