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