2 * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * @page page_keyset Certificate store operations
41 * Type of certificates store:
43 * In memory based format. Doesn't support storing.
45 * FILE supports raw DER certicates and PEM certicates. When PEM is
46 * used the file can contain may certificates and match private
47 * keys. Support storing the certificates. DER format only supports
48 * on certificate and no private key.
50 * Same as FILE, defaulting to PEM encoded certificates.
52 * Same as FILE, defaulting to DER encoded certificates.
57 * Apple Mac OS X KeyChain backed keychain object.
59 * See the library functions here: @ref hx509_keyset
62 struct hx509_certs_data {
64 struct hx509_keyset_ops *ops;
69 struct hx509_keyset_ops *
70 _hx509_ks_type(hx509_context context, const char *type)
74 for (i = 0; i < context->ks_num_ops; i++)
75 if (strcasecmp(type, context->ks_ops[i]->name) == 0)
76 return context->ks_ops[i];
81 HX509_LIB_FUNCTION void HX509_LIB_CALL
82 _hx509_ks_register(hx509_context context, struct hx509_keyset_ops *ops)
84 struct hx509_keyset_ops **val;
86 if (_hx509_ks_type(context, ops->name))
89 val = realloc(context->ks_ops,
90 (context->ks_num_ops + 1) * sizeof(context->ks_ops[0]));
93 val[context->ks_num_ops] = ops;
94 context->ks_ops = val;
95 context->ks_num_ops++;
99 * Open or creates a new hx509 certificate store.
101 * @param context A hx509 context
102 * @param name name of the store, format is TYPE:type-specific-string,
103 * if NULL is used the MEMORY store is used.
104 * @param flags list of flags:
105 * - HX509_CERTS_CREATE create a new keystore of the specific TYPE.
106 * - HX509_CERTS_UNPROTECT_ALL fails if any private key failed to be extracted.
107 * - HX509_CERTS_NO_PRIVATE_KEYS does not load or permit adding private keys
108 * @param lock a lock that unlocks the certificates store, use NULL to
109 * select no password/certifictes/prompt lock (see @ref page_lock).
110 * @param certs return pointer, free with hx509_certs_free().
112 * @return Returns an hx509 error code.
114 * @ingroup hx509_keyset
117 HX509_LIB_FUNCTION int HX509_LIB_CALL
118 hx509_certs_init(hx509_context context,
119 const char *name, int flags,
120 hx509_lock lock, hx509_certs *certs)
122 struct hx509_keyset_ops *ops;
133 residue = strchr(name, ':');
135 type = malloc(residue - name + 1);
137 strlcpy(type, name, residue - name + 1);
139 if (residue[0] == '\0')
142 type = strdup("MEMORY");
146 hx509_clear_error_string(context);
150 ops = _hx509_ks_type(context, type);
152 hx509_set_error_string(context, 0, ENOENT,
153 "Keyset type %s is not supported", type);
158 c = calloc(1, sizeof(*c));
160 hx509_clear_error_string(context);
167 ret = (*ops->init)(context, c, &c->ops_data, flags, residue, lock);
178 * Destroys and frees a hx509 certificate store.
180 * @param context A hx509 context
181 * @param certs A store to destroy
183 * @return Returns an hx509 error code.
185 * @ingroup hx509_keyset
188 HX509_LIB_FUNCTION int HX509_LIB_CALL
189 hx509_certs_destroy(hx509_context context,
195 if ((*certs)->ops->destroy)
196 ret = ((*certs)->ops->destroy)(context, *certs, (*certs)->ops_data);
200 hx509_certs_free(certs);
205 * Write the certificate store to stable storage.
207 * Use the HX509_CERTS_STORE_NO_PRIVATE_KEYS flag to ensure that no private
208 * keys are stored, even if added.
210 * @param context A hx509 context.
211 * @param certs a certificate store to store.
212 * @param flags currently one flag is defined: HX509_CERTS_STORE_NO_PRIVATE_KEYS
213 * @param lock a lock that unlocks the certificates store, use NULL to
214 * select no password/certifictes/prompt lock (see @ref page_lock).
216 * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION if
217 * the certificate store doesn't support the store operation.
219 * @ingroup hx509_keyset
222 HX509_LIB_FUNCTION int HX509_LIB_CALL
223 hx509_certs_store(hx509_context context,
228 if (certs->ops->store == NULL) {
229 hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
230 "keystore if type %s doesn't support "
233 return HX509_UNSUPPORTED_OPERATION;
236 return (*certs->ops->store)(context, certs, certs->ops_data, flags, lock);
240 HX509_LIB_FUNCTION hx509_certs HX509_LIB_CALL
241 hx509_certs_ref(hx509_certs certs)
246 _hx509_abort("certs refcount == 0 on ref");
247 if (certs->ref == UINT_MAX)
248 _hx509_abort("certs refcount == UINT_MAX on ref");
254 * Free a certificate store.
256 * @param certs certificate store to free.
258 * @ingroup hx509_keyset
261 HX509_LIB_FUNCTION void HX509_LIB_CALL
262 hx509_certs_free(hx509_certs *certs)
265 if ((*certs)->ref == 0)
266 _hx509_abort("cert refcount == 0 on free");
267 if (--(*certs)->ref > 0)
270 (*(*certs)->ops->free)(*certs, (*certs)->ops_data);
277 * Start the integration
279 * @param context a hx509 context.
280 * @param certs certificate store to iterate over
281 * @param cursor cursor that will keep track of progress, free with
282 * hx509_certs_end_seq().
284 * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION is
285 * returned if the certificate store doesn't support the iteration
288 * @ingroup hx509_keyset
291 HX509_LIB_FUNCTION int HX509_LIB_CALL
292 hx509_certs_start_seq(hx509_context context,
294 hx509_cursor *cursor)
298 if (certs->ops->iter_start == NULL) {
299 hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
300 "Keyset type %s doesn't support iteration",
302 return HX509_UNSUPPORTED_OPERATION;
305 ret = (*certs->ops->iter_start)(context, certs, certs->ops_data, cursor);
313 * Get next ceritificate from the certificate keystore pointed out by
316 * @param context a hx509 context.
317 * @param certs certificate store to iterate over.
318 * @param cursor cursor that keeps track of progress.
319 * @param cert return certificate next in store, NULL if the store
320 * contains no more certificates. Free with hx509_cert_free().
322 * @return Returns an hx509 error code.
324 * @ingroup hx509_keyset
327 HX509_LIB_FUNCTION int HX509_LIB_CALL
328 hx509_certs_next_cert(hx509_context context,
334 return (*certs->ops->iter)(context, certs, certs->ops_data, cursor, cert);
338 * End the iteration over certificates.
340 * @param context a hx509 context.
341 * @param certs certificate store to iterate over.
342 * @param cursor cursor that will keep track of progress, freed.
344 * @return Returns an hx509 error code.
346 * @ingroup hx509_keyset
349 HX509_LIB_FUNCTION int HX509_LIB_CALL
350 hx509_certs_end_seq(hx509_context context,
354 (*certs->ops->iter_end)(context, certs, certs->ops_data, cursor);
359 * Iterate over all certificates in a keystore and call a function
362 * @param context a hx509 context.
363 * @param certs certificate store to iterate over.
364 * @param func function to call for each certificate. The function
365 * should return non-zero to abort the iteration, that value is passed
366 * back to the caller of hx509_certs_iter_f().
367 * @param ctx context variable that will passed to the function.
369 * @return Returns an hx509 error code.
371 * @ingroup hx509_keyset
374 HX509_LIB_FUNCTION int HX509_LIB_CALL
375 hx509_certs_iter_f(hx509_context context,
377 int (HX509_LIB_CALL *func)(hx509_context, void *, hx509_cert),
384 ret = hx509_certs_start_seq(context, certs, &cursor);
389 ret = hx509_certs_next_cert(context, certs, cursor, &c);
396 ret = (*func)(context, ctx, c);
402 hx509_certs_end_seq(context, certs, cursor);
410 certs_iter(hx509_context context, void *ctx, hx509_cert cert)
412 int (^func)(hx509_cert) = ctx;
417 * Iterate over all certificates in a keystore and call a block
420 * @param context a hx509 context.
421 * @param certs certificate store to iterate over.
422 * @param func block to call for each certificate. The function
423 * should return non-zero to abort the iteration, that value is passed
424 * back to the caller of hx509_certs_iter().
426 * @return Returns an hx509 error code.
428 * @ingroup hx509_keyset
431 HX509_LIB_FUNCTION int HX509_LIB_CALL
432 hx509_certs_iter(hx509_context context,
434 int (^func)(hx509_cert))
436 return hx509_certs_iter_f(context, certs, certs_iter, func);
442 * Function to use to hx509_certs_iter_f() as a function argument, the
443 * ctx variable to hx509_certs_iter_f() should be a FILE file descriptor.
445 * @param context a hx509 context.
446 * @param ctx used by hx509_certs_iter_f().
447 * @param c a certificate
449 * @return Returns an hx509 error code.
451 * @ingroup hx509_keyset
454 HX509_LIB_FUNCTION int HX509_LIB_CALL
455 hx509_ci_print_names(hx509_context context, void *ctx, hx509_cert c)
461 cert = _hx509_get_cert(c);
463 _hx509_name_from_Name(&cert->tbsCertificate.subject, &n);
464 hx509_name_to_string(n, &s);
466 _hx509_name_from_Name(&cert->tbsCertificate.issuer, &n);
467 hx509_name_to_string(n, &i);
469 fprintf(ctx, "subject: %s\nissuer: %s\n", s, i);
476 * Add a certificate to the certificiate store.
478 * The receiving keyset certs will either increase reference counter
479 * of the cert or make a deep copy, either way, the caller needs to
480 * free the cert itself.
482 * @param context a hx509 context.
483 * @param certs certificate store to add the certificate to.
484 * @param cert certificate to add.
486 * @return Returns an hx509 error code.
488 * @ingroup hx509_keyset
491 HX509_LIB_FUNCTION int HX509_LIB_CALL
492 hx509_certs_add(hx509_context context, hx509_certs certs, hx509_cert cert)
494 hx509_cert copy = NULL;
497 if (certs->ops->add == NULL) {
498 hx509_set_error_string(context, 0, ENOENT,
499 "Keyset type %s doesn't support add operation",
504 if ((certs->flags & HX509_CERTS_NO_PRIVATE_KEYS) &&
505 hx509_cert_have_private_key(cert)) {
506 if ((copy = hx509_cert_copy_no_private_key(context, cert,
508 hx509_set_error_string(context, 0, ENOMEM,
509 "Could not add certificate to store");
515 ret = (*certs->ops->add)(context, certs, certs->ops_data, cert);
516 hx509_cert_free(copy);
521 * Find a certificate matching the query.
523 * @param context a hx509 context.
524 * @param certs certificate store to search.
525 * @param q query allocated with @ref hx509_query functions.
526 * @param r return certificate (or NULL on error), should be freed
527 * with hx509_cert_free().
529 * @return Returns an hx509 error code.
531 * @ingroup hx509_keyset
534 HX509_LIB_FUNCTION int HX509_LIB_CALL
535 hx509_certs_find(hx509_context context,
537 const hx509_query *q,
546 _hx509_query_statistic(context, 0, q);
548 if (certs->ops->query)
549 return (*certs->ops->query)(context, certs, certs->ops_data, q, r);
551 ret = hx509_certs_start_seq(context, certs, &cursor);
557 ret = hx509_certs_next_cert(context, certs, cursor, &c);
562 if (_hx509_query_match_cert(context, q, c)) {
569 hx509_certs_end_seq(context, certs, cursor);
573 * Return HX509_CERT_NOT_FOUND if no certificate in certs matched
577 hx509_clear_error_string(context);
578 return HX509_CERT_NOT_FOUND;
585 * Filter certificate matching the query.
587 * @param context a hx509 context.
588 * @param certs certificate store to search.
589 * @param q query allocated with @ref hx509_query functions.
590 * @param result the filtered certificate store, caller must free with
591 * hx509_certs_free().
593 * @return Returns an hx509 error code.
595 * @ingroup hx509_keyset
598 HX509_LIB_FUNCTION int HX509_LIB_CALL
599 hx509_certs_filter(hx509_context context,
601 const hx509_query *q,
608 _hx509_query_statistic(context, 0, q);
610 ret = hx509_certs_init(context, "MEMORY:filter-certs", 0,
615 ret = hx509_certs_start_seq(context, certs, &cursor);
617 hx509_certs_free(result);
623 ret = hx509_certs_next_cert(context, certs, cursor, &c);
628 if (_hx509_query_match_cert(context, q, c)) {
629 hx509_certs_add(context, *result, c);
635 hx509_certs_end_seq(context, certs, cursor);
637 hx509_certs_free(result);
642 * Return HX509_CERT_NOT_FOUND if no certificate in certs matched
646 hx509_certs_free(result);
647 hx509_clear_error_string(context);
648 return HX509_CERT_NOT_FOUND;
655 static int HX509_LIB_CALL
656 certs_merge_func(hx509_context context, void *ctx, hx509_cert c)
658 return hx509_certs_add(context, (hx509_certs)ctx, c);
662 * Merge one certificate store into another. The from store is kept intact.
664 * @param context a hx509 context.
665 * @param to the store to merge into.
666 * @param from the store to copy the object from.
668 * @return Returns an hx509 error code.
670 * @ingroup hx509_keyset
673 HX509_LIB_FUNCTION int HX509_LIB_CALL
674 hx509_certs_merge(hx509_context context, hx509_certs to, hx509_certs from)
678 return hx509_certs_iter_f(context, from, certs_merge_func, to);
682 * Same a hx509_certs_merge() but use a lock and name to describe the
685 * @param context a hx509 context.
686 * @param to the store to merge into.
687 * @param lock a lock that unlocks the certificates store, use NULL to
688 * select no password/certifictes/prompt lock (see @ref page_lock).
689 * @param name name of the source store
691 * @return Returns an hx509 error code.
693 * @ingroup hx509_keyset
696 HX509_LIB_FUNCTION int HX509_LIB_CALL
697 hx509_certs_append(hx509_context context,
705 ret = hx509_certs_init(context, name, 0, lock, &s);
708 ret = hx509_certs_merge(context, to, s);
709 hx509_certs_free(&s);
714 * Get one random certificate from the certificate store.
716 * @param context a hx509 context.
717 * @param certs a certificate store to get the certificate from.
718 * @param c return certificate, should be freed with hx509_cert_free().
720 * @return Returns an hx509 error code.
722 * @ingroup hx509_keyset
725 HX509_LIB_FUNCTION int HX509_LIB_CALL
726 hx509_get_one_cert(hx509_context context, hx509_certs certs, hx509_cert *c)
733 ret = hx509_certs_start_seq(context, certs, &cursor);
737 ret = hx509_certs_next_cert(context, certs, cursor, c);
741 hx509_certs_end_seq(context, certs, cursor);
746 certs_info_stdio(void *ctx, const char *str)
749 fprintf(f, "%s\n", str);
754 * Print some info about the certificate store.
756 * @param context a hx509 context.
757 * @param certs certificate store to print information about.
758 * @param func function that will get each line of the information, if
759 * NULL is used the data is printed on a FILE descriptor that should
760 * be passed in ctx, if ctx also is NULL, stdout is used.
761 * @param ctx parameter to func.
763 * @return Returns an hx509 error code.
765 * @ingroup hx509_keyset
768 HX509_LIB_FUNCTION int HX509_LIB_CALL
769 hx509_certs_info(hx509_context context,
771 int (*func)(void *, const char *),
775 func = certs_info_stdio;
779 if (certs->ops->printinfo == NULL) {
780 (*func)(ctx, "No info function for certs");
783 return (*certs->ops->printinfo)(context, certs, certs->ops_data,
787 HX509_LIB_FUNCTION void HX509_LIB_CALL
788 _hx509_pi_printf(int (*func)(void *, const char *), void *ctx,
789 const char *fmt, ...)
796 ret = vasprintf(&str, fmt, ap);
798 if (ret == -1 || str == NULL)
804 HX509_LIB_FUNCTION int HX509_LIB_CALL
805 _hx509_certs_keys_get(hx509_context context,
807 hx509_private_key **keys)
809 if (certs->ops->getkeys == NULL) {
813 return (*certs->ops->getkeys)(context, certs, certs->ops_data, keys);
816 HX509_LIB_FUNCTION int HX509_LIB_CALL
817 _hx509_certs_keys_add(hx509_context context,
819 hx509_private_key key)
821 if (certs->ops->addkey == NULL) {
822 hx509_set_error_string(context, 0, EINVAL,
823 "keystore if type %s doesn't support "
828 return (*certs->ops->addkey)(context, certs, certs->ops_data, key);
832 HX509_LIB_FUNCTION void HX509_LIB_CALL
833 _hx509_certs_keys_free(hx509_context context,
834 hx509_private_key *keys)
840 for (i = 0; keys[i]; i++)
841 hx509_private_key_free(&keys[i]);