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 existence 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, diff;
1981     size_t proxy_cert_depth, selfsigned_depth;
1982     size_t i, k;
1983     enum certtype type;
1984     Name proxy_issuer;
1985     hx509_certs anchors = NULL;
1986 
1987     memset(&proxy_issuer, 0, sizeof(proxy_issuer));
1988 
1989     ret = init_name_constraints(&nc);
1990     if (ret)
1991 	return ret;
1992 
1993     path.val = NULL;
1994     path.len = 0;
1995 
1996     if ((ctx->flags & HX509_VERIFY_CTX_F_TIME_SET) == 0)
1997 	ctx->time_now = time(NULL);
1998 
1999     /*
2000      *
2001      */
2002     if (ctx->trust_anchors)
2003 	anchors = hx509_certs_ref(ctx->trust_anchors);
2004     else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx))
2005 	anchors = hx509_certs_ref(context->default_trust_anchors);
2006     else {
2007 	ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors);
2008 	if (ret)
2009 	    goto out;
2010     }
2011 
2012     /*
2013      * Calculate the path from the certificate user presented to the
2014      * to an anchor.
2015      */
2016     ret = _hx509_calculate_path(context, 0, ctx->time_now,
2017 				anchors, ctx->max_depth,
2018 				cert, pool, &path);
2019     if (ret)
2020 	goto out;
2021 
2022     /*
2023      * Check CA and proxy certificate chain from the top of the
2024      * certificate chain. Also check certificate is valid with respect
2025      * to the current time.
2026      *
2027      */
2028 
2029     proxy_cert_depth = 0;
2030     selfsigned_depth = 0;
2031 
2032     if (ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE)
2033 	type = PROXY_CERT;
2034     else
2035 	type = EE_CERT;
2036 
2037     for (i = 0; i < path.len; i++) {
2038 	Certificate *c;
2039 	time_t t;
2040 
2041 	c = _hx509_get_cert(path.val[i]);
2042 
2043 	/*
2044 	 * Lets do some basic check on issuer like
2045 	 * keyUsage.keyCertSign and basicConstraints.cA bit depending
2046 	 * on what type of certificate this is.
2047 	 */
2048 
2049 	switch (type) {
2050 	case CA_CERT:
2051 
2052 	    /* XXX make constants for keyusage */
2053 	    ret = check_key_usage(context, c, 1 << 5,
2054 				  REQUIRE_RFC3280(ctx) ? TRUE : FALSE);
2055 	    if (ret) {
2056 		hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
2057 				       "Key usage missing from CA certificate");
2058 		goto out;
2059 	    }
2060 
2061 	    /* self signed cert doesn't add to path length */
2062 	    if (i + 1 != path.len) {
2063 		int selfsigned;
2064 
2065 		ret = certificate_is_self_signed(context, c, &selfsigned);
2066 		if (ret)
2067 		    goto out;
2068 		if (selfsigned)
2069 		    selfsigned_depth++;
2070 	    }
2071 
2072 	    break;
2073 	case PROXY_CERT: {
2074 	    ProxyCertInfo info;
2075 
2076 	    if (is_proxy_cert(context, c, &info) == 0) {
2077 		size_t j;
2078 
2079 		if (info.pCPathLenConstraint != NULL &&
2080 		    *info.pCPathLenConstraint < i)
2081 		{
2082 		    free_ProxyCertInfo(&info);
2083 		    ret = HX509_PATH_TOO_LONG;
2084 		    hx509_set_error_string(context, 0, ret,
2085 					   "Proxy certificate chain "
2086 					   "longer then allowed");
2087 		    goto out;
2088 		}
2089 		/* XXX MUST check info.proxyPolicy */
2090 		free_ProxyCertInfo(&info);
2091 
2092 		j = 0;
2093 		if (find_extension(c, &asn1_oid_id_x509_ce_subjectAltName, &j)) {
2094 		    ret = HX509_PROXY_CERT_INVALID;
2095 		    hx509_set_error_string(context, 0, ret,
2096 					   "Proxy certificate have explicitly "
2097 					   "forbidden subjectAltName");
2098 		    goto out;
2099 		}
2100 
2101 		j = 0;
2102 		if (find_extension(c, &asn1_oid_id_x509_ce_issuerAltName, &j)) {
2103 		    ret = HX509_PROXY_CERT_INVALID;
2104 		    hx509_set_error_string(context, 0, ret,
2105 					   "Proxy certificate have explicitly "
2106 					   "forbidden issuerAltName");
2107 		    goto out;
2108 		}
2109 
2110 		/*
2111 		 * The subject name of the proxy certificate should be
2112 		 * CN=XXX,<proxy issuer>, prune of CN and check if its
2113 		 * the same over the whole chain of proxy certs and
2114 		 * then check with the EE cert when we get to it.
2115 		 */
2116 
2117 		if (proxy_cert_depth) {
2118 		    ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject, &diff);
2119 		    if (ret) {
2120 			hx509_set_error_string(context, 0, ret, "Out of memory");
2121 			goto out;
2122 		    }
2123 		    if (diff) {
2124 			ret = HX509_PROXY_CERT_NAME_WRONG;
2125 			hx509_set_error_string(context, 0, ret,
2126 					       "Base proxy name not right");
2127 			goto out;
2128 		    }
2129 		}
2130 
2131 		free_Name(&proxy_issuer);
2132 
2133 		ret = copy_Name(&c->tbsCertificate.subject, &proxy_issuer);
2134 		if (ret) {
2135 		    hx509_clear_error_string(context);
2136 		    goto out;
2137 		}
2138 
2139 		j = proxy_issuer.u.rdnSequence.len;
2140 		if (proxy_issuer.u.rdnSequence.len < 2
2141 		    || proxy_issuer.u.rdnSequence.val[j - 1].len > 1
2142 		    || der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type,
2143 					&asn1_oid_id_at_commonName))
2144 		{
2145 		    ret = HX509_PROXY_CERT_NAME_WRONG;
2146 		    hx509_set_error_string(context, 0, ret,
2147 					   "Proxy name too short or "
2148 					   "does not have Common name "
2149 					   "at the top");
2150 		    goto out;
2151 		}
2152 
2153 		free_RelativeDistinguishedName(&proxy_issuer.u.rdnSequence.val[j - 1]);
2154 		proxy_issuer.u.rdnSequence.len -= 1;
2155 
2156 		ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer, &diff);
2157 		if (ret) {
2158 		    hx509_set_error_string(context, 0, ret, "Out of memory");
2159 		    goto out;
2160 		}
2161 		if (diff != 0) {
2162 		    ret = HX509_PROXY_CERT_NAME_WRONG;
2163 		    hx509_set_error_string(context, 0, ret,
2164 					   "Proxy issuer name not as expected");
2165 		    goto out;
2166 		}
2167 
2168 		break;
2169 	    } else {
2170 		/*
2171 		 * Now we are done with the proxy certificates, this
2172 		 * cert was an EE cert and we we will fall though to
2173 		 * EE checking below.
2174 		 */
2175 		type = EE_CERT;
2176 		/* FALLTHOUGH */
2177 	    }
2178 	}
2179 	case EE_CERT:
2180 	    /*
2181 	     * If there where any proxy certificates in the chain
2182 	     * (proxy_cert_depth > 0), check that the proxy issuer
2183 	     * matched proxy certificates "base" subject.
2184 	     */
2185 	    if (proxy_cert_depth) {
2186 
2187 		ret = _hx509_name_cmp(&proxy_issuer,
2188 				      &c->tbsCertificate.subject, &diff);
2189 		if (ret) {
2190 		    hx509_set_error_string(context, 0, ret, "out of memory");
2191 		    goto out;
2192 		}
2193 		if (diff) {
2194 		    ret = HX509_PROXY_CERT_NAME_WRONG;
2195 		    hx509_clear_error_string(context);
2196 		    goto out;
2197 		}
2198 		if (cert->basename)
2199 		    hx509_name_free(&cert->basename);
2200 
2201 		ret = _hx509_name_from_Name(&proxy_issuer, &cert->basename);
2202 		if (ret) {
2203 		    hx509_clear_error_string(context);
2204 		    goto out;
2205 		}
2206 	    }
2207 
2208 	    break;
2209 	}
2210 
2211 	ret = check_basic_constraints(context, c, type,
2212 				      i - proxy_cert_depth - selfsigned_depth);
2213 	if (ret)
2214 	    goto out;
2215 
2216 	/*
2217 	 * Don't check the trust anchors expiration time since they
2218 	 * are transported out of band, from RFC3820.
2219 	 */
2220 	if (i + 1 != path.len || CHECK_TA(ctx)) {
2221 
2222 	    t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2223 	    if (t > ctx->time_now) {
2224 		ret = HX509_CERT_USED_BEFORE_TIME;
2225 		hx509_clear_error_string(context);
2226 		goto out;
2227 	    }
2228 	    t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
2229 	    if (t < ctx->time_now) {
2230 		ret = HX509_CERT_USED_AFTER_TIME;
2231 		hx509_clear_error_string(context);
2232 		goto out;
2233 	    }
2234 	}
2235 
2236 	if (type == EE_CERT)
2237 	    type = CA_CERT;
2238 	else if (type == PROXY_CERT)
2239 	    proxy_cert_depth++;
2240     }
2241 
2242     /*
2243      * Verify constraints, do this backward so path constraints are
2244      * checked in the right order.
2245      */
2246 
2247     for (ret = 0, k = path.len; k > 0; k--) {
2248 	Certificate *c;
2249 	int selfsigned;
2250 	i = k - 1;
2251 
2252 	c = _hx509_get_cert(path.val[i]);
2253 
2254 	ret = certificate_is_self_signed(context, c, &selfsigned);
2255 	if (ret)
2256 	    goto out;
2257 
2258 	/* verify name constraints, not for selfsigned and anchor */
2259 	if (!selfsigned || i + 1 != path.len) {
2260 	    ret = check_name_constraints(context, &nc, c);
2261 	    if (ret) {
2262 		goto out;
2263 	    }
2264 	}
2265 	ret = add_name_constraints(context, c, i == 0, &nc);
2266 	if (ret)
2267 	    goto out;
2268 
2269 	/* XXX verify all other silly constraints */
2270 
2271     }
2272 
2273     /*
2274      * Verify that no certificates has been revoked.
2275      */
2276 
2277     if (ctx->revoke_ctx) {
2278 	hx509_certs certs;
2279 
2280 	ret = hx509_certs_init(context, "MEMORY:revoke-certs", 0,
2281 			       NULL, &certs);
2282 	if (ret)
2283 	    goto out;
2284 
2285 	for (i = 0; i < path.len; i++) {
2286 	    ret = hx509_certs_add(context, certs, path.val[i]);
2287 	    if (ret) {
2288 		hx509_certs_free(&certs);
2289 		goto out;
2290 	    }
2291 	}
2292 	ret = hx509_certs_merge(context, certs, pool);
2293 	if (ret) {
2294 	    hx509_certs_free(&certs);
2295 	    goto out;
2296 	}
2297 
2298 	for (i = 0; i < path.len - 1; i++) {
2299 	    size_t parent = (i < path.len - 1) ? i + 1 : i;
2300 
2301 	    ret = hx509_revoke_verify(context,
2302 				      ctx->revoke_ctx,
2303 				      certs,
2304 				      ctx->time_now,
2305 				      path.val[i],
2306 				      path.val[parent]);
2307 	    if (ret) {
2308 		hx509_certs_free(&certs);
2309 		goto out;
2310 	    }
2311 	}
2312 	hx509_certs_free(&certs);
2313     }
2314 
2315     /*
2316      * Verify signatures, do this backward so public key working
2317      * parameter is passed up from the anchor up though the chain.
2318      */
2319 
2320     for (k = path.len; k > 0; k--) {
2321 	hx509_cert signer;
2322 	Certificate *c;
2323 	i = k - 1;
2324 
2325 	c = _hx509_get_cert(path.val[i]);
2326 
2327 	/* is last in chain (trust anchor) */
2328 	if (i + 1 == path.len) {
2329 	    int selfsigned;
2330 
2331 	    signer = path.val[i];
2332 
2333 	    ret = certificate_is_self_signed(context, signer->data, &selfsigned);
2334 	    if (ret)
2335 		goto out;
2336 
2337 	    /* if trust anchor is not self signed, don't check sig */
2338 	    if (!selfsigned)
2339 		continue;
2340 	} else {
2341 	    /* take next certificate in chain */
2342 	    signer = path.val[i + 1];
2343 	}
2344 
2345 	/* verify signatureValue */
2346 	ret = _hx509_verify_signature_bitstring(context,
2347 						signer,
2348 						&c->signatureAlgorithm,
2349 						&c->tbsCertificate._save,
2350 						&c->signatureValue);
2351 	if (ret) {
2352 	    hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
2353 				   "Failed to verify signature of certificate");
2354 	    goto out;
2355 	}
2356 	/*
2357 	 * Verify that the sigature algorithm "best-before" date is
2358 	 * before the creation date of the certificate, do this for
2359 	 * trust anchors too, since any trust anchor that is created
2360 	 * after a algorithm is known to be bad deserved to be invalid.
2361 	 *
2362 	 * Skip the leaf certificate for now...
2363 	 */
2364 
2365 	if (i != 0 && (ctx->flags & HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK) == 0) {
2366 	    time_t notBefore =
2367 		_hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2368 	    ret = _hx509_signature_best_before(context,
2369 					       &c->signatureAlgorithm,
2370 					       notBefore);
2371 	    if (ret)
2372 		goto out;
2373 	}
2374     }
2375 
2376 out:
2377     hx509_certs_free(&anchors);
2378     free_Name(&proxy_issuer);
2379     free_name_constraints(&nc);
2380     _hx509_path_free(&path);
2381 
2382     return ret;
2383 }
2384 
2385 /**
2386  * Verify a signature made using the private key of an certificate.
2387  *
2388  * @param context A hx509 context.
2389  * @param signer the certificate that made the signature.
2390  * @param alg algorthm that was used to sign the data.
2391  * @param data the data that was signed.
2392  * @param sig the sigature to verify.
2393  *
2394  * @return An hx509 error code, see hx509_get_error_string().
2395  *
2396  * @ingroup hx509_crypto
2397  */
2398 
2399 int
hx509_verify_signature(hx509_context context,const hx509_cert signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,const heim_octet_string * sig)2400 hx509_verify_signature(hx509_context context,
2401 		       const hx509_cert signer,
2402 		       const AlgorithmIdentifier *alg,
2403 		       const heim_octet_string *data,
2404 		       const heim_octet_string *sig)
2405 {
2406     return _hx509_verify_signature(context, signer, alg, data, sig);
2407 }
2408 
2409 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)2410 _hx509_verify_signature_bitstring(hx509_context context,
2411 				  const hx509_cert signer,
2412 				  const AlgorithmIdentifier *alg,
2413 				  const heim_octet_string *data,
2414 				  const heim_bit_string *sig)
2415 {
2416     heim_octet_string os;
2417 
2418     if (sig->length & 7) {
2419 	hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT,
2420 			       "signature not multiple of 8 bits");
2421 	return HX509_CRYPTO_SIG_INVALID_FORMAT;
2422     }
2423 
2424     os.data = sig->data;
2425     os.length = sig->length / 8;
2426 
2427     return _hx509_verify_signature(context, signer, alg, data, &os);
2428 }
2429 
2430 
2431 
2432 /**
2433  * Verify that the certificate is allowed to be used for the hostname
2434  * and address.
2435  *
2436  * @param context A hx509 context.
2437  * @param cert the certificate to match with
2438  * @param flags Flags to modify the behavior:
2439  * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
2440  * @param type type of hostname:
2441  * - HX509_HN_HOSTNAME for plain hostname.
2442  * - HX509_HN_DNSSRV for DNS SRV names.
2443  * @param hostname the hostname to check
2444  * @param sa address of the host
2445  * @param sa_size length of address
2446  *
2447  * @return An hx509 error code, see hx509_get_error_string().
2448  *
2449  * @ingroup hx509_cert
2450  */
2451 
2452 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)2453 hx509_verify_hostname(hx509_context context,
2454 		      const hx509_cert cert,
2455 		      int flags,
2456 		      hx509_hostname_type type,
2457 		      const char *hostname,
2458 		      const struct sockaddr *sa,
2459 		      /* XXX krb5_socklen_t */ int sa_size)
2460 {
2461     GeneralNames san;
2462     const Name *name;
2463     int ret;
2464     size_t i, j, k;
2465 
2466     if (sa && sa_size <= 0)
2467 	return EINVAL;
2468 
2469     memset(&san, 0, sizeof(san));
2470 
2471     i = 0;
2472     do {
2473 	ret = find_extension_subject_alt_name(cert->data, &i, &san);
2474 	if (ret == HX509_EXTENSION_NOT_FOUND)
2475 	    break;
2476 	else if (ret != 0)
2477 	    return HX509_PARSING_NAME_FAILED;
2478 
2479 	for (j = 0; j < san.len; j++) {
2480 	    switch (san.val[j].element) {
2481 	    case choice_GeneralName_dNSName: {
2482 		heim_printable_string hn;
2483 		hn.data = rk_UNCONST(hostname);
2484 		hn.length = strlen(hostname);
2485 
2486 		if (der_printable_string_cmp(&san.val[j].u.dNSName, &hn) == 0) {
2487 		    free_GeneralNames(&san);
2488 		    return 0;
2489 		}
2490 		break;
2491 	    }
2492 	    default:
2493 		break;
2494 	    }
2495 	}
2496 	free_GeneralNames(&san);
2497     } while (1);
2498 
2499     name = &cert->data->tbsCertificate.subject;
2500 
2501     /* Find first CN= in the name, and try to match the hostname on that */
2502     for (ret = 0, k = name->u.rdnSequence.len; ret == 0 && k > 0; k--) {
2503 	i = k - 1;
2504 	for (j = 0; ret == 0 && j < name->u.rdnSequence.val[i].len; j++) {
2505 	    AttributeTypeAndValue *n = &name->u.rdnSequence.val[i].val[j];
2506 
2507 	    if (der_heim_oid_cmp(&n->type, &asn1_oid_id_at_commonName) == 0) {
2508 		DirectoryString *ds = &n->value;
2509 		switch (ds->element) {
2510 		case choice_DirectoryString_printableString: {
2511 		    heim_printable_string hn;
2512 		    hn.data = rk_UNCONST(hostname);
2513 		    hn.length = strlen(hostname);
2514 
2515 		    if (der_printable_string_cmp(&ds->u.printableString, &hn) == 0)
2516 			return 0;
2517 		    break;
2518 		}
2519 		case choice_DirectoryString_ia5String: {
2520 		    heim_ia5_string hn;
2521 		    hn.data = rk_UNCONST(hostname);
2522 		    hn.length = strlen(hostname);
2523 
2524 		    if (der_ia5_string_cmp(&ds->u.ia5String, &hn) == 0)
2525 			return 0;
2526 		    break;
2527 		}
2528 		case choice_DirectoryString_utf8String:
2529 		    if (strcasecmp(ds->u.utf8String, hostname) == 0)
2530 			return 0;
2531 		default:
2532 		    break;
2533 		}
2534 		ret = HX509_NAME_CONSTRAINT_ERROR;
2535 	    }
2536 	}
2537     }
2538 
2539     if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0)
2540 	ret = HX509_NAME_CONSTRAINT_ERROR;
2541 
2542     return ret;
2543 }
2544 
2545 int
_hx509_set_cert_attribute(hx509_context context,hx509_cert cert,const heim_oid * oid,const heim_octet_string * attr)2546 _hx509_set_cert_attribute(hx509_context context,
2547 			  hx509_cert cert,
2548 			  const heim_oid *oid,
2549 			  const heim_octet_string *attr)
2550 {
2551     hx509_cert_attribute a;
2552     void *d;
2553 
2554     if (hx509_cert_get_attribute(cert, oid) != NULL)
2555 	return 0;
2556 
2557     d = realloc(cert->attrs.val,
2558 		sizeof(cert->attrs.val[0]) * (cert->attrs.len + 1));
2559     if (d == NULL) {
2560 	hx509_clear_error_string(context);
2561 	return ENOMEM;
2562     }
2563     cert->attrs.val = d;
2564 
2565     a = malloc(sizeof(*a));
2566     if (a == NULL)
2567 	return ENOMEM;
2568 
2569     der_copy_octet_string(attr, &a->data);
2570     der_copy_oid(oid, &a->oid);
2571 
2572     cert->attrs.val[cert->attrs.len] = a;
2573     cert->attrs.len++;
2574 
2575     return 0;
2576 }
2577 
2578 /**
2579  * Get an external attribute for the certificate, examples are
2580  * friendly name and id.
2581  *
2582  * @param cert hx509 certificate object to search
2583  * @param oid an oid to search for.
2584  *
2585  * @return an hx509_cert_attribute, only valid as long as the
2586  * certificate is referenced.
2587  *
2588  * @ingroup hx509_cert
2589  */
2590 
2591 hx509_cert_attribute
hx509_cert_get_attribute(hx509_cert cert,const heim_oid * oid)2592 hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid)
2593 {
2594     size_t i;
2595     for (i = 0; i < cert->attrs.len; i++)
2596 	if (der_heim_oid_cmp(oid, &cert->attrs.val[i]->oid) == 0)
2597 	    return cert->attrs.val[i];
2598     return NULL;
2599 }
2600 
2601 /**
2602  * Set the friendly name on the certificate.
2603  *
2604  * @param cert The certificate to set the friendly name on
2605  * @param name Friendly name.
2606  *
2607  * @return An hx509 error code, see hx509_get_error_string().
2608  *
2609  * @ingroup hx509_cert
2610  */
2611 
2612 int
hx509_cert_set_friendly_name(hx509_cert cert,const char * name)2613 hx509_cert_set_friendly_name(hx509_cert cert, const char *name)
2614 {
2615     if (cert->friendlyname)
2616 	free(cert->friendlyname);
2617     cert->friendlyname = strdup(name);
2618     if (cert->friendlyname == NULL)
2619 	return ENOMEM;
2620     return 0;
2621 }
2622 
2623 /**
2624  * Get friendly name of the certificate.
2625  *
2626  * @param cert cert to get the friendly name from.
2627  *
2628  * @return an friendly name or NULL if there is. The friendly name is
2629  * only valid as long as the certificate is referenced.
2630  *
2631  * @ingroup hx509_cert
2632  */
2633 
2634 const char *
hx509_cert_get_friendly_name(hx509_cert cert)2635 hx509_cert_get_friendly_name(hx509_cert cert)
2636 {
2637     hx509_cert_attribute a;
2638     PKCS9_friendlyName n;
2639     size_t sz;
2640     int ret;
2641     size_t i;
2642 
2643     if (cert->friendlyname)
2644 	return cert->friendlyname;
2645 
2646     a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_friendlyName);
2647     if (a == NULL) {
2648 	hx509_name name;
2649 
2650 	ret = hx509_cert_get_subject(cert, &name);
2651 	if (ret)
2652 	    return NULL;
2653 	ret = hx509_name_to_string(name, &cert->friendlyname);
2654 	hx509_name_free(&name);
2655 	if (ret)
2656 	    return NULL;
2657 	return cert->friendlyname;
2658     }
2659 
2660     ret = decode_PKCS9_friendlyName(a->data.data, a->data.length, &n, &sz);
2661     if (ret)
2662 	return NULL;
2663 
2664     if (n.len != 1) {
2665 	free_PKCS9_friendlyName(&n);
2666 	return NULL;
2667     }
2668 
2669     cert->friendlyname = malloc(n.val[0].length + 1);
2670     if (cert->friendlyname == NULL) {
2671 	free_PKCS9_friendlyName(&n);
2672 	return NULL;
2673     }
2674 
2675     for (i = 0; i < n.val[0].length; i++) {
2676 	if (n.val[0].data[i] <= 0xff)
2677 	    cert->friendlyname[i] = n.val[0].data[i] & 0xff;
2678 	else
2679 	    cert->friendlyname[i] = 'X';
2680     }
2681     cert->friendlyname[i] = '\0';
2682     free_PKCS9_friendlyName(&n);
2683 
2684     return cert->friendlyname;
2685 }
2686 
2687 void
_hx509_query_clear(hx509_query * q)2688 _hx509_query_clear(hx509_query *q)
2689 {
2690     memset(q, 0, sizeof(*q));
2691 }
2692 
2693 /**
2694  * Allocate an query controller. Free using hx509_query_free().
2695  *
2696  * @param context A hx509 context.
2697  * @param q return pointer to a hx509_query.
2698  *
2699  * @return An hx509 error code, see hx509_get_error_string().
2700  *
2701  * @ingroup hx509_cert
2702  */
2703 
2704 int
hx509_query_alloc(hx509_context context,hx509_query ** q)2705 hx509_query_alloc(hx509_context context, hx509_query **q)
2706 {
2707     *q = calloc(1, sizeof(**q));
2708     if (*q == NULL)
2709 	return ENOMEM;
2710     return 0;
2711 }
2712 
2713 
2714 /**
2715  * Set match options for the hx509 query controller.
2716  *
2717  * @param q query controller.
2718  * @param option options to control the query controller.
2719  *
2720  * @return An hx509 error code, see hx509_get_error_string().
2721  *
2722  * @ingroup hx509_cert
2723  */
2724 
2725 void
hx509_query_match_option(hx509_query * q,hx509_query_option option)2726 hx509_query_match_option(hx509_query *q, hx509_query_option option)
2727 {
2728     switch(option) {
2729     case HX509_QUERY_OPTION_PRIVATE_KEY:
2730 	q->match |= HX509_QUERY_PRIVATE_KEY;
2731 	break;
2732     case HX509_QUERY_OPTION_KU_ENCIPHERMENT:
2733 	q->match |= HX509_QUERY_KU_ENCIPHERMENT;
2734 	break;
2735     case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE:
2736 	q->match |= HX509_QUERY_KU_DIGITALSIGNATURE;
2737 	break;
2738     case HX509_QUERY_OPTION_KU_KEYCERTSIGN:
2739 	q->match |= HX509_QUERY_KU_KEYCERTSIGN;
2740 	break;
2741     case HX509_QUERY_OPTION_END:
2742     default:
2743 	break;
2744     }
2745 }
2746 
2747 /**
2748  * Set the issuer and serial number of match in the query
2749  * controller. The function make copies of the isser and serial number.
2750  *
2751  * @param q a hx509 query controller
2752  * @param issuer issuer to search for
2753  * @param serialNumber the serialNumber of the issuer.
2754  *
2755  * @return An hx509 error code, see hx509_get_error_string().
2756  *
2757  * @ingroup hx509_cert
2758  */
2759 
2760 int
hx509_query_match_issuer_serial(hx509_query * q,const Name * issuer,const heim_integer * serialNumber)2761 hx509_query_match_issuer_serial(hx509_query *q,
2762 				const Name *issuer,
2763 				const heim_integer *serialNumber)
2764 {
2765     int ret;
2766     if (q->serial) {
2767 	der_free_heim_integer(q->serial);
2768 	free(q->serial);
2769     }
2770     q->serial = malloc(sizeof(*q->serial));
2771     if (q->serial == NULL)
2772 	return ENOMEM;
2773     ret = der_copy_heim_integer(serialNumber, q->serial);
2774     if (ret) {
2775 	free(q->serial);
2776 	q->serial = NULL;
2777 	return ret;
2778     }
2779     if (q->issuer_name) {
2780 	free_Name(q->issuer_name);
2781 	free(q->issuer_name);
2782     }
2783     q->issuer_name = malloc(sizeof(*q->issuer_name));
2784     if (q->issuer_name == NULL)
2785 	return ENOMEM;
2786     ret = copy_Name(issuer, q->issuer_name);
2787     if (ret) {
2788 	free(q->issuer_name);
2789 	q->issuer_name = NULL;
2790 	return ret;
2791     }
2792     q->match |= HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
2793     return 0;
2794 }
2795 
2796 /**
2797  * Set the query controller to match on a friendly name
2798  *
2799  * @param q a hx509 query controller.
2800  * @param name a friendly name to match on
2801  *
2802  * @return An hx509 error code, see hx509_get_error_string().
2803  *
2804  * @ingroup hx509_cert
2805  */
2806 
2807 int
hx509_query_match_friendly_name(hx509_query * q,const char * name)2808 hx509_query_match_friendly_name(hx509_query *q, const char *name)
2809 {
2810     if (q->friendlyname)
2811 	free(q->friendlyname);
2812     q->friendlyname = strdup(name);
2813     if (q->friendlyname == NULL)
2814 	return ENOMEM;
2815     q->match |= HX509_QUERY_MATCH_FRIENDLY_NAME;
2816     return 0;
2817 }
2818 
2819 /**
2820  * Set the query controller to require an one specific EKU (extended
2821  * key usage). Any previous EKU matching is overwitten. If NULL is
2822  * passed in as the eku, the EKU requirement is reset.
2823  *
2824  * @param q a hx509 query controller.
2825  * @param eku an EKU to match on.
2826  *
2827  * @return An hx509 error code, see hx509_get_error_string().
2828  *
2829  * @ingroup hx509_cert
2830  */
2831 
2832 int
hx509_query_match_eku(hx509_query * q,const heim_oid * eku)2833 hx509_query_match_eku(hx509_query *q, const heim_oid *eku)
2834 {
2835     int ret;
2836 
2837     if (eku == NULL) {
2838 	if (q->eku) {
2839 	    der_free_oid(q->eku);
2840 	    free(q->eku);
2841 	    q->eku = NULL;
2842 	}
2843 	q->match &= ~HX509_QUERY_MATCH_EKU;
2844     } else {
2845 	if (q->eku) {
2846 	    der_free_oid(q->eku);
2847 	} else {
2848 	    q->eku = calloc(1, sizeof(*q->eku));
2849 	    if (q->eku == NULL)
2850 		return ENOMEM;
2851 	}
2852 	ret = der_copy_oid(eku, q->eku);
2853 	if (ret) {
2854 	    free(q->eku);
2855 	    q->eku = NULL;
2856 	    return ret;
2857 	}
2858 	q->match |= HX509_QUERY_MATCH_EKU;
2859     }
2860     return 0;
2861 }
2862 
2863 int
hx509_query_match_expr(hx509_context context,hx509_query * q,const char * expr)2864 hx509_query_match_expr(hx509_context context, hx509_query *q, const char *expr)
2865 {
2866     if (q->expr) {
2867 	_hx509_expr_free(q->expr);
2868 	q->expr = NULL;
2869     }
2870 
2871     if (expr == NULL) {
2872 	q->match &= ~HX509_QUERY_MATCH_EXPR;
2873     } else {
2874 	q->expr = _hx509_expr_parse(expr);
2875 	if (q->expr)
2876 	    q->match |= HX509_QUERY_MATCH_EXPR;
2877     }
2878 
2879     return 0;
2880 }
2881 
2882 /**
2883  * Set the query controller to match using a specific match function.
2884  *
2885  * @param q a hx509 query controller.
2886  * @param func function to use for matching, if the argument is NULL,
2887  * the match function is removed.
2888  * @param ctx context passed to the function.
2889  *
2890  * @return An hx509 error code, see hx509_get_error_string().
2891  *
2892  * @ingroup hx509_cert
2893  */
2894 
2895 int
hx509_query_match_cmp_func(hx509_query * q,int (* func)(hx509_context,hx509_cert,void *),void * ctx)2896 hx509_query_match_cmp_func(hx509_query *q,
2897 			   int (*func)(hx509_context, hx509_cert, void *),
2898 			   void *ctx)
2899 {
2900     if (func)
2901 	q->match |= HX509_QUERY_MATCH_FUNCTION;
2902     else
2903 	q->match &= ~HX509_QUERY_MATCH_FUNCTION;
2904     q->cmp_func = func;
2905     q->cmp_func_ctx = ctx;
2906     return 0;
2907 }
2908 
2909 /**
2910  * Free the query controller.
2911  *
2912  * @param context A hx509 context.
2913  * @param q a pointer to the query controller.
2914  *
2915  * @ingroup hx509_cert
2916  */
2917 
2918 void
hx509_query_free(hx509_context context,hx509_query * q)2919 hx509_query_free(hx509_context context, hx509_query *q)
2920 {
2921     if (q == NULL)
2922 	return;
2923 
2924     if (q->serial) {
2925 	der_free_heim_integer(q->serial);
2926 	free(q->serial);
2927     }
2928     if (q->issuer_name) {
2929 	free_Name(q->issuer_name);
2930 	free(q->issuer_name);
2931     }
2932     if (q->eku) {
2933 	der_free_oid(q->eku);
2934 	free(q->eku);
2935     }
2936     if (q->friendlyname)
2937 	free(q->friendlyname);
2938     if (q->expr)
2939 	_hx509_expr_free(q->expr);
2940 
2941     memset(q, 0, sizeof(*q));
2942     free(q);
2943 }
2944 
2945 int
_hx509_query_match_cert(hx509_context context,const hx509_query * q,hx509_cert cert)2946 _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert)
2947 {
2948     Certificate *c = _hx509_get_cert(cert);
2949     int ret, diff;
2950 
2951     _hx509_query_statistic(context, 1, q);
2952 
2953     if ((q->match & HX509_QUERY_FIND_ISSUER_CERT) &&
2954 	_hx509_cert_is_parent_cmp(q->subject, c, 0) != 0)
2955 	return 0;
2956 
2957     if ((q->match & HX509_QUERY_MATCH_CERTIFICATE) &&
2958 	_hx509_Certificate_cmp(q->certificate, c) != 0)
2959 	return 0;
2960 
2961     if ((q->match & HX509_QUERY_MATCH_SERIALNUMBER)
2962 	&& der_heim_integer_cmp(&c->tbsCertificate.serialNumber, q->serial) != 0)
2963 	return 0;
2964 
2965     if (q->match & HX509_QUERY_MATCH_ISSUER_NAME) {
2966 	ret = _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name, &diff);
2967 	if (ret || diff)
2968 	    return 0;
2969     }
2970 
2971     if (q->match & HX509_QUERY_MATCH_SUBJECT_NAME) {
2972 	ret = _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name, &diff);
2973 	if (ret || diff)
2974 	    return 0;
2975     }
2976 
2977     if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) {
2978 	SubjectKeyIdentifier si;
2979 
2980 	ret = _hx509_find_extension_subject_key_id(c, &si);
2981 	if (ret == 0) {
2982 	    if (der_heim_octet_string_cmp(&si, q->subject_id) != 0)
2983 		ret = 1;
2984 	    free_SubjectKeyIdentifier(&si);
2985 	}
2986 	if (ret)
2987 	    return 0;
2988     }
2989     if ((q->match & HX509_QUERY_MATCH_ISSUER_ID))
2990 	return 0;
2991     if ((q->match & HX509_QUERY_PRIVATE_KEY) &&
2992 	_hx509_cert_private_key(cert) == NULL)
2993 	return 0;
2994 
2995     {
2996 	unsigned ku = 0;
2997 	if (q->match & HX509_QUERY_KU_DIGITALSIGNATURE)
2998 	    ku |= (1 << 0);
2999 	if (q->match & HX509_QUERY_KU_NONREPUDIATION)
3000 	    ku |= (1 << 1);
3001 	if (q->match & HX509_QUERY_KU_ENCIPHERMENT)
3002 	    ku |= (1 << 2);
3003 	if (q->match & HX509_QUERY_KU_DATAENCIPHERMENT)
3004 	    ku |= (1 << 3);
3005 	if (q->match & HX509_QUERY_KU_KEYAGREEMENT)
3006 	    ku |= (1 << 4);
3007 	if (q->match & HX509_QUERY_KU_KEYCERTSIGN)
3008 	    ku |= (1 << 5);
3009 	if (q->match & HX509_QUERY_KU_CRLSIGN)
3010 	    ku |= (1 << 6);
3011 	if (ku && check_key_usage(context, c, ku, TRUE))
3012 	    return 0;
3013     }
3014     if ((q->match & HX509_QUERY_ANCHOR))
3015 	return 0;
3016 
3017     if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) {
3018 	hx509_cert_attribute a;
3019 
3020 	a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_localKeyId);
3021 	if (a == NULL)
3022 	    return 0;
3023 	if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0)
3024 	    return 0;
3025     }
3026 
3027     if (q->match & HX509_QUERY_NO_MATCH_PATH) {
3028 	size_t i;
3029 
3030 	for (i = 0; i < q->path->len; i++)
3031 	    if (hx509_cert_cmp(q->path->val[i], cert) == 0)
3032 		return 0;
3033     }
3034     if (q->match & HX509_QUERY_MATCH_FRIENDLY_NAME) {
3035 	const char *name = hx509_cert_get_friendly_name(cert);
3036 	if (name == NULL)
3037 	    return 0;
3038 	if (strcasecmp(q->friendlyname, name) != 0)
3039 	    return 0;
3040     }
3041     if (q->match & HX509_QUERY_MATCH_FUNCTION) {
3042 	ret = (*q->cmp_func)(context, cert, q->cmp_func_ctx);
3043 	if (ret != 0)
3044 	    return 0;
3045     }
3046 
3047     if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) {
3048 	heim_octet_string os;
3049 
3050 	os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
3051 	os.length =
3052 	    c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
3053 
3054 	ret = _hx509_verify_signature(context,
3055 				      NULL,
3056 				      hx509_signature_sha1(),
3057 				      &os,
3058 				      q->keyhash_sha1);
3059 	if (ret != 0)
3060 	    return 0;
3061     }
3062 
3063     if (q->match & HX509_QUERY_MATCH_TIME) {
3064 	time_t t;
3065 	t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
3066 	if (t > q->timenow)
3067 	    return 0;
3068 	t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
3069 	if (t < q->timenow)
3070 	    return 0;
3071     }
3072 
3073     /* If an EKU is required, check the cert for it. */
3074     if ((q->match & HX509_QUERY_MATCH_EKU) &&
3075 	hx509_cert_check_eku(context, cert, q->eku, 0))
3076 	return 0;
3077 
3078     if ((q->match & HX509_QUERY_MATCH_EXPR)) {
3079 	hx509_env env = NULL;
3080 
3081 	ret = _hx509_cert_to_env(context, cert, &env);
3082 	if (ret)
3083 	    return 0;
3084 
3085 	ret = _hx509_expr_eval(context, env, q->expr);
3086 	hx509_env_free(&env);
3087 	if (ret == 0)
3088 	    return 0;
3089     }
3090 
3091     if (q->match & ~HX509_QUERY_MASK)
3092 	return 0;
3093 
3094     return 1;
3095 }
3096 
3097 /**
3098  * Set a statistic file for the query statistics.
3099  *
3100  * @param context A hx509 context.
3101  * @param fn statistics file name
3102  *
3103  * @ingroup hx509_cert
3104  */
3105 
3106 void
hx509_query_statistic_file(hx509_context context,const char * fn)3107 hx509_query_statistic_file(hx509_context context, const char *fn)
3108 {
3109     if (context->querystat)
3110 	free(context->querystat);
3111     context->querystat = strdup(fn);
3112 }
3113 
3114 void
_hx509_query_statistic(hx509_context context,int type,const hx509_query * q)3115 _hx509_query_statistic(hx509_context context, int type, const hx509_query *q)
3116 {
3117     FILE *f;
3118     if (context->querystat == NULL)
3119 	return;
3120     f = fopen(context->querystat, "a");
3121     if (f == NULL)
3122 	return;
3123     rk_cloexec_file(f);
3124     fprintf(f, "%d %d\n", type, q->match);
3125     fclose(f);
3126 }
3127 
3128 static const char *statname[] = {
3129     "find issuer cert",
3130     "match serialnumber",
3131     "match issuer name",
3132     "match subject name",
3133     "match subject key id",
3134     "match issuer id",
3135     "private key",
3136     "ku encipherment",
3137     "ku digitalsignature",
3138     "ku keycertsign",
3139     "ku crlsign",
3140     "ku nonrepudiation",
3141     "ku keyagreement",
3142     "ku dataencipherment",
3143     "anchor",
3144     "match certificate",
3145     "match local key id",
3146     "no match path",
3147     "match friendly name",
3148     "match function",
3149     "match key hash sha1",
3150     "match time"
3151 };
3152 
3153 struct stat_el {
3154     unsigned long stats;
3155     unsigned int index;
3156 };
3157 
3158 
3159 static int
stat_sort(const void * a,const void * b)3160 stat_sort(const void *a, const void *b)
3161 {
3162     const struct stat_el *ae = a;
3163     const struct stat_el *be = b;
3164     return be->stats - ae->stats;
3165 }
3166 
3167 /**
3168  * Unparse the statistics file and print the result on a FILE descriptor.
3169  *
3170  * @param context A hx509 context.
3171  * @param printtype tyep to print
3172  * @param out the FILE to write the data on.
3173  *
3174  * @ingroup hx509_cert
3175  */
3176 
3177 void
hx509_query_unparse_stats(hx509_context context,int printtype,FILE * out)3178 hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out)
3179 {
3180     rtbl_t t;
3181     FILE *f;
3182     int type, mask, num;
3183     size_t i;
3184     unsigned long multiqueries = 0, totalqueries = 0;
3185     struct stat_el stats[32];
3186 
3187     if (context->querystat == NULL)
3188 	return;
3189     f = fopen(context->querystat, "r");
3190     if (f == NULL) {
3191 	fprintf(out, "No statistic file %s: %s.\n",
3192 		context->querystat, strerror(errno));
3193 	return;
3194     }
3195     rk_cloexec_file(f);
3196 
3197     for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3198 	stats[i].index = i;
3199 	stats[i].stats = 0;
3200     }
3201 
3202     while (fscanf(f, "%d %d\n", &type, &mask) == 2) {
3203 	if (type != printtype)
3204 	    continue;
3205 	num = i = 0;
3206 	while (mask && i < sizeof(stats)/sizeof(stats[0])) {
3207 	    if (mask & 1) {
3208 		stats[i].stats++;
3209 		num++;
3210 	    }
3211 	    mask = mask >>1 ;
3212 	    i++;
3213 	}
3214 	if (num > 1)
3215 	    multiqueries++;
3216 	totalqueries++;
3217     }
3218     fclose(f);
3219 
3220     qsort(stats, sizeof(stats)/sizeof(stats[0]), sizeof(stats[0]), stat_sort);
3221 
3222     t = rtbl_create();
3223     if (t == NULL)
3224 	errx(1, "out of memory");
3225 
3226     rtbl_set_separator (t, "  ");
3227 
3228     rtbl_add_column_by_id (t, 0, "Name", 0);
3229     rtbl_add_column_by_id (t, 1, "Counter", 0);
3230 
3231 
3232     for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3233 	char str[10];
3234 
3235 	if (stats[i].index < sizeof(statname)/sizeof(statname[0]))
3236 	    rtbl_add_column_entry_by_id (t, 0, statname[stats[i].index]);
3237 	else {
3238 	    snprintf(str, sizeof(str), "%d", stats[i].index);
3239 	    rtbl_add_column_entry_by_id (t, 0, str);
3240 	}
3241 	snprintf(str, sizeof(str), "%lu", stats[i].stats);
3242 	rtbl_add_column_entry_by_id (t, 1, str);
3243     }
3244 
3245     rtbl_format(t, out);
3246     rtbl_destroy(t);
3247 
3248     fprintf(out, "\nQueries: multi %lu total %lu\n",
3249 	    multiqueries, totalqueries);
3250 }
3251 
3252 /**
3253  * Check the extended key usage on the hx509 certificate.
3254  *
3255  * @param context A hx509 context.
3256  * @param cert A hx509 context.
3257  * @param eku the EKU to check for
3258  * @param allow_any_eku if the any EKU is set, allow that to be a
3259  * substitute.
3260  *
3261  * @return An hx509 error code, see hx509_get_error_string().
3262  *
3263  * @ingroup hx509_cert
3264  */
3265 
3266 int
hx509_cert_check_eku(hx509_context context,hx509_cert cert,const heim_oid * eku,int allow_any_eku)3267 hx509_cert_check_eku(hx509_context context, hx509_cert cert,
3268 		     const heim_oid *eku, int allow_any_eku)
3269 {
3270     ExtKeyUsage e;
3271     int ret;
3272     size_t i;
3273 
3274     ret = find_extension_eku(_hx509_get_cert(cert), &e);
3275     if (ret) {
3276 	hx509_clear_error_string(context);
3277 	return ret;
3278     }
3279 
3280     for (i = 0; i < e.len; i++) {
3281 	if (der_heim_oid_cmp(eku, &e.val[i]) == 0) {
3282 	    free_ExtKeyUsage(&e);
3283 	    return 0;
3284 	}
3285 	if (allow_any_eku) {
3286 #if 0
3287 	    if (der_heim_oid_cmp(id_any_eku, &e.val[i]) == 0) {
3288 		free_ExtKeyUsage(&e);
3289 		return 0;
3290 	    }
3291 #endif
3292 	}
3293     }
3294     free_ExtKeyUsage(&e);
3295     hx509_clear_error_string(context);
3296     return HX509_CERTIFICATE_MISSING_EKU;
3297 }
3298 
3299 int
_hx509_cert_get_keyusage(hx509_context context,hx509_cert c,KeyUsage * ku)3300 _hx509_cert_get_keyusage(hx509_context context,
3301 			 hx509_cert c,
3302 			 KeyUsage *ku)
3303 {
3304     Certificate *cert;
3305     const Extension *e;
3306     size_t size;
3307     int ret;
3308     size_t i = 0;
3309 
3310     memset(ku, 0, sizeof(*ku));
3311 
3312     cert = _hx509_get_cert(c);
3313 
3314     if (_hx509_cert_get_version(cert) < 3)
3315 	return 0;
3316 
3317     e = find_extension(cert, &asn1_oid_id_x509_ce_keyUsage, &i);
3318     if (e == NULL)
3319 	return HX509_KU_CERT_MISSING;
3320 
3321     ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, ku, &size);
3322     if (ret)
3323 	return ret;
3324     return 0;
3325 }
3326 
3327 int
_hx509_cert_get_eku(hx509_context context,hx509_cert cert,ExtKeyUsage * e)3328 _hx509_cert_get_eku(hx509_context context,
3329 		    hx509_cert cert,
3330 		    ExtKeyUsage *e)
3331 {
3332     int ret;
3333 
3334     memset(e, 0, sizeof(*e));
3335 
3336     ret = find_extension_eku(_hx509_get_cert(cert), e);
3337     if (ret && ret != HX509_EXTENSION_NOT_FOUND) {
3338 	hx509_clear_error_string(context);
3339 	return ret;
3340     }
3341     return 0;
3342 }
3343 
3344 /**
3345  * Encodes the hx509 certificate as a DER encode binary.
3346  *
3347  * @param context A hx509 context.
3348  * @param c the certificate to encode.
3349  * @param os the encode certificate, set to NULL, 0 on case of
3350  * error. Free the os->data with hx509_xfree().
3351  *
3352  * @return An hx509 error code, see hx509_get_error_string().
3353  *
3354  * @ingroup hx509_cert
3355  */
3356 
3357 int
hx509_cert_binary(hx509_context context,hx509_cert c,heim_octet_string * os)3358 hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
3359 {
3360     size_t size;
3361     int ret;
3362 
3363     os->data = NULL;
3364     os->length = 0;
3365 
3366     ASN1_MALLOC_ENCODE(Certificate, os->data, os->length,
3367 		       _hx509_get_cert(c), &size, ret);
3368     if (ret) {
3369 	os->data = NULL;
3370 	os->length = 0;
3371 	return ret;
3372     }
3373     if (os->length != size)
3374 	_hx509_abort("internal ASN.1 encoder error");
3375 
3376     return ret;
3377 }
3378 
3379 /*
3380  * Last to avoid lost __attribute__s due to #undef.
3381  */
3382 
3383 #undef __attribute__
3384 #define __attribute__(X)
3385 
3386 void
_hx509_abort(const char * fmt,...)3387 _hx509_abort(const char *fmt, ...)
3388      __attribute__ ((noreturn, format (printf, 1, 2)))
3389 {
3390     va_list ap;
3391     va_start(ap, fmt);
3392     vprintf(fmt, ap);
3393     va_end(ap);
3394     printf("\n");
3395     fflush(stdout);
3396     abort();
3397 }
3398 
3399 /**
3400  * Free a data element allocated in the library.
3401  *
3402  * @param ptr data to be freed.
3403  *
3404  * @ingroup hx509_misc
3405  */
3406 
3407 void
hx509_xfree(void * ptr)3408 hx509_xfree(void *ptr)
3409 {
3410     free(ptr);
3411 }
3412 
3413 /**
3414  *
3415  */
3416 
3417 int
_hx509_cert_to_env(hx509_context context,hx509_cert cert,hx509_env * env)3418 _hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env)
3419 {
3420     ExtKeyUsage eku;
3421     hx509_name name;
3422     char *buf;
3423     int ret;
3424     hx509_env envcert = NULL;
3425 
3426     *env = NULL;
3427 
3428     /* version */
3429     asprintf(&buf, "%d", _hx509_cert_get_version(_hx509_get_cert(cert)));
3430     ret = hx509_env_add(context, &envcert, "version", buf);
3431     free(buf);
3432     if (ret)
3433 	goto out;
3434 
3435     /* subject */
3436     ret = hx509_cert_get_subject(cert, &name);
3437     if (ret)
3438 	goto out;
3439 
3440     ret = hx509_name_to_string(name, &buf);
3441     if (ret) {
3442 	hx509_name_free(&name);
3443 	goto out;
3444     }
3445 
3446     ret = hx509_env_add(context, &envcert, "subject", buf);
3447     hx509_name_free(&name);
3448     if (ret)
3449 	goto out;
3450 
3451     /* issuer */
3452     ret = hx509_cert_get_issuer(cert, &name);
3453     if (ret)
3454 	goto out;
3455 
3456     ret = hx509_name_to_string(name, &buf);
3457     hx509_name_free(&name);
3458     if (ret)
3459 	goto out;
3460 
3461     ret = hx509_env_add(context, &envcert, "issuer", buf);
3462     hx509_xfree(buf);
3463     if (ret)
3464 	goto out;
3465 
3466     /* eku */
3467 
3468     ret = _hx509_cert_get_eku(context, cert, &eku);
3469     if (ret == HX509_EXTENSION_NOT_FOUND)
3470 	;
3471     else if (ret != 0)
3472 	goto out;
3473     else {
3474 	size_t i;
3475 	hx509_env enveku = NULL;
3476 
3477 	for (i = 0; i < eku.len; i++) {
3478 
3479 	    ret = der_print_heim_oid(&eku.val[i], '.', &buf);
3480 	    if (ret) {
3481 		free_ExtKeyUsage(&eku);
3482 		hx509_env_free(&enveku);
3483 		goto out;
3484 	    }
3485 	    ret = hx509_env_add(context, &enveku, buf, "oid-name-here");
3486 	    free(buf);
3487 	    if (ret) {
3488 		free_ExtKeyUsage(&eku);
3489 		hx509_env_free(&enveku);
3490 		goto out;
3491 	    }
3492 	}
3493 	free_ExtKeyUsage(&eku);
3494 
3495 	ret = hx509_env_add_binding(context, &envcert, "eku", enveku);
3496 	if (ret) {
3497 	    hx509_env_free(&enveku);
3498 	    goto out;
3499 	}
3500     }
3501 
3502     {
3503 	Certificate *c = _hx509_get_cert(cert);
3504         heim_octet_string os, sig;
3505 	hx509_env envhash = NULL;
3506 
3507 	os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
3508 	os.length =
3509 	  c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
3510 
3511 	ret = _hx509_create_signature(context,
3512 				      NULL,
3513 				      hx509_signature_sha1(),
3514 				      &os,
3515 				      NULL,
3516 				      &sig);
3517 	if (ret != 0)
3518 	    goto out;
3519 
3520 	ret = hex_encode(sig.data, sig.length, &buf);
3521 	der_free_octet_string(&sig);
3522 	if (ret < 0) {
3523 	    ret = ENOMEM;
3524 	    hx509_set_error_string(context, 0, ret,
3525 				   "Out of memory");
3526 	    goto out;
3527 	}
3528 
3529 	ret = hx509_env_add(context, &envhash, "sha1", buf);
3530 	free(buf);
3531 	if (ret)
3532 	    goto out;
3533 
3534 	ret = hx509_env_add_binding(context, &envcert, "hash", envhash);
3535 	if (ret) {
3536 	  hx509_env_free(&envhash);
3537 	  goto out;
3538 	}
3539     }
3540 
3541     ret = hx509_env_add_binding(context, env, "certificate", envcert);
3542     if (ret)
3543 	goto out;
3544 
3545     return 0;
3546 
3547 out:
3548     hx509_env_free(&envcert);
3549     return ret;
3550 }
3551 
3552 /**
3553  * Print a simple representation of a certificate
3554  *
3555  * @param context A hx509 context, can be NULL
3556  * @param cert certificate to print
3557  * @param out the stdio output stream, if NULL, stdout is used
3558  *
3559  * @return An hx509 error code
3560  *
3561  * @ingroup hx509_cert
3562  */
3563 
3564 int
hx509_print_cert(hx509_context context,hx509_cert cert,FILE * out)3565 hx509_print_cert(hx509_context context, hx509_cert cert, FILE *out)
3566 {
3567     hx509_name name;
3568     char *str;
3569     int ret;
3570 
3571     if (out == NULL)
3572 	out = stderr;
3573 
3574     ret = hx509_cert_get_issuer(cert, &name);
3575     if (ret)
3576 	return ret;
3577     hx509_name_to_string(name, &str);
3578     hx509_name_free(&name);
3579     fprintf(out, "    issuer:  \"%s\"\n", str);
3580     free(str);
3581 
3582     ret = hx509_cert_get_subject(cert, &name);
3583     if (ret)
3584 	return ret;
3585     hx509_name_to_string(name, &str);
3586     hx509_name_free(&name);
3587     fprintf(out, "    subject: \"%s\"\n", str);
3588     free(str);
3589 
3590     {
3591 	heim_integer serialNumber;
3592 
3593 	ret = hx509_cert_get_serialnumber(cert, &serialNumber);
3594 	if (ret)
3595 	    return ret;
3596 	ret = der_print_hex_heim_integer(&serialNumber, &str);
3597 	if (ret)
3598 	    return ret;
3599 	der_free_heim_integer(&serialNumber);
3600 	fprintf(out, "    serial: %s\n", str);
3601 	free(str);
3602     }
3603 
3604     printf("    keyusage: ");
3605     ret = hx509_cert_keyusage_print(context, cert, &str);
3606     if (ret == 0) {
3607 	fprintf(out, "%s\n", str);
3608 	free(str);
3609     } else
3610 	fprintf(out, "no");
3611 
3612     return 0;
3613 }
3614