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