r23456: Update Samba4 to current lorikeet-heimdal.
[ab/samba.git/.git] / source4 / heimdal / lib / hx509 / revoke.c
1 /*
2  * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden). 
4  * All rights reserved. 
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met: 
9  *
10  * 1. Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer. 
12  *
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. 
16  *
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. 
20  *
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 
31  * SUCH DAMAGE. 
32  */
33
34 #include "hx_locl.h"
35 RCSID("$Id: revoke.c 20871 2007-06-03 21:22:51Z lha $");
36
37 struct revoke_crl {
38     char *path;
39     time_t last_modfied;
40     CRLCertificateList crl;
41     int verified;
42 };
43
44 struct revoke_ocsp {
45     char *path;
46     time_t last_modfied;
47     OCSPBasicOCSPResponse ocsp;
48     hx509_certs certs;
49     hx509_cert signer;
50 };
51
52
53 struct hx509_revoke_ctx_data {
54     struct {
55         struct revoke_crl *val;
56         size_t len;
57     } crls;
58     struct {
59         struct revoke_ocsp *val;
60         size_t len;
61     } ocsps;
62 };
63
64 int
65 hx509_revoke_init(hx509_context context, hx509_revoke_ctx *ctx)
66 {
67     *ctx = calloc(1, sizeof(**ctx));
68     if (*ctx == NULL)
69         return ENOMEM;
70
71     (*ctx)->crls.len = 0;
72     (*ctx)->crls.val = NULL;
73     (*ctx)->ocsps.len = 0;
74     (*ctx)->ocsps.val = NULL;
75
76     return 0;
77 }
78
79 static void
80 free_ocsp(struct revoke_ocsp *ocsp)
81 {
82     free(ocsp->path);
83     free_OCSPBasicOCSPResponse(&ocsp->ocsp);
84     hx509_certs_free(&ocsp->certs);
85     hx509_cert_free(ocsp->signer);
86 }
87
88 void
89 hx509_revoke_free(hx509_revoke_ctx *ctx)
90 {
91     size_t i ;
92
93     if (ctx == NULL || *ctx == NULL)
94         return;
95
96     for (i = 0; i < (*ctx)->crls.len; i++) {
97         free((*ctx)->crls.val[i].path);
98         free_CRLCertificateList(&(*ctx)->crls.val[i].crl);
99     }
100
101     for (i = 0; i < (*ctx)->ocsps.len; i++)
102         free_ocsp(&(*ctx)->ocsps.val[i]);
103     free((*ctx)->ocsps.val);
104
105     free((*ctx)->crls.val);
106
107     memset(*ctx, 0, sizeof(**ctx));
108     free(*ctx);
109     *ctx = NULL;
110 }
111
112 static int
113 verify_ocsp(hx509_context context,
114             struct revoke_ocsp *ocsp,
115             time_t time_now,
116             hx509_certs certs,
117             hx509_cert parent)
118 {
119     hx509_cert signer = NULL;
120     hx509_query q;
121     int ret;
122         
123     _hx509_query_clear(&q);
124         
125     /*
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.
129      */
130
131     q.match = HX509_QUERY_MATCH_ISSUER_NAME;
132     q.issuer_name = &_hx509_get_cert(parent)->tbsCertificate.issuer;
133
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;
138         break;
139     case choice_OCSPResponderID_byKey:
140         q.match |= HX509_QUERY_MATCH_KEY_HASH_SHA1;
141         q.keyhash_sha1 = &ocsp->ocsp.tbsResponseData.responderID.u.byKey;
142         break;
143     }
144         
145     ret = hx509_certs_find(context, certs, &q, &signer);
146     if (ret && ocsp->certs)
147         ret = hx509_certs_find(context, ocsp->certs, &q, &signer);
148     if (ret)
149         goto out;
150
151     /*
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
154      * is set.
155      */
156     if (hx509_cert_cmp(signer, parent) != 0) {
157         Certificate *p = _hx509_get_cert(parent);
158         Certificate *s = _hx509_get_cert(signer);
159
160         ret = _hx509_cert_is_parent_cmp(s, p, 0);
161         if (ret != 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");
165             goto out;
166         }
167
168         ret = _hx509_verify_signature_bitstring(context,
169                                                 p,
170                                                 &s->signatureAlgorithm,
171                                                 &s->tbsCertificate._save,
172                                                 &s->signatureValue);
173         if (ret) {
174             hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
175                                    "OSCP signer signature invalid");
176             goto out;
177         }
178
179         ret = hx509_cert_check_eku(context, signer, 
180                                    oid_id_pkix_kp_OCSPSigning(), 0);
181         if (ret)
182             goto out;
183     }
184
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);
190     if (ret) {
191         hx509_set_error_string(context, HX509_ERROR_APPEND, ret, 
192                                "OSCP signature invalid");
193         goto out;
194     }
195
196     ocsp->signer = signer;
197     signer = NULL;
198 out:
199     if (signer)
200         hx509_cert_free(signer);
201
202     return ret;
203 }
204
205 /*
206  *
207  */
208
209 static int
210 parse_ocsp_basic(const void *data, size_t length, OCSPBasicOCSPResponse *basic)
211 {
212     OCSPResponse resp;
213     size_t size;
214     int ret;
215
216     memset(basic, 0, sizeof(*basic));
217
218     ret = decode_OCSPResponse(data, length, &resp, &size);
219     if (ret)
220         return ret;
221     if (length != size) {
222         free_OCSPResponse(&resp);
223         return ASN1_EXTRA_DATA;
224     }
225
226     switch (resp.responseStatus) {
227     case successful:
228         break;
229     default:
230         free_OCSPResponse(&resp);
231         return HX509_REVOKE_WRONG_DATA;
232     }
233
234     if (resp.responseBytes == NULL) {
235         free_OCSPResponse(&resp);
236         return EINVAL;
237     }
238
239     ret = der_heim_oid_cmp(&resp.responseBytes->responseType, 
240                            oid_id_pkix_ocsp_basic());
241     if (ret != 0) {
242         free_OCSPResponse(&resp);
243         return HX509_REVOKE_WRONG_DATA;
244     }
245
246     ret = decode_OCSPBasicOCSPResponse(resp.responseBytes->response.data,
247                                        resp.responseBytes->response.length,
248                                        basic,
249                                        &size);
250     if (ret) {
251         free_OCSPResponse(&resp);
252         return ret;
253     }
254     if (size != resp.responseBytes->response.length) {
255         free_OCSPResponse(&resp);
256         free_OCSPBasicOCSPResponse(basic);
257         return ASN1_EXTRA_DATA;
258     }
259     free_OCSPResponse(&resp);
260
261     return 0;
262 }
263
264 /*
265  *
266  */
267
268 static int
269 load_ocsp(hx509_context context, struct revoke_ocsp *ocsp)
270 {
271     OCSPBasicOCSPResponse basic;
272     hx509_certs certs = NULL;
273     size_t length;
274     struct stat sb;
275     void *data;
276     int ret;
277
278     ret = _hx509_map_file(ocsp->path, &data, &length, &sb);
279     if (ret)
280         return ret;
281
282     ret = parse_ocsp_basic(data, length, &basic);
283     _hx509_unmap_file(data, length);
284     if (ret) {
285         hx509_set_error_string(context, 0, ret,
286                                "Failed to parse OCSP response");
287         return ret;
288     }
289
290     if (basic.certs) {
291         int i;
292
293         ret = hx509_certs_init(context, "MEMORY:ocsp-certs", 0, 
294                                NULL, &certs);
295         if (ret) {
296             free_OCSPBasicOCSPResponse(&basic);
297             return ret;
298         }
299
300         for (i = 0; i < basic.certs->len; i++) {
301             hx509_cert c;
302             
303             ret = hx509_cert_init(context, &basic.certs->val[i], &c);
304             if (ret)
305                 continue;
306             
307             ret = hx509_certs_add(context, certs, c);
308             hx509_cert_free(c);
309             if (ret)
310                 continue;
311         }
312     }
313
314     ocsp->last_modfied = sb.st_mtime;
315
316     free_OCSPBasicOCSPResponse(&ocsp->ocsp);
317     hx509_certs_free(&ocsp->certs);
318     hx509_cert_free(ocsp->signer);
319
320     ocsp->ocsp = basic;
321     ocsp->certs = certs;
322     ocsp->signer = NULL;
323
324     return 0;
325 }
326
327 int
328 hx509_revoke_add_ocsp(hx509_context context,
329                       hx509_revoke_ctx ctx,
330                       const char *path)
331 {
332     void *data;
333     int ret;
334     size_t i;
335
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;
340     }
341
342     path += 5;
343
344     for (i = 0; i < ctx->ocsps.len; i++) {
345         if (strcmp(ctx->ocsps.val[0].path, path) == 0)
346             return 0;
347     }
348
349     data = realloc(ctx->ocsps.val, 
350                    (ctx->ocsps.len + 1) * sizeof(ctx->ocsps.val[0]));
351     if (data == NULL) {
352         hx509_clear_error_string(context);
353         return ENOMEM;
354     }
355
356     ctx->ocsps.val = data;
357
358     memset(&ctx->ocsps.val[ctx->ocsps.len], 0, 
359            sizeof(ctx->ocsps.val[0]));
360
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);
364         return ENOMEM;
365     }
366
367     ret = load_ocsp(context, &ctx->ocsps.val[ctx->ocsps.len]);
368     if (ret) {
369         free(ctx->ocsps.val[ctx->ocsps.len].path);
370         return ret;
371     }
372     ctx->ocsps.len++;
373
374     return ret;
375 }
376
377 /*
378  *
379  */
380
381 static int
382 verify_crl(hx509_context context,
383            CRLCertificateList *crl,
384            time_t time_now,
385            hx509_certs certs,
386            hx509_cert parent)
387 {
388     hx509_cert signer;
389     hx509_query q;
390     time_t t;
391     int ret;
392         
393     t = _hx509_Time2time_t(&crl->tbsCertList.thisUpdate);
394     if (t > time_now)
395         return HX509_CRL_USED_BEFORE_TIME;
396
397     if (crl->tbsCertList.nextUpdate == NULL)
398         return HX509_CRL_INVALID_FORMAT;
399
400     t = _hx509_Time2time_t(crl->tbsCertList.nextUpdate);
401     if (t < time_now)
402         return HX509_CRL_USED_AFTER_TIME;
403
404     _hx509_query_clear(&q);
405         
406     q.match = HX509_QUERY_MATCH_SUBJECT_NAME;
407     q.subject_name = &crl->tbsCertList.issuer;
408         
409     ret = hx509_certs_find(context, certs, &q, &signer);
410     if (ret)
411         return ret;
412
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);
417
418         ret = _hx509_cert_is_parent_cmp(s, p, 0);
419         if (ret != 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");
423             goto out;
424         }
425
426         ret = _hx509_verify_signature_bitstring(context,
427                                                 p,
428                                                 &s->signatureAlgorithm,
429                                                 &s->tbsCertificate._save,
430                                                 &s->signatureValue);
431         if (ret) {
432             hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
433                                    "CRL signer signature invalid");
434             goto out;
435         }
436
437         ret = _hx509_check_key_usage(context, signer, 1 << 6, TRUE); /* crl */
438         if (ret != 0)
439             goto out;
440     }
441
442     ret = _hx509_verify_signature_bitstring(context,
443                                             _hx509_get_cert(signer), 
444                                             &crl->signatureAlgorithm,
445                                             &crl->tbsCertList._save,
446                                             &crl->signatureValue);
447     if (ret) {
448         hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
449                                "CRL signature invalid");
450         goto out;
451     }
452
453 out:
454     hx509_cert_free(signer);
455
456     return ret;
457 }
458
459 static int
460 load_crl(const char *path, time_t *t, CRLCertificateList *crl)
461 {
462     size_t length, size;
463     struct stat sb;
464     void *data;
465     int ret;
466
467     memset(crl, 0, sizeof(*crl));
468
469     ret = _hx509_map_file(path, &data, &length, &sb);
470     if (ret)
471         return ret;
472
473     *t = sb.st_mtime;
474
475     ret = decode_CRLCertificateList(data, length, crl, &size);
476     _hx509_unmap_file(data, length);
477     if (ret)
478         return ret;
479
480     /* check signature is aligned */
481     if (crl->signatureValue.length & 7) {
482         free_CRLCertificateList(crl);
483         return HX509_CRYPTO_SIG_INVALID_FORMAT;
484     }
485     return 0;
486 }
487
488 int
489 hx509_revoke_add_crl(hx509_context context,
490                      hx509_revoke_ctx ctx,
491                      const char *path)
492 {
493     void *data;
494     size_t i;
495     int ret;
496
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;
501     }
502
503     
504     path += 5;
505
506     for (i = 0; i < ctx->crls.len; i++) {
507         if (strcmp(ctx->crls.val[0].path, path) == 0)
508             return 0;
509     }
510
511     data = realloc(ctx->crls.val, 
512                    (ctx->crls.len + 1) * sizeof(ctx->crls.val[0]));
513     if (data == NULL) {
514         hx509_clear_error_string(context);
515         return ENOMEM;
516     }
517     ctx->crls.val = data;
518
519     memset(&ctx->crls.val[ctx->crls.len], 0, sizeof(ctx->crls.val[0]));
520
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);
524         return ENOMEM;
525     }
526
527     ret = load_crl(path, 
528                    &ctx->crls.val[ctx->crls.len].last_modfied,
529                    &ctx->crls.val[ctx->crls.len].crl);
530     if (ret) {
531         free(ctx->crls.val[ctx->crls.len].path);
532         return ret;
533     }
534
535     ctx->crls.len++;
536
537     return ret;
538 }
539
540
541 int
542 hx509_revoke_verify(hx509_context context,
543                     hx509_revoke_ctx ctx,
544                     hx509_certs certs,
545                     time_t now,
546                     hx509_cert cert,
547                     hx509_cert parent_cert)
548 {
549     const Certificate *c = _hx509_get_cert(cert);
550     const Certificate *p = _hx509_get_cert(parent_cert);
551     unsigned long i, j, k;
552     int ret;
553
554     for (i = 0; i < ctx->ocsps.len; i++) {
555         struct revoke_ocsp *ocsp = &ctx->ocsps.val[i];
556         struct stat sb;
557
558         /* check this ocsp apply to this cert */
559
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);
564             if (ret)
565                 continue;
566         }
567
568         /* verify signature in ocsp if not already done */
569         if (ocsp->signer == NULL) {
570             ret = verify_ocsp(context, ocsp, now, certs, parent_cert);
571             if (ret)
572                 continue;
573         }
574
575         for (i = 0; i < ocsp->ocsp.tbsResponseData.responses.len; i++) {
576             heim_octet_string os;
577
578             ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[i].certID.serialNumber,
579                                    &c->tbsCertificate.serialNumber);
580             if (ret != 0)
581                 continue;
582             
583             /* verify issuer hashes hash */
584             ret = _hx509_verify_signature(context,
585                                           NULL,
586                                           &ocsp->ocsp.tbsResponseData.responses.val[i].certID.hashAlgorithm,
587                                           &c->tbsCertificate.issuer._save,
588                                           &ocsp->ocsp.tbsResponseData.responses.val[i].certID.issuerNameHash);
589             if (ret != 0)
590                 continue;
591
592             os.data = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
593             os.length = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
594
595             ret = _hx509_verify_signature(context,
596                                           NULL,
597                                           &ocsp->ocsp.tbsResponseData.responses.val[i].certID.hashAlgorithm,
598                                           &os,
599                                           &ocsp->ocsp.tbsResponseData.responses.val[i].certID.issuerKeyHash);
600             if (ret != 0)
601                 continue;
602
603             switch (ocsp->ocsp.tbsResponseData.responses.val[i].certStatus.element) {
604             case choice_OCSPCertStatus_good:
605                 break;
606             case choice_OCSPCertStatus_revoked:
607             case choice_OCSPCertStatus_unknown:
608                 continue;
609             }
610
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)
614                 continue;
615
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)
619                     continue;
620             } else
621                 /* Should force a refetch, but can we ? */;
622
623             return 0;
624         }
625     }
626
627     for (i = 0; i < ctx->crls.len; i++) {
628         struct revoke_crl *crl = &ctx->crls.val[i];
629         struct stat sb;
630
631         /* check if cert.issuer == crls.val[i].crl.issuer */
632         ret = _hx509_name_cmp(&c->tbsCertificate.issuer, 
633                               &crl->crl.tbsCertList.issuer);
634         if (ret)
635             continue;
636
637         ret = stat(crl->path, &sb);
638         if (ret == 0 && crl->last_modfied != sb.st_mtime) {
639             CRLCertificateList cl;
640
641             ret = load_crl(crl->path, &crl->last_modfied, &cl);
642             if (ret == 0) {
643                 free_CRLCertificateList(&crl->crl);
644                 crl->crl = cl;
645                 crl->verified = 0;
646             }
647         }
648
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);
652             if (ret)
653                 return ret;
654             crl->verified = 1;
655         }
656         
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;
661
662         if (crl->crl.tbsCertList.revokedCertificates == NULL)
663             return 0;
664
665         /* check if cert is in crl */
666         for (j = 0; j < crl->crl.tbsCertList.revokedCertificates->len; j++) {
667             time_t t;
668
669             ret = der_heim_integer_cmp(&crl->crl.tbsCertList.revokedCertificates->val[j].userCertificate,
670                                    &c->tbsCertificate.serialNumber);
671             if (ret != 0)
672                 continue;
673
674             t = _hx509_Time2time_t(&crl->crl.tbsCertList.revokedCertificates->val[j].revocationDate);
675             if (t > now)
676                 continue;
677             
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;
682             
683             return HX509_CRL_CERT_REVOKED;
684         }
685
686         return 0;
687     }
688
689
690     if (context->flags & HX509_CTX_VERIFY_MISSING_OK)
691         return 0;
692     return HX509_REVOKE_STATUS_MISSING;
693 }
694
695 struct ocsp_add_ctx {
696     OCSPTBSRequest *req;
697     hx509_certs certs;
698     const AlgorithmIdentifier *digest;
699     hx509_cert parent;
700 };
701
702 static int
703 add_to_req(hx509_context context, void *ptr, hx509_cert cert)
704 {
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;
710     int ret;
711     hx509_query q;
712     void *d;
713
714     d = realloc(ctx->req->requestList.val, 
715                 sizeof(ctx->req->requestList.val[0]) *
716                 (ctx->req->requestList.len + 1));
717     if (d == NULL)
718         return ENOMEM;
719     ctx->req->requestList.val = d;
720     
721     one = &ctx->req->requestList.val[ctx->req->requestList.len];
722     memset(one, 0, sizeof(*one));
723
724     _hx509_query_clear(&q);
725
726     q.match |= HX509_QUERY_FIND_ISSUER_CERT;
727     q.subject = c;
728
729     ret = hx509_certs_find(context, ctx->certs, &q, &parent);
730     if (ret)
731         goto out;
732
733     if (ctx->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");
739             goto out;
740         }
741     } else
742         ctx->parent = hx509_cert_ref(parent);
743
744     p = _hx509_get_cert(parent);
745
746     ret = copy_AlgorithmIdentifier(ctx->digest, &one->reqCert.hashAlgorithm);
747     if (ret)
748         goto out;
749
750     ret = _hx509_create_signature(context,
751                                   NULL,
752                                   &one->reqCert.hashAlgorithm,
753                                   &c->tbsCertificate.issuer._save,
754                                   NULL,
755                                   &one->reqCert.issuerNameHash);
756     if (ret)
757         goto out;
758
759     os.data = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
760     os.length = 
761         p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
762
763     ret = _hx509_create_signature(context,
764                                   NULL,
765                                   &one->reqCert.hashAlgorithm,
766                                   &os,
767                                   NULL,
768                                   &one->reqCert.issuerKeyHash);
769     if (ret)
770         goto out;
771
772     ret = copy_CertificateSerialNumber(&c->tbsCertificate.serialNumber,
773                                        &one->reqCert.serialNumber);
774     if (ret)
775         goto out;
776
777     ctx->req->requestList.len++;
778 out:
779     hx509_cert_free(parent);
780     if (ret) {
781         free_OCSPInnerRequest(one);
782         memset(one, 0, sizeof(*one));
783     }
784
785     return ret;
786 }
787
788
789 int
790 hx509_ocsp_request(hx509_context context,
791                    hx509_certs reqcerts,
792                    hx509_certs pool,
793                    hx509_cert signer,
794                    const AlgorithmIdentifier *digest,
795                    heim_octet_string *request,
796                    heim_octet_string *nonce)
797 {
798     OCSPRequest req;
799     size_t size;
800     int ret;
801     struct ocsp_add_ctx ctx;
802     Extensions *es;
803
804     memset(&req, 0, sizeof(req));
805
806     if (digest == NULL)
807         digest = _hx509_crypto_default_digest_alg;
808
809     ctx.req = &req.tbsRequest;
810     ctx.certs = pool;
811     ctx.digest = digest;
812     ctx.parent = NULL;
813
814     ret = hx509_certs_iter(context, reqcerts, add_to_req, &ctx);
815     hx509_cert_free(ctx.parent);
816     if (ret) {
817         free_OCSPRequest(&req);
818         return ret;
819     }
820     
821     if (nonce) {
822
823         req.tbsRequest.requestExtensions = 
824             calloc(1, sizeof(*req.tbsRequest.requestExtensions));
825         if (req.tbsRequest.requestExtensions == NULL) {
826             free_OCSPRequest(&req);
827             return ENOMEM;
828         }
829
830         es = req.tbsRequest.requestExtensions;
831         
832         es->len = 1;
833         es->val = calloc(es->len, sizeof(es->val[0]));
834         
835         ret = der_copy_oid(oid_id_pkix_ocsp_nonce(), &es->val[0].extnID);
836         if (ret)
837             abort();
838         
839         es->val[0].extnValue.data = malloc(10);
840         if (es->val[0].extnValue.data == NULL) {
841             free_OCSPRequest(&req);
842             return ENOMEM;
843         }
844         es->val[0].extnValue.length = 10;
845         
846         ret = RAND_bytes(es->val[0].extnValue.data,
847                          es->val[0].extnValue.length);
848         if (ret != 1) {
849             free_OCSPRequest(&req);
850             return HX509_CRYPTO_INTERNAL_ERROR;
851         }
852     }
853
854     ASN1_MALLOC_ENCODE(OCSPRequest, request->data, request->length,
855                        &req, &size, ret);
856     free_OCSPRequest(&req);
857     if (ret)
858         return ret;
859     if (size != request->length)
860         _hx509_abort("internal ASN.1 encoder error");
861
862
863     return 0;
864 }
865
866 static char *
867 printable_time(time_t t)
868 {
869     static char s[128];
870     strlcpy(s, ctime(&t)+ 4, sizeof(s));
871     s[20] = 0;
872     return s;
873 }
874
875 int
876 hx509_revoke_ocsp_print(hx509_context context, const char *path, FILE *out)
877 {
878     struct revoke_ocsp ocsp;
879     int ret, i;
880     
881     if (out == NULL)
882         out = stdout;
883
884     memset(&ocsp, 0, sizeof(ocsp));
885
886     ocsp.path = strdup(path);
887     if (ocsp.path == NULL)
888         return ENOMEM;
889
890     ret = load_ocsp(context, &ocsp);
891     if (ret) {
892         free_ocsp(&ocsp);
893         return ret;
894     }
895
896     fprintf(out, "signer: ");
897
898     switch(ocsp.ocsp.tbsResponseData.responderID.element) {
899     case choice_OCSPResponderID_byName: {
900         hx509_name n;
901         char *s;
902         _hx509_name_from_Name(&ocsp.ocsp.tbsResponseData.responderID.u.byName, &n);
903         hx509_name_to_string(n, &s);
904         hx509_name_free(&n);
905         fprintf(out, " byName: %s\n", s);
906         free(s);
907         break;
908     }
909     case choice_OCSPResponderID_byKey: {
910         char *s;
911         hex_encode(ocsp.ocsp.tbsResponseData.responderID.u.byKey.data,
912                    ocsp.ocsp.tbsResponseData.responderID.u.byKey.length,
913                    &s);
914         fprintf(out, " byKey: %s\n", s);
915         free(s);
916         break;
917     }
918     default:
919         _hx509_abort("choice_OCSPResponderID unknown");
920         break;
921     }
922
923     fprintf(out, "producedAt: %s\n", 
924             printable_time(ocsp.ocsp.tbsResponseData.producedAt));
925
926     fprintf(out, "replies: %d\n", ocsp.ocsp.tbsResponseData.responses.len);
927
928     for (i = 0; i < ocsp.ocsp.tbsResponseData.responses.len; i++) {
929         const char *status;
930         switch (ocsp.ocsp.tbsResponseData.responses.val[i].certStatus.element) {
931         case choice_OCSPCertStatus_good:
932             status = "good";
933             break;
934         case choice_OCSPCertStatus_revoked:
935             status = "revoked";
936             break;
937         case choice_OCSPCertStatus_unknown:
938             status = "unknown";
939             break;
940         default:
941             status = "element unknown";
942         }
943
944         fprintf(out, "\t%d. status: %s\n", i, status);
945
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));
951
952     }
953
954     fprintf(out, "appended certs:\n");
955     if (ocsp.certs)
956         ret = hx509_certs_iter(context, ocsp.certs, hx509_ci_print_names, out);
957
958     free_ocsp(&ocsp);
959     return ret;
960 }
961
962 /*
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.
966  */
967
968 int
969 hx509_ocsp_verify(hx509_context context,
970                   time_t now,
971                   hx509_cert cert,
972                   int flags,
973                   const void *data, size_t length,
974                   time_t *expiration)
975 {
976     const Certificate *c = _hx509_get_cert(cert);
977     OCSPBasicOCSPResponse basic;
978     int ret, i;
979
980     if (now == 0)
981         now = time(NULL);
982
983     *expiration = 0;
984
985     ret = parse_ocsp_basic(data, length, &basic);
986     if (ret) {
987         hx509_set_error_string(context, 0, ret,
988                                "Failed to parse OCSP response");
989         return ret;
990     }
991
992     for (i = 0; i < basic.tbsResponseData.responses.len; i++) {
993
994         ret = der_heim_integer_cmp(&basic.tbsResponseData.responses.val[i].certID.serialNumber,
995                                &c->tbsCertificate.serialNumber);
996         if (ret != 0)
997             continue;
998             
999         /* verify issuer hashes hash */
1000         ret = _hx509_verify_signature(context,
1001                                       NULL,
1002                                       &basic.tbsResponseData.responses.val[i].certID.hashAlgorithm,
1003                                       &c->tbsCertificate.issuer._save,
1004                                       &basic.tbsResponseData.responses.val[i].certID.issuerNameHash);
1005         if (ret != 0)
1006             continue;
1007
1008         switch (basic.tbsResponseData.responses.val[i].certStatus.element) {
1009         case choice_OCSPCertStatus_good:
1010             break;
1011         case choice_OCSPCertStatus_revoked:
1012         case choice_OCSPCertStatus_unknown:
1013             continue;
1014         }
1015
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)
1019             continue;
1020
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)
1024                 continue;
1025             *expiration = *basic.tbsResponseData.responses.val[i].nextUpdate;
1026         } else
1027             *expiration = now;
1028
1029         free_OCSPBasicOCSPResponse(&basic);
1030         return 0;
1031     }
1032
1033     free_OCSPBasicOCSPResponse(&basic);
1034
1035     {
1036         hx509_name name;
1037         char *subject;
1038         
1039         ret = hx509_cert_get_subject(cert, &name);
1040         if (ret) {
1041             hx509_clear_error_string(context);
1042             goto out;
1043         }
1044         ret = hx509_name_to_string(name, &subject);
1045         hx509_name_free(&name);
1046         if (ret) {
1047             hx509_clear_error_string(context);
1048             goto out;
1049         }
1050         hx509_set_error_string(context, 0, HX509_CERT_NOT_IN_OCSP,
1051                                "Certificate %s not in OCSP response "
1052                                "or not good",
1053                                subject);
1054         free(subject);
1055     }
1056 out:
1057     return HX509_CERT_NOT_IN_OCSP;
1058 }
1059
1060 struct hx509_crl {
1061     hx509_certs revoked;
1062     time_t expire;
1063 };
1064
1065 int
1066 hx509_crl_alloc(hx509_context context, hx509_crl *crl)
1067 {
1068     int ret;
1069
1070     *crl = calloc(1, sizeof(**crl));
1071     if (*crl == NULL) {
1072         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1073         return ENOMEM;
1074     }
1075
1076     ret = hx509_certs_init(context, "MEMORY:crl", 0, NULL, &(*crl)->revoked);
1077     if (ret) {
1078         free(*crl);
1079         *crl = NULL;
1080     }
1081     (*crl)->expire = 0;
1082     return ret;
1083 }
1084
1085 int
1086 hx509_crl_add_revoked_certs(hx509_context context,
1087                             hx509_crl crl, 
1088                             hx509_certs certs)
1089 {
1090     return hx509_certs_merge(context, crl->revoked, certs);
1091 }
1092
1093 int
1094 hx509_crl_lifetime(hx509_context context, hx509_crl crl, int delta)
1095 {
1096     crl->expire = time(NULL) + delta;
1097     return 0;
1098 }
1099
1100
1101 void
1102 hx509_crl_free(hx509_context context, hx509_crl *crl)
1103 {
1104     if (*crl == NULL)
1105         return;
1106     hx509_certs_free(&(*crl)->revoked);
1107     memset(*crl, 0, sizeof(**crl));
1108     free(*crl);
1109     *crl = NULL;
1110 }
1111
1112 static int
1113 add_revoked(hx509_context context, void *ctx, hx509_cert cert)
1114 {
1115     TBSCRLCertList *c = ctx;
1116     unsigned int num;
1117     void *ptr;
1118     int ret;
1119
1120     num = c->revokedCertificates->len;
1121     ptr = realloc(c->revokedCertificates->val,
1122                   (num + 1) * sizeof(c->revokedCertificates->val[0]));
1123     if (ptr == NULL) {
1124         hx509_clear_error_string(context);
1125         return ENOMEM;
1126     }
1127     c->revokedCertificates->val = ptr;
1128
1129     ret = hx509_cert_get_serialnumber(cert, 
1130                                       &c->revokedCertificates->val[num].userCertificate);
1131     if (ret) {
1132         hx509_clear_error_string(context);
1133         return ret;
1134     }
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;
1140
1141     c->revokedCertificates->len++;
1142
1143     return 0;
1144 }    
1145
1146
1147 int
1148 hx509_crl_sign(hx509_context context,
1149                hx509_cert signer,
1150                hx509_crl crl,
1151                heim_octet_string *os)
1152 {
1153     const AlgorithmIdentifier *sigalg = _hx509_crypto_default_sig_alg;
1154     CRLCertificateList c;
1155     size_t size;
1156     int ret;
1157     hx509_private_key signerkey;
1158
1159     memset(&c, 0, sizeof(c));
1160
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");
1166         return ret;
1167     }
1168
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");
1172         return ENOMEM;
1173     }
1174
1175     *c.tbsCertList.version = 1;
1176
1177     ret = copy_AlgorithmIdentifier(sigalg, &c.tbsCertList.signature);
1178     if (ret) {
1179         hx509_clear_error_string(context);
1180         goto out;
1181     }
1182
1183     ret = copy_Name(&_hx509_get_cert(signer)->tbsCertificate.issuer,
1184                     &c.tbsCertList.issuer);
1185     if (ret) {
1186         hx509_clear_error_string(context);
1187         goto out;
1188     }
1189
1190     c.tbsCertList.thisUpdate.element = choice_Time_generalTime;
1191     c.tbsCertList.thisUpdate.u.generalTime = time(NULL) - 24 * 3600;
1192
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");
1196         ret = ENOMEM;
1197         goto out;
1198     }
1199
1200     {
1201         time_t next = crl->expire;
1202         if (next == 0)
1203             next = time(NULL) + 24 * 3600 * 365;
1204
1205         c.tbsCertList.nextUpdate->element = choice_Time_generalTime;
1206         c.tbsCertList.nextUpdate->u.generalTime = next;
1207     }
1208
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");
1213         ret = ENOMEM;
1214         goto out;
1215     }
1216     c.tbsCertList.crlExtensions = NULL;
1217
1218     ret = hx509_certs_iter(context, crl->revoked, add_revoked, &c.tbsCertList);
1219     if (ret)
1220         goto out;
1221
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;
1226     }
1227
1228     ASN1_MALLOC_ENCODE(TBSCRLCertList, os->data, os->length,
1229                        &c.tbsCertList, &size, ret);
1230     if (ret) {
1231         hx509_set_error_string(context, 0, ret, "failed to encode tbsCRL");
1232         goto out;
1233     }
1234     if (size != os->length)
1235         _hx509_abort("internal ASN.1 encoder error");
1236
1237
1238     ret = _hx509_create_signature_bitstring(context,
1239                                             signerkey,
1240                                             sigalg,
1241                                             os,
1242                                             &c.signatureAlgorithm,
1243                                             &c.signatureValue);
1244     free(os->data);
1245
1246     ASN1_MALLOC_ENCODE(CRLCertificateList, os->data, os->length,
1247                        &c, &size, ret);
1248     free_CRLCertificateList(&c);
1249     if (ret) {
1250         hx509_set_error_string(context, 0, ret, "failed to encode CRL");
1251         goto out;
1252     }
1253     if (size != os->length)
1254         _hx509_abort("internal ASN.1 encoder error");
1255
1256     return 0;
1257
1258 out:
1259     free_CRLCertificateList(&c);
1260     return ret;
1261 }