1/*
2 * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
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.
18 *
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.
22 *
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
33 * SUCH DAMAGE.
34 */
35
36#include "hx_locl.h"
37
38/**
39 * @page page_keyset Certificate store operations
40 *
41 * Type of certificates store:
42 * - MEMORY
43 *   In memory based format. Doesnt support storing.
44 * - FILE
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.
49 * - PEM-FILE
50 *   Same as FILE, defaulting to PEM encoded certificates.
51 * - PEM-FILE
52 *   Same as FILE, defaulting to DER encoded certificates.
53 * - PKCS11
54 * - PKCS12
55 * - DIR
56 * - KEYCHAIN
57 *   Apple Mac OS X KeyChain backed keychain object.
58 *
59 * See the library functions here: @ref hx509_keyset
60 */
61
62struct hx509_certs_data {
63    unsigned int ref;
64    struct hx509_keyset_ops *ops;
65    void *ops_data;
66};
67
68static struct hx509_keyset_ops *
69_hx509_ks_type(hx509_context context, const char *type)
70{
71    int i;
72
73    for (i = 0; i < context->ks_num_ops; i++)
74	if (strcasecmp(type, context->ks_ops[i]->name) == 0)
75	    return context->ks_ops[i];
76
77    return NULL;
78}
79
80void
81_hx509_ks_register(hx509_context context, struct hx509_keyset_ops *ops)
82{
83    struct hx509_keyset_ops **val;
84
85    if (_hx509_ks_type(context, ops->name))
86	return;
87
88    val = realloc(context->ks_ops,
89		  (context->ks_num_ops + 1) * sizeof(context->ks_ops[0]));
90    if (val == NULL)
91	return;
92    val[context->ks_num_ops] = ops;
93    context->ks_ops = val;
94    context->ks_num_ops++;
95}
96
97/**
98 * Open or creates a new hx509 certificate store.
99 *
100 * @param context A hx509 context
101 * @param name name of the store, format is TYPE:type-specific-string,
102 * if NULL is used the MEMORY store is used.
103 * @param flags list of flags:
104 * - HX509_CERTS_CREATE create a new keystore of the specific TYPE.
105 * - HX509_CERTS_UNPROTECT_ALL fails if any private key failed to be extracted.
106 * @param lock a lock that unlocks the certificates store, use NULL to
107 * select no password/certifictes/prompt lock (see @ref page_lock).
108 * @param certs return pointer, free with hx509_certs_free().
109 *
110 * @ingroup hx509_keyset
111 */
112
113int
114hx509_certs_init(hx509_context context,
115		 const char *name, int flags,
116		 hx509_lock lock, hx509_certs *certs)
117{
118    struct hx509_keyset_ops *ops;
119    const char *residue;
120    hx509_certs c;
121    char *type;
122    int ret;
123
124    *certs = NULL;
125
126    residue = strchr(name, ':');
127    if (residue) {
128	type = malloc(residue - name + 1);
129	if (type)
130	    strlcpy(type, name, residue - name + 1);
131	residue++;
132	if (residue[0] == '\0')
133	    residue = NULL;
134    } else {
135	type = strdup("MEMORY");
136	residue = name;
137    }
138    if (type == NULL) {
139	hx509_clear_error_string(context);
140	return ENOMEM;
141    }
142
143    ops = _hx509_ks_type(context, type);
144    if (ops == NULL) {
145	hx509_set_error_string(context, 0, ENOENT,
146			       "Keyset type %s is not supported", type);
147	free(type);
148	return ENOENT;
149    }
150    free(type);
151    c = calloc(1, sizeof(*c));
152    if (c == NULL) {
153	hx509_clear_error_string(context);
154	return ENOMEM;
155    }
156    c->ops = ops;
157    c->ref = 1;
158
159    ret = (*ops->init)(context, c, &c->ops_data, flags, residue, lock);
160    if (ret) {
161	free(c);
162	return ret;
163    }
164
165    *certs = c;
166    return 0;
167}
168
169/**
170 * Write the certificate store to stable storage.
171 *
172 * @param context A hx509 context.
173 * @param certs a certificate store to store.
174 * @param flags currently unused, use 0.
175 * @param lock a lock that unlocks the certificates store, use NULL to
176 * select no password/certifictes/prompt lock (see @ref page_lock).
177 *
178 * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION if
179 * the certificate store doesn't support the store operation.
180 *
181 * @ingroup hx509_keyset
182 */
183
184int
185hx509_certs_store(hx509_context context,
186		  hx509_certs certs,
187		  int flags,
188		  hx509_lock lock)
189{
190    if (certs->ops->store == NULL) {
191	hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
192			       "keystore if type %s doesn't support "
193			       "store operation",
194			       certs->ops->name);
195	return HX509_UNSUPPORTED_OPERATION;
196    }
197
198    return (*certs->ops->store)(context, certs, certs->ops_data, flags, lock);
199}
200
201
202hx509_certs
203hx509_certs_ref(hx509_certs certs)
204{
205    if (certs == NULL)
206	return NULL;
207    if (certs->ref == 0)
208	_hx509_abort("certs refcount == 0 on ref");
209    if (certs->ref == UINT_MAX)
210	_hx509_abort("certs refcount == UINT_MAX on ref");
211    certs->ref++;
212    return certs;
213}
214
215/**
216 * Free a certificate store.
217 *
218 * @param certs certificate store to free.
219 *
220 * @ingroup hx509_keyset
221 */
222
223void
224hx509_certs_free(hx509_certs *certs)
225{
226    if (*certs) {
227	if ((*certs)->ref == 0)
228	    _hx509_abort("cert refcount == 0 on free");
229	if (--(*certs)->ref > 0)
230	    return;
231
232	(*(*certs)->ops->free)(*certs, (*certs)->ops_data);
233	free(*certs);
234	*certs = NULL;
235    }
236}
237
238/**
239 * Start the integration
240 *
241 * @param context a hx509 context.
242 * @param certs certificate store to iterate over
243 * @param cursor cursor that will keep track of progress, free with
244 * hx509_certs_end_seq().
245 *
246 * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION is
247 * returned if the certificate store doesn't support the iteration
248 * operation.
249 *
250 * @ingroup hx509_keyset
251 */
252
253int
254hx509_certs_start_seq(hx509_context context,
255		      hx509_certs certs,
256		      hx509_cursor *cursor)
257{
258    int ret;
259
260    if (certs->ops->iter_start == NULL) {
261	hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
262			       "Keyset type %s doesn't support iteration",
263			       certs->ops->name);
264	return HX509_UNSUPPORTED_OPERATION;
265    }
266
267    ret = (*certs->ops->iter_start)(context, certs, certs->ops_data, cursor);
268    if (ret)
269	return ret;
270
271    return 0;
272}
273
274/**
275 * Get next ceritificate from the certificate keystore pointed out by
276 * cursor.
277 *
278 * @param context a hx509 context.
279 * @param certs certificate store to iterate over.
280 * @param cursor cursor that keeps track of progress.
281 * @param cert return certificate next in store, NULL if the store
282 * contains no more certificates. Free with hx509_cert_free().
283 *
284 * @return Returns an hx509 error code.
285 *
286 * @ingroup hx509_keyset
287 */
288
289int
290hx509_certs_next_cert(hx509_context context,
291		      hx509_certs certs,
292		      hx509_cursor cursor,
293		      hx509_cert *cert)
294{
295    *cert = NULL;
296    return (*certs->ops->iter)(context, certs, certs->ops_data, cursor, cert);
297}
298
299/**
300 * End the iteration over certificates.
301 *
302 * @param context a hx509 context.
303 * @param certs certificate store to iterate over.
304 * @param cursor cursor that will keep track of progress, freed.
305 *
306 * @return Returns an hx509 error code.
307 *
308 * @ingroup hx509_keyset
309 */
310
311int
312hx509_certs_end_seq(hx509_context context,
313		    hx509_certs certs,
314		    hx509_cursor cursor)
315{
316    (*certs->ops->iter_end)(context, certs, certs->ops_data, cursor);
317    return 0;
318}
319
320/**
321 * Iterate over all certificates in a keystore and call an function
322 * for each fo them.
323 *
324 * @param context a hx509 context.
325 * @param certs certificate store to iterate over.
326 * @param func function to call for each certificate. The function
327 * should return non-zero to abort the iteration, that value is passed
328 * back to the caller of hx509_certs_iter_f().
329 * @param ctx context variable that will passed to the function.
330 *
331 * @return Returns an hx509 error code.
332 *
333 * @ingroup hx509_keyset
334 */
335
336int
337hx509_certs_iter_f(hx509_context context,
338		   hx509_certs certs,
339		   int (*func)(hx509_context, void *, hx509_cert),
340		   void *ctx)
341{
342    hx509_cursor cursor;
343    hx509_cert c;
344    int ret;
345
346    ret = hx509_certs_start_seq(context, certs, &cursor);
347    if (ret)
348	return ret;
349
350    while (1) {
351	ret = hx509_certs_next_cert(context, certs, cursor, &c);
352	if (ret)
353	    break;
354	if (c == NULL) {
355	    ret = 0;
356	    break;
357	}
358	ret = (*func)(context, ctx, c);
359	hx509_cert_free(c);
360	if (ret)
361	    break;
362    }
363
364    hx509_certs_end_seq(context, certs, cursor);
365
366    return ret;
367}
368
369/**
370 * Iterate over all certificates in a keystore and call an function
371 * for each fo them.
372 *
373 * @param context a hx509 context.
374 * @param certs certificate store to iterate over.
375 * @param func function to call for each certificate. The function
376 * should return non-zero to abort the iteration, that value is passed
377 * back to the caller of hx509_certs_iter().
378 *
379 * @return Returns an hx509 error code.
380 *
381 * @ingroup hx509_keyset
382 */
383
384#ifdef __BLOCKS__
385
386static int
387certs_iter(hx509_context context, void *ctx, hx509_cert cert)
388{
389    int (^func)(hx509_cert) = ctx;
390    return func(cert);
391}
392
393/**
394 * Iterate over all certificates in a keystore and call an block
395 * for each fo them.
396 *
397 * @param context a hx509 context.
398 * @param certs certificate store to iterate over.
399 * @param func block to call for each certificate. The function
400 * should return non-zero to abort the iteration, that value is passed
401 * back to the caller of hx509_certs_iter().
402 *
403 * @return Returns an hx509 error code.
404 *
405 * @ingroup hx509_keyset
406 */
407
408int
409hx509_certs_iter(hx509_context context,
410		 hx509_certs certs,
411		 int (^func)(hx509_cert))
412{
413    return hx509_certs_iter_f(context, certs, certs_iter, func);
414}
415#endif
416
417
418/**
419 * Function to use to hx509_certs_iter_f() as a function argument, the
420 * ctx variable to hx509_certs_iter_f() should be a FILE file descriptor.
421 *
422 * @param context a hx509 context.
423 * @param ctx used by hx509_certs_iter_f().
424 * @param c a certificate
425 *
426 * @return Returns an hx509 error code.
427 *
428 * @ingroup hx509_keyset
429 */
430
431int
432hx509_ci_print_names(hx509_context context, void *ctx, hx509_cert c)
433{
434    Certificate *cert;
435    hx509_name n;
436    char *s, *i;
437
438    cert = _hx509_get_cert(c);
439
440    _hx509_name_from_Name(&cert->tbsCertificate.subject, &n);
441    hx509_name_to_string(n, &s);
442    hx509_name_free(&n);
443    _hx509_name_from_Name(&cert->tbsCertificate.issuer, &n);
444    hx509_name_to_string(n, &i);
445    hx509_name_free(&n);
446    fprintf(ctx, "subject: %s\nissuer: %s\n", s, i);
447    free(s);
448    free(i);
449    return 0;
450}
451
452/**
453 * Add a certificate to the certificiate store.
454 *
455 * The receiving keyset certs will either increase reference counter
456 * of the cert or make a deep copy, either way, the caller needs to
457 * free the cert itself.
458 *
459 * @param context a hx509 context.
460 * @param certs certificate store to add the certificate to.
461 * @param cert certificate to add.
462 *
463 * @return Returns an hx509 error code.
464 *
465 * @ingroup hx509_keyset
466 */
467
468int
469hx509_certs_add(hx509_context context, hx509_certs certs, hx509_cert cert)
470{
471    if (certs->ops->add == NULL) {
472	hx509_set_error_string(context, 0, ENOENT,
473			       "Keyset type %s doesn't support add operation",
474			       certs->ops->name);
475	return ENOENT;
476    }
477
478    return (*certs->ops->add)(context, certs, certs->ops_data, cert);
479}
480
481/**
482 * Find a certificate matching the query.
483 *
484 * @param context a hx509 context.
485 * @param certs certificate store to search.
486 * @param q query allocated with @ref hx509_query functions.
487 * @param r return certificate (or NULL on error), should be freed
488 * with hx509_cert_free().
489 *
490 * @return Returns an hx509 error code.
491 *
492 * @ingroup hx509_keyset
493 */
494
495int
496hx509_certs_find(hx509_context context,
497		 hx509_certs certs,
498		 const hx509_query *q,
499		 hx509_cert *r)
500{
501    hx509_cursor cursor;
502    hx509_cert c;
503    int ret;
504
505    *r = NULL;
506
507    _hx509_query_statistic(context, 0, q);
508
509    if (certs->ops->query)
510	return (*certs->ops->query)(context, certs, certs->ops_data, q, r);
511
512    ret = hx509_certs_start_seq(context, certs, &cursor);
513    if (ret)
514	return ret;
515
516    c = NULL;
517    while (1) {
518	ret = hx509_certs_next_cert(context, certs, cursor, &c);
519	if (ret)
520	    break;
521	if (c == NULL)
522	    break;
523	if (_hx509_query_match_cert(context, q, c)) {
524	    *r = c;
525	    break;
526	}
527	hx509_cert_free(c);
528    }
529
530    hx509_certs_end_seq(context, certs, cursor);
531    if (ret)
532	return ret;
533    /**
534     * Return HX509_CERT_NOT_FOUND if no certificate in certs matched
535     * the query.
536     */
537    if (c == NULL) {
538	hx509_clear_error_string(context);
539	return HX509_CERT_NOT_FOUND;
540    }
541
542    return 0;
543}
544
545/**
546 * Filter certificate matching the query.
547 *
548 * @param context a hx509 context.
549 * @param certs certificate store to search.
550 * @param q query allocated with @ref hx509_query functions.
551 * @param result the filtered certificate store, caller must free with
552 *        hx509_certs_free().
553 *
554 * @return Returns an hx509 error code.
555 *
556 * @ingroup hx509_keyset
557 */
558
559int
560hx509_certs_filter(hx509_context context,
561		   hx509_certs certs,
562		   const hx509_query *q,
563		   hx509_certs *result)
564{
565    hx509_cursor cursor;
566    hx509_cert c;
567    int ret, found = 0;
568
569    _hx509_query_statistic(context, 0, q);
570
571    ret = hx509_certs_init(context, "MEMORY:filter-certs", 0,
572			   NULL, result);
573    if (ret)
574	return ret;
575
576    ret = hx509_certs_start_seq(context, certs, &cursor);
577    if (ret) {
578	hx509_certs_free(result);
579	return ret;
580    }
581
582    c = NULL;
583    while (1) {
584	ret = hx509_certs_next_cert(context, certs, cursor, &c);
585	if (ret)
586	    break;
587	if (c == NULL)
588	    break;
589	if (_hx509_query_match_cert(context, q, c)) {
590	    hx509_certs_add(context, *result, c);
591	    found = 1;
592	}
593	hx509_cert_free(c);
594    }
595
596    hx509_certs_end_seq(context, certs, cursor);
597    if (ret) {
598	hx509_certs_free(result);
599	return ret;
600    }
601
602    /**
603     * Return HX509_CERT_NOT_FOUND if no certificate in certs matched
604     * the query.
605     */
606    if (!found) {
607	hx509_certs_free(result);
608	hx509_clear_error_string(context);
609	return HX509_CERT_NOT_FOUND;
610    }
611
612    return 0;
613}
614
615
616static int
617certs_merge_func(hx509_context context, void *ctx, hx509_cert c)
618{
619    return hx509_certs_add(context, (hx509_certs)ctx, c);
620}
621
622/**
623 * Merge a certificate store into another. The from store is keep
624 * intact.
625 *
626 * @param context a hx509 context.
627 * @param to the store to merge into.
628 * @param from the store to copy the object from.
629 *
630 * @return Returns an hx509 error code.
631 *
632 * @ingroup hx509_keyset
633 */
634
635int
636hx509_certs_merge(hx509_context context, hx509_certs to, hx509_certs from)
637{
638    if (from == NULL)
639	return 0;
640    return hx509_certs_iter_f(context, from, certs_merge_func, to);
641}
642
643/**
644 * Same a hx509_certs_merge() but use a lock and name to describe the
645 * from source.
646 *
647 * @param context a hx509 context.
648 * @param to the store to merge into.
649 * @param lock a lock that unlocks the certificates store, use NULL to
650 * select no password/certifictes/prompt lock (see @ref page_lock).
651 * @param name name of the source store
652 *
653 * @return Returns an hx509 error code.
654 *
655 * @ingroup hx509_keyset
656 */
657
658int
659hx509_certs_append(hx509_context context,
660		   hx509_certs to,
661		   hx509_lock lock,
662		   const char *name)
663{
664    hx509_certs s;
665    int ret;
666
667    ret = hx509_certs_init(context, name, 0, lock, &s);
668    if (ret)
669	return ret;
670    ret = hx509_certs_merge(context, to, s);
671    hx509_certs_free(&s);
672    return ret;
673}
674
675/**
676 * Get one random certificate from the certificate store.
677 *
678 * @param context a hx509 context.
679 * @param certs a certificate store to get the certificate from.
680 * @param c return certificate, should be freed with hx509_cert_free().
681 *
682 * @return Returns an hx509 error code.
683 *
684 * @ingroup hx509_keyset
685 */
686
687int
688hx509_get_one_cert(hx509_context context, hx509_certs certs, hx509_cert *c)
689{
690    hx509_cursor cursor;
691    int ret;
692
693    *c = NULL;
694
695    ret = hx509_certs_start_seq(context, certs, &cursor);
696    if (ret)
697	return ret;
698
699    ret = hx509_certs_next_cert(context, certs, cursor, c);
700    if (ret)
701	return ret;
702
703    hx509_certs_end_seq(context, certs, cursor);
704    return 0;
705}
706
707static int
708certs_info_stdio(void *ctx, const char *str)
709{
710    FILE *f = ctx;
711    fprintf(f, "%s\n", str);
712    return 0;
713}
714
715/**
716 * Print some info about the certificate store.
717 *
718 * @param context a hx509 context.
719 * @param certs certificate store to print information about.
720 * @param func function that will get each line of the information, if
721 * NULL is used the data is printed on a FILE descriptor that should
722 * be passed in ctx, if ctx also is NULL, stdout is used.
723 * @param ctx parameter to func.
724 *
725 * @return Returns an hx509 error code.
726 *
727 * @ingroup hx509_keyset
728 */
729
730int
731hx509_certs_info(hx509_context context,
732		 hx509_certs certs,
733		 int (*func)(void *, const char *),
734		 void *ctx)
735{
736    if (func == NULL) {
737	func = certs_info_stdio;
738	if (ctx == NULL)
739	    ctx = stdout;
740    }
741    if (certs->ops->printinfo == NULL) {
742	(*func)(ctx, "No info function for certs");
743	return 0;
744    }
745    return (*certs->ops->printinfo)(context, certs, certs->ops_data,
746				    func, ctx);
747}
748
749void
750_hx509_pi_printf(int (*func)(void *, const char *), void *ctx,
751		 const char *fmt, ...)
752{
753    va_list ap;
754    char *str;
755
756    va_start(ap, fmt);
757    vasprintf(&str, fmt, ap);
758    va_end(ap);
759    if (str == NULL)
760	return;
761    (*func)(ctx, str);
762    free(str);
763}
764
765int
766_hx509_certs_keys_get(hx509_context context,
767		      hx509_certs certs,
768		      hx509_private_key **keys)
769{
770    if (certs->ops->getkeys == NULL) {
771	*keys = NULL;
772	return 0;
773    }
774    return (*certs->ops->getkeys)(context, certs, certs->ops_data, keys);
775}
776
777int
778_hx509_certs_keys_add(hx509_context context,
779		      hx509_certs certs,
780		      hx509_private_key key)
781{
782    if (certs->ops->addkey == NULL) {
783	hx509_set_error_string(context, 0, EINVAL,
784			       "keystore if type %s doesn't support "
785			       "key add operation",
786			       certs->ops->name);
787	return EINVAL;
788    }
789    return (*certs->ops->addkey)(context, certs, certs->ops_data, key);
790}
791
792
793void
794_hx509_certs_keys_free(hx509_context context,
795		       hx509_private_key *keys)
796{
797    int i;
798    for (i = 0; keys[i]; i++)
799	hx509_private_key_free(&keys[i]);
800    free(keys);
801}
802