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