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