Branch data Line data Source code
1 : : /* v3_purp.c */
2 : : /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 : : * project 2001.
4 : : */
5 : : /* ====================================================================
6 : : * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
7 : : *
8 : : * Redistribution and use in source and binary forms, with or without
9 : : * modification, are permitted provided that the following conditions
10 : : * are met:
11 : : *
12 : : * 1. Redistributions of source code must retain the above copyright
13 : : * notice, this list of conditions and the following disclaimer.
14 : : *
15 : : * 2. Redistributions in binary form must reproduce the above copyright
16 : : * notice, this list of conditions and the following disclaimer in
17 : : * the documentation and/or other materials provided with the
18 : : * distribution.
19 : : *
20 : : * 3. All advertising materials mentioning features or use of this
21 : : * software must display the following acknowledgment:
22 : : * "This product includes software developed by the OpenSSL Project
23 : : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 : : *
25 : : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 : : * endorse or promote products derived from this software without
27 : : * prior written permission. For written permission, please contact
28 : : * licensing@OpenSSL.org.
29 : : *
30 : : * 5. Products derived from this software may not be called "OpenSSL"
31 : : * nor may "OpenSSL" appear in their names without prior written
32 : : * permission of the OpenSSL Project.
33 : : *
34 : : * 6. Redistributions of any form whatsoever must retain the following
35 : : * acknowledgment:
36 : : * "This product includes software developed by the OpenSSL Project
37 : : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 : : *
39 : : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 : : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 : : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 : : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 : : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 : : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 : : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 : : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 : : * OF THE POSSIBILITY OF SUCH DAMAGE.
51 : : * ====================================================================
52 : : *
53 : : * This product includes cryptographic software written by Eric Young
54 : : * (eay@cryptsoft.com). This product includes software written by Tim
55 : : * Hudson (tjh@cryptsoft.com).
56 : : *
57 : : */
58 : :
59 : : #include <stdio.h>
60 : : #include "cryptlib.h"
61 : : #include <openssl/x509v3.h>
62 : : #include <openssl/x509_vfy.h>
63 : :
64 : : static void x509v3_cache_extensions(X509 *x);
65 : :
66 : : static int check_ssl_ca(const X509 *x);
67 : : static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca);
68 : : static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca);
69 : : static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca);
70 : : static int purpose_smime(const X509 *x, int ca);
71 : : static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
72 : : static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca);
73 : : static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
74 : : static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
75 : : static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca);
76 : : static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca);
77 : :
78 : : static int xp_cmp(const X509_PURPOSE * const *a,
79 : : const X509_PURPOSE * const *b);
80 : : static void xptable_free(X509_PURPOSE *p);
81 : :
82 : : static X509_PURPOSE xstandard[] = {
83 : : {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, check_purpose_ssl_client, "SSL client", "sslclient", NULL},
84 : : {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ssl_server, "SSL server", "sslserver", NULL},
85 : : {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL},
86 : : {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, "S/MIME signing", "smimesign", NULL},
87 : : {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL},
88 : : {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, "CRL signing", "crlsign", NULL},
89 : : {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any", NULL},
90 : : {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, "OCSP helper", "ocsphelper", NULL},
91 : : {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0, check_purpose_timestamp_sign, "Time Stamp signing", "timestampsign", NULL},
92 : : };
93 : :
94 : : #define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE))
95 : :
96 : : IMPLEMENT_STACK_OF(X509_PURPOSE)
97 : :
98 : : static STACK_OF(X509_PURPOSE) *xptable = NULL;
99 : :
100 : 0 : static int xp_cmp(const X509_PURPOSE * const *a,
101 : : const X509_PURPOSE * const *b)
102 : : {
103 : 0 : return (*a)->purpose - (*b)->purpose;
104 : : }
105 : :
106 : : /* As much as I'd like to make X509_check_purpose use a "const" X509*
107 : : * I really can't because it does recalculate hashes and do other non-const
108 : : * things. */
109 : 20196 : int X509_check_purpose(X509 *x, int id, int ca)
110 : : {
111 : : int idx;
112 : : const X509_PURPOSE *pt;
113 [ + + ]: 20196 : if(!(x->ex_flags & EXFLAG_SET)) {
114 : 2222 : CRYPTO_w_lock(CRYPTO_LOCK_X509);
115 : 2222 : x509v3_cache_extensions(x);
116 : 2222 : CRYPTO_w_unlock(CRYPTO_LOCK_X509);
117 : : }
118 [ + + ]: 20196 : if(id == -1) return 1;
119 : 625 : idx = X509_PURPOSE_get_by_id(id);
120 [ + - ]: 625 : if(idx == -1) return -1;
121 : 625 : pt = X509_PURPOSE_get0(idx);
122 : 625 : return pt->check_purpose(pt, x, ca);
123 : : }
124 : :
125 : 0 : int X509_PURPOSE_set(int *p, int purpose)
126 : : {
127 [ # # ]: 0 : if(X509_PURPOSE_get_by_id(purpose) == -1) {
128 : 0 : X509V3err(X509V3_F_X509_PURPOSE_SET, X509V3_R_INVALID_PURPOSE);
129 : 0 : return 0;
130 : : }
131 : 0 : *p = purpose;
132 : 0 : return 1;
133 : : }
134 : :
135 : 0 : int X509_PURPOSE_get_count(void)
136 : : {
137 [ # # ]: 0 : if(!xptable) return X509_PURPOSE_COUNT;
138 : 0 : return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT;
139 : : }
140 : :
141 : 658 : X509_PURPOSE * X509_PURPOSE_get0(int idx)
142 : : {
143 [ + - ]: 658 : if(idx < 0) return NULL;
144 [ + - ]: 658 : if(idx < (int)X509_PURPOSE_COUNT) return xstandard + idx;
145 : 0 : return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT);
146 : : }
147 : :
148 : 0 : int X509_PURPOSE_get_by_sname(char *sname)
149 : : {
150 : : int i;
151 : : X509_PURPOSE *xptmp;
152 [ # # ]: 0 : for(i = 0; i < X509_PURPOSE_get_count(); i++) {
153 : 0 : xptmp = X509_PURPOSE_get0(i);
154 [ # # ]: 0 : if(!strcmp(xptmp->sname, sname)) return i;
155 : : }
156 : : return -1;
157 : : }
158 : :
159 : 658 : int X509_PURPOSE_get_by_id(int purpose)
160 : : {
161 : : X509_PURPOSE tmp;
162 : : int idx;
163 [ + - ]: 658 : if((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX))
164 : 658 : return purpose - X509_PURPOSE_MIN;
165 : 0 : tmp.purpose = purpose;
166 [ # # ]: 0 : if(!xptable) return -1;
167 : 0 : idx = sk_X509_PURPOSE_find(xptable, &tmp);
168 [ # # ]: 0 : if(idx == -1) return -1;
169 : 0 : return idx + X509_PURPOSE_COUNT;
170 : : }
171 : :
172 : 0 : int X509_PURPOSE_add(int id, int trust, int flags,
173 : : int (*ck)(const X509_PURPOSE *, const X509 *, int),
174 : : char *name, char *sname, void *arg)
175 : : {
176 : : int idx;
177 : : X509_PURPOSE *ptmp;
178 : : /* This is set according to what we change: application can't set it */
179 : 0 : flags &= ~X509_PURPOSE_DYNAMIC;
180 : : /* This will always be set for application modified trust entries */
181 : 0 : flags |= X509_PURPOSE_DYNAMIC_NAME;
182 : : /* Get existing entry if any */
183 : 0 : idx = X509_PURPOSE_get_by_id(id);
184 : : /* Need a new entry */
185 [ # # ]: 0 : if(idx == -1) {
186 [ # # ]: 0 : if(!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) {
187 : 0 : X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE);
188 : 0 : return 0;
189 : : }
190 : 0 : ptmp->flags = X509_PURPOSE_DYNAMIC;
191 : 0 : } else ptmp = X509_PURPOSE_get0(idx);
192 : :
193 : : /* OPENSSL_free existing name if dynamic */
194 [ # # ]: 0 : if(ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
195 : 0 : OPENSSL_free(ptmp->name);
196 : 0 : OPENSSL_free(ptmp->sname);
197 : : }
198 : : /* dup supplied name */
199 : 0 : ptmp->name = BUF_strdup(name);
200 : 0 : ptmp->sname = BUF_strdup(sname);
201 [ # # ][ # # ]: 0 : if(!ptmp->name || !ptmp->sname) {
202 : 0 : X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE);
203 : 0 : return 0;
204 : : }
205 : : /* Keep the dynamic flag of existing entry */
206 : 0 : ptmp->flags &= X509_PURPOSE_DYNAMIC;
207 : : /* Set all other flags */
208 : 0 : ptmp->flags |= flags;
209 : :
210 : 0 : ptmp->purpose = id;
211 : 0 : ptmp->trust = trust;
212 : 0 : ptmp->check_purpose = ck;
213 : 0 : ptmp->usr_data = arg;
214 : :
215 : : /* If its a new entry manage the dynamic table */
216 [ # # ]: 0 : if(idx == -1) {
217 [ # # ][ # # ]: 0 : if(!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) {
218 : 0 : X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE);
219 : 0 : return 0;
220 : : }
221 [ # # ]: 0 : if (!sk_X509_PURPOSE_push(xptable, ptmp)) {
222 : 0 : X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE);
223 : 0 : return 0;
224 : : }
225 : : }
226 : : return 1;
227 : : }
228 : :
229 : 0 : static void xptable_free(X509_PURPOSE *p)
230 : : {
231 [ # # ]: 0 : if(!p) return;
232 [ # # ]: 0 : if (p->flags & X509_PURPOSE_DYNAMIC)
233 : : {
234 [ # # ]: 0 : if (p->flags & X509_PURPOSE_DYNAMIC_NAME) {
235 : 0 : OPENSSL_free(p->name);
236 : 0 : OPENSSL_free(p->sname);
237 : : }
238 : 0 : OPENSSL_free(p);
239 : : }
240 : : }
241 : :
242 : 0 : void X509_PURPOSE_cleanup(void)
243 : : {
244 : : unsigned int i;
245 : 0 : sk_X509_PURPOSE_pop_free(xptable, xptable_free);
246 [ # # ]: 0 : for(i = 0; i < X509_PURPOSE_COUNT; i++) xptable_free(xstandard + i);
247 : 0 : xptable = NULL;
248 : 0 : }
249 : :
250 : 0 : int X509_PURPOSE_get_id(X509_PURPOSE *xp)
251 : : {
252 : 0 : return xp->purpose;
253 : : }
254 : :
255 : 0 : char *X509_PURPOSE_get0_name(X509_PURPOSE *xp)
256 : : {
257 : 0 : return xp->name;
258 : : }
259 : :
260 : 0 : char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp)
261 : : {
262 : 0 : return xp->sname;
263 : : }
264 : :
265 : 0 : int X509_PURPOSE_get_trust(X509_PURPOSE *xp)
266 : : {
267 : 0 : return xp->trust;
268 : : }
269 : :
270 : 17720 : static int nid_cmp(const int *a, const int *b)
271 : : {
272 : 8860 : return *a - *b;
273 : : }
274 : :
275 : : DECLARE_OBJ_BSEARCH_CMP_FN(int, int, nid);
276 : 23320 : IMPLEMENT_OBJ_BSEARCH_CMP_FN(int, int, nid);
277 : :
278 : 2800 : int X509_supported_extension(X509_EXTENSION *ex)
279 : : {
280 : : /* This table is a list of the NIDs of supported extensions:
281 : : * that is those which are used by the verify process. If
282 : : * an extension is critical and doesn't appear in this list
283 : : * then the verify process will normally reject the certificate.
284 : : * The list must be kept in numerical order because it will be
285 : : * searched using bsearch.
286 : : */
287 : :
288 : : static const int supported_nids[] = {
289 : : NID_netscape_cert_type, /* 71 */
290 : : NID_key_usage, /* 83 */
291 : : NID_subject_alt_name, /* 85 */
292 : : NID_basic_constraints, /* 87 */
293 : : NID_certificate_policies, /* 89 */
294 : : NID_ext_key_usage, /* 126 */
295 : : #ifndef OPENSSL_NO_RFC3779
296 : : NID_sbgp_ipAddrBlock, /* 290 */
297 : : NID_sbgp_autonomousSysNum, /* 291 */
298 : : #endif
299 : : NID_policy_constraints, /* 401 */
300 : : NID_proxyCertInfo, /* 663 */
301 : : NID_name_constraints, /* 666 */
302 : : NID_policy_mappings, /* 747 */
303 : : NID_inhibit_any_policy /* 748 */
304 : : };
305 : :
306 : 2800 : int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
307 : :
308 [ + - ]: 2800 : if (ex_nid == NID_undef)
309 : : return 0;
310 : :
311 [ - + ]: 2800 : if (OBJ_bsearch_nid(&ex_nid, supported_nids,
312 : : sizeof(supported_nids)/sizeof(int)))
313 : : return 1;
314 : 0 : return 0;
315 : : }
316 : :
317 : 14 : static void setup_dp(X509 *x, DIST_POINT *dp)
318 : : {
319 : 14 : X509_NAME *iname = NULL;
320 : : int i;
321 [ - + ]: 14 : if (dp->reasons)
322 : : {
323 [ # # ]: 0 : if (dp->reasons->length > 0)
324 : 0 : dp->dp_reasons = dp->reasons->data[0];
325 [ # # ]: 0 : if (dp->reasons->length > 1)
326 : 0 : dp->dp_reasons |= (dp->reasons->data[1] << 8);
327 : 0 : dp->dp_reasons &= CRLDP_ALL_REASONS;
328 : : }
329 : : else
330 : 14 : dp->dp_reasons = CRLDP_ALL_REASONS;
331 [ + - ][ - + ]: 14 : if (!dp->distpoint || (dp->distpoint->type != 1))
332 : 14 : return;
333 [ # # ]: 0 : for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++)
334 : : {
335 : 0 : GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
336 [ # # ]: 0 : if (gen->type == GEN_DIRNAME)
337 : : {
338 : 0 : iname = gen->d.directoryName;
339 : 0 : break;
340 : : }
341 : : }
342 [ # # ]: 0 : if (!iname)
343 : 0 : iname = X509_get_issuer_name(x);
344 : :
345 : 0 : DIST_POINT_set_dpname(dp->distpoint, iname);
346 : :
347 : : }
348 : :
349 : 3700 : static void setup_crldp(X509 *x)
350 : : {
351 : : int i;
352 : 3700 : x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
353 [ + + ]: 3714 : for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
354 : 14 : setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
355 : 3700 : }
356 : :
357 : 5632 : static void x509v3_cache_extensions(X509 *x)
358 : : {
359 : : BASIC_CONSTRAINTS *bs;
360 : : PROXY_CERT_INFO_EXTENSION *pci;
361 : : ASN1_BIT_STRING *usage;
362 : : ASN1_BIT_STRING *ns;
363 : : EXTENDED_KEY_USAGE *extusage;
364 : : X509_EXTENSION *ex;
365 : :
366 : : int i;
367 [ + + ]: 5632 : if(x->ex_flags & EXFLAG_SET) return;
368 : : #ifndef OPENSSL_NO_SHA
369 : 3700 : X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
370 : : #endif
371 : : /* V1 should mean no extensions ... */
372 [ + + ]: 3700 : if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1;
373 : : /* Handle basic constraints */
374 [ + + ]: 3700 : if((bs=X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) {
375 [ + + ]: 3697 : if(bs->ca) x->ex_flags |= EXFLAG_CA;
376 [ + + ]: 3697 : if(bs->pathlen) {
377 [ + - ]: 654 : if((bs->pathlen->type == V_ASN1_NEG_INTEGER)
378 [ - + ]: 654 : || !bs->ca) {
379 : 0 : x->ex_flags |= EXFLAG_INVALID;
380 : 0 : x->ex_pathlen = 0;
381 : 654 : } else x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
382 : 3043 : } else x->ex_pathlen = -1;
383 : 3697 : BASIC_CONSTRAINTS_free(bs);
384 : 3697 : x->ex_flags |= EXFLAG_BCONS;
385 : : }
386 : : /* Handle proxy certificates */
387 [ + + ]: 3700 : if((pci=X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) {
388 [ + - ]: 1837 : if (x->ex_flags & EXFLAG_CA
389 [ + - ]: 1837 : || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0
390 [ - + ]: 1837 : || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) {
391 : 0 : x->ex_flags |= EXFLAG_INVALID;
392 : : }
393 [ + - ]: 1837 : if (pci->pcPathLengthConstraint) {
394 : 1837 : x->ex_pcpathlen =
395 : 1837 : ASN1_INTEGER_get(pci->pcPathLengthConstraint);
396 : 0 : } else x->ex_pcpathlen = -1;
397 : 1837 : PROXY_CERT_INFO_EXTENSION_free(pci);
398 : 1837 : x->ex_flags |= EXFLAG_PROXY;
399 : : }
400 : : /* Handle key usage */
401 [ + + ]: 3700 : if((usage=X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) {
402 [ + - ]: 1847 : if(usage->length > 0) {
403 : 1847 : x->ex_kusage = usage->data[0];
404 [ - + ]: 1847 : if(usage->length > 1)
405 : 0 : x->ex_kusage |= usage->data[1] << 8;
406 : 0 : } else x->ex_kusage = 0;
407 : 1847 : x->ex_flags |= EXFLAG_KUSAGE;
408 : 1847 : ASN1_BIT_STRING_free(usage);
409 : : }
410 : 3700 : x->ex_xkusage = 0;
411 [ + + ]: 3700 : if((extusage=X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) {
412 : 31 : x->ex_flags |= EXFLAG_XKUSAGE;
413 [ + + ]: 80 : for(i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
414 [ + + - - : 49 : switch(OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage,i))) {
+ + + - -
- ]
415 : : case NID_server_auth:
416 : 9 : x->ex_xkusage |= XKU_SSL_SERVER;
417 : 9 : break;
418 : :
419 : : case NID_client_auth:
420 : 9 : x->ex_xkusage |= XKU_SSL_CLIENT;
421 : 9 : break;
422 : :
423 : : case NID_email_protect:
424 : 0 : x->ex_xkusage |= XKU_SMIME;
425 : 0 : break;
426 : :
427 : : case NID_code_sign:
428 : 0 : x->ex_xkusage |= XKU_CODE_SIGN;
429 : 0 : break;
430 : :
431 : : case NID_ms_sgc:
432 : : case NID_ns_sgc:
433 : 4 : x->ex_xkusage |= XKU_SGC;
434 : 4 : break;
435 : :
436 : : case NID_OCSP_sign:
437 : 15 : x->ex_xkusage |= XKU_OCSP_SIGN;
438 : 15 : break;
439 : :
440 : : case NID_time_stamp:
441 : 12 : x->ex_xkusage |= XKU_TIMESTAMP;
442 : 12 : break;
443 : :
444 : : case NID_dvcs:
445 : 0 : x->ex_xkusage |= XKU_DVCS;
446 : 0 : break;
447 : :
448 : : case NID_anyExtendedKeyUsage:
449 : 0 : x->ex_xkusage |= XKU_ANYEKU;
450 : 0 : break;
451 : : }
452 : : }
453 : 31 : sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
454 : : }
455 : :
456 [ - + ]: 3700 : if((ns=X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) {
457 [ # # ]: 0 : if(ns->length > 0) x->ex_nscert = ns->data[0];
458 : 0 : else x->ex_nscert = 0;
459 : 0 : x->ex_flags |= EXFLAG_NSCERT;
460 : 0 : ASN1_BIT_STRING_free(ns);
461 : : }
462 : 3700 : x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
463 : 3700 : x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
464 : : /* Does subject name match issuer ? */
465 [ + + ]: 3700 : if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)))
466 : : {
467 : 721 : x->ex_flags |= EXFLAG_SI;
468 : : /* If SKID matches AKID also indicate self signed */
469 [ + - ]: 721 : if (X509_check_akid(x, x->akid) == X509_V_OK)
470 : 721 : x->ex_flags |= EXFLAG_SS;
471 : : }
472 : 3700 : x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
473 : 3700 : x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL);
474 [ + - ][ - + ]: 3700 : if (!x->nc && (i != -1))
475 : 0 : x->ex_flags |= EXFLAG_INVALID;
476 : 3700 : setup_crldp(x);
477 : :
478 : : #ifndef OPENSSL_NO_RFC3779
479 : : x->rfc3779_addr =X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL);
480 : : x->rfc3779_asid =X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum,
481 : : NULL, NULL);
482 : : #endif
483 [ + + ]: 20145 : for (i = 0; i < X509_get_ext_count(x); i++)
484 : : {
485 : 16445 : ex = X509_get_ext(x, i);
486 [ - + ]: 16445 : if (OBJ_obj2nid(X509_EXTENSION_get_object(ex))
487 : : == NID_freshest_crl)
488 : 0 : x->ex_flags |= EXFLAG_FRESHEST;
489 [ + + ]: 16445 : if (!X509_EXTENSION_get_critical(ex))
490 : 13645 : continue;
491 [ - + ]: 2800 : if (!X509_supported_extension(ex))
492 : : {
493 : 0 : x->ex_flags |= EXFLAG_CRITICAL;
494 : 0 : break;
495 : : }
496 : : }
497 : 3700 : x->ex_flags |= EXFLAG_SET;
498 : : }
499 : :
500 : : /* CA checks common to all purposes
501 : : * return codes:
502 : : * 0 not a CA
503 : : * 1 is a CA
504 : : * 2 basicConstraints absent so "maybe" a CA
505 : : * 3 basicConstraints absent but self signed V1.
506 : : * 4 basicConstraints absent but keyUsage present and keyCertSign asserted.
507 : : */
508 : :
509 : : #define V1_ROOT (EXFLAG_V1|EXFLAG_SS)
510 : : #define ku_reject(x, usage) \
511 : : (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
512 : : #define xku_reject(x, usage) \
513 : : (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage)))
514 : : #define ns_reject(x, usage) \
515 : : (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
516 : :
517 : 648 : static int check_ca(const X509 *x)
518 : : {
519 : : /* keyUsage if present should allow cert signing */
520 [ + + ][ - + ]: 648 : if(ku_reject(x, KU_KEY_CERT_SIGN)) return 0;
521 [ + + ]: 333 : if(x->ex_flags & EXFLAG_BCONS) {
522 [ + + ]: 332 : if(x->ex_flags & EXFLAG_CA) return 1;
523 : : /* If basicConstraints says not a CA then say so */
524 : 331 : else return 0;
525 : : } else {
526 : : /* we support V1 roots for... uh, I don't really know why. */
527 [ + - ]: 1 : if((x->ex_flags & V1_ROOT) == V1_ROOT) return 3;
528 : : /* If key usage present it must have certSign so tolerate it */
529 [ + - ]: 1 : else if (x->ex_flags & EXFLAG_KUSAGE) return 4;
530 : : /* Older certificates could have Netscape-specific CA types */
531 [ - + ]: 1 : else if (x->ex_flags & EXFLAG_NSCERT
532 [ # # ]: 0 : && x->ex_nscert & NS_ANY_CA) return 5;
533 : : /* can this still be regarded a CA certificate? I doubt it */
534 : 1 : return 0;
535 : : }
536 : : }
537 : :
538 : 648 : int X509_check_ca(X509 *x)
539 : : {
540 [ - + ]: 648 : if(!(x->ex_flags & EXFLAG_SET)) {
541 : 0 : CRYPTO_w_lock(CRYPTO_LOCK_X509);
542 : 0 : x509v3_cache_extensions(x);
543 : 0 : CRYPTO_w_unlock(CRYPTO_LOCK_X509);
544 : : }
545 : :
546 : 648 : return check_ca(x);
547 : : }
548 : :
549 : : /* Check SSL CA: common checks for SSL client and server */
550 : 0 : static int check_ssl_ca(const X509 *x)
551 : : {
552 : : int ca_ret;
553 : 0 : ca_ret = check_ca(x);
554 [ # # ]: 0 : if(!ca_ret) return 0;
555 : : /* check nsCertType if present */
556 [ # # ][ # # ]: 0 : if(ca_ret != 5 || x->ex_nscert & NS_SSL_CA) return ca_ret;
557 : : else return 0;
558 : : }
559 : :
560 : :
561 : 244 : static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca)
562 : : {
563 [ - + ][ # # ]: 244 : if(xku_reject(x,XKU_SSL_CLIENT)) return 0;
564 [ - + ]: 244 : if(ca) return check_ssl_ca(x);
565 : : /* We need to do digital signatures or key agreement */
566 [ + + ][ + - ]: 244 : if(ku_reject(x,KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT)) return 0;
567 : : /* nsCertType if present should allow SSL client use */
568 [ - + ][ # # ]: 244 : if(ns_reject(x, NS_SSL_CLIENT)) return 0;
569 : 244 : return 1;
570 : : }
571 : : /* Key usage needed for TLS/SSL server: digital signature, encipherment or
572 : : * key agreement. The ssl code can check this more thoroughly for individual
573 : : * key types.
574 : : */
575 : : #define KU_TLS \
576 : : KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT
577 : :
578 : 272 : static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca)
579 : : {
580 [ - + ][ # # ]: 272 : if(xku_reject(x,XKU_SSL_SERVER|XKU_SGC)) return 0;
581 [ - + ]: 272 : if(ca) return check_ssl_ca(x);
582 : :
583 [ - + ][ # # ]: 272 : if(ns_reject(x, NS_SSL_SERVER)) return 0;
584 [ + + ][ + - ]: 272 : if(ku_reject(x, KU_TLS)) return 0;
585 : :
586 : 272 : return 1;
587 : :
588 : : }
589 : :
590 : 0 : static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca)
591 : : {
592 : : int ret;
593 : 0 : ret = check_purpose_ssl_server(xp, x, ca);
594 [ # # ]: 0 : if(!ret || ca) return ret;
595 : : /* We need to encipher or Netscape complains */
596 [ # # ][ # # ]: 0 : if(ku_reject(x, KU_KEY_ENCIPHERMENT)) return 0;
597 : 0 : return ret;
598 : : }
599 : :
600 : : /* common S/MIME checks */
601 : 85 : static int purpose_smime(const X509 *x, int ca)
602 : : {
603 [ - + ][ # # ]: 85 : if(xku_reject(x,XKU_SMIME)) return 0;
604 [ - + ]: 85 : if(ca) {
605 : : int ca_ret;
606 : 0 : ca_ret = check_ca(x);
607 [ # # ]: 0 : if(!ca_ret) return 0;
608 : : /* check nsCertType if present */
609 [ # # ][ # # ]: 0 : if(ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) return ca_ret;
610 : : else return 0;
611 : : }
612 [ - + ]: 85 : if(x->ex_flags & EXFLAG_NSCERT) {
613 [ # # ]: 0 : if(x->ex_nscert & NS_SMIME) return 1;
614 : : /* Workaround for some buggy certificates */
615 [ # # ]: 0 : if(x->ex_nscert & NS_SSL_CLIENT) return 2;
616 : 0 : return 0;
617 : : }
618 : : return 1;
619 : : }
620 : :
621 : 85 : static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
622 : : {
623 : : int ret;
624 : 85 : ret = purpose_smime(x, ca);
625 [ + - ]: 85 : if(!ret || ca) return ret;
626 [ + - ][ + - ]: 85 : if(ku_reject(x, KU_DIGITAL_SIGNATURE|KU_NON_REPUDIATION)) return 0;
627 : 85 : return ret;
628 : : }
629 : :
630 : 0 : static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca)
631 : : {
632 : : int ret;
633 : 0 : ret = purpose_smime(x, ca);
634 [ # # ]: 0 : if(!ret || ca) return ret;
635 [ # # ][ # # ]: 0 : if(ku_reject(x, KU_KEY_ENCIPHERMENT)) return 0;
636 : 0 : return ret;
637 : : }
638 : :
639 : 0 : static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
640 : : {
641 [ # # ]: 0 : if(ca) {
642 : : int ca_ret;
643 [ # # ]: 0 : if((ca_ret = check_ca(x)) != 2) return ca_ret;
644 : : else return 0;
645 : : }
646 [ # # ][ # # ]: 0 : if(ku_reject(x, KU_CRL_SIGN)) return 0;
647 : 0 : return 1;
648 : : }
649 : :
650 : : /* OCSP helper: this is *not* a full OCSP check. It just checks that
651 : : * each CA is valid. Additional checks must be made on the chain.
652 : : */
653 : :
654 : 12 : static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca)
655 : : {
656 : : /* Must be a valid CA. Should we really support the "I don't know"
657 : : value (2)? */
658 [ - + ]: 12 : if(ca) return check_ca(x);
659 : : /* leaf certificate is checked in OCSP_verify() */
660 : : return 1;
661 : : }
662 : :
663 : 12 : static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
664 : : int ca)
665 : : {
666 : : int i_ext;
667 : :
668 : : /* If ca is true we must return if this is a valid CA certificate. */
669 [ - + ]: 12 : if (ca) return check_ca(x);
670 : :
671 : : /*
672 : : * Check the optional key usage field:
673 : : * if Key Usage is present, it must be one of digitalSignature
674 : : * and/or nonRepudiation (other values are not consistent and shall
675 : : * be rejected).
676 : : */
677 [ + - ]: 12 : if ((x->ex_flags & EXFLAG_KUSAGE)
678 [ + - ][ + - ]: 12 : && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) ||
679 : 12 : !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE))))
680 : : return 0;
681 : :
682 : : /* Only time stamp key usage is permitted and it's required. */
683 [ + - ][ + - ]: 12 : if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP)
684 : : return 0;
685 : :
686 : : /* Extended Key Usage MUST be critical */
687 : 12 : i_ext = X509_get_ext_by_NID((X509 *) x, NID_ext_key_usage, -1);
688 [ + - ]: 12 : if (i_ext >= 0)
689 : : {
690 : 12 : X509_EXTENSION *ext = X509_get_ext((X509 *) x, i_ext);
691 [ + - ]: 12 : if (!X509_EXTENSION_get_critical(ext))
692 : : return 0;
693 : : }
694 : :
695 : : return 1;
696 : : }
697 : :
698 : 0 : static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca)
699 : : {
700 : 0 : return 1;
701 : : }
702 : :
703 : : /* Various checks to see if one certificate issued the second.
704 : : * This can be used to prune a set of possible issuer certificates
705 : : * which have been looked up using some simple method such as by
706 : : * subject name.
707 : : * These are:
708 : : * 1. Check issuer_name(subject) == subject_name(issuer)
709 : : * 2. If akid(subject) exists check it matches issuer
710 : : * 3. If key_usage(issuer) exists check it supports certificate signing
711 : : * returns 0 for OK, positive for reason for mismatch, reasons match
712 : : * codes for X509_verify_cert()
713 : : */
714 : :
715 : 2160 : int X509_check_issued(X509 *issuer, X509 *subject)
716 : : {
717 [ + + ]: 2160 : if(X509_NAME_cmp(X509_get_subject_name(issuer),
718 : 2160 : X509_get_issuer_name(subject)))
719 : : return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
720 : 1705 : x509v3_cache_extensions(issuer);
721 : 1705 : x509v3_cache_extensions(subject);
722 : :
723 [ + + ]: 1705 : if(subject->akid)
724 : : {
725 : 1695 : int ret = X509_check_akid(issuer, subject->akid);
726 [ + - ]: 1695 : if (ret != X509_V_OK)
727 : : return ret;
728 : : }
729 : :
730 [ + + ]: 1705 : if(subject->ex_flags & EXFLAG_PROXY)
731 : : {
732 [ + + ][ + - ]: 765 : if(ku_reject(issuer, KU_DIGITAL_SIGNATURE))
733 : : return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE;
734 : : }
735 [ + + ][ + - ]: 940 : else if(ku_reject(issuer, KU_KEY_CERT_SIGN))
736 : : return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
737 : 1705 : return X509_V_OK;
738 : : }
739 : :
740 : 2416 : int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid)
741 : : {
742 : :
743 [ + + ]: 2416 : if(!akid)
744 : : return X509_V_OK;
745 : :
746 : : /* Check key ids (if present) */
747 [ + - ]: 4812 : if(akid->keyid && issuer->skid &&
[ + - + - ]
748 : 2406 : ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid) )
749 : : return X509_V_ERR_AKID_SKID_MISMATCH;
750 : : /* Check serial number */
751 [ + + + - ]: 4670 : if(akid->serial &&
752 : 2264 : ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial))
753 : : return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
754 : : /* Check issuer name */
755 [ + + ]: 2406 : if(akid->issuer)
756 : : {
757 : : /* Ugh, for some peculiar reason AKID includes
758 : : * SEQUENCE OF GeneralName. So look for a DirName.
759 : : * There may be more than one but we only take any
760 : : * notice of the first.
761 : : */
762 : : GENERAL_NAMES *gens;
763 : : GENERAL_NAME *gen;
764 : : X509_NAME *nm = NULL;
765 : : int i;
766 : : gens = akid->issuer;
767 [ + - ]: 2264 : for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
768 : : {
769 : 2264 : gen = sk_GENERAL_NAME_value(gens, i);
770 [ + - ]: 2264 : if(gen->type == GEN_DIRNAME)
771 : : {
772 : 2264 : nm = gen->d.dirn;
773 : 2264 : break;
774 : : }
775 : : }
776 [ + - ][ + - ]: 2264 : if(nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
777 : : return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
778 : : }
779 : : return X509_V_OK;
780 : : }
781 : :
|