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