2 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 RCSID("$Id: revoke.c 20871 2007-06-03 21:22:51Z lha $");
40 CRLCertificateList crl;
47 OCSPBasicOCSPResponse ocsp;
53 struct hx509_revoke_ctx_data {
55 struct revoke_crl *val;
59 struct revoke_ocsp *val;
65 hx509_revoke_init(hx509_context context, hx509_revoke_ctx *ctx)
67 *ctx = calloc(1, sizeof(**ctx));
72 (*ctx)->crls.val = NULL;
73 (*ctx)->ocsps.len = 0;
74 (*ctx)->ocsps.val = NULL;
80 free_ocsp(struct revoke_ocsp *ocsp)
83 free_OCSPBasicOCSPResponse(&ocsp->ocsp);
84 hx509_certs_free(&ocsp->certs);
85 hx509_cert_free(ocsp->signer);
89 hx509_revoke_free(hx509_revoke_ctx *ctx)
93 if (ctx == NULL || *ctx == NULL)
96 for (i = 0; i < (*ctx)->crls.len; i++) {
97 free((*ctx)->crls.val[i].path);
98 free_CRLCertificateList(&(*ctx)->crls.val[i].crl);
101 for (i = 0; i < (*ctx)->ocsps.len; i++)
102 free_ocsp(&(*ctx)->ocsps.val[i]);
103 free((*ctx)->ocsps.val);
105 free((*ctx)->crls.val);
107 memset(*ctx, 0, sizeof(**ctx));
113 verify_ocsp(hx509_context context,
114 struct revoke_ocsp *ocsp,
119 hx509_cert signer = NULL;
123 _hx509_query_clear(&q);
126 * Need to match on issuer too in case there are two CA that have
127 * issued the same name to a certificate. One example of this is
128 * the www.openvalidation.org test's ocsp validator.
131 q.match = HX509_QUERY_MATCH_ISSUER_NAME;
132 q.issuer_name = &_hx509_get_cert(parent)->tbsCertificate.issuer;
134 switch(ocsp->ocsp.tbsResponseData.responderID.element) {
135 case choice_OCSPResponderID_byName:
136 q.match |= HX509_QUERY_MATCH_SUBJECT_NAME;
137 q.subject_name = &ocsp->ocsp.tbsResponseData.responderID.u.byName;
139 case choice_OCSPResponderID_byKey:
140 q.match |= HX509_QUERY_MATCH_KEY_HASH_SHA1;
141 q.keyhash_sha1 = &ocsp->ocsp.tbsResponseData.responderID.u.byKey;
145 ret = hx509_certs_find(context, certs, &q, &signer);
146 if (ret && ocsp->certs)
147 ret = hx509_certs_find(context, ocsp->certs, &q, &signer);
152 * If signer certificate isn't the CA certificate, lets check the
153 * its the CA that signed the signer certificate and the OCSP EKU
156 if (hx509_cert_cmp(signer, parent) != 0) {
157 Certificate *p = _hx509_get_cert(parent);
158 Certificate *s = _hx509_get_cert(signer);
160 ret = _hx509_cert_is_parent_cmp(s, p, 0);
162 ret = HX509_PARENT_NOT_CA;
163 hx509_set_error_string(context, 0, ret, "Revoke OSCP signer is "
164 "doesn't have CA as signer certificate");
168 ret = _hx509_verify_signature_bitstring(context,
170 &s->signatureAlgorithm,
171 &s->tbsCertificate._save,
174 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
175 "OSCP signer signature invalid");
179 ret = hx509_cert_check_eku(context, signer,
180 oid_id_pkix_kp_OCSPSigning(), 0);
185 ret = _hx509_verify_signature_bitstring(context,
186 _hx509_get_cert(signer),
187 &ocsp->ocsp.signatureAlgorithm,
188 &ocsp->ocsp.tbsResponseData._save,
189 &ocsp->ocsp.signature);
191 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
192 "OSCP signature invalid");
196 ocsp->signer = signer;
200 hx509_cert_free(signer);
210 parse_ocsp_basic(const void *data, size_t length, OCSPBasicOCSPResponse *basic)
216 memset(basic, 0, sizeof(*basic));
218 ret = decode_OCSPResponse(data, length, &resp, &size);
221 if (length != size) {
222 free_OCSPResponse(&resp);
223 return ASN1_EXTRA_DATA;
226 switch (resp.responseStatus) {
230 free_OCSPResponse(&resp);
231 return HX509_REVOKE_WRONG_DATA;
234 if (resp.responseBytes == NULL) {
235 free_OCSPResponse(&resp);
239 ret = der_heim_oid_cmp(&resp.responseBytes->responseType,
240 oid_id_pkix_ocsp_basic());
242 free_OCSPResponse(&resp);
243 return HX509_REVOKE_WRONG_DATA;
246 ret = decode_OCSPBasicOCSPResponse(resp.responseBytes->response.data,
247 resp.responseBytes->response.length,
251 free_OCSPResponse(&resp);
254 if (size != resp.responseBytes->response.length) {
255 free_OCSPResponse(&resp);
256 free_OCSPBasicOCSPResponse(basic);
257 return ASN1_EXTRA_DATA;
259 free_OCSPResponse(&resp);
269 load_ocsp(hx509_context context, struct revoke_ocsp *ocsp)
271 OCSPBasicOCSPResponse basic;
272 hx509_certs certs = NULL;
278 ret = _hx509_map_file(ocsp->path, &data, &length, &sb);
282 ret = parse_ocsp_basic(data, length, &basic);
283 _hx509_unmap_file(data, length);
285 hx509_set_error_string(context, 0, ret,
286 "Failed to parse OCSP response");
293 ret = hx509_certs_init(context, "MEMORY:ocsp-certs", 0,
296 free_OCSPBasicOCSPResponse(&basic);
300 for (i = 0; i < basic.certs->len; i++) {
303 ret = hx509_cert_init(context, &basic.certs->val[i], &c);
307 ret = hx509_certs_add(context, certs, c);
314 ocsp->last_modfied = sb.st_mtime;
316 free_OCSPBasicOCSPResponse(&ocsp->ocsp);
317 hx509_certs_free(&ocsp->certs);
318 hx509_cert_free(ocsp->signer);
328 hx509_revoke_add_ocsp(hx509_context context,
329 hx509_revoke_ctx ctx,
336 if (strncmp(path, "FILE:", 5) != 0) {
337 hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
338 "unsupport type in %s", path);
339 return HX509_UNSUPPORTED_OPERATION;
344 for (i = 0; i < ctx->ocsps.len; i++) {
345 if (strcmp(ctx->ocsps.val[0].path, path) == 0)
349 data = realloc(ctx->ocsps.val,
350 (ctx->ocsps.len + 1) * sizeof(ctx->ocsps.val[0]));
352 hx509_clear_error_string(context);
356 ctx->ocsps.val = data;
358 memset(&ctx->ocsps.val[ctx->ocsps.len], 0,
359 sizeof(ctx->ocsps.val[0]));
361 ctx->ocsps.val[ctx->ocsps.len].path = strdup(path);
362 if (ctx->ocsps.val[ctx->ocsps.len].path == NULL) {
363 hx509_clear_error_string(context);
367 ret = load_ocsp(context, &ctx->ocsps.val[ctx->ocsps.len]);
369 free(ctx->ocsps.val[ctx->ocsps.len].path);
382 verify_crl(hx509_context context,
383 CRLCertificateList *crl,
393 t = _hx509_Time2time_t(&crl->tbsCertList.thisUpdate);
395 return HX509_CRL_USED_BEFORE_TIME;
397 if (crl->tbsCertList.nextUpdate == NULL)
398 return HX509_CRL_INVALID_FORMAT;
400 t = _hx509_Time2time_t(crl->tbsCertList.nextUpdate);
402 return HX509_CRL_USED_AFTER_TIME;
404 _hx509_query_clear(&q);
406 q.match = HX509_QUERY_MATCH_SUBJECT_NAME;
407 q.subject_name = &crl->tbsCertList.issuer;
409 ret = hx509_certs_find(context, certs, &q, &signer);
413 /* verify is parent or CRLsigner */
414 if (hx509_cert_cmp(signer, parent) != 0) {
415 Certificate *p = _hx509_get_cert(parent);
416 Certificate *s = _hx509_get_cert(signer);
418 ret = _hx509_cert_is_parent_cmp(s, p, 0);
420 ret = HX509_PARENT_NOT_CA;
421 hx509_set_error_string(context, 0, ret, "Revoke CRL signer is "
422 "doesn't have CA as signer certificate");
426 ret = _hx509_verify_signature_bitstring(context,
428 &s->signatureAlgorithm,
429 &s->tbsCertificate._save,
432 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
433 "CRL signer signature invalid");
437 ret = _hx509_check_key_usage(context, signer, 1 << 6, TRUE); /* crl */
442 ret = _hx509_verify_signature_bitstring(context,
443 _hx509_get_cert(signer),
444 &crl->signatureAlgorithm,
445 &crl->tbsCertList._save,
446 &crl->signatureValue);
448 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
449 "CRL signature invalid");
454 hx509_cert_free(signer);
460 load_crl(const char *path, time_t *t, CRLCertificateList *crl)
467 memset(crl, 0, sizeof(*crl));
469 ret = _hx509_map_file(path, &data, &length, &sb);
475 ret = decode_CRLCertificateList(data, length, crl, &size);
476 _hx509_unmap_file(data, length);
480 /* check signature is aligned */
481 if (crl->signatureValue.length & 7) {
482 free_CRLCertificateList(crl);
483 return HX509_CRYPTO_SIG_INVALID_FORMAT;
489 hx509_revoke_add_crl(hx509_context context,
490 hx509_revoke_ctx ctx,
497 if (strncmp(path, "FILE:", 5) != 0) {
498 hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
499 "unsupport type in %s", path);
500 return HX509_UNSUPPORTED_OPERATION;
506 for (i = 0; i < ctx->crls.len; i++) {
507 if (strcmp(ctx->crls.val[0].path, path) == 0)
511 data = realloc(ctx->crls.val,
512 (ctx->crls.len + 1) * sizeof(ctx->crls.val[0]));
514 hx509_clear_error_string(context);
517 ctx->crls.val = data;
519 memset(&ctx->crls.val[ctx->crls.len], 0, sizeof(ctx->crls.val[0]));
521 ctx->crls.val[ctx->crls.len].path = strdup(path);
522 if (ctx->crls.val[ctx->crls.len].path == NULL) {
523 hx509_clear_error_string(context);
528 &ctx->crls.val[ctx->crls.len].last_modfied,
529 &ctx->crls.val[ctx->crls.len].crl);
531 free(ctx->crls.val[ctx->crls.len].path);
542 hx509_revoke_verify(hx509_context context,
543 hx509_revoke_ctx ctx,
547 hx509_cert parent_cert)
549 const Certificate *c = _hx509_get_cert(cert);
550 const Certificate *p = _hx509_get_cert(parent_cert);
551 unsigned long i, j, k;
554 for (i = 0; i < ctx->ocsps.len; i++) {
555 struct revoke_ocsp *ocsp = &ctx->ocsps.val[i];
558 /* check this ocsp apply to this cert */
560 /* check if there is a newer version of the file */
561 ret = stat(ocsp->path, &sb);
562 if (ret == 0 && ocsp->last_modfied != sb.st_mtime) {
563 ret = load_ocsp(context, ocsp);
568 /* verify signature in ocsp if not already done */
569 if (ocsp->signer == NULL) {
570 ret = verify_ocsp(context, ocsp, now, certs, parent_cert);
575 for (i = 0; i < ocsp->ocsp.tbsResponseData.responses.len; i++) {
576 heim_octet_string os;
578 ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[i].certID.serialNumber,
579 &c->tbsCertificate.serialNumber);
583 /* verify issuer hashes hash */
584 ret = _hx509_verify_signature(context,
586 &ocsp->ocsp.tbsResponseData.responses.val[i].certID.hashAlgorithm,
587 &c->tbsCertificate.issuer._save,
588 &ocsp->ocsp.tbsResponseData.responses.val[i].certID.issuerNameHash);
592 os.data = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
593 os.length = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
595 ret = _hx509_verify_signature(context,
597 &ocsp->ocsp.tbsResponseData.responses.val[i].certID.hashAlgorithm,
599 &ocsp->ocsp.tbsResponseData.responses.val[i].certID.issuerKeyHash);
603 switch (ocsp->ocsp.tbsResponseData.responses.val[i].certStatus.element) {
604 case choice_OCSPCertStatus_good:
606 case choice_OCSPCertStatus_revoked:
607 case choice_OCSPCertStatus_unknown:
611 /* don't allow the update to be in the future */
612 if (ocsp->ocsp.tbsResponseData.responses.val[i].thisUpdate >
613 now + context->ocsp_time_diff)
616 /* don't allow the next updte to be in the past */
617 if (ocsp->ocsp.tbsResponseData.responses.val[i].nextUpdate) {
618 if (*ocsp->ocsp.tbsResponseData.responses.val[i].nextUpdate < now)
621 /* Should force a refetch, but can we ? */;
627 for (i = 0; i < ctx->crls.len; i++) {
628 struct revoke_crl *crl = &ctx->crls.val[i];
631 /* check if cert.issuer == crls.val[i].crl.issuer */
632 ret = _hx509_name_cmp(&c->tbsCertificate.issuer,
633 &crl->crl.tbsCertList.issuer);
637 ret = stat(crl->path, &sb);
638 if (ret == 0 && crl->last_modfied != sb.st_mtime) {
639 CRLCertificateList cl;
641 ret = load_crl(crl->path, &crl->last_modfied, &cl);
643 free_CRLCertificateList(&crl->crl);
649 /* verify signature in crl if not already done */
650 if (crl->verified == 0) {
651 ret = verify_crl(context, &crl->crl, now, certs, parent_cert);
657 if (crl->crl.tbsCertList.crlExtensions)
658 for (j = 0; j < crl->crl.tbsCertList.crlExtensions->len; j++)
659 if (crl->crl.tbsCertList.crlExtensions->val[j].critical)
660 return HX509_CRL_UNKNOWN_EXTENSION;
662 if (crl->crl.tbsCertList.revokedCertificates == NULL)
665 /* check if cert is in crl */
666 for (j = 0; j < crl->crl.tbsCertList.revokedCertificates->len; j++) {
669 ret = der_heim_integer_cmp(&crl->crl.tbsCertList.revokedCertificates->val[j].userCertificate,
670 &c->tbsCertificate.serialNumber);
674 t = _hx509_Time2time_t(&crl->crl.tbsCertList.revokedCertificates->val[j].revocationDate);
678 if (crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions)
679 for (k = 0; k < crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions->len; k++)
680 if (crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions->val[k].critical)
681 return HX509_CRL_UNKNOWN_EXTENSION;
683 return HX509_CRL_CERT_REVOKED;
690 if (context->flags & HX509_CTX_VERIFY_MISSING_OK)
692 return HX509_REVOKE_STATUS_MISSING;
695 struct ocsp_add_ctx {
698 const AlgorithmIdentifier *digest;
703 add_to_req(hx509_context context, void *ptr, hx509_cert cert)
705 struct ocsp_add_ctx *ctx = ptr;
706 OCSPInnerRequest *one;
707 hx509_cert parent = NULL;
708 Certificate *p, *c = _hx509_get_cert(cert);
709 heim_octet_string os;
714 d = realloc(ctx->req->requestList.val,
715 sizeof(ctx->req->requestList.val[0]) *
716 (ctx->req->requestList.len + 1));
719 ctx->req->requestList.val = d;
721 one = &ctx->req->requestList.val[ctx->req->requestList.len];
722 memset(one, 0, sizeof(*one));
724 _hx509_query_clear(&q);
726 q.match |= HX509_QUERY_FIND_ISSUER_CERT;
729 ret = hx509_certs_find(context, ctx->certs, &q, &parent);
734 if (hx509_cert_cmp(ctx->parent, parent) != 0) {
735 ret = HX509_REVOKE_NOT_SAME_PARENT;
736 hx509_set_error_string(context, 0, ret,
737 "Not same parent certifate as "
738 "last certificate in request");
742 ctx->parent = hx509_cert_ref(parent);
744 p = _hx509_get_cert(parent);
746 ret = copy_AlgorithmIdentifier(ctx->digest, &one->reqCert.hashAlgorithm);
750 ret = _hx509_create_signature(context,
752 &one->reqCert.hashAlgorithm,
753 &c->tbsCertificate.issuer._save,
755 &one->reqCert.issuerNameHash);
759 os.data = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
761 p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
763 ret = _hx509_create_signature(context,
765 &one->reqCert.hashAlgorithm,
768 &one->reqCert.issuerKeyHash);
772 ret = copy_CertificateSerialNumber(&c->tbsCertificate.serialNumber,
773 &one->reqCert.serialNumber);
777 ctx->req->requestList.len++;
779 hx509_cert_free(parent);
781 free_OCSPInnerRequest(one);
782 memset(one, 0, sizeof(*one));
790 hx509_ocsp_request(hx509_context context,
791 hx509_certs reqcerts,
794 const AlgorithmIdentifier *digest,
795 heim_octet_string *request,
796 heim_octet_string *nonce)
801 struct ocsp_add_ctx ctx;
804 memset(&req, 0, sizeof(req));
807 digest = _hx509_crypto_default_digest_alg;
809 ctx.req = &req.tbsRequest;
814 ret = hx509_certs_iter(context, reqcerts, add_to_req, &ctx);
815 hx509_cert_free(ctx.parent);
817 free_OCSPRequest(&req);
823 req.tbsRequest.requestExtensions =
824 calloc(1, sizeof(*req.tbsRequest.requestExtensions));
825 if (req.tbsRequest.requestExtensions == NULL) {
826 free_OCSPRequest(&req);
830 es = req.tbsRequest.requestExtensions;
833 es->val = calloc(es->len, sizeof(es->val[0]));
835 ret = der_copy_oid(oid_id_pkix_ocsp_nonce(), &es->val[0].extnID);
839 es->val[0].extnValue.data = malloc(10);
840 if (es->val[0].extnValue.data == NULL) {
841 free_OCSPRequest(&req);
844 es->val[0].extnValue.length = 10;
846 ret = RAND_bytes(es->val[0].extnValue.data,
847 es->val[0].extnValue.length);
849 free_OCSPRequest(&req);
850 return HX509_CRYPTO_INTERNAL_ERROR;
854 ASN1_MALLOC_ENCODE(OCSPRequest, request->data, request->length,
856 free_OCSPRequest(&req);
859 if (size != request->length)
860 _hx509_abort("internal ASN.1 encoder error");
867 printable_time(time_t t)
870 strlcpy(s, ctime(&t)+ 4, sizeof(s));
876 hx509_revoke_ocsp_print(hx509_context context, const char *path, FILE *out)
878 struct revoke_ocsp ocsp;
884 memset(&ocsp, 0, sizeof(ocsp));
886 ocsp.path = strdup(path);
887 if (ocsp.path == NULL)
890 ret = load_ocsp(context, &ocsp);
896 fprintf(out, "signer: ");
898 switch(ocsp.ocsp.tbsResponseData.responderID.element) {
899 case choice_OCSPResponderID_byName: {
902 _hx509_name_from_Name(&ocsp.ocsp.tbsResponseData.responderID.u.byName, &n);
903 hx509_name_to_string(n, &s);
905 fprintf(out, " byName: %s\n", s);
909 case choice_OCSPResponderID_byKey: {
911 hex_encode(ocsp.ocsp.tbsResponseData.responderID.u.byKey.data,
912 ocsp.ocsp.tbsResponseData.responderID.u.byKey.length,
914 fprintf(out, " byKey: %s\n", s);
919 _hx509_abort("choice_OCSPResponderID unknown");
923 fprintf(out, "producedAt: %s\n",
924 printable_time(ocsp.ocsp.tbsResponseData.producedAt));
926 fprintf(out, "replies: %d\n", ocsp.ocsp.tbsResponseData.responses.len);
928 for (i = 0; i < ocsp.ocsp.tbsResponseData.responses.len; i++) {
930 switch (ocsp.ocsp.tbsResponseData.responses.val[i].certStatus.element) {
931 case choice_OCSPCertStatus_good:
934 case choice_OCSPCertStatus_revoked:
937 case choice_OCSPCertStatus_unknown:
941 status = "element unknown";
944 fprintf(out, "\t%d. status: %s\n", i, status);
946 fprintf(out, "\tthisUpdate: %s\n",
947 printable_time(ocsp.ocsp.tbsResponseData.responses.val[i].thisUpdate));
948 if (ocsp.ocsp.tbsResponseData.responses.val[i].nextUpdate)
949 fprintf(out, "\tproducedAt: %s\n",
950 printable_time(ocsp.ocsp.tbsResponseData.responses.val[i].thisUpdate));
954 fprintf(out, "appended certs:\n");
956 ret = hx509_certs_iter(context, ocsp.certs, hx509_ci_print_names, out);
963 * Verify that the `cert' is part of the OCSP reply and its not
964 * expired. Doesn't verify signature the OCSP reply or its done by a
965 * authorized sender, that is assumed to be already done.
969 hx509_ocsp_verify(hx509_context context,
973 const void *data, size_t length,
976 const Certificate *c = _hx509_get_cert(cert);
977 OCSPBasicOCSPResponse basic;
985 ret = parse_ocsp_basic(data, length, &basic);
987 hx509_set_error_string(context, 0, ret,
988 "Failed to parse OCSP response");
992 for (i = 0; i < basic.tbsResponseData.responses.len; i++) {
994 ret = der_heim_integer_cmp(&basic.tbsResponseData.responses.val[i].certID.serialNumber,
995 &c->tbsCertificate.serialNumber);
999 /* verify issuer hashes hash */
1000 ret = _hx509_verify_signature(context,
1002 &basic.tbsResponseData.responses.val[i].certID.hashAlgorithm,
1003 &c->tbsCertificate.issuer._save,
1004 &basic.tbsResponseData.responses.val[i].certID.issuerNameHash);
1008 switch (basic.tbsResponseData.responses.val[i].certStatus.element) {
1009 case choice_OCSPCertStatus_good:
1011 case choice_OCSPCertStatus_revoked:
1012 case choice_OCSPCertStatus_unknown:
1016 /* don't allow the update to be in the future */
1017 if (basic.tbsResponseData.responses.val[i].thisUpdate >
1018 now + context->ocsp_time_diff)
1021 /* don't allow the next update to be in the past */
1022 if (basic.tbsResponseData.responses.val[i].nextUpdate) {
1023 if (*basic.tbsResponseData.responses.val[i].nextUpdate < now)
1025 *expiration = *basic.tbsResponseData.responses.val[i].nextUpdate;
1029 free_OCSPBasicOCSPResponse(&basic);
1033 free_OCSPBasicOCSPResponse(&basic);
1039 ret = hx509_cert_get_subject(cert, &name);
1041 hx509_clear_error_string(context);
1044 ret = hx509_name_to_string(name, &subject);
1045 hx509_name_free(&name);
1047 hx509_clear_error_string(context);
1050 hx509_set_error_string(context, 0, HX509_CERT_NOT_IN_OCSP,
1051 "Certificate %s not in OCSP response "
1057 return HX509_CERT_NOT_IN_OCSP;
1061 hx509_certs revoked;
1066 hx509_crl_alloc(hx509_context context, hx509_crl *crl)
1070 *crl = calloc(1, sizeof(**crl));
1072 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1076 ret = hx509_certs_init(context, "MEMORY:crl", 0, NULL, &(*crl)->revoked);
1086 hx509_crl_add_revoked_certs(hx509_context context,
1090 return hx509_certs_merge(context, crl->revoked, certs);
1094 hx509_crl_lifetime(hx509_context context, hx509_crl crl, int delta)
1096 crl->expire = time(NULL) + delta;
1102 hx509_crl_free(hx509_context context, hx509_crl *crl)
1106 hx509_certs_free(&(*crl)->revoked);
1107 memset(*crl, 0, sizeof(**crl));
1113 add_revoked(hx509_context context, void *ctx, hx509_cert cert)
1115 TBSCRLCertList *c = ctx;
1120 num = c->revokedCertificates->len;
1121 ptr = realloc(c->revokedCertificates->val,
1122 (num + 1) * sizeof(c->revokedCertificates->val[0]));
1124 hx509_clear_error_string(context);
1127 c->revokedCertificates->val = ptr;
1129 ret = hx509_cert_get_serialnumber(cert,
1130 &c->revokedCertificates->val[num].userCertificate);
1132 hx509_clear_error_string(context);
1135 c->revokedCertificates->val[num].revocationDate.element =
1136 choice_Time_generalTime;
1137 c->revokedCertificates->val[num].revocationDate.u.generalTime =
1138 time(NULL) - 3600 * 24;
1139 c->revokedCertificates->val[num].crlEntryExtensions = NULL;
1141 c->revokedCertificates->len++;
1148 hx509_crl_sign(hx509_context context,
1151 heim_octet_string *os)
1153 const AlgorithmIdentifier *sigalg = _hx509_crypto_default_sig_alg;
1154 CRLCertificateList c;
1157 hx509_private_key signerkey;
1159 memset(&c, 0, sizeof(c));
1161 signerkey = _hx509_cert_private_key(signer);
1162 if (signerkey == NULL) {
1163 ret = HX509_PRIVATE_KEY_MISSING;
1164 hx509_set_error_string(context, 0, ret,
1165 "Private key missing for CRL signing");
1169 c.tbsCertList.version = malloc(sizeof(*c.tbsCertList.version));
1170 if (c.tbsCertList.version == NULL) {
1171 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1175 *c.tbsCertList.version = 1;
1177 ret = copy_AlgorithmIdentifier(sigalg, &c.tbsCertList.signature);
1179 hx509_clear_error_string(context);
1183 ret = copy_Name(&_hx509_get_cert(signer)->tbsCertificate.issuer,
1184 &c.tbsCertList.issuer);
1186 hx509_clear_error_string(context);
1190 c.tbsCertList.thisUpdate.element = choice_Time_generalTime;
1191 c.tbsCertList.thisUpdate.u.generalTime = time(NULL) - 24 * 3600;
1193 c.tbsCertList.nextUpdate = malloc(sizeof(*c.tbsCertList.nextUpdate));
1194 if (c.tbsCertList.nextUpdate == NULL) {
1195 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1201 time_t next = crl->expire;
1203 next = time(NULL) + 24 * 3600 * 365;
1205 c.tbsCertList.nextUpdate->element = choice_Time_generalTime;
1206 c.tbsCertList.nextUpdate->u.generalTime = next;
1209 c.tbsCertList.revokedCertificates =
1210 calloc(1, sizeof(*c.tbsCertList.revokedCertificates));
1211 if (c.tbsCertList.revokedCertificates == NULL) {
1212 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1216 c.tbsCertList.crlExtensions = NULL;
1218 ret = hx509_certs_iter(context, crl->revoked, add_revoked, &c.tbsCertList);
1222 /* if not revoked certs, remove OPTIONAL entry */
1223 if (c.tbsCertList.revokedCertificates->len == 0) {
1224 free(c.tbsCertList.revokedCertificates);
1225 c.tbsCertList.revokedCertificates = NULL;
1228 ASN1_MALLOC_ENCODE(TBSCRLCertList, os->data, os->length,
1229 &c.tbsCertList, &size, ret);
1231 hx509_set_error_string(context, 0, ret, "failed to encode tbsCRL");
1234 if (size != os->length)
1235 _hx509_abort("internal ASN.1 encoder error");
1238 ret = _hx509_create_signature_bitstring(context,
1242 &c.signatureAlgorithm,
1246 ASN1_MALLOC_ENCODE(CRLCertificateList, os->data, os->length,
1248 free_CRLCertificateList(&c);
1250 hx509_set_error_string(context, 0, ret, "failed to encode CRL");
1253 if (size != os->length)
1254 _hx509_abort("internal ASN.1 encoder error");
1259 free_CRLCertificateList(&c);