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