v3_purp.c revision 296465
1/* v3_purp.c */ 2/* 3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4 * 2001. 5 */ 6/* ==================================================================== 7 * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * licensing@OpenSSL.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 * 54 * This product includes cryptographic software written by Eric Young 55 * (eay@cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh@cryptsoft.com). 57 * 58 */ 59 60#include <stdio.h> 61#include "cryptlib.h" 62#include <openssl/x509v3.h> 63#include <openssl/x509_vfy.h> 64 65static void x509v3_cache_extensions(X509 *x); 66 67static int check_ssl_ca(const X509 *x); 68static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, 69 int ca); 70static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, 71 int ca); 72static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, 73 int ca); 74static int purpose_smime(const X509 *x, int ca); 75static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, 76 int ca); 77static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, 78 int ca); 79static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, 80 int ca); 81static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca); 82static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca); 83 84static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b); 85static void xptable_free(X509_PURPOSE *p); 86 87static X509_PURPOSE xstandard[] = { 88 {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, 89 check_purpose_ssl_client, "SSL client", "sslclient", NULL}, 90 {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, 91 check_purpose_ssl_server, "SSL server", "sslserver", NULL}, 92 {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, 93 check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL}, 94 {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, 95 "S/MIME signing", "smimesign", NULL}, 96 {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, 97 check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL}, 98 {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, 99 "CRL signing", "crlsign", NULL}, 100 {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any", 101 NULL}, 102 {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, 103 "OCSP helper", "ocsphelper", NULL}, 104}; 105 106#define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE)) 107 108IMPLEMENT_STACK_OF(X509_PURPOSE) 109 110static STACK_OF(X509_PURPOSE) *xptable = NULL; 111 112static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b) 113{ 114 return (*a)->purpose - (*b)->purpose; 115} 116 117/* 118 * As much as I'd like to make X509_check_purpose use a "const" X509* I 119 * really can't because it does recalculate hashes and do other non-const 120 * things. 121 */ 122int X509_check_purpose(X509 *x, int id, int ca) 123{ 124 int idx; 125 const X509_PURPOSE *pt; 126 if (!(x->ex_flags & EXFLAG_SET)) { 127 CRYPTO_w_lock(CRYPTO_LOCK_X509); 128 x509v3_cache_extensions(x); 129 CRYPTO_w_unlock(CRYPTO_LOCK_X509); 130 } 131 if (id == -1) 132 return 1; 133 idx = X509_PURPOSE_get_by_id(id); 134 if (idx == -1) 135 return -1; 136 pt = X509_PURPOSE_get0(idx); 137 return pt->check_purpose(pt, x, ca); 138} 139 140int X509_PURPOSE_set(int *p, int purpose) 141{ 142 if (X509_PURPOSE_get_by_id(purpose) == -1) { 143 X509V3err(X509V3_F_X509_PURPOSE_SET, X509V3_R_INVALID_PURPOSE); 144 return 0; 145 } 146 *p = purpose; 147 return 1; 148} 149 150int X509_PURPOSE_get_count(void) 151{ 152 if (!xptable) 153 return X509_PURPOSE_COUNT; 154 return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT; 155} 156 157X509_PURPOSE *X509_PURPOSE_get0(int idx) 158{ 159 if (idx < 0) 160 return NULL; 161 if (idx < (int)X509_PURPOSE_COUNT) 162 return xstandard + idx; 163 return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT); 164} 165 166int X509_PURPOSE_get_by_sname(char *sname) 167{ 168 int i; 169 X509_PURPOSE *xptmp; 170 for (i = 0; i < X509_PURPOSE_get_count(); i++) { 171 xptmp = X509_PURPOSE_get0(i); 172 if (!strcmp(xptmp->sname, sname)) 173 return i; 174 } 175 return -1; 176} 177 178int X509_PURPOSE_get_by_id(int purpose) 179{ 180 X509_PURPOSE tmp; 181 int idx; 182 if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX)) 183 return purpose - X509_PURPOSE_MIN; 184 tmp.purpose = purpose; 185 if (!xptable) 186 return -1; 187 idx = sk_X509_PURPOSE_find(xptable, &tmp); 188 if (idx == -1) 189 return -1; 190 return idx + X509_PURPOSE_COUNT; 191} 192 193int X509_PURPOSE_add(int id, int trust, int flags, 194 int (*ck) (const X509_PURPOSE *, const X509 *, int), 195 char *name, char *sname, void *arg) 196{ 197 int idx; 198 X509_PURPOSE *ptmp; 199 /* 200 * This is set according to what we change: application can't set it 201 */ 202 flags &= ~X509_PURPOSE_DYNAMIC; 203 /* This will always be set for application modified trust entries */ 204 flags |= X509_PURPOSE_DYNAMIC_NAME; 205 /* Get existing entry if any */ 206 idx = X509_PURPOSE_get_by_id(id); 207 /* Need a new entry */ 208 if (idx == -1) { 209 if (!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) { 210 X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); 211 return 0; 212 } 213 ptmp->flags = X509_PURPOSE_DYNAMIC; 214 } else 215 ptmp = X509_PURPOSE_get0(idx); 216 217 /* OPENSSL_free existing name if dynamic */ 218 if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { 219 OPENSSL_free(ptmp->name); 220 OPENSSL_free(ptmp->sname); 221 } 222 /* dup supplied name */ 223 ptmp->name = BUF_strdup(name); 224 ptmp->sname = BUF_strdup(sname); 225 if (!ptmp->name || !ptmp->sname) { 226 X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); 227 return 0; 228 } 229 /* Keep the dynamic flag of existing entry */ 230 ptmp->flags &= X509_PURPOSE_DYNAMIC; 231 /* Set all other flags */ 232 ptmp->flags |= flags; 233 234 ptmp->purpose = id; 235 ptmp->trust = trust; 236 ptmp->check_purpose = ck; 237 ptmp->usr_data = arg; 238 239 /* If its a new entry manage the dynamic table */ 240 if (idx == -1) { 241 if (!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) { 242 X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); 243 return 0; 244 } 245 if (!sk_X509_PURPOSE_push(xptable, ptmp)) { 246 X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); 247 return 0; 248 } 249 } 250 return 1; 251} 252 253static void xptable_free(X509_PURPOSE *p) 254{ 255 if (!p) 256 return; 257 if (p->flags & X509_PURPOSE_DYNAMIC) { 258 if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { 259 OPENSSL_free(p->name); 260 OPENSSL_free(p->sname); 261 } 262 OPENSSL_free(p); 263 } 264} 265 266void X509_PURPOSE_cleanup(void) 267{ 268 unsigned int i; 269 sk_X509_PURPOSE_pop_free(xptable, xptable_free); 270 for (i = 0; i < X509_PURPOSE_COUNT; i++) 271 xptable_free(xstandard + i); 272 xptable = NULL; 273} 274 275int X509_PURPOSE_get_id(X509_PURPOSE *xp) 276{ 277 return xp->purpose; 278} 279 280char *X509_PURPOSE_get0_name(X509_PURPOSE *xp) 281{ 282 return xp->name; 283} 284 285char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp) 286{ 287 return xp->sname; 288} 289 290int X509_PURPOSE_get_trust(X509_PURPOSE *xp) 291{ 292 return xp->trust; 293} 294 295static int nid_cmp(int *a, int *b) 296{ 297 return *a - *b; 298} 299 300int X509_supported_extension(X509_EXTENSION *ex) 301{ 302 /* 303 * This table is a list of the NIDs of supported extensions: that is 304 * those which are used by the verify process. If an extension is 305 * critical and doesn't appear in this list then the verify process will 306 * normally reject the certificate. The list must be kept in numerical 307 * order because it will be searched using bsearch. 308 */ 309 310 static int supported_nids[] = { 311 NID_netscape_cert_type, /* 71 */ 312 NID_key_usage, /* 83 */ 313 NID_subject_alt_name, /* 85 */ 314 NID_basic_constraints, /* 87 */ 315 NID_certificate_policies, /* 89 */ 316 NID_ext_key_usage, /* 126 */ 317#ifndef OPENSSL_NO_RFC3779 318 NID_sbgp_ipAddrBlock, /* 290 */ 319 NID_sbgp_autonomousSysNum, /* 291 */ 320#endif 321 NID_policy_constraints, /* 401 */ 322 NID_proxyCertInfo, /* 661 */ 323 NID_inhibit_any_policy /* 748 */ 324 }; 325 326 int ex_nid; 327 328 ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex)); 329 330 if (ex_nid == NID_undef) 331 return 0; 332 333 if (OBJ_bsearch((char *)&ex_nid, (char *)supported_nids, 334 sizeof(supported_nids) / sizeof(int), sizeof(int), 335 (int (*)(const void *, const void *))nid_cmp)) 336 return 1; 337 return 0; 338} 339 340static void x509v3_cache_extensions(X509 *x) 341{ 342 BASIC_CONSTRAINTS *bs; 343 PROXY_CERT_INFO_EXTENSION *pci; 344 ASN1_BIT_STRING *usage; 345 ASN1_BIT_STRING *ns; 346 EXTENDED_KEY_USAGE *extusage; 347 X509_EXTENSION *ex; 348 349 int i; 350 if (x->ex_flags & EXFLAG_SET) 351 return; 352#ifndef OPENSSL_NO_SHA 353 X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); 354#endif 355 /* Does subject name match issuer ? */ 356 if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) 357 x->ex_flags |= EXFLAG_SI; 358 /* V1 should mean no extensions ... */ 359 if (!X509_get_version(x)) 360 x->ex_flags |= EXFLAG_V1; 361 /* Handle basic constraints */ 362 if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) { 363 if (bs->ca) 364 x->ex_flags |= EXFLAG_CA; 365 if (bs->pathlen) { 366 if ((bs->pathlen->type == V_ASN1_NEG_INTEGER) 367 || !bs->ca) { 368 x->ex_flags |= EXFLAG_INVALID; 369 x->ex_pathlen = 0; 370 } else 371 x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen); 372 } else 373 x->ex_pathlen = -1; 374 BASIC_CONSTRAINTS_free(bs); 375 x->ex_flags |= EXFLAG_BCONS; 376 } 377 /* Handle proxy certificates */ 378 if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) { 379 if (x->ex_flags & EXFLAG_CA 380 || X509_get_ext_by_NID(x, NID_subject_alt_name, 0) >= 0 381 || X509_get_ext_by_NID(x, NID_issuer_alt_name, 0) >= 0) { 382 x->ex_flags |= EXFLAG_INVALID; 383 } 384 if (pci->pcPathLengthConstraint) { 385 x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint); 386 } else 387 x->ex_pcpathlen = -1; 388 PROXY_CERT_INFO_EXTENSION_free(pci); 389 x->ex_flags |= EXFLAG_PROXY; 390 } 391 /* Handle key usage */ 392 if ((usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) { 393 if (usage->length > 0) { 394 x->ex_kusage = usage->data[0]; 395 if (usage->length > 1) 396 x->ex_kusage |= usage->data[1] << 8; 397 } else 398 x->ex_kusage = 0; 399 x->ex_flags |= EXFLAG_KUSAGE; 400 ASN1_BIT_STRING_free(usage); 401 } 402 x->ex_xkusage = 0; 403 if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) { 404 x->ex_flags |= EXFLAG_XKUSAGE; 405 for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) { 406 switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) { 407 case NID_server_auth: 408 x->ex_xkusage |= XKU_SSL_SERVER; 409 break; 410 411 case NID_client_auth: 412 x->ex_xkusage |= XKU_SSL_CLIENT; 413 break; 414 415 case NID_email_protect: 416 x->ex_xkusage |= XKU_SMIME; 417 break; 418 419 case NID_code_sign: 420 x->ex_xkusage |= XKU_CODE_SIGN; 421 break; 422 423 case NID_ms_sgc: 424 case NID_ns_sgc: 425 x->ex_xkusage |= XKU_SGC; 426 break; 427 428 case NID_OCSP_sign: 429 x->ex_xkusage |= XKU_OCSP_SIGN; 430 break; 431 432 case NID_time_stamp: 433 x->ex_xkusage |= XKU_TIMESTAMP; 434 break; 435 436 case NID_dvcs: 437 x->ex_xkusage |= XKU_DVCS; 438 break; 439 } 440 } 441 sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); 442 } 443 444 if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) { 445 if (ns->length > 0) 446 x->ex_nscert = ns->data[0]; 447 else 448 x->ex_nscert = 0; 449 x->ex_flags |= EXFLAG_NSCERT; 450 ASN1_BIT_STRING_free(ns); 451 } 452 x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL); 453 x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL); 454#ifndef OPENSSL_NO_RFC3779 455 x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL); 456 x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, 457 NULL, NULL); 458#endif 459 for (i = 0; i < X509_get_ext_count(x); i++) { 460 ex = X509_get_ext(x, i); 461 if (!X509_EXTENSION_get_critical(ex)) 462 continue; 463 if (!X509_supported_extension(ex)) { 464 x->ex_flags |= EXFLAG_CRITICAL; 465 break; 466 } 467 } 468 x->ex_flags |= EXFLAG_SET; 469} 470 471/*- 472 * CA checks common to all purposes 473 * return codes: 474 * 0 not a CA 475 * 1 is a CA 476 * 2 basicConstraints absent so "maybe" a CA 477 * 3 basicConstraints absent but self signed V1. 478 * 4 basicConstraints absent but keyUsage present and keyCertSign asserted. 479 */ 480 481#define V1_ROOT (EXFLAG_V1|EXFLAG_SS) 482#define ku_reject(x, usage) \ 483 (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) 484#define xku_reject(x, usage) \ 485 (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage))) 486#define ns_reject(x, usage) \ 487 (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) 488 489static int check_ca(const X509 *x) 490{ 491 /* keyUsage if present should allow cert signing */ 492 if (ku_reject(x, KU_KEY_CERT_SIGN)) 493 return 0; 494 if (x->ex_flags & EXFLAG_BCONS) { 495 if (x->ex_flags & EXFLAG_CA) 496 return 1; 497 /* If basicConstraints says not a CA then say so */ 498 else 499 return 0; 500 } else { 501 /* we support V1 roots for... uh, I don't really know why. */ 502 if ((x->ex_flags & V1_ROOT) == V1_ROOT) 503 return 3; 504 /* 505 * If key usage present it must have certSign so tolerate it 506 */ 507 else if (x->ex_flags & EXFLAG_KUSAGE) 508 return 4; 509 /* Older certificates could have Netscape-specific CA types */ 510 else if (x->ex_flags & EXFLAG_NSCERT && x->ex_nscert & NS_ANY_CA) 511 return 5; 512 /* can this still be regarded a CA certificate? I doubt it */ 513 return 0; 514 } 515} 516 517int X509_check_ca(X509 *x) 518{ 519 if (!(x->ex_flags & EXFLAG_SET)) { 520 CRYPTO_w_lock(CRYPTO_LOCK_X509); 521 x509v3_cache_extensions(x); 522 CRYPTO_w_unlock(CRYPTO_LOCK_X509); 523 } 524 525 return check_ca(x); 526} 527 528/* Check SSL CA: common checks for SSL client and server */ 529static int check_ssl_ca(const X509 *x) 530{ 531 int ca_ret; 532 ca_ret = check_ca(x); 533 if (!ca_ret) 534 return 0; 535 /* check nsCertType if present */ 536 if (ca_ret != 5 || x->ex_nscert & NS_SSL_CA) 537 return ca_ret; 538 else 539 return 0; 540} 541 542static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, 543 int ca) 544{ 545 if (xku_reject(x, XKU_SSL_CLIENT)) 546 return 0; 547 if (ca) 548 return check_ssl_ca(x); 549 /* We need to do digital signatures with it */ 550 if (ku_reject(x, KU_DIGITAL_SIGNATURE)) 551 return 0; 552 /* nsCertType if present should allow SSL client use */ 553 if (ns_reject(x, NS_SSL_CLIENT)) 554 return 0; 555 return 1; 556} 557 558static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, 559 int ca) 560{ 561 if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC)) 562 return 0; 563 if (ca) 564 return check_ssl_ca(x); 565 566 if (ns_reject(x, NS_SSL_SERVER)) 567 return 0; 568 /* Now as for keyUsage: we'll at least need to sign OR encipher */ 569 if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_ENCIPHERMENT)) 570 return 0; 571 572 return 1; 573 574} 575 576static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, 577 int ca) 578{ 579 int ret; 580 ret = check_purpose_ssl_server(xp, x, ca); 581 if (!ret || ca) 582 return ret; 583 /* We need to encipher or Netscape complains */ 584 if (ku_reject(x, KU_KEY_ENCIPHERMENT)) 585 return 0; 586 return ret; 587} 588 589/* common S/MIME checks */ 590static int purpose_smime(const X509 *x, int ca) 591{ 592 if (xku_reject(x, XKU_SMIME)) 593 return 0; 594 if (ca) { 595 int ca_ret; 596 ca_ret = check_ca(x); 597 if (!ca_ret) 598 return 0; 599 /* check nsCertType if present */ 600 if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) 601 return ca_ret; 602 else 603 return 0; 604 } 605 if (x->ex_flags & EXFLAG_NSCERT) { 606 if (x->ex_nscert & NS_SMIME) 607 return 1; 608 /* Workaround for some buggy certificates */ 609 if (x->ex_nscert & NS_SSL_CLIENT) 610 return 2; 611 return 0; 612 } 613 return 1; 614} 615 616static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, 617 int ca) 618{ 619 int ret; 620 ret = purpose_smime(x, ca); 621 if (!ret || ca) 622 return ret; 623 if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION)) 624 return 0; 625 return ret; 626} 627 628static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, 629 int ca) 630{ 631 int ret; 632 ret = purpose_smime(x, ca); 633 if (!ret || ca) 634 return ret; 635 if (ku_reject(x, KU_KEY_ENCIPHERMENT)) 636 return 0; 637 return ret; 638} 639 640static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, 641 int ca) 642{ 643 if (ca) { 644 int ca_ret; 645 if ((ca_ret = check_ca(x)) != 2) 646 return ca_ret; 647 else 648 return 0; 649 } 650 if (ku_reject(x, KU_CRL_SIGN)) 651 return 0; 652 return 1; 653} 654 655/* 656 * OCSP helper: this is *not* a full OCSP check. It just checks that each CA 657 * is valid. Additional checks must be made on the chain. 658 */ 659 660static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) 661{ 662 /* 663 * Must be a valid CA. Should we really support the "I don't know" value 664 * (2)? 665 */ 666 if (ca) 667 return check_ca(x); 668 /* leaf certificate is checked in OCSP_verify() */ 669 return 1; 670} 671 672static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) 673{ 674 return 1; 675} 676 677/*- 678 * Various checks to see if one certificate issued the second. 679 * This can be used to prune a set of possible issuer certificates 680 * which have been looked up using some simple method such as by 681 * subject name. 682 * These are: 683 * 1. Check issuer_name(subject) == subject_name(issuer) 684 * 2. If akid(subject) exists check it matches issuer 685 * 3. If key_usage(issuer) exists check it supports certificate signing 686 * returns 0 for OK, positive for reason for mismatch, reasons match 687 * codes for X509_verify_cert() 688 */ 689 690int X509_check_issued(X509 *issuer, X509 *subject) 691{ 692 if (X509_NAME_cmp(X509_get_subject_name(issuer), 693 X509_get_issuer_name(subject))) 694 return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; 695 x509v3_cache_extensions(issuer); 696 x509v3_cache_extensions(subject); 697 if (subject->akid) { 698 /* Check key ids (if present) */ 699 if (subject->akid->keyid && issuer->skid && 700 ASN1_OCTET_STRING_cmp(subject->akid->keyid, issuer->skid)) 701 return X509_V_ERR_AKID_SKID_MISMATCH; 702 /* Check serial number */ 703 if (subject->akid->serial && 704 ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), 705 subject->akid->serial)) 706 return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; 707 /* Check issuer name */ 708 if (subject->akid->issuer) { 709 /* 710 * Ugh, for some peculiar reason AKID includes SEQUENCE OF 711 * GeneralName. So look for a DirName. There may be more than one 712 * but we only take any notice of the first. 713 */ 714 GENERAL_NAMES *gens; 715 GENERAL_NAME *gen; 716 X509_NAME *nm = NULL; 717 int i; 718 gens = subject->akid->issuer; 719 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 720 gen = sk_GENERAL_NAME_value(gens, i); 721 if (gen->type == GEN_DIRNAME) { 722 nm = gen->d.dirn; 723 break; 724 } 725 } 726 if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer))) 727 return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; 728 } 729 } 730 if (subject->ex_flags & EXFLAG_PROXY) { 731 if (ku_reject(issuer, KU_DIGITAL_SIGNATURE)) 732 return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE; 733 } else if (ku_reject(issuer, KU_KEY_CERT_SIGN)) 734 return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; 735 return X509_V_OK; 736} 737