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