Пример #1
0
static int
check_heim_integer_same(const char *p, const char *norm_p, heim_integer *i)
{
    heim_integer i2;
    char *str;
    int ret;

    ret = der_print_hex_heim_integer(i, &str);
    if (ret)
	errx(1, "der_print_hex_heim_integer: %d", ret);

    if (strcmp(str, norm_p) != 0)
	errx(1, "der_print_hex_heim_integer: %s != %s", str, p);

    ret = der_parse_hex_heim_integer(str, &i2);
    if (ret)
	errx(1, "der_parse_hex_heim_integer: %d", ret);

    if (der_heim_integer_cmp(i, &i2) != 0)
	errx(1, "der_heim_integer_cmp: p %s", p);

    der_free_heim_integer(&i2);
    free(str);

    ret = der_parse_hex_heim_integer(p, &i2);
    if (ret)
	errx(1, "der_parse_hex_heim_integer: %d", ret);

    if (der_heim_integer_cmp(i, &i2) != 0)
	errx(1, "der_heim_integer_cmp: norm");

    der_free_heim_integer(&i2);

    return 0;
}
Пример #2
0
static int
test_cmp_heim_integer (void *a, void *b)
{
    return der_heim_integer_cmp((heim_integer *)a, (heim_integer *)b);
}
Пример #3
0
int
hx509_ocsp_verify(hx509_context context,
		  time_t now,
		  hx509_cert cert,
		  int flags,
		  const void *data, size_t length,
		  time_t *expiration)
{
    const Certificate *c = _hx509_get_cert(cert);
    OCSPBasicOCSPResponse basic;
    int ret;
    size_t i;

    if (now == 0)
	now = time(NULL);

    *expiration = 0;

    ret = parse_ocsp_basic(data, length, &basic);
    if (ret) {
	hx509_set_error_string(context, 0, ret,
			       "Failed to parse OCSP response");
	return ret;
    }

    for (i = 0; i < basic.tbsResponseData.responses.len; i++) {

	ret = der_heim_integer_cmp(&basic.tbsResponseData.responses.val[i].certID.serialNumber,
			       &c->tbsCertificate.serialNumber);
	if (ret != 0)
	    continue;

	/* verify issuer hashes hash */
	ret = _hx509_verify_signature(context,
				      NULL,
				      &basic.tbsResponseData.responses.val[i].certID.hashAlgorithm,
				      &c->tbsCertificate.issuer._save,
				      &basic.tbsResponseData.responses.val[i].certID.issuerNameHash);
	if (ret != 0)
	    continue;

	switch (basic.tbsResponseData.responses.val[i].certStatus.element) {
	case choice_OCSPCertStatus_good:
	    break;
	case choice_OCSPCertStatus_revoked:
	case choice_OCSPCertStatus_unknown:
	    continue;
	}

	/* don't allow the update to be in the future */
	if (basic.tbsResponseData.responses.val[i].thisUpdate >
	    now + context->ocsp_time_diff)
	    continue;

	/* don't allow the next update to be in the past */
	if (basic.tbsResponseData.responses.val[i].nextUpdate) {
	    if (*basic.tbsResponseData.responses.val[i].nextUpdate < now)
		continue;
	    *expiration = *basic.tbsResponseData.responses.val[i].nextUpdate;
	} else
	    *expiration = now;

	free_OCSPBasicOCSPResponse(&basic);
	return 0;
    }

    free_OCSPBasicOCSPResponse(&basic);

    {
	hx509_name name;
	char *subject;

	ret = hx509_cert_get_subject(cert, &name);
	if (ret) {
	    hx509_clear_error_string(context);
	    goto out;
	}
	ret = hx509_name_to_string(name, &subject);
	hx509_name_free(&name);
	if (ret) {
	    hx509_clear_error_string(context);
	    goto out;
	}
	hx509_set_error_string(context, 0, HX509_CERT_NOT_IN_OCSP,
			       "Certificate %s not in OCSP response "
			       "or not good",
			       subject);
	free(subject);
    }
out:
    return HX509_CERT_NOT_IN_OCSP;
}
Пример #4
0
int
hx509_revoke_verify(hx509_context context,
		    hx509_revoke_ctx ctx,
		    hx509_certs certs,
		    time_t now,
		    hx509_cert cert,
		    hx509_cert parent_cert)
{
    const Certificate *c = _hx509_get_cert(cert);
    const Certificate *p = _hx509_get_cert(parent_cert);
    unsigned long i, j, k;
    int ret;

    hx509_clear_error_string(context);

    for (i = 0; i < ctx->ocsps.len; i++) {
	struct revoke_ocsp *ocsp = &ctx->ocsps.val[i];
	struct stat sb;

	/* check this ocsp apply to this cert */

	/* check if there is a newer version of the file */
	ret = stat(ocsp->path, &sb);
	if (ret == 0 && ocsp->last_modfied != sb.st_mtime) {
	    ret = load_ocsp(context, ocsp);
	    if (ret)
		continue;
	}

	/* verify signature in ocsp if not already done */
	if (ocsp->signer == NULL) {
	    ret = verify_ocsp(context, ocsp, now, certs, parent_cert);
	    if (ret)
		continue;
	}

	for (j = 0; j < ocsp->ocsp.tbsResponseData.responses.len; j++) {
	    heim_octet_string os;

	    ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[j].certID.serialNumber,
				   &c->tbsCertificate.serialNumber);
	    if (ret != 0)
		continue;

	    /* verify issuer hashes hash */
	    ret = _hx509_verify_signature(context,
					  NULL,
					  &ocsp->ocsp.tbsResponseData.responses.val[i].certID.hashAlgorithm,
					  &c->tbsCertificate.issuer._save,
					  &ocsp->ocsp.tbsResponseData.responses.val[i].certID.issuerNameHash);
	    if (ret != 0)
		continue;

	    os.data = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
	    os.length = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;

	    ret = _hx509_verify_signature(context,
					  NULL,
					  &ocsp->ocsp.tbsResponseData.responses.val[j].certID.hashAlgorithm,
					  &os,
					  &ocsp->ocsp.tbsResponseData.responses.val[j].certID.issuerKeyHash);
	    if (ret != 0)
		continue;

	    switch (ocsp->ocsp.tbsResponseData.responses.val[j].certStatus.element) {
	    case choice_OCSPCertStatus_good:
		break;
	    case choice_OCSPCertStatus_revoked:
		hx509_set_error_string(context, 0,
				       HX509_CERT_REVOKED,
				       "Certificate revoked by issuer in OCSP");
		return HX509_CERT_REVOKED;
	    case choice_OCSPCertStatus_unknown:
		continue;
	    }

	    /* don't allow the update to be in the future */
	    if (ocsp->ocsp.tbsResponseData.responses.val[j].thisUpdate >
		now + context->ocsp_time_diff)
		continue;

	    /* don't allow the next update to be in the past */
	    if (ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate) {
		if (*ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate < now)
		    continue;
	    } /* else should force a refetch, but can we ? */

	    return 0;
	}
    }

    for (i = 0; i < ctx->crls.len; i++) {
	struct revoke_crl *crl = &ctx->crls.val[i];
	struct stat sb;
	int diff;

	/* check if cert.issuer == crls.val[i].crl.issuer */
	ret = _hx509_name_cmp(&c->tbsCertificate.issuer,
			      &crl->crl.tbsCertList.issuer, &diff);
	if (ret || diff)
	    continue;

	ret = stat(crl->path, &sb);
	if (ret == 0 && crl->last_modfied != sb.st_mtime) {
	    CRLCertificateList cl;

	    ret = load_crl(crl->path, &crl->last_modfied, &cl);
	    if (ret == 0) {
		free_CRLCertificateList(&crl->crl);
		crl->crl = cl;
		crl->verified = 0;
		crl->failed_verify = 0;
	    }
	}
	if (crl->failed_verify)
	    continue;

	/* verify signature in crl if not already done */
	if (crl->verified == 0) {
	    ret = verify_crl(context, ctx, &crl->crl, now, certs, parent_cert);
	    if (ret) {
		crl->failed_verify = 1;
		continue;
	    }
	    crl->verified = 1;
	}

	if (crl->crl.tbsCertList.crlExtensions) {
	    for (j = 0; j < crl->crl.tbsCertList.crlExtensions->len; j++) {
		if (crl->crl.tbsCertList.crlExtensions->val[j].critical) {
		    hx509_set_error_string(context, 0,
					   HX509_CRL_UNKNOWN_EXTENSION,
					   "Unknown CRL extension");
		    return HX509_CRL_UNKNOWN_EXTENSION;
		}
	    }
	}

	if (crl->crl.tbsCertList.revokedCertificates == NULL)
	    return 0;

	/* check if cert is in crl */
	for (j = 0; j < crl->crl.tbsCertList.revokedCertificates->len; j++) {
	    time_t t;

	    ret = der_heim_integer_cmp(&crl->crl.tbsCertList.revokedCertificates->val[j].userCertificate,
				       &c->tbsCertificate.serialNumber);
	    if (ret != 0)
		continue;

	    t = _hx509_Time2time_t(&crl->crl.tbsCertList.revokedCertificates->val[j].revocationDate);
	    if (t > now)
		continue;

	    if (crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions)
		for (k = 0; k < crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions->len; k++)
		    if (crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions->val[k].critical)
			return HX509_CRL_UNKNOWN_EXTENSION;

	    hx509_set_error_string(context, 0,
				   HX509_CERT_REVOKED,
				   "Certificate revoked by issuer in CRL");
	    return HX509_CERT_REVOKED;
	}

	return 0;
    }


    if (context->flags & HX509_CTX_VERIFY_MISSING_OK)
	return 0;
    hx509_set_error_string(context, HX509_ERROR_APPEND,
			   HX509_REVOKE_STATUS_MISSING,
			   "No revoke status found for "
			   "certificates");
    return HX509_REVOKE_STATUS_MISSING;
}
Пример #5
0
int
BN_cmp(const BIGNUM *bn1, const BIGNUM *bn2)
{
    return der_heim_integer_cmp((const heim_integer *)bn1,
				(const heim_integer *)bn2);
}