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