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