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