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