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