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