159191Skris/* v3_purp.c */ 2296341Sdelphij/* 3296341Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4296341Sdelphij * 2001. 559191Skris */ 659191Skris/* ==================================================================== 7127128Snectar * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. 859191Skris * 959191Skris * Redistribution and use in source and binary forms, with or without 1059191Skris * modification, are permitted provided that the following conditions 1159191Skris * are met: 1259191Skris * 1359191Skris * 1. Redistributions of source code must retain the above copyright 14296341Sdelphij * notice, this list of conditions and the following disclaimer. 1559191Skris * 1659191Skris * 2. Redistributions in binary form must reproduce the above copyright 1759191Skris * notice, this list of conditions and the following disclaimer in 1859191Skris * the documentation and/or other materials provided with the 1959191Skris * distribution. 2059191Skris * 2159191Skris * 3. All advertising materials mentioning features or use of this 2259191Skris * software must display the following acknowledgment: 2359191Skris * "This product includes software developed by the OpenSSL Project 2459191Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2559191Skris * 2659191Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2759191Skris * endorse or promote products derived from this software without 2859191Skris * prior written permission. For written permission, please contact 2959191Skris * licensing@OpenSSL.org. 3059191Skris * 3159191Skris * 5. Products derived from this software may not be called "OpenSSL" 3259191Skris * nor may "OpenSSL" appear in their names without prior written 3359191Skris * permission of the OpenSSL Project. 3459191Skris * 3559191Skris * 6. Redistributions of any form whatsoever must retain the following 3659191Skris * acknowledgment: 3759191Skris * "This product includes software developed by the OpenSSL Project 3859191Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3959191Skris * 4059191Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4159191Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4259191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4359191Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4459191Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4559191Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4659191Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4759191Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4859191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4959191Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5059191Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5159191Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5259191Skris * ==================================================================== 5359191Skris * 5459191Skris * This product includes cryptographic software written by Eric Young 5559191Skris * (eay@cryptsoft.com). This product includes software written by Tim 5659191Skris * Hudson (tjh@cryptsoft.com). 5759191Skris * 5859191Skris */ 5959191Skris 6059191Skris#include <stdio.h> 6159191Skris#include "cryptlib.h" 6259191Skris#include <openssl/x509v3.h> 6368651Skris#include <openssl/x509_vfy.h> 6459191Skris 6559191Skrisstatic void x509v3_cache_extensions(X509 *x); 6659191Skris 6768651Skrisstatic int check_ssl_ca(const X509 *x); 68296341Sdelphijstatic int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, 69296341Sdelphij int ca); 70296341Sdelphijstatic int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, 71296341Sdelphij int ca); 72296341Sdelphijstatic int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, 73296341Sdelphij int ca); 7468651Skrisstatic int purpose_smime(const X509 *x, int ca); 75296341Sdelphijstatic int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, 76296341Sdelphij int ca); 77296341Sdelphijstatic int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, 78296341Sdelphij int ca); 79296341Sdelphijstatic int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, 80296341Sdelphij int ca); 81296341Sdelphijstatic int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, 82296341Sdelphij int ca); 8368651Skrisstatic int no_check(const X509_PURPOSE *xp, const X509 *x, int ca); 84109998Smarkmstatic int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca); 8559191Skris 86296341Sdelphijstatic int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b); 8759191Skrisstatic void xptable_free(X509_PURPOSE *p); 8859191Skris 8959191Skrisstatic X509_PURPOSE xstandard[] = { 90296341Sdelphij {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, 91296341Sdelphij check_purpose_ssl_client, "SSL client", "sslclient", NULL}, 92296341Sdelphij {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, 93296341Sdelphij check_purpose_ssl_server, "SSL server", "sslserver", NULL}, 94296341Sdelphij {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, 95296341Sdelphij check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL}, 96296341Sdelphij {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, 97296341Sdelphij "S/MIME signing", "smimesign", NULL}, 98296341Sdelphij {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, 99296341Sdelphij check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL}, 100296341Sdelphij {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, 101296341Sdelphij "CRL signing", "crlsign", NULL}, 102296341Sdelphij {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any", 103296341Sdelphij NULL}, 104296341Sdelphij {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, 105296341Sdelphij "OCSP helper", "ocsphelper", NULL}, 106296341Sdelphij {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0, 107296341Sdelphij check_purpose_timestamp_sign, "Time Stamp signing", "timestampsign", 108296341Sdelphij NULL}, 10959191Skris}; 11059191Skris 11159191Skris#define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE)) 11259191Skris 11359191SkrisIMPLEMENT_STACK_OF(X509_PURPOSE) 11459191Skris 11559191Skrisstatic STACK_OF(X509_PURPOSE) *xptable = NULL; 11659191Skris 117296341Sdelphijstatic int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b) 11859191Skris{ 119296341Sdelphij return (*a)->purpose - (*b)->purpose; 12059191Skris} 12159191Skris 122296341Sdelphij/* 123296341Sdelphij * As much as I'd like to make X509_check_purpose use a "const" X509* I 124296341Sdelphij * really can't because it does recalculate hashes and do other non-const 125296341Sdelphij * things. 126296341Sdelphij */ 12759191Skrisint X509_check_purpose(X509 *x, int id, int ca) 12859191Skris{ 129296341Sdelphij int idx; 130296341Sdelphij const X509_PURPOSE *pt; 131296341Sdelphij if (!(x->ex_flags & EXFLAG_SET)) { 132296341Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_X509); 133296341Sdelphij x509v3_cache_extensions(x); 134296341Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_X509); 135296341Sdelphij } 136296341Sdelphij if (id == -1) 137296341Sdelphij return 1; 138296341Sdelphij idx = X509_PURPOSE_get_by_id(id); 139296341Sdelphij if (idx == -1) 140296341Sdelphij return -1; 141296341Sdelphij pt = X509_PURPOSE_get0(idx); 142296341Sdelphij return pt->check_purpose(pt, x, ca); 14359191Skris} 14459191Skris 145109998Smarkmint X509_PURPOSE_set(int *p, int purpose) 146109998Smarkm{ 147296341Sdelphij if (X509_PURPOSE_get_by_id(purpose) == -1) { 148296341Sdelphij X509V3err(X509V3_F_X509_PURPOSE_SET, X509V3_R_INVALID_PURPOSE); 149296341Sdelphij return 0; 150296341Sdelphij } 151296341Sdelphij *p = purpose; 152296341Sdelphij return 1; 153109998Smarkm} 154109998Smarkm 15559191Skrisint X509_PURPOSE_get_count(void) 15659191Skris{ 157296341Sdelphij if (!xptable) 158296341Sdelphij return X509_PURPOSE_COUNT; 159296341Sdelphij return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT; 16059191Skris} 16159191Skris 162296341SdelphijX509_PURPOSE *X509_PURPOSE_get0(int idx) 16359191Skris{ 164296341Sdelphij if (idx < 0) 165296341Sdelphij return NULL; 166296341Sdelphij if (idx < (int)X509_PURPOSE_COUNT) 167296341Sdelphij return xstandard + idx; 168296341Sdelphij return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT); 16959191Skris} 17059191Skris 17159191Skrisint X509_PURPOSE_get_by_sname(char *sname) 17259191Skris{ 173296341Sdelphij int i; 174296341Sdelphij X509_PURPOSE *xptmp; 175296341Sdelphij for (i = 0; i < X509_PURPOSE_get_count(); i++) { 176296341Sdelphij xptmp = X509_PURPOSE_get0(i); 177296341Sdelphij if (!strcmp(xptmp->sname, sname)) 178296341Sdelphij return i; 179296341Sdelphij } 180296341Sdelphij return -1; 18159191Skris} 18259191Skris 18359191Skrisint X509_PURPOSE_get_by_id(int purpose) 18459191Skris{ 185296341Sdelphij X509_PURPOSE tmp; 186296341Sdelphij int idx; 187296341Sdelphij if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX)) 188296341Sdelphij return purpose - X509_PURPOSE_MIN; 189296341Sdelphij tmp.purpose = purpose; 190296341Sdelphij if (!xptable) 191296341Sdelphij return -1; 192296341Sdelphij idx = sk_X509_PURPOSE_find(xptable, &tmp); 193296341Sdelphij if (idx == -1) 194296341Sdelphij return -1; 195296341Sdelphij return idx + X509_PURPOSE_COUNT; 19659191Skris} 19759191Skris 19859191Skrisint X509_PURPOSE_add(int id, int trust, int flags, 199296341Sdelphij int (*ck) (const X509_PURPOSE *, const X509 *, int), 200296341Sdelphij char *name, char *sname, void *arg) 20159191Skris{ 202296341Sdelphij int idx; 203296341Sdelphij X509_PURPOSE *ptmp; 204296341Sdelphij /* 205296341Sdelphij * This is set according to what we change: application can't set it 206296341Sdelphij */ 207296341Sdelphij flags &= ~X509_PURPOSE_DYNAMIC; 208296341Sdelphij /* This will always be set for application modified trust entries */ 209296341Sdelphij flags |= X509_PURPOSE_DYNAMIC_NAME; 210296341Sdelphij /* Get existing entry if any */ 211296341Sdelphij idx = X509_PURPOSE_get_by_id(id); 212296341Sdelphij /* Need a new entry */ 213296341Sdelphij if (idx == -1) { 214296341Sdelphij if (!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) { 215296341Sdelphij X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); 216296341Sdelphij return 0; 217296341Sdelphij } 218296341Sdelphij ptmp->flags = X509_PURPOSE_DYNAMIC; 219296341Sdelphij } else 220296341Sdelphij ptmp = X509_PURPOSE_get0(idx); 22159191Skris 222296341Sdelphij /* OPENSSL_free existing name if dynamic */ 223296341Sdelphij if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { 224296341Sdelphij OPENSSL_free(ptmp->name); 225296341Sdelphij OPENSSL_free(ptmp->sname); 226296341Sdelphij } 227296341Sdelphij /* dup supplied name */ 228296341Sdelphij ptmp->name = BUF_strdup(name); 229296341Sdelphij ptmp->sname = BUF_strdup(sname); 230296341Sdelphij if (!ptmp->name || !ptmp->sname) { 231296341Sdelphij X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); 232296341Sdelphij return 0; 233296341Sdelphij } 234296341Sdelphij /* Keep the dynamic flag of existing entry */ 235296341Sdelphij ptmp->flags &= X509_PURPOSE_DYNAMIC; 236296341Sdelphij /* Set all other flags */ 237296341Sdelphij ptmp->flags |= flags; 23859191Skris 239296341Sdelphij ptmp->purpose = id; 240296341Sdelphij ptmp->trust = trust; 241296341Sdelphij ptmp->check_purpose = ck; 242296341Sdelphij ptmp->usr_data = arg; 24359191Skris 244296341Sdelphij /* If its a new entry manage the dynamic table */ 245296341Sdelphij if (idx == -1) { 246296341Sdelphij if (!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) { 247296341Sdelphij X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); 248296341Sdelphij return 0; 249296341Sdelphij } 250296341Sdelphij if (!sk_X509_PURPOSE_push(xptable, ptmp)) { 251296341Sdelphij X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); 252296341Sdelphij return 0; 253296341Sdelphij } 254296341Sdelphij } 255296341Sdelphij return 1; 25659191Skris} 25759191Skris 25859191Skrisstatic void xptable_free(X509_PURPOSE *p) 259296341Sdelphij{ 260296341Sdelphij if (!p) 261296341Sdelphij return; 262296341Sdelphij if (p->flags & X509_PURPOSE_DYNAMIC) { 263296341Sdelphij if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { 264296341Sdelphij OPENSSL_free(p->name); 265296341Sdelphij OPENSSL_free(p->sname); 266296341Sdelphij } 267296341Sdelphij OPENSSL_free(p); 268296341Sdelphij } 269296341Sdelphij} 27059191Skris 27159191Skrisvoid X509_PURPOSE_cleanup(void) 27259191Skris{ 273296341Sdelphij unsigned int i; 274296341Sdelphij sk_X509_PURPOSE_pop_free(xptable, xptable_free); 275296341Sdelphij for (i = 0; i < X509_PURPOSE_COUNT; i++) 276296341Sdelphij xptable_free(xstandard + i); 277296341Sdelphij xptable = NULL; 27859191Skris} 27959191Skris 28059191Skrisint X509_PURPOSE_get_id(X509_PURPOSE *xp) 28159191Skris{ 282296341Sdelphij return xp->purpose; 28359191Skris} 28459191Skris 28559191Skrischar *X509_PURPOSE_get0_name(X509_PURPOSE *xp) 28659191Skris{ 287296341Sdelphij return xp->name; 28859191Skris} 28959191Skris 29059191Skrischar *X509_PURPOSE_get0_sname(X509_PURPOSE *xp) 29159191Skris{ 292296341Sdelphij return xp->sname; 29359191Skris} 29459191Skris 29559191Skrisint X509_PURPOSE_get_trust(X509_PURPOSE *xp) 29659191Skris{ 297296341Sdelphij return xp->trust; 29859191Skris} 29959191Skris 300238405Sjkimstatic int nid_cmp(const int *a, const int *b) 301296341Sdelphij{ 302296341Sdelphij return *a - *b; 303296341Sdelphij} 304109998Smarkm 305238405SjkimDECLARE_OBJ_BSEARCH_CMP_FN(int, int, nid); 306238405SjkimIMPLEMENT_OBJ_BSEARCH_CMP_FN(int, int, nid); 307238405Sjkim 308109998Smarkmint X509_supported_extension(X509_EXTENSION *ex) 309296341Sdelphij{ 310296341Sdelphij /* 311296341Sdelphij * This table is a list of the NIDs of supported extensions: that is 312296341Sdelphij * those which are used by the verify process. If an extension is 313296341Sdelphij * critical and doesn't appear in this list then the verify process will 314296341Sdelphij * normally reject the certificate. The list must be kept in numerical 315296341Sdelphij * order because it will be searched using bsearch. 316296341Sdelphij */ 317109998Smarkm 318296341Sdelphij static const int supported_nids[] = { 319296341Sdelphij NID_netscape_cert_type, /* 71 */ 320296341Sdelphij NID_key_usage, /* 83 */ 321296341Sdelphij NID_subject_alt_name, /* 85 */ 322296341Sdelphij NID_basic_constraints, /* 87 */ 323296341Sdelphij NID_certificate_policies, /* 89 */ 324296341Sdelphij NID_ext_key_usage, /* 126 */ 325167612Ssimon#ifndef OPENSSL_NO_RFC3779 326296341Sdelphij NID_sbgp_ipAddrBlock, /* 290 */ 327296341Sdelphij NID_sbgp_autonomousSysNum, /* 291 */ 328167612Ssimon#endif 329296341Sdelphij NID_policy_constraints, /* 401 */ 330296341Sdelphij NID_proxyCertInfo, /* 663 */ 331296341Sdelphij NID_name_constraints, /* 666 */ 332296341Sdelphij NID_policy_mappings, /* 747 */ 333296341Sdelphij NID_inhibit_any_policy /* 748 */ 334296341Sdelphij }; 335109998Smarkm 336296341Sdelphij int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex)); 337109998Smarkm 338296341Sdelphij if (ex_nid == NID_undef) 339296341Sdelphij return 0; 340109998Smarkm 341296341Sdelphij if (OBJ_bsearch_nid(&ex_nid, supported_nids, 342296341Sdelphij sizeof(supported_nids) / sizeof(int))) 343296341Sdelphij return 1; 344296341Sdelphij return 0; 345296341Sdelphij} 346109998Smarkm 347238405Sjkimstatic void setup_dp(X509 *x, DIST_POINT *dp) 348296341Sdelphij{ 349296341Sdelphij X509_NAME *iname = NULL; 350296341Sdelphij int i; 351296341Sdelphij if (dp->reasons) { 352296341Sdelphij if (dp->reasons->length > 0) 353296341Sdelphij dp->dp_reasons = dp->reasons->data[0]; 354296341Sdelphij if (dp->reasons->length > 1) 355296341Sdelphij dp->dp_reasons |= (dp->reasons->data[1] << 8); 356296341Sdelphij dp->dp_reasons &= CRLDP_ALL_REASONS; 357296341Sdelphij } else 358296341Sdelphij dp->dp_reasons = CRLDP_ALL_REASONS; 359296341Sdelphij if (!dp->distpoint || (dp->distpoint->type != 1)) 360296341Sdelphij return; 361296341Sdelphij for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) { 362296341Sdelphij GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i); 363296341Sdelphij if (gen->type == GEN_DIRNAME) { 364296341Sdelphij iname = gen->d.directoryName; 365296341Sdelphij break; 366296341Sdelphij } 367296341Sdelphij } 368296341Sdelphij if (!iname) 369296341Sdelphij iname = X509_get_issuer_name(x); 370238405Sjkim 371296341Sdelphij DIST_POINT_set_dpname(dp->distpoint, iname); 372238405Sjkim 373296341Sdelphij} 374238405Sjkim 375238405Sjkimstatic void setup_crldp(X509 *x) 376296341Sdelphij{ 377296341Sdelphij int i; 378296341Sdelphij x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); 379296341Sdelphij for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) 380296341Sdelphij setup_dp(x, sk_DIST_POINT_value(x->crldp, i)); 381296341Sdelphij} 382238405Sjkim 38359191Skrisstatic void x509v3_cache_extensions(X509 *x) 38459191Skris{ 385296341Sdelphij BASIC_CONSTRAINTS *bs; 386296341Sdelphij PROXY_CERT_INFO_EXTENSION *pci; 387296341Sdelphij ASN1_BIT_STRING *usage; 388296341Sdelphij ASN1_BIT_STRING *ns; 389296341Sdelphij EXTENDED_KEY_USAGE *extusage; 390296341Sdelphij X509_EXTENSION *ex; 391296341Sdelphij 392296341Sdelphij int i; 393296341Sdelphij if (x->ex_flags & EXFLAG_SET) 394296341Sdelphij return; 395109998Smarkm#ifndef OPENSSL_NO_SHA 396296341Sdelphij X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); 39768651Skris#endif 398296341Sdelphij /* Does subject name match issuer ? */ 399296341Sdelphij if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) 400296341Sdelphij x->ex_flags |= EXFLAG_SI; 401296341Sdelphij /* V1 should mean no extensions ... */ 402296341Sdelphij if (!X509_get_version(x)) 403296341Sdelphij x->ex_flags |= EXFLAG_V1; 404296341Sdelphij /* Handle basic constraints */ 405296341Sdelphij if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) { 406296341Sdelphij if (bs->ca) 407296341Sdelphij x->ex_flags |= EXFLAG_CA; 408296341Sdelphij if (bs->pathlen) { 409296341Sdelphij if ((bs->pathlen->type == V_ASN1_NEG_INTEGER) 410296341Sdelphij || !bs->ca) { 411296341Sdelphij x->ex_flags |= EXFLAG_INVALID; 412296341Sdelphij x->ex_pathlen = 0; 413296341Sdelphij } else 414296341Sdelphij x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen); 415296341Sdelphij } else 416296341Sdelphij x->ex_pathlen = -1; 417296341Sdelphij BASIC_CONSTRAINTS_free(bs); 418296341Sdelphij x->ex_flags |= EXFLAG_BCONS; 419296341Sdelphij } 420296341Sdelphij /* Handle proxy certificates */ 421296341Sdelphij if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) { 422296341Sdelphij if (x->ex_flags & EXFLAG_CA 423296341Sdelphij || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0 424296341Sdelphij || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) { 425296341Sdelphij x->ex_flags |= EXFLAG_INVALID; 426296341Sdelphij } 427296341Sdelphij if (pci->pcPathLengthConstraint) { 428296341Sdelphij x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint); 429296341Sdelphij } else 430296341Sdelphij x->ex_pcpathlen = -1; 431296341Sdelphij PROXY_CERT_INFO_EXTENSION_free(pci); 432296341Sdelphij x->ex_flags |= EXFLAG_PROXY; 433296341Sdelphij } 434296341Sdelphij /* Handle key usage */ 435296341Sdelphij if ((usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) { 436296341Sdelphij if (usage->length > 0) { 437296341Sdelphij x->ex_kusage = usage->data[0]; 438296341Sdelphij if (usage->length > 1) 439296341Sdelphij x->ex_kusage |= usage->data[1] << 8; 440296341Sdelphij } else 441296341Sdelphij x->ex_kusage = 0; 442296341Sdelphij x->ex_flags |= EXFLAG_KUSAGE; 443296341Sdelphij ASN1_BIT_STRING_free(usage); 444296341Sdelphij } 445296341Sdelphij x->ex_xkusage = 0; 446296341Sdelphij if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) { 447296341Sdelphij x->ex_flags |= EXFLAG_XKUSAGE; 448296341Sdelphij for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) { 449296341Sdelphij switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) { 450296341Sdelphij case NID_server_auth: 451296341Sdelphij x->ex_xkusage |= XKU_SSL_SERVER; 452296341Sdelphij break; 45359191Skris 454296341Sdelphij case NID_client_auth: 455296341Sdelphij x->ex_xkusage |= XKU_SSL_CLIENT; 456296341Sdelphij break; 45759191Skris 458296341Sdelphij case NID_email_protect: 459296341Sdelphij x->ex_xkusage |= XKU_SMIME; 460296341Sdelphij break; 46159191Skris 462296341Sdelphij case NID_code_sign: 463296341Sdelphij x->ex_xkusage |= XKU_CODE_SIGN; 464296341Sdelphij break; 46559191Skris 466296341Sdelphij case NID_ms_sgc: 467296341Sdelphij case NID_ns_sgc: 468296341Sdelphij x->ex_xkusage |= XKU_SGC; 469296341Sdelphij break; 470109998Smarkm 471296341Sdelphij case NID_OCSP_sign: 472296341Sdelphij x->ex_xkusage |= XKU_OCSP_SIGN; 473296341Sdelphij break; 474109998Smarkm 475296341Sdelphij case NID_time_stamp: 476296341Sdelphij x->ex_xkusage |= XKU_TIMESTAMP; 477296341Sdelphij break; 478111147Snectar 479296341Sdelphij case NID_dvcs: 480296341Sdelphij x->ex_xkusage |= XKU_DVCS; 481296341Sdelphij break; 482296341Sdelphij } 483296341Sdelphij } 484296341Sdelphij sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); 485296341Sdelphij } 48659191Skris 487296341Sdelphij if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) { 488296341Sdelphij if (ns->length > 0) 489296341Sdelphij x->ex_nscert = ns->data[0]; 490296341Sdelphij else 491296341Sdelphij x->ex_nscert = 0; 492296341Sdelphij x->ex_flags |= EXFLAG_NSCERT; 493296341Sdelphij ASN1_BIT_STRING_free(ns); 494296341Sdelphij } 495296341Sdelphij x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL); 496296341Sdelphij x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL); 497296341Sdelphij x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); 498296341Sdelphij x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL); 499296341Sdelphij if (!x->nc && (i != -1)) 500296341Sdelphij x->ex_flags |= EXFLAG_INVALID; 501296341Sdelphij setup_crldp(x); 502238405Sjkim 503167612Ssimon#ifndef OPENSSL_NO_RFC3779 504296341Sdelphij x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL); 505296341Sdelphij x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, 506296341Sdelphij NULL, NULL); 507167612Ssimon#endif 508296341Sdelphij for (i = 0; i < X509_get_ext_count(x); i++) { 509296341Sdelphij ex = X509_get_ext(x, i); 510296341Sdelphij if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) 511296341Sdelphij == NID_freshest_crl) 512296341Sdelphij x->ex_flags |= EXFLAG_FRESHEST; 513296341Sdelphij if (!X509_EXTENSION_get_critical(ex)) 514296341Sdelphij continue; 515296341Sdelphij if (!X509_supported_extension(ex)) { 516296341Sdelphij x->ex_flags |= EXFLAG_CRITICAL; 517296341Sdelphij break; 518296341Sdelphij } 519296341Sdelphij } 520296341Sdelphij x->ex_flags |= EXFLAG_SET; 52159191Skris} 52259191Skris 523296341Sdelphij/*- 524296341Sdelphij * CA checks common to all purposes 52559191Skris * return codes: 52659191Skris * 0 not a CA 52759191Skris * 1 is a CA 52859191Skris * 2 basicConstraints absent so "maybe" a CA 52959191Skris * 3 basicConstraints absent but self signed V1. 530127128Snectar * 4 basicConstraints absent but keyUsage present and keyCertSign asserted. 53159191Skris */ 53259191Skris 53359191Skris#define V1_ROOT (EXFLAG_V1|EXFLAG_SS) 53459191Skris#define ku_reject(x, usage) \ 535296341Sdelphij (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) 53659191Skris#define xku_reject(x, usage) \ 537296341Sdelphij (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage))) 53859191Skris#define ns_reject(x, usage) \ 539296341Sdelphij (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) 54059191Skris 541160814Ssimonstatic int check_ca(const X509 *x) 54259191Skris{ 543296341Sdelphij /* keyUsage if present should allow cert signing */ 544296341Sdelphij if (ku_reject(x, KU_KEY_CERT_SIGN)) 545296341Sdelphij return 0; 546296341Sdelphij if (x->ex_flags & EXFLAG_BCONS) { 547296341Sdelphij if (x->ex_flags & EXFLAG_CA) 548296341Sdelphij return 1; 549296341Sdelphij /* If basicConstraints says not a CA then say so */ 550296341Sdelphij else 551296341Sdelphij return 0; 552296341Sdelphij } else { 553296341Sdelphij /* we support V1 roots for... uh, I don't really know why. */ 554296341Sdelphij if ((x->ex_flags & V1_ROOT) == V1_ROOT) 555296341Sdelphij return 3; 556296341Sdelphij /* 557296341Sdelphij * If key usage present it must have certSign so tolerate it 558296341Sdelphij */ 559296341Sdelphij else if (x->ex_flags & EXFLAG_KUSAGE) 560296341Sdelphij return 4; 561296341Sdelphij /* Older certificates could have Netscape-specific CA types */ 562296341Sdelphij else if (x->ex_flags & EXFLAG_NSCERT && x->ex_nscert & NS_ANY_CA) 563296341Sdelphij return 5; 564296341Sdelphij /* can this still be regarded a CA certificate? I doubt it */ 565296341Sdelphij return 0; 566296341Sdelphij } 56759191Skris} 56859191Skris 569160814Ssimonint X509_check_ca(X509 *x) 570160814Ssimon{ 571296341Sdelphij if (!(x->ex_flags & EXFLAG_SET)) { 572296341Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_X509); 573296341Sdelphij x509v3_cache_extensions(x); 574296341Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_X509); 575296341Sdelphij } 576160814Ssimon 577296341Sdelphij return check_ca(x); 578160814Ssimon} 579160814Ssimon 58068651Skris/* Check SSL CA: common checks for SSL client and server */ 58168651Skrisstatic int check_ssl_ca(const X509 *x) 58268651Skris{ 583296341Sdelphij int ca_ret; 584296341Sdelphij ca_ret = check_ca(x); 585296341Sdelphij if (!ca_ret) 586296341Sdelphij return 0; 587296341Sdelphij /* check nsCertType if present */ 588296341Sdelphij if (ca_ret != 5 || x->ex_nscert & NS_SSL_CA) 589296341Sdelphij return ca_ret; 590296341Sdelphij else 591296341Sdelphij return 0; 59268651Skris} 59359191Skris 594296341Sdelphijstatic int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, 595296341Sdelphij int ca) 59659191Skris{ 597296341Sdelphij if (xku_reject(x, XKU_SSL_CLIENT)) 598296341Sdelphij return 0; 599296341Sdelphij if (ca) 600296341Sdelphij return check_ssl_ca(x); 601296341Sdelphij /* We need to do digital signatures with it */ 602296341Sdelphij if (ku_reject(x, KU_DIGITAL_SIGNATURE)) 603296341Sdelphij return 0; 604296341Sdelphij /* nsCertType if present should allow SSL client use */ 605296341Sdelphij if (ns_reject(x, NS_SSL_CLIENT)) 606296341Sdelphij return 0; 607296341Sdelphij return 1; 60859191Skris} 60959191Skris 610296341Sdelphijstatic int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, 611296341Sdelphij int ca) 61259191Skris{ 613296341Sdelphij if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC)) 614296341Sdelphij return 0; 615296341Sdelphij if (ca) 616296341Sdelphij return check_ssl_ca(x); 61759191Skris 618296341Sdelphij if (ns_reject(x, NS_SSL_SERVER)) 619296341Sdelphij return 0; 620296341Sdelphij /* Now as for keyUsage: we'll at least need to sign OR encipher */ 621296341Sdelphij if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_ENCIPHERMENT)) 622296341Sdelphij return 0; 62359191Skris 624296341Sdelphij return 1; 625296341Sdelphij 62659191Skris} 62759191Skris 628296341Sdelphijstatic int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, 629296341Sdelphij int ca) 63059191Skris{ 631296341Sdelphij int ret; 632296341Sdelphij ret = check_purpose_ssl_server(xp, x, ca); 633296341Sdelphij if (!ret || ca) 634296341Sdelphij return ret; 635296341Sdelphij /* We need to encipher or Netscape complains */ 636296341Sdelphij if (ku_reject(x, KU_KEY_ENCIPHERMENT)) 637296341Sdelphij return 0; 638296341Sdelphij return ret; 63959191Skris} 64059191Skris 64159191Skris/* common S/MIME checks */ 64268651Skrisstatic int purpose_smime(const X509 *x, int ca) 64359191Skris{ 644296341Sdelphij if (xku_reject(x, XKU_SMIME)) 645296341Sdelphij return 0; 646296341Sdelphij if (ca) { 647296341Sdelphij int ca_ret; 648296341Sdelphij ca_ret = check_ca(x); 649296341Sdelphij if (!ca_ret) 650296341Sdelphij return 0; 651296341Sdelphij /* check nsCertType if present */ 652296341Sdelphij if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) 653296341Sdelphij return ca_ret; 654296341Sdelphij else 655296341Sdelphij return 0; 656296341Sdelphij } 657296341Sdelphij if (x->ex_flags & EXFLAG_NSCERT) { 658296341Sdelphij if (x->ex_nscert & NS_SMIME) 659296341Sdelphij return 1; 660296341Sdelphij /* Workaround for some buggy certificates */ 661296341Sdelphij if (x->ex_nscert & NS_SSL_CLIENT) 662296341Sdelphij return 2; 663296341Sdelphij return 0; 664296341Sdelphij } 665296341Sdelphij return 1; 66659191Skris} 66759191Skris 668296341Sdelphijstatic int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, 669296341Sdelphij int ca) 67059191Skris{ 671296341Sdelphij int ret; 672296341Sdelphij ret = purpose_smime(x, ca); 673296341Sdelphij if (!ret || ca) 674296341Sdelphij return ret; 675296341Sdelphij if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION)) 676296341Sdelphij return 0; 677296341Sdelphij return ret; 67859191Skris} 67959191Skris 680296341Sdelphijstatic int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, 681296341Sdelphij int ca) 68259191Skris{ 683296341Sdelphij int ret; 684296341Sdelphij ret = purpose_smime(x, ca); 685296341Sdelphij if (!ret || ca) 686296341Sdelphij return ret; 687296341Sdelphij if (ku_reject(x, KU_KEY_ENCIPHERMENT)) 688296341Sdelphij return 0; 689296341Sdelphij return ret; 69059191Skris} 69159191Skris 692296341Sdelphijstatic int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, 693296341Sdelphij int ca) 69459191Skris{ 695296341Sdelphij if (ca) { 696296341Sdelphij int ca_ret; 697296341Sdelphij if ((ca_ret = check_ca(x)) != 2) 698296341Sdelphij return ca_ret; 699296341Sdelphij else 700296341Sdelphij return 0; 701296341Sdelphij } 702296341Sdelphij if (ku_reject(x, KU_CRL_SIGN)) 703296341Sdelphij return 0; 704296341Sdelphij return 1; 70559191Skris} 70659191Skris 707296341Sdelphij/* 708296341Sdelphij * OCSP helper: this is *not* a full OCSP check. It just checks that each CA 709296341Sdelphij * is valid. Additional checks must be made on the chain. 710109998Smarkm */ 711109998Smarkm 712109998Smarkmstatic int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) 713109998Smarkm{ 714296341Sdelphij /* 715296341Sdelphij * Must be a valid CA. Should we really support the "I don't know" value 716296341Sdelphij * (2)? 717296341Sdelphij */ 718296341Sdelphij if (ca) 719296341Sdelphij return check_ca(x); 720296341Sdelphij /* leaf certificate is checked in OCSP_verify() */ 721296341Sdelphij return 1; 722109998Smarkm} 723109998Smarkm 724238405Sjkimstatic int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, 725296341Sdelphij int ca) 726238405Sjkim{ 727296341Sdelphij int i_ext; 728238405Sjkim 729296341Sdelphij /* If ca is true we must return if this is a valid CA certificate. */ 730296341Sdelphij if (ca) 731296341Sdelphij return check_ca(x); 732238405Sjkim 733296341Sdelphij /* 734296341Sdelphij * Check the optional key usage field: 735296341Sdelphij * if Key Usage is present, it must be one of digitalSignature 736296341Sdelphij * and/or nonRepudiation (other values are not consistent and shall 737296341Sdelphij * be rejected). 738296341Sdelphij */ 739296341Sdelphij if ((x->ex_flags & EXFLAG_KUSAGE) 740296341Sdelphij && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) || 741296341Sdelphij !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)))) 742296341Sdelphij return 0; 743238405Sjkim 744296341Sdelphij /* Only time stamp key usage is permitted and it's required. */ 745296341Sdelphij if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP) 746296341Sdelphij return 0; 747238405Sjkim 748296341Sdelphij /* Extended Key Usage MUST be critical */ 749296341Sdelphij i_ext = X509_get_ext_by_NID((X509 *)x, NID_ext_key_usage, -1); 750296341Sdelphij if (i_ext >= 0) { 751296341Sdelphij X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext); 752296341Sdelphij if (!X509_EXTENSION_get_critical(ext)) 753296341Sdelphij return 0; 754296341Sdelphij } 755238405Sjkim 756296341Sdelphij return 1; 757238405Sjkim} 758238405Sjkim 75968651Skrisstatic int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) 76059191Skris{ 761296341Sdelphij return 1; 76259191Skris} 76368651Skris 764296341Sdelphij/*- 765296341Sdelphij * Various checks to see if one certificate issued the second. 76668651Skris * This can be used to prune a set of possible issuer certificates 76768651Skris * which have been looked up using some simple method such as by 76868651Skris * subject name. 76968651Skris * These are: 77068651Skris * 1. Check issuer_name(subject) == subject_name(issuer) 77168651Skris * 2. If akid(subject) exists check it matches issuer 77268651Skris * 3. If key_usage(issuer) exists check it supports certificate signing 77368651Skris * returns 0 for OK, positive for reason for mismatch, reasons match 77468651Skris * codes for X509_verify_cert() 77568651Skris */ 77668651Skris 77768651Skrisint X509_check_issued(X509 *issuer, X509 *subject) 77868651Skris{ 779296341Sdelphij if (X509_NAME_cmp(X509_get_subject_name(issuer), 780296341Sdelphij X509_get_issuer_name(subject))) 781296341Sdelphij return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; 782296341Sdelphij x509v3_cache_extensions(issuer); 783296341Sdelphij x509v3_cache_extensions(subject); 784238405Sjkim 785296341Sdelphij if (subject->akid) { 786296341Sdelphij int ret = X509_check_akid(issuer, subject->akid); 787296341Sdelphij if (ret != X509_V_OK) 788296341Sdelphij return ret; 789296341Sdelphij } 790238405Sjkim 791296341Sdelphij if (subject->ex_flags & EXFLAG_PROXY) { 792296341Sdelphij if (ku_reject(issuer, KU_DIGITAL_SIGNATURE)) 793296341Sdelphij return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE; 794296341Sdelphij } else if (ku_reject(issuer, KU_KEY_CERT_SIGN)) 795296341Sdelphij return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; 796296341Sdelphij return X509_V_OK; 79768651Skris} 79868651Skris 799238405Sjkimint X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid) 800296341Sdelphij{ 801238405Sjkim 802296341Sdelphij if (!akid) 803296341Sdelphij return X509_V_OK; 804238405Sjkim 805296341Sdelphij /* Check key ids (if present) */ 806296341Sdelphij if (akid->keyid && issuer->skid && 807296341Sdelphij ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid)) 808296341Sdelphij return X509_V_ERR_AKID_SKID_MISMATCH; 809296341Sdelphij /* Check serial number */ 810296341Sdelphij if (akid->serial && 811296341Sdelphij ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial)) 812296341Sdelphij return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; 813296341Sdelphij /* Check issuer name */ 814296341Sdelphij if (akid->issuer) { 815296341Sdelphij /* 816296341Sdelphij * Ugh, for some peculiar reason AKID includes SEQUENCE OF 817296341Sdelphij * GeneralName. So look for a DirName. There may be more than one but 818296341Sdelphij * we only take any notice of the first. 819296341Sdelphij */ 820296341Sdelphij GENERAL_NAMES *gens; 821296341Sdelphij GENERAL_NAME *gen; 822296341Sdelphij X509_NAME *nm = NULL; 823296341Sdelphij int i; 824296341Sdelphij gens = akid->issuer; 825296341Sdelphij for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 826296341Sdelphij gen = sk_GENERAL_NAME_value(gens, i); 827296341Sdelphij if (gen->type == GEN_DIRNAME) { 828296341Sdelphij nm = gen->d.dirn; 829296341Sdelphij break; 830296341Sdelphij } 831296341Sdelphij } 832296341Sdelphij if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer))) 833296341Sdelphij return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; 834296341Sdelphij } 835296341Sdelphij return X509_V_OK; 836296341Sdelphij} 837