/* 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;
}
Exemple #2
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 #3
0
/* Check if the given signature algorithm is accepted by
 * the peer. Returns 0 on success or a negative value
 * on error.
 */
int
_gnutls_session_sign_algo_requested (gnutls_session_t session,
                                     gnutls_sign_algorithm_t sig)
{
    unsigned i;
    int ret, hash;
    gnutls_protocol_t ver = gnutls_protocol_get_version (session);
    sig_ext_st *priv;
    extension_priv_data_t epriv;

    if (!_gnutls_version_has_selectable_sighash (ver))
    {
        return 0;
    }

    ret =
        _gnutls_ext_get_session_data (session,
                                      GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
                                      &epriv);
    if (ret < 0)
    {
        gnutls_assert ();
        /* extension not received allow SHA1 and SHA256 */
        hash = _gnutls_sign_get_hash_algorithm (sig);
        if (hash == GNUTLS_DIG_SHA1 || hash == GNUTLS_DIG_SHA256)
            return 0;
        else
            return ret;
    }
    priv = epriv.ptr;

    if (priv->sign_algorithms_size == 0)
        /* none set, allow all */
    {
        return 0;
    }

    for (i = 0; i < priv->sign_algorithms_size; i++)
    {
        if (priv->sign_algorithms[i] == sig)
        {
            return 0;             /* ok */
        }
    }

    return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
}
Exemple #4
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;
}
Exemple #5
0
/* 
 * Verifies the given certificate again a certificate list of
 * trusted CAs.
 *
 * Returns only 0 or 1. If 1 it means that the certificate 
 * was successfuly verified.
 *
 * 'flags': an OR of the gnutls_certificate_verify_flags enumeration.
 *
 * Output will hold some extra information about the verification
 * procedure. Issuer will hold the actual issuer from the trusted list.
 */
static int
_gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
                             const gnutls_x509_crt_t * trusted_cas,
                             int tcas_size, unsigned int flags,
                             unsigned int *output,
                             gnutls_x509_crt_t * _issuer,
                             time_t now,
                             gnutls_verify_output_function func)
{
  gnutls_datum_t cert_signed_data = { NULL, 0 };
  gnutls_datum_t cert_signature = { NULL, 0 };
  gnutls_x509_crt_t issuer = NULL;
  int issuer_version, result, hash_algo;
  unsigned int out = 0;

  if (output)
    *output = 0;

  if (tcas_size >= 1)
    issuer = find_issuer (cert, trusted_cas, tcas_size);
  else
    {
      gnutls_assert ();
      out = GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID;
      if (output)
        *output |= out;
      result = 0;
      goto cleanup;
    }

  /* issuer is not in trusted certificate
   * authorities.
   */
  if (issuer == NULL)
    {
      out = GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID;
      if (output)
        *output |= out;
      gnutls_assert ();
      result = 0;
      goto cleanup;
    }

  if (_issuer != NULL)
    *_issuer = issuer;

  issuer_version = gnutls_x509_crt_get_version (issuer);
  if (issuer_version < 0)
    {
      gnutls_assert ();
      return issuer_version;
    }

  if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN) &&
      ((flags & GNUTLS_VERIFY_DO_NOT_ALLOW_X509_V1_CA_CRT)
       || issuer_version != 1))
    {
      if (check_if_ca (cert, issuer, flags) == 0)
        {
          gnutls_assert ();
          out = GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID;
          if (output)
            *output |= out;
          result = 0;
          goto cleanup;
        }
    }

  result =
    _gnutls_x509_get_signed_data (cert->cert, "tbsCertificate",
                                  &cert_signed_data);
  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  result =
    _gnutls_x509_get_signature (cert->cert, "signature", &cert_signature);
  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  result = _gnutls_x509_get_signature_algorithm(cert->cert, "signatureAlgorithm.algorithm");
  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  hash_algo = _gnutls_sign_get_hash_algorithm(result);

  result =
    _gnutls_x509_verify_data (hash_algo, &cert_signed_data, &cert_signature,
                                   issuer);
  if (result == GNUTLS_E_PK_SIG_VERIFY_FAILED)
    {
      gnutls_assert ();
      out |= GNUTLS_CERT_INVALID;
      /* error. ignore it */
      if (output)
        *output |= out;
      result = 0;
    }
  else if (result < 0)
    {
      gnutls_assert();
      goto cleanup;
    }

  /* If the certificate is not self signed check if the algorithms
   * used are secure. If the certificate is self signed it doesn't
   * really matter.
   */
  if (is_issuer (cert, cert) == 0)
    {
      int sigalg;

      sigalg = gnutls_x509_crt_get_signature_algorithm (cert);

      if (((sigalg == GNUTLS_SIGN_RSA_MD2) &&
           !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) ||
          ((sigalg == GNUTLS_SIGN_RSA_MD5) &&
           !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5)))
        {
          out = GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID;
          if (output)
            *output |= out;
          result = 0;
        }
    }

  /* Check activation/expiration times
   */
  if (!(flags & GNUTLS_VERIFY_DISABLE_TIME_CHECKS))
    {
      /* check the time of the issuer first */
      if (!(flags & GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS))
        {
          out |= check_time (issuer, now);
          if (out != 0)
            {
              result = 0;
              if (output) *output |= out;
            }
        }

      out |= check_time (cert, now);
      if (out != 0)
        {
          result = 0;
          if (output) *output |= out;
        }
    }

cleanup:
  if (result >= 0 && func) func(cert, issuer, NULL, out);
  _gnutls_free_datum (&cert_signed_data);
  _gnutls_free_datum (&cert_signature);

  return result;
}
Exemple #6
0
/* 
 * Returns only 0 or 1. If 1 it means that the CRL
 * was successfuly verified.
 *
 * 'flags': an OR of the gnutls_certificate_verify_flags enumeration.
 *
 * Output will hold information about the verification
 * procedure. 
 */
static int
_gnutls_verify_crl2 (gnutls_x509_crl_t crl,
                     const gnutls_x509_crt_t * trusted_cas,
                     int tcas_size, unsigned int flags, unsigned int *output)
{
/* CRL is ignored for now */
  gnutls_datum_t crl_signed_data = { NULL, 0 };
  gnutls_datum_t crl_signature = { NULL, 0 };
  gnutls_x509_crt_t issuer;
  int result, hash_algo;

  if (output)
    *output = 0;

  if (tcas_size >= 1)
    issuer = find_crl_issuer (crl, trusted_cas, tcas_size);
  else
    {
      gnutls_assert ();
      if (output)
        *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID;
      return 0;
    }

  /* issuer is not in trusted certificate
   * authorities.
   */
  if (issuer == NULL)
    {
      gnutls_assert ();
      if (output)
        *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID;
      return 0;
    }

  if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN))
    {
      if (gnutls_x509_crt_get_ca_status (issuer, NULL) != 1)
        {
          gnutls_assert ();
          if (output)
            *output |= GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID;
          return 0;
        }
    }

  result =
    _gnutls_x509_get_signed_data (crl->crl, "tbsCertList", &crl_signed_data);
  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  result = _gnutls_x509_get_signature (crl->crl, "signature", &crl_signature);
  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  result = _gnutls_x509_get_signature_algorithm(crl->crl, "signatureAlgorithm.algorithm");
  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  hash_algo = _gnutls_sign_get_hash_algorithm(result);

  result =
    _gnutls_x509_verify_data (hash_algo, &crl_signed_data, &crl_signature,
                                   issuer);
  if (result == GNUTLS_E_PK_SIG_VERIFY_FAILED)
    {
      gnutls_assert ();
      /* error. ignore it */
      if (output)
        *output |= GNUTLS_CERT_INVALID;
      result = 0;
    }
  else if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  {
    int sigalg;

    sigalg = gnutls_x509_crl_get_signature_algorithm (crl);

    if (((sigalg == GNUTLS_SIGN_RSA_MD2) &&
         !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) ||
        ((sigalg == GNUTLS_SIGN_RSA_MD5) &&
         !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5)))
      {
        if (output)
          *output |= GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID;
        result = 0;
      }
  }

cleanup:
  _gnutls_free_datum (&crl_signed_data);
  _gnutls_free_datum (&crl_signature);

  return result;
}
Exemple #7
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;

}
Exemple #8
0
/* Generates a signature of all the random data and the parameters.
 * Used in DHE_* ciphersuites.
 */
int
_gnutls_handshake_sign_data (gnutls_session_t session, gnutls_pcert_st* cert,
                             gnutls_privkey_t pkey, gnutls_datum_t * params,
                             gnutls_datum_t * signature,
                             gnutls_sign_algorithm_t * sign_algo)
{
  gnutls_datum_t dconcat;
  int ret;
  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;

  *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_handshake_log ("HSK[%p]: signing handshake data: using %s\n",
                    session, gnutls_sign_algorithm_get_name (*sign_algo));

  ret = _gnutls_hash_init (&td_sha, hash_algo);
  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 (gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL))
    {
    case GNUTLS_PK_RSA:
      if (!_gnutls_version_has_selectable_sighash (ver))
        {
          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.data = concat;
          dconcat.size = 36;
        }
      else
        { /* TLS 1.2 way */

          _gnutls_hash_deinit (&td_sha, concat);

          dconcat.data = concat;
          dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
        }
      break;
    case GNUTLS_PK_DSA:
      _gnutls_hash_deinit (&td_sha, concat);

      if ((hash_algo != GNUTLS_DIG_SHA1) && (hash_algo != GNUTLS_DIG_SHA224)
          && (hash_algo != GNUTLS_DIG_SHA256))
        {
          gnutls_assert ();
          return GNUTLS_E_INTERNAL_ERROR;
        }
      dconcat.data = concat;
      dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
      break;

    default:
      gnutls_assert ();
      _gnutls_hash_deinit (&td_sha, NULL);
      return GNUTLS_E_INTERNAL_ERROR;
    }

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

  return ret;

}
Exemple #9
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;

}