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