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