159191Skris/* x509_trs.c */ 2280297Sjkim/* 3280297Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4280297Sjkim * 1999. 559191Skris */ 659191Skris/* ==================================================================== 759191Skris * Copyright (c) 1999 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 14280297Sjkim * 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> 6359191Skris 64280297Sjkimstatic int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b); 6559191Skrisstatic void trtable_free(X509_TRUST *p); 6659191Skris 6759191Skrisstatic int trust_1oidany(X509_TRUST *trust, X509 *x, int flags); 68109998Smarkmstatic int trust_1oid(X509_TRUST *trust, X509 *x, int flags); 6959191Skrisstatic int trust_compat(X509_TRUST *trust, X509 *x, int flags); 7059191Skris 7159191Skrisstatic int obj_trust(int id, X509 *x, int flags); 72280297Sjkimstatic int (*default_trust) (int id, X509 *x, int flags) = obj_trust; 7359191Skris 74280297Sjkim/* 75280297Sjkim * WARNING: the following table should be kept in order of trust and without 76280297Sjkim * any gaps so we can just subtract the minimum trust value to get an index 77280297Sjkim * into the table 7859191Skris */ 7959191Skris 8059191Skrisstatic X509_TRUST trstandard[] = { 81280297Sjkim {X509_TRUST_COMPAT, 0, trust_compat, "compatible", 0, NULL}, 82280297Sjkim {X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth, 83280297Sjkim NULL}, 84280297Sjkim {X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Server", NID_server_auth, 85280297Sjkim NULL}, 86280297Sjkim {X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect, 87280297Sjkim NULL}, 88280297Sjkim {X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, "Object Signer", NID_code_sign, 89280297Sjkim NULL}, 90280297Sjkim {X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign, 91280297Sjkim NULL}, 92280297Sjkim {X509_TRUST_OCSP_REQUEST, 0, trust_1oid, "OCSP request", NID_ad_OCSP, 93280297Sjkim NULL}, 94280297Sjkim {X509_TRUST_TSA, 0, trust_1oidany, "TSA server", NID_time_stamp, NULL} 9559191Skris}; 9659191Skris 97280297Sjkim#define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST)) 9859191Skris 9959191SkrisIMPLEMENT_STACK_OF(X509_TRUST) 10059191Skris 10159191Skrisstatic STACK_OF(X509_TRUST) *trtable = NULL; 10259191Skris 103280297Sjkimstatic int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b) 10459191Skris{ 105280297Sjkim return (*a)->trust - (*b)->trust; 10659191Skris} 10759191Skris 108280297Sjkimint (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *, 109280297Sjkim int) { 110280297Sjkim int (*oldtrust) (int, X509 *, int); 111280297Sjkim oldtrust = default_trust; 112280297Sjkim default_trust = trust; 113280297Sjkim return oldtrust; 11459191Skris} 11559191Skris 11659191Skrisint X509_check_trust(X509 *x, int id, int flags) 11759191Skris{ 118280297Sjkim X509_TRUST *pt; 119280297Sjkim int idx; 120280297Sjkim if (id == -1) 121280297Sjkim return 1; 122290207Sjkim /* We get this as a default value */ 123290207Sjkim if (id == 0) { 124290207Sjkim int rv; 125290207Sjkim rv = obj_trust(NID_anyExtendedKeyUsage, x, 0); 126290207Sjkim if (rv != X509_TRUST_UNTRUSTED) 127290207Sjkim return rv; 128290207Sjkim return trust_compat(NULL, x, 0); 129290207Sjkim } 130280297Sjkim idx = X509_TRUST_get_by_id(id); 131280297Sjkim if (idx == -1) 132280297Sjkim return default_trust(id, x, flags); 133280297Sjkim pt = X509_TRUST_get0(idx); 134280297Sjkim return pt->check_trust(pt, x, flags); 13559191Skris} 13659191Skris 13759191Skrisint X509_TRUST_get_count(void) 13859191Skris{ 139280297Sjkim if (!trtable) 140280297Sjkim return X509_TRUST_COUNT; 141280297Sjkim return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT; 14259191Skris} 14359191Skris 144280297SjkimX509_TRUST *X509_TRUST_get0(int idx) 14559191Skris{ 146280297Sjkim if (idx < 0) 147280297Sjkim return NULL; 148280297Sjkim if (idx < (int)X509_TRUST_COUNT) 149280297Sjkim return trstandard + idx; 150280297Sjkim return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT); 15159191Skris} 15259191Skris 15359191Skrisint X509_TRUST_get_by_id(int id) 15459191Skris{ 155280297Sjkim X509_TRUST tmp; 156280297Sjkim int idx; 157280297Sjkim if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX)) 158280297Sjkim return id - X509_TRUST_MIN; 159280297Sjkim tmp.trust = id; 160280297Sjkim if (!trtable) 161280297Sjkim return -1; 162280297Sjkim idx = sk_X509_TRUST_find(trtable, &tmp); 163280297Sjkim if (idx == -1) 164280297Sjkim return -1; 165280297Sjkim return idx + X509_TRUST_COUNT; 16659191Skris} 16759191Skris 168109998Smarkmint X509_TRUST_set(int *t, int trust) 169109998Smarkm{ 170280297Sjkim if (X509_TRUST_get_by_id(trust) == -1) { 171280297Sjkim X509err(X509_F_X509_TRUST_SET, X509_R_INVALID_TRUST); 172280297Sjkim return 0; 173280297Sjkim } 174280297Sjkim *t = trust; 175280297Sjkim return 1; 176109998Smarkm} 177109998Smarkm 178280297Sjkimint X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), 179280297Sjkim char *name, int arg1, void *arg2) 18059191Skris{ 181280297Sjkim int idx; 182280297Sjkim X509_TRUST *trtmp; 183280297Sjkim /* 184280297Sjkim * This is set according to what we change: application can't set it 185280297Sjkim */ 186280297Sjkim flags &= ~X509_TRUST_DYNAMIC; 187280297Sjkim /* This will always be set for application modified trust entries */ 188280297Sjkim flags |= X509_TRUST_DYNAMIC_NAME; 189280297Sjkim /* Get existing entry if any */ 190280297Sjkim idx = X509_TRUST_get_by_id(id); 191280297Sjkim /* Need a new entry */ 192280297Sjkim if (idx == -1) { 193280297Sjkim if (!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) { 194280297Sjkim X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); 195280297Sjkim return 0; 196280297Sjkim } 197280297Sjkim trtmp->flags = X509_TRUST_DYNAMIC; 198280297Sjkim } else 199280297Sjkim trtmp = X509_TRUST_get0(idx); 20059191Skris 201280297Sjkim /* OPENSSL_free existing name if dynamic */ 202280297Sjkim if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) 203280297Sjkim OPENSSL_free(trtmp->name); 204280297Sjkim /* dup supplied name */ 205280297Sjkim if (!(trtmp->name = BUF_strdup(name))) { 206280297Sjkim X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); 207280297Sjkim return 0; 208280297Sjkim } 209280297Sjkim /* Keep the dynamic flag of existing entry */ 210280297Sjkim trtmp->flags &= X509_TRUST_DYNAMIC; 211280297Sjkim /* Set all other flags */ 212280297Sjkim trtmp->flags |= flags; 21359191Skris 214280297Sjkim trtmp->trust = id; 215280297Sjkim trtmp->check_trust = ck; 216280297Sjkim trtmp->arg1 = arg1; 217280297Sjkim trtmp->arg2 = arg2; 21859191Skris 219280297Sjkim /* If its a new entry manage the dynamic table */ 220280297Sjkim if (idx == -1) { 221280297Sjkim if (!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) { 222280297Sjkim X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); 223280297Sjkim return 0; 224280297Sjkim } 225280297Sjkim if (!sk_X509_TRUST_push(trtable, trtmp)) { 226280297Sjkim X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); 227280297Sjkim return 0; 228280297Sjkim } 229280297Sjkim } 230280297Sjkim return 1; 23159191Skris} 23259191Skris 23359191Skrisstatic void trtable_free(X509_TRUST *p) 234280297Sjkim{ 235280297Sjkim if (!p) 236280297Sjkim return; 237280297Sjkim if (p->flags & X509_TRUST_DYNAMIC) { 238280297Sjkim if (p->flags & X509_TRUST_DYNAMIC_NAME) 239280297Sjkim OPENSSL_free(p->name); 240280297Sjkim OPENSSL_free(p); 241280297Sjkim } 242280297Sjkim} 24359191Skris 24459191Skrisvoid X509_TRUST_cleanup(void) 24559191Skris{ 246280297Sjkim unsigned int i; 247280297Sjkim for (i = 0; i < X509_TRUST_COUNT; i++) 248280297Sjkim trtable_free(trstandard + i); 249280297Sjkim sk_X509_TRUST_pop_free(trtable, trtable_free); 250280297Sjkim trtable = NULL; 25159191Skris} 25259191Skris 25359191Skrisint X509_TRUST_get_flags(X509_TRUST *xp) 25459191Skris{ 255280297Sjkim return xp->flags; 25659191Skris} 25759191Skris 25859191Skrischar *X509_TRUST_get0_name(X509_TRUST *xp) 25959191Skris{ 260280297Sjkim return xp->name; 26159191Skris} 26259191Skris 26359191Skrisint X509_TRUST_get_trust(X509_TRUST *xp) 26459191Skris{ 265280297Sjkim return xp->trust; 26659191Skris} 26759191Skris 26859191Skrisstatic int trust_1oidany(X509_TRUST *trust, X509 *x, int flags) 26959191Skris{ 270280297Sjkim if (x->aux && (x->aux->trust || x->aux->reject)) 271280297Sjkim return obj_trust(trust->arg1, x, flags); 272280297Sjkim /* 273280297Sjkim * we don't have any trust settings: for compatibility we return trusted 274280297Sjkim * if it is self signed 275280297Sjkim */ 276280297Sjkim return trust_compat(trust, x, flags); 27759191Skris} 27859191Skris 279109998Smarkmstatic int trust_1oid(X509_TRUST *trust, X509 *x, int flags) 280109998Smarkm{ 281280297Sjkim if (x->aux) 282280297Sjkim return obj_trust(trust->arg1, x, flags); 283280297Sjkim return X509_TRUST_UNTRUSTED; 284109998Smarkm} 285109998Smarkm 28659191Skrisstatic int trust_compat(X509_TRUST *trust, X509 *x, int flags) 28759191Skris{ 288280297Sjkim X509_check_purpose(x, -1, 0); 289280297Sjkim if (x->ex_flags & EXFLAG_SS) 290280297Sjkim return X509_TRUST_TRUSTED; 291280297Sjkim else 292280297Sjkim return X509_TRUST_UNTRUSTED; 29359191Skris} 29459191Skris 29559191Skrisstatic int obj_trust(int id, X509 *x, int flags) 29659191Skris{ 297280297Sjkim ASN1_OBJECT *obj; 298280297Sjkim int i; 299280297Sjkim X509_CERT_AUX *ax; 300280297Sjkim ax = x->aux; 301280297Sjkim if (!ax) 302280297Sjkim return X509_TRUST_UNTRUSTED; 303280297Sjkim if (ax->reject) { 304280297Sjkim for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) { 305280297Sjkim obj = sk_ASN1_OBJECT_value(ax->reject, i); 306280297Sjkim if (OBJ_obj2nid(obj) == id) 307280297Sjkim return X509_TRUST_REJECTED; 308280297Sjkim } 309280297Sjkim } 310280297Sjkim if (ax->trust) { 311280297Sjkim for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) { 312280297Sjkim obj = sk_ASN1_OBJECT_value(ax->trust, i); 313280297Sjkim if (OBJ_obj2nid(obj) == id) 314280297Sjkim return X509_TRUST_TRUSTED; 315280297Sjkim } 316280297Sjkim } 317280297Sjkim return X509_TRUST_UNTRUSTED; 31859191Skris} 319