Example #1
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 | GNUTLS_CERT_SIGNATURE_FAILURE;
      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;
}
Example #2
0
/**
 * gnutls_x509_crl_verify:
 * @crl: is the crl to be verified
 * @trusted_cas: is a certificate list that is considered to be trusted one
 * @tcas_size: holds the number of CA certificates in CA_list
 * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
 * @verify: will hold the crl verification output.
 *
 * This function will try to verify the given crl and return its verification status.
 * See gnutls_x509_crt_list_verify() for a detailed description of
 * return values. Note that since GnuTLS 3.1.4 this function includes
 * the time checks.
 *
 * Note that value in @verify is set only when the return value of this 
 * function is success (i.e, failure to trust a CRL a certificate does not imply 
 * a negative return value).
 *
 * Before GnuTLS 3.5.7 this function would return zero or a positive
 * number on success.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0), otherwise a
 *   negative error value.
 **/
int
gnutls_x509_crl_verify(gnutls_x509_crl_t crl,
		       const gnutls_x509_crt_t * trusted_cas,
		       unsigned tcas_size, unsigned int flags,
		       unsigned int *verify)
{
/* 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 = NULL;
	int result, hash_algo;
	time_t now = gnutls_time(0);
	unsigned int usage;

	if (verify)
		*verify = 0;

	if (tcas_size >= 1)
		issuer = find_crl_issuer(crl, trusted_cas, tcas_size);

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

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

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

	hash_algo = gnutls_sign_get_hash_algorithm(result);

	/* issuer is not in trusted certificate
	 * authorities.
	 */
	if (issuer == NULL) {
		gnutls_assert();
		if (verify)
			*verify |=
			    GNUTLS_CERT_SIGNER_NOT_FOUND |
			    GNUTLS_CERT_INVALID;
	} else {
		if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN)) {
			if (gnutls_x509_crt_get_ca_status(issuer, NULL) != 1) {
				gnutls_assert();
				if (verify)
					*verify |=
					    GNUTLS_CERT_SIGNER_NOT_CA |
					    GNUTLS_CERT_INVALID;
			}

			result =
			    gnutls_x509_crt_get_key_usage(issuer, &usage, NULL);
			if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
				if (result < 0) {
					gnutls_assert();
					if (verify)
						*verify |= GNUTLS_CERT_INVALID;
				} else if (!(usage & GNUTLS_KEY_CRL_SIGN)) {
					gnutls_assert();
					if (verify)
						*verify |=
						    GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE
						    | GNUTLS_CERT_INVALID;
				}
			}
		}

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

	{
		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 (verify)
				*verify |= GNUTLS_CERT_INSECURE_ALGORITHM;
			result = 0;
		}
	}

	if (gnutls_x509_crl_get_this_update(crl) > now && verify)
		*verify |= GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE;

	if (gnutls_x509_crl_get_next_update(crl) < now && verify)
		*verify |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED;


      cleanup:
	if (verify && *verify != 0)
		*verify |= GNUTLS_CERT_INVALID;

	_gnutls_free_datum(&crl_signed_data);
	_gnutls_free_datum(&crl_signature);

	return result;
}