Fix safestack issues in x509.h
[openssl.git] / crypto / x509 / x509_trs.c
1 /*
2  * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include <openssl/x509v3.h>
13 #include "crypto/x509.h"
14
15 DEFINE_STACK_OF(ASN1_OBJECT)
16
17 static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b);
18 static void trtable_free(X509_TRUST *p);
19
20 static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags);
21 static int trust_1oid(X509_TRUST *trust, X509 *x, int flags);
22 static int trust_compat(X509_TRUST *trust, X509 *x, int flags);
23
24 static int obj_trust(int id, X509 *x, int flags);
25 static int (*default_trust) (int id, X509 *x, int flags) = obj_trust;
26
27 /*
28  * WARNING: the following table should be kept in order of trust and without
29  * any gaps so we can just subtract the minimum trust value to get an index
30  * into the table
31  */
32
33 static X509_TRUST trstandard[] = {
34     {X509_TRUST_COMPAT, 0, trust_compat, "compatible", 0, NULL},
35     {X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth,
36      NULL},
37     {X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Server", NID_server_auth,
38      NULL},
39     {X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect,
40      NULL},
41     {X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, "Object Signer", NID_code_sign,
42      NULL},
43     {X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign,
44      NULL},
45     {X509_TRUST_OCSP_REQUEST, 0, trust_1oid, "OCSP request", NID_ad_OCSP,
46      NULL},
47     {X509_TRUST_TSA, 0, trust_1oidany, "TSA server", NID_time_stamp, NULL}
48 };
49
50 #define X509_TRUST_COUNT        OSSL_NELEM(trstandard)
51
52 static STACK_OF(X509_TRUST) *trtable = NULL;
53
54 static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b)
55 {
56     return (*a)->trust - (*b)->trust;
57 }
58
59 int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *,
60                                                                 int) {
61     int (*oldtrust) (int, X509 *, int);
62     oldtrust = default_trust;
63     default_trust = trust;
64     return oldtrust;
65 }
66
67 int X509_check_trust(X509 *x, int id, int flags)
68 {
69     X509_TRUST *pt;
70     int idx;
71
72     /* We get this as a default value */
73     if (id == X509_TRUST_DEFAULT)
74         return obj_trust(NID_anyExtendedKeyUsage, x,
75                          flags | X509_TRUST_DO_SS_COMPAT);
76     idx = X509_TRUST_get_by_id(id);
77     if (idx == -1)
78         return default_trust(id, x, flags);
79     pt = X509_TRUST_get0(idx);
80     return pt->check_trust(pt, x, flags);
81 }
82
83 int X509_TRUST_get_count(void)
84 {
85     if (!trtable)
86         return X509_TRUST_COUNT;
87     return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT;
88 }
89
90 X509_TRUST *X509_TRUST_get0(int idx)
91 {
92     if (idx < 0)
93         return NULL;
94     if (idx < (int)X509_TRUST_COUNT)
95         return trstandard + idx;
96     return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT);
97 }
98
99 int X509_TRUST_get_by_id(int id)
100 {
101     X509_TRUST tmp;
102     int idx;
103
104     if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX))
105         return id - X509_TRUST_MIN;
106     if (trtable == NULL)
107         return -1;
108     tmp.trust = id;
109     idx = sk_X509_TRUST_find(trtable, &tmp);
110     if (idx < 0)
111         return -1;
112     return idx + X509_TRUST_COUNT;
113 }
114
115 int X509_TRUST_set(int *t, int trust)
116 {
117     if (X509_TRUST_get_by_id(trust) == -1) {
118         X509err(X509_F_X509_TRUST_SET, X509_R_INVALID_TRUST);
119         return 0;
120     }
121     *t = trust;
122     return 1;
123 }
124
125 int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
126                    const char *name, int arg1, void *arg2)
127 {
128     int idx;
129     X509_TRUST *trtmp;
130     /*
131      * This is set according to what we change: application can't set it
132      */
133     flags &= ~X509_TRUST_DYNAMIC;
134     /* This will always be set for application modified trust entries */
135     flags |= X509_TRUST_DYNAMIC_NAME;
136     /* Get existing entry if any */
137     idx = X509_TRUST_get_by_id(id);
138     /* Need a new entry */
139     if (idx == -1) {
140         if ((trtmp = OPENSSL_malloc(sizeof(*trtmp))) == NULL) {
141             X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
142             return 0;
143         }
144         trtmp->flags = X509_TRUST_DYNAMIC;
145     } else
146         trtmp = X509_TRUST_get0(idx);
147
148     /* OPENSSL_free existing name if dynamic */
149     if (trtmp->flags & X509_TRUST_DYNAMIC_NAME)
150         OPENSSL_free(trtmp->name);
151     /* dup supplied name */
152     if ((trtmp->name = OPENSSL_strdup(name)) == NULL) {
153         X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
154         goto err;
155     }
156     /* Keep the dynamic flag of existing entry */
157     trtmp->flags &= X509_TRUST_DYNAMIC;
158     /* Set all other flags */
159     trtmp->flags |= flags;
160
161     trtmp->trust = id;
162     trtmp->check_trust = ck;
163     trtmp->arg1 = arg1;
164     trtmp->arg2 = arg2;
165
166     /* If its a new entry manage the dynamic table */
167     if (idx == -1) {
168         if (trtable == NULL
169             && (trtable = sk_X509_TRUST_new(tr_cmp)) == NULL) {
170             X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
171             goto err;;
172         }
173         if (!sk_X509_TRUST_push(trtable, trtmp)) {
174             X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
175             goto err;
176         }
177     }
178     return 1;
179  err:
180     if (idx == -1) {
181         OPENSSL_free(trtmp->name);
182         OPENSSL_free(trtmp);
183     }
184     return 0;
185 }
186
187 static void trtable_free(X509_TRUST *p)
188 {
189     if (p == NULL)
190         return;
191     if (p->flags & X509_TRUST_DYNAMIC) {
192         if (p->flags & X509_TRUST_DYNAMIC_NAME)
193             OPENSSL_free(p->name);
194         OPENSSL_free(p);
195     }
196 }
197
198 void X509_TRUST_cleanup(void)
199 {
200     sk_X509_TRUST_pop_free(trtable, trtable_free);
201     trtable = NULL;
202 }
203
204 int X509_TRUST_get_flags(const X509_TRUST *xp)
205 {
206     return xp->flags;
207 }
208
209 char *X509_TRUST_get0_name(const X509_TRUST *xp)
210 {
211     return xp->name;
212 }
213
214 int X509_TRUST_get_trust(const X509_TRUST *xp)
215 {
216     return xp->trust;
217 }
218
219 static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags)
220 {
221     /*
222      * Declare the chain verified if the desired trust OID is not rejected in
223      * any auxiliary trust info for this certificate, and the OID is either
224      * expressly trusted, or else either "anyEKU" is trusted, or the
225      * certificate is self-signed.
226      */
227     flags |= X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU;
228     return obj_trust(trust->arg1, x, flags);
229 }
230
231 static int trust_1oid(X509_TRUST *trust, X509 *x, int flags)
232 {
233     /*
234      * Declare the chain verified only if the desired trust OID is not
235      * rejected and is expressly trusted.  Neither "anyEKU" nor "compat"
236      * trust in self-signed certificates apply.
237      */
238     flags &= ~(X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU);
239     return obj_trust(trust->arg1, x, flags);
240 }
241
242 static int trust_compat(X509_TRUST *trust, X509 *x, int flags)
243 {
244     /* Call for side-effect of computing hash and caching extensions */
245     if (X509_check_purpose(x, -1, 0) != 1)
246         return X509_TRUST_UNTRUSTED;
247     if ((flags & X509_TRUST_NO_SS_COMPAT) == 0 && (x->ex_flags & EXFLAG_SS))
248         return X509_TRUST_TRUSTED;
249     else
250         return X509_TRUST_UNTRUSTED;
251 }
252
253 static int obj_trust(int id, X509 *x, int flags)
254 {
255     X509_CERT_AUX *ax = x->aux;
256     int i;
257
258     if (ax && ax->reject) {
259         for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
260             ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->reject, i);
261             int nid = OBJ_obj2nid(obj);
262
263             if (nid == id || (nid == NID_anyExtendedKeyUsage &&
264                 (flags & X509_TRUST_OK_ANY_EKU)))
265                 return X509_TRUST_REJECTED;
266         }
267     }
268
269     if (ax && ax->trust) {
270         for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
271             ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->trust, i);
272             int nid = OBJ_obj2nid(obj);
273
274             if (nid == id || (nid == NID_anyExtendedKeyUsage &&
275                 (flags & X509_TRUST_OK_ANY_EKU)))
276                 return X509_TRUST_TRUSTED;
277         }
278         /*
279          * Reject when explicit trust EKU are set and none match.
280          *
281          * Returning untrusted is enough for for full chains that end in
282          * self-signed roots, because when explicit trust is specified it
283          * suppresses the default blanket trust of self-signed objects.
284          *
285          * But for partial chains, this is not enough, because absent a similar
286          * trust-self-signed policy, non matching EKUs are indistinguishable
287          * from lack of EKU constraints.
288          *
289          * Therefore, failure to match any trusted purpose must trigger an
290          * explicit reject.
291          */
292         return X509_TRUST_REJECTED;
293     }
294
295     if ((flags & X509_TRUST_DO_SS_COMPAT) == 0)
296         return X509_TRUST_UNTRUSTED;
297
298     /*
299      * Not rejected, and there is no list of accepted uses, try compat.
300      */
301     return trust_compat(NULL, x, flags);
302 }