159191Skris/* v3_purp.c */ 2296465Sdelphij/* 3296465Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4296465Sdelphij * 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 14296465Sdelphij * 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); 68296465Sdelphijstatic int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, 69296465Sdelphij int ca); 70296465Sdelphijstatic int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, 71296465Sdelphij int ca); 72296465Sdelphijstatic int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, 73296465Sdelphij int ca); 7468651Skrisstatic int purpose_smime(const X509 *x, int ca); 75296465Sdelphijstatic int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, 76296465Sdelphij int ca); 77296465Sdelphijstatic int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, 78296465Sdelphij int ca); 79296465Sdelphijstatic int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, 80296465Sdelphij int ca); 8168651Skrisstatic int no_check(const X509_PURPOSE *xp, const X509 *x, int ca); 82109998Smarkmstatic int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca); 8359191Skris 84296465Sdelphijstatic int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b); 8559191Skrisstatic void xptable_free(X509_PURPOSE *p); 8659191Skris 8759191Skrisstatic X509_PURPOSE xstandard[] = { 88296465Sdelphij {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, 89296465Sdelphij check_purpose_ssl_client, "SSL client", "sslclient", NULL}, 90296465Sdelphij {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, 91296465Sdelphij check_purpose_ssl_server, "SSL server", "sslserver", NULL}, 92296465Sdelphij {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, 93296465Sdelphij check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL}, 94296465Sdelphij {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, 95296465Sdelphij "S/MIME signing", "smimesign", NULL}, 96296465Sdelphij {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, 97296465Sdelphij check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL}, 98296465Sdelphij {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, 99296465Sdelphij "CRL signing", "crlsign", NULL}, 100296465Sdelphij {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any", 101296465Sdelphij NULL}, 102296465Sdelphij {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, 103296465Sdelphij "OCSP helper", "ocsphelper", NULL}, 10459191Skris}; 10559191Skris 10659191Skris#define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE)) 10759191Skris 10859191SkrisIMPLEMENT_STACK_OF(X509_PURPOSE) 10959191Skris 11059191Skrisstatic STACK_OF(X509_PURPOSE) *xptable = NULL; 11159191Skris 112296465Sdelphijstatic int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b) 11359191Skris{ 114296465Sdelphij return (*a)->purpose - (*b)->purpose; 11559191Skris} 11659191Skris 117296465Sdelphij/* 118296465Sdelphij * As much as I'd like to make X509_check_purpose use a "const" X509* I 119296465Sdelphij * really can't because it does recalculate hashes and do other non-const 120296465Sdelphij * things. 121296465Sdelphij */ 12259191Skrisint X509_check_purpose(X509 *x, int id, int ca) 12359191Skris{ 124296465Sdelphij int idx; 125296465Sdelphij const X509_PURPOSE *pt; 126296465Sdelphij if (!(x->ex_flags & EXFLAG_SET)) { 127296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_X509); 128296465Sdelphij x509v3_cache_extensions(x); 129296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_X509); 130296465Sdelphij } 131296465Sdelphij if (id == -1) 132296465Sdelphij return 1; 133296465Sdelphij idx = X509_PURPOSE_get_by_id(id); 134296465Sdelphij if (idx == -1) 135296465Sdelphij return -1; 136296465Sdelphij pt = X509_PURPOSE_get0(idx); 137296465Sdelphij return pt->check_purpose(pt, x, ca); 13859191Skris} 13959191Skris 140109998Smarkmint X509_PURPOSE_set(int *p, int purpose) 141109998Smarkm{ 142296465Sdelphij if (X509_PURPOSE_get_by_id(purpose) == -1) { 143296465Sdelphij X509V3err(X509V3_F_X509_PURPOSE_SET, X509V3_R_INVALID_PURPOSE); 144296465Sdelphij return 0; 145296465Sdelphij } 146296465Sdelphij *p = purpose; 147296465Sdelphij return 1; 148109998Smarkm} 149109998Smarkm 15059191Skrisint X509_PURPOSE_get_count(void) 15159191Skris{ 152296465Sdelphij if (!xptable) 153296465Sdelphij return X509_PURPOSE_COUNT; 154296465Sdelphij return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT; 15559191Skris} 15659191Skris 157296465SdelphijX509_PURPOSE *X509_PURPOSE_get0(int idx) 15859191Skris{ 159296465Sdelphij if (idx < 0) 160296465Sdelphij return NULL; 161296465Sdelphij if (idx < (int)X509_PURPOSE_COUNT) 162296465Sdelphij return xstandard + idx; 163296465Sdelphij return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT); 16459191Skris} 16559191Skris 16659191Skrisint X509_PURPOSE_get_by_sname(char *sname) 16759191Skris{ 168296465Sdelphij int i; 169296465Sdelphij X509_PURPOSE *xptmp; 170296465Sdelphij for (i = 0; i < X509_PURPOSE_get_count(); i++) { 171296465Sdelphij xptmp = X509_PURPOSE_get0(i); 172296465Sdelphij if (!strcmp(xptmp->sname, sname)) 173296465Sdelphij return i; 174296465Sdelphij } 175296465Sdelphij return -1; 17659191Skris} 17759191Skris 17859191Skrisint X509_PURPOSE_get_by_id(int purpose) 17959191Skris{ 180296465Sdelphij X509_PURPOSE tmp; 181296465Sdelphij int idx; 182296465Sdelphij if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX)) 183296465Sdelphij return purpose - X509_PURPOSE_MIN; 184296465Sdelphij tmp.purpose = purpose; 185296465Sdelphij if (!xptable) 186296465Sdelphij return -1; 187296465Sdelphij idx = sk_X509_PURPOSE_find(xptable, &tmp); 188296465Sdelphij if (idx == -1) 189296465Sdelphij return -1; 190296465Sdelphij return idx + X509_PURPOSE_COUNT; 19159191Skris} 19259191Skris 19359191Skrisint X509_PURPOSE_add(int id, int trust, int flags, 194296465Sdelphij int (*ck) (const X509_PURPOSE *, const X509 *, int), 195296465Sdelphij char *name, char *sname, void *arg) 19659191Skris{ 197296465Sdelphij int idx; 198296465Sdelphij X509_PURPOSE *ptmp; 199296465Sdelphij /* 200296465Sdelphij * This is set according to what we change: application can't set it 201296465Sdelphij */ 202296465Sdelphij flags &= ~X509_PURPOSE_DYNAMIC; 203296465Sdelphij /* This will always be set for application modified trust entries */ 204296465Sdelphij flags |= X509_PURPOSE_DYNAMIC_NAME; 205296465Sdelphij /* Get existing entry if any */ 206296465Sdelphij idx = X509_PURPOSE_get_by_id(id); 207296465Sdelphij /* Need a new entry */ 208296465Sdelphij if (idx == -1) { 209296465Sdelphij if (!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) { 210296465Sdelphij X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); 211296465Sdelphij return 0; 212296465Sdelphij } 213296465Sdelphij ptmp->flags = X509_PURPOSE_DYNAMIC; 214296465Sdelphij } else 215296465Sdelphij ptmp = X509_PURPOSE_get0(idx); 21659191Skris 217296465Sdelphij /* OPENSSL_free existing name if dynamic */ 218296465Sdelphij if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { 219296465Sdelphij OPENSSL_free(ptmp->name); 220296465Sdelphij OPENSSL_free(ptmp->sname); 221296465Sdelphij } 222296465Sdelphij /* dup supplied name */ 223296465Sdelphij ptmp->name = BUF_strdup(name); 224296465Sdelphij ptmp->sname = BUF_strdup(sname); 225296465Sdelphij if (!ptmp->name || !ptmp->sname) { 226296465Sdelphij X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); 227296465Sdelphij return 0; 228296465Sdelphij } 229296465Sdelphij /* Keep the dynamic flag of existing entry */ 230296465Sdelphij ptmp->flags &= X509_PURPOSE_DYNAMIC; 231296465Sdelphij /* Set all other flags */ 232296465Sdelphij ptmp->flags |= flags; 23359191Skris 234296465Sdelphij ptmp->purpose = id; 235296465Sdelphij ptmp->trust = trust; 236296465Sdelphij ptmp->check_purpose = ck; 237296465Sdelphij ptmp->usr_data = arg; 23859191Skris 239296465Sdelphij /* If its a new entry manage the dynamic table */ 240296465Sdelphij if (idx == -1) { 241296465Sdelphij if (!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) { 242296465Sdelphij X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); 243296465Sdelphij return 0; 244296465Sdelphij } 245296465Sdelphij if (!sk_X509_PURPOSE_push(xptable, ptmp)) { 246296465Sdelphij X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); 247296465Sdelphij return 0; 248296465Sdelphij } 249296465Sdelphij } 250296465Sdelphij return 1; 25159191Skris} 25259191Skris 25359191Skrisstatic void xptable_free(X509_PURPOSE *p) 254296465Sdelphij{ 255296465Sdelphij if (!p) 256296465Sdelphij return; 257296465Sdelphij if (p->flags & X509_PURPOSE_DYNAMIC) { 258296465Sdelphij if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { 259296465Sdelphij OPENSSL_free(p->name); 260296465Sdelphij OPENSSL_free(p->sname); 261296465Sdelphij } 262296465Sdelphij OPENSSL_free(p); 263296465Sdelphij } 264296465Sdelphij} 26559191Skris 26659191Skrisvoid X509_PURPOSE_cleanup(void) 26759191Skris{ 268296465Sdelphij unsigned int i; 269296465Sdelphij sk_X509_PURPOSE_pop_free(xptable, xptable_free); 270296465Sdelphij for (i = 0; i < X509_PURPOSE_COUNT; i++) 271296465Sdelphij xptable_free(xstandard + i); 272296465Sdelphij xptable = NULL; 27359191Skris} 27459191Skris 27559191Skrisint X509_PURPOSE_get_id(X509_PURPOSE *xp) 27659191Skris{ 277296465Sdelphij return xp->purpose; 27859191Skris} 27959191Skris 28059191Skrischar *X509_PURPOSE_get0_name(X509_PURPOSE *xp) 28159191Skris{ 282296465Sdelphij return xp->name; 28359191Skris} 28459191Skris 28559191Skrischar *X509_PURPOSE_get0_sname(X509_PURPOSE *xp) 28659191Skris{ 287296465Sdelphij return xp->sname; 28859191Skris} 28959191Skris 29059191Skrisint X509_PURPOSE_get_trust(X509_PURPOSE *xp) 29159191Skris{ 292296465Sdelphij return xp->trust; 29359191Skris} 29459191Skris 295109998Smarkmstatic int nid_cmp(int *a, int *b) 296296465Sdelphij{ 297296465Sdelphij return *a - *b; 298296465Sdelphij} 299109998Smarkm 300109998Smarkmint X509_supported_extension(X509_EXTENSION *ex) 301296465Sdelphij{ 302296465Sdelphij /* 303296465Sdelphij * This table is a list of the NIDs of supported extensions: that is 304296465Sdelphij * those which are used by the verify process. If an extension is 305296465Sdelphij * critical and doesn't appear in this list then the verify process will 306296465Sdelphij * normally reject the certificate. The list must be kept in numerical 307296465Sdelphij * order because it will be searched using bsearch. 308296465Sdelphij */ 309109998Smarkm 310296465Sdelphij static int supported_nids[] = { 311296465Sdelphij NID_netscape_cert_type, /* 71 */ 312296465Sdelphij NID_key_usage, /* 83 */ 313296465Sdelphij NID_subject_alt_name, /* 85 */ 314296465Sdelphij NID_basic_constraints, /* 87 */ 315296465Sdelphij NID_certificate_policies, /* 89 */ 316296465Sdelphij NID_ext_key_usage, /* 126 */ 317167612Ssimon#ifndef OPENSSL_NO_RFC3779 318296465Sdelphij NID_sbgp_ipAddrBlock, /* 290 */ 319296465Sdelphij NID_sbgp_autonomousSysNum, /* 291 */ 320167612Ssimon#endif 321296465Sdelphij NID_policy_constraints, /* 401 */ 322296465Sdelphij NID_proxyCertInfo, /* 661 */ 323296465Sdelphij NID_inhibit_any_policy /* 748 */ 324296465Sdelphij }; 325109998Smarkm 326296465Sdelphij int ex_nid; 327109998Smarkm 328296465Sdelphij ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex)); 329109998Smarkm 330296465Sdelphij if (ex_nid == NID_undef) 331296465Sdelphij return 0; 332109998Smarkm 333296465Sdelphij if (OBJ_bsearch((char *)&ex_nid, (char *)supported_nids, 334296465Sdelphij sizeof(supported_nids) / sizeof(int), sizeof(int), 335296465Sdelphij (int (*)(const void *, const void *))nid_cmp)) 336296465Sdelphij return 1; 337296465Sdelphij return 0; 338296465Sdelphij} 339109998Smarkm 34059191Skrisstatic void x509v3_cache_extensions(X509 *x) 34159191Skris{ 342296465Sdelphij BASIC_CONSTRAINTS *bs; 343296465Sdelphij PROXY_CERT_INFO_EXTENSION *pci; 344296465Sdelphij ASN1_BIT_STRING *usage; 345296465Sdelphij ASN1_BIT_STRING *ns; 346296465Sdelphij EXTENDED_KEY_USAGE *extusage; 347296465Sdelphij X509_EXTENSION *ex; 348296465Sdelphij 349296465Sdelphij int i; 350296465Sdelphij if (x->ex_flags & EXFLAG_SET) 351296465Sdelphij return; 352109998Smarkm#ifndef OPENSSL_NO_SHA 353296465Sdelphij X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); 35468651Skris#endif 355296465Sdelphij /* Does subject name match issuer ? */ 356296465Sdelphij if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) 357296465Sdelphij x->ex_flags |= EXFLAG_SI; 358296465Sdelphij /* V1 should mean no extensions ... */ 359296465Sdelphij if (!X509_get_version(x)) 360296465Sdelphij x->ex_flags |= EXFLAG_V1; 361296465Sdelphij /* Handle basic constraints */ 362296465Sdelphij if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) { 363296465Sdelphij if (bs->ca) 364296465Sdelphij x->ex_flags |= EXFLAG_CA; 365296465Sdelphij if (bs->pathlen) { 366296465Sdelphij if ((bs->pathlen->type == V_ASN1_NEG_INTEGER) 367296465Sdelphij || !bs->ca) { 368296465Sdelphij x->ex_flags |= EXFLAG_INVALID; 369296465Sdelphij x->ex_pathlen = 0; 370296465Sdelphij } else 371296465Sdelphij x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen); 372296465Sdelphij } else 373296465Sdelphij x->ex_pathlen = -1; 374296465Sdelphij BASIC_CONSTRAINTS_free(bs); 375296465Sdelphij x->ex_flags |= EXFLAG_BCONS; 376296465Sdelphij } 377296465Sdelphij /* Handle proxy certificates */ 378296465Sdelphij if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) { 379296465Sdelphij if (x->ex_flags & EXFLAG_CA 380296465Sdelphij || X509_get_ext_by_NID(x, NID_subject_alt_name, 0) >= 0 381296465Sdelphij || X509_get_ext_by_NID(x, NID_issuer_alt_name, 0) >= 0) { 382296465Sdelphij x->ex_flags |= EXFLAG_INVALID; 383296465Sdelphij } 384296465Sdelphij if (pci->pcPathLengthConstraint) { 385296465Sdelphij x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint); 386296465Sdelphij } else 387296465Sdelphij x->ex_pcpathlen = -1; 388296465Sdelphij PROXY_CERT_INFO_EXTENSION_free(pci); 389296465Sdelphij x->ex_flags |= EXFLAG_PROXY; 390296465Sdelphij } 391296465Sdelphij /* Handle key usage */ 392296465Sdelphij if ((usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) { 393296465Sdelphij if (usage->length > 0) { 394296465Sdelphij x->ex_kusage = usage->data[0]; 395296465Sdelphij if (usage->length > 1) 396296465Sdelphij x->ex_kusage |= usage->data[1] << 8; 397296465Sdelphij } else 398296465Sdelphij x->ex_kusage = 0; 399296465Sdelphij x->ex_flags |= EXFLAG_KUSAGE; 400296465Sdelphij ASN1_BIT_STRING_free(usage); 401296465Sdelphij } 402296465Sdelphij x->ex_xkusage = 0; 403296465Sdelphij if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) { 404296465Sdelphij x->ex_flags |= EXFLAG_XKUSAGE; 405296465Sdelphij for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) { 406296465Sdelphij switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) { 407296465Sdelphij case NID_server_auth: 408296465Sdelphij x->ex_xkusage |= XKU_SSL_SERVER; 409296465Sdelphij break; 41059191Skris 411296465Sdelphij case NID_client_auth: 412296465Sdelphij x->ex_xkusage |= XKU_SSL_CLIENT; 413296465Sdelphij break; 41459191Skris 415296465Sdelphij case NID_email_protect: 416296465Sdelphij x->ex_xkusage |= XKU_SMIME; 417296465Sdelphij break; 41859191Skris 419296465Sdelphij case NID_code_sign: 420296465Sdelphij x->ex_xkusage |= XKU_CODE_SIGN; 421296465Sdelphij break; 42259191Skris 423296465Sdelphij case NID_ms_sgc: 424296465Sdelphij case NID_ns_sgc: 425296465Sdelphij x->ex_xkusage |= XKU_SGC; 426296465Sdelphij break; 427109998Smarkm 428296465Sdelphij case NID_OCSP_sign: 429296465Sdelphij x->ex_xkusage |= XKU_OCSP_SIGN; 430296465Sdelphij break; 431109998Smarkm 432296465Sdelphij case NID_time_stamp: 433296465Sdelphij x->ex_xkusage |= XKU_TIMESTAMP; 434296465Sdelphij break; 435111147Snectar 436296465Sdelphij case NID_dvcs: 437296465Sdelphij x->ex_xkusage |= XKU_DVCS; 438296465Sdelphij break; 439296465Sdelphij } 440296465Sdelphij } 441296465Sdelphij sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); 442296465Sdelphij } 44359191Skris 444296465Sdelphij if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) { 445296465Sdelphij if (ns->length > 0) 446296465Sdelphij x->ex_nscert = ns->data[0]; 447296465Sdelphij else 448296465Sdelphij x->ex_nscert = 0; 449296465Sdelphij x->ex_flags |= EXFLAG_NSCERT; 450296465Sdelphij ASN1_BIT_STRING_free(ns); 451296465Sdelphij } 452296465Sdelphij x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL); 453296465Sdelphij x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL); 454167612Ssimon#ifndef OPENSSL_NO_RFC3779 455296465Sdelphij x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL); 456296465Sdelphij x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, 457296465Sdelphij NULL, NULL); 458167612Ssimon#endif 459296465Sdelphij for (i = 0; i < X509_get_ext_count(x); i++) { 460296465Sdelphij ex = X509_get_ext(x, i); 461296465Sdelphij if (!X509_EXTENSION_get_critical(ex)) 462296465Sdelphij continue; 463296465Sdelphij if (!X509_supported_extension(ex)) { 464296465Sdelphij x->ex_flags |= EXFLAG_CRITICAL; 465296465Sdelphij break; 466296465Sdelphij } 467296465Sdelphij } 468296465Sdelphij x->ex_flags |= EXFLAG_SET; 46959191Skris} 47059191Skris 471296465Sdelphij/*- 472296465Sdelphij * CA checks common to all purposes 47359191Skris * return codes: 47459191Skris * 0 not a CA 47559191Skris * 1 is a CA 47659191Skris * 2 basicConstraints absent so "maybe" a CA 47759191Skris * 3 basicConstraints absent but self signed V1. 478127128Snectar * 4 basicConstraints absent but keyUsage present and keyCertSign asserted. 47959191Skris */ 48059191Skris 48159191Skris#define V1_ROOT (EXFLAG_V1|EXFLAG_SS) 48259191Skris#define ku_reject(x, usage) \ 483296465Sdelphij (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) 48459191Skris#define xku_reject(x, usage) \ 485296465Sdelphij (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage))) 48659191Skris#define ns_reject(x, usage) \ 487296465Sdelphij (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) 48859191Skris 489160814Ssimonstatic int check_ca(const X509 *x) 49059191Skris{ 491296465Sdelphij /* keyUsage if present should allow cert signing */ 492296465Sdelphij if (ku_reject(x, KU_KEY_CERT_SIGN)) 493296465Sdelphij return 0; 494296465Sdelphij if (x->ex_flags & EXFLAG_BCONS) { 495296465Sdelphij if (x->ex_flags & EXFLAG_CA) 496296465Sdelphij return 1; 497296465Sdelphij /* If basicConstraints says not a CA then say so */ 498296465Sdelphij else 499296465Sdelphij return 0; 500296465Sdelphij } else { 501296465Sdelphij /* we support V1 roots for... uh, I don't really know why. */ 502296465Sdelphij if ((x->ex_flags & V1_ROOT) == V1_ROOT) 503296465Sdelphij return 3; 504296465Sdelphij /* 505296465Sdelphij * If key usage present it must have certSign so tolerate it 506296465Sdelphij */ 507296465Sdelphij else if (x->ex_flags & EXFLAG_KUSAGE) 508296465Sdelphij return 4; 509296465Sdelphij /* Older certificates could have Netscape-specific CA types */ 510296465Sdelphij else if (x->ex_flags & EXFLAG_NSCERT && x->ex_nscert & NS_ANY_CA) 511296465Sdelphij return 5; 512296465Sdelphij /* can this still be regarded a CA certificate? I doubt it */ 513296465Sdelphij return 0; 514296465Sdelphij } 51559191Skris} 51659191Skris 517160814Ssimonint X509_check_ca(X509 *x) 518160814Ssimon{ 519296465Sdelphij if (!(x->ex_flags & EXFLAG_SET)) { 520296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_X509); 521296465Sdelphij x509v3_cache_extensions(x); 522296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_X509); 523296465Sdelphij } 524160814Ssimon 525296465Sdelphij return check_ca(x); 526160814Ssimon} 527160814Ssimon 52868651Skris/* Check SSL CA: common checks for SSL client and server */ 52968651Skrisstatic int check_ssl_ca(const X509 *x) 53068651Skris{ 531296465Sdelphij int ca_ret; 532296465Sdelphij ca_ret = check_ca(x); 533296465Sdelphij if (!ca_ret) 534296465Sdelphij return 0; 535296465Sdelphij /* check nsCertType if present */ 536296465Sdelphij if (ca_ret != 5 || x->ex_nscert & NS_SSL_CA) 537296465Sdelphij return ca_ret; 538296465Sdelphij else 539296465Sdelphij return 0; 54068651Skris} 54159191Skris 542296465Sdelphijstatic int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, 543296465Sdelphij int ca) 54459191Skris{ 545296465Sdelphij if (xku_reject(x, XKU_SSL_CLIENT)) 546296465Sdelphij return 0; 547296465Sdelphij if (ca) 548296465Sdelphij return check_ssl_ca(x); 549296465Sdelphij /* We need to do digital signatures with it */ 550296465Sdelphij if (ku_reject(x, KU_DIGITAL_SIGNATURE)) 551296465Sdelphij return 0; 552296465Sdelphij /* nsCertType if present should allow SSL client use */ 553296465Sdelphij if (ns_reject(x, NS_SSL_CLIENT)) 554296465Sdelphij return 0; 555296465Sdelphij return 1; 55659191Skris} 55759191Skris 558296465Sdelphijstatic int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, 559296465Sdelphij int ca) 56059191Skris{ 561296465Sdelphij if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC)) 562296465Sdelphij return 0; 563296465Sdelphij if (ca) 564296465Sdelphij return check_ssl_ca(x); 56559191Skris 566296465Sdelphij if (ns_reject(x, NS_SSL_SERVER)) 567296465Sdelphij return 0; 568296465Sdelphij /* Now as for keyUsage: we'll at least need to sign OR encipher */ 569296465Sdelphij if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_ENCIPHERMENT)) 570296465Sdelphij return 0; 57159191Skris 572296465Sdelphij return 1; 573296465Sdelphij 57459191Skris} 57559191Skris 576296465Sdelphijstatic int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, 577296465Sdelphij int ca) 57859191Skris{ 579296465Sdelphij int ret; 580296465Sdelphij ret = check_purpose_ssl_server(xp, x, ca); 581296465Sdelphij if (!ret || ca) 582296465Sdelphij return ret; 583296465Sdelphij /* We need to encipher or Netscape complains */ 584296465Sdelphij if (ku_reject(x, KU_KEY_ENCIPHERMENT)) 585296465Sdelphij return 0; 586296465Sdelphij return ret; 58759191Skris} 58859191Skris 58959191Skris/* common S/MIME checks */ 59068651Skrisstatic int purpose_smime(const X509 *x, int ca) 59159191Skris{ 592296465Sdelphij if (xku_reject(x, XKU_SMIME)) 593296465Sdelphij return 0; 594296465Sdelphij if (ca) { 595296465Sdelphij int ca_ret; 596296465Sdelphij ca_ret = check_ca(x); 597296465Sdelphij if (!ca_ret) 598296465Sdelphij return 0; 599296465Sdelphij /* check nsCertType if present */ 600296465Sdelphij if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) 601296465Sdelphij return ca_ret; 602296465Sdelphij else 603296465Sdelphij return 0; 604296465Sdelphij } 605296465Sdelphij if (x->ex_flags & EXFLAG_NSCERT) { 606296465Sdelphij if (x->ex_nscert & NS_SMIME) 607296465Sdelphij return 1; 608296465Sdelphij /* Workaround for some buggy certificates */ 609296465Sdelphij if (x->ex_nscert & NS_SSL_CLIENT) 610296465Sdelphij return 2; 611296465Sdelphij return 0; 612296465Sdelphij } 613296465Sdelphij return 1; 61459191Skris} 61559191Skris 616296465Sdelphijstatic int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, 617296465Sdelphij int ca) 61859191Skris{ 619296465Sdelphij int ret; 620296465Sdelphij ret = purpose_smime(x, ca); 621296465Sdelphij if (!ret || ca) 622296465Sdelphij return ret; 623296465Sdelphij if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION)) 624296465Sdelphij return 0; 625296465Sdelphij return ret; 62659191Skris} 62759191Skris 628296465Sdelphijstatic int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, 629296465Sdelphij int ca) 63059191Skris{ 631296465Sdelphij int ret; 632296465Sdelphij ret = purpose_smime(x, ca); 633296465Sdelphij if (!ret || ca) 634296465Sdelphij return ret; 635296465Sdelphij if (ku_reject(x, KU_KEY_ENCIPHERMENT)) 636296465Sdelphij return 0; 637296465Sdelphij return ret; 63859191Skris} 63959191Skris 640296465Sdelphijstatic int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, 641296465Sdelphij int ca) 64259191Skris{ 643296465Sdelphij if (ca) { 644296465Sdelphij int ca_ret; 645296465Sdelphij if ((ca_ret = check_ca(x)) != 2) 646296465Sdelphij return ca_ret; 647296465Sdelphij else 648296465Sdelphij return 0; 649296465Sdelphij } 650296465Sdelphij if (ku_reject(x, KU_CRL_SIGN)) 651296465Sdelphij return 0; 652296465Sdelphij return 1; 65359191Skris} 65459191Skris 655296465Sdelphij/* 656296465Sdelphij * OCSP helper: this is *not* a full OCSP check. It just checks that each CA 657296465Sdelphij * is valid. Additional checks must be made on the chain. 658109998Smarkm */ 659109998Smarkm 660109998Smarkmstatic int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) 661109998Smarkm{ 662296465Sdelphij /* 663296465Sdelphij * Must be a valid CA. Should we really support the "I don't know" value 664296465Sdelphij * (2)? 665296465Sdelphij */ 666296465Sdelphij if (ca) 667296465Sdelphij return check_ca(x); 668296465Sdelphij /* leaf certificate is checked in OCSP_verify() */ 669296465Sdelphij return 1; 670109998Smarkm} 671109998Smarkm 67268651Skrisstatic int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) 67359191Skris{ 674296465Sdelphij return 1; 67559191Skris} 67668651Skris 677296465Sdelphij/*- 678296465Sdelphij * Various checks to see if one certificate issued the second. 67968651Skris * This can be used to prune a set of possible issuer certificates 68068651Skris * which have been looked up using some simple method such as by 68168651Skris * subject name. 68268651Skris * These are: 68368651Skris * 1. Check issuer_name(subject) == subject_name(issuer) 68468651Skris * 2. If akid(subject) exists check it matches issuer 68568651Skris * 3. If key_usage(issuer) exists check it supports certificate signing 68668651Skris * returns 0 for OK, positive for reason for mismatch, reasons match 68768651Skris * codes for X509_verify_cert() 68868651Skris */ 68968651Skris 69068651Skrisint X509_check_issued(X509 *issuer, X509 *subject) 69168651Skris{ 692296465Sdelphij if (X509_NAME_cmp(X509_get_subject_name(issuer), 693296465Sdelphij X509_get_issuer_name(subject))) 694296465Sdelphij return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; 695296465Sdelphij x509v3_cache_extensions(issuer); 696296465Sdelphij x509v3_cache_extensions(subject); 697296465Sdelphij if (subject->akid) { 698296465Sdelphij /* Check key ids (if present) */ 699296465Sdelphij if (subject->akid->keyid && issuer->skid && 700296465Sdelphij ASN1_OCTET_STRING_cmp(subject->akid->keyid, issuer->skid)) 701296465Sdelphij return X509_V_ERR_AKID_SKID_MISMATCH; 702296465Sdelphij /* Check serial number */ 703296465Sdelphij if (subject->akid->serial && 704296465Sdelphij ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), 705296465Sdelphij subject->akid->serial)) 706296465Sdelphij return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; 707296465Sdelphij /* Check issuer name */ 708296465Sdelphij if (subject->akid->issuer) { 709296465Sdelphij /* 710296465Sdelphij * Ugh, for some peculiar reason AKID includes SEQUENCE OF 711296465Sdelphij * GeneralName. So look for a DirName. There may be more than one 712296465Sdelphij * but we only take any notice of the first. 713296465Sdelphij */ 714296465Sdelphij GENERAL_NAMES *gens; 715296465Sdelphij GENERAL_NAME *gen; 716296465Sdelphij X509_NAME *nm = NULL; 717296465Sdelphij int i; 718296465Sdelphij gens = subject->akid->issuer; 719296465Sdelphij for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 720296465Sdelphij gen = sk_GENERAL_NAME_value(gens, i); 721296465Sdelphij if (gen->type == GEN_DIRNAME) { 722296465Sdelphij nm = gen->d.dirn; 723296465Sdelphij break; 724296465Sdelphij } 725296465Sdelphij } 726296465Sdelphij if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer))) 727296465Sdelphij return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; 728296465Sdelphij } 729296465Sdelphij } 730296465Sdelphij if (subject->ex_flags & EXFLAG_PROXY) { 731296465Sdelphij if (ku_reject(issuer, KU_DIGITAL_SIGNATURE)) 732296465Sdelphij return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE; 733296465Sdelphij } else if (ku_reject(issuer, KU_KEY_CERT_SIGN)) 734296465Sdelphij return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; 735296465Sdelphij return X509_V_OK; 73668651Skris} 737