1160814Ssimon/* x509_vpm.c */ 2280304Sjkim/* 3280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4280304Sjkim * 2004. 5160814Ssimon */ 6160814Ssimon/* ==================================================================== 7160814Ssimon * Copyright (c) 2004 The OpenSSL Project. All rights reserved. 8160814Ssimon * 9160814Ssimon * Redistribution and use in source and binary forms, with or without 10160814Ssimon * modification, are permitted provided that the following conditions 11160814Ssimon * are met: 12160814Ssimon * 13160814Ssimon * 1. Redistributions of source code must retain the above copyright 14280304Sjkim * notice, this list of conditions and the following disclaimer. 15160814Ssimon * 16160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 17160814Ssimon * notice, this list of conditions and the following disclaimer in 18160814Ssimon * the documentation and/or other materials provided with the 19160814Ssimon * distribution. 20160814Ssimon * 21160814Ssimon * 3. All advertising materials mentioning features or use of this 22160814Ssimon * software must display the following acknowledgment: 23160814Ssimon * "This product includes software developed by the OpenSSL Project 24160814Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25160814Ssimon * 26160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27160814Ssimon * endorse or promote products derived from this software without 28160814Ssimon * prior written permission. For written permission, please contact 29160814Ssimon * licensing@OpenSSL.org. 30160814Ssimon * 31160814Ssimon * 5. Products derived from this software may not be called "OpenSSL" 32160814Ssimon * nor may "OpenSSL" appear in their names without prior written 33160814Ssimon * permission of the OpenSSL Project. 34160814Ssimon * 35160814Ssimon * 6. Redistributions of any form whatsoever must retain the following 36160814Ssimon * acknowledgment: 37160814Ssimon * "This product includes software developed by the OpenSSL Project 38160814Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39160814Ssimon * 40160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43160814Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 52160814Ssimon * ==================================================================== 53160814Ssimon * 54160814Ssimon * This product includes cryptographic software written by Eric Young 55160814Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 56160814Ssimon * Hudson (tjh@cryptsoft.com). 57160814Ssimon * 58160814Ssimon */ 59160814Ssimon 60160814Ssimon#include <stdio.h> 61160814Ssimon 62160814Ssimon#include "cryptlib.h" 63160814Ssimon#include <openssl/crypto.h> 64160814Ssimon#include <openssl/lhash.h> 65160814Ssimon#include <openssl/buffer.h> 66160814Ssimon#include <openssl/x509.h> 67160814Ssimon#include <openssl/x509v3.h> 68160814Ssimon 69160814Ssimon/* X509_VERIFY_PARAM functions */ 70160814Ssimon 71160814Ssimonstatic void x509_verify_param_zero(X509_VERIFY_PARAM *param) 72280304Sjkim{ 73280304Sjkim if (!param) 74280304Sjkim return; 75280304Sjkim param->name = NULL; 76280304Sjkim param->purpose = 0; 77280304Sjkim param->trust = 0; 78280304Sjkim /* 79280304Sjkim * param->inh_flags = X509_VP_FLAG_DEFAULT; 80280304Sjkim */ 81280304Sjkim param->inh_flags = 0; 82280304Sjkim param->flags = 0; 83280304Sjkim param->depth = -1; 84280304Sjkim if (param->policies) { 85280304Sjkim sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); 86280304Sjkim param->policies = NULL; 87280304Sjkim } 88280304Sjkim} 89160814Ssimon 90160814SsimonX509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) 91280304Sjkim{ 92280304Sjkim X509_VERIFY_PARAM *param; 93280304Sjkim param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM)); 94280304Sjkim if (!param) 95280304Sjkim return NULL; 96280304Sjkim memset(param, 0, sizeof(X509_VERIFY_PARAM)); 97280304Sjkim x509_verify_param_zero(param); 98280304Sjkim return param; 99280304Sjkim} 100160814Ssimon 101160814Ssimonvoid X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) 102280304Sjkim{ 103284285Sjkim if (param == NULL) 104284285Sjkim return; 105280304Sjkim x509_verify_param_zero(param); 106280304Sjkim OPENSSL_free(param); 107280304Sjkim} 108160814Ssimon 109280304Sjkim/*- 110280304Sjkim * This function determines how parameters are "inherited" from one structure 111160814Ssimon * to another. There are several different ways this can happen. 112160814Ssimon * 113160814Ssimon * 1. If a child structure needs to have its values initialized from a parent 114160814Ssimon * they are simply copied across. For example SSL_CTX copied to SSL. 115160814Ssimon * 2. If the structure should take on values only if they are currently unset. 116160814Ssimon * For example the values in an SSL structure will take appropriate value 117160814Ssimon * for SSL servers or clients but only if the application has not set new 118160814Ssimon * ones. 119160814Ssimon * 120280304Sjkim * The "inh_flags" field determines how this function behaves. 121160814Ssimon * 122160814Ssimon * Normally any values which are set in the default are not copied from the 123160814Ssimon * destination and verify flags are ORed together. 124160814Ssimon * 125160814Ssimon * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied 126160814Ssimon * to the destination. Effectively the values in "to" become default values 127160814Ssimon * which will be used only if nothing new is set in "from". 128160814Ssimon * 129160814Ssimon * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether 130160814Ssimon * they are set or not. Flags is still Ored though. 131160814Ssimon * 132160814Ssimon * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead 133160814Ssimon * of ORed. 134160814Ssimon * 135160814Ssimon * If X509_VP_FLAG_LOCKED is set then no values are copied. 136160814Ssimon * 137160814Ssimon * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed 138160814Ssimon * after the next call. 139160814Ssimon */ 140160814Ssimon 141160814Ssimon/* Macro to test if a field should be copied from src to dest */ 142160814Ssimon 143160814Ssimon#define test_x509_verify_param_copy(field, def) \ 144280304Sjkim (to_overwrite || \ 145280304Sjkim ((src->field != def) && (to_default || (dest->field == def)))) 146160814Ssimon 147160814Ssimon/* Macro to test and copy a field if necessary */ 148160814Ssimon 149160814Ssimon#define x509_verify_param_copy(field, def) \ 150280304Sjkim if (test_x509_verify_param_copy(field, def)) \ 151280304Sjkim dest->field = src->field 152160814Ssimon 153160814Ssimonint X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, 154280304Sjkim const X509_VERIFY_PARAM *src) 155280304Sjkim{ 156280304Sjkim unsigned long inh_flags; 157280304Sjkim int to_default, to_overwrite; 158280304Sjkim if (!src) 159280304Sjkim return 1; 160280304Sjkim inh_flags = dest->inh_flags | src->inh_flags; 161160814Ssimon 162280304Sjkim if (inh_flags & X509_VP_FLAG_ONCE) 163280304Sjkim dest->inh_flags = 0; 164160814Ssimon 165280304Sjkim if (inh_flags & X509_VP_FLAG_LOCKED) 166280304Sjkim return 1; 167160814Ssimon 168280304Sjkim if (inh_flags & X509_VP_FLAG_DEFAULT) 169280304Sjkim to_default = 1; 170280304Sjkim else 171280304Sjkim to_default = 0; 172160814Ssimon 173280304Sjkim if (inh_flags & X509_VP_FLAG_OVERWRITE) 174280304Sjkim to_overwrite = 1; 175280304Sjkim else 176280304Sjkim to_overwrite = 0; 177160814Ssimon 178280304Sjkim x509_verify_param_copy(purpose, 0); 179280304Sjkim x509_verify_param_copy(trust, 0); 180280304Sjkim x509_verify_param_copy(depth, -1); 181160814Ssimon 182280304Sjkim /* If overwrite or check time not set, copy across */ 183160814Ssimon 184280304Sjkim if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) { 185280304Sjkim dest->check_time = src->check_time; 186280304Sjkim dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME; 187280304Sjkim /* Don't need to copy flag: that is done below */ 188280304Sjkim } 189160814Ssimon 190280304Sjkim if (inh_flags & X509_VP_FLAG_RESET_FLAGS) 191280304Sjkim dest->flags = 0; 192160814Ssimon 193280304Sjkim dest->flags |= src->flags; 194160814Ssimon 195280304Sjkim if (test_x509_verify_param_copy(policies, NULL)) { 196280304Sjkim if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies)) 197280304Sjkim return 0; 198280304Sjkim } 199160814Ssimon 200280304Sjkim return 1; 201280304Sjkim} 202160814Ssimon 203160814Ssimonint X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, 204280304Sjkim const X509_VERIFY_PARAM *from) 205280304Sjkim{ 206280304Sjkim unsigned long save_flags = to->inh_flags; 207280304Sjkim int ret; 208280304Sjkim to->inh_flags |= X509_VP_FLAG_DEFAULT; 209280304Sjkim ret = X509_VERIFY_PARAM_inherit(to, from); 210280304Sjkim to->inh_flags = save_flags; 211280304Sjkim return ret; 212280304Sjkim} 213160814Ssimon 214160814Ssimonint X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name) 215280304Sjkim{ 216280304Sjkim if (param->name) 217280304Sjkim OPENSSL_free(param->name); 218280304Sjkim param->name = BUF_strdup(name); 219280304Sjkim if (param->name) 220280304Sjkim return 1; 221280304Sjkim return 0; 222280304Sjkim} 223160814Ssimon 224160814Ssimonint X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags) 225280304Sjkim{ 226280304Sjkim param->flags |= flags; 227280304Sjkim if (flags & X509_V_FLAG_POLICY_MASK) 228280304Sjkim param->flags |= X509_V_FLAG_POLICY_CHECK; 229280304Sjkim return 1; 230280304Sjkim} 231160814Ssimon 232280304Sjkimint X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, 233280304Sjkim unsigned long flags) 234280304Sjkim{ 235280304Sjkim param->flags &= ~flags; 236280304Sjkim return 1; 237280304Sjkim} 238160814Ssimon 239160814Ssimonunsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param) 240280304Sjkim{ 241280304Sjkim return param->flags; 242280304Sjkim} 243160814Ssimon 244160814Ssimonint X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) 245280304Sjkim{ 246280304Sjkim return X509_PURPOSE_set(¶m->purpose, purpose); 247280304Sjkim} 248160814Ssimon 249160814Ssimonint X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) 250280304Sjkim{ 251280304Sjkim return X509_TRUST_set(¶m->trust, trust); 252280304Sjkim} 253160814Ssimon 254160814Ssimonvoid X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth) 255280304Sjkim{ 256280304Sjkim param->depth = depth; 257280304Sjkim} 258160814Ssimon 259160814Ssimonvoid X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t) 260280304Sjkim{ 261280304Sjkim param->check_time = t; 262280304Sjkim param->flags |= X509_V_FLAG_USE_CHECK_TIME; 263280304Sjkim} 264160814Ssimon 265280304Sjkimint X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, 266280304Sjkim ASN1_OBJECT *policy) 267280304Sjkim{ 268280304Sjkim if (!param->policies) { 269280304Sjkim param->policies = sk_ASN1_OBJECT_new_null(); 270280304Sjkim if (!param->policies) 271280304Sjkim return 0; 272280304Sjkim } 273280304Sjkim if (!sk_ASN1_OBJECT_push(param->policies, policy)) 274280304Sjkim return 0; 275280304Sjkim return 1; 276280304Sjkim} 277160814Ssimon 278280304Sjkimint X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, 279280304Sjkim STACK_OF(ASN1_OBJECT) *policies) 280280304Sjkim{ 281280304Sjkim int i; 282280304Sjkim ASN1_OBJECT *oid, *doid; 283280304Sjkim if (!param) 284280304Sjkim return 0; 285280304Sjkim if (param->policies) 286280304Sjkim sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); 287160814Ssimon 288280304Sjkim if (!policies) { 289280304Sjkim param->policies = NULL; 290280304Sjkim return 1; 291280304Sjkim } 292160814Ssimon 293280304Sjkim param->policies = sk_ASN1_OBJECT_new_null(); 294280304Sjkim if (!param->policies) 295280304Sjkim return 0; 296160814Ssimon 297280304Sjkim for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) { 298280304Sjkim oid = sk_ASN1_OBJECT_value(policies, i); 299280304Sjkim doid = OBJ_dup(oid); 300280304Sjkim if (!doid) 301280304Sjkim return 0; 302280304Sjkim if (!sk_ASN1_OBJECT_push(param->policies, doid)) { 303280304Sjkim ASN1_OBJECT_free(doid); 304280304Sjkim return 0; 305280304Sjkim } 306280304Sjkim } 307280304Sjkim param->flags |= X509_V_FLAG_POLICY_CHECK; 308280304Sjkim return 1; 309280304Sjkim} 310160814Ssimon 311160814Ssimonint X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param) 312280304Sjkim{ 313280304Sjkim return param->depth; 314280304Sjkim} 315160814Ssimon 316280304Sjkim/* 317280304Sjkim * Default verify parameters: these are used for various applications and can 318280304Sjkim * be overridden by the user specified table. NB: the 'name' field *must* be 319280304Sjkim * in alphabetical order because it will be searched using OBJ_search. 320160814Ssimon */ 321160814Ssimon 322160814Ssimonstatic const X509_VERIFY_PARAM default_table[] = { 323280304Sjkim { 324280304Sjkim "default", /* X509 default parameters */ 325280304Sjkim 0, /* Check time */ 326280304Sjkim 0, /* internal flags */ 327280304Sjkim 0, /* flags */ 328280304Sjkim 0, /* purpose */ 329280304Sjkim 0, /* trust */ 330280304Sjkim 100, /* depth */ 331280304Sjkim NULL /* policies */ 332280304Sjkim }, 333280304Sjkim { 334280304Sjkim "pkcs7", /* S/MIME sign parameters */ 335280304Sjkim 0, /* Check time */ 336280304Sjkim 0, /* internal flags */ 337280304Sjkim 0, /* flags */ 338280304Sjkim X509_PURPOSE_SMIME_SIGN, /* purpose */ 339280304Sjkim X509_TRUST_EMAIL, /* trust */ 340280304Sjkim -1, /* depth */ 341280304Sjkim NULL /* policies */ 342280304Sjkim }, 343280304Sjkim { 344280304Sjkim "smime_sign", /* S/MIME sign parameters */ 345280304Sjkim 0, /* Check time */ 346280304Sjkim 0, /* internal flags */ 347280304Sjkim 0, /* flags */ 348280304Sjkim X509_PURPOSE_SMIME_SIGN, /* purpose */ 349280304Sjkim X509_TRUST_EMAIL, /* trust */ 350280304Sjkim -1, /* depth */ 351280304Sjkim NULL /* policies */ 352280304Sjkim }, 353280304Sjkim { 354280304Sjkim "ssl_client", /* SSL/TLS client parameters */ 355280304Sjkim 0, /* Check time */ 356280304Sjkim 0, /* internal flags */ 357280304Sjkim 0, /* flags */ 358280304Sjkim X509_PURPOSE_SSL_CLIENT, /* purpose */ 359280304Sjkim X509_TRUST_SSL_CLIENT, /* trust */ 360280304Sjkim -1, /* depth */ 361280304Sjkim NULL /* policies */ 362280304Sjkim }, 363280304Sjkim { 364280304Sjkim "ssl_server", /* SSL/TLS server parameters */ 365280304Sjkim 0, /* Check time */ 366280304Sjkim 0, /* internal flags */ 367280304Sjkim 0, /* flags */ 368280304Sjkim X509_PURPOSE_SSL_SERVER, /* purpose */ 369280304Sjkim X509_TRUST_SSL_SERVER, /* trust */ 370280304Sjkim -1, /* depth */ 371280304Sjkim NULL /* policies */ 372280304Sjkim } 373280304Sjkim}; 374160814Ssimon 375160814Ssimonstatic STACK_OF(X509_VERIFY_PARAM) *param_table = NULL; 376160814Ssimon 377238405Sjkimstatic int table_cmp(const X509_VERIFY_PARAM *a, const X509_VERIFY_PARAM *b) 378280304Sjkim{ 379280304Sjkim return strcmp(a->name, b->name); 380280304Sjkim} 381238405Sjkim 382280304SjkimDECLARE_OBJ_BSEARCH_CMP_FN(X509_VERIFY_PARAM, X509_VERIFY_PARAM, table); 383280304SjkimIMPLEMENT_OBJ_BSEARCH_CMP_FN(X509_VERIFY_PARAM, X509_VERIFY_PARAM, table); 384160814Ssimon 385280304Sjkimstatic int param_cmp(const X509_VERIFY_PARAM *const *a, 386280304Sjkim const X509_VERIFY_PARAM *const *b) 387280304Sjkim{ 388280304Sjkim return strcmp((*a)->name, (*b)->name); 389280304Sjkim} 390238405Sjkim 391160814Ssimonint X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param) 392280304Sjkim{ 393280304Sjkim int idx; 394280304Sjkim X509_VERIFY_PARAM *ptmp; 395280304Sjkim if (!param_table) { 396280304Sjkim param_table = sk_X509_VERIFY_PARAM_new(param_cmp); 397280304Sjkim if (!param_table) 398280304Sjkim return 0; 399280304Sjkim } else { 400280304Sjkim idx = sk_X509_VERIFY_PARAM_find(param_table, param); 401280304Sjkim if (idx != -1) { 402280304Sjkim ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx); 403280304Sjkim X509_VERIFY_PARAM_free(ptmp); 404280304Sjkim (void)sk_X509_VERIFY_PARAM_delete(param_table, idx); 405280304Sjkim } 406280304Sjkim } 407280304Sjkim if (!sk_X509_VERIFY_PARAM_push(param_table, param)) 408280304Sjkim return 0; 409280304Sjkim return 1; 410280304Sjkim} 411160814Ssimon 412160814Ssimonconst X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name) 413280304Sjkim{ 414280304Sjkim int idx; 415280304Sjkim X509_VERIFY_PARAM pm; 416238405Sjkim 417280304Sjkim pm.name = (char *)name; 418280304Sjkim if (param_table) { 419280304Sjkim idx = sk_X509_VERIFY_PARAM_find(param_table, &pm); 420280304Sjkim if (idx != -1) 421280304Sjkim return sk_X509_VERIFY_PARAM_value(param_table, idx); 422280304Sjkim } 423280304Sjkim return OBJ_bsearch_table(&pm, default_table, 424280304Sjkim sizeof(default_table) / 425280304Sjkim sizeof(X509_VERIFY_PARAM)); 426280304Sjkim} 427160814Ssimon 428160814Ssimonvoid X509_VERIFY_PARAM_table_cleanup(void) 429280304Sjkim{ 430280304Sjkim if (param_table) 431280304Sjkim sk_X509_VERIFY_PARAM_pop_free(param_table, X509_VERIFY_PARAM_free); 432280304Sjkim param_table = NULL; 433280304Sjkim} 434