1178825Sdfr/* 2178825Sdfr * Copyright (c) 2004 - 2007 Kungliga Tekniska H�gskolan 3178825Sdfr * (Royal Institute of Technology, Stockholm, Sweden). 4178825Sdfr * All rights reserved. 5178825Sdfr * 6178825Sdfr * Redistribution and use in source and binary forms, with or without 7178825Sdfr * modification, are permitted provided that the following conditions 8178825Sdfr * are met: 9178825Sdfr * 10178825Sdfr * 1. Redistributions of source code must retain the above copyright 11178825Sdfr * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 14178825Sdfr * notice, this list of conditions and the following disclaimer in the 15178825Sdfr * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17178825Sdfr * 3. Neither the name of the Institute nor the names of its contributors 18178825Sdfr * may be used to endorse or promote products derived from this software 19178825Sdfr * without specific prior written permission. 20178825Sdfr * 21178825Sdfr * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31178825Sdfr * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "hx_locl.h" 35178825SdfrRCSID("$Id: cert.c 22450 2008-01-15 19:39:14Z lha $"); 36178825Sdfr#include "crypto-headers.h" 37178825Sdfr#include <rtbl.h> 38178825Sdfr 39178825Sdfr/** 40178825Sdfr * @page page_cert The basic certificate 41178825Sdfr * 42178825Sdfr * The basic hx509 cerificate object in hx509 is hx509_cert. The 43178825Sdfr * hx509_cert object is representing one X509/PKIX certificate and 44178825Sdfr * associated attributes; like private key, friendly name, etc. 45178825Sdfr * 46178825Sdfr * A hx509_cert object is usully found via the keyset interfaces (@ref 47178825Sdfr * page_keyset), but its also possible to create a certificate 48178825Sdfr * directly from a parsed object with hx509_cert_init() and 49178825Sdfr * hx509_cert_init_data(). 50178825Sdfr * 51178825Sdfr * See the library functions here: @ref hx509_cert 52178825Sdfr */ 53178825Sdfr 54178825Sdfrstruct hx509_verify_ctx_data { 55178825Sdfr hx509_certs trust_anchors; 56178825Sdfr int flags; 57178825Sdfr#define HX509_VERIFY_CTX_F_TIME_SET 1 58178825Sdfr#define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE 2 59178825Sdfr#define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4 60178825Sdfr#define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8 61178825Sdfr#define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16 62178825Sdfr time_t time_now; 63178825Sdfr unsigned int max_depth; 64178825Sdfr#define HX509_VERIFY_MAX_DEPTH 30 65178825Sdfr hx509_revoke_ctx revoke_ctx; 66178825Sdfr}; 67178825Sdfr 68178825Sdfr#define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280) 69178825Sdfr#define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS) 70178825Sdfr#define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0) 71178825Sdfr 72178825Sdfrstruct _hx509_cert_attrs { 73178825Sdfr size_t len; 74178825Sdfr hx509_cert_attribute *val; 75178825Sdfr}; 76178825Sdfr 77178825Sdfrstruct hx509_cert_data { 78178825Sdfr unsigned int ref; 79178825Sdfr char *friendlyname; 80178825Sdfr Certificate *data; 81178825Sdfr hx509_private_key private_key; 82178825Sdfr struct _hx509_cert_attrs attrs; 83178825Sdfr hx509_name basename; 84178825Sdfr _hx509_cert_release_func release; 85178825Sdfr void *ctx; 86178825Sdfr}; 87178825Sdfr 88178825Sdfrtypedef struct hx509_name_constraints { 89178825Sdfr NameConstraints *val; 90178825Sdfr size_t len; 91178825Sdfr} hx509_name_constraints; 92178825Sdfr 93178825Sdfr#define GeneralSubtrees_SET(g,var) \ 94178825Sdfr (g)->len = (var)->len, (g)->val = (var)->val; 95178825Sdfr 96178825Sdfr/** 97178825Sdfr * Creates a hx509 context that most functions in the library 98178825Sdfr * uses. The context is only allowed to be used by one thread at each 99178825Sdfr * moment. Free the context with hx509_context_free(). 100178825Sdfr * 101178825Sdfr * @param context Returns a pointer to new hx509 context. 102178825Sdfr * 103178825Sdfr * @return Returns an hx509 error code. 104178825Sdfr * 105178825Sdfr * @ingroup hx509 106178825Sdfr */ 107178825Sdfr 108178825Sdfrint 109178825Sdfrhx509_context_init(hx509_context *context) 110178825Sdfr{ 111178825Sdfr *context = calloc(1, sizeof(**context)); 112178825Sdfr if (*context == NULL) 113178825Sdfr return ENOMEM; 114178825Sdfr 115178825Sdfr _hx509_ks_null_register(*context); 116178825Sdfr _hx509_ks_mem_register(*context); 117178825Sdfr _hx509_ks_file_register(*context); 118178825Sdfr _hx509_ks_pkcs12_register(*context); 119178825Sdfr _hx509_ks_pkcs11_register(*context); 120178825Sdfr _hx509_ks_dir_register(*context); 121178825Sdfr _hx509_ks_keychain_register(*context); 122178825Sdfr 123178825Sdfr ENGINE_add_conf_module(); 124178825Sdfr OpenSSL_add_all_algorithms(); 125178825Sdfr 126178825Sdfr (*context)->ocsp_time_diff = HX509_DEFAULT_OCSP_TIME_DIFF; 127178825Sdfr 128178825Sdfr initialize_hx_error_table_r(&(*context)->et_list); 129178825Sdfr initialize_asn1_error_table_r(&(*context)->et_list); 130178825Sdfr 131178825Sdfr#ifdef HX509_DEFAULT_ANCHORS 132178825Sdfr (void)hx509_certs_init(*context, HX509_DEFAULT_ANCHORS, 0, 133178825Sdfr NULL, &(*context)->default_trust_anchors); 134178825Sdfr#endif 135178825Sdfr 136178825Sdfr return 0; 137178825Sdfr} 138178825Sdfr 139178825Sdfr/** 140178825Sdfr * Selects if the hx509_revoke_verify() function is going to require 141178825Sdfr * the existans of a revokation method (OSCP, CRL) or not. Note that 142178825Sdfr * hx509_verify_path(), hx509_cms_verify_signed(), and other function 143178825Sdfr * call hx509_revoke_verify(). 144178825Sdfr * 145178825Sdfr * @param context hx509 context to change the flag for. 146178825Sdfr * @param flag zero, revokation method required, non zero missing 147178825Sdfr * revokation method ok 148178825Sdfr * 149178825Sdfr * @ingroup hx509_verify 150178825Sdfr */ 151178825Sdfr 152178825Sdfrvoid 153178825Sdfrhx509_context_set_missing_revoke(hx509_context context, int flag) 154178825Sdfr{ 155178825Sdfr if (flag) 156178825Sdfr context->flags |= HX509_CTX_VERIFY_MISSING_OK; 157178825Sdfr else 158178825Sdfr context->flags &= ~HX509_CTX_VERIFY_MISSING_OK; 159178825Sdfr} 160178825Sdfr 161178825Sdfr/** 162178825Sdfr * Free the context allocated by hx509_context_init(). 163178825Sdfr * 164178825Sdfr * @param context context to be freed. 165178825Sdfr * 166178825Sdfr * @ingroup hx509 167178825Sdfr */ 168178825Sdfr 169178825Sdfrvoid 170178825Sdfrhx509_context_free(hx509_context *context) 171178825Sdfr{ 172178825Sdfr hx509_clear_error_string(*context); 173178825Sdfr if ((*context)->ks_ops) { 174178825Sdfr free((*context)->ks_ops); 175178825Sdfr (*context)->ks_ops = NULL; 176178825Sdfr } 177178825Sdfr (*context)->ks_num_ops = 0; 178178825Sdfr free_error_table ((*context)->et_list); 179178825Sdfr if ((*context)->querystat) 180178825Sdfr free((*context)->querystat); 181178825Sdfr memset(*context, 0, sizeof(**context)); 182178825Sdfr free(*context); 183178825Sdfr *context = NULL; 184178825Sdfr} 185178825Sdfr 186178825Sdfr/* 187178825Sdfr * 188178825Sdfr */ 189178825Sdfr 190178825SdfrCertificate * 191178825Sdfr_hx509_get_cert(hx509_cert cert) 192178825Sdfr{ 193178825Sdfr return cert->data; 194178825Sdfr} 195178825Sdfr 196178825Sdfr/* 197178825Sdfr * 198178825Sdfr */ 199178825Sdfr 200178825Sdfrint 201178825Sdfr_hx509_cert_get_version(const Certificate *t) 202178825Sdfr{ 203178825Sdfr return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1; 204178825Sdfr} 205178825Sdfr 206178825Sdfr/** 207178825Sdfr * Allocate and init an hx509 certificate object from the decoded 208178825Sdfr * certificate `c�. 209178825Sdfr * 210178825Sdfr * @param context A hx509 context. 211178825Sdfr * @param c 212178825Sdfr * @param cert 213178825Sdfr * 214178825Sdfr * @return Returns an hx509 error code. 215178825Sdfr * 216178825Sdfr * @ingroup hx509_cert 217178825Sdfr */ 218178825Sdfr 219178825Sdfrint 220178825Sdfrhx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert) 221178825Sdfr{ 222178825Sdfr int ret; 223178825Sdfr 224178825Sdfr *cert = malloc(sizeof(**cert)); 225178825Sdfr if (*cert == NULL) 226178825Sdfr return ENOMEM; 227178825Sdfr (*cert)->ref = 1; 228178825Sdfr (*cert)->friendlyname = NULL; 229178825Sdfr (*cert)->attrs.len = 0; 230178825Sdfr (*cert)->attrs.val = NULL; 231178825Sdfr (*cert)->private_key = NULL; 232178825Sdfr (*cert)->basename = NULL; 233178825Sdfr (*cert)->release = NULL; 234178825Sdfr (*cert)->ctx = NULL; 235178825Sdfr 236178825Sdfr (*cert)->data = calloc(1, sizeof(*(*cert)->data)); 237178825Sdfr if ((*cert)->data == NULL) { 238178825Sdfr free(*cert); 239178825Sdfr return ENOMEM; 240178825Sdfr } 241178825Sdfr ret = copy_Certificate(c, (*cert)->data); 242178825Sdfr if (ret) { 243178825Sdfr free((*cert)->data); 244178825Sdfr free(*cert); 245178825Sdfr *cert = NULL; 246178825Sdfr } 247178825Sdfr return ret; 248178825Sdfr} 249178825Sdfr 250178825Sdfr/** 251178825Sdfr * Just like hx509_cert_init(), but instead of a decode certificate 252178825Sdfr * takes an pointer and length to a memory region that contains a 253178825Sdfr * DER/BER encoded certificate. 254178825Sdfr * 255178825Sdfr * If the memory region doesn't contain just the certificate and 256178825Sdfr * nothing more the function will fail with 257178825Sdfr * HX509_EXTRA_DATA_AFTER_STRUCTURE. 258178825Sdfr * 259178825Sdfr * @param context A hx509 context. 260178825Sdfr * @param ptr pointer to memory region containing encoded certificate. 261178825Sdfr * @param len length of memory region. 262178825Sdfr * @param cert a return pointer to a hx509 certificate object, will 263178825Sdfr * contain NULL on error. 264178825Sdfr * 265178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 266178825Sdfr * 267178825Sdfr * @ingroup hx509_cert 268178825Sdfr */ 269178825Sdfr 270178825Sdfrint 271178825Sdfrhx509_cert_init_data(hx509_context context, 272178825Sdfr const void *ptr, 273178825Sdfr size_t len, 274178825Sdfr hx509_cert *cert) 275178825Sdfr{ 276178825Sdfr Certificate t; 277178825Sdfr size_t size; 278178825Sdfr int ret; 279178825Sdfr 280178825Sdfr ret = decode_Certificate(ptr, len, &t, &size); 281178825Sdfr if (ret) { 282178825Sdfr hx509_set_error_string(context, 0, ret, "Failed to decode certificate"); 283178825Sdfr return ret; 284178825Sdfr } 285178825Sdfr if (size != len) { 286178825Sdfr hx509_set_error_string(context, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE, 287178825Sdfr "Extra data after certificate"); 288178825Sdfr return HX509_EXTRA_DATA_AFTER_STRUCTURE; 289178825Sdfr } 290178825Sdfr 291178825Sdfr ret = hx509_cert_init(context, &t, cert); 292178825Sdfr free_Certificate(&t); 293178825Sdfr return ret; 294178825Sdfr} 295178825Sdfr 296178825Sdfrvoid 297178825Sdfr_hx509_cert_set_release(hx509_cert cert, 298178825Sdfr _hx509_cert_release_func release, 299178825Sdfr void *ctx) 300178825Sdfr{ 301178825Sdfr cert->release = release; 302178825Sdfr cert->ctx = ctx; 303178825Sdfr} 304178825Sdfr 305178825Sdfr 306178825Sdfr/* Doesn't make a copy of `private_key'. */ 307178825Sdfr 308178825Sdfrint 309178825Sdfr_hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key) 310178825Sdfr{ 311178825Sdfr if (cert->private_key) 312178825Sdfr _hx509_private_key_free(&cert->private_key); 313178825Sdfr cert->private_key = _hx509_private_key_ref(private_key); 314178825Sdfr return 0; 315178825Sdfr} 316178825Sdfr 317178825Sdfr/** 318178825Sdfr * Free reference to the hx509 certificate object, if the refcounter 319178825Sdfr * reaches 0, the object if freed. Its allowed to pass in NULL. 320178825Sdfr * 321178825Sdfr * @param cert the cert to free. 322178825Sdfr * 323178825Sdfr * @ingroup hx509_cert 324178825Sdfr */ 325178825Sdfr 326178825Sdfrvoid 327178825Sdfrhx509_cert_free(hx509_cert cert) 328178825Sdfr{ 329178825Sdfr int i; 330178825Sdfr 331178825Sdfr if (cert == NULL) 332178825Sdfr return; 333178825Sdfr 334178825Sdfr if (cert->ref <= 0) 335178825Sdfr _hx509_abort("cert refcount <= 0 on free"); 336178825Sdfr if (--cert->ref > 0) 337178825Sdfr return; 338178825Sdfr 339178825Sdfr if (cert->release) 340178825Sdfr (cert->release)(cert, cert->ctx); 341178825Sdfr 342178825Sdfr if (cert->private_key) 343178825Sdfr _hx509_private_key_free(&cert->private_key); 344178825Sdfr 345178825Sdfr free_Certificate(cert->data); 346178825Sdfr free(cert->data); 347178825Sdfr 348178825Sdfr for (i = 0; i < cert->attrs.len; i++) { 349178825Sdfr der_free_octet_string(&cert->attrs.val[i]->data); 350178825Sdfr der_free_oid(&cert->attrs.val[i]->oid); 351178825Sdfr free(cert->attrs.val[i]); 352178825Sdfr } 353178825Sdfr free(cert->attrs.val); 354178825Sdfr free(cert->friendlyname); 355178825Sdfr if (cert->basename) 356178825Sdfr hx509_name_free(&cert->basename); 357178825Sdfr memset(cert, 0, sizeof(cert)); 358178825Sdfr free(cert); 359178825Sdfr} 360178825Sdfr 361178825Sdfr/** 362178825Sdfr * Add a reference to a hx509 certificate object. 363178825Sdfr * 364178825Sdfr * @param cert a pointer to an hx509 certificate object. 365178825Sdfr * 366178825Sdfr * @return the same object as is passed in. 367178825Sdfr * 368178825Sdfr * @ingroup hx509_cert 369178825Sdfr */ 370178825Sdfr 371178825Sdfrhx509_cert 372178825Sdfrhx509_cert_ref(hx509_cert cert) 373178825Sdfr{ 374178825Sdfr if (cert == NULL) 375178825Sdfr return NULL; 376178825Sdfr if (cert->ref <= 0) 377178825Sdfr _hx509_abort("cert refcount <= 0"); 378178825Sdfr cert->ref++; 379178825Sdfr if (cert->ref == 0) 380178825Sdfr _hx509_abort("cert refcount == 0"); 381178825Sdfr return cert; 382178825Sdfr} 383178825Sdfr 384178825Sdfr/** 385178825Sdfr * Allocate an verification context that is used fo control the 386178825Sdfr * verification process. 387178825Sdfr * 388178825Sdfr * @param context A hx509 context. 389178825Sdfr * @param ctx returns a pointer to a hx509_verify_ctx object. 390178825Sdfr * 391178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 392178825Sdfr * 393178825Sdfr * @ingroup hx509_verify 394178825Sdfr */ 395178825Sdfr 396178825Sdfrint 397178825Sdfrhx509_verify_init_ctx(hx509_context context, hx509_verify_ctx *ctx) 398178825Sdfr{ 399178825Sdfr hx509_verify_ctx c; 400178825Sdfr 401178825Sdfr c = calloc(1, sizeof(*c)); 402178825Sdfr if (c == NULL) 403178825Sdfr return ENOMEM; 404178825Sdfr 405178825Sdfr c->max_depth = HX509_VERIFY_MAX_DEPTH; 406178825Sdfr 407178825Sdfr *ctx = c; 408178825Sdfr 409178825Sdfr return 0; 410178825Sdfr} 411178825Sdfr 412178825Sdfr/** 413178825Sdfr * Free an hx509 verification context. 414178825Sdfr * 415178825Sdfr * @param ctx the context to be freed. 416178825Sdfr * 417178825Sdfr * @ingroup hx509_verify 418178825Sdfr */ 419178825Sdfr 420178825Sdfrvoid 421178825Sdfrhx509_verify_destroy_ctx(hx509_verify_ctx ctx) 422178825Sdfr{ 423178825Sdfr if (ctx) { 424178825Sdfr hx509_certs_free(&ctx->trust_anchors); 425178825Sdfr hx509_revoke_free(&ctx->revoke_ctx); 426178825Sdfr memset(ctx, 0, sizeof(*ctx)); 427178825Sdfr } 428178825Sdfr free(ctx); 429178825Sdfr} 430178825Sdfr 431178825Sdfr/** 432178825Sdfr * Set the trust anchors in the verification context, makes an 433178825Sdfr * reference to the keyset, so the consumer can free the keyset 434178825Sdfr * independent of the destruction of the verification context (ctx). 435178825Sdfr * 436178825Sdfr * @param ctx a verification context 437178825Sdfr * @param set a keyset containing the trust anchors. 438178825Sdfr * 439178825Sdfr * @ingroup hx509_verify 440178825Sdfr */ 441178825Sdfr 442178825Sdfrvoid 443178825Sdfrhx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set) 444178825Sdfr{ 445178825Sdfr ctx->trust_anchors = _hx509_certs_ref(set); 446178825Sdfr} 447178825Sdfr 448178825Sdfr/** 449178825Sdfr * Attach an revocation context to the verfication context, , makes an 450178825Sdfr * reference to the revoke context, so the consumer can free the 451178825Sdfr * revoke context independent of the destruction of the verification 452178825Sdfr * context. If there is no revoke context, the verification process is 453178825Sdfr * NOT going to check any verification status. 454178825Sdfr * 455178825Sdfr * @param ctx a verification context. 456178825Sdfr * @param revoke_ctx a revoke context. 457178825Sdfr * 458178825Sdfr * @ingroup hx509_verify 459178825Sdfr */ 460178825Sdfr 461178825Sdfrvoid 462178825Sdfrhx509_verify_attach_revoke(hx509_verify_ctx ctx, hx509_revoke_ctx revoke_ctx) 463178825Sdfr{ 464178825Sdfr if (ctx->revoke_ctx) 465178825Sdfr hx509_revoke_free(&ctx->revoke_ctx); 466178825Sdfr ctx->revoke_ctx = _hx509_revoke_ref(revoke_ctx); 467178825Sdfr} 468178825Sdfr 469178825Sdfr/** 470178825Sdfr * Set the clock time the the verification process is going to 471178825Sdfr * use. Used to check certificate in the past and future time. If not 472178825Sdfr * set the current time will be used. 473178825Sdfr * 474178825Sdfr * @param ctx a verification context. 475178825Sdfr * @param t the time the verifiation is using. 476178825Sdfr * 477178825Sdfr * 478178825Sdfr * @ingroup hx509_verify 479178825Sdfr */ 480178825Sdfr 481178825Sdfrvoid 482178825Sdfrhx509_verify_set_time(hx509_verify_ctx ctx, time_t t) 483178825Sdfr{ 484178825Sdfr ctx->flags |= HX509_VERIFY_CTX_F_TIME_SET; 485178825Sdfr ctx->time_now = t; 486178825Sdfr} 487178825Sdfr 488178825Sdfr/** 489178825Sdfr * Set the maximum depth of the certificate chain that the path 490178825Sdfr * builder is going to try. 491178825Sdfr * 492178825Sdfr * @param ctx a verification context 493178825Sdfr * @param max_depth maxium depth of the certificate chain, include 494178825Sdfr * trust anchor. 495178825Sdfr * 496178825Sdfr * @ingroup hx509_verify 497178825Sdfr */ 498178825Sdfr 499178825Sdfrvoid 500178825Sdfrhx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth) 501178825Sdfr{ 502178825Sdfr ctx->max_depth = max_depth; 503178825Sdfr} 504178825Sdfr 505178825Sdfr/** 506178825Sdfr * Allow or deny the use of proxy certificates 507178825Sdfr * 508178825Sdfr * @param ctx a verification context 509178825Sdfr * @param boolean if non zero, allow proxy certificates. 510178825Sdfr * 511178825Sdfr * @ingroup hx509_verify 512178825Sdfr */ 513178825Sdfr 514178825Sdfrvoid 515178825Sdfrhx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean) 516178825Sdfr{ 517178825Sdfr if (boolean) 518178825Sdfr ctx->flags |= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE; 519178825Sdfr else 520178825Sdfr ctx->flags &= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE; 521178825Sdfr} 522178825Sdfr 523178825Sdfr/** 524178825Sdfr * Select strict RFC3280 verification of certificiates. This means 525178825Sdfr * checking key usage on CA certificates, this will make version 1 526178825Sdfr * certificiates unuseable. 527178825Sdfr * 528178825Sdfr * @param ctx a verification context 529178825Sdfr * @param boolean if non zero, use strict verification. 530178825Sdfr * 531178825Sdfr * @ingroup hx509_verify 532178825Sdfr */ 533178825Sdfr 534178825Sdfrvoid 535178825Sdfrhx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean) 536178825Sdfr{ 537178825Sdfr if (boolean) 538178825Sdfr ctx->flags |= HX509_VERIFY_CTX_F_REQUIRE_RFC3280; 539178825Sdfr else 540178825Sdfr ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280; 541178825Sdfr} 542178825Sdfr 543178825Sdfr/** 544178825Sdfr * Allow using the operating system builtin trust anchors if no other 545178825Sdfr * trust anchors are configured. 546178825Sdfr * 547178825Sdfr * @param ctx a verification context 548178825Sdfr * @param boolean if non zero, useing the operating systems builtin 549178825Sdfr * trust anchors. 550178825Sdfr * 551178825Sdfr * 552178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 553178825Sdfr * 554178825Sdfr * @ingroup hx509_cert 555178825Sdfr */ 556178825Sdfr 557178825Sdfrvoid 558178825Sdfrhx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean) 559178825Sdfr{ 560178825Sdfr if (boolean) 561178825Sdfr ctx->flags &= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS; 562178825Sdfr else 563178825Sdfr ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS; 564178825Sdfr} 565178825Sdfr 566178825Sdfrstatic const Extension * 567178825Sdfrfind_extension(const Certificate *cert, const heim_oid *oid, int *idx) 568178825Sdfr{ 569178825Sdfr const TBSCertificate *c = &cert->tbsCertificate; 570178825Sdfr 571178825Sdfr if (c->version == NULL || *c->version < 2 || c->extensions == NULL) 572178825Sdfr return NULL; 573178825Sdfr 574178825Sdfr for (;*idx < c->extensions->len; (*idx)++) { 575178825Sdfr if (der_heim_oid_cmp(&c->extensions->val[*idx].extnID, oid) == 0) 576178825Sdfr return &c->extensions->val[(*idx)++]; 577178825Sdfr } 578178825Sdfr return NULL; 579178825Sdfr} 580178825Sdfr 581178825Sdfrstatic int 582178825Sdfrfind_extension_auth_key_id(const Certificate *subject, 583178825Sdfr AuthorityKeyIdentifier *ai) 584178825Sdfr{ 585178825Sdfr const Extension *e; 586178825Sdfr size_t size; 587178825Sdfr int i = 0; 588178825Sdfr 589178825Sdfr memset(ai, 0, sizeof(*ai)); 590178825Sdfr 591178825Sdfr e = find_extension(subject, oid_id_x509_ce_authorityKeyIdentifier(), &i); 592178825Sdfr if (e == NULL) 593178825Sdfr return HX509_EXTENSION_NOT_FOUND; 594178825Sdfr 595178825Sdfr return decode_AuthorityKeyIdentifier(e->extnValue.data, 596178825Sdfr e->extnValue.length, 597178825Sdfr ai, &size); 598178825Sdfr} 599178825Sdfr 600178825Sdfrint 601178825Sdfr_hx509_find_extension_subject_key_id(const Certificate *issuer, 602178825Sdfr SubjectKeyIdentifier *si) 603178825Sdfr{ 604178825Sdfr const Extension *e; 605178825Sdfr size_t size; 606178825Sdfr int i = 0; 607178825Sdfr 608178825Sdfr memset(si, 0, sizeof(*si)); 609178825Sdfr 610178825Sdfr e = find_extension(issuer, oid_id_x509_ce_subjectKeyIdentifier(), &i); 611178825Sdfr if (e == NULL) 612178825Sdfr return HX509_EXTENSION_NOT_FOUND; 613178825Sdfr 614178825Sdfr return decode_SubjectKeyIdentifier(e->extnValue.data, 615178825Sdfr e->extnValue.length, 616178825Sdfr si, &size); 617178825Sdfr} 618178825Sdfr 619178825Sdfrstatic int 620178825Sdfrfind_extension_name_constraints(const Certificate *subject, 621178825Sdfr NameConstraints *nc) 622178825Sdfr{ 623178825Sdfr const Extension *e; 624178825Sdfr size_t size; 625178825Sdfr int i = 0; 626178825Sdfr 627178825Sdfr memset(nc, 0, sizeof(*nc)); 628178825Sdfr 629178825Sdfr e = find_extension(subject, oid_id_x509_ce_nameConstraints(), &i); 630178825Sdfr if (e == NULL) 631178825Sdfr return HX509_EXTENSION_NOT_FOUND; 632178825Sdfr 633178825Sdfr return decode_NameConstraints(e->extnValue.data, 634178825Sdfr e->extnValue.length, 635178825Sdfr nc, &size); 636178825Sdfr} 637178825Sdfr 638178825Sdfrstatic int 639178825Sdfrfind_extension_subject_alt_name(const Certificate *cert, int *i, 640178825Sdfr GeneralNames *sa) 641178825Sdfr{ 642178825Sdfr const Extension *e; 643178825Sdfr size_t size; 644178825Sdfr 645178825Sdfr memset(sa, 0, sizeof(*sa)); 646178825Sdfr 647178825Sdfr e = find_extension(cert, oid_id_x509_ce_subjectAltName(), i); 648178825Sdfr if (e == NULL) 649178825Sdfr return HX509_EXTENSION_NOT_FOUND; 650178825Sdfr 651178825Sdfr return decode_GeneralNames(e->extnValue.data, 652178825Sdfr e->extnValue.length, 653178825Sdfr sa, &size); 654178825Sdfr} 655178825Sdfr 656178825Sdfrstatic int 657178825Sdfrfind_extension_eku(const Certificate *cert, ExtKeyUsage *eku) 658178825Sdfr{ 659178825Sdfr const Extension *e; 660178825Sdfr size_t size; 661178825Sdfr int i = 0; 662178825Sdfr 663178825Sdfr memset(eku, 0, sizeof(*eku)); 664178825Sdfr 665178825Sdfr e = find_extension(cert, oid_id_x509_ce_extKeyUsage(), &i); 666178825Sdfr if (e == NULL) 667178825Sdfr return HX509_EXTENSION_NOT_FOUND; 668178825Sdfr 669178825Sdfr return decode_ExtKeyUsage(e->extnValue.data, 670178825Sdfr e->extnValue.length, 671178825Sdfr eku, &size); 672178825Sdfr} 673178825Sdfr 674178825Sdfrstatic int 675178825Sdfradd_to_list(hx509_octet_string_list *list, const heim_octet_string *entry) 676178825Sdfr{ 677178825Sdfr void *p; 678178825Sdfr int ret; 679178825Sdfr 680178825Sdfr p = realloc(list->val, (list->len + 1) * sizeof(list->val[0])); 681178825Sdfr if (p == NULL) 682178825Sdfr return ENOMEM; 683178825Sdfr list->val = p; 684178825Sdfr ret = der_copy_octet_string(entry, &list->val[list->len]); 685178825Sdfr if (ret) 686178825Sdfr return ret; 687178825Sdfr list->len++; 688178825Sdfr return 0; 689178825Sdfr} 690178825Sdfr 691178825Sdfr/** 692178825Sdfr * Free a list of octet strings returned by another hx509 library 693178825Sdfr * function. 694178825Sdfr * 695178825Sdfr * @param list list to be freed. 696178825Sdfr * 697178825Sdfr * @ingroup hx509_misc 698178825Sdfr */ 699178825Sdfr 700178825Sdfrvoid 701178825Sdfrhx509_free_octet_string_list(hx509_octet_string_list *list) 702178825Sdfr{ 703178825Sdfr int i; 704178825Sdfr for (i = 0; i < list->len; i++) 705178825Sdfr der_free_octet_string(&list->val[i]); 706178825Sdfr free(list->val); 707178825Sdfr list->val = NULL; 708178825Sdfr list->len = 0; 709178825Sdfr} 710178825Sdfr 711178825Sdfr/** 712178825Sdfr * Return a list of subjectAltNames specified by oid in the 713178825Sdfr * certificate. On error the 714178825Sdfr * 715178825Sdfr * The returned list of octet string should be freed with 716178825Sdfr * hx509_free_octet_string_list(). 717178825Sdfr * 718178825Sdfr * @param context A hx509 context. 719178825Sdfr * @param cert a hx509 certificate object. 720178825Sdfr * @param oid an oid to for SubjectAltName. 721178825Sdfr * @param list list of matching SubjectAltName. 722178825Sdfr * 723178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 724178825Sdfr * 725178825Sdfr * @ingroup hx509_cert 726178825Sdfr */ 727178825Sdfr 728178825Sdfrint 729178825Sdfrhx509_cert_find_subjectAltName_otherName(hx509_context context, 730178825Sdfr hx509_cert cert, 731178825Sdfr const heim_oid *oid, 732178825Sdfr hx509_octet_string_list *list) 733178825Sdfr{ 734178825Sdfr GeneralNames sa; 735178825Sdfr int ret, i, j; 736178825Sdfr 737178825Sdfr list->val = NULL; 738178825Sdfr list->len = 0; 739178825Sdfr 740178825Sdfr i = 0; 741178825Sdfr while (1) { 742178825Sdfr ret = find_extension_subject_alt_name(_hx509_get_cert(cert), &i, &sa); 743178825Sdfr i++; 744178825Sdfr if (ret == HX509_EXTENSION_NOT_FOUND) { 745178825Sdfr ret = 0; 746178825Sdfr break; 747178825Sdfr } else if (ret != 0) { 748178825Sdfr hx509_set_error_string(context, 0, ret, "Error searching for SAN"); 749178825Sdfr hx509_free_octet_string_list(list); 750178825Sdfr return ret; 751178825Sdfr } 752178825Sdfr 753178825Sdfr for (j = 0; j < sa.len; j++) { 754178825Sdfr if (sa.val[j].element == choice_GeneralName_otherName && 755178825Sdfr der_heim_oid_cmp(&sa.val[j].u.otherName.type_id, oid) == 0) 756178825Sdfr { 757178825Sdfr ret = add_to_list(list, &sa.val[j].u.otherName.value); 758178825Sdfr if (ret) { 759178825Sdfr hx509_set_error_string(context, 0, ret, 760178825Sdfr "Error adding an exra SAN to " 761178825Sdfr "return list"); 762178825Sdfr hx509_free_octet_string_list(list); 763178825Sdfr free_GeneralNames(&sa); 764178825Sdfr return ret; 765178825Sdfr } 766178825Sdfr } 767178825Sdfr } 768178825Sdfr free_GeneralNames(&sa); 769178825Sdfr } 770178825Sdfr return 0; 771178825Sdfr} 772178825Sdfr 773178825Sdfr 774178825Sdfrstatic int 775178825Sdfrcheck_key_usage(hx509_context context, const Certificate *cert, 776178825Sdfr unsigned flags, int req_present) 777178825Sdfr{ 778178825Sdfr const Extension *e; 779178825Sdfr KeyUsage ku; 780178825Sdfr size_t size; 781178825Sdfr int ret, i = 0; 782178825Sdfr unsigned ku_flags; 783178825Sdfr 784178825Sdfr if (_hx509_cert_get_version(cert) < 3) 785178825Sdfr return 0; 786178825Sdfr 787178825Sdfr e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i); 788178825Sdfr if (e == NULL) { 789178825Sdfr if (req_present) { 790178825Sdfr hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING, 791178825Sdfr "Required extension key " 792178825Sdfr "usage missing from certifiate"); 793178825Sdfr return HX509_KU_CERT_MISSING; 794178825Sdfr } 795178825Sdfr return 0; 796178825Sdfr } 797178825Sdfr 798178825Sdfr ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &size); 799178825Sdfr if (ret) 800178825Sdfr return ret; 801178825Sdfr ku_flags = KeyUsage2int(ku); 802178825Sdfr if ((ku_flags & flags) != flags) { 803178825Sdfr unsigned missing = (~ku_flags) & flags; 804178825Sdfr char buf[256], *name; 805178825Sdfr 806178825Sdfr unparse_flags(missing, asn1_KeyUsage_units(), buf, sizeof(buf)); 807178825Sdfr _hx509_unparse_Name(&cert->tbsCertificate.subject, &name); 808178825Sdfr hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING, 809178825Sdfr "Key usage %s required but missing " 810178825Sdfr "from certifiate %s", buf, name); 811178825Sdfr free(name); 812178825Sdfr return HX509_KU_CERT_MISSING; 813178825Sdfr } 814178825Sdfr return 0; 815178825Sdfr} 816178825Sdfr 817178825Sdfr/* 818178825Sdfr * Return 0 on matching key usage 'flags' for 'cert', otherwise return 819178825Sdfr * an error code. If 'req_present' the existance is required of the 820178825Sdfr * KeyUsage extension. 821178825Sdfr */ 822178825Sdfr 823178825Sdfrint 824178825Sdfr_hx509_check_key_usage(hx509_context context, hx509_cert cert, 825178825Sdfr unsigned flags, int req_present) 826178825Sdfr{ 827178825Sdfr return check_key_usage(context, _hx509_get_cert(cert), flags, req_present); 828178825Sdfr} 829178825Sdfr 830178825Sdfrenum certtype { PROXY_CERT, EE_CERT, CA_CERT }; 831178825Sdfr 832178825Sdfrstatic int 833178825Sdfrcheck_basic_constraints(hx509_context context, const Certificate *cert, 834178825Sdfr enum certtype type, int depth) 835178825Sdfr{ 836178825Sdfr BasicConstraints bc; 837178825Sdfr const Extension *e; 838178825Sdfr size_t size; 839178825Sdfr int ret, i = 0; 840178825Sdfr 841178825Sdfr if (_hx509_cert_get_version(cert) < 3) 842178825Sdfr return 0; 843178825Sdfr 844178825Sdfr e = find_extension(cert, oid_id_x509_ce_basicConstraints(), &i); 845178825Sdfr if (e == NULL) { 846178825Sdfr switch(type) { 847178825Sdfr case PROXY_CERT: 848178825Sdfr case EE_CERT: 849178825Sdfr return 0; 850178825Sdfr case CA_CERT: { 851178825Sdfr char *name; 852178825Sdfr ret = _hx509_unparse_Name(&cert->tbsCertificate.subject, &name); 853178825Sdfr assert(ret == 0); 854178825Sdfr hx509_set_error_string(context, 0, HX509_EXTENSION_NOT_FOUND, 855178825Sdfr "basicConstraints missing from " 856178825Sdfr "CA certifiacte %s", name); 857178825Sdfr free(name); 858178825Sdfr return HX509_EXTENSION_NOT_FOUND; 859178825Sdfr } 860178825Sdfr } 861178825Sdfr } 862178825Sdfr 863178825Sdfr ret = decode_BasicConstraints(e->extnValue.data, 864178825Sdfr e->extnValue.length, &bc, 865178825Sdfr &size); 866178825Sdfr if (ret) 867178825Sdfr return ret; 868178825Sdfr switch(type) { 869178825Sdfr case PROXY_CERT: 870178825Sdfr if (bc.cA != NULL && *bc.cA) 871178825Sdfr ret = HX509_PARENT_IS_CA; 872178825Sdfr break; 873178825Sdfr case EE_CERT: 874178825Sdfr ret = 0; 875178825Sdfr break; 876178825Sdfr case CA_CERT: 877178825Sdfr if (bc.cA == NULL || !*bc.cA) 878178825Sdfr ret = HX509_PARENT_NOT_CA; 879178825Sdfr else if (bc.pathLenConstraint) 880178825Sdfr if (depth - 1 > *bc.pathLenConstraint) 881178825Sdfr ret = HX509_CA_PATH_TOO_DEEP; 882178825Sdfr break; 883178825Sdfr } 884178825Sdfr free_BasicConstraints(&bc); 885178825Sdfr return ret; 886178825Sdfr} 887178825Sdfr 888178825Sdfrint 889178825Sdfr_hx509_cert_is_parent_cmp(const Certificate *subject, 890178825Sdfr const Certificate *issuer, 891178825Sdfr int allow_self_signed) 892178825Sdfr{ 893178825Sdfr int diff; 894178825Sdfr AuthorityKeyIdentifier ai; 895178825Sdfr SubjectKeyIdentifier si; 896178825Sdfr int ret_ai, ret_si; 897178825Sdfr 898178825Sdfr diff = _hx509_name_cmp(&issuer->tbsCertificate.subject, 899178825Sdfr &subject->tbsCertificate.issuer); 900178825Sdfr if (diff) 901178825Sdfr return diff; 902178825Sdfr 903178825Sdfr memset(&ai, 0, sizeof(ai)); 904178825Sdfr memset(&si, 0, sizeof(si)); 905178825Sdfr 906178825Sdfr /* 907178825Sdfr * Try to find AuthorityKeyIdentifier, if it's not present in the 908178825Sdfr * subject certificate nor the parent. 909178825Sdfr */ 910178825Sdfr 911178825Sdfr ret_ai = find_extension_auth_key_id(subject, &ai); 912178825Sdfr if (ret_ai && ret_ai != HX509_EXTENSION_NOT_FOUND) 913178825Sdfr return 1; 914178825Sdfr ret_si = _hx509_find_extension_subject_key_id(issuer, &si); 915178825Sdfr if (ret_si && ret_si != HX509_EXTENSION_NOT_FOUND) 916178825Sdfr return -1; 917178825Sdfr 918178825Sdfr if (ret_si && ret_ai) 919178825Sdfr goto out; 920178825Sdfr if (ret_ai) 921178825Sdfr goto out; 922178825Sdfr if (ret_si) { 923178825Sdfr if (allow_self_signed) { 924178825Sdfr diff = 0; 925178825Sdfr goto out; 926178825Sdfr } else if (ai.keyIdentifier) { 927178825Sdfr diff = -1; 928178825Sdfr goto out; 929178825Sdfr } 930178825Sdfr } 931178825Sdfr 932178825Sdfr if (ai.keyIdentifier == NULL) { 933178825Sdfr Name name; 934178825Sdfr 935178825Sdfr if (ai.authorityCertIssuer == NULL) 936178825Sdfr return -1; 937178825Sdfr if (ai.authorityCertSerialNumber == NULL) 938178825Sdfr return -1; 939178825Sdfr 940178825Sdfr diff = der_heim_integer_cmp(ai.authorityCertSerialNumber, 941178825Sdfr &issuer->tbsCertificate.serialNumber); 942178825Sdfr if (diff) 943178825Sdfr return diff; 944178825Sdfr if (ai.authorityCertIssuer->len != 1) 945178825Sdfr return -1; 946178825Sdfr if (ai.authorityCertIssuer->val[0].element != choice_GeneralName_directoryName) 947178825Sdfr return -1; 948178825Sdfr 949178825Sdfr name.element = 950178825Sdfr ai.authorityCertIssuer->val[0].u.directoryName.element; 951178825Sdfr name.u.rdnSequence = 952178825Sdfr ai.authorityCertIssuer->val[0].u.directoryName.u.rdnSequence; 953178825Sdfr 954178825Sdfr diff = _hx509_name_cmp(&issuer->tbsCertificate.subject, 955178825Sdfr &name); 956178825Sdfr if (diff) 957178825Sdfr return diff; 958178825Sdfr diff = 0; 959178825Sdfr } else 960178825Sdfr diff = der_heim_octet_string_cmp(ai.keyIdentifier, &si); 961178825Sdfr if (diff) 962178825Sdfr goto out; 963178825Sdfr 964178825Sdfr out: 965178825Sdfr free_AuthorityKeyIdentifier(&ai); 966178825Sdfr free_SubjectKeyIdentifier(&si); 967178825Sdfr return diff; 968178825Sdfr} 969178825Sdfr 970178825Sdfrstatic int 971178825Sdfrcertificate_is_anchor(hx509_context context, 972178825Sdfr hx509_certs trust_anchors, 973178825Sdfr const hx509_cert cert) 974178825Sdfr{ 975178825Sdfr hx509_query q; 976178825Sdfr hx509_cert c; 977178825Sdfr int ret; 978178825Sdfr 979178825Sdfr if (trust_anchors == NULL) 980178825Sdfr return 0; 981178825Sdfr 982178825Sdfr _hx509_query_clear(&q); 983178825Sdfr 984178825Sdfr q.match = HX509_QUERY_MATCH_CERTIFICATE; 985178825Sdfr q.certificate = _hx509_get_cert(cert); 986178825Sdfr 987178825Sdfr ret = hx509_certs_find(context, trust_anchors, &q, &c); 988178825Sdfr if (ret == 0) 989178825Sdfr hx509_cert_free(c); 990178825Sdfr return ret == 0; 991178825Sdfr} 992178825Sdfr 993178825Sdfrstatic int 994178825Sdfrcertificate_is_self_signed(const Certificate *cert) 995178825Sdfr{ 996178825Sdfr return _hx509_name_cmp(&cert->tbsCertificate.subject, 997178825Sdfr &cert->tbsCertificate.issuer) == 0; 998178825Sdfr} 999178825Sdfr 1000178825Sdfr/* 1001178825Sdfr * The subjectName is "null" when it's empty set of relative DBs. 1002178825Sdfr */ 1003178825Sdfr 1004178825Sdfrstatic int 1005178825Sdfrsubject_null_p(const Certificate *c) 1006178825Sdfr{ 1007178825Sdfr return c->tbsCertificate.subject.u.rdnSequence.len == 0; 1008178825Sdfr} 1009178825Sdfr 1010178825Sdfr 1011178825Sdfrstatic int 1012178825Sdfrfind_parent(hx509_context context, 1013178825Sdfr time_t time_now, 1014178825Sdfr hx509_certs trust_anchors, 1015178825Sdfr hx509_path *path, 1016178825Sdfr hx509_certs pool, 1017178825Sdfr hx509_cert current, 1018178825Sdfr hx509_cert *parent) 1019178825Sdfr{ 1020178825Sdfr AuthorityKeyIdentifier ai; 1021178825Sdfr hx509_query q; 1022178825Sdfr int ret; 1023178825Sdfr 1024178825Sdfr *parent = NULL; 1025178825Sdfr memset(&ai, 0, sizeof(ai)); 1026178825Sdfr 1027178825Sdfr _hx509_query_clear(&q); 1028178825Sdfr 1029178825Sdfr if (!subject_null_p(current->data)) { 1030178825Sdfr q.match |= HX509_QUERY_FIND_ISSUER_CERT; 1031178825Sdfr q.subject = _hx509_get_cert(current); 1032178825Sdfr } else { 1033178825Sdfr ret = find_extension_auth_key_id(current->data, &ai); 1034178825Sdfr if (ret) { 1035178825Sdfr hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED, 1036178825Sdfr "Subjectless certificate missing AuthKeyID"); 1037178825Sdfr return HX509_CERTIFICATE_MALFORMED; 1038178825Sdfr } 1039178825Sdfr 1040178825Sdfr if (ai.keyIdentifier == NULL) { 1041178825Sdfr free_AuthorityKeyIdentifier(&ai); 1042178825Sdfr hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED, 1043178825Sdfr "Subjectless certificate missing keyIdentifier " 1044178825Sdfr "inside AuthKeyID"); 1045178825Sdfr return HX509_CERTIFICATE_MALFORMED; 1046178825Sdfr } 1047178825Sdfr 1048178825Sdfr q.subject_id = ai.keyIdentifier; 1049178825Sdfr q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID; 1050178825Sdfr } 1051178825Sdfr 1052178825Sdfr q.path = path; 1053178825Sdfr q.match |= HX509_QUERY_NO_MATCH_PATH; 1054178825Sdfr 1055178825Sdfr if (pool) { 1056178825Sdfr q.timenow = time_now; 1057178825Sdfr q.match |= HX509_QUERY_MATCH_TIME; 1058178825Sdfr 1059178825Sdfr ret = hx509_certs_find(context, pool, &q, parent); 1060178825Sdfr if (ret == 0) { 1061178825Sdfr free_AuthorityKeyIdentifier(&ai); 1062178825Sdfr return 0; 1063178825Sdfr } 1064178825Sdfr q.match &= ~HX509_QUERY_MATCH_TIME; 1065178825Sdfr } 1066178825Sdfr 1067178825Sdfr if (trust_anchors) { 1068178825Sdfr ret = hx509_certs_find(context, trust_anchors, &q, parent); 1069178825Sdfr if (ret == 0) { 1070178825Sdfr free_AuthorityKeyIdentifier(&ai); 1071178825Sdfr return ret; 1072178825Sdfr } 1073178825Sdfr } 1074178825Sdfr free_AuthorityKeyIdentifier(&ai); 1075178825Sdfr 1076178825Sdfr { 1077178825Sdfr hx509_name name; 1078178825Sdfr char *str; 1079178825Sdfr 1080178825Sdfr ret = hx509_cert_get_subject(current, &name); 1081178825Sdfr if (ret) { 1082178825Sdfr hx509_clear_error_string(context); 1083178825Sdfr return HX509_ISSUER_NOT_FOUND; 1084178825Sdfr } 1085178825Sdfr ret = hx509_name_to_string(name, &str); 1086178825Sdfr hx509_name_free(&name); 1087178825Sdfr if (ret) { 1088178825Sdfr hx509_clear_error_string(context); 1089178825Sdfr return HX509_ISSUER_NOT_FOUND; 1090178825Sdfr } 1091178825Sdfr 1092178825Sdfr hx509_set_error_string(context, 0, HX509_ISSUER_NOT_FOUND, 1093178825Sdfr "Failed to find issuer for " 1094178825Sdfr "certificate with subject: '%s'", str); 1095178825Sdfr free(str); 1096178825Sdfr } 1097178825Sdfr return HX509_ISSUER_NOT_FOUND; 1098178825Sdfr} 1099178825Sdfr 1100178825Sdfr/* 1101178825Sdfr * 1102178825Sdfr */ 1103178825Sdfr 1104178825Sdfrstatic int 1105178825Sdfris_proxy_cert(hx509_context context, 1106178825Sdfr const Certificate *cert, 1107178825Sdfr ProxyCertInfo *rinfo) 1108178825Sdfr{ 1109178825Sdfr ProxyCertInfo info; 1110178825Sdfr const Extension *e; 1111178825Sdfr size_t size; 1112178825Sdfr int ret, i = 0; 1113178825Sdfr 1114178825Sdfr if (rinfo) 1115178825Sdfr memset(rinfo, 0, sizeof(*rinfo)); 1116178825Sdfr 1117178825Sdfr e = find_extension(cert, oid_id_pkix_pe_proxyCertInfo(), &i); 1118178825Sdfr if (e == NULL) { 1119178825Sdfr hx509_clear_error_string(context); 1120178825Sdfr return HX509_EXTENSION_NOT_FOUND; 1121178825Sdfr } 1122178825Sdfr 1123178825Sdfr ret = decode_ProxyCertInfo(e->extnValue.data, 1124178825Sdfr e->extnValue.length, 1125178825Sdfr &info, 1126178825Sdfr &size); 1127178825Sdfr if (ret) { 1128178825Sdfr hx509_clear_error_string(context); 1129178825Sdfr return ret; 1130178825Sdfr } 1131178825Sdfr if (size != e->extnValue.length) { 1132178825Sdfr free_ProxyCertInfo(&info); 1133178825Sdfr hx509_clear_error_string(context); 1134178825Sdfr return HX509_EXTRA_DATA_AFTER_STRUCTURE; 1135178825Sdfr } 1136178825Sdfr if (rinfo == NULL) 1137178825Sdfr free_ProxyCertInfo(&info); 1138178825Sdfr else 1139178825Sdfr *rinfo = info; 1140178825Sdfr 1141178825Sdfr return 0; 1142178825Sdfr} 1143178825Sdfr 1144178825Sdfr/* 1145178825Sdfr * Path operations are like MEMORY based keyset, but with exposed 1146178825Sdfr * internal so we can do easy searches. 1147178825Sdfr */ 1148178825Sdfr 1149178825Sdfrint 1150178825Sdfr_hx509_path_append(hx509_context context, hx509_path *path, hx509_cert cert) 1151178825Sdfr{ 1152178825Sdfr hx509_cert *val; 1153178825Sdfr val = realloc(path->val, (path->len + 1) * sizeof(path->val[0])); 1154178825Sdfr if (val == NULL) { 1155178825Sdfr hx509_set_error_string(context, 0, ENOMEM, "out of memory"); 1156178825Sdfr return ENOMEM; 1157178825Sdfr } 1158178825Sdfr 1159178825Sdfr path->val = val; 1160178825Sdfr path->val[path->len] = hx509_cert_ref(cert); 1161178825Sdfr path->len++; 1162178825Sdfr 1163178825Sdfr return 0; 1164178825Sdfr} 1165178825Sdfr 1166178825Sdfrvoid 1167178825Sdfr_hx509_path_free(hx509_path *path) 1168178825Sdfr{ 1169178825Sdfr unsigned i; 1170178825Sdfr 1171178825Sdfr for (i = 0; i < path->len; i++) 1172178825Sdfr hx509_cert_free(path->val[i]); 1173178825Sdfr free(path->val); 1174178825Sdfr path->val = NULL; 1175178825Sdfr path->len = 0; 1176178825Sdfr} 1177178825Sdfr 1178178825Sdfr/* 1179178825Sdfr * Find path by looking up issuer for the top certificate and continue 1180178825Sdfr * until an anchor certificate is found or max limit is found. A 1181178825Sdfr * certificate never included twice in the path. 1182178825Sdfr * 1183178825Sdfr * If the trust anchors are not given, calculate optimistic path, just 1184178825Sdfr * follow the chain upward until we no longer find a parent or we hit 1185178825Sdfr * the max path limit. In this case, a failure will always be returned 1186178825Sdfr * depending on what error condition is hit first. 1187178825Sdfr * 1188178825Sdfr * The path includes a path from the top certificate to the anchor 1189178825Sdfr * certificate. 1190178825Sdfr * 1191178825Sdfr * The caller needs to free `path� both on successful built path and 1192178825Sdfr * failure. 1193178825Sdfr */ 1194178825Sdfr 1195178825Sdfrint 1196178825Sdfr_hx509_calculate_path(hx509_context context, 1197178825Sdfr int flags, 1198178825Sdfr time_t time_now, 1199178825Sdfr hx509_certs anchors, 1200178825Sdfr unsigned int max_depth, 1201178825Sdfr hx509_cert cert, 1202178825Sdfr hx509_certs pool, 1203178825Sdfr hx509_path *path) 1204178825Sdfr{ 1205178825Sdfr hx509_cert parent, current; 1206178825Sdfr int ret; 1207178825Sdfr 1208178825Sdfr if (max_depth == 0) 1209178825Sdfr max_depth = HX509_VERIFY_MAX_DEPTH; 1210178825Sdfr 1211178825Sdfr ret = _hx509_path_append(context, path, cert); 1212178825Sdfr if (ret) 1213178825Sdfr return ret; 1214178825Sdfr 1215178825Sdfr current = hx509_cert_ref(cert); 1216178825Sdfr 1217178825Sdfr while (!certificate_is_anchor(context, anchors, current)) { 1218178825Sdfr 1219178825Sdfr ret = find_parent(context, time_now, anchors, path, 1220178825Sdfr pool, current, &parent); 1221178825Sdfr hx509_cert_free(current); 1222178825Sdfr if (ret) 1223178825Sdfr return ret; 1224178825Sdfr 1225178825Sdfr ret = _hx509_path_append(context, path, parent); 1226178825Sdfr if (ret) 1227178825Sdfr return ret; 1228178825Sdfr current = parent; 1229178825Sdfr 1230178825Sdfr if (path->len > max_depth) { 1231178825Sdfr hx509_cert_free(current); 1232178825Sdfr hx509_set_error_string(context, 0, HX509_PATH_TOO_LONG, 1233178825Sdfr "Path too long while bulding " 1234178825Sdfr "certificate chain"); 1235178825Sdfr return HX509_PATH_TOO_LONG; 1236178825Sdfr } 1237178825Sdfr } 1238178825Sdfr 1239178825Sdfr if ((flags & HX509_CALCULATE_PATH_NO_ANCHOR) && 1240178825Sdfr path->len > 0 && 1241178825Sdfr certificate_is_anchor(context, anchors, path->val[path->len - 1])) 1242178825Sdfr { 1243178825Sdfr hx509_cert_free(path->val[path->len - 1]); 1244178825Sdfr path->len--; 1245178825Sdfr } 1246178825Sdfr 1247178825Sdfr hx509_cert_free(current); 1248178825Sdfr return 0; 1249178825Sdfr} 1250178825Sdfr 1251178825Sdfrint 1252178825Sdfr_hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier *p, 1253178825Sdfr const AlgorithmIdentifier *q) 1254178825Sdfr{ 1255178825Sdfr int diff; 1256178825Sdfr diff = der_heim_oid_cmp(&p->algorithm, &q->algorithm); 1257178825Sdfr if (diff) 1258178825Sdfr return diff; 1259178825Sdfr if (p->parameters) { 1260178825Sdfr if (q->parameters) 1261178825Sdfr return heim_any_cmp(p->parameters, 1262178825Sdfr q->parameters); 1263178825Sdfr else 1264178825Sdfr return 1; 1265178825Sdfr } else { 1266178825Sdfr if (q->parameters) 1267178825Sdfr return -1; 1268178825Sdfr else 1269178825Sdfr return 0; 1270178825Sdfr } 1271178825Sdfr} 1272178825Sdfr 1273178825Sdfrint 1274178825Sdfr_hx509_Certificate_cmp(const Certificate *p, const Certificate *q) 1275178825Sdfr{ 1276178825Sdfr int diff; 1277178825Sdfr diff = der_heim_bit_string_cmp(&p->signatureValue, &q->signatureValue); 1278178825Sdfr if (diff) 1279178825Sdfr return diff; 1280178825Sdfr diff = _hx509_AlgorithmIdentifier_cmp(&p->signatureAlgorithm, 1281178825Sdfr &q->signatureAlgorithm); 1282178825Sdfr if (diff) 1283178825Sdfr return diff; 1284178825Sdfr diff = der_heim_octet_string_cmp(&p->tbsCertificate._save, 1285178825Sdfr &q->tbsCertificate._save); 1286178825Sdfr return diff; 1287178825Sdfr} 1288178825Sdfr 1289178825Sdfr/** 1290178825Sdfr * Compare to hx509 certificate object, useful for sorting. 1291178825Sdfr * 1292178825Sdfr * @param p a hx509 certificate object. 1293178825Sdfr * @param q a hx509 certificate object. 1294178825Sdfr * 1295178825Sdfr * @return 0 the objects are the same, returns > 0 is p is "larger" 1296178825Sdfr * then q, < 0 if p is "smaller" then q. 1297178825Sdfr * 1298178825Sdfr * @ingroup hx509_cert 1299178825Sdfr */ 1300178825Sdfr 1301178825Sdfrint 1302178825Sdfrhx509_cert_cmp(hx509_cert p, hx509_cert q) 1303178825Sdfr{ 1304178825Sdfr return _hx509_Certificate_cmp(p->data, q->data); 1305178825Sdfr} 1306178825Sdfr 1307178825Sdfr/** 1308178825Sdfr * Return the name of the issuer of the hx509 certificate. 1309178825Sdfr * 1310178825Sdfr * @param p a hx509 certificate object. 1311178825Sdfr * @param name a pointer to a hx509 name, should be freed by 1312178825Sdfr * hx509_name_free(). 1313178825Sdfr * 1314178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 1315178825Sdfr * 1316178825Sdfr * @ingroup hx509_cert 1317178825Sdfr */ 1318178825Sdfr 1319178825Sdfrint 1320178825Sdfrhx509_cert_get_issuer(hx509_cert p, hx509_name *name) 1321178825Sdfr{ 1322178825Sdfr return _hx509_name_from_Name(&p->data->tbsCertificate.issuer, name); 1323178825Sdfr} 1324178825Sdfr 1325178825Sdfr/** 1326178825Sdfr * Return the name of the subject of the hx509 certificate. 1327178825Sdfr * 1328178825Sdfr * @param p a hx509 certificate object. 1329178825Sdfr * @param name a pointer to a hx509 name, should be freed by 1330178825Sdfr * hx509_name_free(). See also hx509_cert_get_base_subject(). 1331178825Sdfr * 1332178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 1333178825Sdfr * 1334178825Sdfr * @ingroup hx509_cert 1335178825Sdfr */ 1336178825Sdfr 1337178825Sdfrint 1338178825Sdfrhx509_cert_get_subject(hx509_cert p, hx509_name *name) 1339178825Sdfr{ 1340178825Sdfr return _hx509_name_from_Name(&p->data->tbsCertificate.subject, name); 1341178825Sdfr} 1342178825Sdfr 1343178825Sdfr/** 1344178825Sdfr * Return the name of the base subject of the hx509 certificate. If 1345178825Sdfr * the certiicate is a verified proxy certificate, the this function 1346178825Sdfr * return the base certificate (root of the proxy chain). If the proxy 1347178825Sdfr * certificate is not verified with the base certificate 1348178825Sdfr * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned. 1349178825Sdfr * 1350178825Sdfr * @param context a hx509 context. 1351178825Sdfr * @param c a hx509 certificate object. 1352178825Sdfr * @param name a pointer to a hx509 name, should be freed by 1353178825Sdfr * hx509_name_free(). See also hx509_cert_get_subject(). 1354178825Sdfr * 1355178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 1356178825Sdfr * 1357178825Sdfr * @ingroup hx509_cert 1358178825Sdfr */ 1359178825Sdfr 1360178825Sdfrint 1361178825Sdfrhx509_cert_get_base_subject(hx509_context context, hx509_cert c, 1362178825Sdfr hx509_name *name) 1363178825Sdfr{ 1364178825Sdfr if (c->basename) 1365178825Sdfr return hx509_name_copy(context, c->basename, name); 1366178825Sdfr if (is_proxy_cert(context, c->data, NULL) == 0) { 1367178825Sdfr int ret = HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED; 1368178825Sdfr hx509_set_error_string(context, 0, ret, 1369178825Sdfr "Proxy certificate have not been " 1370178825Sdfr "canonicalize yet, no base name"); 1371178825Sdfr return ret; 1372178825Sdfr } 1373178825Sdfr return _hx509_name_from_Name(&c->data->tbsCertificate.subject, name); 1374178825Sdfr} 1375178825Sdfr 1376178825Sdfr/** 1377178825Sdfr * Get serial number of the certificate. 1378178825Sdfr * 1379178825Sdfr * @param p a hx509 certificate object. 1380178825Sdfr * @param i serial number, should be freed ith der_free_heim_integer(). 1381178825Sdfr * 1382178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 1383178825Sdfr * 1384178825Sdfr * @ingroup hx509_cert 1385178825Sdfr */ 1386178825Sdfr 1387178825Sdfrint 1388178825Sdfrhx509_cert_get_serialnumber(hx509_cert p, heim_integer *i) 1389178825Sdfr{ 1390178825Sdfr return der_copy_heim_integer(&p->data->tbsCertificate.serialNumber, i); 1391178825Sdfr} 1392178825Sdfr 1393178825Sdfr/** 1394178825Sdfr * Get notBefore time of the certificate. 1395178825Sdfr * 1396178825Sdfr * @param p a hx509 certificate object. 1397178825Sdfr * 1398178825Sdfr * @return return not before time 1399178825Sdfr * 1400178825Sdfr * @ingroup hx509_cert 1401178825Sdfr */ 1402178825Sdfr 1403178825Sdfrtime_t 1404178825Sdfrhx509_cert_get_notBefore(hx509_cert p) 1405178825Sdfr{ 1406178825Sdfr return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notBefore); 1407178825Sdfr} 1408178825Sdfr 1409178825Sdfr/** 1410178825Sdfr * Get notAfter time of the certificate. 1411178825Sdfr * 1412178825Sdfr * @param p a hx509 certificate object. 1413178825Sdfr * 1414178825Sdfr * @return return not after time. 1415178825Sdfr * 1416178825Sdfr * @ingroup hx509_cert 1417178825Sdfr */ 1418178825Sdfr 1419178825Sdfrtime_t 1420178825Sdfrhx509_cert_get_notAfter(hx509_cert p) 1421178825Sdfr{ 1422178825Sdfr return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter); 1423178825Sdfr} 1424178825Sdfr 1425178825Sdfr/** 1426178825Sdfr * Get the SubjectPublicKeyInfo structure from the hx509 certificate. 1427178825Sdfr * 1428178825Sdfr * @param context a hx509 context. 1429178825Sdfr * @param p a hx509 certificate object. 1430178825Sdfr * @param spki SubjectPublicKeyInfo, should be freed with 1431178825Sdfr * free_SubjectPublicKeyInfo(). 1432178825Sdfr * 1433178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 1434178825Sdfr * 1435178825Sdfr * @ingroup hx509_cert 1436178825Sdfr */ 1437178825Sdfr 1438178825Sdfrint 1439178825Sdfrhx509_cert_get_SPKI(hx509_context context, hx509_cert p, SubjectPublicKeyInfo *spki) 1440178825Sdfr{ 1441178825Sdfr int ret; 1442178825Sdfr 1443178825Sdfr ret = copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo, spki); 1444178825Sdfr if (ret) 1445178825Sdfr hx509_set_error_string(context, 0, ret, "Failed to copy SPKI"); 1446178825Sdfr return ret; 1447178825Sdfr} 1448178825Sdfr 1449178825Sdfr/** 1450178825Sdfr * Get the AlgorithmIdentifier from the hx509 certificate. 1451178825Sdfr * 1452178825Sdfr * @param context a hx509 context. 1453178825Sdfr * @param p a hx509 certificate object. 1454178825Sdfr * @param alg AlgorithmIdentifier, should be freed with 1455178825Sdfr * free_AlgorithmIdentifier(). 1456178825Sdfr * 1457178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 1458178825Sdfr * 1459178825Sdfr * @ingroup hx509_cert 1460178825Sdfr */ 1461178825Sdfr 1462178825Sdfrint 1463178825Sdfrhx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context, 1464178825Sdfr hx509_cert p, 1465178825Sdfr AlgorithmIdentifier *alg) 1466178825Sdfr{ 1467178825Sdfr int ret; 1468178825Sdfr 1469178825Sdfr ret = copy_AlgorithmIdentifier(&p->data->tbsCertificate.subjectPublicKeyInfo.algorithm, alg); 1470178825Sdfr if (ret) 1471178825Sdfr hx509_set_error_string(context, 0, ret, 1472178825Sdfr "Failed to copy SPKI AlgorithmIdentifier"); 1473178825Sdfr return ret; 1474178825Sdfr} 1475178825Sdfr 1476178825Sdfr 1477178825Sdfrhx509_private_key 1478178825Sdfr_hx509_cert_private_key(hx509_cert p) 1479178825Sdfr{ 1480178825Sdfr return p->private_key; 1481178825Sdfr} 1482178825Sdfr 1483178825Sdfrint 1484178825Sdfrhx509_cert_have_private_key(hx509_cert p) 1485178825Sdfr{ 1486178825Sdfr return p->private_key ? 1 : 0; 1487178825Sdfr} 1488178825Sdfr 1489178825Sdfr 1490178825Sdfrint 1491178825Sdfr_hx509_cert_private_key_exportable(hx509_cert p) 1492178825Sdfr{ 1493178825Sdfr if (p->private_key == NULL) 1494178825Sdfr return 0; 1495178825Sdfr return _hx509_private_key_exportable(p->private_key); 1496178825Sdfr} 1497178825Sdfr 1498178825Sdfrint 1499178825Sdfr_hx509_cert_private_decrypt(hx509_context context, 1500178825Sdfr const heim_octet_string *ciphertext, 1501178825Sdfr const heim_oid *encryption_oid, 1502178825Sdfr hx509_cert p, 1503178825Sdfr heim_octet_string *cleartext) 1504178825Sdfr{ 1505178825Sdfr cleartext->data = NULL; 1506178825Sdfr cleartext->length = 0; 1507178825Sdfr 1508178825Sdfr if (p->private_key == NULL) { 1509178825Sdfr hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING, 1510178825Sdfr "Private key missing"); 1511178825Sdfr return HX509_PRIVATE_KEY_MISSING; 1512178825Sdfr } 1513178825Sdfr 1514178825Sdfr return _hx509_private_key_private_decrypt(context, 1515178825Sdfr ciphertext, 1516178825Sdfr encryption_oid, 1517178825Sdfr p->private_key, 1518178825Sdfr cleartext); 1519178825Sdfr} 1520178825Sdfr 1521178825Sdfrint 1522178825Sdfr_hx509_cert_public_encrypt(hx509_context context, 1523178825Sdfr const heim_octet_string *cleartext, 1524178825Sdfr const hx509_cert p, 1525178825Sdfr heim_oid *encryption_oid, 1526178825Sdfr heim_octet_string *ciphertext) 1527178825Sdfr{ 1528178825Sdfr return _hx509_public_encrypt(context, 1529178825Sdfr cleartext, p->data, 1530178825Sdfr encryption_oid, ciphertext); 1531178825Sdfr} 1532178825Sdfr 1533178825Sdfr/* 1534178825Sdfr * 1535178825Sdfr */ 1536178825Sdfr 1537178825Sdfrtime_t 1538178825Sdfr_hx509_Time2time_t(const Time *t) 1539178825Sdfr{ 1540178825Sdfr switch(t->element) { 1541178825Sdfr case choice_Time_utcTime: 1542178825Sdfr return t->u.utcTime; 1543178825Sdfr case choice_Time_generalTime: 1544178825Sdfr return t->u.generalTime; 1545178825Sdfr } 1546178825Sdfr return 0; 1547178825Sdfr} 1548178825Sdfr 1549178825Sdfr/* 1550178825Sdfr * 1551178825Sdfr */ 1552178825Sdfr 1553178825Sdfrstatic int 1554178825Sdfrinit_name_constraints(hx509_name_constraints *nc) 1555178825Sdfr{ 1556178825Sdfr memset(nc, 0, sizeof(*nc)); 1557178825Sdfr return 0; 1558178825Sdfr} 1559178825Sdfr 1560178825Sdfrstatic int 1561178825Sdfradd_name_constraints(hx509_context context, const Certificate *c, int not_ca, 1562178825Sdfr hx509_name_constraints *nc) 1563178825Sdfr{ 1564178825Sdfr NameConstraints tnc; 1565178825Sdfr int ret; 1566178825Sdfr 1567178825Sdfr ret = find_extension_name_constraints(c, &tnc); 1568178825Sdfr if (ret == HX509_EXTENSION_NOT_FOUND) 1569178825Sdfr return 0; 1570178825Sdfr else if (ret) { 1571178825Sdfr hx509_set_error_string(context, 0, ret, "Failed getting NameConstraints"); 1572178825Sdfr return ret; 1573178825Sdfr } else if (not_ca) { 1574178825Sdfr ret = HX509_VERIFY_CONSTRAINTS; 1575178825Sdfr hx509_set_error_string(context, 0, ret, "Not a CA and " 1576178825Sdfr "have NameConstraints"); 1577178825Sdfr } else { 1578178825Sdfr NameConstraints *val; 1579178825Sdfr val = realloc(nc->val, sizeof(nc->val[0]) * (nc->len + 1)); 1580178825Sdfr if (val == NULL) { 1581178825Sdfr hx509_clear_error_string(context); 1582178825Sdfr ret = ENOMEM; 1583178825Sdfr goto out; 1584178825Sdfr } 1585178825Sdfr nc->val = val; 1586178825Sdfr ret = copy_NameConstraints(&tnc, &nc->val[nc->len]); 1587178825Sdfr if (ret) { 1588178825Sdfr hx509_clear_error_string(context); 1589178825Sdfr goto out; 1590178825Sdfr } 1591178825Sdfr nc->len += 1; 1592178825Sdfr } 1593178825Sdfrout: 1594178825Sdfr free_NameConstraints(&tnc); 1595178825Sdfr return ret; 1596178825Sdfr} 1597178825Sdfr 1598178825Sdfrstatic int 1599178825Sdfrmatch_RDN(const RelativeDistinguishedName *c, 1600178825Sdfr const RelativeDistinguishedName *n) 1601178825Sdfr{ 1602178825Sdfr int i; 1603178825Sdfr 1604178825Sdfr if (c->len != n->len) 1605178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1606178825Sdfr 1607178825Sdfr for (i = 0; i < n->len; i++) { 1608178825Sdfr if (der_heim_oid_cmp(&c->val[i].type, &n->val[i].type) != 0) 1609178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1610178825Sdfr if (_hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value) != 0) 1611178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1612178825Sdfr } 1613178825Sdfr return 0; 1614178825Sdfr} 1615178825Sdfr 1616178825Sdfrstatic int 1617178825Sdfrmatch_X501Name(const Name *c, const Name *n) 1618178825Sdfr{ 1619178825Sdfr int i, ret; 1620178825Sdfr 1621178825Sdfr if (c->element != choice_Name_rdnSequence 1622178825Sdfr || n->element != choice_Name_rdnSequence) 1623178825Sdfr return 0; 1624178825Sdfr if (c->u.rdnSequence.len > n->u.rdnSequence.len) 1625178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1626178825Sdfr for (i = 0; i < c->u.rdnSequence.len; i++) { 1627178825Sdfr ret = match_RDN(&c->u.rdnSequence.val[i], &n->u.rdnSequence.val[i]); 1628178825Sdfr if (ret) 1629178825Sdfr return ret; 1630178825Sdfr } 1631178825Sdfr return 0; 1632178825Sdfr} 1633178825Sdfr 1634178825Sdfr 1635178825Sdfrstatic int 1636178825Sdfrmatch_general_name(const GeneralName *c, const GeneralName *n, int *match) 1637178825Sdfr{ 1638178825Sdfr /* 1639178825Sdfr * Name constraints only apply to the same name type, see RFC3280, 1640178825Sdfr * 4.2.1.11. 1641178825Sdfr */ 1642178825Sdfr assert(c->element == n->element); 1643178825Sdfr 1644178825Sdfr switch(c->element) { 1645178825Sdfr case choice_GeneralName_otherName: 1646178825Sdfr if (der_heim_oid_cmp(&c->u.otherName.type_id, 1647178825Sdfr &n->u.otherName.type_id) != 0) 1648178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1649178825Sdfr if (heim_any_cmp(&c->u.otherName.value, 1650178825Sdfr &n->u.otherName.value) != 0) 1651178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1652178825Sdfr *match = 1; 1653178825Sdfr return 0; 1654178825Sdfr case choice_GeneralName_rfc822Name: { 1655178825Sdfr const char *s; 1656178825Sdfr size_t len1, len2; 1657178825Sdfr s = strchr(c->u.rfc822Name, '@'); 1658178825Sdfr if (s) { 1659178825Sdfr if (strcasecmp(c->u.rfc822Name, n->u.rfc822Name) != 0) 1660178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1661178825Sdfr } else { 1662178825Sdfr s = strchr(n->u.rfc822Name, '@'); 1663178825Sdfr if (s == NULL) 1664178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1665178825Sdfr len1 = strlen(c->u.rfc822Name); 1666178825Sdfr len2 = strlen(s + 1); 1667178825Sdfr if (len1 > len2) 1668178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1669178825Sdfr if (strcasecmp(s + 1 + len2 - len1, c->u.rfc822Name) != 0) 1670178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1671178825Sdfr if (len1 < len2 && s[len2 - len1 + 1] != '.') 1672178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1673178825Sdfr } 1674178825Sdfr *match = 1; 1675178825Sdfr return 0; 1676178825Sdfr } 1677178825Sdfr case choice_GeneralName_dNSName: { 1678178825Sdfr size_t lenc, lenn; 1679178825Sdfr 1680178825Sdfr lenc = strlen(c->u.dNSName); 1681178825Sdfr lenn = strlen(n->u.dNSName); 1682178825Sdfr if (lenc > lenn) 1683178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1684178825Sdfr if (strcasecmp(&n->u.dNSName[lenn - lenc], c->u.dNSName) != 0) 1685178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1686178825Sdfr if (lenc != lenn && n->u.dNSName[lenn - lenc - 1] != '.') 1687178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1688178825Sdfr *match = 1; 1689178825Sdfr return 0; 1690178825Sdfr } 1691178825Sdfr case choice_GeneralName_directoryName: { 1692178825Sdfr Name c_name, n_name; 1693178825Sdfr int ret; 1694178825Sdfr 1695178825Sdfr c_name._save.data = NULL; 1696178825Sdfr c_name._save.length = 0; 1697178825Sdfr c_name.element = c->u.directoryName.element; 1698178825Sdfr c_name.u.rdnSequence = c->u.directoryName.u.rdnSequence; 1699178825Sdfr 1700178825Sdfr n_name._save.data = NULL; 1701178825Sdfr n_name._save.length = 0; 1702178825Sdfr n_name.element = n->u.directoryName.element; 1703178825Sdfr n_name.u.rdnSequence = n->u.directoryName.u.rdnSequence; 1704178825Sdfr 1705178825Sdfr ret = match_X501Name(&c_name, &n_name); 1706178825Sdfr if (ret == 0) 1707178825Sdfr *match = 1; 1708178825Sdfr return ret; 1709178825Sdfr } 1710178825Sdfr case choice_GeneralName_uniformResourceIdentifier: 1711178825Sdfr case choice_GeneralName_iPAddress: 1712178825Sdfr case choice_GeneralName_registeredID: 1713178825Sdfr default: 1714178825Sdfr return HX509_NAME_CONSTRAINT_ERROR; 1715178825Sdfr } 1716178825Sdfr} 1717178825Sdfr 1718178825Sdfrstatic int 1719178825Sdfrmatch_alt_name(const GeneralName *n, const Certificate *c, 1720178825Sdfr int *same, int *match) 1721178825Sdfr{ 1722178825Sdfr GeneralNames sa; 1723178825Sdfr int ret, i, j; 1724178825Sdfr 1725178825Sdfr i = 0; 1726178825Sdfr do { 1727178825Sdfr ret = find_extension_subject_alt_name(c, &i, &sa); 1728178825Sdfr if (ret == HX509_EXTENSION_NOT_FOUND) { 1729178825Sdfr ret = 0; 1730178825Sdfr break; 1731178825Sdfr } else if (ret != 0) 1732178825Sdfr break; 1733178825Sdfr 1734178825Sdfr for (j = 0; j < sa.len; j++) { 1735178825Sdfr if (n->element == sa.val[j].element) { 1736178825Sdfr *same = 1; 1737178825Sdfr ret = match_general_name(n, &sa.val[j], match); 1738178825Sdfr } 1739178825Sdfr } 1740178825Sdfr free_GeneralNames(&sa); 1741178825Sdfr } while (1); 1742178825Sdfr return ret; 1743178825Sdfr} 1744178825Sdfr 1745178825Sdfr 1746178825Sdfrstatic int 1747178825Sdfrmatch_tree(const GeneralSubtrees *t, const Certificate *c, int *match) 1748178825Sdfr{ 1749178825Sdfr int name, alt_name, same; 1750178825Sdfr unsigned int i; 1751178825Sdfr int ret = 0; 1752178825Sdfr 1753178825Sdfr name = alt_name = same = *match = 0; 1754178825Sdfr for (i = 0; i < t->len; i++) { 1755178825Sdfr if (t->val[i].minimum && t->val[i].maximum) 1756178825Sdfr return HX509_RANGE; 1757178825Sdfr 1758178825Sdfr /* 1759178825Sdfr * If the constraint apply to directoryNames, test is with 1760178825Sdfr * subjectName of the certificate if the certificate have a 1761178825Sdfr * non-null (empty) subjectName. 1762178825Sdfr */ 1763178825Sdfr 1764178825Sdfr if (t->val[i].base.element == choice_GeneralName_directoryName 1765178825Sdfr && !subject_null_p(c)) 1766178825Sdfr { 1767178825Sdfr GeneralName certname; 1768178825Sdfr 1769178825Sdfr memset(&certname, 0, sizeof(certname)); 1770178825Sdfr certname.element = choice_GeneralName_directoryName; 1771178825Sdfr certname.u.directoryName.element = 1772178825Sdfr c->tbsCertificate.subject.element; 1773178825Sdfr certname.u.directoryName.u.rdnSequence = 1774178825Sdfr c->tbsCertificate.subject.u.rdnSequence; 1775178825Sdfr 1776178825Sdfr ret = match_general_name(&t->val[i].base, &certname, &name); 1777178825Sdfr } 1778178825Sdfr 1779178825Sdfr /* Handle subjectAltNames, this is icky since they 1780178825Sdfr * restrictions only apply if the subjectAltName is of the 1781178825Sdfr * same type. So if there have been a match of type, require 1782178825Sdfr * altname to be set. 1783178825Sdfr */ 1784178825Sdfr ret = match_alt_name(&t->val[i].base, c, &same, &alt_name); 1785178825Sdfr } 1786178825Sdfr if (name && (!same || alt_name)) 1787178825Sdfr *match = 1; 1788178825Sdfr return ret; 1789178825Sdfr} 1790178825Sdfr 1791178825Sdfrstatic int 1792178825Sdfrcheck_name_constraints(hx509_context context, 1793178825Sdfr const hx509_name_constraints *nc, 1794178825Sdfr const Certificate *c) 1795178825Sdfr{ 1796178825Sdfr int match, ret; 1797178825Sdfr int i; 1798178825Sdfr 1799178825Sdfr for (i = 0 ; i < nc->len; i++) { 1800178825Sdfr GeneralSubtrees gs; 1801178825Sdfr 1802178825Sdfr if (nc->val[i].permittedSubtrees) { 1803178825Sdfr GeneralSubtrees_SET(&gs, nc->val[i].permittedSubtrees); 1804178825Sdfr ret = match_tree(&gs, c, &match); 1805178825Sdfr if (ret) { 1806178825Sdfr hx509_clear_error_string(context); 1807178825Sdfr return ret; 1808178825Sdfr } 1809178825Sdfr /* allow null subjectNames, they wont matches anything */ 1810178825Sdfr if (match == 0 && !subject_null_p(c)) { 1811178825Sdfr hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS, 1812178825Sdfr "Error verify constraints, " 1813178825Sdfr "certificate didn't match any " 1814178825Sdfr "permitted subtree"); 1815178825Sdfr return HX509_VERIFY_CONSTRAINTS; 1816178825Sdfr } 1817178825Sdfr } 1818178825Sdfr if (nc->val[i].excludedSubtrees) { 1819178825Sdfr GeneralSubtrees_SET(&gs, nc->val[i].excludedSubtrees); 1820178825Sdfr ret = match_tree(&gs, c, &match); 1821178825Sdfr if (ret) { 1822178825Sdfr hx509_clear_error_string(context); 1823178825Sdfr return ret; 1824178825Sdfr } 1825178825Sdfr if (match) { 1826178825Sdfr hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS, 1827178825Sdfr "Error verify constraints, " 1828178825Sdfr "certificate included in excluded " 1829178825Sdfr "subtree"); 1830178825Sdfr return HX509_VERIFY_CONSTRAINTS; 1831178825Sdfr } 1832178825Sdfr } 1833178825Sdfr } 1834178825Sdfr return 0; 1835178825Sdfr} 1836178825Sdfr 1837178825Sdfrstatic void 1838178825Sdfrfree_name_constraints(hx509_name_constraints *nc) 1839178825Sdfr{ 1840178825Sdfr int i; 1841178825Sdfr 1842178825Sdfr for (i = 0 ; i < nc->len; i++) 1843178825Sdfr free_NameConstraints(&nc->val[i]); 1844178825Sdfr free(nc->val); 1845178825Sdfr} 1846178825Sdfr 1847178825Sdfr/** 1848178825Sdfr * Build and verify the path for the certificate to the trust anchor 1849178825Sdfr * specified in the verify context. The path is constructed from the 1850178825Sdfr * certificate, the pool and the trust anchors. 1851178825Sdfr * 1852178825Sdfr * @param context A hx509 context. 1853178825Sdfr * @param ctx A hx509 verification context. 1854178825Sdfr * @param cert the certificate to build the path from. 1855178825Sdfr * @param pool A keyset of certificates to build the chain from. 1856178825Sdfr * 1857178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 1858178825Sdfr * 1859178825Sdfr * @ingroup hx509_verify 1860178825Sdfr */ 1861178825Sdfr 1862178825Sdfrint 1863178825Sdfrhx509_verify_path(hx509_context context, 1864178825Sdfr hx509_verify_ctx ctx, 1865178825Sdfr hx509_cert cert, 1866178825Sdfr hx509_certs pool) 1867178825Sdfr{ 1868178825Sdfr hx509_name_constraints nc; 1869178825Sdfr hx509_path path; 1870178825Sdfr#if 0 1871178825Sdfr const AlgorithmIdentifier *alg_id; 1872178825Sdfr#endif 1873178825Sdfr int ret, i, proxy_cert_depth, selfsigned_depth; 1874178825Sdfr enum certtype type; 1875178825Sdfr Name proxy_issuer; 1876178825Sdfr hx509_certs anchors = NULL; 1877178825Sdfr 1878178825Sdfr memset(&proxy_issuer, 0, sizeof(proxy_issuer)); 1879178825Sdfr 1880178825Sdfr ret = init_name_constraints(&nc); 1881178825Sdfr if (ret) 1882178825Sdfr return ret; 1883178825Sdfr 1884178825Sdfr path.val = NULL; 1885178825Sdfr path.len = 0; 1886178825Sdfr 1887178825Sdfr if ((ctx->flags & HX509_VERIFY_CTX_F_TIME_SET) == 0) 1888178825Sdfr ctx->time_now = time(NULL); 1889178825Sdfr 1890178825Sdfr /* 1891178825Sdfr * 1892178825Sdfr */ 1893178825Sdfr if (ctx->trust_anchors) 1894178825Sdfr anchors = _hx509_certs_ref(ctx->trust_anchors); 1895178825Sdfr else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx)) 1896178825Sdfr anchors = _hx509_certs_ref(context->default_trust_anchors); 1897178825Sdfr else { 1898178825Sdfr ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors); 1899178825Sdfr if (ret) 1900178825Sdfr goto out; 1901178825Sdfr } 1902178825Sdfr 1903178825Sdfr /* 1904178825Sdfr * Calculate the path from the certificate user presented to the 1905178825Sdfr * to an anchor. 1906178825Sdfr */ 1907178825Sdfr ret = _hx509_calculate_path(context, 0, ctx->time_now, 1908178825Sdfr anchors, ctx->max_depth, 1909178825Sdfr cert, pool, &path); 1910178825Sdfr if (ret) 1911178825Sdfr goto out; 1912178825Sdfr 1913178825Sdfr#if 0 1914178825Sdfr alg_id = path.val[path->len - 1]->data->tbsCertificate.signature; 1915178825Sdfr#endif 1916178825Sdfr 1917178825Sdfr /* 1918178825Sdfr * Check CA and proxy certificate chain from the top of the 1919178825Sdfr * certificate chain. Also check certificate is valid with respect 1920178825Sdfr * to the current time. 1921178825Sdfr * 1922178825Sdfr */ 1923178825Sdfr 1924178825Sdfr proxy_cert_depth = 0; 1925178825Sdfr selfsigned_depth = 0; 1926178825Sdfr 1927178825Sdfr if (ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE) 1928178825Sdfr type = PROXY_CERT; 1929178825Sdfr else 1930178825Sdfr type = EE_CERT; 1931178825Sdfr 1932178825Sdfr for (i = 0; i < path.len; i++) { 1933178825Sdfr Certificate *c; 1934178825Sdfr time_t t; 1935178825Sdfr 1936178825Sdfr c = _hx509_get_cert(path.val[i]); 1937178825Sdfr 1938178825Sdfr /* 1939178825Sdfr * Lets do some basic check on issuer like 1940178825Sdfr * keyUsage.keyCertSign and basicConstraints.cA bit depending 1941178825Sdfr * on what type of certificate this is. 1942178825Sdfr */ 1943178825Sdfr 1944178825Sdfr switch (type) { 1945178825Sdfr case CA_CERT: 1946178825Sdfr /* XXX make constants for keyusage */ 1947178825Sdfr ret = check_key_usage(context, c, 1 << 5, 1948178825Sdfr REQUIRE_RFC3280(ctx) ? TRUE : FALSE); 1949178825Sdfr if (ret) { 1950178825Sdfr hx509_set_error_string(context, HX509_ERROR_APPEND, ret, 1951178825Sdfr "Key usage missing from CA certificate"); 1952178825Sdfr goto out; 1953178825Sdfr } 1954178825Sdfr 1955178825Sdfr if (i + 1 != path.len && certificate_is_self_signed(c)) 1956178825Sdfr selfsigned_depth++; 1957178825Sdfr 1958178825Sdfr break; 1959178825Sdfr case PROXY_CERT: { 1960178825Sdfr ProxyCertInfo info; 1961178825Sdfr 1962178825Sdfr if (is_proxy_cert(context, c, &info) == 0) { 1963178825Sdfr int j; 1964178825Sdfr 1965178825Sdfr if (info.pCPathLenConstraint != NULL && 1966178825Sdfr *info.pCPathLenConstraint < i) 1967178825Sdfr { 1968178825Sdfr free_ProxyCertInfo(&info); 1969178825Sdfr ret = HX509_PATH_TOO_LONG; 1970178825Sdfr hx509_set_error_string(context, 0, ret, 1971178825Sdfr "Proxy certificate chain " 1972178825Sdfr "longer then allowed"); 1973178825Sdfr goto out; 1974178825Sdfr } 1975178825Sdfr /* XXX MUST check info.proxyPolicy */ 1976178825Sdfr free_ProxyCertInfo(&info); 1977178825Sdfr 1978178825Sdfr j = 0; 1979178825Sdfr if (find_extension(c, oid_id_x509_ce_subjectAltName(), &j)) { 1980178825Sdfr ret = HX509_PROXY_CERT_INVALID; 1981178825Sdfr hx509_set_error_string(context, 0, ret, 1982178825Sdfr "Proxy certificate have explicity " 1983178825Sdfr "forbidden subjectAltName"); 1984178825Sdfr goto out; 1985178825Sdfr } 1986178825Sdfr 1987178825Sdfr j = 0; 1988178825Sdfr if (find_extension(c, oid_id_x509_ce_issuerAltName(), &j)) { 1989178825Sdfr ret = HX509_PROXY_CERT_INVALID; 1990178825Sdfr hx509_set_error_string(context, 0, ret, 1991178825Sdfr "Proxy certificate have explicity " 1992178825Sdfr "forbidden issuerAltName"); 1993178825Sdfr goto out; 1994178825Sdfr } 1995178825Sdfr 1996178825Sdfr /* 1997178825Sdfr * The subject name of the proxy certificate should be 1998178825Sdfr * CN=XXX,<proxy issuer>, prune of CN and check if its 1999178825Sdfr * the same over the whole chain of proxy certs and 2000178825Sdfr * then check with the EE cert when we get to it. 2001178825Sdfr */ 2002178825Sdfr 2003178825Sdfr if (proxy_cert_depth) { 2004178825Sdfr ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject); 2005178825Sdfr if (ret) { 2006178825Sdfr ret = HX509_PROXY_CERT_NAME_WRONG; 2007178825Sdfr hx509_set_error_string(context, 0, ret, 2008178825Sdfr "Base proxy name not right"); 2009178825Sdfr goto out; 2010178825Sdfr } 2011178825Sdfr } 2012178825Sdfr 2013178825Sdfr free_Name(&proxy_issuer); 2014178825Sdfr 2015178825Sdfr ret = copy_Name(&c->tbsCertificate.subject, &proxy_issuer); 2016178825Sdfr if (ret) { 2017178825Sdfr hx509_clear_error_string(context); 2018178825Sdfr goto out; 2019178825Sdfr } 2020178825Sdfr 2021178825Sdfr j = proxy_issuer.u.rdnSequence.len; 2022178825Sdfr if (proxy_issuer.u.rdnSequence.len < 2 2023178825Sdfr || proxy_issuer.u.rdnSequence.val[j - 1].len > 1 2024178825Sdfr || der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type, 2025178825Sdfr oid_id_at_commonName())) 2026178825Sdfr { 2027178825Sdfr ret = HX509_PROXY_CERT_NAME_WRONG; 2028178825Sdfr hx509_set_error_string(context, 0, ret, 2029178825Sdfr "Proxy name too short or " 2030178825Sdfr "does not have Common name " 2031178825Sdfr "at the top"); 2032178825Sdfr goto out; 2033178825Sdfr } 2034178825Sdfr 2035178825Sdfr free_RelativeDistinguishedName(&proxy_issuer.u.rdnSequence.val[j - 1]); 2036178825Sdfr proxy_issuer.u.rdnSequence.len -= 1; 2037178825Sdfr 2038178825Sdfr ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer); 2039178825Sdfr if (ret != 0) { 2040178825Sdfr ret = HX509_PROXY_CERT_NAME_WRONG; 2041178825Sdfr hx509_set_error_string(context, 0, ret, 2042178825Sdfr "Proxy issuer name not as expected"); 2043178825Sdfr goto out; 2044178825Sdfr } 2045178825Sdfr 2046178825Sdfr break; 2047178825Sdfr } else { 2048178825Sdfr /* 2049178825Sdfr * Now we are done with the proxy certificates, this 2050178825Sdfr * cert was an EE cert and we we will fall though to 2051178825Sdfr * EE checking below. 2052178825Sdfr */ 2053178825Sdfr type = EE_CERT; 2054178825Sdfr /* FALLTHOUGH */ 2055178825Sdfr } 2056178825Sdfr } 2057178825Sdfr case EE_CERT: 2058178825Sdfr /* 2059178825Sdfr * If there where any proxy certificates in the chain 2060178825Sdfr * (proxy_cert_depth > 0), check that the proxy issuer 2061178825Sdfr * matched proxy certificates "base" subject. 2062178825Sdfr */ 2063178825Sdfr if (proxy_cert_depth) { 2064178825Sdfr 2065178825Sdfr ret = _hx509_name_cmp(&proxy_issuer, 2066178825Sdfr &c->tbsCertificate.subject); 2067178825Sdfr if (ret) { 2068178825Sdfr ret = HX509_PROXY_CERT_NAME_WRONG; 2069178825Sdfr hx509_clear_error_string(context); 2070178825Sdfr goto out; 2071178825Sdfr } 2072178825Sdfr if (cert->basename) 2073178825Sdfr hx509_name_free(&cert->basename); 2074178825Sdfr 2075178825Sdfr ret = _hx509_name_from_Name(&proxy_issuer, &cert->basename); 2076178825Sdfr if (ret) { 2077178825Sdfr hx509_clear_error_string(context); 2078178825Sdfr goto out; 2079178825Sdfr } 2080178825Sdfr } 2081178825Sdfr 2082178825Sdfr break; 2083178825Sdfr } 2084178825Sdfr 2085178825Sdfr ret = check_basic_constraints(context, c, type, 2086178825Sdfr i - proxy_cert_depth - selfsigned_depth); 2087178825Sdfr if (ret) 2088178825Sdfr goto out; 2089178825Sdfr 2090178825Sdfr /* 2091178825Sdfr * Don't check the trust anchors expiration time since they 2092178825Sdfr * are transported out of band, from RFC3820. 2093178825Sdfr */ 2094178825Sdfr if (i + 1 != path.len || CHECK_TA(ctx)) { 2095178825Sdfr 2096178825Sdfr t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore); 2097178825Sdfr if (t > ctx->time_now) { 2098178825Sdfr ret = HX509_CERT_USED_BEFORE_TIME; 2099178825Sdfr hx509_clear_error_string(context); 2100178825Sdfr goto out; 2101178825Sdfr } 2102178825Sdfr t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter); 2103178825Sdfr if (t < ctx->time_now) { 2104178825Sdfr ret = HX509_CERT_USED_AFTER_TIME; 2105178825Sdfr hx509_clear_error_string(context); 2106178825Sdfr goto out; 2107178825Sdfr } 2108178825Sdfr } 2109178825Sdfr 2110178825Sdfr if (type == EE_CERT) 2111178825Sdfr type = CA_CERT; 2112178825Sdfr else if (type == PROXY_CERT) 2113178825Sdfr proxy_cert_depth++; 2114178825Sdfr } 2115178825Sdfr 2116178825Sdfr /* 2117178825Sdfr * Verify constraints, do this backward so path constraints are 2118178825Sdfr * checked in the right order. 2119178825Sdfr */ 2120178825Sdfr 2121178825Sdfr for (ret = 0, i = path.len - 1; i >= 0; i--) { 2122178825Sdfr Certificate *c; 2123178825Sdfr 2124178825Sdfr c = _hx509_get_cert(path.val[i]); 2125178825Sdfr 2126178825Sdfr /* verify name constraints, not for selfsigned and anchor */ 2127178825Sdfr if (!certificate_is_self_signed(c) || i + 1 != path.len) { 2128178825Sdfr ret = check_name_constraints(context, &nc, c); 2129178825Sdfr if (ret) { 2130178825Sdfr goto out; 2131178825Sdfr } 2132178825Sdfr } 2133178825Sdfr ret = add_name_constraints(context, c, i == 0, &nc); 2134178825Sdfr if (ret) 2135178825Sdfr goto out; 2136178825Sdfr 2137178825Sdfr /* XXX verify all other silly constraints */ 2138178825Sdfr 2139178825Sdfr } 2140178825Sdfr 2141178825Sdfr /* 2142178825Sdfr * Verify that no certificates has been revoked. 2143178825Sdfr */ 2144178825Sdfr 2145178825Sdfr if (ctx->revoke_ctx) { 2146178825Sdfr hx509_certs certs; 2147178825Sdfr 2148178825Sdfr ret = hx509_certs_init(context, "MEMORY:revoke-certs", 0, 2149178825Sdfr NULL, &certs); 2150178825Sdfr if (ret) 2151178825Sdfr goto out; 2152178825Sdfr 2153178825Sdfr for (i = 0; i < path.len; i++) { 2154178825Sdfr ret = hx509_certs_add(context, certs, path.val[i]); 2155178825Sdfr if (ret) { 2156178825Sdfr hx509_certs_free(&certs); 2157178825Sdfr goto out; 2158178825Sdfr } 2159178825Sdfr } 2160178825Sdfr ret = hx509_certs_merge(context, certs, pool); 2161178825Sdfr if (ret) { 2162178825Sdfr hx509_certs_free(&certs); 2163178825Sdfr goto out; 2164178825Sdfr } 2165178825Sdfr 2166178825Sdfr for (i = 0; i < path.len - 1; i++) { 2167178825Sdfr int parent = (i < path.len - 1) ? i + 1 : i; 2168178825Sdfr 2169178825Sdfr ret = hx509_revoke_verify(context, 2170178825Sdfr ctx->revoke_ctx, 2171178825Sdfr certs, 2172178825Sdfr ctx->time_now, 2173178825Sdfr path.val[i], 2174178825Sdfr path.val[parent]); 2175178825Sdfr if (ret) { 2176178825Sdfr hx509_certs_free(&certs); 2177178825Sdfr goto out; 2178178825Sdfr } 2179178825Sdfr } 2180178825Sdfr hx509_certs_free(&certs); 2181178825Sdfr } 2182178825Sdfr 2183178825Sdfr /* 2184178825Sdfr * Verify signatures, do this backward so public key working 2185178825Sdfr * parameter is passed up from the anchor up though the chain. 2186178825Sdfr */ 2187178825Sdfr 2188178825Sdfr for (i = path.len - 1; i >= 0; i--) { 2189178825Sdfr Certificate *signer, *c; 2190178825Sdfr 2191178825Sdfr c = _hx509_get_cert(path.val[i]); 2192178825Sdfr 2193178825Sdfr /* is last in chain (trust anchor) */ 2194178825Sdfr if (i + 1 == path.len) { 2195178825Sdfr signer = path.val[i]->data; 2196178825Sdfr 2197178825Sdfr /* if trust anchor is not self signed, don't check sig */ 2198178825Sdfr if (!certificate_is_self_signed(signer)) 2199178825Sdfr continue; 2200178825Sdfr } else { 2201178825Sdfr /* take next certificate in chain */ 2202178825Sdfr signer = path.val[i + 1]->data; 2203178825Sdfr } 2204178825Sdfr 2205178825Sdfr /* verify signatureValue */ 2206178825Sdfr ret = _hx509_verify_signature_bitstring(context, 2207178825Sdfr signer, 2208178825Sdfr &c->signatureAlgorithm, 2209178825Sdfr &c->tbsCertificate._save, 2210178825Sdfr &c->signatureValue); 2211178825Sdfr if (ret) { 2212178825Sdfr hx509_set_error_string(context, HX509_ERROR_APPEND, ret, 2213178825Sdfr "Failed to verify signature of certificate"); 2214178825Sdfr goto out; 2215178825Sdfr } 2216178825Sdfr } 2217178825Sdfr 2218178825Sdfrout: 2219178825Sdfr hx509_certs_free(&anchors); 2220178825Sdfr free_Name(&proxy_issuer); 2221178825Sdfr free_name_constraints(&nc); 2222178825Sdfr _hx509_path_free(&path); 2223178825Sdfr 2224178825Sdfr return ret; 2225178825Sdfr} 2226178825Sdfr 2227178825Sdfr/** 2228178825Sdfr * Verify a signature made using the private key of an certificate. 2229178825Sdfr * 2230178825Sdfr * @param context A hx509 context. 2231178825Sdfr * @param signer the certificate that made the signature. 2232178825Sdfr * @param alg algorthm that was used to sign the data. 2233178825Sdfr * @param data the data that was signed. 2234178825Sdfr * @param sig the sigature to verify. 2235178825Sdfr * 2236178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 2237178825Sdfr * 2238178825Sdfr * @ingroup hx509_crypto 2239178825Sdfr */ 2240178825Sdfr 2241178825Sdfrint 2242178825Sdfrhx509_verify_signature(hx509_context context, 2243178825Sdfr const hx509_cert signer, 2244178825Sdfr const AlgorithmIdentifier *alg, 2245178825Sdfr const heim_octet_string *data, 2246178825Sdfr const heim_octet_string *sig) 2247178825Sdfr{ 2248178825Sdfr return _hx509_verify_signature(context, signer->data, alg, data, sig); 2249178825Sdfr} 2250178825Sdfr 2251178825Sdfr 2252178825Sdfr/** 2253178825Sdfr * Verify that the certificate is allowed to be used for the hostname 2254178825Sdfr * and address. 2255178825Sdfr * 2256178825Sdfr * @param context A hx509 context. 2257178825Sdfr * @param cert the certificate to match with 2258178825Sdfr * @param flags Flags to modify the behavior: 2259178825Sdfr * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok 2260178825Sdfr * @param type type of hostname: 2261178825Sdfr * - HX509_HN_HOSTNAME for plain hostname. 2262178825Sdfr * - HX509_HN_DNSSRV for DNS SRV names. 2263178825Sdfr * @param hostname the hostname to check 2264178825Sdfr * @param sa address of the host 2265178825Sdfr * @param sa_size length of address 2266178825Sdfr * 2267178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 2268178825Sdfr * 2269178825Sdfr * @ingroup hx509_cert 2270178825Sdfr */ 2271178825Sdfr 2272178825Sdfrint 2273178825Sdfrhx509_verify_hostname(hx509_context context, 2274178825Sdfr const hx509_cert cert, 2275178825Sdfr int flags, 2276178825Sdfr hx509_hostname_type type, 2277178825Sdfr const char *hostname, 2278178825Sdfr const struct sockaddr *sa, 2279178825Sdfr /* XXX krb5_socklen_t */ int sa_size) 2280178825Sdfr{ 2281178825Sdfr GeneralNames san; 2282178825Sdfr int ret, i, j; 2283178825Sdfr 2284178825Sdfr if (sa && sa_size <= 0) 2285178825Sdfr return EINVAL; 2286178825Sdfr 2287178825Sdfr memset(&san, 0, sizeof(san)); 2288178825Sdfr 2289178825Sdfr i = 0; 2290178825Sdfr do { 2291178825Sdfr ret = find_extension_subject_alt_name(cert->data, &i, &san); 2292178825Sdfr if (ret == HX509_EXTENSION_NOT_FOUND) { 2293178825Sdfr ret = 0; 2294178825Sdfr break; 2295178825Sdfr } else if (ret != 0) 2296178825Sdfr break; 2297178825Sdfr 2298178825Sdfr for (j = 0; j < san.len; j++) { 2299178825Sdfr switch (san.val[j].element) { 2300178825Sdfr case choice_GeneralName_dNSName: 2301178825Sdfr if (strcasecmp(san.val[j].u.dNSName, hostname) == 0) { 2302178825Sdfr free_GeneralNames(&san); 2303178825Sdfr return 0; 2304178825Sdfr } 2305178825Sdfr break; 2306178825Sdfr default: 2307178825Sdfr break; 2308178825Sdfr } 2309178825Sdfr } 2310178825Sdfr free_GeneralNames(&san); 2311178825Sdfr } while (1); 2312178825Sdfr 2313178825Sdfr { 2314178825Sdfr Name *name = &cert->data->tbsCertificate.subject; 2315178825Sdfr 2316178825Sdfr /* match if first component is a CN= */ 2317178825Sdfr if (name->u.rdnSequence.len > 0 2318178825Sdfr && name->u.rdnSequence.val[0].len == 1 2319178825Sdfr && der_heim_oid_cmp(&name->u.rdnSequence.val[0].val[0].type, 2320178825Sdfr oid_id_at_commonName()) == 0) 2321178825Sdfr { 2322178825Sdfr DirectoryString *ds = &name->u.rdnSequence.val[0].val[0].value; 2323178825Sdfr 2324178825Sdfr switch (ds->element) { 2325178825Sdfr case choice_DirectoryString_printableString: 2326178825Sdfr if (strcasecmp(ds->u.printableString, hostname) == 0) 2327178825Sdfr return 0; 2328178825Sdfr break; 2329178825Sdfr case choice_DirectoryString_ia5String: 2330178825Sdfr if (strcasecmp(ds->u.ia5String, hostname) == 0) 2331178825Sdfr return 0; 2332178825Sdfr break; 2333178825Sdfr case choice_DirectoryString_utf8String: 2334178825Sdfr if (strcasecmp(ds->u.utf8String, hostname) == 0) 2335178825Sdfr return 0; 2336178825Sdfr default: 2337178825Sdfr break; 2338178825Sdfr } 2339178825Sdfr } 2340178825Sdfr } 2341178825Sdfr 2342178825Sdfr if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0) 2343178825Sdfr ret = HX509_NAME_CONSTRAINT_ERROR; 2344178825Sdfr 2345178825Sdfr return ret; 2346178825Sdfr} 2347178825Sdfr 2348178825Sdfrint 2349178825Sdfr_hx509_set_cert_attribute(hx509_context context, 2350178825Sdfr hx509_cert cert, 2351178825Sdfr const heim_oid *oid, 2352178825Sdfr const heim_octet_string *attr) 2353178825Sdfr{ 2354178825Sdfr hx509_cert_attribute a; 2355178825Sdfr void *d; 2356178825Sdfr 2357178825Sdfr if (hx509_cert_get_attribute(cert, oid) != NULL) 2358178825Sdfr return 0; 2359178825Sdfr 2360178825Sdfr d = realloc(cert->attrs.val, 2361178825Sdfr sizeof(cert->attrs.val[0]) * (cert->attrs.len + 1)); 2362178825Sdfr if (d == NULL) { 2363178825Sdfr hx509_clear_error_string(context); 2364178825Sdfr return ENOMEM; 2365178825Sdfr } 2366178825Sdfr cert->attrs.val = d; 2367178825Sdfr 2368178825Sdfr a = malloc(sizeof(*a)); 2369178825Sdfr if (a == NULL) 2370178825Sdfr return ENOMEM; 2371178825Sdfr 2372178825Sdfr der_copy_octet_string(attr, &a->data); 2373178825Sdfr der_copy_oid(oid, &a->oid); 2374178825Sdfr 2375178825Sdfr cert->attrs.val[cert->attrs.len] = a; 2376178825Sdfr cert->attrs.len++; 2377178825Sdfr 2378178825Sdfr return 0; 2379178825Sdfr} 2380178825Sdfr 2381178825Sdfr/** 2382178825Sdfr * Get an external attribute for the certificate, examples are 2383178825Sdfr * friendly name and id. 2384178825Sdfr * 2385178825Sdfr * @param cert hx509 certificate object to search 2386178825Sdfr * @param oid an oid to search for. 2387178825Sdfr * 2388178825Sdfr * @return an hx509_cert_attribute, only valid as long as the 2389178825Sdfr * certificate is referenced. 2390178825Sdfr * 2391178825Sdfr * @ingroup hx509_cert 2392178825Sdfr */ 2393178825Sdfr 2394178825Sdfrhx509_cert_attribute 2395178825Sdfrhx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid) 2396178825Sdfr{ 2397178825Sdfr int i; 2398178825Sdfr for (i = 0; i < cert->attrs.len; i++) 2399178825Sdfr if (der_heim_oid_cmp(oid, &cert->attrs.val[i]->oid) == 0) 2400178825Sdfr return cert->attrs.val[i]; 2401178825Sdfr return NULL; 2402178825Sdfr} 2403178825Sdfr 2404178825Sdfr/** 2405178825Sdfr * Set the friendly name on the certificate. 2406178825Sdfr * 2407178825Sdfr * @param cert The certificate to set the friendly name on 2408178825Sdfr * @param name Friendly name. 2409178825Sdfr * 2410178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 2411178825Sdfr * 2412178825Sdfr * @ingroup hx509_cert 2413178825Sdfr */ 2414178825Sdfr 2415178825Sdfrint 2416178825Sdfrhx509_cert_set_friendly_name(hx509_cert cert, const char *name) 2417178825Sdfr{ 2418178825Sdfr if (cert->friendlyname) 2419178825Sdfr free(cert->friendlyname); 2420178825Sdfr cert->friendlyname = strdup(name); 2421178825Sdfr if (cert->friendlyname == NULL) 2422178825Sdfr return ENOMEM; 2423178825Sdfr return 0; 2424178825Sdfr} 2425178825Sdfr 2426178825Sdfr/** 2427178825Sdfr * Get friendly name of the certificate. 2428178825Sdfr * 2429178825Sdfr * @param cert cert to get the friendly name from. 2430178825Sdfr * 2431178825Sdfr * @return an friendly name or NULL if there is. The friendly name is 2432178825Sdfr * only valid as long as the certificate is referenced. 2433178825Sdfr * 2434178825Sdfr * @ingroup hx509_cert 2435178825Sdfr */ 2436178825Sdfr 2437178825Sdfrconst char * 2438178825Sdfrhx509_cert_get_friendly_name(hx509_cert cert) 2439178825Sdfr{ 2440178825Sdfr hx509_cert_attribute a; 2441178825Sdfr PKCS9_friendlyName n; 2442178825Sdfr size_t sz; 2443178825Sdfr int ret, i; 2444178825Sdfr 2445178825Sdfr if (cert->friendlyname) 2446178825Sdfr return cert->friendlyname; 2447178825Sdfr 2448178825Sdfr a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_friendlyName()); 2449178825Sdfr if (a == NULL) { 2450178825Sdfr /* XXX use subject name ? */ 2451178825Sdfr return NULL; 2452178825Sdfr } 2453178825Sdfr 2454178825Sdfr ret = decode_PKCS9_friendlyName(a->data.data, a->data.length, &n, &sz); 2455178825Sdfr if (ret) 2456178825Sdfr return NULL; 2457178825Sdfr 2458178825Sdfr if (n.len != 1) { 2459178825Sdfr free_PKCS9_friendlyName(&n); 2460178825Sdfr return NULL; 2461178825Sdfr } 2462178825Sdfr 2463178825Sdfr cert->friendlyname = malloc(n.val[0].length + 1); 2464178825Sdfr if (cert->friendlyname == NULL) { 2465178825Sdfr free_PKCS9_friendlyName(&n); 2466178825Sdfr return NULL; 2467178825Sdfr } 2468178825Sdfr 2469178825Sdfr for (i = 0; i < n.val[0].length; i++) { 2470178825Sdfr if (n.val[0].data[i] <= 0xff) 2471178825Sdfr cert->friendlyname[i] = n.val[0].data[i] & 0xff; 2472178825Sdfr else 2473178825Sdfr cert->friendlyname[i] = 'X'; 2474178825Sdfr } 2475178825Sdfr cert->friendlyname[i] = '\0'; 2476178825Sdfr free_PKCS9_friendlyName(&n); 2477178825Sdfr 2478178825Sdfr return cert->friendlyname; 2479178825Sdfr} 2480178825Sdfr 2481178825Sdfrvoid 2482178825Sdfr_hx509_query_clear(hx509_query *q) 2483178825Sdfr{ 2484178825Sdfr memset(q, 0, sizeof(*q)); 2485178825Sdfr} 2486178825Sdfr 2487178825Sdfr/** 2488178825Sdfr * Allocate an query controller. Free using hx509_query_free(). 2489178825Sdfr * 2490178825Sdfr * @param context A hx509 context. 2491178825Sdfr * @param q return pointer to a hx509_query. 2492178825Sdfr * 2493178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 2494178825Sdfr * 2495178825Sdfr * @ingroup hx509_cert 2496178825Sdfr */ 2497178825Sdfr 2498178825Sdfrint 2499178825Sdfrhx509_query_alloc(hx509_context context, hx509_query **q) 2500178825Sdfr{ 2501178825Sdfr *q = calloc(1, sizeof(**q)); 2502178825Sdfr if (*q == NULL) 2503178825Sdfr return ENOMEM; 2504178825Sdfr return 0; 2505178825Sdfr} 2506178825Sdfr 2507178825Sdfr/** 2508178825Sdfr * Set match options for the hx509 query controller. 2509178825Sdfr * 2510178825Sdfr * @param q query controller. 2511178825Sdfr * @param option options to control the query controller. 2512178825Sdfr * 2513178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 2514178825Sdfr * 2515178825Sdfr * @ingroup hx509_cert 2516178825Sdfr */ 2517178825Sdfr 2518178825Sdfrvoid 2519178825Sdfrhx509_query_match_option(hx509_query *q, hx509_query_option option) 2520178825Sdfr{ 2521178825Sdfr switch(option) { 2522178825Sdfr case HX509_QUERY_OPTION_PRIVATE_KEY: 2523178825Sdfr q->match |= HX509_QUERY_PRIVATE_KEY; 2524178825Sdfr break; 2525178825Sdfr case HX509_QUERY_OPTION_KU_ENCIPHERMENT: 2526178825Sdfr q->match |= HX509_QUERY_KU_ENCIPHERMENT; 2527178825Sdfr break; 2528178825Sdfr case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE: 2529178825Sdfr q->match |= HX509_QUERY_KU_DIGITALSIGNATURE; 2530178825Sdfr break; 2531178825Sdfr case HX509_QUERY_OPTION_KU_KEYCERTSIGN: 2532178825Sdfr q->match |= HX509_QUERY_KU_KEYCERTSIGN; 2533178825Sdfr break; 2534178825Sdfr case HX509_QUERY_OPTION_END: 2535178825Sdfr default: 2536178825Sdfr break; 2537178825Sdfr } 2538178825Sdfr} 2539178825Sdfr 2540178825Sdfr/** 2541178825Sdfr * Set the issuer and serial number of match in the query 2542178825Sdfr * controller. The function make copies of the isser and serial number. 2543178825Sdfr * 2544178825Sdfr * @param q a hx509 query controller 2545178825Sdfr * @param issuer issuer to search for 2546178825Sdfr * @param serialNumber the serialNumber of the issuer. 2547178825Sdfr * 2548178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 2549178825Sdfr * 2550178825Sdfr * @ingroup hx509_cert 2551178825Sdfr */ 2552178825Sdfr 2553178825Sdfrint 2554178825Sdfrhx509_query_match_issuer_serial(hx509_query *q, 2555178825Sdfr const Name *issuer, 2556178825Sdfr const heim_integer *serialNumber) 2557178825Sdfr{ 2558178825Sdfr int ret; 2559178825Sdfr if (q->serial) { 2560178825Sdfr der_free_heim_integer(q->serial); 2561178825Sdfr free(q->serial); 2562178825Sdfr } 2563178825Sdfr q->serial = malloc(sizeof(*q->serial)); 2564178825Sdfr if (q->serial == NULL) 2565178825Sdfr return ENOMEM; 2566178825Sdfr ret = der_copy_heim_integer(serialNumber, q->serial); 2567178825Sdfr if (ret) { 2568178825Sdfr free(q->serial); 2569178825Sdfr q->serial = NULL; 2570178825Sdfr return ret; 2571178825Sdfr } 2572178825Sdfr if (q->issuer_name) { 2573178825Sdfr free_Name(q->issuer_name); 2574178825Sdfr free(q->issuer_name); 2575178825Sdfr } 2576178825Sdfr q->issuer_name = malloc(sizeof(*q->issuer_name)); 2577178825Sdfr if (q->issuer_name == NULL) 2578178825Sdfr return ENOMEM; 2579178825Sdfr ret = copy_Name(issuer, q->issuer_name); 2580178825Sdfr if (ret) { 2581178825Sdfr free(q->issuer_name); 2582178825Sdfr q->issuer_name = NULL; 2583178825Sdfr return ret; 2584178825Sdfr } 2585178825Sdfr q->match |= HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME; 2586178825Sdfr return 0; 2587178825Sdfr} 2588178825Sdfr 2589178825Sdfr/** 2590178825Sdfr * Set the query controller to match on a friendly name 2591178825Sdfr * 2592178825Sdfr * @param q a hx509 query controller. 2593178825Sdfr * @param name a friendly name to match on 2594178825Sdfr * 2595178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 2596178825Sdfr * 2597178825Sdfr * @ingroup hx509_cert 2598178825Sdfr */ 2599178825Sdfr 2600178825Sdfrint 2601178825Sdfrhx509_query_match_friendly_name(hx509_query *q, const char *name) 2602178825Sdfr{ 2603178825Sdfr if (q->friendlyname) 2604178825Sdfr free(q->friendlyname); 2605178825Sdfr q->friendlyname = strdup(name); 2606178825Sdfr if (q->friendlyname == NULL) 2607178825Sdfr return ENOMEM; 2608178825Sdfr q->match |= HX509_QUERY_MATCH_FRIENDLY_NAME; 2609178825Sdfr return 0; 2610178825Sdfr} 2611178825Sdfr 2612178825Sdfr/** 2613178825Sdfr * Set the query controller to match using a specific match function. 2614178825Sdfr * 2615178825Sdfr * @param q a hx509 query controller. 2616178825Sdfr * @param func function to use for matching, if the argument is NULL, 2617178825Sdfr * the match function is removed. 2618178825Sdfr * @param ctx context passed to the function. 2619178825Sdfr * 2620178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 2621178825Sdfr * 2622178825Sdfr * @ingroup hx509_cert 2623178825Sdfr */ 2624178825Sdfr 2625178825Sdfrint 2626178825Sdfrhx509_query_match_cmp_func(hx509_query *q, 2627178825Sdfr int (*func)(void *, hx509_cert), 2628178825Sdfr void *ctx) 2629178825Sdfr{ 2630178825Sdfr if (func) 2631178825Sdfr q->match |= HX509_QUERY_MATCH_FUNCTION; 2632178825Sdfr else 2633178825Sdfr q->match &= ~HX509_QUERY_MATCH_FUNCTION; 2634178825Sdfr q->cmp_func = func; 2635178825Sdfr q->cmp_func_ctx = ctx; 2636178825Sdfr return 0; 2637178825Sdfr} 2638178825Sdfr 2639178825Sdfr/** 2640178825Sdfr * Free the query controller. 2641178825Sdfr * 2642178825Sdfr * @param context A hx509 context. 2643178825Sdfr * @param q a pointer to the query controller. 2644178825Sdfr * 2645178825Sdfr * @ingroup hx509_cert 2646178825Sdfr */ 2647178825Sdfr 2648178825Sdfrvoid 2649178825Sdfrhx509_query_free(hx509_context context, hx509_query *q) 2650178825Sdfr{ 2651178825Sdfr if (q->serial) { 2652178825Sdfr der_free_heim_integer(q->serial); 2653178825Sdfr free(q->serial); 2654178825Sdfr q->serial = NULL; 2655178825Sdfr } 2656178825Sdfr if (q->issuer_name) { 2657178825Sdfr free_Name(q->issuer_name); 2658178825Sdfr free(q->issuer_name); 2659178825Sdfr q->issuer_name = NULL; 2660178825Sdfr } 2661178825Sdfr if (q) { 2662178825Sdfr free(q->friendlyname); 2663178825Sdfr memset(q, 0, sizeof(*q)); 2664178825Sdfr } 2665178825Sdfr free(q); 2666178825Sdfr} 2667178825Sdfr 2668178825Sdfrint 2669178825Sdfr_hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert) 2670178825Sdfr{ 2671178825Sdfr Certificate *c = _hx509_get_cert(cert); 2672178825Sdfr 2673178825Sdfr _hx509_query_statistic(context, 1, q); 2674178825Sdfr 2675178825Sdfr if ((q->match & HX509_QUERY_FIND_ISSUER_CERT) && 2676178825Sdfr _hx509_cert_is_parent_cmp(q->subject, c, 0) != 0) 2677178825Sdfr return 0; 2678178825Sdfr 2679178825Sdfr if ((q->match & HX509_QUERY_MATCH_CERTIFICATE) && 2680178825Sdfr _hx509_Certificate_cmp(q->certificate, c) != 0) 2681178825Sdfr return 0; 2682178825Sdfr 2683178825Sdfr if ((q->match & HX509_QUERY_MATCH_SERIALNUMBER) 2684178825Sdfr && der_heim_integer_cmp(&c->tbsCertificate.serialNumber, q->serial) != 0) 2685178825Sdfr return 0; 2686178825Sdfr 2687178825Sdfr if ((q->match & HX509_QUERY_MATCH_ISSUER_NAME) 2688178825Sdfr && _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name) != 0) 2689178825Sdfr return 0; 2690178825Sdfr 2691178825Sdfr if ((q->match & HX509_QUERY_MATCH_SUBJECT_NAME) 2692178825Sdfr && _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name) != 0) 2693178825Sdfr return 0; 2694178825Sdfr 2695178825Sdfr if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) { 2696178825Sdfr SubjectKeyIdentifier si; 2697178825Sdfr int ret; 2698178825Sdfr 2699178825Sdfr ret = _hx509_find_extension_subject_key_id(c, &si); 2700178825Sdfr if (ret == 0) { 2701178825Sdfr if (der_heim_octet_string_cmp(&si, q->subject_id) != 0) 2702178825Sdfr ret = 1; 2703178825Sdfr free_SubjectKeyIdentifier(&si); 2704178825Sdfr } 2705178825Sdfr if (ret) 2706178825Sdfr return 0; 2707178825Sdfr } 2708178825Sdfr if ((q->match & HX509_QUERY_MATCH_ISSUER_ID)) 2709178825Sdfr return 0; 2710178825Sdfr if ((q->match & HX509_QUERY_PRIVATE_KEY) && 2711178825Sdfr _hx509_cert_private_key(cert) == NULL) 2712178825Sdfr return 0; 2713178825Sdfr 2714178825Sdfr { 2715178825Sdfr unsigned ku = 0; 2716178825Sdfr if (q->match & HX509_QUERY_KU_DIGITALSIGNATURE) 2717178825Sdfr ku |= (1 << 0); 2718178825Sdfr if (q->match & HX509_QUERY_KU_NONREPUDIATION) 2719178825Sdfr ku |= (1 << 1); 2720178825Sdfr if (q->match & HX509_QUERY_KU_ENCIPHERMENT) 2721178825Sdfr ku |= (1 << 2); 2722178825Sdfr if (q->match & HX509_QUERY_KU_DATAENCIPHERMENT) 2723178825Sdfr ku |= (1 << 3); 2724178825Sdfr if (q->match & HX509_QUERY_KU_KEYAGREEMENT) 2725178825Sdfr ku |= (1 << 4); 2726178825Sdfr if (q->match & HX509_QUERY_KU_KEYCERTSIGN) 2727178825Sdfr ku |= (1 << 5); 2728178825Sdfr if (q->match & HX509_QUERY_KU_CRLSIGN) 2729178825Sdfr ku |= (1 << 6); 2730178825Sdfr if (ku && check_key_usage(context, c, ku, TRUE)) 2731178825Sdfr return 0; 2732178825Sdfr } 2733178825Sdfr if ((q->match & HX509_QUERY_ANCHOR)) 2734178825Sdfr return 0; 2735178825Sdfr 2736178825Sdfr if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) { 2737178825Sdfr hx509_cert_attribute a; 2738178825Sdfr 2739178825Sdfr a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_localKeyId()); 2740178825Sdfr if (a == NULL) 2741178825Sdfr return 0; 2742178825Sdfr if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0) 2743178825Sdfr return 0; 2744178825Sdfr } 2745178825Sdfr 2746178825Sdfr if (q->match & HX509_QUERY_NO_MATCH_PATH) { 2747178825Sdfr size_t i; 2748178825Sdfr 2749178825Sdfr for (i = 0; i < q->path->len; i++) 2750178825Sdfr if (hx509_cert_cmp(q->path->val[i], cert) == 0) 2751178825Sdfr return 0; 2752178825Sdfr } 2753178825Sdfr if (q->match & HX509_QUERY_MATCH_FRIENDLY_NAME) { 2754178825Sdfr const char *name = hx509_cert_get_friendly_name(cert); 2755178825Sdfr if (name == NULL) 2756178825Sdfr return 0; 2757178825Sdfr if (strcasecmp(q->friendlyname, name) != 0) 2758178825Sdfr return 0; 2759178825Sdfr } 2760178825Sdfr if (q->match & HX509_QUERY_MATCH_FUNCTION) { 2761178825Sdfr int ret = (*q->cmp_func)(q->cmp_func_ctx, cert); 2762178825Sdfr if (ret != 0) 2763178825Sdfr return 0; 2764178825Sdfr } 2765178825Sdfr 2766178825Sdfr if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) { 2767178825Sdfr heim_octet_string os; 2768178825Sdfr int ret; 2769178825Sdfr 2770178825Sdfr os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; 2771178825Sdfr os.length = 2772178825Sdfr c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8; 2773178825Sdfr 2774178825Sdfr ret = _hx509_verify_signature(context, 2775178825Sdfr NULL, 2776178825Sdfr hx509_signature_sha1(), 2777178825Sdfr &os, 2778178825Sdfr q->keyhash_sha1); 2779178825Sdfr if (ret != 0) 2780178825Sdfr return 0; 2781178825Sdfr } 2782178825Sdfr 2783178825Sdfr if (q->match & HX509_QUERY_MATCH_TIME) { 2784178825Sdfr time_t t; 2785178825Sdfr t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore); 2786178825Sdfr if (t > q->timenow) 2787178825Sdfr return 0; 2788178825Sdfr t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter); 2789178825Sdfr if (t < q->timenow) 2790178825Sdfr return 0; 2791178825Sdfr } 2792178825Sdfr 2793178825Sdfr if (q->match & ~HX509_QUERY_MASK) 2794178825Sdfr return 0; 2795178825Sdfr 2796178825Sdfr return 1; 2797178825Sdfr} 2798178825Sdfr 2799178825Sdfr/** 2800178825Sdfr * Set a statistic file for the query statistics. 2801178825Sdfr * 2802178825Sdfr * @param context A hx509 context. 2803178825Sdfr * @param fn statistics file name 2804178825Sdfr * 2805178825Sdfr * @ingroup hx509_cert 2806178825Sdfr */ 2807178825Sdfr 2808178825Sdfrvoid 2809178825Sdfrhx509_query_statistic_file(hx509_context context, const char *fn) 2810178825Sdfr{ 2811178825Sdfr if (context->querystat) 2812178825Sdfr free(context->querystat); 2813178825Sdfr context->querystat = strdup(fn); 2814178825Sdfr} 2815178825Sdfr 2816178825Sdfrvoid 2817178825Sdfr_hx509_query_statistic(hx509_context context, int type, const hx509_query *q) 2818178825Sdfr{ 2819178825Sdfr FILE *f; 2820178825Sdfr if (context->querystat == NULL) 2821178825Sdfr return; 2822178825Sdfr f = fopen(context->querystat, "a"); 2823178825Sdfr if (f == NULL) 2824178825Sdfr return; 2825178825Sdfr fprintf(f, "%d %d\n", type, q->match); 2826178825Sdfr fclose(f); 2827178825Sdfr} 2828178825Sdfr 2829178825Sdfrstatic const char *statname[] = { 2830178825Sdfr "find issuer cert", 2831178825Sdfr "match serialnumber", 2832178825Sdfr "match issuer name", 2833178825Sdfr "match subject name", 2834178825Sdfr "match subject key id", 2835178825Sdfr "match issuer id", 2836178825Sdfr "private key", 2837178825Sdfr "ku encipherment", 2838178825Sdfr "ku digitalsignature", 2839178825Sdfr "ku keycertsign", 2840178825Sdfr "ku crlsign", 2841178825Sdfr "ku nonrepudiation", 2842178825Sdfr "ku keyagreement", 2843178825Sdfr "ku dataencipherment", 2844178825Sdfr "anchor", 2845178825Sdfr "match certificate", 2846178825Sdfr "match local key id", 2847178825Sdfr "no match path", 2848178825Sdfr "match friendly name", 2849178825Sdfr "match function", 2850178825Sdfr "match key hash sha1", 2851178825Sdfr "match time" 2852178825Sdfr}; 2853178825Sdfr 2854178825Sdfrstruct stat_el { 2855178825Sdfr unsigned long stats; 2856178825Sdfr unsigned int index; 2857178825Sdfr}; 2858178825Sdfr 2859178825Sdfr 2860178825Sdfrstatic int 2861178825Sdfrstat_sort(const void *a, const void *b) 2862178825Sdfr{ 2863178825Sdfr const struct stat_el *ae = a; 2864178825Sdfr const struct stat_el *be = b; 2865178825Sdfr return be->stats - ae->stats; 2866178825Sdfr} 2867178825Sdfr 2868178825Sdfr/** 2869178825Sdfr * Unparse the statistics file and print the result on a FILE descriptor. 2870178825Sdfr * 2871178825Sdfr * @param context A hx509 context. 2872178825Sdfr * @param printtype tyep to print 2873178825Sdfr * @param out the FILE to write the data on. 2874178825Sdfr * 2875178825Sdfr * @ingroup hx509_cert 2876178825Sdfr */ 2877178825Sdfr 2878178825Sdfrvoid 2879178825Sdfrhx509_query_unparse_stats(hx509_context context, int printtype, FILE *out) 2880178825Sdfr{ 2881178825Sdfr rtbl_t t; 2882178825Sdfr FILE *f; 2883178825Sdfr int type, mask, i, num; 2884178825Sdfr unsigned long multiqueries = 0, totalqueries = 0; 2885178825Sdfr struct stat_el stats[32]; 2886178825Sdfr 2887178825Sdfr if (context->querystat == NULL) 2888178825Sdfr return; 2889178825Sdfr f = fopen(context->querystat, "r"); 2890178825Sdfr if (f == NULL) { 2891178825Sdfr fprintf(out, "No statistic file %s: %s.\n", 2892178825Sdfr context->querystat, strerror(errno)); 2893178825Sdfr return; 2894178825Sdfr } 2895178825Sdfr 2896178825Sdfr for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) { 2897178825Sdfr stats[i].index = i; 2898178825Sdfr stats[i].stats = 0; 2899178825Sdfr } 2900178825Sdfr 2901178825Sdfr while (fscanf(f, "%d %d\n", &type, &mask) == 2) { 2902178825Sdfr if (type != printtype) 2903178825Sdfr continue; 2904178825Sdfr num = i = 0; 2905178825Sdfr while (mask && i < sizeof(stats)/sizeof(stats[0])) { 2906178825Sdfr if (mask & 1) { 2907178825Sdfr stats[i].stats++; 2908178825Sdfr num++; 2909178825Sdfr } 2910178825Sdfr mask = mask >>1 ; 2911178825Sdfr i++; 2912178825Sdfr } 2913178825Sdfr if (num > 1) 2914178825Sdfr multiqueries++; 2915178825Sdfr totalqueries++; 2916178825Sdfr } 2917178825Sdfr fclose(f); 2918178825Sdfr 2919178825Sdfr qsort(stats, sizeof(stats)/sizeof(stats[0]), sizeof(stats[0]), stat_sort); 2920178825Sdfr 2921178825Sdfr t = rtbl_create(); 2922178825Sdfr if (t == NULL) 2923178825Sdfr errx(1, "out of memory"); 2924178825Sdfr 2925178825Sdfr rtbl_set_separator (t, " "); 2926178825Sdfr 2927178825Sdfr rtbl_add_column_by_id (t, 0, "Name", 0); 2928178825Sdfr rtbl_add_column_by_id (t, 1, "Counter", 0); 2929178825Sdfr 2930178825Sdfr 2931178825Sdfr for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) { 2932178825Sdfr char str[10]; 2933178825Sdfr 2934178825Sdfr if (stats[i].index < sizeof(statname)/sizeof(statname[0])) 2935178825Sdfr rtbl_add_column_entry_by_id (t, 0, statname[stats[i].index]); 2936178825Sdfr else { 2937178825Sdfr snprintf(str, sizeof(str), "%d", stats[i].index); 2938178825Sdfr rtbl_add_column_entry_by_id (t, 0, str); 2939178825Sdfr } 2940178825Sdfr snprintf(str, sizeof(str), "%lu", stats[i].stats); 2941178825Sdfr rtbl_add_column_entry_by_id (t, 1, str); 2942178825Sdfr } 2943178825Sdfr 2944178825Sdfr rtbl_format(t, out); 2945178825Sdfr rtbl_destroy(t); 2946178825Sdfr 2947178825Sdfr fprintf(out, "\nQueries: multi %lu total %lu\n", 2948178825Sdfr multiqueries, totalqueries); 2949178825Sdfr} 2950178825Sdfr 2951178825Sdfr/** 2952178825Sdfr * Check the extended key usage on the hx509 certificate. 2953178825Sdfr * 2954178825Sdfr * @param context A hx509 context. 2955178825Sdfr * @param cert A hx509 context. 2956178825Sdfr * @param eku the EKU to check for 2957178825Sdfr * @param allow_any_eku if the any EKU is set, allow that to be a 2958178825Sdfr * substitute. 2959178825Sdfr * 2960178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 2961178825Sdfr * 2962178825Sdfr * @ingroup hx509_cert 2963178825Sdfr */ 2964178825Sdfr 2965178825Sdfrint 2966178825Sdfrhx509_cert_check_eku(hx509_context context, hx509_cert cert, 2967178825Sdfr const heim_oid *eku, int allow_any_eku) 2968178825Sdfr{ 2969178825Sdfr ExtKeyUsage e; 2970178825Sdfr int ret, i; 2971178825Sdfr 2972178825Sdfr ret = find_extension_eku(_hx509_get_cert(cert), &e); 2973178825Sdfr if (ret) { 2974178825Sdfr hx509_clear_error_string(context); 2975178825Sdfr return ret; 2976178825Sdfr } 2977178825Sdfr 2978178825Sdfr for (i = 0; i < e.len; i++) { 2979178825Sdfr if (der_heim_oid_cmp(eku, &e.val[i]) == 0) { 2980178825Sdfr free_ExtKeyUsage(&e); 2981178825Sdfr return 0; 2982178825Sdfr } 2983178825Sdfr if (allow_any_eku) { 2984178825Sdfr#if 0 2985178825Sdfr if (der_heim_oid_cmp(id_any_eku, &e.val[i]) == 0) { 2986178825Sdfr free_ExtKeyUsage(&e); 2987178825Sdfr return 0; 2988178825Sdfr } 2989178825Sdfr#endif 2990178825Sdfr } 2991178825Sdfr } 2992178825Sdfr free_ExtKeyUsage(&e); 2993178825Sdfr hx509_clear_error_string(context); 2994178825Sdfr return HX509_CERTIFICATE_MISSING_EKU; 2995178825Sdfr} 2996178825Sdfr 2997178825Sdfrint 2998178825Sdfr_hx509_cert_get_keyusage(hx509_context context, 2999178825Sdfr hx509_cert c, 3000178825Sdfr KeyUsage *ku) 3001178825Sdfr{ 3002178825Sdfr Certificate *cert; 3003178825Sdfr const Extension *e; 3004178825Sdfr size_t size; 3005178825Sdfr int ret, i = 0; 3006178825Sdfr 3007178825Sdfr memset(ku, 0, sizeof(*ku)); 3008178825Sdfr 3009178825Sdfr cert = _hx509_get_cert(c); 3010178825Sdfr 3011178825Sdfr if (_hx509_cert_get_version(cert) < 3) 3012178825Sdfr return 0; 3013178825Sdfr 3014178825Sdfr e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i); 3015178825Sdfr if (e == NULL) 3016178825Sdfr return HX509_KU_CERT_MISSING; 3017178825Sdfr 3018178825Sdfr ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, ku, &size); 3019178825Sdfr if (ret) 3020178825Sdfr return ret; 3021178825Sdfr return 0; 3022178825Sdfr} 3023178825Sdfr 3024178825Sdfrint 3025178825Sdfr_hx509_cert_get_eku(hx509_context context, 3026178825Sdfr hx509_cert cert, 3027178825Sdfr ExtKeyUsage *e) 3028178825Sdfr{ 3029178825Sdfr int ret; 3030178825Sdfr 3031178825Sdfr memset(e, 0, sizeof(*e)); 3032178825Sdfr 3033178825Sdfr ret = find_extension_eku(_hx509_get_cert(cert), e); 3034178825Sdfr if (ret && ret != HX509_EXTENSION_NOT_FOUND) { 3035178825Sdfr hx509_clear_error_string(context); 3036178825Sdfr return ret; 3037178825Sdfr } 3038178825Sdfr return 0; 3039178825Sdfr} 3040178825Sdfr 3041178825Sdfr/** 3042178825Sdfr * Encodes the hx509 certificate as a DER encode binary. 3043178825Sdfr * 3044178825Sdfr * @param context A hx509 context. 3045178825Sdfr * @param c the certificate to encode. 3046178825Sdfr * @param os the encode certificate, set to NULL, 0 on case of 3047178825Sdfr * error. Free the returned structure with hx509_xfree(). 3048178825Sdfr * 3049178825Sdfr * @return An hx509 error code, see hx509_get_error_string(). 3050178825Sdfr * 3051178825Sdfr * @ingroup hx509_cert 3052178825Sdfr */ 3053178825Sdfr 3054178825Sdfrint 3055178825Sdfrhx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os) 3056178825Sdfr{ 3057178825Sdfr size_t size; 3058178825Sdfr int ret; 3059178825Sdfr 3060178825Sdfr os->data = NULL; 3061178825Sdfr os->length = 0; 3062178825Sdfr 3063178825Sdfr ASN1_MALLOC_ENCODE(Certificate, os->data, os->length, 3064178825Sdfr _hx509_get_cert(c), &size, ret); 3065178825Sdfr if (ret) { 3066178825Sdfr os->data = NULL; 3067178825Sdfr os->length = 0; 3068178825Sdfr return ret; 3069178825Sdfr } 3070178825Sdfr if (os->length != size) 3071178825Sdfr _hx509_abort("internal ASN.1 encoder error"); 3072178825Sdfr 3073178825Sdfr return ret; 3074178825Sdfr} 3075178825Sdfr 3076178825Sdfr/* 3077178825Sdfr * Last to avoid lost __attribute__s due to #undef. 3078178825Sdfr */ 3079178825Sdfr 3080178825Sdfr#undef __attribute__ 3081178825Sdfr#define __attribute__(X) 3082178825Sdfr 3083178825Sdfrvoid 3084178825Sdfr_hx509_abort(const char *fmt, ...) 3085178825Sdfr __attribute__ ((noreturn, format (printf, 1, 2))) 3086178825Sdfr{ 3087178825Sdfr va_list ap; 3088178825Sdfr va_start(ap, fmt); 3089178825Sdfr vprintf(fmt, ap); 3090178825Sdfr va_end(ap); 3091178825Sdfr printf("\n"); 3092178825Sdfr fflush(stdout); 3093178825Sdfr abort(); 3094178825Sdfr} 3095178825Sdfr 3096178825Sdfr/** 3097178825Sdfr * Free a data element allocated in the library. 3098178825Sdfr * 3099178825Sdfr * @param ptr data to be freed. 3100178825Sdfr * 3101178825Sdfr * @ingroup hx509_misc 3102178825Sdfr */ 3103178825Sdfr 3104178825Sdfrvoid 3105178825Sdfrhx509_xfree(void *ptr) 3106178825Sdfr{ 3107178825Sdfr free(ptr); 3108178825Sdfr} 3109