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