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