ee144e2fb0be2b1a51646bf52660c3b7d54b7b81
[metze/heimdal/wip.git] / lib / hx509 / cert.c
1 /*
2  * Copyright (c) 2004 - 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 #include "crypto-headers.h"
36 #include <rtbl.h>
37
38 /**
39  * @page page_cert The basic certificate
40  *
41  * The basic hx509 cerificate object in hx509 is hx509_cert. The
42  * hx509_cert object is representing one X509/PKIX certificate and
43  * associated attributes; like private key, friendly name, etc.
44  *
45  * A hx509_cert object is usully found via the keyset interfaces (@ref
46  * page_keyset), but its also possible to create a certificate
47  * directly from a parsed object with hx509_cert_init() and
48  * hx509_cert_init_data().
49  *
50  * See the library functions here: @ref hx509_cert
51  */
52
53 struct hx509_verify_ctx_data {
54     hx509_certs trust_anchors;
55     int flags;
56 #define HX509_VERIFY_CTX_F_TIME_SET                     1
57 #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE      2
58 #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280              4
59 #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS          8
60 #define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS           16
61 #define HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK         32
62     time_t time_now;
63     unsigned int max_depth;
64 #define HX509_VERIFY_MAX_DEPTH 30
65     hx509_revoke_ctx revoke_ctx;
66 };
67
68 #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
69 #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
70 #define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0)
71
72 struct _hx509_cert_attrs {
73     size_t len;
74     hx509_cert_attribute *val;
75 };
76
77 struct hx509_cert_data {
78     unsigned int ref;
79     char *friendlyname;
80     Certificate *data;
81     hx509_private_key private_key;
82     struct _hx509_cert_attrs attrs;
83     hx509_name basename;
84     _hx509_cert_release_func release;
85     void *ctx;
86 };
87
88 typedef struct hx509_name_constraints {
89     NameConstraints *val;
90     size_t len;
91 } hx509_name_constraints;
92
93 #define GeneralSubtrees_SET(g,var) \
94         (g)->len = (var)->len, (g)->val = (var)->val;
95
96 /**
97  * Creates a hx509 context that most functions in the library
98  * uses. The context is only allowed to be used by one thread at each
99  * moment. Free the context with hx509_context_free().
100  *
101  * @param context Returns a pointer to new hx509 context.
102  *
103  * @return Returns an hx509 error code.
104  *
105  * @ingroup hx509
106  */
107
108 int
109 hx509_context_init(hx509_context *context)
110 {
111     *context = calloc(1, sizeof(**context));
112     if (*context == NULL)
113         return ENOMEM;
114
115     _hx509_ks_null_register(*context);
116     _hx509_ks_mem_register(*context);
117     _hx509_ks_file_register(*context);
118     _hx509_ks_pkcs12_register(*context);
119     _hx509_ks_pkcs11_register(*context);
120     _hx509_ks_dir_register(*context);
121     _hx509_ks_keychain_register(*context);
122
123     ENGINE_add_conf_module();
124     OpenSSL_add_all_algorithms();
125
126     (*context)->ocsp_time_diff = HX509_DEFAULT_OCSP_TIME_DIFF;
127
128     initialize_hx_error_table_r(&(*context)->et_list);
129     initialize_asn1_error_table_r(&(*context)->et_list);
130
131 #ifdef HX509_DEFAULT_ANCHORS
132     (void)hx509_certs_init(*context, HX509_DEFAULT_ANCHORS, 0,
133                            NULL, &(*context)->default_trust_anchors);
134 #endif
135
136     return 0;
137 }
138
139 /**
140  * Selects if the hx509_revoke_verify() function is going to require
141  * the existans of a revokation method (OCSP, CRL) or not. Note that
142  * hx509_verify_path(), hx509_cms_verify_signed(), and other function
143  * call hx509_revoke_verify().
144  *
145  * @param context hx509 context to change the flag for.
146  * @param flag zero, revokation method required, non zero missing
147  * revokation method ok
148  *
149  * @ingroup hx509_verify
150  */
151
152 void
153 hx509_context_set_missing_revoke(hx509_context context, int flag)
154 {
155     if (flag)
156         context->flags |= HX509_CTX_VERIFY_MISSING_OK;
157     else
158         context->flags &= ~HX509_CTX_VERIFY_MISSING_OK;
159 }
160
161 /**
162  * Free the context allocated by hx509_context_init().
163  *
164  * @param context context to be freed.
165  *
166  * @ingroup hx509
167  */
168
169 void
170 hx509_context_free(hx509_context *context)
171 {
172     hx509_clear_error_string(*context);
173     if ((*context)->ks_ops) {
174         free((*context)->ks_ops);
175         (*context)->ks_ops = NULL;
176     }
177     (*context)->ks_num_ops = 0;
178     free_error_table ((*context)->et_list);
179     if ((*context)->querystat)
180         free((*context)->querystat);
181     memset(*context, 0, sizeof(**context));
182     free(*context);
183     *context = NULL;
184 }
185
186 /*
187  *
188  */
189
190 Certificate *
191 _hx509_get_cert(hx509_cert cert)
192 {
193     return cert->data;
194 }
195
196 /*
197  *
198  */
199
200 int
201 _hx509_cert_get_version(const Certificate *t)
202 {
203     return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1;
204 }
205
206 /**
207  * Allocate and init an hx509 certificate object from the decoded
208  * certificate `c´.
209  *
210  * @param context A hx509 context.
211  * @param c
212  * @param cert
213  *
214  * @return Returns an hx509 error code.
215  *
216  * @ingroup hx509_cert
217  */
218
219 int
220 hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert)
221 {
222     int ret;
223
224     *cert = malloc(sizeof(**cert));
225     if (*cert == NULL)
226         return ENOMEM;
227     (*cert)->ref = 1;
228     (*cert)->friendlyname = NULL;
229     (*cert)->attrs.len = 0;
230     (*cert)->attrs.val = NULL;
231     (*cert)->private_key = NULL;
232     (*cert)->basename = NULL;
233     (*cert)->release = NULL;
234     (*cert)->ctx = NULL;
235
236     (*cert)->data = calloc(1, sizeof(*(*cert)->data));
237     if ((*cert)->data == NULL) {
238         free(*cert);
239         return ENOMEM;
240     }
241     ret = copy_Certificate(c, (*cert)->data);
242     if (ret) {
243         free((*cert)->data);
244         free(*cert);
245         *cert = NULL;
246     }
247     return ret;
248 }
249
250 /**
251  * Just like hx509_cert_init(), but instead of a decode certificate
252  * takes an pointer and length to a memory region that contains a
253  * DER/BER encoded certificate.
254  *
255  * If the memory region doesn't contain just the certificate and
256  * nothing more the function will fail with
257  * HX509_EXTRA_DATA_AFTER_STRUCTURE.
258  *
259  * @param context A hx509 context.
260  * @param ptr pointer to memory region containing encoded certificate.
261  * @param len length of memory region.
262  * @param cert a return pointer to a hx509 certificate object, will
263  * contain NULL on error.
264  *
265  * @return An hx509 error code, see hx509_get_error_string().
266  *
267  * @ingroup hx509_cert
268  */
269
270 int
271 hx509_cert_init_data(hx509_context context,
272                      const void *ptr,
273                      size_t len,
274                      hx509_cert *cert)
275 {
276     Certificate t;
277     size_t size;
278     int ret;
279
280     ret = decode_Certificate(ptr, len, &t, &size);
281     if (ret) {
282         hx509_set_error_string(context, 0, ret, "Failed to decode certificate");
283         return ret;
284     }
285     if (size != len) {
286         hx509_set_error_string(context, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE,
287                                "Extra data after certificate");
288         return HX509_EXTRA_DATA_AFTER_STRUCTURE;
289     }
290
291     ret = hx509_cert_init(context, &t, cert);
292     free_Certificate(&t);
293     return ret;
294 }
295
296 void
297 _hx509_cert_set_release(hx509_cert cert,
298                         _hx509_cert_release_func release,
299                         void *ctx)
300 {
301     cert->release = release;
302     cert->ctx = ctx;
303 }
304
305
306 /* Doesn't make a copy of `private_key'. */
307
308 int
309 _hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key)
310 {
311     if (cert->private_key)
312         _hx509_private_key_free(&cert->private_key);
313     cert->private_key = _hx509_private_key_ref(private_key);
314     return 0;
315 }
316
317 /**
318  * Free reference to the hx509 certificate object, if the refcounter
319  * reaches 0, the object if freed. Its allowed to pass in NULL.
320  *
321  * @param cert the cert to free.
322  *
323  * @ingroup hx509_cert
324  */
325
326 void
327 hx509_cert_free(hx509_cert cert)
328 {
329     int i;
330
331     if (cert == NULL)
332         return;
333
334     if (cert->ref <= 0)
335         _hx509_abort("cert refcount <= 0 on free");
336     if (--cert->ref > 0)
337         return;
338
339     if (cert->release)
340         (cert->release)(cert, cert->ctx);
341
342     if (cert->private_key)
343         _hx509_private_key_free(&cert->private_key);
344
345     free_Certificate(cert->data);
346     free(cert->data);
347
348     for (i = 0; i < cert->attrs.len; i++) {
349         der_free_octet_string(&cert->attrs.val[i]->data);
350         der_free_oid(&cert->attrs.val[i]->oid);
351         free(cert->attrs.val[i]);
352     }
353     free(cert->attrs.val);
354     free(cert->friendlyname);
355     if (cert->basename)
356         hx509_name_free(&cert->basename);
357     memset(cert, 0, sizeof(cert));
358     free(cert);
359 }
360
361 /**
362  * Add a reference to a hx509 certificate object.
363  *
364  * @param cert a pointer to an hx509 certificate object.
365  *
366  * @return the same object as is passed in.
367  *
368  * @ingroup hx509_cert
369  */
370
371 hx509_cert
372 hx509_cert_ref(hx509_cert cert)
373 {
374     if (cert == NULL)
375         return NULL;
376     if (cert->ref <= 0)
377         _hx509_abort("cert refcount <= 0");
378     cert->ref++;
379     if (cert->ref == 0)
380         _hx509_abort("cert refcount == 0");
381     return cert;
382 }
383
384 /**
385  * Allocate an verification context that is used fo control the
386  * verification process.
387  *
388  * @param context A hx509 context.
389  * @param ctx returns a pointer to a hx509_verify_ctx object.
390  *
391  * @return An hx509 error code, see hx509_get_error_string().
392  *
393  * @ingroup hx509_verify
394  */
395
396 int
397 hx509_verify_init_ctx(hx509_context context, hx509_verify_ctx *ctx)
398 {
399     hx509_verify_ctx c;
400
401     c = calloc(1, sizeof(*c));
402     if (c == NULL)
403         return ENOMEM;
404
405     c->max_depth = HX509_VERIFY_MAX_DEPTH;
406
407     *ctx = c;
408
409     return 0;
410 }
411
412 /**
413  * Free an hx509 verification context.
414  *
415  * @param ctx the context to be freed.
416  *
417  * @ingroup hx509_verify
418  */
419
420 void
421 hx509_verify_destroy_ctx(hx509_verify_ctx ctx)
422 {
423     if (ctx) {
424         hx509_certs_free(&ctx->trust_anchors);
425         hx509_revoke_free(&ctx->revoke_ctx);
426         memset(ctx, 0, sizeof(*ctx));
427     }
428     free(ctx);
429 }
430
431 /**
432  * Set the trust anchors in the verification context, makes an
433  * reference to the keyset, so the consumer can free the keyset
434  * independent of the destruction of the verification context (ctx).
435  *
436  * @param ctx a verification context
437  * @param set a keyset containing the trust anchors.
438  *
439  * @ingroup hx509_verify
440  */
441
442 void
443 hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set)
444 {
445     ctx->trust_anchors = _hx509_certs_ref(set);
446 }
447
448 /**
449  * Attach an revocation context to the verfication context, , makes an
450  * reference to the revoke context, so the consumer can free the
451  * revoke context independent of the destruction of the verification
452  * context. If there is no revoke context, the verification process is
453  * NOT going to check any verification status.
454  *
455  * @param ctx a verification context.
456  * @param revoke_ctx a revoke context.
457  *
458  * @ingroup hx509_verify
459  */
460
461 void
462 hx509_verify_attach_revoke(hx509_verify_ctx ctx, hx509_revoke_ctx revoke_ctx)
463 {
464     if (ctx->revoke_ctx)
465         hx509_revoke_free(&ctx->revoke_ctx);
466     ctx->revoke_ctx = _hx509_revoke_ref(revoke_ctx);
467 }
468
469 /**
470  * Set the clock time the the verification process is going to
471  * use. Used to check certificate in the past and future time. If not
472  * set the current time will be used.
473  *
474  * @param ctx a verification context.
475  * @param t the time the verifiation is using.
476  *
477  *
478  * @ingroup hx509_verify
479  */
480
481 void
482 hx509_verify_set_time(hx509_verify_ctx ctx, time_t t)
483 {
484     ctx->flags |= HX509_VERIFY_CTX_F_TIME_SET;
485     ctx->time_now = t;
486 }
487
488 time_t
489 _hx509_verify_get_time(hx509_verify_ctx ctx)
490 {
491     return ctx->time_now;
492 }
493
494 /**
495  * Set the maximum depth of the certificate chain that the path
496  * builder is going to try.
497  *
498  * @param ctx a verification context
499  * @param max_depth maxium depth of the certificate chain, include
500  * trust anchor.
501  *
502  * @ingroup hx509_verify
503  */
504
505 void
506 hx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth)
507 {
508     ctx->max_depth = max_depth;
509 }
510
511 /**
512  * Allow or deny the use of proxy certificates
513  *
514  * @param ctx a verification context
515  * @param boolean if non zero, allow proxy certificates.
516  *
517  * @ingroup hx509_verify
518  */
519
520 void
521 hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean)
522 {
523     if (boolean)
524         ctx->flags |= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
525     else
526         ctx->flags &= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
527 }
528
529 /**
530  * Select strict RFC3280 verification of certificiates. This means
531  * checking key usage on CA certificates, this will make version 1
532  * certificiates unuseable.
533  *
534  * @param ctx a verification context
535  * @param boolean if non zero, use strict verification.
536  *
537  * @ingroup hx509_verify
538  */
539
540 void
541 hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean)
542 {
543     if (boolean)
544         ctx->flags |= HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
545     else
546         ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
547 }
548
549 /**
550  * Allow using the operating system builtin trust anchors if no other
551  * trust anchors are configured.
552  *
553  * @param ctx a verification context
554  * @param boolean if non zero, useing the operating systems builtin
555  * trust anchors.
556  *
557  *
558  * @return An hx509 error code, see hx509_get_error_string().
559  *
560  * @ingroup hx509_cert
561  */
562
563 void
564 hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean)
565 {
566     if (boolean)
567         ctx->flags &= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
568     else
569         ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
570 }
571
572 void
573 hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx, 
574                                                     int boolean)
575 {
576     if (boolean)
577         ctx->flags &= ~HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
578     else
579         ctx->flags |= HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
580 }
581
582 static const Extension *
583 find_extension(const Certificate *cert, const heim_oid *oid, int *idx)
584 {
585     const TBSCertificate *c = &cert->tbsCertificate;
586
587     if (c->version == NULL || *c->version < 2 || c->extensions == NULL)
588         return NULL;
589
590     for (;*idx < c->extensions->len; (*idx)++) {
591         if (der_heim_oid_cmp(&c->extensions->val[*idx].extnID, oid) == 0)
592             return &c->extensions->val[(*idx)++];
593     }
594     return NULL;
595 }
596
597 static int
598 find_extension_auth_key_id(const Certificate *subject,
599                            AuthorityKeyIdentifier *ai)
600 {
601     const Extension *e;
602     size_t size;
603     int i = 0;
604
605     memset(ai, 0, sizeof(*ai));
606
607     e = find_extension(subject, oid_id_x509_ce_authorityKeyIdentifier(), &i);
608     if (e == NULL)
609         return HX509_EXTENSION_NOT_FOUND;
610
611     return decode_AuthorityKeyIdentifier(e->extnValue.data,
612                                          e->extnValue.length,
613                                          ai, &size);
614 }
615
616 int
617 _hx509_find_extension_subject_key_id(const Certificate *issuer,
618                                      SubjectKeyIdentifier *si)
619 {
620     const Extension *e;
621     size_t size;
622     int i = 0;
623
624     memset(si, 0, sizeof(*si));
625
626     e = find_extension(issuer, oid_id_x509_ce_subjectKeyIdentifier(), &i);
627     if (e == NULL)
628         return HX509_EXTENSION_NOT_FOUND;
629
630     return decode_SubjectKeyIdentifier(e->extnValue.data,
631                                        e->extnValue.length,
632                                        si, &size);
633 }
634
635 static int
636 find_extension_name_constraints(const Certificate *subject,
637                                 NameConstraints *nc)
638 {
639     const Extension *e;
640     size_t size;
641     int i = 0;
642
643     memset(nc, 0, sizeof(*nc));
644
645     e = find_extension(subject, oid_id_x509_ce_nameConstraints(), &i);
646     if (e == NULL)
647         return HX509_EXTENSION_NOT_FOUND;
648
649     return decode_NameConstraints(e->extnValue.data,
650                                   e->extnValue.length,
651                                   nc, &size);
652 }
653
654 static int
655 find_extension_subject_alt_name(const Certificate *cert, int *i,
656                                 GeneralNames *sa)
657 {
658     const Extension *e;
659     size_t size;
660
661     memset(sa, 0, sizeof(*sa));
662
663     e = find_extension(cert, oid_id_x509_ce_subjectAltName(), i);
664     if (e == NULL)
665         return HX509_EXTENSION_NOT_FOUND;
666
667     return decode_GeneralNames(e->extnValue.data,
668                                e->extnValue.length,
669                                sa, &size);
670 }
671
672 static int
673 find_extension_eku(const Certificate *cert, ExtKeyUsage *eku)
674 {
675     const Extension *e;
676     size_t size;
677     int i = 0;
678
679     memset(eku, 0, sizeof(*eku));
680
681     e = find_extension(cert, oid_id_x509_ce_extKeyUsage(), &i);
682     if (e == NULL)
683         return HX509_EXTENSION_NOT_FOUND;
684
685     return decode_ExtKeyUsage(e->extnValue.data,
686                               e->extnValue.length,
687                               eku, &size);
688 }
689
690 static int
691 add_to_list(hx509_octet_string_list *list, const heim_octet_string *entry)
692 {
693     void *p;
694     int ret;
695
696     p = realloc(list->val, (list->len + 1) * sizeof(list->val[0]));
697     if (p == NULL)
698         return ENOMEM;
699     list->val = p;
700     ret = der_copy_octet_string(entry, &list->val[list->len]);
701     if (ret)
702         return ret;
703     list->len++;
704     return 0;
705 }
706
707 /**
708  * Free a list of octet strings returned by another hx509 library
709  * function.
710  *
711  * @param list list to be freed.
712  *
713  * @ingroup hx509_misc
714  */
715
716 void
717 hx509_free_octet_string_list(hx509_octet_string_list *list)
718 {
719     int i;
720     for (i = 0; i < list->len; i++)
721         der_free_octet_string(&list->val[i]);
722     free(list->val);
723     list->val = NULL;
724     list->len = 0;
725 }
726
727 /**
728  * Return a list of subjectAltNames specified by oid in the
729  * certificate. On error the
730  *
731  * The returned list of octet string should be freed with
732  * hx509_free_octet_string_list().
733  *
734  * @param context A hx509 context.
735  * @param cert a hx509 certificate object.
736  * @param oid an oid to for SubjectAltName.
737  * @param list list of matching SubjectAltName.
738  *
739  * @return An hx509 error code, see hx509_get_error_string().
740  *
741  * @ingroup hx509_cert
742  */
743
744 int
745 hx509_cert_find_subjectAltName_otherName(hx509_context context,
746                                          hx509_cert cert,
747                                          const heim_oid *oid,
748                                          hx509_octet_string_list *list)
749 {
750     GeneralNames sa;
751     int ret, i, j;
752
753     list->val = NULL;
754     list->len = 0;
755
756     i = 0;
757     while (1) {
758         ret = find_extension_subject_alt_name(_hx509_get_cert(cert), &i, &sa);
759         i++;
760         if (ret == HX509_EXTENSION_NOT_FOUND) {
761             ret = 0;
762             break;
763         } else if (ret != 0) {
764             hx509_set_error_string(context, 0, ret, "Error searching for SAN");
765             hx509_free_octet_string_list(list);
766             return ret;
767         }
768
769         for (j = 0; j < sa.len; j++) {
770             if (sa.val[j].element == choice_GeneralName_otherName &&
771                 der_heim_oid_cmp(&sa.val[j].u.otherName.type_id, oid) == 0)
772             {
773                 ret = add_to_list(list, &sa.val[j].u.otherName.value);
774                 if (ret) {
775                     hx509_set_error_string(context, 0, ret,
776                                            "Error adding an exra SAN to "
777                                            "return list");
778                     hx509_free_octet_string_list(list);
779                     free_GeneralNames(&sa);
780                     return ret;
781                 }
782             }
783         }
784         free_GeneralNames(&sa);
785     }
786     return 0;
787 }
788
789
790 static int
791 check_key_usage(hx509_context context, const Certificate *cert,
792                 unsigned flags, int req_present)
793 {
794     const Extension *e;
795     KeyUsage ku;
796     size_t size;
797     int ret, i = 0;
798     unsigned ku_flags;
799
800     if (_hx509_cert_get_version(cert) < 3)
801         return 0;
802
803     e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
804     if (e == NULL) {
805         if (req_present) {
806             hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
807                                    "Required extension key "
808                                    "usage missing from certifiate");
809             return HX509_KU_CERT_MISSING;
810         }
811         return 0;
812     }
813
814     ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &size);
815     if (ret)
816         return ret;
817     ku_flags = KeyUsage2int(ku);
818     if ((ku_flags & flags) != flags) {
819         unsigned missing = (~ku_flags) & flags;
820         char buf[256], *name;
821
822         unparse_flags(missing, asn1_KeyUsage_units(), buf, sizeof(buf));
823         _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
824         hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
825                                "Key usage %s required but missing "
826                                "from certifiate %s", buf, name);
827         free(name);
828         return HX509_KU_CERT_MISSING;
829     }
830     return 0;
831 }
832
833 /*
834  * Return 0 on matching key usage 'flags' for 'cert', otherwise return
835  * an error code. If 'req_present' the existance is required of the
836  * KeyUsage extension.
837  */
838
839 int
840 _hx509_check_key_usage(hx509_context context, hx509_cert cert,
841                        unsigned flags, int req_present)
842 {
843     return check_key_usage(context, _hx509_get_cert(cert), flags, req_present);
844 }
845
846 enum certtype { PROXY_CERT, EE_CERT, CA_CERT };
847
848 static int
849 check_basic_constraints(hx509_context context, const Certificate *cert,
850                         enum certtype type, int depth)
851 {
852     BasicConstraints bc;
853     const Extension *e;
854     size_t size;
855     int ret, i = 0;
856
857     if (_hx509_cert_get_version(cert) < 3)
858         return 0;
859
860     e = find_extension(cert, oid_id_x509_ce_basicConstraints(), &i);
861     if (e == NULL) {
862         switch(type) {
863         case PROXY_CERT:
864         case EE_CERT:
865             return 0;
866         case CA_CERT: {
867             char *name;
868             ret = _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
869             assert(ret == 0);
870             hx509_set_error_string(context, 0, HX509_EXTENSION_NOT_FOUND,
871                                    "basicConstraints missing from "
872                                    "CA certifiacte %s", name);
873             free(name);
874             return HX509_EXTENSION_NOT_FOUND;
875         }
876         }
877     }
878
879     ret = decode_BasicConstraints(e->extnValue.data,
880                                   e->extnValue.length, &bc,
881                                   &size);
882     if (ret)
883         return ret;
884     switch(type) {
885     case PROXY_CERT:
886         if (bc.cA != NULL && *bc.cA)
887             ret = HX509_PARENT_IS_CA;
888         break;
889     case EE_CERT:
890         ret = 0;
891         break;
892     case CA_CERT:
893         if (bc.cA == NULL || !*bc.cA)
894             ret = HX509_PARENT_NOT_CA;
895         else if (bc.pathLenConstraint)
896             if (depth - 1 > *bc.pathLenConstraint)
897                 ret = HX509_CA_PATH_TOO_DEEP;
898         break;
899     }
900     free_BasicConstraints(&bc);
901     return ret;
902 }
903
904 int
905 _hx509_cert_is_parent_cmp(const Certificate *subject,
906                           const Certificate *issuer,
907                           int allow_self_signed)
908 {
909     int diff;
910     AuthorityKeyIdentifier ai;
911     SubjectKeyIdentifier si;
912     int ret_ai, ret_si, ret;
913
914     ret = _hx509_name_cmp(&issuer->tbsCertificate.subject,
915                           &subject->tbsCertificate.issuer,
916                           &diff);
917     if (ret)
918         return ret;
919     if (diff)
920         return diff;
921
922     memset(&ai, 0, sizeof(ai));
923     memset(&si, 0, sizeof(si));
924
925     /*
926      * Try to find AuthorityKeyIdentifier, if it's not present in the
927      * subject certificate nor the parent.
928      */
929
930     ret_ai = find_extension_auth_key_id(subject, &ai);
931     if (ret_ai && ret_ai != HX509_EXTENSION_NOT_FOUND)
932         return 1;
933     ret_si = _hx509_find_extension_subject_key_id(issuer, &si);
934     if (ret_si && ret_si != HX509_EXTENSION_NOT_FOUND)
935         return -1;
936
937     if (ret_si && ret_ai)
938         goto out;
939     if (ret_ai)
940         goto out;
941     if (ret_si) {
942         if (allow_self_signed) {
943             diff = 0;
944             goto out;
945         } else if (ai.keyIdentifier) {
946             diff = -1;
947             goto out;
948         }
949     }
950
951     if (ai.keyIdentifier == NULL) {
952         Name name;
953
954         if (ai.authorityCertIssuer == NULL)
955             return -1;
956         if (ai.authorityCertSerialNumber == NULL)
957             return -1;
958
959         diff = der_heim_integer_cmp(ai.authorityCertSerialNumber,
960                                     &issuer->tbsCertificate.serialNumber);
961         if (diff)
962             return diff;
963         if (ai.authorityCertIssuer->len != 1)
964             return -1;
965         if (ai.authorityCertIssuer->val[0].element != choice_GeneralName_directoryName)
966             return -1;
967         
968         name.element =
969             ai.authorityCertIssuer->val[0].u.directoryName.element;
970         name.u.rdnSequence =
971             ai.authorityCertIssuer->val[0].u.directoryName.u.rdnSequence;
972
973         ret = _hx509_name_cmp(&issuer->tbsCertificate.subject,
974                               &name,
975                               &diff);
976         if (ret)
977             return ret;
978         if (diff)
979             return diff;
980         diff = 0;
981     } else
982         diff = der_heim_octet_string_cmp(ai.keyIdentifier, &si);
983     if (diff)
984         goto out;
985
986  out:
987     free_AuthorityKeyIdentifier(&ai);
988     free_SubjectKeyIdentifier(&si);
989     return diff;
990 }
991
992 static int
993 certificate_is_anchor(hx509_context context,
994                       hx509_certs trust_anchors,
995                       const hx509_cert cert)
996 {
997     hx509_query q;
998     hx509_cert c;
999     int ret;
1000
1001     if (trust_anchors == NULL)
1002         return 0;
1003
1004     _hx509_query_clear(&q);
1005
1006     q.match = HX509_QUERY_MATCH_CERTIFICATE;
1007     q.certificate = _hx509_get_cert(cert);
1008
1009     ret = hx509_certs_find(context, trust_anchors, &q, &c);
1010     if (ret == 0)
1011         hx509_cert_free(c);
1012     return ret == 0;
1013 }
1014
1015 static int
1016 certificate_is_self_signed(hx509_context context,
1017                            const Certificate *cert,
1018                            int *self_signed)
1019 {
1020     int ret, diff;
1021     ret = _hx509_name_cmp(&cert->tbsCertificate.subject,
1022                           &cert->tbsCertificate.issuer, &diff);
1023     *self_signed = (diff == 0);
1024     if (ret)
1025         hx509_set_error_string(context, 0, ret,
1026                                "Failed to check if self signed");
1027     return ret;
1028 }
1029
1030 /*
1031  * The subjectName is "null" when it's empty set of relative DBs.
1032  */
1033
1034 static int
1035 subject_null_p(const Certificate *c)
1036 {
1037     return c->tbsCertificate.subject.u.rdnSequence.len == 0;
1038 }
1039
1040
1041 static int
1042 find_parent(hx509_context context,
1043             time_t time_now,
1044             hx509_certs trust_anchors,
1045             hx509_path *path,
1046             hx509_certs pool,
1047             hx509_cert current,
1048             hx509_cert *parent)
1049 {
1050     AuthorityKeyIdentifier ai;
1051     hx509_query q;
1052     int ret;
1053
1054     *parent = NULL;
1055     memset(&ai, 0, sizeof(ai));
1056
1057     _hx509_query_clear(&q);
1058
1059     if (!subject_null_p(current->data)) {
1060         q.match |= HX509_QUERY_FIND_ISSUER_CERT;
1061         q.subject = _hx509_get_cert(current);
1062     } else {
1063         ret = find_extension_auth_key_id(current->data, &ai);
1064         if (ret) {
1065             hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
1066                                    "Subjectless certificate missing AuthKeyID");
1067             return HX509_CERTIFICATE_MALFORMED;
1068         }
1069
1070         if (ai.keyIdentifier == NULL) {
1071             free_AuthorityKeyIdentifier(&ai);
1072             hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
1073                                    "Subjectless certificate missing keyIdentifier "
1074                                    "inside AuthKeyID");
1075             return HX509_CERTIFICATE_MALFORMED;
1076         }
1077
1078         q.subject_id = ai.keyIdentifier;
1079         q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;
1080     }
1081
1082     q.path = path;
1083     q.match |= HX509_QUERY_NO_MATCH_PATH;
1084
1085     if (pool) {
1086         q.timenow = time_now;
1087         q.match |= HX509_QUERY_MATCH_TIME;
1088
1089         ret = hx509_certs_find(context, pool, &q, parent);
1090         if (ret == 0) {
1091             free_AuthorityKeyIdentifier(&ai);
1092             return 0;
1093         }
1094         q.match &= ~HX509_QUERY_MATCH_TIME;
1095     }
1096
1097     if (trust_anchors) {
1098         ret = hx509_certs_find(context, trust_anchors, &q, parent);
1099         if (ret == 0) {
1100             free_AuthorityKeyIdentifier(&ai);
1101             return ret;
1102         }
1103     }
1104     free_AuthorityKeyIdentifier(&ai);
1105
1106     {
1107         hx509_name name;
1108         char *str;
1109
1110         ret = hx509_cert_get_subject(current, &name);
1111         if (ret) {
1112             hx509_clear_error_string(context);
1113             return HX509_ISSUER_NOT_FOUND;
1114         }
1115         ret = hx509_name_to_string(name, &str);
1116         hx509_name_free(&name);
1117         if (ret) {
1118             hx509_clear_error_string(context);
1119             return HX509_ISSUER_NOT_FOUND;
1120         }
1121         
1122         hx509_set_error_string(context, 0, HX509_ISSUER_NOT_FOUND,
1123                                "Failed to find issuer for "
1124                                "certificate with subject: '%s'", str);
1125         free(str);
1126     }
1127     return HX509_ISSUER_NOT_FOUND;
1128 }
1129
1130 /*
1131  *
1132  */
1133
1134 static int
1135 is_proxy_cert(hx509_context context,
1136               const Certificate *cert,
1137               ProxyCertInfo *rinfo)
1138 {
1139     ProxyCertInfo info;
1140     const Extension *e;
1141     size_t size;
1142     int ret, i = 0;
1143
1144     if (rinfo)
1145         memset(rinfo, 0, sizeof(*rinfo));
1146
1147     e = find_extension(cert, oid_id_pkix_pe_proxyCertInfo(), &i);
1148     if (e == NULL) {
1149         hx509_clear_error_string(context);
1150         return HX509_EXTENSION_NOT_FOUND;
1151     }
1152
1153     ret = decode_ProxyCertInfo(e->extnValue.data,
1154                                e->extnValue.length,
1155                                &info,
1156                                &size);
1157     if (ret) {
1158         hx509_clear_error_string(context);
1159         return ret;
1160     }
1161     if (size != e->extnValue.length) {
1162         free_ProxyCertInfo(&info);
1163         hx509_clear_error_string(context);
1164         return HX509_EXTRA_DATA_AFTER_STRUCTURE;
1165     }
1166     if (rinfo == NULL)
1167         free_ProxyCertInfo(&info);
1168     else
1169         *rinfo = info;
1170
1171     return 0;
1172 }
1173
1174 /*
1175  * Path operations are like MEMORY based keyset, but with exposed
1176  * internal so we can do easy searches.
1177  */
1178
1179 int
1180 _hx509_path_append(hx509_context context, hx509_path *path, hx509_cert cert)
1181 {
1182     hx509_cert *val;
1183     val = realloc(path->val, (path->len + 1) * sizeof(path->val[0]));
1184     if (val == NULL) {
1185         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1186         return ENOMEM;
1187     }
1188
1189     path->val = val;
1190     path->val[path->len] = hx509_cert_ref(cert);
1191     path->len++;
1192
1193     return 0;
1194 }
1195
1196 void
1197 _hx509_path_free(hx509_path *path)
1198 {
1199     unsigned i;
1200
1201     for (i = 0; i < path->len; i++)
1202         hx509_cert_free(path->val[i]);
1203     free(path->val);
1204     path->val = NULL;
1205     path->len = 0;
1206 }
1207
1208 /*
1209  * Find path by looking up issuer for the top certificate and continue
1210  * until an anchor certificate is found or max limit is found. A
1211  * certificate never included twice in the path.
1212  *
1213  * If the trust anchors are not given, calculate optimistic path, just
1214  * follow the chain upward until we no longer find a parent or we hit
1215  * the max path limit. In this case, a failure will always be returned
1216  * depending on what error condition is hit first.
1217  *
1218  * The path includes a path from the top certificate to the anchor
1219  * certificate.
1220  *
1221  * The caller needs to free `path´ both on successful built path and
1222  * failure.
1223  */
1224
1225 int
1226 _hx509_calculate_path(hx509_context context,
1227                       int flags,
1228                       time_t time_now,
1229                       hx509_certs anchors,
1230                       unsigned int max_depth,
1231                       hx509_cert cert,
1232                       hx509_certs pool,
1233                       hx509_path *path)
1234 {
1235     hx509_cert parent, current;
1236     int ret;
1237
1238     if (max_depth == 0)
1239         max_depth = HX509_VERIFY_MAX_DEPTH;
1240
1241     ret = _hx509_path_append(context, path, cert);
1242     if (ret)
1243         return ret;
1244
1245     current = hx509_cert_ref(cert);
1246
1247     while (!certificate_is_anchor(context, anchors, current)) {
1248
1249         ret = find_parent(context, time_now, anchors, path,
1250                           pool, current, &parent);
1251         hx509_cert_free(current);
1252         if (ret)
1253             return ret;
1254
1255         ret = _hx509_path_append(context, path, parent);
1256         if (ret)
1257             return ret;
1258         current = parent;
1259
1260         if (path->len > max_depth) {
1261             hx509_cert_free(current);
1262             hx509_set_error_string(context, 0, HX509_PATH_TOO_LONG,
1263                                    "Path too long while bulding "
1264                                    "certificate chain");
1265             return HX509_PATH_TOO_LONG;
1266         }
1267     }
1268
1269     if ((flags & HX509_CALCULATE_PATH_NO_ANCHOR) &&
1270         path->len > 0 &&
1271         certificate_is_anchor(context, anchors, path->val[path->len - 1]))
1272     {
1273         hx509_cert_free(path->val[path->len - 1]);
1274         path->len--;
1275     }
1276
1277     hx509_cert_free(current);
1278     return 0;
1279 }
1280
1281 int
1282 _hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier *p,
1283                                const AlgorithmIdentifier *q)
1284 {
1285     int diff;
1286     diff = der_heim_oid_cmp(&p->algorithm, &q->algorithm);
1287     if (diff)
1288         return diff;
1289     if (p->parameters) {
1290         if (q->parameters)
1291             return heim_any_cmp(p->parameters,
1292                                 q->parameters);
1293         else
1294             return 1;
1295     } else {
1296         if (q->parameters)
1297             return -1;
1298         else
1299             return 0;
1300     }
1301 }
1302
1303 int
1304 _hx509_Certificate_cmp(const Certificate *p, const Certificate *q)
1305 {
1306     int diff;
1307     diff = der_heim_bit_string_cmp(&p->signatureValue, &q->signatureValue);
1308     if (diff)
1309         return diff;
1310     diff = _hx509_AlgorithmIdentifier_cmp(&p->signatureAlgorithm,
1311                                           &q->signatureAlgorithm);
1312     if (diff)
1313         return diff;
1314     diff = der_heim_octet_string_cmp(&p->tbsCertificate._save,
1315                                      &q->tbsCertificate._save);
1316     return diff;
1317 }
1318
1319 /**
1320  * Compare to hx509 certificate object, useful for sorting.
1321  *
1322  * @param p a hx509 certificate object.
1323  * @param q a hx509 certificate object.
1324  *
1325  * @return 0 the objects are the same, returns > 0 is p is "larger"
1326  * then q, < 0 if p is "smaller" then q.
1327  *
1328  * @ingroup hx509_cert
1329  */
1330
1331 int
1332 hx509_cert_cmp(hx509_cert p, hx509_cert q)
1333 {
1334     return _hx509_Certificate_cmp(p->data, q->data);
1335 }
1336
1337 /**
1338  * Return the name of the issuer of the hx509 certificate.
1339  *
1340  * @param p a hx509 certificate object.
1341  * @param name a pointer to a hx509 name, should be freed by
1342  * hx509_name_free().
1343  *
1344  * @return An hx509 error code, see hx509_get_error_string().
1345  *
1346  * @ingroup hx509_cert
1347  */
1348
1349 int
1350 hx509_cert_get_issuer(hx509_cert p, hx509_name *name)
1351 {
1352     return _hx509_name_from_Name(&p->data->tbsCertificate.issuer, name);
1353 }
1354
1355 /**
1356  * Return the name of the subject of the hx509 certificate.
1357  *
1358  * @param p a hx509 certificate object.
1359  * @param name a pointer to a hx509 name, should be freed by
1360  * hx509_name_free(). See also hx509_cert_get_base_subject().
1361  *
1362  * @return An hx509 error code, see hx509_get_error_string().
1363  *
1364  * @ingroup hx509_cert
1365  */
1366
1367 int
1368 hx509_cert_get_subject(hx509_cert p, hx509_name *name)
1369 {
1370     return _hx509_name_from_Name(&p->data->tbsCertificate.subject, name);
1371 }
1372
1373 /**
1374  * Return the name of the base subject of the hx509 certificate. If
1375  * the certiicate is a verified proxy certificate, the this function
1376  * return the base certificate (root of the proxy chain). If the proxy
1377  * certificate is not verified with the base certificate
1378  * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
1379  *
1380  * @param context a hx509 context.
1381  * @param c a hx509 certificate object.
1382  * @param name a pointer to a hx509 name, should be freed by
1383  * hx509_name_free(). See also hx509_cert_get_subject().
1384  *
1385  * @return An hx509 error code, see hx509_get_error_string().
1386  *
1387  * @ingroup hx509_cert
1388  */
1389
1390 int
1391 hx509_cert_get_base_subject(hx509_context context, hx509_cert c,
1392                             hx509_name *name)
1393 {
1394     if (c->basename)
1395         return hx509_name_copy(context, c->basename, name);
1396     if (is_proxy_cert(context, c->data, NULL) == 0) {
1397         int ret = HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED;
1398         hx509_set_error_string(context, 0, ret,
1399                                "Proxy certificate have not been "
1400                                "canonicalize yet, no base name");
1401         return ret;
1402     }
1403     return _hx509_name_from_Name(&c->data->tbsCertificate.subject, name);
1404 }
1405
1406 /**
1407  * Get serial number of the certificate.
1408  *
1409  * @param p a hx509 certificate object.
1410  * @param i serial number, should be freed ith der_free_heim_integer().
1411  *
1412  * @return An hx509 error code, see hx509_get_error_string().
1413  *
1414  * @ingroup hx509_cert
1415  */
1416
1417 int
1418 hx509_cert_get_serialnumber(hx509_cert p, heim_integer *i)
1419 {
1420     return der_copy_heim_integer(&p->data->tbsCertificate.serialNumber, i);
1421 }
1422
1423 /**
1424  * Get notBefore time of the certificate.
1425  *
1426  * @param p a hx509 certificate object.
1427  *
1428  * @return return not before time
1429  *
1430  * @ingroup hx509_cert
1431  */
1432
1433 time_t
1434 hx509_cert_get_notBefore(hx509_cert p)
1435 {
1436     return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notBefore);
1437 }
1438
1439 /**
1440  * Get notAfter time of the certificate.
1441  *
1442  * @param p a hx509 certificate object.
1443  *
1444  * @return return not after time.
1445  *
1446  * @ingroup hx509_cert
1447  */
1448
1449 time_t
1450 hx509_cert_get_notAfter(hx509_cert p)
1451 {
1452     return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter);
1453 }
1454
1455 /**
1456  * Get the SubjectPublicKeyInfo structure from the hx509 certificate.
1457  *
1458  * @param context a hx509 context.
1459  * @param p a hx509 certificate object.
1460  * @param spki SubjectPublicKeyInfo, should be freed with
1461  * free_SubjectPublicKeyInfo().
1462  *
1463  * @return An hx509 error code, see hx509_get_error_string().
1464  *
1465  * @ingroup hx509_cert
1466  */
1467
1468 int
1469 hx509_cert_get_SPKI(hx509_context context, hx509_cert p, SubjectPublicKeyInfo *spki)
1470 {
1471     int ret;
1472
1473     ret = copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo, spki);
1474     if (ret)
1475         hx509_set_error_string(context, 0, ret, "Failed to copy SPKI");
1476     return ret;
1477 }
1478
1479 /**
1480  * Get the AlgorithmIdentifier from the hx509 certificate.
1481  *
1482  * @param context a hx509 context.
1483  * @param p a hx509 certificate object.
1484  * @param alg AlgorithmIdentifier, should be freed with
1485  *            free_AlgorithmIdentifier(). The algorithmidentifier is
1486  *            typicly rsaEncryption, or id-ecPublicKey, or some other
1487  *            public key mechanism.
1488  *
1489  * @return An hx509 error code, see hx509_get_error_string().
1490  *
1491  * @ingroup hx509_cert
1492  */
1493
1494 int
1495 hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context,
1496                                         hx509_cert p,
1497                                         AlgorithmIdentifier *alg)
1498 {
1499     int ret;
1500
1501     ret = copy_AlgorithmIdentifier(&p->data->tbsCertificate.subjectPublicKeyInfo.algorithm, alg);
1502     if (ret)
1503         hx509_set_error_string(context, 0, ret,
1504                                "Failed to copy SPKI AlgorithmIdentifier");
1505     return ret;
1506 }
1507
1508
1509 hx509_private_key
1510 _hx509_cert_private_key(hx509_cert p)
1511 {
1512     return p->private_key;
1513 }
1514
1515 int
1516 hx509_cert_have_private_key(hx509_cert p)
1517 {
1518     return p->private_key ? 1 : 0;
1519 }
1520
1521
1522 int
1523 _hx509_cert_private_key_exportable(hx509_cert p)
1524 {
1525     if (p->private_key == NULL)
1526         return 0;
1527     return _hx509_private_key_exportable(p->private_key);
1528 }
1529
1530 int
1531 _hx509_cert_private_decrypt(hx509_context context,
1532                             const heim_octet_string *ciphertext,
1533                             const heim_oid *encryption_oid,
1534                             hx509_cert p,
1535                             heim_octet_string *cleartext)
1536 {
1537     cleartext->data = NULL;
1538     cleartext->length = 0;
1539
1540     if (p->private_key == NULL) {
1541         hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
1542                                "Private key missing");
1543         return HX509_PRIVATE_KEY_MISSING;
1544     }
1545
1546     return _hx509_private_key_private_decrypt(context,
1547                                               ciphertext,
1548                                               encryption_oid,
1549                                               p->private_key,
1550                                               cleartext);
1551 }
1552
1553 int
1554 _hx509_cert_public_encrypt(hx509_context context,
1555                            const heim_octet_string *cleartext,
1556                            const hx509_cert p,
1557                            heim_oid *encryption_oid,
1558                            heim_octet_string *ciphertext)
1559 {
1560     return _hx509_public_encrypt(context,
1561                                  cleartext, p->data,
1562                                  encryption_oid, ciphertext);
1563 }
1564
1565 /*
1566  *
1567  */
1568
1569 time_t
1570 _hx509_Time2time_t(const Time *t)
1571 {
1572     switch(t->element) {
1573     case choice_Time_utcTime:
1574         return t->u.utcTime;
1575     case choice_Time_generalTime:
1576         return t->u.generalTime;
1577     }
1578     return 0;
1579 }
1580
1581 /*
1582  *
1583  */
1584
1585 static int
1586 init_name_constraints(hx509_name_constraints *nc)
1587 {
1588     memset(nc, 0, sizeof(*nc));
1589     return 0;
1590 }
1591
1592 static int
1593 add_name_constraints(hx509_context context, const Certificate *c, int not_ca,
1594                      hx509_name_constraints *nc)
1595 {
1596     NameConstraints tnc;
1597     int ret;
1598
1599     ret = find_extension_name_constraints(c, &tnc);
1600     if (ret == HX509_EXTENSION_NOT_FOUND)
1601         return 0;
1602     else if (ret) {
1603         hx509_set_error_string(context, 0, ret, "Failed getting NameConstraints");
1604         return ret;
1605     } else if (not_ca) {
1606         ret = HX509_VERIFY_CONSTRAINTS;
1607         hx509_set_error_string(context, 0, ret, "Not a CA and "
1608                                "have NameConstraints");
1609     } else {
1610         NameConstraints *val;
1611         val = realloc(nc->val, sizeof(nc->val[0]) * (nc->len + 1));
1612         if (val == NULL) {
1613             hx509_clear_error_string(context);
1614             ret = ENOMEM;
1615             goto out;
1616         }
1617         nc->val = val;
1618         ret = copy_NameConstraints(&tnc, &nc->val[nc->len]);
1619         if (ret) {
1620             hx509_clear_error_string(context);
1621             goto out;
1622         }
1623         nc->len += 1;
1624     }
1625 out:
1626     free_NameConstraints(&tnc);
1627     return ret;
1628 }
1629
1630 static int
1631 match_RDN(const RelativeDistinguishedName *c,
1632           const RelativeDistinguishedName *n)
1633 {
1634     int i;
1635
1636     if (c->len != n->len)
1637         return HX509_NAME_CONSTRAINT_ERROR;
1638
1639     for (i = 0; i < n->len; i++) {
1640         int diff, ret;
1641
1642         if (der_heim_oid_cmp(&c->val[i].type, &n->val[i].type) != 0)
1643             return HX509_NAME_CONSTRAINT_ERROR;
1644         ret = _hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value, &diff);
1645         if (ret)
1646             return ret;
1647         if (diff != 0)
1648             return HX509_NAME_CONSTRAINT_ERROR;
1649     }
1650     return 0;
1651 }
1652
1653 static int
1654 match_X501Name(const Name *c, const Name *n)
1655 {
1656     int i, ret;
1657
1658     if (c->element != choice_Name_rdnSequence
1659         || n->element != choice_Name_rdnSequence)
1660         return 0;
1661     if (c->u.rdnSequence.len > n->u.rdnSequence.len)
1662         return HX509_NAME_CONSTRAINT_ERROR;
1663     for (i = 0; i < c->u.rdnSequence.len; i++) {
1664         ret = match_RDN(&c->u.rdnSequence.val[i], &n->u.rdnSequence.val[i]);
1665         if (ret)
1666             return ret;
1667     }
1668     return 0;
1669 }
1670
1671
1672 static int
1673 match_general_name(const GeneralName *c, const GeneralName *n, int *match)
1674 {
1675     /*
1676      * Name constraints only apply to the same name type, see RFC3280,
1677      * 4.2.1.11.
1678      */
1679     assert(c->element == n->element);
1680
1681     switch(c->element) {
1682     case choice_GeneralName_otherName:
1683         if (der_heim_oid_cmp(&c->u.otherName.type_id,
1684                          &n->u.otherName.type_id) != 0)
1685             return HX509_NAME_CONSTRAINT_ERROR;
1686         if (heim_any_cmp(&c->u.otherName.value,
1687                          &n->u.otherName.value) != 0)
1688             return HX509_NAME_CONSTRAINT_ERROR;
1689         *match = 1;
1690         return 0;
1691     case choice_GeneralName_rfc822Name: {
1692         const char *s;
1693         size_t len1, len2;
1694         s = strchr(c->u.rfc822Name, '@');
1695         if (s) {
1696             if (strcasecmp(c->u.rfc822Name, n->u.rfc822Name) != 0)
1697                 return HX509_NAME_CONSTRAINT_ERROR;
1698         } else {
1699             s = strchr(n->u.rfc822Name, '@');
1700             if (s == NULL)
1701                 return HX509_NAME_CONSTRAINT_ERROR;
1702             len1 = strlen(c->u.rfc822Name);
1703             len2 = strlen(s + 1);
1704             if (len1 > len2)
1705                 return HX509_NAME_CONSTRAINT_ERROR;
1706             if (strcasecmp(s + 1 + len2 - len1, c->u.rfc822Name) != 0)
1707                 return HX509_NAME_CONSTRAINT_ERROR;
1708             if (len1 < len2 && s[len2 - len1 + 1] != '.')
1709                 return HX509_NAME_CONSTRAINT_ERROR;
1710         }
1711         *match = 1;
1712         return 0;
1713     }
1714     case choice_GeneralName_dNSName: {
1715         size_t lenc, lenn;
1716
1717         lenc = strlen(c->u.dNSName);
1718         lenn = strlen(n->u.dNSName);
1719         if (lenc > lenn)
1720             return HX509_NAME_CONSTRAINT_ERROR;
1721         if (strcasecmp(&n->u.dNSName[lenn - lenc], c->u.dNSName) != 0)
1722             return HX509_NAME_CONSTRAINT_ERROR;
1723         if (lenc != lenn && n->u.dNSName[lenn - lenc - 1] != '.')
1724             return HX509_NAME_CONSTRAINT_ERROR;
1725         *match = 1;
1726         return 0;
1727     }
1728     case choice_GeneralName_directoryName: {
1729         Name c_name, n_name;
1730         int ret;
1731
1732         c_name._save.data = NULL;
1733         c_name._save.length = 0;
1734         c_name.element = c->u.directoryName.element;
1735         c_name.u.rdnSequence = c->u.directoryName.u.rdnSequence;
1736
1737         n_name._save.data = NULL;
1738         n_name._save.length = 0;
1739         n_name.element = n->u.directoryName.element;
1740         n_name.u.rdnSequence = n->u.directoryName.u.rdnSequence;
1741
1742         ret = match_X501Name(&c_name, &n_name);
1743         if (ret == 0)
1744             *match = 1;
1745         return ret;
1746     }
1747     case choice_GeneralName_uniformResourceIdentifier:
1748     case choice_GeneralName_iPAddress:
1749     case choice_GeneralName_registeredID:
1750     default:
1751         return HX509_NAME_CONSTRAINT_ERROR;
1752     }
1753 }
1754
1755 static int
1756 match_alt_name(const GeneralName *n, const Certificate *c,
1757                int *same, int *match)
1758 {
1759     GeneralNames sa;
1760     int ret, i, j;
1761
1762     i = 0;
1763     do {
1764         ret = find_extension_subject_alt_name(c, &i, &sa);
1765         if (ret == HX509_EXTENSION_NOT_FOUND) {
1766             ret = 0;
1767             break;
1768         } else if (ret != 0)
1769             break;
1770
1771         for (j = 0; j < sa.len; j++) {
1772             if (n->element == sa.val[j].element) {
1773                 *same = 1;
1774                 ret = match_general_name(n, &sa.val[j], match);
1775             }
1776         }
1777         free_GeneralNames(&sa);
1778     } while (1);
1779     return ret;
1780 }
1781
1782
1783 static int
1784 match_tree(const GeneralSubtrees *t, const Certificate *c, int *match)
1785 {
1786     int name, alt_name, same;
1787     unsigned int i;
1788     int ret = 0;
1789
1790     name = alt_name = same = *match = 0;
1791     for (i = 0; i < t->len; i++) {
1792         if (t->val[i].minimum && t->val[i].maximum)
1793             return HX509_RANGE;
1794
1795         /*
1796          * If the constraint apply to directoryNames, test is with
1797          * subjectName of the certificate if the certificate have a
1798          * non-null (empty) subjectName.
1799          */
1800
1801         if (t->val[i].base.element == choice_GeneralName_directoryName
1802             && !subject_null_p(c))
1803         {
1804             GeneralName certname;
1805         
1806             memset(&certname, 0, sizeof(certname));
1807             certname.element = choice_GeneralName_directoryName;
1808             certname.u.directoryName.element =
1809                 c->tbsCertificate.subject.element;
1810             certname.u.directoryName.u.rdnSequence =
1811                 c->tbsCertificate.subject.u.rdnSequence;
1812
1813             ret = match_general_name(&t->val[i].base, &certname, &name);
1814         }
1815
1816         /* Handle subjectAltNames, this is icky since they
1817          * restrictions only apply if the subjectAltName is of the
1818          * same type. So if there have been a match of type, require
1819          * altname to be set.
1820          */
1821         ret = match_alt_name(&t->val[i].base, c, &same, &alt_name);
1822     }
1823     if (name && (!same || alt_name))
1824         *match = 1;
1825     return ret;
1826 }
1827
1828 static int
1829 check_name_constraints(hx509_context context,
1830                        const hx509_name_constraints *nc,
1831                        const Certificate *c)
1832 {
1833     int match, ret;
1834     int i;
1835
1836     for (i = 0 ; i < nc->len; i++) {
1837         GeneralSubtrees gs;
1838
1839         if (nc->val[i].permittedSubtrees) {
1840             GeneralSubtrees_SET(&gs, nc->val[i].permittedSubtrees);
1841             ret = match_tree(&gs, c, &match);
1842             if (ret) {
1843                 hx509_clear_error_string(context);
1844                 return ret;
1845             }
1846             /* allow null subjectNames, they wont matches anything */
1847             if (match == 0 && !subject_null_p(c)) {
1848                 hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
1849                                        "Error verify constraints, "
1850                                        "certificate didn't match any "
1851                                        "permitted subtree");
1852                 return HX509_VERIFY_CONSTRAINTS;
1853             }
1854         }
1855         if (nc->val[i].excludedSubtrees) {
1856             GeneralSubtrees_SET(&gs, nc->val[i].excludedSubtrees);
1857             ret = match_tree(&gs, c, &match);
1858             if (ret) {
1859                 hx509_clear_error_string(context);
1860                 return ret;
1861             }
1862             if (match) {
1863                 hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
1864                                        "Error verify constraints, "
1865                                        "certificate included in excluded "
1866                                        "subtree");
1867                 return HX509_VERIFY_CONSTRAINTS;
1868             }
1869         }
1870     }
1871     return 0;
1872 }
1873
1874 static void
1875 free_name_constraints(hx509_name_constraints *nc)
1876 {
1877     int i;
1878
1879     for (i = 0 ; i < nc->len; i++)
1880         free_NameConstraints(&nc->val[i]);
1881     free(nc->val);
1882 }
1883
1884 /**
1885  * Build and verify the path for the certificate to the trust anchor
1886  * specified in the verify context. The path is constructed from the
1887  * certificate, the pool and the trust anchors.
1888  *
1889  * @param context A hx509 context.
1890  * @param ctx A hx509 verification context.
1891  * @param cert the certificate to build the path from.
1892  * @param pool A keyset of certificates to build the chain from.
1893  *
1894  * @return An hx509 error code, see hx509_get_error_string().
1895  *
1896  * @ingroup hx509_verify
1897  */
1898
1899 int
1900 hx509_verify_path(hx509_context context,
1901                   hx509_verify_ctx ctx,
1902                   hx509_cert cert,
1903                   hx509_certs pool)
1904 {
1905     hx509_name_constraints nc;
1906     hx509_path path;
1907     int ret, i, proxy_cert_depth, selfsigned_depth, diff;
1908     enum certtype type;
1909     Name proxy_issuer;
1910     hx509_certs anchors = NULL;
1911
1912     memset(&proxy_issuer, 0, sizeof(proxy_issuer));
1913
1914     ret = init_name_constraints(&nc);
1915     if (ret)    
1916         return ret;
1917
1918     path.val = NULL;
1919     path.len = 0;
1920
1921     if ((ctx->flags & HX509_VERIFY_CTX_F_TIME_SET) == 0)
1922         ctx->time_now = time(NULL);
1923
1924     /*
1925      *
1926      */
1927     if (ctx->trust_anchors)
1928         anchors = _hx509_certs_ref(ctx->trust_anchors);
1929     else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx))
1930         anchors = _hx509_certs_ref(context->default_trust_anchors);
1931     else {
1932         ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors);
1933         if (ret)
1934             goto out;
1935     }
1936
1937     /*
1938      * Calculate the path from the certificate user presented to the
1939      * to an anchor.
1940      */
1941     ret = _hx509_calculate_path(context, 0, ctx->time_now,
1942                                 anchors, ctx->max_depth,
1943                                 cert, pool, &path);
1944     if (ret)
1945         goto out;
1946
1947     /*
1948      * Check CA and proxy certificate chain from the top of the
1949      * certificate chain. Also check certificate is valid with respect
1950      * to the current time.
1951      *
1952      */
1953
1954     proxy_cert_depth = 0;
1955     selfsigned_depth = 0;
1956
1957     if (ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE)
1958         type = PROXY_CERT;
1959     else
1960         type = EE_CERT;
1961
1962     for (i = 0; i < path.len; i++) {
1963         Certificate *c;
1964         time_t t;
1965
1966         c = _hx509_get_cert(path.val[i]);
1967         
1968         /*
1969          * Lets do some basic check on issuer like
1970          * keyUsage.keyCertSign and basicConstraints.cA bit depending
1971          * on what type of certificate this is.
1972          */
1973
1974         switch (type) {
1975         case CA_CERT:
1976
1977             /* XXX make constants for keyusage */
1978             ret = check_key_usage(context, c, 1 << 5,
1979                                   REQUIRE_RFC3280(ctx) ? TRUE : FALSE);
1980             if (ret) {
1981                 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
1982                                        "Key usage missing from CA certificate");
1983                 goto out;
1984             }
1985
1986             /* self signed cert doesn't add to path length */
1987             if (i + 1 != path.len) {
1988                 int selfsigned;
1989
1990                 ret = certificate_is_self_signed(context, c, &selfsigned);
1991                 if (ret)
1992                     goto out;
1993                 if (selfsigned)
1994                     selfsigned_depth++;
1995             }
1996
1997             break;
1998         case PROXY_CERT: {
1999             ProxyCertInfo info; 
2000
2001             if (is_proxy_cert(context, c, &info) == 0) {
2002                 int j;
2003
2004                 if (info.pCPathLenConstraint != NULL &&
2005                     *info.pCPathLenConstraint < i)
2006                 {
2007                     free_ProxyCertInfo(&info);
2008                     ret = HX509_PATH_TOO_LONG;
2009                     hx509_set_error_string(context, 0, ret,
2010                                            "Proxy certificate chain "
2011                                            "longer then allowed");
2012                     goto out;
2013                 }
2014                 /* XXX MUST check info.proxyPolicy */
2015                 free_ProxyCertInfo(&info);
2016                 
2017                 j = 0;
2018                 if (find_extension(c, oid_id_x509_ce_subjectAltName(), &j)) {
2019                     ret = HX509_PROXY_CERT_INVALID;
2020                     hx509_set_error_string(context, 0, ret,
2021                                            "Proxy certificate have explicity "
2022                                            "forbidden subjectAltName");
2023                     goto out;
2024                 }
2025
2026                 j = 0;
2027                 if (find_extension(c, oid_id_x509_ce_issuerAltName(), &j)) {
2028                     ret = HX509_PROXY_CERT_INVALID;
2029                     hx509_set_error_string(context, 0, ret,
2030                                            "Proxy certificate have explicity "
2031                                            "forbidden issuerAltName");
2032                     goto out;
2033                 }
2034                         
2035                 /*
2036                  * The subject name of the proxy certificate should be
2037                  * CN=XXX,<proxy issuer>, prune of CN and check if its
2038                  * the same over the whole chain of proxy certs and
2039                  * then check with the EE cert when we get to it.
2040                  */
2041
2042                 if (proxy_cert_depth) {
2043                     ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject, &diff);
2044                     if (ret) {
2045                         hx509_set_error_string(context, 0, ret, "Out of memory");
2046                         goto out;
2047                     }
2048                     if (diff) {
2049                         ret = HX509_PROXY_CERT_NAME_WRONG;
2050                         hx509_set_error_string(context, 0, ret,
2051                                                "Base proxy name not right");
2052                         goto out;
2053                     }
2054                 }
2055
2056                 free_Name(&proxy_issuer);
2057
2058                 ret = copy_Name(&c->tbsCertificate.subject, &proxy_issuer);
2059                 if (ret) {
2060                     hx509_clear_error_string(context);
2061                     goto out;
2062                 }
2063
2064                 j = proxy_issuer.u.rdnSequence.len;
2065                 if (proxy_issuer.u.rdnSequence.len < 2
2066                     || proxy_issuer.u.rdnSequence.val[j - 1].len > 1
2067                     || der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type,
2068                                         oid_id_at_commonName()))
2069                 {
2070                     ret = HX509_PROXY_CERT_NAME_WRONG;
2071                     hx509_set_error_string(context, 0, ret,
2072                                            "Proxy name too short or "
2073                                            "does not have Common name "
2074                                            "at the top");
2075                     goto out;
2076                 }
2077
2078                 free_RelativeDistinguishedName(&proxy_issuer.u.rdnSequence.val[j - 1]);
2079                 proxy_issuer.u.rdnSequence.len -= 1;
2080
2081                 ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer, &diff);
2082                 if (ret) {
2083                     hx509_set_error_string(context, 0, ret, "Out of memory");
2084                     goto out;
2085                 }
2086                 if (diff != 0) {
2087                     ret = HX509_PROXY_CERT_NAME_WRONG;
2088                     hx509_set_error_string(context, 0, ret,
2089                                            "Proxy issuer name not as expected");
2090                     goto out;
2091                 }
2092
2093                 break;
2094             } else {
2095                 /*
2096                  * Now we are done with the proxy certificates, this
2097                  * cert was an EE cert and we we will fall though to
2098                  * EE checking below.
2099                  */
2100                 type = EE_CERT;
2101                 /* FALLTHOUGH */
2102             }
2103         }
2104         case EE_CERT:
2105             /*
2106              * If there where any proxy certificates in the chain
2107              * (proxy_cert_depth > 0), check that the proxy issuer
2108              * matched proxy certificates "base" subject.
2109              */
2110             if (proxy_cert_depth) {
2111
2112                 ret = _hx509_name_cmp(&proxy_issuer,
2113                                       &c->tbsCertificate.subject, &diff);
2114                 if (ret) {
2115                     hx509_set_error_string(context, 0, ret, "out of memory");
2116                     goto out;
2117                 }
2118                 if (diff) {
2119                     ret = HX509_PROXY_CERT_NAME_WRONG;
2120                     hx509_clear_error_string(context);
2121                     goto out;
2122                 }
2123                 if (cert->basename)
2124                     hx509_name_free(&cert->basename);
2125                 
2126                 ret = _hx509_name_from_Name(&proxy_issuer, &cert->basename);
2127                 if (ret) {
2128                     hx509_clear_error_string(context);
2129                     goto out;
2130                 }
2131             }
2132
2133             break;
2134         }
2135
2136         ret = check_basic_constraints(context, c, type,
2137                                       i - proxy_cert_depth - selfsigned_depth);
2138         if (ret)
2139             goto out;
2140         
2141         /*
2142          * Don't check the trust anchors expiration time since they
2143          * are transported out of band, from RFC3820.
2144          */
2145         if (i + 1 != path.len || CHECK_TA(ctx)) {
2146
2147             t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2148             if (t > ctx->time_now) {
2149                 ret = HX509_CERT_USED_BEFORE_TIME;
2150                 hx509_clear_error_string(context);
2151                 goto out;
2152             }
2153             t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
2154             if (t < ctx->time_now) {
2155                 ret = HX509_CERT_USED_AFTER_TIME;
2156                 hx509_clear_error_string(context);
2157                 goto out;
2158             }
2159         }
2160
2161         if (type == EE_CERT)
2162             type = CA_CERT;
2163         else if (type == PROXY_CERT)
2164             proxy_cert_depth++;
2165     }
2166
2167     /*
2168      * Verify constraints, do this backward so path constraints are
2169      * checked in the right order.
2170      */
2171
2172     for (ret = 0, i = path.len - 1; i >= 0; i--) {
2173         Certificate *c;
2174         int selfsigned;
2175
2176         c = _hx509_get_cert(path.val[i]);
2177
2178         ret = certificate_is_self_signed(context, c, &selfsigned);
2179         if (ret)
2180             goto out;
2181
2182         /* verify name constraints, not for selfsigned and anchor */
2183         if (!selfsigned || i + 1 != path.len) {
2184             ret = check_name_constraints(context, &nc, c);
2185             if (ret) {
2186                 goto out;
2187             }
2188         }
2189         ret = add_name_constraints(context, c, i == 0, &nc);
2190         if (ret)
2191             goto out;
2192
2193         /* XXX verify all other silly constraints */
2194
2195     }
2196
2197     /*
2198      * Verify that no certificates has been revoked.
2199      */
2200
2201     if (ctx->revoke_ctx) {
2202         hx509_certs certs;
2203
2204         ret = hx509_certs_init(context, "MEMORY:revoke-certs", 0,
2205                                NULL, &certs);
2206         if (ret)
2207             goto out;
2208
2209         for (i = 0; i < path.len; i++) {
2210             ret = hx509_certs_add(context, certs, path.val[i]);
2211             if (ret) {
2212                 hx509_certs_free(&certs);
2213                 goto out;
2214             }
2215         }
2216         ret = hx509_certs_merge(context, certs, pool);
2217         if (ret) {
2218             hx509_certs_free(&certs);
2219             goto out;
2220         }
2221
2222         for (i = 0; i < path.len - 1; i++) {
2223             int parent = (i < path.len - 1) ? i + 1 : i;
2224
2225             ret = hx509_revoke_verify(context,
2226                                       ctx->revoke_ctx,
2227                                       certs,
2228                                       ctx->time_now,
2229                                       path.val[i],
2230                                       path.val[parent]);
2231             if (ret) {
2232                 hx509_certs_free(&certs);
2233                 goto out;
2234             }
2235         }
2236         hx509_certs_free(&certs);
2237     }
2238
2239     /*
2240      * Verify signatures, do this backward so public key working
2241      * parameter is passed up from the anchor up though the chain.
2242      */
2243
2244     for (i = path.len - 1; i >= 0; i--) {
2245         Certificate *signer, *c;
2246
2247         c = _hx509_get_cert(path.val[i]);
2248
2249         /* is last in chain (trust anchor) */
2250         if (i + 1 == path.len) {
2251             int selfsigned;
2252
2253             signer = path.val[i]->data;
2254
2255             ret = certificate_is_self_signed(context, signer, &selfsigned);
2256             if (ret)
2257                 goto out;
2258
2259             /* if trust anchor is not self signed, don't check sig */
2260             if (!selfsigned)
2261                 continue;
2262         } else {
2263             /* take next certificate in chain */
2264             signer = path.val[i + 1]->data;
2265         }
2266
2267         /* verify signatureValue */
2268         ret = _hx509_verify_signature_bitstring(context,
2269                                                 signer,
2270                                                 &c->signatureAlgorithm,
2271                                                 &c->tbsCertificate._save,
2272                                                 &c->signatureValue);
2273         if (ret) {
2274             hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
2275                                    "Failed to verify signature of certificate");
2276             goto out;
2277         }
2278         /* 
2279          * Verify that the sigature algorithm "best-before" date is
2280          * before the creation date of the certificate, do this for
2281          * trust anchors too, since any trust anchor that is created
2282          * after a algorithm is known to be bad deserved to be invalid.
2283          *
2284          * Skip the leaf certificate for now...
2285          */
2286
2287         if (i != 0 && (ctx->flags & HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK) == 0) {
2288             time_t notBefore = 
2289                 _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2290             ret = _hx509_signature_best_before(context,
2291                                                &c->signatureAlgorithm,
2292                                                notBefore);
2293             if (ret)
2294                 goto out;
2295         }
2296     }
2297
2298 out:
2299     hx509_certs_free(&anchors);
2300     free_Name(&proxy_issuer);
2301     free_name_constraints(&nc);
2302     _hx509_path_free(&path);
2303
2304     return ret;
2305 }
2306
2307 /**
2308  * Verify a signature made using the private key of an certificate.
2309  *
2310  * @param context A hx509 context.
2311  * @param signer the certificate that made the signature.
2312  * @param alg algorthm that was used to sign the data.
2313  * @param data the data that was signed.
2314  * @param sig the sigature to verify.
2315  *
2316  * @return An hx509 error code, see hx509_get_error_string().
2317  *
2318  * @ingroup hx509_crypto
2319  */
2320
2321 int
2322 hx509_verify_signature(hx509_context context,
2323                        const hx509_cert signer,
2324                        const AlgorithmIdentifier *alg,
2325                        const heim_octet_string *data,
2326                        const heim_octet_string *sig)
2327 {
2328     return _hx509_verify_signature(context, signer->data, alg, data, sig);
2329 }
2330
2331
2332 /**
2333  * Verify that the certificate is allowed to be used for the hostname
2334  * and address.
2335  *
2336  * @param context A hx509 context.
2337  * @param cert the certificate to match with
2338  * @param flags Flags to modify the behavior:
2339  * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
2340  * @param type type of hostname:
2341  * - HX509_HN_HOSTNAME for plain hostname.
2342  * - HX509_HN_DNSSRV for DNS SRV names.
2343  * @param hostname the hostname to check
2344  * @param sa address of the host
2345  * @param sa_size length of address
2346  *
2347  * @return An hx509 error code, see hx509_get_error_string().
2348  *
2349  * @ingroup hx509_cert
2350  */
2351
2352 int
2353 hx509_verify_hostname(hx509_context context,
2354                       const hx509_cert cert,
2355                       int flags,
2356                       hx509_hostname_type type,
2357                       const char *hostname,
2358                       const struct sockaddr *sa,
2359                       /* XXX krb5_socklen_t */ int sa_size)
2360 {
2361     GeneralNames san;
2362     int ret, i, j;
2363
2364     if (sa && sa_size <= 0)
2365         return EINVAL;
2366
2367     memset(&san, 0, sizeof(san));
2368
2369     i = 0;
2370     do {
2371         ret = find_extension_subject_alt_name(cert->data, &i, &san);
2372         if (ret == HX509_EXTENSION_NOT_FOUND) {
2373             ret = 0;
2374             break;
2375         } else if (ret != 0)
2376             break;
2377
2378         for (j = 0; j < san.len; j++) {
2379             switch (san.val[j].element) {
2380             case choice_GeneralName_dNSName:
2381                 if (strcasecmp(san.val[j].u.dNSName, hostname) == 0) {
2382                     free_GeneralNames(&san);
2383                     return 0;
2384                 }
2385                 break;
2386             default:
2387                 break;
2388             }
2389         }
2390         free_GeneralNames(&san);
2391     } while (1);
2392
2393     {
2394         const Name *name = &cert->data->tbsCertificate.subject;
2395
2396         /* match if first component is a CN= */
2397         if (name->u.rdnSequence.len > 0
2398             && name->u.rdnSequence.val[0].len == 1
2399             && der_heim_oid_cmp(&name->u.rdnSequence.val[0].val[0].type,
2400                                 oid_id_at_commonName()) == 0)
2401         {
2402             DirectoryString *ds = &name->u.rdnSequence.val[0].val[0].value;
2403
2404             switch (ds->element) {
2405             case choice_DirectoryString_printableString:
2406                 if (strcasecmp(ds->u.printableString, hostname) == 0)
2407                     return 0;
2408                 break;
2409             case choice_DirectoryString_ia5String:
2410                 if (strcasecmp(ds->u.ia5String, hostname) == 0)
2411                     return 0;
2412                 break;
2413             case choice_DirectoryString_utf8String:
2414                 if (strcasecmp(ds->u.utf8String, hostname) == 0)
2415                     return 0;
2416             default:
2417                 break;
2418             }
2419         }
2420     }
2421
2422     if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0)
2423         ret = HX509_NAME_CONSTRAINT_ERROR;
2424
2425     return ret;
2426 }
2427
2428 int
2429 _hx509_set_cert_attribute(hx509_context context,
2430                           hx509_cert cert,
2431                           const heim_oid *oid,
2432                           const heim_octet_string *attr)
2433 {
2434     hx509_cert_attribute a;
2435     void *d;
2436
2437     if (hx509_cert_get_attribute(cert, oid) != NULL)
2438         return 0;
2439
2440     d = realloc(cert->attrs.val,
2441                 sizeof(cert->attrs.val[0]) * (cert->attrs.len + 1));
2442     if (d == NULL) {
2443         hx509_clear_error_string(context);
2444         return ENOMEM;
2445     }
2446     cert->attrs.val = d;
2447
2448     a = malloc(sizeof(*a));
2449     if (a == NULL)
2450         return ENOMEM;
2451
2452     der_copy_octet_string(attr, &a->data);
2453     der_copy_oid(oid, &a->oid);
2454
2455     cert->attrs.val[cert->attrs.len] = a;
2456     cert->attrs.len++;
2457
2458     return 0;
2459 }
2460
2461 /**
2462  * Get an external attribute for the certificate, examples are
2463  * friendly name and id.
2464  *
2465  * @param cert hx509 certificate object to search
2466  * @param oid an oid to search for.
2467  *
2468  * @return an hx509_cert_attribute, only valid as long as the
2469  * certificate is referenced.
2470  *
2471  * @ingroup hx509_cert
2472  */
2473
2474 hx509_cert_attribute
2475 hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid)
2476 {
2477     int i;
2478     for (i = 0; i < cert->attrs.len; i++)
2479         if (der_heim_oid_cmp(oid, &cert->attrs.val[i]->oid) == 0)
2480             return cert->attrs.val[i];
2481     return NULL;
2482 }
2483
2484 /**
2485  * Set the friendly name on the certificate.
2486  *
2487  * @param cert The certificate to set the friendly name on
2488  * @param name Friendly name.
2489  *
2490  * @return An hx509 error code, see hx509_get_error_string().
2491  *
2492  * @ingroup hx509_cert
2493  */
2494
2495 int
2496 hx509_cert_set_friendly_name(hx509_cert cert, const char *name)
2497 {
2498     if (cert->friendlyname)
2499         free(cert->friendlyname);
2500     cert->friendlyname = strdup(name);
2501     if (cert->friendlyname == NULL)
2502         return ENOMEM;
2503     return 0;
2504 }
2505
2506 /**
2507  * Get friendly name of the certificate.
2508  *
2509  * @param cert cert to get the friendly name from.
2510  *
2511  * @return an friendly name or NULL if there is. The friendly name is
2512  * only valid as long as the certificate is referenced.
2513  *
2514  * @ingroup hx509_cert
2515  */
2516
2517 const char *
2518 hx509_cert_get_friendly_name(hx509_cert cert)
2519 {
2520     hx509_cert_attribute a;
2521     PKCS9_friendlyName n;
2522     size_t sz;
2523     int ret, i;
2524
2525     if (cert->friendlyname)
2526         return cert->friendlyname;
2527
2528     a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_friendlyName());
2529     if (a == NULL) {
2530         hx509_name name;
2531
2532         ret = hx509_cert_get_subject(cert, &name);
2533         if (ret)
2534             return NULL;
2535         ret = hx509_name_to_string(name, &cert->friendlyname);
2536         hx509_name_free(&name);
2537         if (ret)
2538             return NULL;
2539         return cert->friendlyname;
2540     }
2541
2542     ret = decode_PKCS9_friendlyName(a->data.data, a->data.length, &n, &sz);
2543     if (ret)
2544         return NULL;
2545         
2546     if (n.len != 1) {
2547         free_PKCS9_friendlyName(&n);
2548         return NULL;
2549     }
2550
2551     cert->friendlyname = malloc(n.val[0].length + 1);
2552     if (cert->friendlyname == NULL) {
2553         free_PKCS9_friendlyName(&n);
2554         return NULL;
2555     }
2556
2557     for (i = 0; i < n.val[0].length; i++) {
2558         if (n.val[0].data[i] <= 0xff)
2559             cert->friendlyname[i] = n.val[0].data[i] & 0xff;
2560         else
2561             cert->friendlyname[i] = 'X';
2562     }
2563     cert->friendlyname[i] = '\0';
2564     free_PKCS9_friendlyName(&n);
2565
2566     return cert->friendlyname;
2567 }
2568
2569 void
2570 _hx509_query_clear(hx509_query *q)
2571 {
2572     memset(q, 0, sizeof(*q));
2573 }
2574
2575 /**
2576  * Allocate an query controller. Free using hx509_query_free().
2577  *
2578  * @param context A hx509 context.
2579  * @param q return pointer to a hx509_query.
2580  *
2581  * @return An hx509 error code, see hx509_get_error_string().
2582  *
2583  * @ingroup hx509_cert
2584  */
2585
2586 int
2587 hx509_query_alloc(hx509_context context, hx509_query **q)
2588 {
2589     *q = calloc(1, sizeof(**q));
2590     if (*q == NULL)
2591         return ENOMEM;
2592     return 0;
2593 }
2594
2595
2596 /**
2597  * Set match options for the hx509 query controller.
2598  *
2599  * @param q query controller.
2600  * @param option options to control the query controller.
2601  *
2602  * @return An hx509 error code, see hx509_get_error_string().
2603  *
2604  * @ingroup hx509_cert
2605  */
2606
2607 void
2608 hx509_query_match_option(hx509_query *q, hx509_query_option option)
2609 {
2610     switch(option) {
2611     case HX509_QUERY_OPTION_PRIVATE_KEY:
2612         q->match |= HX509_QUERY_PRIVATE_KEY;
2613         break;
2614     case HX509_QUERY_OPTION_KU_ENCIPHERMENT:
2615         q->match |= HX509_QUERY_KU_ENCIPHERMENT;
2616         break;
2617     case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE:
2618         q->match |= HX509_QUERY_KU_DIGITALSIGNATURE;
2619         break;
2620     case HX509_QUERY_OPTION_KU_KEYCERTSIGN:
2621         q->match |= HX509_QUERY_KU_KEYCERTSIGN;
2622         break;
2623     case HX509_QUERY_OPTION_END:
2624     default:
2625         break;
2626     }
2627 }
2628
2629 /**
2630  * Set the issuer and serial number of match in the query
2631  * controller. The function make copies of the isser and serial number.
2632  *
2633  * @param q a hx509 query controller
2634  * @param issuer issuer to search for
2635  * @param serialNumber the serialNumber of the issuer.
2636  *
2637  * @return An hx509 error code, see hx509_get_error_string().
2638  *
2639  * @ingroup hx509_cert
2640  */
2641
2642 int
2643 hx509_query_match_issuer_serial(hx509_query *q,
2644                                 const Name *issuer,
2645                                 const heim_integer *serialNumber)
2646 {
2647     int ret;
2648     if (q->serial) {
2649         der_free_heim_integer(q->serial);
2650         free(q->serial);
2651     }
2652     q->serial = malloc(sizeof(*q->serial));
2653     if (q->serial == NULL)
2654         return ENOMEM;
2655     ret = der_copy_heim_integer(serialNumber, q->serial);
2656     if (ret) {
2657         free(q->serial);
2658         q->serial = NULL;
2659         return ret;
2660     }
2661     if (q->issuer_name) {
2662         free_Name(q->issuer_name);
2663         free(q->issuer_name);
2664     }
2665     q->issuer_name = malloc(sizeof(*q->issuer_name));
2666     if (q->issuer_name == NULL)
2667         return ENOMEM;
2668     ret = copy_Name(issuer, q->issuer_name);
2669     if (ret) {
2670         free(q->issuer_name);
2671         q->issuer_name = NULL;
2672         return ret;
2673     }
2674     q->match |= HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
2675     return 0;
2676 }
2677
2678 /**
2679  * Set the query controller to match on a friendly name
2680  *
2681  * @param q a hx509 query controller.
2682  * @param name a friendly name to match on
2683  *
2684  * @return An hx509 error code, see hx509_get_error_string().
2685  *
2686  * @ingroup hx509_cert
2687  */
2688
2689 int
2690 hx509_query_match_friendly_name(hx509_query *q, const char *name)
2691 {
2692     if (q->friendlyname)
2693         free(q->friendlyname);
2694     q->friendlyname = strdup(name);
2695     if (q->friendlyname == NULL)
2696         return ENOMEM;
2697     q->match |= HX509_QUERY_MATCH_FRIENDLY_NAME;
2698     return 0;
2699 }
2700
2701 /**
2702  * Set the query controller to require an one specific EKU (extended
2703  * key usage). Any previous EKU matching is overwitten. If NULL is
2704  * passed in as the eku, the EKU requirement is reset.
2705  *
2706  * @param q a hx509 query controller.
2707  * @param eku an EKU to match on.
2708  *
2709  * @return An hx509 error code, see hx509_get_error_string().
2710  *
2711  * @ingroup hx509_cert
2712  */
2713
2714 int
2715 hx509_query_match_eku(hx509_query *q, const heim_oid *eku)
2716 {
2717     int ret;
2718
2719     if (eku == NULL) {
2720         if (q->eku) {
2721             der_free_oid(q->eku);
2722             free(q->eku);
2723             q->eku = NULL;
2724         }
2725         q->match &= ~HX509_QUERY_MATCH_EKU;
2726     } else {
2727         if (q->eku) {
2728             der_free_oid(q->eku);
2729         } else {
2730             q->eku = calloc(1, sizeof(*q->eku));
2731             if (q->eku == NULL)
2732                 return ENOMEM;
2733         }
2734         ret = der_copy_oid(eku, q->eku);
2735         if (ret) {
2736             free(q->eku);
2737             q->eku = NULL;
2738             return ret;
2739         }
2740         q->match |= HX509_QUERY_MATCH_EKU;
2741     }
2742     return 0;
2743 }
2744
2745 int
2746 hx509_query_match_expr(hx509_context context, hx509_query *q, const char *expr)
2747 {
2748     if (q->expr) {
2749         _hx509_expr_free(q->expr);
2750         q->expr = NULL;
2751     }
2752
2753     if (expr == NULL) {
2754         q->match &= ~HX509_QUERY_MATCH_EXPR;
2755     } else {
2756         q->expr = _hx509_expr_parse(expr);
2757         if (q->expr)
2758             q->match |= HX509_QUERY_MATCH_EXPR;
2759     }
2760
2761     return 0;
2762 }
2763
2764 /**
2765  * Set the query controller to match using a specific match function.
2766  *
2767  * @param q a hx509 query controller.
2768  * @param func function to use for matching, if the argument is NULL,
2769  * the match function is removed.
2770  * @param ctx context passed to the function.
2771  *
2772  * @return An hx509 error code, see hx509_get_error_string().
2773  *
2774  * @ingroup hx509_cert
2775  */
2776
2777 int
2778 hx509_query_match_cmp_func(hx509_query *q,
2779                            int (*func)(hx509_context, hx509_cert, void *),
2780                            void *ctx)
2781 {
2782     if (func)
2783         q->match |= HX509_QUERY_MATCH_FUNCTION;
2784     else
2785         q->match &= ~HX509_QUERY_MATCH_FUNCTION;
2786     q->cmp_func = func;
2787     q->cmp_func_ctx = ctx;
2788     return 0;
2789 }
2790
2791 /**
2792  * Free the query controller.
2793  *
2794  * @param context A hx509 context.
2795  * @param q a pointer to the query controller.
2796  *
2797  * @ingroup hx509_cert
2798  */
2799
2800 void
2801 hx509_query_free(hx509_context context, hx509_query *q)
2802 {
2803     if (q == NULL)
2804         return;
2805
2806     if (q->serial) {
2807         der_free_heim_integer(q->serial);
2808         free(q->serial);
2809     }
2810     if (q->issuer_name) {
2811         free_Name(q->issuer_name);
2812         free(q->issuer_name);
2813     }
2814     if (q->eku) {
2815         der_free_oid(q->eku);
2816         free(q->eku);
2817     }
2818     if (q->friendlyname)
2819         free(q->friendlyname);
2820     if (q->expr)
2821         _hx509_expr_free(q->expr);
2822
2823     memset(q, 0, sizeof(*q));
2824     free(q);
2825 }
2826
2827 int
2828 _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert)
2829 {
2830     Certificate *c = _hx509_get_cert(cert);
2831     int ret, diff;
2832
2833     _hx509_query_statistic(context, 1, q);
2834
2835     if ((q->match & HX509_QUERY_FIND_ISSUER_CERT) &&
2836         _hx509_cert_is_parent_cmp(q->subject, c, 0) != 0)
2837         return 0;
2838
2839     if ((q->match & HX509_QUERY_MATCH_CERTIFICATE) &&
2840         _hx509_Certificate_cmp(q->certificate, c) != 0)
2841         return 0;
2842
2843     if ((q->match & HX509_QUERY_MATCH_SERIALNUMBER)
2844         && der_heim_integer_cmp(&c->tbsCertificate.serialNumber, q->serial) != 0)
2845         return 0;
2846
2847     if (q->match & HX509_QUERY_MATCH_ISSUER_NAME) {
2848         ret = _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name, &diff);
2849         if (ret || diff)
2850             return 0;
2851     }
2852
2853     if (q->match & HX509_QUERY_MATCH_SUBJECT_NAME) {
2854         ret = _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name, &diff);
2855         if (ret || diff)
2856             return 0;
2857     }
2858
2859     if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) {
2860         SubjectKeyIdentifier si;
2861
2862         ret = _hx509_find_extension_subject_key_id(c, &si);
2863         if (ret == 0) {
2864             if (der_heim_octet_string_cmp(&si, q->subject_id) != 0)
2865                 ret = 1;
2866             free_SubjectKeyIdentifier(&si);
2867         }
2868         if (ret)
2869             return 0;
2870     }
2871     if ((q->match & HX509_QUERY_MATCH_ISSUER_ID))
2872         return 0;
2873     if ((q->match & HX509_QUERY_PRIVATE_KEY) &&
2874         _hx509_cert_private_key(cert) == NULL)
2875         return 0;
2876
2877     {
2878         unsigned ku = 0;
2879         if (q->match & HX509_QUERY_KU_DIGITALSIGNATURE)
2880             ku |= (1 << 0);
2881         if (q->match & HX509_QUERY_KU_NONREPUDIATION)
2882             ku |= (1 << 1);
2883         if (q->match & HX509_QUERY_KU_ENCIPHERMENT)
2884             ku |= (1 << 2);
2885         if (q->match & HX509_QUERY_KU_DATAENCIPHERMENT)
2886             ku |= (1 << 3);
2887         if (q->match & HX509_QUERY_KU_KEYAGREEMENT)
2888             ku |= (1 << 4);
2889         if (q->match & HX509_QUERY_KU_KEYCERTSIGN)
2890             ku |= (1 << 5);
2891         if (q->match & HX509_QUERY_KU_CRLSIGN)
2892             ku |= (1 << 6);
2893         if (ku && check_key_usage(context, c, ku, TRUE))
2894             return 0;
2895     }
2896     if ((q->match & HX509_QUERY_ANCHOR))
2897         return 0;
2898
2899     if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) {
2900         hx509_cert_attribute a;
2901
2902         a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_localKeyId());
2903         if (a == NULL)
2904             return 0;
2905         if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0)
2906             return 0;
2907     }
2908
2909     if (q->match & HX509_QUERY_NO_MATCH_PATH) {
2910         size_t i;
2911
2912         for (i = 0; i < q->path->len; i++)
2913             if (hx509_cert_cmp(q->path->val[i], cert) == 0)
2914                 return 0;
2915     }
2916     if (q->match & HX509_QUERY_MATCH_FRIENDLY_NAME) {
2917         const char *name = hx509_cert_get_friendly_name(cert);
2918         if (name == NULL)
2919             return 0;
2920         if (strcasecmp(q->friendlyname, name) != 0)
2921             return 0;
2922     }
2923     if (q->match & HX509_QUERY_MATCH_FUNCTION) {
2924         ret = (*q->cmp_func)(context, cert, q->cmp_func_ctx);
2925         if (ret != 0)
2926             return 0;
2927     }
2928
2929     if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) {
2930         heim_octet_string os;
2931
2932         os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
2933         os.length =
2934             c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
2935
2936         ret = _hx509_verify_signature(context,
2937                                       NULL,
2938                                       hx509_signature_sha1(),
2939                                       &os,
2940                                       q->keyhash_sha1);
2941         if (ret != 0)
2942             return 0;
2943     }
2944
2945     if (q->match & HX509_QUERY_MATCH_TIME) {
2946         time_t t;
2947         t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2948         if (t > q->timenow)
2949             return 0;
2950         t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
2951         if (t < q->timenow)
2952             return 0;
2953     }
2954
2955     /* If an EKU is required, check the cert for it. */
2956     if ((q->match & HX509_QUERY_MATCH_EKU) &&
2957         hx509_cert_check_eku(context, cert, q->eku, 0))
2958         return 0;
2959
2960     if ((q->match & HX509_QUERY_MATCH_EXPR)) {
2961         hx509_env env = NULL;
2962
2963         ret = _hx509_cert_to_env(context, cert, &env);
2964         if (ret)
2965             return 0;
2966
2967         ret = _hx509_expr_eval(context, env, q->expr);
2968         hx509_env_free(&env);
2969         if (ret == 0)
2970             return 0;
2971     }
2972
2973     if (q->match & ~HX509_QUERY_MASK)
2974         return 0;
2975
2976     return 1;
2977 }
2978
2979 /**
2980  * Set a statistic file for the query statistics.
2981  *
2982  * @param context A hx509 context.
2983  * @param fn statistics file name
2984  *
2985  * @ingroup hx509_cert
2986  */
2987
2988 void
2989 hx509_query_statistic_file(hx509_context context, const char *fn)
2990 {
2991     if (context->querystat)
2992         free(context->querystat);
2993     context->querystat = strdup(fn);
2994 }
2995
2996 void
2997 _hx509_query_statistic(hx509_context context, int type, const hx509_query *q)
2998 {
2999     FILE *f;
3000     if (context->querystat == NULL)
3001         return;
3002     f = fopen(context->querystat, "a");
3003     if (f == NULL)
3004         return;
3005     rk_cloexec_file(f);
3006     fprintf(f, "%d %d\n", type, q->match);
3007     fclose(f);
3008 }
3009
3010 static const char *statname[] = {
3011     "find issuer cert",
3012     "match serialnumber",
3013     "match issuer name",
3014     "match subject name",
3015     "match subject key id",
3016     "match issuer id",
3017     "private key",
3018     "ku encipherment",
3019     "ku digitalsignature",
3020     "ku keycertsign",
3021     "ku crlsign",
3022     "ku nonrepudiation",
3023     "ku keyagreement",
3024     "ku dataencipherment",
3025     "anchor",
3026     "match certificate",
3027     "match local key id",
3028     "no match path",
3029     "match friendly name",
3030     "match function",
3031     "match key hash sha1",
3032     "match time"
3033 };
3034
3035 struct stat_el {
3036     unsigned long stats;
3037     unsigned int index;
3038 };
3039
3040
3041 static int
3042 stat_sort(const void *a, const void *b)
3043 {
3044     const struct stat_el *ae = a;
3045     const struct stat_el *be = b;
3046     return be->stats - ae->stats;
3047 }
3048
3049 /**
3050  * Unparse the statistics file and print the result on a FILE descriptor.
3051  *
3052  * @param context A hx509 context.
3053  * @param printtype tyep to print
3054  * @param out the FILE to write the data on.
3055  *
3056  * @ingroup hx509_cert
3057  */
3058
3059 void
3060 hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out)
3061 {
3062     rtbl_t t;
3063     FILE *f;
3064     int type, mask, i, num;
3065     unsigned long multiqueries = 0, totalqueries = 0;
3066     struct stat_el stats[32];
3067
3068     if (context->querystat == NULL)
3069         return;
3070     f = fopen(context->querystat, "r");
3071     if (f == NULL) {
3072         fprintf(out, "No statistic file %s: %s.\n",
3073                 context->querystat, strerror(errno));
3074         return;
3075     }
3076     rk_cloexec_file(f);
3077
3078     for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3079         stats[i].index = i;
3080         stats[i].stats = 0;
3081     }
3082
3083     while (fscanf(f, "%d %d\n", &type, &mask) == 2) {
3084         if (type != printtype)
3085             continue;
3086         num = i = 0;
3087         while (mask && i < sizeof(stats)/sizeof(stats[0])) {
3088             if (mask & 1) {
3089                 stats[i].stats++;
3090                 num++;
3091             }
3092             mask = mask >>1 ;
3093             i++;
3094         }
3095         if (num > 1)
3096             multiqueries++;
3097         totalqueries++;
3098     }
3099     fclose(f);
3100
3101     qsort(stats, sizeof(stats)/sizeof(stats[0]), sizeof(stats[0]), stat_sort);
3102
3103     t = rtbl_create();
3104     if (t == NULL)
3105         errx(1, "out of memory");
3106
3107     rtbl_set_separator (t, "  ");
3108
3109     rtbl_add_column_by_id (t, 0, "Name", 0);
3110     rtbl_add_column_by_id (t, 1, "Counter", 0);
3111
3112
3113     for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3114         char str[10];
3115
3116         if (stats[i].index < sizeof(statname)/sizeof(statname[0]))
3117             rtbl_add_column_entry_by_id (t, 0, statname[stats[i].index]);
3118         else {
3119             snprintf(str, sizeof(str), "%d", stats[i].index);
3120             rtbl_add_column_entry_by_id (t, 0, str);
3121         }
3122         snprintf(str, sizeof(str), "%lu", stats[i].stats);
3123         rtbl_add_column_entry_by_id (t, 1, str);
3124     }
3125
3126     rtbl_format(t, out);
3127     rtbl_destroy(t);
3128
3129     fprintf(out, "\nQueries: multi %lu total %lu\n",
3130             multiqueries, totalqueries);
3131 }
3132
3133 /**
3134  * Check the extended key usage on the hx509 certificate.
3135  *
3136  * @param context A hx509 context.
3137  * @param cert A hx509 context.
3138  * @param eku the EKU to check for
3139  * @param allow_any_eku if the any EKU is set, allow that to be a
3140  * substitute.
3141  *
3142  * @return An hx509 error code, see hx509_get_error_string().
3143  *
3144  * @ingroup hx509_cert
3145  */
3146
3147 int
3148 hx509_cert_check_eku(hx509_context context, hx509_cert cert,
3149                      const heim_oid *eku, int allow_any_eku)
3150 {
3151     ExtKeyUsage e;
3152     int ret, i;
3153
3154     ret = find_extension_eku(_hx509_get_cert(cert), &e);
3155     if (ret) {
3156         hx509_clear_error_string(context);
3157         return ret;
3158     }
3159
3160     for (i = 0; i < e.len; i++) {
3161         if (der_heim_oid_cmp(eku, &e.val[i]) == 0) {
3162             free_ExtKeyUsage(&e);
3163             return 0;
3164         }
3165         if (allow_any_eku) {
3166 #if 0
3167             if (der_heim_oid_cmp(id_any_eku, &e.val[i]) == 0) {
3168                 free_ExtKeyUsage(&e);
3169                 return 0;
3170             }
3171 #endif
3172         }
3173     }
3174     free_ExtKeyUsage(&e);
3175     hx509_clear_error_string(context);
3176     return HX509_CERTIFICATE_MISSING_EKU;
3177 }
3178
3179 int
3180 _hx509_cert_get_keyusage(hx509_context context,
3181                          hx509_cert c,
3182                          KeyUsage *ku)
3183 {
3184     Certificate *cert;
3185     const Extension *e;
3186     size_t size;
3187     int ret, i = 0;
3188
3189     memset(ku, 0, sizeof(*ku));
3190
3191     cert = _hx509_get_cert(c);
3192
3193     if (_hx509_cert_get_version(cert) < 3)
3194         return 0;
3195
3196     e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
3197     if (e == NULL)
3198         return HX509_KU_CERT_MISSING;
3199
3200     ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, ku, &size);
3201     if (ret)
3202         return ret;
3203     return 0;
3204 }
3205
3206 int
3207 _hx509_cert_get_eku(hx509_context context,
3208                     hx509_cert cert,
3209                     ExtKeyUsage *e)
3210 {
3211     int ret;
3212
3213     memset(e, 0, sizeof(*e));
3214
3215     ret = find_extension_eku(_hx509_get_cert(cert), e);
3216     if (ret && ret != HX509_EXTENSION_NOT_FOUND) {
3217         hx509_clear_error_string(context);
3218         return ret;
3219     }
3220     return 0;
3221 }
3222
3223 /**
3224  * Encodes the hx509 certificate as a DER encode binary.
3225  *
3226  * @param context A hx509 context.
3227  * @param c the certificate to encode.
3228  * @param os the encode certificate, set to NULL, 0 on case of
3229  * error. Free the returned structure with hx509_xfree().
3230  *
3231  * @return An hx509 error code, see hx509_get_error_string().
3232  *
3233  * @ingroup hx509_cert
3234  */
3235
3236 int
3237 hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
3238 {
3239     size_t size;
3240     int ret;
3241
3242     os->data = NULL;
3243     os->length = 0;
3244
3245     ASN1_MALLOC_ENCODE(Certificate, os->data, os->length,
3246                        _hx509_get_cert(c), &size, ret);
3247     if (ret) {
3248         os->data = NULL;
3249         os->length = 0;
3250         return ret;
3251     }
3252     if (os->length != size)
3253         _hx509_abort("internal ASN.1 encoder error");
3254
3255     return ret;
3256 }
3257
3258 /*
3259  * Last to avoid lost __attribute__s due to #undef.
3260  */
3261
3262 #undef __attribute__
3263 #define __attribute__(X)
3264
3265 void
3266 _hx509_abort(const char *fmt, ...)
3267      __attribute__ ((noreturn, format (printf, 1, 2)))
3268 {
3269     va_list ap;
3270     va_start(ap, fmt);
3271     vprintf(fmt, ap);
3272     va_end(ap);
3273     printf("\n");
3274     fflush(stdout);
3275     abort();
3276 }
3277
3278 /**
3279  * Free a data element allocated in the library.
3280  *
3281  * @param ptr data to be freed.
3282  *
3283  * @ingroup hx509_misc
3284  */
3285
3286 void
3287 hx509_xfree(void *ptr)
3288 {
3289     free(ptr);
3290 }
3291
3292 /**
3293  *
3294  */
3295
3296 int
3297 _hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env)
3298 {
3299     ExtKeyUsage eku;
3300     hx509_name name;
3301     char *buf;
3302     int ret;
3303     hx509_env envcert = NULL;
3304
3305     *env = NULL;
3306
3307     /* version */
3308     asprintf(&buf, "%d", _hx509_cert_get_version(_hx509_get_cert(cert)));
3309     ret = hx509_env_add(context, &envcert, "version", buf);
3310     free(buf);
3311     if (ret)
3312         goto out;
3313
3314     /* subject */
3315     ret = hx509_cert_get_subject(cert, &name);
3316     if (ret)
3317         goto out;
3318
3319     ret = hx509_name_to_string(name, &buf);
3320     if (ret) {
3321         hx509_name_free(&name);
3322         goto out;
3323     }
3324
3325     ret = hx509_env_add(context, &envcert, "subject", buf);
3326     hx509_name_free(&name);
3327     if (ret)
3328         goto out;
3329
3330     /* issuer */
3331     ret = hx509_cert_get_issuer(cert, &name);
3332     if (ret)
3333         goto out;
3334
3335     ret = hx509_name_to_string(name, &buf);
3336     hx509_name_free(&name);
3337     if (ret)
3338         goto out;
3339
3340     ret = hx509_env_add(context, &envcert, "issuer", buf);
3341     hx509_xfree(buf);
3342     if (ret)
3343         goto out;
3344
3345     /* eku */
3346
3347     ret = _hx509_cert_get_eku(context, cert, &eku);
3348     if (ret == HX509_EXTENSION_NOT_FOUND)
3349         ;
3350     else if (ret != 0)
3351         goto out;
3352     else {
3353         int i;
3354         hx509_env enveku = NULL;
3355
3356         for (i = 0; i < eku.len; i++) {
3357
3358             ret = der_print_heim_oid(&eku.val[i], '.', &buf);
3359             if (ret) {
3360                 free_ExtKeyUsage(&eku);
3361                 hx509_env_free(&enveku);
3362                 goto out;
3363             }
3364             ret = hx509_env_add(context, &enveku, buf, "oid-name-here");
3365             free(buf);
3366             if (ret) {
3367                 free_ExtKeyUsage(&eku);
3368                 hx509_env_free(&enveku);
3369                 goto out;
3370             }
3371         }
3372         free_ExtKeyUsage(&eku);
3373
3374         ret = hx509_env_add_binding(context, &envcert, "eku", enveku);
3375         if (ret) {
3376             hx509_env_free(&enveku);
3377             goto out;
3378         }
3379     }
3380
3381     {
3382         Certificate *c = _hx509_get_cert(cert);
3383         heim_octet_string os, sig;
3384         hx509_env envhash = NULL;
3385         char *buf;
3386
3387         os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
3388         os.length =
3389           c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
3390
3391         ret = _hx509_create_signature(context,
3392                                       NULL,
3393                                       hx509_signature_sha1(),
3394                                       &os,
3395                                       NULL,
3396                                       &sig);
3397         if (ret != 0)
3398             goto out;
3399
3400         ret = hex_encode(sig.data, sig.length, &buf);
3401         der_free_octet_string(&sig);
3402         if (ret < 0) {
3403             ret = ENOMEM;
3404             hx509_set_error_string(context, 0, ret,
3405                                    "Out of memory");
3406             goto out;
3407         }
3408         
3409         ret = hx509_env_add(context, &envhash, "sha1", buf);
3410         free(buf);
3411         if (ret) 
3412             goto out;
3413
3414         ret = hx509_env_add_binding(context, &envcert, "hash", envhash);
3415         if (ret) {
3416           hx509_env_free(&envhash);
3417           goto out;
3418         }
3419     }
3420
3421     ret = hx509_env_add_binding(context, env, "certificate", envcert);
3422     if (ret)
3423         goto out;
3424
3425     return 0;
3426
3427 out:
3428     hx509_env_free(&envcert);
3429     return ret;
3430 }