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_datum_t cert_signed_data = { NULL, 0 };
    gnutls_datum_t cert_signature = { NULL, 0 };
    gnutls_x509_crt_t issuer;
    int ret, issuer_version, result;

    if (output)
	*output = 0;

    if (tcas_size >= 1)
	issuer = find_issuer(cert, 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) {
	if (output)
	    *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID;
	gnutls_assert();
	return 0;
    }

    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_ALLOW_X509_V1_CA_CRT)
	  && issuer_version == 1)) {
	if (check_if_ca(cert, issuer, flags) == 0) {
	    gnutls_assert();
	    if (output)
		*output |= GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID;
	    return 0;
	}
    }


    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;
    }

    ret =
	_gnutls_x509_verify_signature(&cert_signed_data, &cert_signature,
				      issuer);
    if (ret < 0) {
	gnutls_assert();
    } else if (ret == 0) {
	gnutls_assert();
	/* error. ignore it */
	if (output)
	    *output |= GNUTLS_CERT_INVALID;
	ret = 0;
    }

    result = ret;

  cleanup:
    _gnutls_free_datum(&cert_signed_data);
    _gnutls_free_datum(&cert_signature);

    return result;
}
Unknown