1*75e21034Sbeck /* $OpenBSD: x509_purp.c,v 1.43 2024/07/12 18:15:10 beck Exp $ */
2e500e238Sjsing /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3e500e238Sjsing * project 2001.
4e500e238Sjsing */
5e500e238Sjsing /* ====================================================================
6e500e238Sjsing * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
7e500e238Sjsing *
8e500e238Sjsing * Redistribution and use in source and binary forms, with or without
9e500e238Sjsing * modification, are permitted provided that the following conditions
10e500e238Sjsing * are met:
11e500e238Sjsing *
12e500e238Sjsing * 1. Redistributions of source code must retain the above copyright
13e500e238Sjsing * notice, this list of conditions and the following disclaimer.
14e500e238Sjsing *
15e500e238Sjsing * 2. Redistributions in binary form must reproduce the above copyright
16e500e238Sjsing * notice, this list of conditions and the following disclaimer in
17e500e238Sjsing * the documentation and/or other materials provided with the
18e500e238Sjsing * distribution.
19e500e238Sjsing *
20e500e238Sjsing * 3. All advertising materials mentioning features or use of this
21e500e238Sjsing * software must display the following acknowledgment:
22e500e238Sjsing * "This product includes software developed by the OpenSSL Project
23e500e238Sjsing * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24e500e238Sjsing *
25e500e238Sjsing * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26e500e238Sjsing * endorse or promote products derived from this software without
27e500e238Sjsing * prior written permission. For written permission, please contact
28e500e238Sjsing * licensing@OpenSSL.org.
29e500e238Sjsing *
30e500e238Sjsing * 5. Products derived from this software may not be called "OpenSSL"
31e500e238Sjsing * nor may "OpenSSL" appear in their names without prior written
32e500e238Sjsing * permission of the OpenSSL Project.
33e500e238Sjsing *
34e500e238Sjsing * 6. Redistributions of any form whatsoever must retain the following
35e500e238Sjsing * acknowledgment:
36e500e238Sjsing * "This product includes software developed by the OpenSSL Project
37e500e238Sjsing * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38e500e238Sjsing *
39e500e238Sjsing * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40e500e238Sjsing * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41e500e238Sjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42e500e238Sjsing * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43e500e238Sjsing * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44e500e238Sjsing * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45e500e238Sjsing * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46e500e238Sjsing * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47e500e238Sjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48e500e238Sjsing * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49e500e238Sjsing * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50e500e238Sjsing * OF THE POSSIBILITY OF SUCH DAMAGE.
51e500e238Sjsing * ====================================================================
52e500e238Sjsing *
53e500e238Sjsing * This product includes cryptographic software written by Eric Young
54e500e238Sjsing * (eay@cryptsoft.com). This product includes software written by Tim
55e500e238Sjsing * Hudson (tjh@cryptsoft.com).
56e500e238Sjsing *
57e500e238Sjsing */
58e500e238Sjsing
59e500e238Sjsing #include <stdio.h>
60e500e238Sjsing #include <string.h>
61e500e238Sjsing
62e500e238Sjsing #include <openssl/opensslconf.h>
63e500e238Sjsing
64e500e238Sjsing #include <openssl/err.h>
65e500e238Sjsing #include <openssl/x509v3.h>
66e500e238Sjsing #include <openssl/x509_vfy.h>
67e500e238Sjsing
6888e5d447Sbeck #include "x509_internal.h"
69c9675a23Stb #include "x509_local.h"
70838f0b6dStb
7140ab66bcStb struct x509_purpose_st {
7240ab66bcStb int purpose;
7340ab66bcStb int trust; /* Default trust ID */
7440ab66bcStb int flags;
7540ab66bcStb int (*check_purpose)(const struct x509_purpose_st *, const X509 *, int);
7640ab66bcStb char *name;
7740ab66bcStb char *sname;
7840ab66bcStb void *usr_data;
7940ab66bcStb } /* X509_PURPOSE */;
8040ab66bcStb
81e500e238Sjsing #define V1_ROOT (EXFLAG_V1|EXFLAG_SS)
82e500e238Sjsing #define ku_reject(x, usage) \
83e500e238Sjsing (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
84e500e238Sjsing #define xku_reject(x, usage) \
85e500e238Sjsing (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage)))
86e500e238Sjsing #define ns_reject(x, usage) \
87e500e238Sjsing (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
88e500e238Sjsing
89e500e238Sjsing static int check_ssl_ca(const X509 *x);
90e500e238Sjsing static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
91e500e238Sjsing int ca);
92e500e238Sjsing static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
93e500e238Sjsing int ca);
94e500e238Sjsing static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
95e500e238Sjsing int ca);
96e500e238Sjsing static int purpose_smime(const X509 *x, int ca);
97e500e238Sjsing static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
98e500e238Sjsing int ca);
99e500e238Sjsing static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
100e500e238Sjsing int ca);
101e500e238Sjsing static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
102e500e238Sjsing int ca);
103e500e238Sjsing static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
104e500e238Sjsing int ca);
105e500e238Sjsing static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca);
106e500e238Sjsing static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca);
107e500e238Sjsing
108b9dfbe76Stb static const X509_PURPOSE xstandard[] = {
1094c21d318Stb {
1104c21d318Stb .purpose = X509_PURPOSE_SSL_CLIENT,
1114c21d318Stb .trust = X509_TRUST_SSL_CLIENT,
1124c21d318Stb .check_purpose = check_purpose_ssl_client,
1134c21d318Stb .name = "SSL client",
1144c21d318Stb .sname = "sslclient",
1154c21d318Stb },
1164c21d318Stb {
1174c21d318Stb .purpose = X509_PURPOSE_SSL_SERVER,
1184c21d318Stb .trust = X509_TRUST_SSL_SERVER,
1194c21d318Stb .check_purpose = check_purpose_ssl_server,
1204c21d318Stb .name = "SSL server",
1214c21d318Stb .sname = "sslserver",
1224c21d318Stb },
1234c21d318Stb {
1244c21d318Stb .purpose = X509_PURPOSE_NS_SSL_SERVER,
1254c21d318Stb .trust = X509_TRUST_SSL_SERVER,
1264c21d318Stb .check_purpose = check_purpose_ns_ssl_server,
1274c21d318Stb .name = "Netscape SSL server",
1284c21d318Stb .sname = "nssslserver",
1294c21d318Stb },
1304c21d318Stb {
1314c21d318Stb .purpose = X509_PURPOSE_SMIME_SIGN,
1324c21d318Stb .trust = X509_TRUST_EMAIL,
1334c21d318Stb .check_purpose = check_purpose_smime_sign,
1344c21d318Stb .name = "S/MIME signing",
1354c21d318Stb .sname = "smimesign",
1364c21d318Stb },
1374c21d318Stb {
1384c21d318Stb .purpose = X509_PURPOSE_SMIME_ENCRYPT,
1394c21d318Stb .trust = X509_TRUST_EMAIL,
1404c21d318Stb .check_purpose = check_purpose_smime_encrypt,
1414c21d318Stb .name = "S/MIME encryption",
1424c21d318Stb .sname = "smimeencrypt",
1434c21d318Stb },
1444c21d318Stb {
1454c21d318Stb .purpose = X509_PURPOSE_CRL_SIGN,
1464c21d318Stb .trust = X509_TRUST_COMPAT,
1474c21d318Stb .check_purpose = check_purpose_crl_sign,
1484c21d318Stb .name = "CRL signing",
1494c21d318Stb .sname = "crlsign",
1504c21d318Stb },
1514c21d318Stb {
1524c21d318Stb .purpose = X509_PURPOSE_ANY,
153*75e21034Sbeck .trust = X509_TRUST_ACCEPT_ALL,
1544c21d318Stb .check_purpose = no_check,
1554c21d318Stb .name = "Any Purpose",
1564c21d318Stb .sname = "any",
1574c21d318Stb },
1584c21d318Stb {
1594c21d318Stb .purpose = X509_PURPOSE_OCSP_HELPER,
1604c21d318Stb .trust = X509_TRUST_COMPAT,
1614c21d318Stb .check_purpose = ocsp_helper,
1624c21d318Stb .name = "OCSP helper",
1634c21d318Stb .sname = "ocsphelper",
1644c21d318Stb },
1654c21d318Stb {
1664c21d318Stb .purpose = X509_PURPOSE_TIMESTAMP_SIGN,
1674c21d318Stb .trust = X509_TRUST_TSA,
1684c21d318Stb .check_purpose = check_purpose_timestamp_sign,
1694c21d318Stb .name = "Time Stamp signing",
1704c21d318Stb .sname = "timestampsign",
1714c21d318Stb },
172e500e238Sjsing };
173e500e238Sjsing
1744c21d318Stb #define X509_PURPOSE_COUNT (sizeof(xstandard) / sizeof(xstandard[0]))
175e500e238Sjsing
176e500e238Sjsing /* As much as I'd like to make X509_check_purpose use a "const" X509*
177e500e238Sjsing * I really can't because it does recalculate hashes and do other non-const
178e500e238Sjsing * things. */
179e500e238Sjsing int
X509_check_purpose(X509 * x,int id,int ca)180e500e238Sjsing X509_check_purpose(X509 *x, int id, int ca)
181e500e238Sjsing {
182e500e238Sjsing int idx;
183e500e238Sjsing const X509_PURPOSE *pt;
184e500e238Sjsing
1850051318fSjob if (!x509v3_cache_extensions(x))
186607be1c9Stb return -1;
1870051318fSjob
188e500e238Sjsing if (id == -1)
189e500e238Sjsing return 1;
190e5d416dfStb
191e5d416dfStb if ((idx = X509_PURPOSE_get_by_id(id)) == -1)
192e500e238Sjsing return -1;
193e5d416dfStb if ((pt = X509_PURPOSE_get0(idx)) == NULL)
194e5d416dfStb return -1;
195e5d416dfStb
196e500e238Sjsing return pt->check_purpose(pt, x, ca);
197e500e238Sjsing }
198cedac418Stb LCRYPTO_ALIAS(X509_check_purpose);
199e500e238Sjsing
200e500e238Sjsing int
X509_PURPOSE_get_count(void)201e500e238Sjsing X509_PURPOSE_get_count(void)
202e500e238Sjsing {
203e500e238Sjsing return X509_PURPOSE_COUNT;
204e500e238Sjsing }
205cedac418Stb LCRYPTO_ALIAS(X509_PURPOSE_get_count);
206e500e238Sjsing
207b9dfbe76Stb const X509_PURPOSE *
X509_PURPOSE_get0(int idx)208e500e238Sjsing X509_PURPOSE_get0(int idx)
209e500e238Sjsing {
2109c4f0f43Stb if (idx < 0 || (size_t)idx >= X509_PURPOSE_COUNT)
211e500e238Sjsing return NULL;
2129c4f0f43Stb
2139c4f0f43Stb return &xstandard[idx];
214e500e238Sjsing }
215cedac418Stb LCRYPTO_ALIAS(X509_PURPOSE_get0);
216e500e238Sjsing
217e500e238Sjsing int
X509_PURPOSE_get_by_sname(const char * sname)218e500e238Sjsing X509_PURPOSE_get_by_sname(const char *sname)
219e500e238Sjsing {
220e500e238Sjsing int i;
221b9dfbe76Stb const X509_PURPOSE *xptmp;
222e500e238Sjsing
223e500e238Sjsing for (i = 0; i < X509_PURPOSE_get_count(); i++) {
224e500e238Sjsing xptmp = X509_PURPOSE_get0(i);
225e500e238Sjsing if (!strcmp(xptmp->sname, sname))
226e500e238Sjsing return i;
227e500e238Sjsing }
228e500e238Sjsing return -1;
229e500e238Sjsing }
230cedac418Stb LCRYPTO_ALIAS(X509_PURPOSE_get_by_sname);
231e500e238Sjsing
232e500e238Sjsing int
X509_PURPOSE_get_by_id(int purpose)233e500e238Sjsing X509_PURPOSE_get_by_id(int purpose)
234e500e238Sjsing {
23577e48307Stb /*
23677e48307Stb * Ensure the purpose identifier is between MIN and MAX inclusive.
23777e48307Stb * If so, translate it to an index into the xstandard[] table.
23877e48307Stb */
2399c4f0f43Stb if (purpose < X509_PURPOSE_MIN || purpose > X509_PURPOSE_MAX)
2409c4f0f43Stb return -1;
241e500e238Sjsing
242e500e238Sjsing return purpose - X509_PURPOSE_MIN;
243e500e238Sjsing }
244e500e238Sjsing
245e500e238Sjsing int
X509_PURPOSE_get_id(const X509_PURPOSE * xp)246e500e238Sjsing X509_PURPOSE_get_id(const X509_PURPOSE *xp)
247e500e238Sjsing {
248e500e238Sjsing return xp->purpose;
249e500e238Sjsing }
250cedac418Stb LCRYPTO_ALIAS(X509_PURPOSE_get_id);
251e500e238Sjsing
252b9dfbe76Stb const char *
X509_PURPOSE_get0_name(const X509_PURPOSE * xp)253e500e238Sjsing X509_PURPOSE_get0_name(const X509_PURPOSE *xp)
254e500e238Sjsing {
255e500e238Sjsing return xp->name;
256e500e238Sjsing }
257cedac418Stb LCRYPTO_ALIAS(X509_PURPOSE_get0_name);
258e500e238Sjsing
259b9dfbe76Stb const char *
X509_PURPOSE_get0_sname(const X509_PURPOSE * xp)260e500e238Sjsing X509_PURPOSE_get0_sname(const X509_PURPOSE *xp)
261e500e238Sjsing {
262e500e238Sjsing return xp->sname;
263e500e238Sjsing }
264cedac418Stb LCRYPTO_ALIAS(X509_PURPOSE_get0_sname);
265e500e238Sjsing
266e500e238Sjsing int
X509_PURPOSE_get_trust(const X509_PURPOSE * xp)267e500e238Sjsing X509_PURPOSE_get_trust(const X509_PURPOSE *xp)
268e500e238Sjsing {
269e500e238Sjsing return xp->trust;
270e500e238Sjsing }
271e500e238Sjsing
2729e624728Stb /*
2739e624728Stb * List of NIDs of extensions supported by the verifier. If an extension
2749e624728Stb * is critical and doesn't appear in this list, then the certificate will
2759e624728Stb * normally be rejected.
276e500e238Sjsing */
2779e624728Stb int
X509_supported_extension(X509_EXTENSION * ext)2789e624728Stb X509_supported_extension(X509_EXTENSION *ext)
2799e624728Stb {
2809e624728Stb switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext))) {
2819e624728Stb case NID_basic_constraints:
2829e624728Stb case NID_certificate_policies:
2839e624728Stb case NID_ext_key_usage:
2843c74274bStb case NID_inhibit_any_policy:
2853c74274bStb case NID_key_usage:
2863c74274bStb case NID_name_constraints:
2873c74274bStb case NID_netscape_cert_type:
2883c74274bStb case NID_policy_constraints:
2893c74274bStb case NID_policy_mappings:
2900b5aa37fSjob #ifndef OPENSSL_NO_RFC3779
2919e624728Stb case NID_sbgp_ipAddrBlock:
2929e624728Stb case NID_sbgp_autonomousSysNum:
2930b5aa37fSjob #endif
2943c74274bStb case NID_subject_alt_name:
295e500e238Sjsing return 1;
2969e624728Stb default:
297e500e238Sjsing return 0;
298e500e238Sjsing }
2999e624728Stb }
300cedac418Stb LCRYPTO_ALIAS(X509_supported_extension);
301e500e238Sjsing
302e500e238Sjsing static void
setup_dp(X509 * x,DIST_POINT * dp)303e500e238Sjsing setup_dp(X509 *x, DIST_POINT *dp)
304e500e238Sjsing {
305e500e238Sjsing X509_NAME *iname = NULL;
306e500e238Sjsing int i;
307e500e238Sjsing
308e500e238Sjsing if (dp->reasons) {
309e500e238Sjsing if (dp->reasons->length > 0)
310e500e238Sjsing dp->dp_reasons = dp->reasons->data[0];
311e500e238Sjsing if (dp->reasons->length > 1)
312e500e238Sjsing dp->dp_reasons |= (dp->reasons->data[1] << 8);
313e500e238Sjsing dp->dp_reasons &= CRLDP_ALL_REASONS;
314e500e238Sjsing } else
315e500e238Sjsing dp->dp_reasons = CRLDP_ALL_REASONS;
316e500e238Sjsing if (!dp->distpoint || (dp->distpoint->type != 1))
317e500e238Sjsing return;
318e500e238Sjsing for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) {
319e500e238Sjsing GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
320e500e238Sjsing if (gen->type == GEN_DIRNAME) {
321e500e238Sjsing iname = gen->d.directoryName;
322e500e238Sjsing break;
323e500e238Sjsing }
324e500e238Sjsing }
325e500e238Sjsing if (!iname)
326e500e238Sjsing iname = X509_get_issuer_name(x);
327e500e238Sjsing
328e500e238Sjsing DIST_POINT_set_dpname(dp->distpoint, iname);
329e500e238Sjsing }
330e500e238Sjsing
331e500e238Sjsing static void
setup_crldp(X509 * x)332e500e238Sjsing setup_crldp(X509 *x)
333e500e238Sjsing {
334e500e238Sjsing int i;
335e500e238Sjsing
3363746f1b0Stobhe x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, &i, NULL);
3373746f1b0Stobhe if (x->crldp == NULL && i != -1) {
3383746f1b0Stobhe x->ex_flags |= EXFLAG_INVALID;
3393746f1b0Stobhe return;
3403746f1b0Stobhe }
3413746f1b0Stobhe
342e500e238Sjsing for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
343e500e238Sjsing setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
344e500e238Sjsing }
345e500e238Sjsing
346a7f5be1eStb static int
x509_extension_oid_cmp(const X509_EXTENSION * const * a,const X509_EXTENSION * const * b)347a7f5be1eStb x509_extension_oid_cmp(const X509_EXTENSION *const *a,
348a7f5be1eStb const X509_EXTENSION *const *b)
349a7f5be1eStb {
350a7f5be1eStb return OBJ_cmp((*a)->object, (*b)->object);
351a7f5be1eStb }
352a7f5be1eStb
353a7f5be1eStb static int
x509_extension_oids_are_unique(X509 * x509)354a7f5be1eStb x509_extension_oids_are_unique(X509 *x509)
355a7f5be1eStb {
356a7f5be1eStb STACK_OF(X509_EXTENSION) *exts = NULL;
357a7f5be1eStb const X509_EXTENSION *prev_ext, *curr_ext;
358a7f5be1eStb int i;
359a7f5be1eStb int ret = 0;
360a7f5be1eStb
361a7f5be1eStb if (X509_get_ext_count(x509) <= 1)
362a7f5be1eStb goto done;
363a7f5be1eStb
364a7f5be1eStb if ((exts = sk_X509_EXTENSION_dup(x509->cert_info->extensions)) == NULL)
365a7f5be1eStb goto err;
366a7f5be1eStb
367a7f5be1eStb (void)sk_X509_EXTENSION_set_cmp_func(exts, x509_extension_oid_cmp);
368a7f5be1eStb sk_X509_EXTENSION_sort(exts);
369a7f5be1eStb
370a7f5be1eStb prev_ext = sk_X509_EXTENSION_value(exts, 0);
371a7f5be1eStb for (i = 1; i < sk_X509_EXTENSION_num(exts); i++) {
372a7f5be1eStb curr_ext = sk_X509_EXTENSION_value(exts, i);
373a7f5be1eStb if (x509_extension_oid_cmp(&prev_ext, &curr_ext) == 0)
374a7f5be1eStb goto err;
375a7f5be1eStb prev_ext = curr_ext;
376a7f5be1eStb }
377a7f5be1eStb
378a7f5be1eStb done:
379a7f5be1eStb ret = 1;
380a7f5be1eStb
381a7f5be1eStb err:
382a7f5be1eStb sk_X509_EXTENSION_free(exts);
383a7f5be1eStb
384a7f5be1eStb return ret;
385a7f5be1eStb }
386a7f5be1eStb
3870051318fSjob static void
x509v3_cache_extensions_internal(X509 * x)3880051318fSjob x509v3_cache_extensions_internal(X509 *x)
389e500e238Sjsing {
390e500e238Sjsing BASIC_CONSTRAINTS *bs;
391e500e238Sjsing ASN1_BIT_STRING *usage;
392e500e238Sjsing ASN1_BIT_STRING *ns;
393e500e238Sjsing EXTENDED_KEY_USAGE *extusage;
394e500e238Sjsing X509_EXTENSION *ex;
395e857c54fStb long version;
396e500e238Sjsing int i;
397e500e238Sjsing
398e500e238Sjsing if (x->ex_flags & EXFLAG_SET)
399e500e238Sjsing return;
400e500e238Sjsing
401b0fd9985Stb /*
402b0fd9985Stb * XXX - this should really only set EXFLAG_INVALID if extensions are
403b0fd9985Stb * invalid. However, the X509_digest() failure matches OpenSSL/BoringSSL
404b0fd9985Stb * behavior and the version checks are at least vaguely related to
405b0fd9985Stb * extensions.
406b0fd9985Stb */
407b0fd9985Stb
4085f814157Stb if (!X509_digest(x, X509_CERT_HASH_EVP, x->hash, NULL))
4095f814157Stb x->ex_flags |= EXFLAG_INVALID;
410e500e238Sjsing
411e857c54fStb version = X509_get_version(x);
412e857c54fStb if (version < 0 || version > 2)
413e857c54fStb x->ex_flags |= EXFLAG_INVALID;
414e857c54fStb if (version == 0) {
415e500e238Sjsing x->ex_flags |= EXFLAG_V1;
416e857c54fStb /* UIDs may only appear in v2 or v3 certs */
417e857c54fStb if (x->cert_info->issuerUID != NULL ||
418e857c54fStb x->cert_info->subjectUID != NULL)
41936d21cc0Sjob x->ex_flags |= EXFLAG_INVALID;
42036d21cc0Sjob }
421e857c54fStb if (version != 2 && X509_get_ext_count(x) != 0)
422e857c54fStb x->ex_flags |= EXFLAG_INVALID;
423e500e238Sjsing
424e500e238Sjsing /* Handle basic constraints */
4253746f1b0Stobhe if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, &i, NULL))) {
426e500e238Sjsing if (bs->ca)
427e500e238Sjsing x->ex_flags |= EXFLAG_CA;
428e500e238Sjsing if (bs->pathlen) {
429e500e238Sjsing if ((bs->pathlen->type == V_ASN1_NEG_INTEGER) ||
430e500e238Sjsing !bs->ca) {
431e500e238Sjsing x->ex_flags |= EXFLAG_INVALID;
432e500e238Sjsing x->ex_pathlen = 0;
433e500e238Sjsing } else
434e500e238Sjsing x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
435e500e238Sjsing } else
436e500e238Sjsing x->ex_pathlen = -1;
437e500e238Sjsing BASIC_CONSTRAINTS_free(bs);
438e500e238Sjsing x->ex_flags |= EXFLAG_BCONS;
4393746f1b0Stobhe } else if (i != -1) {
4403746f1b0Stobhe x->ex_flags |= EXFLAG_INVALID;
441e500e238Sjsing }
442e500e238Sjsing
443e500e238Sjsing /* Handle key usage */
4443746f1b0Stobhe if ((usage = X509_get_ext_d2i(x, NID_key_usage, &i, NULL))) {
445e500e238Sjsing if (usage->length > 0) {
446e500e238Sjsing x->ex_kusage = usage->data[0];
447e500e238Sjsing if (usage->length > 1)
448e500e238Sjsing x->ex_kusage |= usage->data[1] << 8;
449e500e238Sjsing } else
450e500e238Sjsing x->ex_kusage = 0;
451e500e238Sjsing x->ex_flags |= EXFLAG_KUSAGE;
452e500e238Sjsing ASN1_BIT_STRING_free(usage);
4533746f1b0Stobhe } else if (i != -1) {
4543746f1b0Stobhe x->ex_flags |= EXFLAG_INVALID;
455e500e238Sjsing }
4563746f1b0Stobhe
457e500e238Sjsing x->ex_xkusage = 0;
4583746f1b0Stobhe if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, &i, NULL))) {
459e500e238Sjsing x->ex_flags |= EXFLAG_XKUSAGE;
460e500e238Sjsing for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
461e500e238Sjsing switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) {
462e500e238Sjsing case NID_server_auth:
463e500e238Sjsing x->ex_xkusage |= XKU_SSL_SERVER;
464e500e238Sjsing break;
465e500e238Sjsing
466e500e238Sjsing case NID_client_auth:
467e500e238Sjsing x->ex_xkusage |= XKU_SSL_CLIENT;
468e500e238Sjsing break;
469e500e238Sjsing
470e500e238Sjsing case NID_email_protect:
471e500e238Sjsing x->ex_xkusage |= XKU_SMIME;
472e500e238Sjsing break;
473e500e238Sjsing
474e500e238Sjsing case NID_code_sign:
475e500e238Sjsing x->ex_xkusage |= XKU_CODE_SIGN;
476e500e238Sjsing break;
477e500e238Sjsing
478e500e238Sjsing case NID_ms_sgc:
479e500e238Sjsing case NID_ns_sgc:
480e500e238Sjsing x->ex_xkusage |= XKU_SGC;
481e500e238Sjsing break;
482e500e238Sjsing
483e500e238Sjsing case NID_OCSP_sign:
484e500e238Sjsing x->ex_xkusage |= XKU_OCSP_SIGN;
485e500e238Sjsing break;
486e500e238Sjsing
487e500e238Sjsing case NID_time_stamp:
488e500e238Sjsing x->ex_xkusage |= XKU_TIMESTAMP;
489e500e238Sjsing break;
490e500e238Sjsing
491e500e238Sjsing case NID_dvcs:
492e500e238Sjsing x->ex_xkusage |= XKU_DVCS;
493e500e238Sjsing break;
4943e6cffe7Stb
4953e6cffe7Stb case NID_anyExtendedKeyUsage:
4963e6cffe7Stb x->ex_xkusage |= XKU_ANYEKU;
4973e6cffe7Stb break;
498e500e238Sjsing }
499e500e238Sjsing }
500e500e238Sjsing sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
5013746f1b0Stobhe } else if (i != -1) {
5023746f1b0Stobhe x->ex_flags |= EXFLAG_INVALID;
503e500e238Sjsing }
504e500e238Sjsing
5053746f1b0Stobhe if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, &i, NULL))) {
506e500e238Sjsing if (ns->length > 0)
507e500e238Sjsing x->ex_nscert = ns->data[0];
508e500e238Sjsing else
509e500e238Sjsing x->ex_nscert = 0;
510e500e238Sjsing x->ex_flags |= EXFLAG_NSCERT;
511e500e238Sjsing ASN1_BIT_STRING_free(ns);
5123746f1b0Stobhe } else if (i != -1) {
5133746f1b0Stobhe x->ex_flags |= EXFLAG_INVALID;
514e500e238Sjsing }
515e500e238Sjsing
5163746f1b0Stobhe x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, &i, NULL);
5173746f1b0Stobhe if (x->skid == NULL && i != -1)
5183746f1b0Stobhe x->ex_flags |= EXFLAG_INVALID;
5193746f1b0Stobhe x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, &i, NULL);
52074808df3Stb if (x->akid == NULL && i != -1)
5213746f1b0Stobhe x->ex_flags |= EXFLAG_INVALID;
522e500e238Sjsing
523e500e238Sjsing /* Does subject name match issuer? */
524e500e238Sjsing if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) {
525e500e238Sjsing x->ex_flags |= EXFLAG_SI;
526e500e238Sjsing /* If SKID matches AKID also indicate self signed. */
527e500e238Sjsing if (X509_check_akid(x, x->akid) == X509_V_OK &&
528e500e238Sjsing !ku_reject(x, KU_KEY_CERT_SIGN))
529e500e238Sjsing x->ex_flags |= EXFLAG_SS;
530e500e238Sjsing }
531e500e238Sjsing
5323746f1b0Stobhe x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, &i, NULL);
5333746f1b0Stobhe if (x->altname == NULL && i != -1)
5343746f1b0Stobhe x->ex_flags |= EXFLAG_INVALID;
535e500e238Sjsing x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL);
536e500e238Sjsing if (!x->nc && (i != -1))
537e500e238Sjsing x->ex_flags |= EXFLAG_INVALID;
538e500e238Sjsing setup_crldp(x);
539e500e238Sjsing
5400b5aa37fSjob #ifndef OPENSSL_NO_RFC3779
5410b5aa37fSjob x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, &i, NULL);
5420b5aa37fSjob if (x->rfc3779_addr == NULL && i != -1)
5430b5aa37fSjob x->ex_flags |= EXFLAG_INVALID;
5441b14589dStb if (!X509v3_addr_is_canonical(x->rfc3779_addr))
5451b14589dStb x->ex_flags |= EXFLAG_INVALID;
5460b5aa37fSjob x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, &i, NULL);
5470b5aa37fSjob if (x->rfc3779_asid == NULL && i != -1)
5480b5aa37fSjob x->ex_flags |= EXFLAG_INVALID;
5491b14589dStb if (!X509v3_asid_is_canonical(x->rfc3779_asid))
5501b14589dStb x->ex_flags |= EXFLAG_INVALID;
5510b5aa37fSjob #endif
5520b5aa37fSjob
553e500e238Sjsing for (i = 0; i < X509_get_ext_count(x); i++) {
554e500e238Sjsing ex = X509_get_ext(x, i);
555e500e238Sjsing if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) ==
556e500e238Sjsing NID_freshest_crl)
557e500e238Sjsing x->ex_flags |= EXFLAG_FRESHEST;
558e500e238Sjsing if (!X509_EXTENSION_get_critical(ex))
559e500e238Sjsing continue;
560e500e238Sjsing if (!X509_supported_extension(ex)) {
561e500e238Sjsing x->ex_flags |= EXFLAG_CRITICAL;
562e500e238Sjsing break;
563e500e238Sjsing }
564e500e238Sjsing }
56588e5d447Sbeck
566a7f5be1eStb if (!x509_extension_oids_are_unique(x))
567a7f5be1eStb x->ex_flags |= EXFLAG_INVALID;
568a7f5be1eStb
569e500e238Sjsing x->ex_flags |= EXFLAG_SET;
570e500e238Sjsing }
571e500e238Sjsing
5720051318fSjob int
x509v3_cache_extensions(X509 * x)5730051318fSjob x509v3_cache_extensions(X509 *x)
5740051318fSjob {
5750051318fSjob if ((x->ex_flags & EXFLAG_SET) == 0) {
5760051318fSjob CRYPTO_w_lock(CRYPTO_LOCK_X509);
5770051318fSjob x509v3_cache_extensions_internal(x);
5780051318fSjob CRYPTO_w_unlock(CRYPTO_LOCK_X509);
5790051318fSjob }
5800051318fSjob
5810051318fSjob return (x->ex_flags & EXFLAG_INVALID) == 0;
5820051318fSjob }
5830051318fSjob
584e500e238Sjsing /* CA checks common to all purposes
585e500e238Sjsing * return codes:
586e500e238Sjsing * 0 not a CA
587e500e238Sjsing * 1 is a CA
588e500e238Sjsing * 2 basicConstraints absent so "maybe" a CA
589e500e238Sjsing * 3 basicConstraints absent but self signed V1.
590e500e238Sjsing * 4 basicConstraints absent but keyUsage present and keyCertSign asserted.
591e500e238Sjsing */
592e500e238Sjsing
593e500e238Sjsing static int
check_ca(const X509 * x)594e500e238Sjsing check_ca(const X509 *x)
595e500e238Sjsing {
596e500e238Sjsing /* keyUsage if present should allow cert signing */
597e500e238Sjsing if (ku_reject(x, KU_KEY_CERT_SIGN))
598e500e238Sjsing return 0;
599e500e238Sjsing if (x->ex_flags & EXFLAG_BCONS) {
600e500e238Sjsing if (x->ex_flags & EXFLAG_CA)
601e500e238Sjsing return 1;
602e500e238Sjsing /* If basicConstraints says not a CA then say so */
603e500e238Sjsing else
604e500e238Sjsing return 0;
605e500e238Sjsing } else {
606e500e238Sjsing /* we support V1 roots for... uh, I don't really know why. */
607e500e238Sjsing if ((x->ex_flags & V1_ROOT) == V1_ROOT)
608e500e238Sjsing return 3;
609e500e238Sjsing /* If key usage present it must have certSign so tolerate it */
610e500e238Sjsing else if (x->ex_flags & EXFLAG_KUSAGE)
611e500e238Sjsing return 4;
612e500e238Sjsing /* Older certificates could have Netscape-specific CA types */
613e500e238Sjsing else if (x->ex_flags & EXFLAG_NSCERT &&
614e500e238Sjsing x->ex_nscert & NS_ANY_CA)
615e500e238Sjsing return 5;
616e500e238Sjsing /* can this still be regarded a CA certificate? I doubt it */
617e500e238Sjsing return 0;
618e500e238Sjsing }
619e500e238Sjsing }
620e500e238Sjsing
621e500e238Sjsing int
X509_check_ca(X509 * x)622e500e238Sjsing X509_check_ca(X509 *x)
623e500e238Sjsing {
624e500e238Sjsing x509v3_cache_extensions(x);
625e500e238Sjsing
626e500e238Sjsing return check_ca(x);
627e500e238Sjsing }
628cedac418Stb LCRYPTO_ALIAS(X509_check_ca);
629e500e238Sjsing
630e500e238Sjsing /* Check SSL CA: common checks for SSL client and server */
631e500e238Sjsing static int
check_ssl_ca(const X509 * x)632e500e238Sjsing check_ssl_ca(const X509 *x)
633e500e238Sjsing {
634e500e238Sjsing int ca_ret;
635e500e238Sjsing
636e500e238Sjsing ca_ret = check_ca(x);
637e500e238Sjsing if (!ca_ret)
638e500e238Sjsing return 0;
639e500e238Sjsing /* check nsCertType if present */
640e500e238Sjsing if (ca_ret != 5 || x->ex_nscert & NS_SSL_CA)
641e500e238Sjsing return ca_ret;
642e500e238Sjsing else
643e500e238Sjsing return 0;
644e500e238Sjsing }
645e500e238Sjsing
646e500e238Sjsing static int
check_purpose_ssl_client(const X509_PURPOSE * xp,const X509 * x,int ca)647e500e238Sjsing check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca)
648e500e238Sjsing {
649e500e238Sjsing if (xku_reject(x, XKU_SSL_CLIENT))
650e500e238Sjsing return 0;
651e500e238Sjsing if (ca)
652e500e238Sjsing return check_ssl_ca(x);
653e500e238Sjsing /* We need to do digital signatures with it */
654e500e238Sjsing if (ku_reject(x, KU_DIGITAL_SIGNATURE))
655e500e238Sjsing return 0;
656e500e238Sjsing /* nsCertType if present should allow SSL client use */
657e500e238Sjsing if (ns_reject(x, NS_SSL_CLIENT))
658e500e238Sjsing return 0;
659e500e238Sjsing return 1;
660e500e238Sjsing }
661e500e238Sjsing
662e500e238Sjsing static int
check_purpose_ssl_server(const X509_PURPOSE * xp,const X509 * x,int ca)663e500e238Sjsing check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca)
664e500e238Sjsing {
665e500e238Sjsing if (xku_reject(x, XKU_SSL_SERVER|XKU_SGC))
666e500e238Sjsing return 0;
667e500e238Sjsing if (ca)
668e500e238Sjsing return check_ssl_ca(x);
669e500e238Sjsing
670e500e238Sjsing if (ns_reject(x, NS_SSL_SERVER))
671e500e238Sjsing return 0;
672e500e238Sjsing /* Now as for keyUsage: we'll at least need to sign OR encipher */
673e500e238Sjsing if (ku_reject(x, KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT))
674e500e238Sjsing return 0;
675e500e238Sjsing
676e500e238Sjsing return 1;
677e500e238Sjsing }
678e500e238Sjsing
679e500e238Sjsing static int
check_purpose_ns_ssl_server(const X509_PURPOSE * xp,const X509 * x,int ca)680e500e238Sjsing check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca)
681e500e238Sjsing {
682e500e238Sjsing int ret;
683e500e238Sjsing
684e500e238Sjsing ret = check_purpose_ssl_server(xp, x, ca);
685e500e238Sjsing if (!ret || ca)
686e500e238Sjsing return ret;
687e500e238Sjsing /* We need to encipher or Netscape complains */
688e500e238Sjsing if (ku_reject(x, KU_KEY_ENCIPHERMENT))
689e500e238Sjsing return 0;
690e500e238Sjsing return ret;
691e500e238Sjsing }
692e500e238Sjsing
693e500e238Sjsing /* common S/MIME checks */
694e500e238Sjsing static int
purpose_smime(const X509 * x,int ca)695e500e238Sjsing purpose_smime(const X509 *x, int ca)
696e500e238Sjsing {
697e500e238Sjsing if (xku_reject(x, XKU_SMIME))
698e500e238Sjsing return 0;
699e500e238Sjsing if (ca) {
700e500e238Sjsing int ca_ret;
701e500e238Sjsing ca_ret = check_ca(x);
702e500e238Sjsing if (!ca_ret)
703e500e238Sjsing return 0;
704e500e238Sjsing /* check nsCertType if present */
705e500e238Sjsing if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA)
706e500e238Sjsing return ca_ret;
707e500e238Sjsing else
708e500e238Sjsing return 0;
709e500e238Sjsing }
710e500e238Sjsing if (x->ex_flags & EXFLAG_NSCERT) {
711e500e238Sjsing if (x->ex_nscert & NS_SMIME)
712e500e238Sjsing return 1;
713e500e238Sjsing /* Workaround for some buggy certificates */
714e500e238Sjsing if (x->ex_nscert & NS_SSL_CLIENT)
715e500e238Sjsing return 2;
716e500e238Sjsing return 0;
717e500e238Sjsing }
718e500e238Sjsing return 1;
719e500e238Sjsing }
720e500e238Sjsing
721e500e238Sjsing static int
check_purpose_smime_sign(const X509_PURPOSE * xp,const X509 * x,int ca)722e500e238Sjsing check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
723e500e238Sjsing {
724e500e238Sjsing int ret;
725e500e238Sjsing
726e500e238Sjsing ret = purpose_smime(x, ca);
727e500e238Sjsing if (!ret || ca)
728e500e238Sjsing return ret;
729e500e238Sjsing if (ku_reject(x, KU_DIGITAL_SIGNATURE|KU_NON_REPUDIATION))
730e500e238Sjsing return 0;
731e500e238Sjsing return ret;
732e500e238Sjsing }
733e500e238Sjsing
734e500e238Sjsing static int
check_purpose_smime_encrypt(const X509_PURPOSE * xp,const X509 * x,int ca)735e500e238Sjsing check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca)
736e500e238Sjsing {
737e500e238Sjsing int ret;
738e500e238Sjsing
739e500e238Sjsing ret = purpose_smime(x, ca);
740e500e238Sjsing if (!ret || ca)
741e500e238Sjsing return ret;
742e500e238Sjsing if (ku_reject(x, KU_KEY_ENCIPHERMENT))
743e500e238Sjsing return 0;
744e500e238Sjsing return ret;
745e500e238Sjsing }
746e500e238Sjsing
747e500e238Sjsing static int
check_purpose_crl_sign(const X509_PURPOSE * xp,const X509 * x,int ca)748e500e238Sjsing check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
749e500e238Sjsing {
750e500e238Sjsing if (ca) {
751e500e238Sjsing int ca_ret;
752e500e238Sjsing if ((ca_ret = check_ca(x)) != 2)
753e500e238Sjsing return ca_ret;
754e500e238Sjsing else
755e500e238Sjsing return 0;
756e500e238Sjsing }
757e500e238Sjsing if (ku_reject(x, KU_CRL_SIGN))
758e500e238Sjsing return 0;
759e500e238Sjsing return 1;
760e500e238Sjsing }
761e500e238Sjsing
762e500e238Sjsing /* OCSP helper: this is *not* a full OCSP check. It just checks that
763e500e238Sjsing * each CA is valid. Additional checks must be made on the chain.
764e500e238Sjsing */
765e500e238Sjsing static int
ocsp_helper(const X509_PURPOSE * xp,const X509 * x,int ca)766e500e238Sjsing ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca)
767e500e238Sjsing {
768e500e238Sjsing /* Must be a valid CA. Should we really support the "I don't know"
769e500e238Sjsing value (2)? */
770e500e238Sjsing if (ca)
771e500e238Sjsing return check_ca(x);
772e500e238Sjsing /* leaf certificate is checked in OCSP_verify() */
773e500e238Sjsing return 1;
774e500e238Sjsing }
775e500e238Sjsing
776e500e238Sjsing static int
check_purpose_timestamp_sign(const X509_PURPOSE * xp,const X509 * x,int ca)777e500e238Sjsing check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
778e500e238Sjsing {
779e500e238Sjsing int i_ext;
780e500e238Sjsing
781e500e238Sjsing /* If ca is true we must return if this is a valid CA certificate. */
782e500e238Sjsing if (ca)
783e500e238Sjsing return check_ca(x);
784e500e238Sjsing
785e500e238Sjsing /*
786e500e238Sjsing * Check the optional key usage field:
787e500e238Sjsing * if Key Usage is present, it must be one of digitalSignature
788e500e238Sjsing * and/or nonRepudiation (other values are not consistent and shall
789e500e238Sjsing * be rejected).
790e500e238Sjsing */
791e500e238Sjsing if ((x->ex_flags & EXFLAG_KUSAGE) &&
792e500e238Sjsing ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) ||
793e500e238Sjsing !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE))))
794e500e238Sjsing return 0;
795e500e238Sjsing
796e500e238Sjsing /* Only time stamp key usage is permitted and it's required. */
797e500e238Sjsing if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP)
798e500e238Sjsing return 0;
799e500e238Sjsing
800e500e238Sjsing /* Extended Key Usage MUST be critical */
801e500e238Sjsing i_ext = X509_get_ext_by_NID((X509 *) x, NID_ext_key_usage, -1);
802e500e238Sjsing if (i_ext >= 0) {
803e500e238Sjsing X509_EXTENSION *ext = X509_get_ext((X509 *) x, i_ext);
804e500e238Sjsing if (!X509_EXTENSION_get_critical(ext))
805e500e238Sjsing return 0;
806e500e238Sjsing }
807e500e238Sjsing
808e500e238Sjsing return 1;
809e500e238Sjsing }
810e500e238Sjsing
811e500e238Sjsing static int
no_check(const X509_PURPOSE * xp,const X509 * x,int ca)812e500e238Sjsing no_check(const X509_PURPOSE *xp, const X509 *x, int ca)
813e500e238Sjsing {
814e500e238Sjsing return 1;
815e500e238Sjsing }
816e500e238Sjsing
817e500e238Sjsing /* Various checks to see if one certificate issued the second.
818e500e238Sjsing * This can be used to prune a set of possible issuer certificates
819e500e238Sjsing * which have been looked up using some simple method such as by
820e500e238Sjsing * subject name.
821e500e238Sjsing * These are:
822e500e238Sjsing * 1. Check issuer_name(subject) == subject_name(issuer)
823e500e238Sjsing * 2. If akid(subject) exists check it matches issuer
824e500e238Sjsing * 3. If key_usage(issuer) exists check it supports certificate signing
825e500e238Sjsing * returns 0 for OK, positive for reason for mismatch, reasons match
826e500e238Sjsing * codes for X509_verify_cert()
827e500e238Sjsing */
828e500e238Sjsing
829e500e238Sjsing int
X509_check_issued(X509 * issuer,X509 * subject)830e500e238Sjsing X509_check_issued(X509 *issuer, X509 *subject)
831e500e238Sjsing {
832e500e238Sjsing if (X509_NAME_cmp(X509_get_subject_name(issuer),
833e500e238Sjsing X509_get_issuer_name(subject)))
834e500e238Sjsing return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
8350051318fSjob
8360051318fSjob if (!x509v3_cache_extensions(issuer))
8373746f1b0Stobhe return X509_V_ERR_UNSPECIFIED;
8380051318fSjob if (!x509v3_cache_extensions(subject))
8393746f1b0Stobhe return X509_V_ERR_UNSPECIFIED;
840e500e238Sjsing
841e500e238Sjsing if (subject->akid) {
842e500e238Sjsing int ret = X509_check_akid(issuer, subject->akid);
843e500e238Sjsing if (ret != X509_V_OK)
844e500e238Sjsing return ret;
845e500e238Sjsing }
846e500e238Sjsing
847d376c969Stb if (ku_reject(issuer, KU_KEY_CERT_SIGN))
848e500e238Sjsing return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
849e500e238Sjsing return X509_V_OK;
850e500e238Sjsing }
851cedac418Stb LCRYPTO_ALIAS(X509_check_issued);
852e500e238Sjsing
853e500e238Sjsing int
X509_check_akid(X509 * issuer,AUTHORITY_KEYID * akid)854e500e238Sjsing X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid)
855e500e238Sjsing {
856e500e238Sjsing if (!akid)
857e500e238Sjsing return X509_V_OK;
858e500e238Sjsing
859e500e238Sjsing /* Check key ids (if present) */
860e500e238Sjsing if (akid->keyid && issuer->skid &&
861e500e238Sjsing ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid))
862e500e238Sjsing return X509_V_ERR_AKID_SKID_MISMATCH;
863e500e238Sjsing /* Check serial number */
864e500e238Sjsing if (akid->serial &&
865e500e238Sjsing ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial))
866e500e238Sjsing return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
867e500e238Sjsing /* Check issuer name */
868e500e238Sjsing if (akid->issuer) {
869e500e238Sjsing /* Ugh, for some peculiar reason AKID includes
870e500e238Sjsing * SEQUENCE OF GeneralName. So look for a DirName.
871e500e238Sjsing * There may be more than one but we only take any
872e500e238Sjsing * notice of the first.
873e500e238Sjsing */
874e500e238Sjsing GENERAL_NAMES *gens;
875e500e238Sjsing GENERAL_NAME *gen;
876e500e238Sjsing X509_NAME *nm = NULL;
877e500e238Sjsing int i;
878e500e238Sjsing gens = akid->issuer;
879e500e238Sjsing for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
880e500e238Sjsing gen = sk_GENERAL_NAME_value(gens, i);
881e500e238Sjsing if (gen->type == GEN_DIRNAME) {
882e500e238Sjsing nm = gen->d.dirn;
883e500e238Sjsing break;
884e500e238Sjsing }
885e500e238Sjsing }
886e500e238Sjsing if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
887e500e238Sjsing return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
888e500e238Sjsing }
889e500e238Sjsing return X509_V_OK;
890e500e238Sjsing }
891cedac418Stb LCRYPTO_ALIAS(X509_check_akid);
8922fc70a27Stb
8932fc70a27Stb uint32_t
X509_get_extension_flags(X509 * x)894c7d885c5Stb X509_get_extension_flags(X509 *x)
895c7d885c5Stb {
896c7d885c5Stb /* Call for side-effect of computing hash and caching extensions */
897c7d885c5Stb if (X509_check_purpose(x, -1, -1) != 1)
8988ed36ed2Stb return EXFLAG_INVALID;
899c7d885c5Stb
900c7d885c5Stb return x->ex_flags;
901c7d885c5Stb }
902cedac418Stb LCRYPTO_ALIAS(X509_get_extension_flags);
903c7d885c5Stb
904c7d885c5Stb uint32_t
X509_get_key_usage(X509 * x)9052fc70a27Stb X509_get_key_usage(X509 *x)
9062fc70a27Stb {
9072fc70a27Stb /* Call for side-effect of computing hash and caching extensions */
9082fc70a27Stb if (X509_check_purpose(x, -1, -1) != 1)
9092fc70a27Stb return 0;
9102fc70a27Stb
9112fc70a27Stb if (x->ex_flags & EXFLAG_KUSAGE)
9122fc70a27Stb return x->ex_kusage;
9132fc70a27Stb
9142fc70a27Stb return UINT32_MAX;
9152fc70a27Stb }
916cedac418Stb LCRYPTO_ALIAS(X509_get_key_usage);
9172fc70a27Stb
9182fc70a27Stb uint32_t
X509_get_extended_key_usage(X509 * x)9192fc70a27Stb X509_get_extended_key_usage(X509 *x)
9202fc70a27Stb {
9212fc70a27Stb /* Call for side-effect of computing hash and caching extensions */
9222fc70a27Stb if (X509_check_purpose(x, -1, -1) != 1)
9232fc70a27Stb return 0;
9242fc70a27Stb
9252fc70a27Stb if (x->ex_flags & EXFLAG_XKUSAGE)
9262fc70a27Stb return x->ex_xkusage;
9272fc70a27Stb
9282fc70a27Stb return UINT32_MAX;
9292fc70a27Stb }
930cedac418Stb LCRYPTO_ALIAS(X509_get_extended_key_usage);
931