xref: /third_party/openssl/crypto/x509/v3_purp.c (revision e1051a39)
1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <stdio.h>
11e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
12e1051a39Sopenharmony_ci#include "internal/numbers.h"
13e1051a39Sopenharmony_ci#include <openssl/x509v3.h>
14e1051a39Sopenharmony_ci#include <openssl/x509_vfy.h>
15e1051a39Sopenharmony_ci#include "crypto/x509.h"
16e1051a39Sopenharmony_ci#include "internal/tsan_assist.h"
17e1051a39Sopenharmony_ci#include "x509_local.h"
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_cistatic int check_ssl_ca(const X509 *x);
20e1051a39Sopenharmony_cistatic int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
21e1051a39Sopenharmony_ci                                    int require_ca);
22e1051a39Sopenharmony_cistatic int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
23e1051a39Sopenharmony_ci                                    int require_ca);
24e1051a39Sopenharmony_cistatic int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
25e1051a39Sopenharmony_ci                                       int require_ca);
26e1051a39Sopenharmony_cistatic int purpose_smime(const X509 *x, int require_ca);
27e1051a39Sopenharmony_cistatic int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
28e1051a39Sopenharmony_ci                                    int require_ca);
29e1051a39Sopenharmony_cistatic int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
30e1051a39Sopenharmony_ci                                       int require_ca);
31e1051a39Sopenharmony_cistatic int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
32e1051a39Sopenharmony_ci                                  int require_ca);
33e1051a39Sopenharmony_cistatic int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
34e1051a39Sopenharmony_ci                                        int require_ca);
35e1051a39Sopenharmony_cistatic int no_check_purpose(const X509_PURPOSE *xp, const X509 *x,
36e1051a39Sopenharmony_ci                            int require_ca);
37e1051a39Sopenharmony_cistatic int check_purpose_ocsp_helper(const X509_PURPOSE *xp, const X509 *x,
38e1051a39Sopenharmony_ci                                     int require_ca);
39e1051a39Sopenharmony_ci
40e1051a39Sopenharmony_cistatic int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b);
41e1051a39Sopenharmony_cistatic void xptable_free(X509_PURPOSE *p);
42e1051a39Sopenharmony_ci
43e1051a39Sopenharmony_cistatic X509_PURPOSE xstandard[] = {
44e1051a39Sopenharmony_ci    {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0,
45e1051a39Sopenharmony_ci     check_purpose_ssl_client, "SSL client", "sslclient", NULL},
46e1051a39Sopenharmony_ci    {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
47e1051a39Sopenharmony_ci     check_purpose_ssl_server, "SSL server", "sslserver", NULL},
48e1051a39Sopenharmony_ci    {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
49e1051a39Sopenharmony_ci     check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL},
50e1051a39Sopenharmony_ci    {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign,
51e1051a39Sopenharmony_ci     "S/MIME signing", "smimesign", NULL},
52e1051a39Sopenharmony_ci    {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0,
53e1051a39Sopenharmony_ci     check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL},
54e1051a39Sopenharmony_ci    {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign,
55e1051a39Sopenharmony_ci     "CRL signing", "crlsign", NULL},
56e1051a39Sopenharmony_ci    {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check_purpose,
57e1051a39Sopenharmony_ci     "Any Purpose", "any",
58e1051a39Sopenharmony_ci     NULL},
59e1051a39Sopenharmony_ci    {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, check_purpose_ocsp_helper,
60e1051a39Sopenharmony_ci     "OCSP helper", "ocsphelper", NULL},
61e1051a39Sopenharmony_ci    {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0,
62e1051a39Sopenharmony_ci     check_purpose_timestamp_sign, "Time Stamp signing", "timestampsign",
63e1051a39Sopenharmony_ci     NULL},
64e1051a39Sopenharmony_ci};
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_ci#define X509_PURPOSE_COUNT OSSL_NELEM(xstandard)
67e1051a39Sopenharmony_ci
68e1051a39Sopenharmony_cistatic STACK_OF(X509_PURPOSE) *xptable = NULL;
69e1051a39Sopenharmony_ci
70e1051a39Sopenharmony_cistatic int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b)
71e1051a39Sopenharmony_ci{
72e1051a39Sopenharmony_ci    return (*a)->purpose - (*b)->purpose;
73e1051a39Sopenharmony_ci}
74e1051a39Sopenharmony_ci
75e1051a39Sopenharmony_ci/*
76e1051a39Sopenharmony_ci * As much as I'd like to make X509_check_purpose use a "const" X509* I really
77e1051a39Sopenharmony_ci * can't because it does recalculate hashes and do other non-const things.
78e1051a39Sopenharmony_ci * If id == -1 it just calls x509v3_cache_extensions() for its side-effect.
79e1051a39Sopenharmony_ci * Returns 1 on success, 0 if x does not allow purpose, -1 on (internal) error.
80e1051a39Sopenharmony_ci */
81e1051a39Sopenharmony_ciint X509_check_purpose(X509 *x, int id, int require_ca)
82e1051a39Sopenharmony_ci{
83e1051a39Sopenharmony_ci    int idx;
84e1051a39Sopenharmony_ci    const X509_PURPOSE *pt;
85e1051a39Sopenharmony_ci
86e1051a39Sopenharmony_ci    if (!ossl_x509v3_cache_extensions(x))
87e1051a39Sopenharmony_ci        return -1;
88e1051a39Sopenharmony_ci    if (id == -1)
89e1051a39Sopenharmony_ci        return 1;
90e1051a39Sopenharmony_ci
91e1051a39Sopenharmony_ci    idx = X509_PURPOSE_get_by_id(id);
92e1051a39Sopenharmony_ci    if (idx == -1)
93e1051a39Sopenharmony_ci        return -1;
94e1051a39Sopenharmony_ci    pt = X509_PURPOSE_get0(idx);
95e1051a39Sopenharmony_ci    return pt->check_purpose(pt, x, require_ca);
96e1051a39Sopenharmony_ci}
97e1051a39Sopenharmony_ci
98e1051a39Sopenharmony_ciint X509_PURPOSE_set(int *p, int purpose)
99e1051a39Sopenharmony_ci{
100e1051a39Sopenharmony_ci    if (X509_PURPOSE_get_by_id(purpose) == -1) {
101e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_PURPOSE);
102e1051a39Sopenharmony_ci        return 0;
103e1051a39Sopenharmony_ci    }
104e1051a39Sopenharmony_ci    *p = purpose;
105e1051a39Sopenharmony_ci    return 1;
106e1051a39Sopenharmony_ci}
107e1051a39Sopenharmony_ci
108e1051a39Sopenharmony_ciint X509_PURPOSE_get_count(void)
109e1051a39Sopenharmony_ci{
110e1051a39Sopenharmony_ci    if (!xptable)
111e1051a39Sopenharmony_ci        return X509_PURPOSE_COUNT;
112e1051a39Sopenharmony_ci    return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT;
113e1051a39Sopenharmony_ci}
114e1051a39Sopenharmony_ci
115e1051a39Sopenharmony_ciX509_PURPOSE *X509_PURPOSE_get0(int idx)
116e1051a39Sopenharmony_ci{
117e1051a39Sopenharmony_ci    if (idx < 0)
118e1051a39Sopenharmony_ci        return NULL;
119e1051a39Sopenharmony_ci    if (idx < (int)X509_PURPOSE_COUNT)
120e1051a39Sopenharmony_ci        return xstandard + idx;
121e1051a39Sopenharmony_ci    return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT);
122e1051a39Sopenharmony_ci}
123e1051a39Sopenharmony_ci
124e1051a39Sopenharmony_ciint X509_PURPOSE_get_by_sname(const char *sname)
125e1051a39Sopenharmony_ci{
126e1051a39Sopenharmony_ci    int i;
127e1051a39Sopenharmony_ci    X509_PURPOSE *xptmp;
128e1051a39Sopenharmony_ci    for (i = 0; i < X509_PURPOSE_get_count(); i++) {
129e1051a39Sopenharmony_ci        xptmp = X509_PURPOSE_get0(i);
130e1051a39Sopenharmony_ci        if (strcmp(xptmp->sname, sname) == 0)
131e1051a39Sopenharmony_ci            return i;
132e1051a39Sopenharmony_ci    }
133e1051a39Sopenharmony_ci    return -1;
134e1051a39Sopenharmony_ci}
135e1051a39Sopenharmony_ci
136e1051a39Sopenharmony_ci/* Returns -1 on error, else an index => 0 in standard/extended purpose table */
137e1051a39Sopenharmony_ciint X509_PURPOSE_get_by_id(int purpose)
138e1051a39Sopenharmony_ci{
139e1051a39Sopenharmony_ci    X509_PURPOSE tmp;
140e1051a39Sopenharmony_ci    int idx;
141e1051a39Sopenharmony_ci
142e1051a39Sopenharmony_ci    if (purpose >= X509_PURPOSE_MIN && purpose <= X509_PURPOSE_MAX)
143e1051a39Sopenharmony_ci        return purpose - X509_PURPOSE_MIN;
144e1051a39Sopenharmony_ci    if (xptable == NULL)
145e1051a39Sopenharmony_ci        return -1;
146e1051a39Sopenharmony_ci    tmp.purpose = purpose;
147e1051a39Sopenharmony_ci    idx = sk_X509_PURPOSE_find(xptable, &tmp);
148e1051a39Sopenharmony_ci    if (idx < 0)
149e1051a39Sopenharmony_ci        return -1;
150e1051a39Sopenharmony_ci    return idx + X509_PURPOSE_COUNT;
151e1051a39Sopenharmony_ci}
152e1051a39Sopenharmony_ci
153e1051a39Sopenharmony_ciint X509_PURPOSE_add(int id, int trust, int flags,
154e1051a39Sopenharmony_ci                     int (*ck) (const X509_PURPOSE *, const X509 *, int),
155e1051a39Sopenharmony_ci                     const char *name, const char *sname, void *arg)
156e1051a39Sopenharmony_ci{
157e1051a39Sopenharmony_ci    int idx;
158e1051a39Sopenharmony_ci    X509_PURPOSE *ptmp;
159e1051a39Sopenharmony_ci
160e1051a39Sopenharmony_ci    /* This is set according to what we change: application can't set it */
161e1051a39Sopenharmony_ci    flags &= ~X509_PURPOSE_DYNAMIC;
162e1051a39Sopenharmony_ci    /* This will always be set for application modified trust entries */
163e1051a39Sopenharmony_ci    flags |= X509_PURPOSE_DYNAMIC_NAME;
164e1051a39Sopenharmony_ci    /* Get existing entry if any */
165e1051a39Sopenharmony_ci    idx = X509_PURPOSE_get_by_id(id);
166e1051a39Sopenharmony_ci    /* Need a new entry */
167e1051a39Sopenharmony_ci    if (idx == -1) {
168e1051a39Sopenharmony_ci        if ((ptmp = OPENSSL_malloc(sizeof(*ptmp))) == NULL) {
169e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
170e1051a39Sopenharmony_ci            return 0;
171e1051a39Sopenharmony_ci        }
172e1051a39Sopenharmony_ci        ptmp->flags = X509_PURPOSE_DYNAMIC;
173e1051a39Sopenharmony_ci    } else
174e1051a39Sopenharmony_ci        ptmp = X509_PURPOSE_get0(idx);
175e1051a39Sopenharmony_ci
176e1051a39Sopenharmony_ci    /* OPENSSL_free existing name if dynamic */
177e1051a39Sopenharmony_ci    if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
178e1051a39Sopenharmony_ci        OPENSSL_free(ptmp->name);
179e1051a39Sopenharmony_ci        OPENSSL_free(ptmp->sname);
180e1051a39Sopenharmony_ci    }
181e1051a39Sopenharmony_ci    /* Dup supplied name */
182e1051a39Sopenharmony_ci    ptmp->name = OPENSSL_strdup(name);
183e1051a39Sopenharmony_ci    ptmp->sname = OPENSSL_strdup(sname);
184e1051a39Sopenharmony_ci    if (ptmp->name == NULL|| ptmp->sname == NULL) {
185e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
186e1051a39Sopenharmony_ci        goto err;
187e1051a39Sopenharmony_ci    }
188e1051a39Sopenharmony_ci    /* Keep the dynamic flag of existing entry */
189e1051a39Sopenharmony_ci    ptmp->flags &= X509_PURPOSE_DYNAMIC;
190e1051a39Sopenharmony_ci    /* Set all other flags */
191e1051a39Sopenharmony_ci    ptmp->flags |= flags;
192e1051a39Sopenharmony_ci
193e1051a39Sopenharmony_ci    ptmp->purpose = id;
194e1051a39Sopenharmony_ci    ptmp->trust = trust;
195e1051a39Sopenharmony_ci    ptmp->check_purpose = ck;
196e1051a39Sopenharmony_ci    ptmp->usr_data = arg;
197e1051a39Sopenharmony_ci
198e1051a39Sopenharmony_ci    /* If its a new entry manage the dynamic table */
199e1051a39Sopenharmony_ci    if (idx == -1) {
200e1051a39Sopenharmony_ci        if (xptable == NULL
201e1051a39Sopenharmony_ci            && (xptable = sk_X509_PURPOSE_new(xp_cmp)) == NULL) {
202e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
203e1051a39Sopenharmony_ci            goto err;
204e1051a39Sopenharmony_ci        }
205e1051a39Sopenharmony_ci        if (!sk_X509_PURPOSE_push(xptable, ptmp)) {
206e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
207e1051a39Sopenharmony_ci            goto err;
208e1051a39Sopenharmony_ci        }
209e1051a39Sopenharmony_ci    }
210e1051a39Sopenharmony_ci    return 1;
211e1051a39Sopenharmony_ci err:
212e1051a39Sopenharmony_ci    if (idx == -1) {
213e1051a39Sopenharmony_ci        OPENSSL_free(ptmp->name);
214e1051a39Sopenharmony_ci        OPENSSL_free(ptmp->sname);
215e1051a39Sopenharmony_ci        OPENSSL_free(ptmp);
216e1051a39Sopenharmony_ci    }
217e1051a39Sopenharmony_ci    return 0;
218e1051a39Sopenharmony_ci}
219e1051a39Sopenharmony_ci
220e1051a39Sopenharmony_cistatic void xptable_free(X509_PURPOSE *p)
221e1051a39Sopenharmony_ci{
222e1051a39Sopenharmony_ci    if (p == NULL)
223e1051a39Sopenharmony_ci        return;
224e1051a39Sopenharmony_ci    if (p->flags & X509_PURPOSE_DYNAMIC) {
225e1051a39Sopenharmony_ci        if (p->flags & X509_PURPOSE_DYNAMIC_NAME) {
226e1051a39Sopenharmony_ci            OPENSSL_free(p->name);
227e1051a39Sopenharmony_ci            OPENSSL_free(p->sname);
228e1051a39Sopenharmony_ci        }
229e1051a39Sopenharmony_ci        OPENSSL_free(p);
230e1051a39Sopenharmony_ci    }
231e1051a39Sopenharmony_ci}
232e1051a39Sopenharmony_ci
233e1051a39Sopenharmony_civoid X509_PURPOSE_cleanup(void)
234e1051a39Sopenharmony_ci{
235e1051a39Sopenharmony_ci    sk_X509_PURPOSE_pop_free(xptable, xptable_free);
236e1051a39Sopenharmony_ci    xptable = NULL;
237e1051a39Sopenharmony_ci}
238e1051a39Sopenharmony_ci
239e1051a39Sopenharmony_ciint X509_PURPOSE_get_id(const X509_PURPOSE *xp)
240e1051a39Sopenharmony_ci{
241e1051a39Sopenharmony_ci    return xp->purpose;
242e1051a39Sopenharmony_ci}
243e1051a39Sopenharmony_ci
244e1051a39Sopenharmony_cichar *X509_PURPOSE_get0_name(const X509_PURPOSE *xp)
245e1051a39Sopenharmony_ci{
246e1051a39Sopenharmony_ci    return xp->name;
247e1051a39Sopenharmony_ci}
248e1051a39Sopenharmony_ci
249e1051a39Sopenharmony_cichar *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp)
250e1051a39Sopenharmony_ci{
251e1051a39Sopenharmony_ci    return xp->sname;
252e1051a39Sopenharmony_ci}
253e1051a39Sopenharmony_ci
254e1051a39Sopenharmony_ciint X509_PURPOSE_get_trust(const X509_PURPOSE *xp)
255e1051a39Sopenharmony_ci{
256e1051a39Sopenharmony_ci    return xp->trust;
257e1051a39Sopenharmony_ci}
258e1051a39Sopenharmony_ci
259e1051a39Sopenharmony_cistatic int nid_cmp(const int *a, const int *b)
260e1051a39Sopenharmony_ci{
261e1051a39Sopenharmony_ci    return *a - *b;
262e1051a39Sopenharmony_ci}
263e1051a39Sopenharmony_ci
264e1051a39Sopenharmony_ciDECLARE_OBJ_BSEARCH_CMP_FN(int, int, nid);
265e1051a39Sopenharmony_ciIMPLEMENT_OBJ_BSEARCH_CMP_FN(int, int, nid);
266e1051a39Sopenharmony_ci
267e1051a39Sopenharmony_ciint X509_supported_extension(X509_EXTENSION *ex)
268e1051a39Sopenharmony_ci{
269e1051a39Sopenharmony_ci    /*
270e1051a39Sopenharmony_ci     * This table is a list of the NIDs of supported extensions: that is
271e1051a39Sopenharmony_ci     * those which are used by the verify process. If an extension is
272e1051a39Sopenharmony_ci     * critical and doesn't appear in this list then the verify process will
273e1051a39Sopenharmony_ci     * normally reject the certificate. The list must be kept in numerical
274e1051a39Sopenharmony_ci     * order because it will be searched using bsearch.
275e1051a39Sopenharmony_ci     */
276e1051a39Sopenharmony_ci    static const int supported_nids[] = {
277e1051a39Sopenharmony_ci        NID_netscape_cert_type, /* 71 */
278e1051a39Sopenharmony_ci        NID_key_usage,          /* 83 */
279e1051a39Sopenharmony_ci        NID_subject_alt_name,   /* 85 */
280e1051a39Sopenharmony_ci        NID_basic_constraints,  /* 87 */
281e1051a39Sopenharmony_ci        NID_certificate_policies, /* 89 */
282e1051a39Sopenharmony_ci        NID_crl_distribution_points, /* 103 */
283e1051a39Sopenharmony_ci        NID_ext_key_usage,      /* 126 */
284e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_RFC3779
285e1051a39Sopenharmony_ci        NID_sbgp_ipAddrBlock,   /* 290 */
286e1051a39Sopenharmony_ci        NID_sbgp_autonomousSysNum, /* 291 */
287e1051a39Sopenharmony_ci#endif
288e1051a39Sopenharmony_ci        NID_id_pkix_OCSP_noCheck, /* 369 */
289e1051a39Sopenharmony_ci        NID_policy_constraints, /* 401 */
290e1051a39Sopenharmony_ci        NID_proxyCertInfo,      /* 663 */
291e1051a39Sopenharmony_ci        NID_name_constraints,   /* 666 */
292e1051a39Sopenharmony_ci        NID_policy_mappings,    /* 747 */
293e1051a39Sopenharmony_ci        NID_inhibit_any_policy  /* 748 */
294e1051a39Sopenharmony_ci    };
295e1051a39Sopenharmony_ci
296e1051a39Sopenharmony_ci    int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
297e1051a39Sopenharmony_ci
298e1051a39Sopenharmony_ci    if (ex_nid == NID_undef)
299e1051a39Sopenharmony_ci        return 0;
300e1051a39Sopenharmony_ci
301e1051a39Sopenharmony_ci    if (OBJ_bsearch_nid(&ex_nid, supported_nids, OSSL_NELEM(supported_nids)))
302e1051a39Sopenharmony_ci        return 1;
303e1051a39Sopenharmony_ci    return 0;
304e1051a39Sopenharmony_ci}
305e1051a39Sopenharmony_ci
306e1051a39Sopenharmony_ci/* Returns 1 on success, 0 if x is invalid, -1 on (internal) error. */
307e1051a39Sopenharmony_cistatic int setup_dp(const X509 *x, DIST_POINT *dp)
308e1051a39Sopenharmony_ci{
309e1051a39Sopenharmony_ci    const X509_NAME *iname = NULL;
310e1051a39Sopenharmony_ci    int i;
311e1051a39Sopenharmony_ci
312e1051a39Sopenharmony_ci    if (dp->distpoint == NULL && sk_GENERAL_NAME_num(dp->CRLissuer) <= 0) {
313e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, X509_R_INVALID_DISTPOINT);
314e1051a39Sopenharmony_ci        return 0;
315e1051a39Sopenharmony_ci    }
316e1051a39Sopenharmony_ci    if (dp->reasons != NULL) {
317e1051a39Sopenharmony_ci        if (dp->reasons->length > 0)
318e1051a39Sopenharmony_ci            dp->dp_reasons = dp->reasons->data[0];
319e1051a39Sopenharmony_ci        if (dp->reasons->length > 1)
320e1051a39Sopenharmony_ci            dp->dp_reasons |= (dp->reasons->data[1] << 8);
321e1051a39Sopenharmony_ci        dp->dp_reasons &= CRLDP_ALL_REASONS;
322e1051a39Sopenharmony_ci    } else {
323e1051a39Sopenharmony_ci        dp->dp_reasons = CRLDP_ALL_REASONS;
324e1051a39Sopenharmony_ci    }
325e1051a39Sopenharmony_ci    if (dp->distpoint == NULL || dp->distpoint->type != 1)
326e1051a39Sopenharmony_ci        return 1;
327e1051a39Sopenharmony_ci
328e1051a39Sopenharmony_ci    /* Handle name fragment given by nameRelativeToCRLIssuer */
329e1051a39Sopenharmony_ci    /*
330e1051a39Sopenharmony_ci     * Note that the below way of determining iname is not really compliant
331e1051a39Sopenharmony_ci     * with https://tools.ietf.org/html/rfc5280#section-4.2.1.13
332e1051a39Sopenharmony_ci     * According to it, sk_GENERAL_NAME_num(dp->CRLissuer) MUST be <= 1
333e1051a39Sopenharmony_ci     * and any CRLissuer could be of type different to GEN_DIRNAME.
334e1051a39Sopenharmony_ci     */
335e1051a39Sopenharmony_ci    for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) {
336e1051a39Sopenharmony_ci        GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
337e1051a39Sopenharmony_ci
338e1051a39Sopenharmony_ci        if (gen->type == GEN_DIRNAME) {
339e1051a39Sopenharmony_ci            iname = gen->d.directoryName;
340e1051a39Sopenharmony_ci            break;
341e1051a39Sopenharmony_ci        }
342e1051a39Sopenharmony_ci    }
343e1051a39Sopenharmony_ci    if (iname == NULL)
344e1051a39Sopenharmony_ci        iname = X509_get_issuer_name(x);
345e1051a39Sopenharmony_ci    return DIST_POINT_set_dpname(dp->distpoint, iname) ? 1 : -1;
346e1051a39Sopenharmony_ci}
347e1051a39Sopenharmony_ci
348e1051a39Sopenharmony_ci/* Return 1 on success, 0 if x is invalid, -1 on (internal) error. */
349e1051a39Sopenharmony_cistatic int setup_crldp(X509 *x)
350e1051a39Sopenharmony_ci{
351e1051a39Sopenharmony_ci    int i;
352e1051a39Sopenharmony_ci
353e1051a39Sopenharmony_ci    x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, &i, NULL);
354e1051a39Sopenharmony_ci    if (x->crldp == NULL && i != -1)
355e1051a39Sopenharmony_ci        return 0;
356e1051a39Sopenharmony_ci
357e1051a39Sopenharmony_ci    for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) {
358e1051a39Sopenharmony_ci        int res = setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
359e1051a39Sopenharmony_ci
360e1051a39Sopenharmony_ci        if (res < 1)
361e1051a39Sopenharmony_ci            return res;
362e1051a39Sopenharmony_ci    }
363e1051a39Sopenharmony_ci    return 1;
364e1051a39Sopenharmony_ci}
365e1051a39Sopenharmony_ci
366e1051a39Sopenharmony_ci/* Check that issuer public key algorithm matches subject signature algorithm */
367e1051a39Sopenharmony_cistatic int check_sig_alg_match(const EVP_PKEY *issuer_key, const X509 *subject)
368e1051a39Sopenharmony_ci{
369e1051a39Sopenharmony_ci    int subj_sig_nid;
370e1051a39Sopenharmony_ci
371e1051a39Sopenharmony_ci    if (issuer_key == NULL)
372e1051a39Sopenharmony_ci        return X509_V_ERR_NO_ISSUER_PUBLIC_KEY;
373e1051a39Sopenharmony_ci    if (OBJ_find_sigid_algs(OBJ_obj2nid(subject->cert_info.signature.algorithm),
374e1051a39Sopenharmony_ci                            NULL, &subj_sig_nid) == 0)
375e1051a39Sopenharmony_ci         return X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM;
376e1051a39Sopenharmony_ci    if (EVP_PKEY_is_a(issuer_key, OBJ_nid2sn(subj_sig_nid))
377e1051a39Sopenharmony_ci        || (EVP_PKEY_is_a(issuer_key, "RSA") && subj_sig_nid == NID_rsassaPss))
378e1051a39Sopenharmony_ci        return X509_V_OK;
379e1051a39Sopenharmony_ci    return X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH;
380e1051a39Sopenharmony_ci}
381e1051a39Sopenharmony_ci
382e1051a39Sopenharmony_ci#define V1_ROOT (EXFLAG_V1|EXFLAG_SS)
383e1051a39Sopenharmony_ci#define ku_reject(x, usage) \
384e1051a39Sopenharmony_ci    (((x)->ex_flags & EXFLAG_KUSAGE) != 0 && ((x)->ex_kusage & (usage)) == 0)
385e1051a39Sopenharmony_ci#define xku_reject(x, usage) \
386e1051a39Sopenharmony_ci    (((x)->ex_flags & EXFLAG_XKUSAGE) != 0 && ((x)->ex_xkusage & (usage)) == 0)
387e1051a39Sopenharmony_ci#define ns_reject(x, usage) \
388e1051a39Sopenharmony_ci    (((x)->ex_flags & EXFLAG_NSCERT) != 0 && ((x)->ex_nscert & (usage)) == 0)
389e1051a39Sopenharmony_ci
390e1051a39Sopenharmony_ci/*
391e1051a39Sopenharmony_ci * Cache info on various X.509v3 extensions and further derived information,
392e1051a39Sopenharmony_ci * e.g., if cert 'x' is self-issued, in x->ex_flags and other internal fields.
393e1051a39Sopenharmony_ci * x->sha1_hash is filled in, or else EXFLAG_NO_FINGERPRINT is set in x->flags.
394e1051a39Sopenharmony_ci * X509_SIG_INFO_VALID is set in x->flags if x->siginf was filled successfully.
395e1051a39Sopenharmony_ci * Set EXFLAG_INVALID and return 0 in case the certificate is invalid.
396e1051a39Sopenharmony_ci */
397e1051a39Sopenharmony_ciint ossl_x509v3_cache_extensions(X509 *x)
398e1051a39Sopenharmony_ci{
399e1051a39Sopenharmony_ci    BASIC_CONSTRAINTS *bs;
400e1051a39Sopenharmony_ci    PROXY_CERT_INFO_EXTENSION *pci;
401e1051a39Sopenharmony_ci    ASN1_BIT_STRING *usage;
402e1051a39Sopenharmony_ci    ASN1_BIT_STRING *ns;
403e1051a39Sopenharmony_ci    EXTENDED_KEY_USAGE *extusage;
404e1051a39Sopenharmony_ci    int i;
405e1051a39Sopenharmony_ci    int res;
406e1051a39Sopenharmony_ci
407e1051a39Sopenharmony_ci#ifdef tsan_ld_acq
408e1051a39Sopenharmony_ci    /* Fast lock-free check, see end of the function for details. */
409e1051a39Sopenharmony_ci    if (tsan_ld_acq((TSAN_QUALIFIER int *)&x->ex_cached))
410e1051a39Sopenharmony_ci        return (x->ex_flags & EXFLAG_INVALID) == 0;
411e1051a39Sopenharmony_ci#endif
412e1051a39Sopenharmony_ci
413e1051a39Sopenharmony_ci    if (!CRYPTO_THREAD_write_lock(x->lock))
414e1051a39Sopenharmony_ci        return 0;
415e1051a39Sopenharmony_ci    if (x->ex_flags & EXFLAG_SET) { /* Cert has already been processed */
416e1051a39Sopenharmony_ci        CRYPTO_THREAD_unlock(x->lock);
417e1051a39Sopenharmony_ci        return (x->ex_flags & EXFLAG_INVALID) == 0;
418e1051a39Sopenharmony_ci    }
419e1051a39Sopenharmony_ci
420e1051a39Sopenharmony_ci    /* Cache the SHA1 digest of the cert */
421e1051a39Sopenharmony_ci    if (!X509_digest(x, EVP_sha1(), x->sha1_hash, NULL))
422e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_NO_FINGERPRINT;
423e1051a39Sopenharmony_ci
424e1051a39Sopenharmony_ci    ERR_set_mark();
425e1051a39Sopenharmony_ci
426e1051a39Sopenharmony_ci    /* V1 should mean no extensions ... */
427e1051a39Sopenharmony_ci    if (X509_get_version(x) == X509_VERSION_1)
428e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_V1;
429e1051a39Sopenharmony_ci
430e1051a39Sopenharmony_ci    /* Handle basic constraints */
431e1051a39Sopenharmony_ci    x->ex_pathlen = -1;
432e1051a39Sopenharmony_ci    if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, &i, NULL)) != NULL) {
433e1051a39Sopenharmony_ci        if (bs->ca)
434e1051a39Sopenharmony_ci            x->ex_flags |= EXFLAG_CA;
435e1051a39Sopenharmony_ci        if (bs->pathlen != NULL) {
436e1051a39Sopenharmony_ci            /*
437e1051a39Sopenharmony_ci             * The error case !bs->ca is checked by check_chain()
438e1051a39Sopenharmony_ci             * in case ctx->param->flags & X509_V_FLAG_X509_STRICT
439e1051a39Sopenharmony_ci             */
440e1051a39Sopenharmony_ci            if (bs->pathlen->type == V_ASN1_NEG_INTEGER) {
441e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509, X509V3_R_NEGATIVE_PATHLEN);
442e1051a39Sopenharmony_ci                x->ex_flags |= EXFLAG_INVALID;
443e1051a39Sopenharmony_ci            } else {
444e1051a39Sopenharmony_ci                x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
445e1051a39Sopenharmony_ci            }
446e1051a39Sopenharmony_ci        }
447e1051a39Sopenharmony_ci        BASIC_CONSTRAINTS_free(bs);
448e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_BCONS;
449e1051a39Sopenharmony_ci    } else if (i != -1) {
450e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_INVALID;
451e1051a39Sopenharmony_ci    }
452e1051a39Sopenharmony_ci
453e1051a39Sopenharmony_ci    /* Handle proxy certificates */
454e1051a39Sopenharmony_ci    if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, &i, NULL)) != NULL) {
455e1051a39Sopenharmony_ci        if (x->ex_flags & EXFLAG_CA
456e1051a39Sopenharmony_ci            || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0
457e1051a39Sopenharmony_ci            || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) {
458e1051a39Sopenharmony_ci            x->ex_flags |= EXFLAG_INVALID;
459e1051a39Sopenharmony_ci        }
460e1051a39Sopenharmony_ci        if (pci->pcPathLengthConstraint != NULL)
461e1051a39Sopenharmony_ci            x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint);
462e1051a39Sopenharmony_ci        else
463e1051a39Sopenharmony_ci            x->ex_pcpathlen = -1;
464e1051a39Sopenharmony_ci        PROXY_CERT_INFO_EXTENSION_free(pci);
465e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_PROXY;
466e1051a39Sopenharmony_ci    } else if (i != -1) {
467e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_INVALID;
468e1051a39Sopenharmony_ci    }
469e1051a39Sopenharmony_ci
470e1051a39Sopenharmony_ci    /* Handle (basic) key usage */
471e1051a39Sopenharmony_ci    if ((usage = X509_get_ext_d2i(x, NID_key_usage, &i, NULL)) != NULL) {
472e1051a39Sopenharmony_ci        x->ex_kusage = 0;
473e1051a39Sopenharmony_ci        if (usage->length > 0) {
474e1051a39Sopenharmony_ci            x->ex_kusage = usage->data[0];
475e1051a39Sopenharmony_ci            if (usage->length > 1)
476e1051a39Sopenharmony_ci                x->ex_kusage |= usage->data[1] << 8;
477e1051a39Sopenharmony_ci        }
478e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_KUSAGE;
479e1051a39Sopenharmony_ci        ASN1_BIT_STRING_free(usage);
480e1051a39Sopenharmony_ci        /* Check for empty key usage according to RFC 5280 section 4.2.1.3 */
481e1051a39Sopenharmony_ci        if (x->ex_kusage == 0) {
482e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509, X509V3_R_EMPTY_KEY_USAGE);
483e1051a39Sopenharmony_ci            x->ex_flags |= EXFLAG_INVALID;
484e1051a39Sopenharmony_ci        }
485e1051a39Sopenharmony_ci    } else if (i != -1) {
486e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_INVALID;
487e1051a39Sopenharmony_ci    }
488e1051a39Sopenharmony_ci
489e1051a39Sopenharmony_ci    /* Handle extended key usage */
490e1051a39Sopenharmony_ci    x->ex_xkusage = 0;
491e1051a39Sopenharmony_ci    if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, &i, NULL)) != NULL) {
492e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_XKUSAGE;
493e1051a39Sopenharmony_ci        for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
494e1051a39Sopenharmony_ci            switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) {
495e1051a39Sopenharmony_ci            case NID_server_auth:
496e1051a39Sopenharmony_ci                x->ex_xkusage |= XKU_SSL_SERVER;
497e1051a39Sopenharmony_ci                break;
498e1051a39Sopenharmony_ci            case NID_client_auth:
499e1051a39Sopenharmony_ci                x->ex_xkusage |= XKU_SSL_CLIENT;
500e1051a39Sopenharmony_ci                break;
501e1051a39Sopenharmony_ci            case NID_email_protect:
502e1051a39Sopenharmony_ci                x->ex_xkusage |= XKU_SMIME;
503e1051a39Sopenharmony_ci                break;
504e1051a39Sopenharmony_ci            case NID_code_sign:
505e1051a39Sopenharmony_ci                x->ex_xkusage |= XKU_CODE_SIGN;
506e1051a39Sopenharmony_ci                break;
507e1051a39Sopenharmony_ci            case NID_ms_sgc:
508e1051a39Sopenharmony_ci            case NID_ns_sgc:
509e1051a39Sopenharmony_ci                x->ex_xkusage |= XKU_SGC;
510e1051a39Sopenharmony_ci                break;
511e1051a39Sopenharmony_ci            case NID_OCSP_sign:
512e1051a39Sopenharmony_ci                x->ex_xkusage |= XKU_OCSP_SIGN;
513e1051a39Sopenharmony_ci                break;
514e1051a39Sopenharmony_ci            case NID_time_stamp:
515e1051a39Sopenharmony_ci                x->ex_xkusage |= XKU_TIMESTAMP;
516e1051a39Sopenharmony_ci                break;
517e1051a39Sopenharmony_ci            case NID_dvcs:
518e1051a39Sopenharmony_ci                x->ex_xkusage |= XKU_DVCS;
519e1051a39Sopenharmony_ci                break;
520e1051a39Sopenharmony_ci            case NID_anyExtendedKeyUsage:
521e1051a39Sopenharmony_ci                x->ex_xkusage |= XKU_ANYEKU;
522e1051a39Sopenharmony_ci                break;
523e1051a39Sopenharmony_ci            default:
524e1051a39Sopenharmony_ci                /* Ignore unknown extended key usage */
525e1051a39Sopenharmony_ci                break;
526e1051a39Sopenharmony_ci            }
527e1051a39Sopenharmony_ci        }
528e1051a39Sopenharmony_ci        sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
529e1051a39Sopenharmony_ci    } else if (i != -1) {
530e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_INVALID;
531e1051a39Sopenharmony_ci    }
532e1051a39Sopenharmony_ci
533e1051a39Sopenharmony_ci    /* Handle legacy Netscape extension */
534e1051a39Sopenharmony_ci    if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, &i, NULL)) != NULL) {
535e1051a39Sopenharmony_ci        if (ns->length > 0)
536e1051a39Sopenharmony_ci            x->ex_nscert = ns->data[0];
537e1051a39Sopenharmony_ci        else
538e1051a39Sopenharmony_ci            x->ex_nscert = 0;
539e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_NSCERT;
540e1051a39Sopenharmony_ci        ASN1_BIT_STRING_free(ns);
541e1051a39Sopenharmony_ci    } else if (i != -1) {
542e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_INVALID;
543e1051a39Sopenharmony_ci    }
544e1051a39Sopenharmony_ci
545e1051a39Sopenharmony_ci    /* Handle subject key identifier and issuer/authority key identifier */
546e1051a39Sopenharmony_ci    x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, &i, NULL);
547e1051a39Sopenharmony_ci    if (x->skid == NULL && i != -1)
548e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_INVALID;
549e1051a39Sopenharmony_ci
550e1051a39Sopenharmony_ci    x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, &i, NULL);
551e1051a39Sopenharmony_ci    if (x->akid == NULL && i != -1)
552e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_INVALID;
553e1051a39Sopenharmony_ci
554e1051a39Sopenharmony_ci    /* Check if subject name matches issuer */
555e1051a39Sopenharmony_ci    if (X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)) == 0) {
556e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_SI; /* Cert is self-issued */
557e1051a39Sopenharmony_ci        if (X509_check_akid(x, x->akid) == X509_V_OK /* SKID matches AKID */
558e1051a39Sopenharmony_ci                /* .. and the signature alg matches the PUBKEY alg: */
559e1051a39Sopenharmony_ci                && check_sig_alg_match(X509_get0_pubkey(x), x) == X509_V_OK)
560e1051a39Sopenharmony_ci            x->ex_flags |= EXFLAG_SS; /* indicate self-signed */
561e1051a39Sopenharmony_ci        /* This is very related to ossl_x509_likely_issued(x, x) == X509_V_OK */
562e1051a39Sopenharmony_ci    }
563e1051a39Sopenharmony_ci
564e1051a39Sopenharmony_ci    /* Handle subject alternative names and various other extensions */
565e1051a39Sopenharmony_ci    x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, &i, NULL);
566e1051a39Sopenharmony_ci    if (x->altname == NULL && i != -1)
567e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_INVALID;
568e1051a39Sopenharmony_ci    x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL);
569e1051a39Sopenharmony_ci    if (x->nc == NULL && i != -1)
570e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_INVALID;
571e1051a39Sopenharmony_ci
572e1051a39Sopenharmony_ci    /* Handle CRL distribution point entries */
573e1051a39Sopenharmony_ci    res = setup_crldp(x);
574e1051a39Sopenharmony_ci    if (res == 0)
575e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_INVALID;
576e1051a39Sopenharmony_ci    else if (res < 0)
577e1051a39Sopenharmony_ci        goto err;
578e1051a39Sopenharmony_ci
579e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_RFC3779
580e1051a39Sopenharmony_ci    x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, &i, NULL);
581e1051a39Sopenharmony_ci    if (x->rfc3779_addr == NULL && i != -1)
582e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_INVALID;
583e1051a39Sopenharmony_ci    x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, &i, NULL);
584e1051a39Sopenharmony_ci    if (x->rfc3779_asid == NULL && i != -1)
585e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_INVALID;
586e1051a39Sopenharmony_ci#endif
587e1051a39Sopenharmony_ci    for (i = 0; i < X509_get_ext_count(x); i++) {
588e1051a39Sopenharmony_ci        X509_EXTENSION *ex = X509_get_ext(x, i);
589e1051a39Sopenharmony_ci        int nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
590e1051a39Sopenharmony_ci
591e1051a39Sopenharmony_ci        if (nid == NID_freshest_crl)
592e1051a39Sopenharmony_ci            x->ex_flags |= EXFLAG_FRESHEST;
593e1051a39Sopenharmony_ci        if (!X509_EXTENSION_get_critical(ex))
594e1051a39Sopenharmony_ci            continue;
595e1051a39Sopenharmony_ci        if (!X509_supported_extension(ex)) {
596e1051a39Sopenharmony_ci            x->ex_flags |= EXFLAG_CRITICAL;
597e1051a39Sopenharmony_ci            break;
598e1051a39Sopenharmony_ci        }
599e1051a39Sopenharmony_ci        switch (nid) {
600e1051a39Sopenharmony_ci        case NID_basic_constraints:
601e1051a39Sopenharmony_ci            x->ex_flags |= EXFLAG_BCONS_CRITICAL;
602e1051a39Sopenharmony_ci            break;
603e1051a39Sopenharmony_ci        case NID_authority_key_identifier:
604e1051a39Sopenharmony_ci            x->ex_flags |= EXFLAG_AKID_CRITICAL;
605e1051a39Sopenharmony_ci            break;
606e1051a39Sopenharmony_ci        case NID_subject_key_identifier:
607e1051a39Sopenharmony_ci            x->ex_flags |= EXFLAG_SKID_CRITICAL;
608e1051a39Sopenharmony_ci            break;
609e1051a39Sopenharmony_ci        case NID_subject_alt_name:
610e1051a39Sopenharmony_ci            x->ex_flags |= EXFLAG_SAN_CRITICAL;
611e1051a39Sopenharmony_ci            break;
612e1051a39Sopenharmony_ci        default:
613e1051a39Sopenharmony_ci            break;
614e1051a39Sopenharmony_ci        }
615e1051a39Sopenharmony_ci    }
616e1051a39Sopenharmony_ci
617e1051a39Sopenharmony_ci    /* Set x->siginf, ignoring errors due to unsupported algos */
618e1051a39Sopenharmony_ci    (void)ossl_x509_init_sig_info(x);
619e1051a39Sopenharmony_ci
620e1051a39Sopenharmony_ci    x->ex_flags |= EXFLAG_SET; /* Indicate that cert has been processed */
621e1051a39Sopenharmony_ci#ifdef tsan_st_rel
622e1051a39Sopenharmony_ci    tsan_st_rel((TSAN_QUALIFIER int *)&x->ex_cached, 1);
623e1051a39Sopenharmony_ci    /*
624e1051a39Sopenharmony_ci     * Above store triggers fast lock-free check in the beginning of the
625e1051a39Sopenharmony_ci     * function. But one has to ensure that the structure is "stable", i.e.
626e1051a39Sopenharmony_ci     * all stores are visible on all processors. Hence the release fence.
627e1051a39Sopenharmony_ci     */
628e1051a39Sopenharmony_ci#endif
629e1051a39Sopenharmony_ci    ERR_pop_to_mark();
630e1051a39Sopenharmony_ci    if ((x->ex_flags & (EXFLAG_INVALID | EXFLAG_NO_FINGERPRINT)) == 0) {
631e1051a39Sopenharmony_ci        CRYPTO_THREAD_unlock(x->lock);
632e1051a39Sopenharmony_ci        return 1;
633e1051a39Sopenharmony_ci    }
634e1051a39Sopenharmony_ci    if ((x->ex_flags & EXFLAG_INVALID) != 0)
635e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509, X509V3_R_INVALID_CERTIFICATE);
636e1051a39Sopenharmony_ci    /* If computing sha1_hash failed the error queue already reflects this. */
637e1051a39Sopenharmony_ci
638e1051a39Sopenharmony_ci err:
639e1051a39Sopenharmony_ci    x->ex_flags |= EXFLAG_SET; /* indicate that cert has been processed */
640e1051a39Sopenharmony_ci    CRYPTO_THREAD_unlock(x->lock);
641e1051a39Sopenharmony_ci    return 0;
642e1051a39Sopenharmony_ci}
643e1051a39Sopenharmony_ci
644e1051a39Sopenharmony_ci/*-
645e1051a39Sopenharmony_ci * CA checks common to all purposes
646e1051a39Sopenharmony_ci * return codes:
647e1051a39Sopenharmony_ci * 0 not a CA
648e1051a39Sopenharmony_ci * 1 is a CA
649e1051a39Sopenharmony_ci * 2 Only possible in older versions of openSSL when basicConstraints are absent
650e1051a39Sopenharmony_ci *   new versions will not return this value. May be a CA
651e1051a39Sopenharmony_ci * 3 basicConstraints absent but self-signed V1.
652e1051a39Sopenharmony_ci * 4 basicConstraints absent but keyUsage present and keyCertSign asserted.
653e1051a39Sopenharmony_ci * 5 Netscape specific CA Flags present
654e1051a39Sopenharmony_ci */
655e1051a39Sopenharmony_ci
656e1051a39Sopenharmony_cistatic int check_ca(const X509 *x)
657e1051a39Sopenharmony_ci{
658e1051a39Sopenharmony_ci    /* keyUsage if present should allow cert signing */
659e1051a39Sopenharmony_ci    if (ku_reject(x, KU_KEY_CERT_SIGN))
660e1051a39Sopenharmony_ci        return 0;
661e1051a39Sopenharmony_ci    if ((x->ex_flags & EXFLAG_BCONS) != 0) {
662e1051a39Sopenharmony_ci        /* If basicConstraints says not a CA then say so */
663e1051a39Sopenharmony_ci        return (x->ex_flags & EXFLAG_CA) != 0;
664e1051a39Sopenharmony_ci    } else {
665e1051a39Sopenharmony_ci        /* We support V1 roots for...  uh, I don't really know why. */
666e1051a39Sopenharmony_ci        if ((x->ex_flags & V1_ROOT) == V1_ROOT)
667e1051a39Sopenharmony_ci            return 3;
668e1051a39Sopenharmony_ci        /*
669e1051a39Sopenharmony_ci         * If key usage present it must have certSign so tolerate it
670e1051a39Sopenharmony_ci         */
671e1051a39Sopenharmony_ci        else if (x->ex_flags & EXFLAG_KUSAGE)
672e1051a39Sopenharmony_ci            return 4;
673e1051a39Sopenharmony_ci        /* Older certificates could have Netscape-specific CA types */
674e1051a39Sopenharmony_ci        else if (x->ex_flags & EXFLAG_NSCERT && x->ex_nscert & NS_ANY_CA)
675e1051a39Sopenharmony_ci            return 5;
676e1051a39Sopenharmony_ci        /* Can this still be regarded a CA certificate?  I doubt it. */
677e1051a39Sopenharmony_ci        return 0;
678e1051a39Sopenharmony_ci    }
679e1051a39Sopenharmony_ci}
680e1051a39Sopenharmony_ci
681e1051a39Sopenharmony_civoid X509_set_proxy_flag(X509 *x)
682e1051a39Sopenharmony_ci{
683e1051a39Sopenharmony_ci    if (CRYPTO_THREAD_write_lock(x->lock)) {
684e1051a39Sopenharmony_ci        x->ex_flags |= EXFLAG_PROXY;
685e1051a39Sopenharmony_ci        CRYPTO_THREAD_unlock(x->lock);
686e1051a39Sopenharmony_ci    }
687e1051a39Sopenharmony_ci}
688e1051a39Sopenharmony_ci
689e1051a39Sopenharmony_civoid X509_set_proxy_pathlen(X509 *x, long l)
690e1051a39Sopenharmony_ci{
691e1051a39Sopenharmony_ci    x->ex_pcpathlen = l;
692e1051a39Sopenharmony_ci}
693e1051a39Sopenharmony_ci
694e1051a39Sopenharmony_ciint X509_check_ca(X509 *x)
695e1051a39Sopenharmony_ci{
696e1051a39Sopenharmony_ci    /* Note 0 normally means "not a CA" - but in this case means error. */
697e1051a39Sopenharmony_ci    if (!ossl_x509v3_cache_extensions(x))
698e1051a39Sopenharmony_ci        return 0;
699e1051a39Sopenharmony_ci
700e1051a39Sopenharmony_ci    return check_ca(x);
701e1051a39Sopenharmony_ci}
702e1051a39Sopenharmony_ci
703e1051a39Sopenharmony_ci/* Check SSL CA: common checks for SSL client and server. */
704e1051a39Sopenharmony_cistatic int check_ssl_ca(const X509 *x)
705e1051a39Sopenharmony_ci{
706e1051a39Sopenharmony_ci    int ca_ret = check_ca(x);
707e1051a39Sopenharmony_ci
708e1051a39Sopenharmony_ci    if (ca_ret == 0)
709e1051a39Sopenharmony_ci        return 0;
710e1051a39Sopenharmony_ci    /* Check nsCertType if present */
711e1051a39Sopenharmony_ci    return ca_ret != 5 || (x->ex_nscert & NS_SSL_CA) != 0;
712e1051a39Sopenharmony_ci}
713e1051a39Sopenharmony_ci
714e1051a39Sopenharmony_cistatic int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
715e1051a39Sopenharmony_ci                                    int require_ca)
716e1051a39Sopenharmony_ci{
717e1051a39Sopenharmony_ci    if (xku_reject(x, XKU_SSL_CLIENT))
718e1051a39Sopenharmony_ci        return 0;
719e1051a39Sopenharmony_ci    if (require_ca)
720e1051a39Sopenharmony_ci        return check_ssl_ca(x);
721e1051a39Sopenharmony_ci    /* We need to do digital signatures or key agreement */
722e1051a39Sopenharmony_ci    if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT))
723e1051a39Sopenharmony_ci        return 0;
724e1051a39Sopenharmony_ci    /* nsCertType if present should allow SSL client use */
725e1051a39Sopenharmony_ci    if (ns_reject(x, NS_SSL_CLIENT))
726e1051a39Sopenharmony_ci        return 0;
727e1051a39Sopenharmony_ci    return 1;
728e1051a39Sopenharmony_ci}
729e1051a39Sopenharmony_ci
730e1051a39Sopenharmony_ci/*
731e1051a39Sopenharmony_ci * Key usage needed for TLS/SSL server: digital signature, encipherment or
732e1051a39Sopenharmony_ci * key agreement. The ssl code can check this more thoroughly for individual
733e1051a39Sopenharmony_ci * key types.
734e1051a39Sopenharmony_ci */
735e1051a39Sopenharmony_ci#define KU_TLS \
736e1051a39Sopenharmony_ci        KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT
737e1051a39Sopenharmony_ci
738e1051a39Sopenharmony_cistatic int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
739e1051a39Sopenharmony_ci                                    int require_ca)
740e1051a39Sopenharmony_ci{
741e1051a39Sopenharmony_ci    if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC))
742e1051a39Sopenharmony_ci        return 0;
743e1051a39Sopenharmony_ci    if (require_ca)
744e1051a39Sopenharmony_ci        return check_ssl_ca(x);
745e1051a39Sopenharmony_ci
746e1051a39Sopenharmony_ci    if (ns_reject(x, NS_SSL_SERVER))
747e1051a39Sopenharmony_ci        return 0;
748e1051a39Sopenharmony_ci    if (ku_reject(x, KU_TLS))
749e1051a39Sopenharmony_ci        return 0;
750e1051a39Sopenharmony_ci
751e1051a39Sopenharmony_ci    return 1;
752e1051a39Sopenharmony_ci
753e1051a39Sopenharmony_ci}
754e1051a39Sopenharmony_ci
755e1051a39Sopenharmony_cistatic int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
756e1051a39Sopenharmony_ci                                       int require_ca)
757e1051a39Sopenharmony_ci{
758e1051a39Sopenharmony_ci    int ret;
759e1051a39Sopenharmony_ci    ret = check_purpose_ssl_server(xp, x, require_ca);
760e1051a39Sopenharmony_ci    if (!ret || require_ca)
761e1051a39Sopenharmony_ci        return ret;
762e1051a39Sopenharmony_ci    /* We need to encipher or Netscape complains */
763e1051a39Sopenharmony_ci    if (ku_reject(x, KU_KEY_ENCIPHERMENT))
764e1051a39Sopenharmony_ci        return 0;
765e1051a39Sopenharmony_ci    return ret;
766e1051a39Sopenharmony_ci}
767e1051a39Sopenharmony_ci
768e1051a39Sopenharmony_ci/* common S/MIME checks */
769e1051a39Sopenharmony_cistatic int purpose_smime(const X509 *x, int require_ca)
770e1051a39Sopenharmony_ci{
771e1051a39Sopenharmony_ci    if (xku_reject(x, XKU_SMIME))
772e1051a39Sopenharmony_ci        return 0;
773e1051a39Sopenharmony_ci    if (require_ca) {
774e1051a39Sopenharmony_ci        int ca_ret;
775e1051a39Sopenharmony_ci        ca_ret = check_ca(x);
776e1051a39Sopenharmony_ci        if (ca_ret == 0)
777e1051a39Sopenharmony_ci            return 0;
778e1051a39Sopenharmony_ci        /* Check nsCertType if present */
779e1051a39Sopenharmony_ci        if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA)
780e1051a39Sopenharmony_ci            return ca_ret;
781e1051a39Sopenharmony_ci        else
782e1051a39Sopenharmony_ci            return 0;
783e1051a39Sopenharmony_ci    }
784e1051a39Sopenharmony_ci    if (x->ex_flags & EXFLAG_NSCERT) {
785e1051a39Sopenharmony_ci        if (x->ex_nscert & NS_SMIME)
786e1051a39Sopenharmony_ci            return 1;
787e1051a39Sopenharmony_ci        /* Workaround for some buggy certificates */
788e1051a39Sopenharmony_ci        if (x->ex_nscert & NS_SSL_CLIENT)
789e1051a39Sopenharmony_ci            return 2;
790e1051a39Sopenharmony_ci        return 0;
791e1051a39Sopenharmony_ci    }
792e1051a39Sopenharmony_ci    return 1;
793e1051a39Sopenharmony_ci}
794e1051a39Sopenharmony_ci
795e1051a39Sopenharmony_cistatic int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
796e1051a39Sopenharmony_ci                                    int require_ca)
797e1051a39Sopenharmony_ci{
798e1051a39Sopenharmony_ci    int ret;
799e1051a39Sopenharmony_ci    ret = purpose_smime(x, require_ca);
800e1051a39Sopenharmony_ci    if (!ret || require_ca)
801e1051a39Sopenharmony_ci        return ret;
802e1051a39Sopenharmony_ci    if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION))
803e1051a39Sopenharmony_ci        return 0;
804e1051a39Sopenharmony_ci    return ret;
805e1051a39Sopenharmony_ci}
806e1051a39Sopenharmony_ci
807e1051a39Sopenharmony_cistatic int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
808e1051a39Sopenharmony_ci                                       int require_ca)
809e1051a39Sopenharmony_ci{
810e1051a39Sopenharmony_ci    int ret;
811e1051a39Sopenharmony_ci    ret = purpose_smime(x, require_ca);
812e1051a39Sopenharmony_ci    if (!ret || require_ca)
813e1051a39Sopenharmony_ci        return ret;
814e1051a39Sopenharmony_ci    if (ku_reject(x, KU_KEY_ENCIPHERMENT))
815e1051a39Sopenharmony_ci        return 0;
816e1051a39Sopenharmony_ci    return ret;
817e1051a39Sopenharmony_ci}
818e1051a39Sopenharmony_ci
819e1051a39Sopenharmony_cistatic int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
820e1051a39Sopenharmony_ci                                  int require_ca)
821e1051a39Sopenharmony_ci{
822e1051a39Sopenharmony_ci    if (require_ca) {
823e1051a39Sopenharmony_ci        int ca_ret;
824e1051a39Sopenharmony_ci        if ((ca_ret = check_ca(x)) != 2)
825e1051a39Sopenharmony_ci            return ca_ret;
826e1051a39Sopenharmony_ci        else
827e1051a39Sopenharmony_ci            return 0;
828e1051a39Sopenharmony_ci    }
829e1051a39Sopenharmony_ci    if (ku_reject(x, KU_CRL_SIGN))
830e1051a39Sopenharmony_ci        return 0;
831e1051a39Sopenharmony_ci    return 1;
832e1051a39Sopenharmony_ci}
833e1051a39Sopenharmony_ci
834e1051a39Sopenharmony_ci/*
835e1051a39Sopenharmony_ci * OCSP helper: this is *not* a full OCSP check. It just checks that each CA
836e1051a39Sopenharmony_ci * is valid. Additional checks must be made on the chain.
837e1051a39Sopenharmony_ci */
838e1051a39Sopenharmony_cistatic int check_purpose_ocsp_helper(const X509_PURPOSE *xp, const X509 *x,
839e1051a39Sopenharmony_ci                                     int require_ca)
840e1051a39Sopenharmony_ci{
841e1051a39Sopenharmony_ci    /*
842e1051a39Sopenharmony_ci     * Must be a valid CA.  Should we really support the "I don't know" value
843e1051a39Sopenharmony_ci     * (2)?
844e1051a39Sopenharmony_ci     */
845e1051a39Sopenharmony_ci    if (require_ca)
846e1051a39Sopenharmony_ci        return check_ca(x);
847e1051a39Sopenharmony_ci    /* Leaf certificate is checked in OCSP_verify() */
848e1051a39Sopenharmony_ci    return 1;
849e1051a39Sopenharmony_ci}
850e1051a39Sopenharmony_ci
851e1051a39Sopenharmony_cistatic int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
852e1051a39Sopenharmony_ci                                        int require_ca)
853e1051a39Sopenharmony_ci{
854e1051a39Sopenharmony_ci    int i_ext;
855e1051a39Sopenharmony_ci
856e1051a39Sopenharmony_ci    /* If ca is true we must return if this is a valid CA certificate. */
857e1051a39Sopenharmony_ci    if (require_ca)
858e1051a39Sopenharmony_ci        return check_ca(x);
859e1051a39Sopenharmony_ci
860e1051a39Sopenharmony_ci    /*
861e1051a39Sopenharmony_ci     * Check the optional key usage field:
862e1051a39Sopenharmony_ci     * if Key Usage is present, it must be one of digitalSignature
863e1051a39Sopenharmony_ci     * and/or nonRepudiation (other values are not consistent and shall
864e1051a39Sopenharmony_ci     * be rejected).
865e1051a39Sopenharmony_ci     */
866e1051a39Sopenharmony_ci    if ((x->ex_flags & EXFLAG_KUSAGE)
867e1051a39Sopenharmony_ci        && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) ||
868e1051a39Sopenharmony_ci            !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE))))
869e1051a39Sopenharmony_ci        return 0;
870e1051a39Sopenharmony_ci
871e1051a39Sopenharmony_ci    /* Only time stamp key usage is permitted and it's required. */
872e1051a39Sopenharmony_ci    if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP)
873e1051a39Sopenharmony_ci        return 0;
874e1051a39Sopenharmony_ci
875e1051a39Sopenharmony_ci    /* Extended Key Usage MUST be critical */
876e1051a39Sopenharmony_ci    i_ext = X509_get_ext_by_NID(x, NID_ext_key_usage, -1);
877e1051a39Sopenharmony_ci    if (i_ext >= 0) {
878e1051a39Sopenharmony_ci        X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext);
879e1051a39Sopenharmony_ci        if (!X509_EXTENSION_get_critical(ext))
880e1051a39Sopenharmony_ci            return 0;
881e1051a39Sopenharmony_ci    }
882e1051a39Sopenharmony_ci
883e1051a39Sopenharmony_ci    return 1;
884e1051a39Sopenharmony_ci}
885e1051a39Sopenharmony_ci
886e1051a39Sopenharmony_cistatic int no_check_purpose(const X509_PURPOSE *xp, const X509 *x,
887e1051a39Sopenharmony_ci                            int require_ca)
888e1051a39Sopenharmony_ci{
889e1051a39Sopenharmony_ci    return 1;
890e1051a39Sopenharmony_ci}
891e1051a39Sopenharmony_ci
892e1051a39Sopenharmony_ci/*-
893e1051a39Sopenharmony_ci * Various checks to see if one certificate potentially issued the second.
894e1051a39Sopenharmony_ci * This can be used to prune a set of possible issuer certificates which
895e1051a39Sopenharmony_ci * have been looked up using some simple method such as by subject name.
896e1051a39Sopenharmony_ci * These are:
897e1051a39Sopenharmony_ci * 1. issuer_name(subject) == subject_name(issuer)
898e1051a39Sopenharmony_ci * 2. If akid(subject) exists, it matches the respective issuer fields.
899e1051a39Sopenharmony_ci * 3. subject signature algorithm == issuer public key algorithm
900e1051a39Sopenharmony_ci * 4. If key_usage(issuer) exists, it allows for signing subject.
901e1051a39Sopenharmony_ci * Note that this does not include actually checking the signature.
902e1051a39Sopenharmony_ci * Returns 0 for OK, or positive for reason for mismatch
903e1051a39Sopenharmony_ci * where reason codes match those for X509_verify_cert().
904e1051a39Sopenharmony_ci */
905e1051a39Sopenharmony_ciint X509_check_issued(X509 *issuer, X509 *subject)
906e1051a39Sopenharmony_ci{
907e1051a39Sopenharmony_ci    int ret;
908e1051a39Sopenharmony_ci
909e1051a39Sopenharmony_ci    if ((ret = ossl_x509_likely_issued(issuer, subject)) != X509_V_OK)
910e1051a39Sopenharmony_ci        return ret;
911e1051a39Sopenharmony_ci    return ossl_x509_signing_allowed(issuer, subject);
912e1051a39Sopenharmony_ci}
913e1051a39Sopenharmony_ci
914e1051a39Sopenharmony_ci/* do the checks 1., 2., and 3. as described above for X509_check_issued() */
915e1051a39Sopenharmony_ciint ossl_x509_likely_issued(X509 *issuer, X509 *subject)
916e1051a39Sopenharmony_ci{
917e1051a39Sopenharmony_ci    int ret;
918e1051a39Sopenharmony_ci
919e1051a39Sopenharmony_ci    if (X509_NAME_cmp(X509_get_subject_name(issuer),
920e1051a39Sopenharmony_ci                      X509_get_issuer_name(subject)) != 0)
921e1051a39Sopenharmony_ci        return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
922e1051a39Sopenharmony_ci
923e1051a39Sopenharmony_ci    /* set issuer->skid and subject->akid */
924e1051a39Sopenharmony_ci    if (!ossl_x509v3_cache_extensions(issuer)
925e1051a39Sopenharmony_ci            || !ossl_x509v3_cache_extensions(subject))
926e1051a39Sopenharmony_ci        return X509_V_ERR_UNSPECIFIED;
927e1051a39Sopenharmony_ci
928e1051a39Sopenharmony_ci    ret = X509_check_akid(issuer, subject->akid);
929e1051a39Sopenharmony_ci    if (ret != X509_V_OK)
930e1051a39Sopenharmony_ci        return ret;
931e1051a39Sopenharmony_ci
932e1051a39Sopenharmony_ci    /* Check if the subject signature alg matches the issuer's PUBKEY alg */
933e1051a39Sopenharmony_ci    return check_sig_alg_match(X509_get0_pubkey(issuer), subject);
934e1051a39Sopenharmony_ci}
935e1051a39Sopenharmony_ci
936e1051a39Sopenharmony_ci/*-
937e1051a39Sopenharmony_ci * Check if certificate I<issuer> is allowed to issue certificate I<subject>
938e1051a39Sopenharmony_ci * according to the B<keyUsage> field of I<issuer> if present
939e1051a39Sopenharmony_ci * depending on any proxyCertInfo extension of I<subject>.
940e1051a39Sopenharmony_ci * Returns 0 for OK, or positive for reason for rejection
941e1051a39Sopenharmony_ci * where reason codes match those for X509_verify_cert().
942e1051a39Sopenharmony_ci */
943e1051a39Sopenharmony_ciint ossl_x509_signing_allowed(const X509 *issuer, const X509 *subject)
944e1051a39Sopenharmony_ci{
945e1051a39Sopenharmony_ci    if (subject->ex_flags & EXFLAG_PROXY) {
946e1051a39Sopenharmony_ci        if (ku_reject(issuer, KU_DIGITAL_SIGNATURE))
947e1051a39Sopenharmony_ci            return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE;
948e1051a39Sopenharmony_ci    } else if (ku_reject(issuer, KU_KEY_CERT_SIGN))
949e1051a39Sopenharmony_ci        return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
950e1051a39Sopenharmony_ci    return X509_V_OK;
951e1051a39Sopenharmony_ci}
952e1051a39Sopenharmony_ci
953e1051a39Sopenharmony_ciint X509_check_akid(const X509 *issuer, const AUTHORITY_KEYID *akid)
954e1051a39Sopenharmony_ci{
955e1051a39Sopenharmony_ci    if (akid == NULL)
956e1051a39Sopenharmony_ci        return X509_V_OK;
957e1051a39Sopenharmony_ci
958e1051a39Sopenharmony_ci    /* Check key ids (if present) */
959e1051a39Sopenharmony_ci    if (akid->keyid && issuer->skid &&
960e1051a39Sopenharmony_ci        ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid))
961e1051a39Sopenharmony_ci        return X509_V_ERR_AKID_SKID_MISMATCH;
962e1051a39Sopenharmony_ci    /* Check serial number */
963e1051a39Sopenharmony_ci    if (akid->serial &&
964e1051a39Sopenharmony_ci        ASN1_INTEGER_cmp(X509_get0_serialNumber(issuer), akid->serial))
965e1051a39Sopenharmony_ci        return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
966e1051a39Sopenharmony_ci    /* Check issuer name */
967e1051a39Sopenharmony_ci    if (akid->issuer) {
968e1051a39Sopenharmony_ci        /*
969e1051a39Sopenharmony_ci         * Ugh, for some peculiar reason AKID includes SEQUENCE OF
970e1051a39Sopenharmony_ci         * GeneralName. So look for a DirName. There may be more than one but
971e1051a39Sopenharmony_ci         * we only take any notice of the first.
972e1051a39Sopenharmony_ci         */
973e1051a39Sopenharmony_ci        GENERAL_NAMES *gens;
974e1051a39Sopenharmony_ci        GENERAL_NAME *gen;
975e1051a39Sopenharmony_ci        X509_NAME *nm = NULL;
976e1051a39Sopenharmony_ci        int i;
977e1051a39Sopenharmony_ci        gens = akid->issuer;
978e1051a39Sopenharmony_ci        for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
979e1051a39Sopenharmony_ci            gen = sk_GENERAL_NAME_value(gens, i);
980e1051a39Sopenharmony_ci            if (gen->type == GEN_DIRNAME) {
981e1051a39Sopenharmony_ci                nm = gen->d.dirn;
982e1051a39Sopenharmony_ci                break;
983e1051a39Sopenharmony_ci            }
984e1051a39Sopenharmony_ci        }
985e1051a39Sopenharmony_ci        if (nm != NULL && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)) != 0)
986e1051a39Sopenharmony_ci            return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
987e1051a39Sopenharmony_ci    }
988e1051a39Sopenharmony_ci    return X509_V_OK;
989e1051a39Sopenharmony_ci}
990e1051a39Sopenharmony_ci
991e1051a39Sopenharmony_ciuint32_t X509_get_extension_flags(X509 *x)
992e1051a39Sopenharmony_ci{
993e1051a39Sopenharmony_ci    /* Call for side-effect of computing hash and caching extensions */
994e1051a39Sopenharmony_ci    X509_check_purpose(x, -1, 0);
995e1051a39Sopenharmony_ci    return x->ex_flags;
996e1051a39Sopenharmony_ci}
997e1051a39Sopenharmony_ci
998e1051a39Sopenharmony_ciuint32_t X509_get_key_usage(X509 *x)
999e1051a39Sopenharmony_ci{
1000e1051a39Sopenharmony_ci    /* Call for side-effect of computing hash and caching extensions */
1001e1051a39Sopenharmony_ci    if (X509_check_purpose(x, -1, 0) != 1)
1002e1051a39Sopenharmony_ci        return 0;
1003e1051a39Sopenharmony_ci    if (x->ex_flags & EXFLAG_KUSAGE)
1004e1051a39Sopenharmony_ci        return x->ex_kusage;
1005e1051a39Sopenharmony_ci    return UINT32_MAX;
1006e1051a39Sopenharmony_ci}
1007e1051a39Sopenharmony_ci
1008e1051a39Sopenharmony_ciuint32_t X509_get_extended_key_usage(X509 *x)
1009e1051a39Sopenharmony_ci{
1010e1051a39Sopenharmony_ci    /* Call for side-effect of computing hash and caching extensions */
1011e1051a39Sopenharmony_ci    if (X509_check_purpose(x, -1, 0) != 1)
1012e1051a39Sopenharmony_ci        return 0;
1013e1051a39Sopenharmony_ci    if (x->ex_flags & EXFLAG_XKUSAGE)
1014e1051a39Sopenharmony_ci        return x->ex_xkusage;
1015e1051a39Sopenharmony_ci    return UINT32_MAX;
1016e1051a39Sopenharmony_ci}
1017e1051a39Sopenharmony_ci
1018e1051a39Sopenharmony_ciconst ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x)
1019e1051a39Sopenharmony_ci{
1020e1051a39Sopenharmony_ci    /* Call for side-effect of computing hash and caching extensions */
1021e1051a39Sopenharmony_ci    if (X509_check_purpose(x, -1, 0) != 1)
1022e1051a39Sopenharmony_ci        return NULL;
1023e1051a39Sopenharmony_ci    return x->skid;
1024e1051a39Sopenharmony_ci}
1025e1051a39Sopenharmony_ci
1026e1051a39Sopenharmony_ciconst ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x)
1027e1051a39Sopenharmony_ci{
1028e1051a39Sopenharmony_ci    /* Call for side-effect of computing hash and caching extensions */
1029e1051a39Sopenharmony_ci    if (X509_check_purpose(x, -1, 0) != 1)
1030e1051a39Sopenharmony_ci        return NULL;
1031e1051a39Sopenharmony_ci    return (x->akid != NULL ? x->akid->keyid : NULL);
1032e1051a39Sopenharmony_ci}
1033e1051a39Sopenharmony_ci
1034e1051a39Sopenharmony_ciconst GENERAL_NAMES *X509_get0_authority_issuer(X509 *x)
1035e1051a39Sopenharmony_ci{
1036e1051a39Sopenharmony_ci    /* Call for side-effect of computing hash and caching extensions */
1037e1051a39Sopenharmony_ci    if (X509_check_purpose(x, -1, 0) != 1)
1038e1051a39Sopenharmony_ci        return NULL;
1039e1051a39Sopenharmony_ci    return (x->akid != NULL ? x->akid->issuer : NULL);
1040e1051a39Sopenharmony_ci}
1041e1051a39Sopenharmony_ci
1042e1051a39Sopenharmony_ciconst ASN1_INTEGER *X509_get0_authority_serial(X509 *x)
1043e1051a39Sopenharmony_ci{
1044e1051a39Sopenharmony_ci    /* Call for side-effect of computing hash and caching extensions */
1045e1051a39Sopenharmony_ci    if (X509_check_purpose(x, -1, 0) != 1)
1046e1051a39Sopenharmony_ci        return NULL;
1047e1051a39Sopenharmony_ci    return (x->akid != NULL ? x->akid->serial : NULL);
1048e1051a39Sopenharmony_ci}
1049e1051a39Sopenharmony_ci
1050e1051a39Sopenharmony_cilong X509_get_pathlen(X509 *x)
1051e1051a39Sopenharmony_ci{
1052e1051a39Sopenharmony_ci    /* Called for side effect of caching extensions */
1053e1051a39Sopenharmony_ci    if (X509_check_purpose(x, -1, 0) != 1
1054e1051a39Sopenharmony_ci            || (x->ex_flags & EXFLAG_BCONS) == 0)
1055e1051a39Sopenharmony_ci        return -1;
1056e1051a39Sopenharmony_ci    return x->ex_pathlen;
1057e1051a39Sopenharmony_ci}
1058e1051a39Sopenharmony_ci
1059e1051a39Sopenharmony_cilong X509_get_proxy_pathlen(X509 *x)
1060e1051a39Sopenharmony_ci{
1061e1051a39Sopenharmony_ci    /* Called for side effect of caching extensions */
1062e1051a39Sopenharmony_ci    if (X509_check_purpose(x, -1, 0) != 1
1063e1051a39Sopenharmony_ci            || (x->ex_flags & EXFLAG_PROXY) == 0)
1064e1051a39Sopenharmony_ci        return -1;
1065e1051a39Sopenharmony_ci    return x->ex_pcpathlen;
1066e1051a39Sopenharmony_ci}
1067