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