Ejemplo n.º 1
0
static int
match_localkeyid(hx509_context context,
		 struct private_key *value,
		 hx509_certs certs)
{
    hx509_cert cert;
    hx509_query q;
    int ret;

    if (value->localKeyId.length == 0) {
	hx509_set_error_string(context, 0, HX509_LOCAL_ATTRIBUTE_MISSING,
			       "No local key attribute on private key");
	return HX509_LOCAL_ATTRIBUTE_MISSING;
    }

    _hx509_query_clear(&q);
    q.match |= HX509_QUERY_MATCH_LOCAL_KEY_ID;

    q.local_key_id = &value->localKeyId;

    ret = hx509_certs_find(context, certs, &q, &cert);
    if (ret == 0) {
	
	if (value->private_key)
	    _hx509_cert_assign_key(cert, value->private_key);
	hx509_cert_free(cert);
    }
    return ret;
}
Ejemplo n.º 2
0
Archivo: cms.c Proyecto: InvLim/heimdal
static int
find_CMSIdentifier(hx509_context context,
		   CMSIdentifier *client,
		   hx509_certs certs,
		   time_t time_now,
		   hx509_cert *signer_cert,
		   int match)
{
    hx509_query q;
    hx509_cert cert;
    Certificate c;
    int ret;

    memset(&c, 0, sizeof(c));
    _hx509_query_clear(&q);

    *signer_cert = NULL;

    switch (client->element) {
    case choice_CMSIdentifier_issuerAndSerialNumber:
	q.serial = &client->u.issuerAndSerialNumber.serialNumber;
	q.issuer_name = &client->u.issuerAndSerialNumber.issuer;
	q.match = HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
	break;
    case choice_CMSIdentifier_subjectKeyIdentifier:
	q.subject_id = &client->u.subjectKeyIdentifier;
	q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;
	break;
    default:
	hx509_set_error_string(context, 0, HX509_CMS_NO_RECIPIENT_CERTIFICATE,
			       "unknown CMS identifier element");
	return HX509_CMS_NO_RECIPIENT_CERTIFICATE;
    }

    q.match |= match;

    q.match |= HX509_QUERY_MATCH_TIME;
    if (time_now)
	q.timenow = time_now;
    else
	q.timenow = time(NULL);

    ret = hx509_certs_find(context, certs, &q, &cert);
    if (ret == HX509_CERT_NOT_FOUND) {
	char *str;

	ret = unparse_CMSIdentifier(context, client, &str);
	if (ret == 0) {
	    hx509_set_error_string(context, 0,
				   HX509_CMS_NO_RECIPIENT_CERTIFICATE,
				   "Failed to find %s", str);
	} else
	    hx509_clear_error_string(context);
	return HX509_CMS_NO_RECIPIENT_CERTIFICATE;
    } else if (ret) {
	hx509_set_error_string(context, HX509_ERROR_APPEND,
			       HX509_CMS_NO_RECIPIENT_CERTIFICATE,
			       "Failed to find CMS id in cert store");
	return HX509_CMS_NO_RECIPIENT_CERTIFICATE;
    }

    *signer_cert = cert;

    return 0;
}
Ejemplo n.º 3
0
static int
add_to_req(hx509_context context, void *ptr, hx509_cert cert)
{
    struct ocsp_add_ctx *ctx = ptr;
    OCSPInnerRequest *one;
    hx509_cert parent = NULL;
    Certificate *p, *c = _hx509_get_cert(cert);
    heim_octet_string os;
    int ret;
    hx509_query q;
    void *d;

    d = realloc(ctx->req->requestList.val,
		sizeof(ctx->req->requestList.val[0]) *
		(ctx->req->requestList.len + 1));
    if (d == NULL)
	return ENOMEM;
    ctx->req->requestList.val = d;

    one = &ctx->req->requestList.val[ctx->req->requestList.len];
    memset(one, 0, sizeof(*one));

    _hx509_query_clear(&q);

    q.match |= HX509_QUERY_FIND_ISSUER_CERT;
    q.subject = c;

    ret = hx509_certs_find(context, ctx->certs, &q, &parent);
    if (ret)
	goto out;

    if (ctx->parent) {
	if (hx509_cert_cmp(ctx->parent, parent) != 0) {
	    ret = HX509_REVOKE_NOT_SAME_PARENT;
	    hx509_set_error_string(context, 0, ret,
				   "Not same parent certifate as "
				   "last certificate in request");
	    goto out;
	}
    } else
	ctx->parent = hx509_cert_ref(parent);

    p = _hx509_get_cert(parent);

    ret = copy_AlgorithmIdentifier(ctx->digest, &one->reqCert.hashAlgorithm);
    if (ret)
	goto out;

    ret = _hx509_create_signature(context,
				  NULL,
				  &one->reqCert.hashAlgorithm,
				  &c->tbsCertificate.issuer._save,
				  NULL,
				  &one->reqCert.issuerNameHash);
    if (ret)
	goto out;

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

    ret = _hx509_create_signature(context,
				  NULL,
				  &one->reqCert.hashAlgorithm,
				  &os,
				  NULL,
				  &one->reqCert.issuerKeyHash);
    if (ret)
	goto out;

    ret = copy_CertificateSerialNumber(&c->tbsCertificate.serialNumber,
				       &one->reqCert.serialNumber);
    if (ret)
	goto out;

    ctx->req->requestList.len++;
out:
    hx509_cert_free(parent);
    if (ret) {
	free_OCSPInnerRequest(one);
	memset(one, 0, sizeof(*one));
    }

    return ret;
}
Ejemplo n.º 4
0
static int
verify_crl(hx509_context context,
	   hx509_revoke_ctx ctx,
	   CRLCertificateList *crl,
	   time_t time_now,
	   hx509_certs certs,
	   hx509_cert parent)
{
    hx509_cert signer;
    hx509_query q;
    time_t t;
    int ret;

    t = _hx509_Time2time_t(&crl->tbsCertList.thisUpdate);
    if (t > time_now) {
	hx509_set_error_string(context, 0, HX509_CRL_USED_BEFORE_TIME,
			       "CRL used before time");
	return HX509_CRL_USED_BEFORE_TIME;
    }

    if (crl->tbsCertList.nextUpdate == NULL) {
	hx509_set_error_string(context, 0, HX509_CRL_INVALID_FORMAT,
			       "CRL missing nextUpdate");
	return HX509_CRL_INVALID_FORMAT;
    }

    t = _hx509_Time2time_t(crl->tbsCertList.nextUpdate);
    if (t < time_now) {
	hx509_set_error_string(context, 0, HX509_CRL_USED_AFTER_TIME,
			       "CRL used after time");
	return HX509_CRL_USED_AFTER_TIME;
    }

    _hx509_query_clear(&q);

    /*
     * If it's the signer have CRLSIGN bit set, use that as the signer
     * cert for the certificate, otherwise, search for a certificate.
     */
    if (_hx509_check_key_usage(context, parent, 1 << 6, FALSE) == 0) {
	signer = hx509_cert_ref(parent);
    } else {
	q.match = HX509_QUERY_MATCH_SUBJECT_NAME;
	q.match |= HX509_QUERY_KU_CRLSIGN;
	q.subject_name = &crl->tbsCertList.issuer;

	ret = hx509_certs_find(context, certs, &q, &signer);
	if (ret) {
	    hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
				   "Failed to find certificate for CRL");
	    return ret;
	}
    }

    ret = _hx509_verify_signature_bitstring(context,
					    signer,
					    &crl->signatureAlgorithm,
					    &crl->tbsCertList._save,
					    &crl->signatureValue);
    if (ret) {
	hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
			       "CRL signature invalid");
	goto out;
    }

    /*
     * If signer is not CA cert, need to check revoke status of this
     * CRL signing cert too, this include all parent CRL signer cert
     * up to the root *sigh*, assume root at least hve CERTSIGN flag
     * set.
     */
    while (_hx509_check_key_usage(context, signer, 1 << 5, TRUE)) {
	hx509_cert crl_parent;

	_hx509_query_clear(&q);

	q.match = HX509_QUERY_MATCH_SUBJECT_NAME;
	q.match |= HX509_QUERY_KU_CRLSIGN;
	q.subject_name = &_hx509_get_cert(signer)->tbsCertificate.issuer;

	ret = hx509_certs_find(context, certs, &q, &crl_parent);
	if (ret) {
	    hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
				   "Failed to find parent of CRL signer");
	    goto out;
	}

	ret = hx509_revoke_verify(context,
				  ctx,
				  certs,
				  time_now,
				  signer,
				  crl_parent);
	hx509_cert_free(signer);
	signer = crl_parent;
	if (ret) {
	    hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
				   "Failed to verify revoke "
				   "status of CRL signer");
	    goto out;
	}
    }

out:
    hx509_cert_free(signer);

    return ret;
}
Ejemplo n.º 5
0
static int
verify_ocsp(hx509_context context,
	    struct revoke_ocsp *ocsp,
	    time_t time_now,
	    hx509_certs certs,
	    hx509_cert parent)
{
    hx509_cert signer = NULL;
    hx509_query q;
    int ret;

    _hx509_query_clear(&q);

    /*
     * Need to match on issuer too in case there are two CA that have
     * issued the same name to a certificate. One example of this is
     * the www.openvalidation.org test's ocsp validator.
     */

    q.match = HX509_QUERY_MATCH_ISSUER_NAME;
    q.issuer_name = &_hx509_get_cert(parent)->tbsCertificate.issuer;

    switch(ocsp->ocsp.tbsResponseData.responderID.element) {
    case choice_OCSPResponderID_byName:
	q.match |= HX509_QUERY_MATCH_SUBJECT_NAME;
	q.subject_name = &ocsp->ocsp.tbsResponseData.responderID.u.byName;
	break;
    case choice_OCSPResponderID_byKey:
	q.match |= HX509_QUERY_MATCH_KEY_HASH_SHA1;
	q.keyhash_sha1 = &ocsp->ocsp.tbsResponseData.responderID.u.byKey;
	break;
    }

    ret = hx509_certs_find(context, certs, &q, &signer);
    if (ret && ocsp->certs)
	ret = hx509_certs_find(context, ocsp->certs, &q, &signer);
    if (ret)
	goto out;

    /*
     * If signer certificate isn't the CA certificate, lets check the
     * it is the CA that signed the signer certificate and the OCSP EKU
     * is set.
     */
    if (hx509_cert_cmp(signer, parent) != 0) {
	Certificate *p = _hx509_get_cert(parent);
	Certificate *s = _hx509_get_cert(signer);

	ret = _hx509_cert_is_parent_cmp(s, p, 0);
	if (ret != 0) {
	    ret = HX509_PARENT_NOT_CA;
	    hx509_set_error_string(context, 0, ret, "Revoke OCSP signer is "
				   "doesn't have CA as signer certificate");
	    goto out;
	}

	ret = _hx509_verify_signature_bitstring(context,
						parent,
						&s->signatureAlgorithm,
						&s->tbsCertificate._save,
						&s->signatureValue);
	if (ret) {
	    hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
				   "OCSP signer signature invalid");
	    goto out;
	}

	ret = hx509_cert_check_eku(context, signer,
				   &asn1_oid_id_pkix_kp_OCSPSigning, 0);
	if (ret)
	    goto out;
    }

    ret = _hx509_verify_signature_bitstring(context,
					    signer,
					    &ocsp->ocsp.signatureAlgorithm,
					    &ocsp->ocsp.tbsResponseData._save,
					    &ocsp->ocsp.signature);
    if (ret) {
	hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
			       "OCSP signature invalid");
	goto out;
    }

    ocsp->signer = signer;
    signer = NULL;
out:
    if (signer)
	hx509_cert_free(signer);

    return ret;
}