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