1 /*	$NetBSD: cert.c,v 1.3 2014/04/24 13:45:34 pettai Exp $	*/
2 
3 /*
4  * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include "hx_locl.h"
37 #include "crypto-headers.h"
38 #include <krb5/rtbl.h>
39 
40 /**
41  * @page page_cert The basic certificate
42  *
43  * The basic hx509 cerificate object in hx509 is hx509_cert. The
44  * hx509_cert object is representing one X509/PKIX certificate and
45  * associated attributes; like private key, friendly name, etc.
46  *
47  * A hx509_cert object is usully found via the keyset interfaces (@ref
48  * page_keyset), but its also possible to create a certificate
49  * directly from a parsed object with hx509_cert_init() and
50  * hx509_cert_init_data().
51  *
52  * See the library functions here: @ref hx509_cert
53  */
54 
55 struct hx509_verify_ctx_data {
56     hx509_certs trust_anchors;
57     int flags;
58 #define HX509_VERIFY_CTX_F_TIME_SET			1
59 #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE	2
60 #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280		4
61 #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS		8
62 #define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS		16
63 #define HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK		32
64     time_t time_now;
65     unsigned int max_depth;
66 #define HX509_VERIFY_MAX_DEPTH 30
67     hx509_revoke_ctx revoke_ctx;
68 };
69 
70 #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
71 #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
72 #define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0)
73 
74 struct _hx509_cert_attrs {
75     size_t len;
76     hx509_cert_attribute *val;
77 };
78 
79 struct hx509_cert_data {
80     unsigned int ref;
81     char *friendlyname;
82     Certificate *data;
83     hx509_private_key private_key;
84     struct _hx509_cert_attrs attrs;
85     hx509_name basename;
86     _hx509_cert_release_func release;
87     void *ctx;
88 };
89 
90 typedef struct hx509_name_constraints {
91     NameConstraints *val;
92     size_t len;
93 } hx509_name_constraints;
94 
95 #define GeneralSubtrees_SET(g,var) \
96 	(g)->len = (var)->len, (g)->val = (var)->val;
97 
98 /**
99  * Creates a hx509 context that most functions in the library
100  * uses. The context is only allowed to be used by one thread at each
101  * moment. Free the context with hx509_context_free().
102  *
103  * @param context Returns a pointer to new hx509 context.
104  *
105  * @return Returns an hx509 error code.
106  *
107  * @ingroup hx509
108  */
109 
110 int
hx509_context_init(hx509_context * context)111 hx509_context_init(hx509_context *context)
112 {
113     *context = calloc(1, sizeof(**context));
114     if (*context == NULL)
115 	return ENOMEM;
116 
117     _hx509_ks_null_register(*context);
118     _hx509_ks_mem_register(*context);
119     _hx509_ks_file_register(*context);
120     _hx509_ks_pkcs12_register(*context);
121     _hx509_ks_pkcs11_register(*context);
122     _hx509_ks_dir_register(*context);
123     _hx509_ks_keychain_register(*context);
124 
125     ENGINE_add_conf_module();
126     OpenSSL_add_all_algorithms();
127 
128     (*context)->ocsp_time_diff = HX509_DEFAULT_OCSP_TIME_DIFF;
129 
130     initialize_hx_error_table_r(&(*context)->et_list);
131     initialize_asn1_error_table_r(&(*context)->et_list);
132 
133 #ifdef HX509_DEFAULT_ANCHORS
134     (void)hx509_certs_init(*context, HX509_DEFAULT_ANCHORS, 0,
135 			   NULL, &(*context)->default_trust_anchors);
136 #endif
137 
138     return 0;
139 }
140 
141 /**
142  * Selects if the hx509_revoke_verify() function is going to require
143  * the existans of a revokation method (OCSP, CRL) or not. Note that
144  * hx509_verify_path(), hx509_cms_verify_signed(), and other function
145  * call hx509_revoke_verify().
146  *
147  * @param context hx509 context to change the flag for.
148  * @param flag zero, revokation method required, non zero missing
149  * revokation method ok
150  *
151  * @ingroup hx509_verify
152  */
153 
154 void
hx509_context_set_missing_revoke(hx509_context context,int flag)155 hx509_context_set_missing_revoke(hx509_context context, int flag)
156 {
157     if (flag)
158 	context->flags |= HX509_CTX_VERIFY_MISSING_OK;
159     else
160 	context->flags &= ~HX509_CTX_VERIFY_MISSING_OK;
161 }
162 
163 /**
164  * Free the context allocated by hx509_context_init().
165  *
166  * @param context context to be freed.
167  *
168  * @ingroup hx509
169  */
170 
171 void
hx509_context_free(hx509_context * context)172 hx509_context_free(hx509_context *context)
173 {
174     hx509_clear_error_string(*context);
175     if ((*context)->ks_ops) {
176 	free((*context)->ks_ops);
177 	(*context)->ks_ops = NULL;
178     }
179     (*context)->ks_num_ops = 0;
180     free_error_table ((*context)->et_list);
181     if ((*context)->querystat)
182 	free((*context)->querystat);
183     memset(*context, 0, sizeof(**context));
184     free(*context);
185     *context = NULL;
186 }
187 
188 /*
189  *
190  */
191 
192 Certificate *
_hx509_get_cert(hx509_cert cert)193 _hx509_get_cert(hx509_cert cert)
194 {
195     return cert->data;
196 }
197 
198 /*
199  *
200  */
201 
202 int
_hx509_cert_get_version(const Certificate * t)203 _hx509_cert_get_version(const Certificate *t)
204 {
205     return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1;
206 }
207 
208 /**
209  * Allocate and init an hx509 certificate object from the decoded
210  * certificate `c´.
211  *
212  * @param context A hx509 context.
213  * @param c
214  * @param cert
215  *
216  * @return Returns an hx509 error code.
217  *
218  * @ingroup hx509_cert
219  */
220 
221 int
hx509_cert_init(hx509_context context,const Certificate * c,hx509_cert * cert)222 hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert)
223 {
224     int ret;
225 
226     *cert = malloc(sizeof(**cert));
227     if (*cert == NULL)
228 	return ENOMEM;
229     (*cert)->ref = 1;
230     (*cert)->friendlyname = NULL;
231     (*cert)->attrs.len = 0;
232     (*cert)->attrs.val = NULL;
233     (*cert)->private_key = NULL;
234     (*cert)->basename = NULL;
235     (*cert)->release = NULL;
236     (*cert)->ctx = NULL;
237 
238     (*cert)->data = calloc(1, sizeof(*(*cert)->data));
239     if ((*cert)->data == NULL) {
240 	free(*cert);
241 	return ENOMEM;
242     }
243     ret = copy_Certificate(c, (*cert)->data);
244     if (ret) {
245 	free((*cert)->data);
246 	free(*cert);
247 	*cert = NULL;
248     }
249     return ret;
250 }
251 
252 /**
253  * Just like hx509_cert_init(), but instead of a decode certificate
254  * takes an pointer and length to a memory region that contains a
255  * DER/BER encoded certificate.
256  *
257  * If the memory region doesn't contain just the certificate and
258  * nothing more the function will fail with
259  * HX509_EXTRA_DATA_AFTER_STRUCTURE.
260  *
261  * @param context A hx509 context.
262  * @param ptr pointer to memory region containing encoded certificate.
263  * @param len length of memory region.
264  * @param cert a return pointer to a hx509 certificate object, will
265  * contain NULL on error.
266  *
267  * @return An hx509 error code, see hx509_get_error_string().
268  *
269  * @ingroup hx509_cert
270  */
271 
272 int
hx509_cert_init_data(hx509_context context,const void * ptr,size_t len,hx509_cert * cert)273 hx509_cert_init_data(hx509_context context,
274 		     const void *ptr,
275 		     size_t len,
276 		     hx509_cert *cert)
277 {
278     Certificate t;
279     size_t size;
280     int ret;
281 
282     ret = decode_Certificate(ptr, len, &t, &size);
283     if (ret) {
284 	hx509_set_error_string(context, 0, ret, "Failed to decode certificate");
285 	return ret;
286     }
287     if (size != len) {
288 	free_Certificate(&t);
289 	hx509_set_error_string(context, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE,
290 			       "Extra data after certificate");
291 	return HX509_EXTRA_DATA_AFTER_STRUCTURE;
292     }
293 
294     ret = hx509_cert_init(context, &t, cert);
295     free_Certificate(&t);
296     return ret;
297 }
298 
299 void
_hx509_cert_set_release(hx509_cert cert,_hx509_cert_release_func release,void * ctx)300 _hx509_cert_set_release(hx509_cert cert,
301 			_hx509_cert_release_func release,
302 			void *ctx)
303 {
304     cert->release = release;
305     cert->ctx = ctx;
306 }
307 
308 
309 /* Doesn't make a copy of `private_key'. */
310 
311 int
_hx509_cert_assign_key(hx509_cert cert,hx509_private_key private_key)312 _hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key)
313 {
314     if (cert->private_key)
315 	hx509_private_key_free(&cert->private_key);
316     cert->private_key = _hx509_private_key_ref(private_key);
317     return 0;
318 }
319 
320 /**
321  * Free reference to the hx509 certificate object, if the refcounter
322  * reaches 0, the object if freed. Its allowed to pass in NULL.
323  *
324  * @param cert the cert to free.
325  *
326  * @ingroup hx509_cert
327  */
328 
329 void
hx509_cert_free(hx509_cert cert)330 hx509_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 
374 hx509_cert
hx509_cert_ref(hx509_cert cert)375 hx509_cert_ref(hx509_cert cert)
376 {
377     if (cert == NULL)
378 	return NULL;
379     if (cert->ref <= 0)
380 	_hx509_abort("cert refcount <= 0");
381     cert->ref++;
382     if (cert->ref == 0)
383 	_hx509_abort("cert refcount == 0");
384     return cert;
385 }
386 
387 /**
388  * Allocate an verification context that is used fo control the
389  * verification process.
390  *
391  * @param context A hx509 context.
392  * @param ctx returns a pointer to a hx509_verify_ctx object.
393  *
394  * @return An hx509 error code, see hx509_get_error_string().
395  *
396  * @ingroup hx509_verify
397  */
398 
399 int
hx509_verify_init_ctx(hx509_context context,hx509_verify_ctx * ctx)400 hx509_verify_init_ctx(hx509_context context, hx509_verify_ctx *ctx)
401 {
402     hx509_verify_ctx c;
403 
404     c = calloc(1, sizeof(*c));
405     if (c == NULL)
406 	return ENOMEM;
407 
408     c->max_depth = HX509_VERIFY_MAX_DEPTH;
409 
410     *ctx = c;
411 
412     return 0;
413 }
414 
415 /**
416  * Free an hx509 verification context.
417  *
418  * @param ctx the context to be freed.
419  *
420  * @ingroup hx509_verify
421  */
422 
423 void
hx509_verify_destroy_ctx(hx509_verify_ctx ctx)424 hx509_verify_destroy_ctx(hx509_verify_ctx ctx)
425 {
426     if (ctx) {
427 	hx509_certs_free(&ctx->trust_anchors);
428 	hx509_revoke_free(&ctx->revoke_ctx);
429 	memset(ctx, 0, sizeof(*ctx));
430     }
431     free(ctx);
432 }
433 
434 /**
435  * Set the trust anchors in the verification context, makes an
436  * reference to the keyset, so the consumer can free the keyset
437  * independent of the destruction of the verification context (ctx).
438  * If there already is a keyset attached, it's released.
439  *
440  * @param ctx a verification context
441  * @param set a keyset containing the trust anchors.
442  *
443  * @ingroup hx509_verify
444  */
445 
446 void
hx509_verify_attach_anchors(hx509_verify_ctx ctx,hx509_certs set)447 hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set)
448 {
449     if (ctx->trust_anchors)
450 	hx509_certs_free(&ctx->trust_anchors);
451     ctx->trust_anchors = hx509_certs_ref(set);
452 }
453 
454 /**
455  * Attach an revocation context to the verfication context, , makes an
456  * reference to the revoke context, so the consumer can free the
457  * revoke context independent of the destruction of the verification
458  * context. If there is no revoke context, the verification process is
459  * NOT going to check any verification status.
460  *
461  * @param ctx a verification context.
462  * @param revoke_ctx a revoke context.
463  *
464  * @ingroup hx509_verify
465  */
466 
467 void
hx509_verify_attach_revoke(hx509_verify_ctx ctx,hx509_revoke_ctx revoke_ctx)468 hx509_verify_attach_revoke(hx509_verify_ctx ctx, hx509_revoke_ctx revoke_ctx)
469 {
470     if (ctx->revoke_ctx)
471 	hx509_revoke_free(&ctx->revoke_ctx);
472     ctx->revoke_ctx = _hx509_revoke_ref(revoke_ctx);
473 }
474 
475 /**
476  * Set the clock time the the verification process is going to
477  * use. Used to check certificate in the past and future time. If not
478  * set the current time will be used.
479  *
480  * @param ctx a verification context.
481  * @param t the time the verifiation is using.
482  *
483  *
484  * @ingroup hx509_verify
485  */
486 
487 void
hx509_verify_set_time(hx509_verify_ctx ctx,time_t t)488 hx509_verify_set_time(hx509_verify_ctx ctx, time_t t)
489 {
490     ctx->flags |= HX509_VERIFY_CTX_F_TIME_SET;
491     ctx->time_now = t;
492 }
493 
494 time_t
_hx509_verify_get_time(hx509_verify_ctx ctx)495 _hx509_verify_get_time(hx509_verify_ctx ctx)
496 {
497     return ctx->time_now;
498 }
499 
500 /**
501  * Set the maximum depth of the certificate chain that the path
502  * builder is going to try.
503  *
504  * @param ctx a verification context
505  * @param max_depth maxium depth of the certificate chain, include
506  * trust anchor.
507  *
508  * @ingroup hx509_verify
509  */
510 
511 void
hx509_verify_set_max_depth(hx509_verify_ctx ctx,unsigned int max_depth)512 hx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth)
513 {
514     ctx->max_depth = max_depth;
515 }
516 
517 /**
518  * Allow or deny the use of proxy certificates
519  *
520  * @param ctx a verification context
521  * @param boolean if non zero, allow proxy certificates.
522  *
523  * @ingroup hx509_verify
524  */
525 
526 void
hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx,int boolean)527 hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean)
528 {
529     if (boolean)
530 	ctx->flags |= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
531     else
532 	ctx->flags &= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
533 }
534 
535 /**
536  * Select strict RFC3280 verification of certificiates. This means
537  * checking key usage on CA certificates, this will make version 1
538  * certificiates unuseable.
539  *
540  * @param ctx a verification context
541  * @param boolean if non zero, use strict verification.
542  *
543  * @ingroup hx509_verify
544  */
545 
546 void
hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx,int boolean)547 hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean)
548 {
549     if (boolean)
550 	ctx->flags |= HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
551     else
552 	ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
553 }
554 
555 /**
556  * Allow using the operating system builtin trust anchors if no other
557  * trust anchors are configured.
558  *
559  * @param ctx a verification context
560  * @param boolean if non zero, useing the operating systems builtin
561  * trust anchors.
562  *
563  *
564  * @return An hx509 error code, see hx509_get_error_string().
565  *
566  * @ingroup hx509_cert
567  */
568 
569 void
hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx,int boolean)570 hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean)
571 {
572     if (boolean)
573 	ctx->flags &= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
574     else
575 	ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
576 }
577 
578 void
hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx,int boolean)579 hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx,
580 						    int boolean)
581 {
582     if (boolean)
583 	ctx->flags &= ~HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
584     else
585 	ctx->flags |= HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
586 }
587 
588 static const Extension *
find_extension(const Certificate * cert,const heim_oid * oid,size_t * idx)589 find_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 
603 static int
find_extension_auth_key_id(const Certificate * subject,AuthorityKeyIdentifier * ai)604 find_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 
622 int
_hx509_find_extension_subject_key_id(const Certificate * issuer,SubjectKeyIdentifier * si)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 
641 static int
find_extension_name_constraints(const Certificate * subject,NameConstraints * nc)642 find_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 
660 static int
find_extension_subject_alt_name(const Certificate * cert,size_t * i,GeneralNames * sa)661 find_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 
678 static int
find_extension_eku(const Certificate * cert,ExtKeyUsage * eku)679 find_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 
696 static int
add_to_list(hx509_octet_string_list * list,const heim_octet_string * entry)697 add_to_list(hx509_octet_string_list *list, const heim_octet_string *entry)
698 {
699     void *p;
700     int ret;
701 
702     p = realloc(list->val, (list->len + 1) * sizeof(list->val[0]));
703     if (p == NULL)
704 	return ENOMEM;
705     list->val = p;
706     ret = der_copy_octet_string(entry, &list->val[list->len]);
707     if (ret)
708 	return ret;
709     list->len++;
710     return 0;
711 }
712 
713 /**
714  * Free a list of octet strings returned by another hx509 library
715  * function.
716  *
717  * @param list list to be freed.
718  *
719  * @ingroup hx509_misc
720  */
721 
722 void
hx509_free_octet_string_list(hx509_octet_string_list * list)723 hx509_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 
750 int
hx509_cert_find_subjectAltName_otherName(hx509_context context,hx509_cert cert,const heim_oid * oid,hx509_octet_string_list * list)751 hx509_cert_find_subjectAltName_otherName(hx509_context context,
752 					 hx509_cert cert,
753 					 const heim_oid *oid,
754 					 hx509_octet_string_list *list)
755 {
756     GeneralNames sa;
757     int ret;
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 
795 static int
check_key_usage(hx509_context context,const Certificate * cert,unsigned flags,int req_present)796 check_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 
845 int
_hx509_check_key_usage(hx509_context context,hx509_cert cert,unsigned flags,int req_present)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 
852 enum certtype { PROXY_CERT, EE_CERT, CA_CERT };
853 
854 static int
check_basic_constraints(hx509_context context,const Certificate * cert,enum certtype type,size_t depth)855 check_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 
911 int
_hx509_cert_is_parent_cmp(const Certificate * subject,const Certificate * issuer,int allow_self_signed)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 
999 static int
certificate_is_anchor(hx509_context context,hx509_certs trust_anchors,const hx509_cert cert)1000 certificate_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 
1022 static int
certificate_is_self_signed(hx509_context context,const Certificate * cert,int * self_signed)1023 certificate_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 
1044 static int
subject_null_p(const Certificate * c)1045 subject_null_p(const Certificate *c)
1046 {
1047     return c->tbsCertificate.subject.u.rdnSequence.len == 0;
1048 }
1049 
1050 
1051 static int
find_parent(hx509_context context,time_t time_now,hx509_certs trust_anchors,hx509_path * path,hx509_certs pool,hx509_cert current,hx509_cert * parent)1052 find_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 
1144 static int
is_proxy_cert(hx509_context context,const Certificate * cert,ProxyCertInfo * rinfo)1145 is_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 
1190 int
_hx509_path_append(hx509_context context,hx509_path * path,hx509_cert cert)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 
1207 void
_hx509_path_free(hx509_path * path)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 
1236 int
_hx509_calculate_path(hx509_context context,int flags,time_t time_now,hx509_certs anchors,unsigned int max_depth,hx509_cert cert,hx509_certs pool,hx509_path * path)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 
1292 int
_hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier * p,const AlgorithmIdentifier * q)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 
1314 int
_hx509_Certificate_cmp(const Certificate * p,const Certificate * q)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 
1342 int
hx509_cert_cmp(hx509_cert p,hx509_cert q)1343 hx509_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 
1360 int
hx509_cert_get_issuer(hx509_cert p,hx509_name * name)1361 hx509_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 
1378 int
hx509_cert_get_subject(hx509_cert p,hx509_name * name)1379 hx509_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 
1401 int
hx509_cert_get_base_subject(hx509_context context,hx509_cert c,hx509_name * name)1402 hx509_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 
1428 int
hx509_cert_get_serialnumber(hx509_cert p,heim_integer * i)1429 hx509_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 
1444 time_t
hx509_cert_get_notBefore(hx509_cert p)1445 hx509_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 
1460 time_t
hx509_cert_get_notAfter(hx509_cert p)1461 hx509_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 
1479 int
hx509_cert_get_SPKI(hx509_context context,hx509_cert p,SubjectPublicKeyInfo * spki)1480 hx509_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 
1505 int
hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context,hx509_cert p,AlgorithmIdentifier * alg)1506 hx509_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 
1519 static int
get_x_unique_id(hx509_context context,const char * name,const heim_bit_string * cert,heim_bit_string * subject)1520 get_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 
1552 int
hx509_cert_get_issuer_unique_id(hx509_context context,hx509_cert p,heim_bit_string * issuer)1553 hx509_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 
1572 int
hx509_cert_get_subject_unique_id(hx509_context context,hx509_cert p,heim_bit_string * subject)1573 hx509_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 
1579 hx509_private_key
_hx509_cert_private_key(hx509_cert p)1580 _hx509_cert_private_key(hx509_cert p)
1581 {
1582     return p->private_key;
1583 }
1584 
1585 int
hx509_cert_have_private_key(hx509_cert p)1586 hx509_cert_have_private_key(hx509_cert p)
1587 {
1588     return p->private_key ? 1 : 0;
1589 }
1590 
1591 
1592 int
_hx509_cert_private_key_exportable(hx509_cert p)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 
1600 int
_hx509_cert_private_decrypt(hx509_context context,const heim_octet_string * ciphertext,const heim_oid * encryption_oid,hx509_cert p,heim_octet_string * cleartext)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 
1623 int
hx509_cert_public_encrypt(hx509_context context,const heim_octet_string * cleartext,const hx509_cert p,heim_oid * encryption_oid,heim_octet_string * ciphertext)1624 hx509_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 
1639 time_t
_hx509_Time2time_t(const Time * 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 
1655 static int
init_name_constraints(hx509_name_constraints * nc)1656 init_name_constraints(hx509_name_constraints *nc)
1657 {
1658     memset(nc, 0, sizeof(*nc));
1659     return 0;
1660 }
1661 
1662 static int
add_name_constraints(hx509_context context,const Certificate * c,int not_ca,hx509_name_constraints * nc)1663 add_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     }
1695 out:
1696     free_NameConstraints(&tnc);
1697     return ret;
1698 }
1699 
1700 static int
match_RDN(const RelativeDistinguishedName * c,const RelativeDistinguishedName * n)1701 match_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 
1723 static int
match_X501Name(const Name * c,const Name * n)1724 match_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 
1743 static int
match_general_name(const GeneralName * c,const GeneralName * n,int * match)1744 match_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 
1829 static int
match_alt_name(const GeneralName * n,const Certificate * c,int * same,int * match)1830 match_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 
1858 static int
match_tree(const GeneralSubtrees * t,const Certificate * c,int * match)1859 match_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 
1903 static int
check_name_constraints(hx509_context context,const hx509_name_constraints * nc,const Certificate * c)1904 check_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 
1949 static void
free_name_constraints(hx509_name_constraints * nc)1950 free_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 
1974 int
hx509_verify_path(hx509_context context,hx509_verify_ctx ctx,hx509_cert cert,hx509_certs pool)1975 hx509_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 
2377 out:
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 
2400 int
hx509_verify_signature(hx509_context context,const hx509_cert signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,const heim_octet_string * sig)2401 hx509_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 
2410 int
_hx509_verify_signature_bitstring(hx509_context context,const hx509_cert signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,const heim_bit_string * sig)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 
2453 int
hx509_verify_hostname(hx509_context context,const hx509_cert cert,int flags,hx509_hostname_type type,const char * hostname,const struct sockaddr * sa,int sa_size)2454 hx509_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 
2546 int
_hx509_set_cert_attribute(hx509_context context,hx509_cert cert,const heim_oid * oid,const heim_octet_string * attr)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 
2592 hx509_cert_attribute
hx509_cert_get_attribute(hx509_cert cert,const heim_oid * oid)2593 hx509_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 
2613 int
hx509_cert_set_friendly_name(hx509_cert cert,const char * name)2614 hx509_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 
2635 const char *
hx509_cert_get_friendly_name(hx509_cert cert)2636 hx509_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 
2688 void
_hx509_query_clear(hx509_query * q)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 
2705 int
hx509_query_alloc(hx509_context context,hx509_query ** q)2706 hx509_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 
2726 void
hx509_query_match_option(hx509_query * q,hx509_query_option option)2727 hx509_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 
2761 int
hx509_query_match_issuer_serial(hx509_query * q,const Name * issuer,const heim_integer * serialNumber)2762 hx509_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 
2808 int
hx509_query_match_friendly_name(hx509_query * q,const char * name)2809 hx509_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 
2833 int
hx509_query_match_eku(hx509_query * q,const heim_oid * eku)2834 hx509_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 
2864 int
hx509_query_match_expr(hx509_context context,hx509_query * q,const char * expr)2865 hx509_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 
2896 int
hx509_query_match_cmp_func(hx509_query * q,int (* func)(hx509_context,hx509_cert,void *),void * ctx)2897 hx509_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 
2919 void
hx509_query_free(hx509_context context,hx509_query * q)2920 hx509_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 
2946 int
_hx509_query_match_cert(hx509_context context,const hx509_query * q,hx509_cert cert)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 
3107 void
hx509_query_statistic_file(hx509_context context,const char * fn)3108 hx509_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 
3115 void
_hx509_query_statistic(hx509_context context,int type,const hx509_query * q)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 
3129 static 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 
3154 struct stat_el {
3155     unsigned long stats;
3156     unsigned int index;
3157 };
3158 
3159 
3160 static int
stat_sort(const void * a,const void * b)3161 stat_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 
3178 void
hx509_query_unparse_stats(hx509_context context,int printtype,FILE * out)3179 hx509_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 
3267 int
hx509_cert_check_eku(hx509_context context,hx509_cert cert,const heim_oid * eku,int allow_any_eku)3268 hx509_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 
3300 int
_hx509_cert_get_keyusage(hx509_context context,hx509_cert c,KeyUsage * ku)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 
3328 int
_hx509_cert_get_eku(hx509_context context,hx509_cert cert,ExtKeyUsage * e)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 
3358 int
hx509_cert_binary(hx509_context context,hx509_cert c,heim_octet_string * os)3359 hx509_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 
3387 void
_hx509_abort(const char * fmt,...)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 
3408 void
hx509_xfree(void * ptr)3409 hx509_xfree(void *ptr)
3410 {
3411     free(ptr);
3412 }
3413 
3414 /**
3415  *
3416  */
3417 
3418 int
_hx509_cert_to_env(hx509_context context,hx509_cert cert,hx509_env * env)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 
3548 out:
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 
3565 int
hx509_print_cert(hx509_context context,hx509_cert cert,FILE * out)3566 hx509_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