summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2023-04-28 16:21:57 +0000
committertb <>2023-04-28 16:21:57 +0000
commit0f7876e466fed4dad77a738f0bdb63846092d5ef (patch)
treeab7bf11dbba9e8b630f9ced2d33ff8be0eb6049a
parent1059b2a4a3d9eb72ad6073bbadee2edc0fd7f990 (diff)
downloadopenbsd-0f7876e466fed4dad77a738f0bdb63846092d5ef.tar.gz
openbsd-0f7876e466fed4dad77a738f0bdb63846092d5ef.tar.bz2
openbsd-0f7876e466fed4dad77a738f0bdb63846092d5ef.zip
Take the old policy code behind the barn
It can go play in the fields with all the other exponential time policy "code". discussed with jsing ok & commit message beck
-rw-r--r--src/lib/libcrypto/Makefile8
-rw-r--r--src/lib/libcrypto/x509/pcy_cache.c276
-rw-r--r--src/lib/libcrypto/x509/pcy_data.c133
-rw-r--r--src/lib/libcrypto/x509/pcy_int.h281
-rw-r--r--src/lib/libcrypto/x509/pcy_lib.c170
-rw-r--r--src/lib/libcrypto/x509/pcy_map.c131
-rw-r--r--src/lib/libcrypto/x509/pcy_node.c204
-rw-r--r--src/lib/libcrypto/x509/pcy_tree.c705
8 files changed, 1 insertions, 1907 deletions
diff --git a/src/lib/libcrypto/Makefile b/src/lib/libcrypto/Makefile
index 7532e32210..110ec3fb97 100644
--- a/src/lib/libcrypto/Makefile
+++ b/src/lib/libcrypto/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.123 2023/04/28 16:14:46 tb Exp $ 1# $OpenBSD: Makefile,v 1.124 2023/04/28 16:21:57 tb Exp $
2 2
3LIB= crypto 3LIB= crypto
4LIBREBUILD=y 4LIBREBUILD=y
@@ -653,12 +653,6 @@ SRCS+= wp_dgst.c
653SRCS+= by_dir.c 653SRCS+= by_dir.c
654SRCS+= by_file.c 654SRCS+= by_file.c
655SRCS+= by_mem.c 655SRCS+= by_mem.c
656SRCS+= pcy_cache.c
657SRCS+= pcy_data.c
658SRCS+= pcy_lib.c
659SRCS+= pcy_map.c
660SRCS+= pcy_node.c
661SRCS+= pcy_tree.c
662SRCS+= x509_addr.c 656SRCS+= x509_addr.c
663SRCS+= x509_akey.c 657SRCS+= x509_akey.c
664SRCS+= x509_akeya.c 658SRCS+= x509_akeya.c
diff --git a/src/lib/libcrypto/x509/pcy_cache.c b/src/lib/libcrypto/x509/pcy_cache.c
deleted file mode 100644
index 10cefd7f34..0000000000
--- a/src/lib/libcrypto/x509/pcy_cache.c
+++ /dev/null
@@ -1,276 +0,0 @@
1/* $OpenBSD: pcy_cache.c,v 1.4 2023/04/26 19:11:32 beck Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2004.
4 */
5/* ====================================================================
6 * Copyright (c) 2004 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <openssl/x509.h>
60#include <openssl/x509v3.h>
61
62#ifndef LIBRESSL_HAS_POLICY_DAG
63
64#include "pcy_int.h"
65#include "x509_local.h"
66
67static int policy_data_cmp(const X509_POLICY_DATA * const *a,
68 const X509_POLICY_DATA * const *b);
69static int policy_cache_set_int(long *out, ASN1_INTEGER *value);
70
71/* Set cache entry according to CertificatePolicies extension.
72 * Note: this destroys the passed CERTIFICATEPOLICIES structure.
73 */
74
75static int
76policy_cache_create(X509 *x, CERTIFICATEPOLICIES *policies, int crit)
77{
78 int i;
79 int ret = 0;
80 X509_POLICY_CACHE *cache = x->policy_cache;
81 X509_POLICY_DATA *data = NULL;
82 POLICYINFO *policy;
83
84 if (sk_POLICYINFO_num(policies) == 0)
85 goto bad_policy;
86 cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp);
87 if (!cache->data)
88 goto bad_policy;
89 for (i = 0; i < sk_POLICYINFO_num(policies); i++) {
90 policy = sk_POLICYINFO_value(policies, i);
91 data = policy_data_new(policy, NULL, crit);
92 if (!data)
93 goto bad_policy;
94 /* Duplicate policy OIDs are illegal: reject if matches
95 * found.
96 */
97 if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
98 if (cache->anyPolicy) {
99 ret = -1;
100 goto bad_policy;
101 }
102 cache->anyPolicy = data;
103 } else if (sk_X509_POLICY_DATA_find(cache->data, data) != -1) {
104 ret = -1;
105 goto bad_policy;
106 } else if (!sk_X509_POLICY_DATA_push(cache->data, data))
107 goto bad_policy;
108 data = NULL;
109 }
110 ret = 1;
111
112bad_policy:
113 if (ret == -1)
114 x->ex_flags |= EXFLAG_INVALID_POLICY;
115 if (data)
116 policy_data_free(data);
117 sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
118 if (ret <= 0) {
119 sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
120 cache->data = NULL;
121 }
122 return ret;
123}
124
125static int
126policy_cache_new(X509 *x)
127{
128 X509_POLICY_CACHE *cache;
129 ASN1_INTEGER *ext_any = NULL;
130 POLICY_CONSTRAINTS *ext_pcons = NULL;
131 CERTIFICATEPOLICIES *ext_cpols = NULL;
132 POLICY_MAPPINGS *ext_pmaps = NULL;
133 int i;
134
135 cache = malloc(sizeof(X509_POLICY_CACHE));
136 if (!cache)
137 return 0;
138 cache->anyPolicy = NULL;
139 cache->data = NULL;
140 cache->any_skip = -1;
141 cache->explicit_skip = -1;
142 cache->map_skip = -1;
143
144 x->policy_cache = cache;
145
146 /* Handle requireExplicitPolicy *first*. Need to process this
147 * even if we don't have any policies.
148 */
149 ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL);
150
151 if (!ext_pcons) {
152 if (i != -1)
153 goto bad_cache;
154 } else {
155 if (!ext_pcons->requireExplicitPolicy &&
156 !ext_pcons->inhibitPolicyMapping)
157 goto bad_cache;
158 if (!policy_cache_set_int(&cache->explicit_skip,
159 ext_pcons->requireExplicitPolicy))
160 goto bad_cache;
161 if (!policy_cache_set_int(&cache->map_skip,
162 ext_pcons->inhibitPolicyMapping))
163 goto bad_cache;
164 }
165
166 /* Process CertificatePolicies */
167
168 ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
169 /* If no CertificatePolicies extension or problem decoding then
170 * there is no point continuing because the valid policies will be
171 * NULL.
172 */
173 if (!ext_cpols) {
174 /* If not absent some problem with extension */
175 if (i != -1)
176 goto bad_cache;
177 return 1;
178 }
179
180 i = policy_cache_create(x, ext_cpols, i);
181
182 /* NB: ext_cpols freed by policy_cache_set_policies */
183
184 if (i <= 0)
185 return i;
186
187 ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL);
188
189 if (!ext_pmaps) {
190 /* If not absent some problem with extension */
191 if (i != -1)
192 goto bad_cache;
193 } else {
194 i = policy_cache_set_mapping(x, ext_pmaps);
195 if (i <= 0)
196 goto bad_cache;
197 }
198
199 ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL);
200
201 if (!ext_any) {
202 if (i != -1)
203 goto bad_cache;
204 } else if (!policy_cache_set_int(&cache->any_skip, ext_any))
205 goto bad_cache;
206
207 if (0) {
208bad_cache:
209 x->ex_flags |= EXFLAG_INVALID_POLICY;
210 }
211
212 if (ext_pcons)
213 POLICY_CONSTRAINTS_free(ext_pcons);
214
215 if (ext_any)
216 ASN1_INTEGER_free(ext_any);
217
218 return 1;
219}
220
221void
222policy_cache_free(X509_POLICY_CACHE *cache)
223{
224 if (!cache)
225 return;
226 if (cache->anyPolicy)
227 policy_data_free(cache->anyPolicy);
228 if (cache->data)
229 sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
230 free(cache);
231}
232
233const X509_POLICY_CACHE *
234policy_cache_set(X509 *x)
235{
236 if (x->policy_cache == NULL) {
237 CRYPTO_w_lock(CRYPTO_LOCK_X509);
238 policy_cache_new(x);
239 CRYPTO_w_unlock(CRYPTO_LOCK_X509);
240 }
241
242 return x->policy_cache;
243}
244
245X509_POLICY_DATA *
246policy_cache_find_data(const X509_POLICY_CACHE *cache, const ASN1_OBJECT *id)
247{
248 int idx;
249 X509_POLICY_DATA tmp;
250
251 tmp.valid_policy = (ASN1_OBJECT *)id;
252 idx = sk_X509_POLICY_DATA_find(cache->data, &tmp);
253 if (idx == -1)
254 return NULL;
255 return sk_X509_POLICY_DATA_value(cache->data, idx);
256}
257
258static int
259policy_data_cmp(const X509_POLICY_DATA * const *a,
260 const X509_POLICY_DATA * const *b)
261{
262 return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy);
263}
264
265static int
266policy_cache_set_int(long *out, ASN1_INTEGER *value)
267{
268 if (value == NULL)
269 return 1;
270 if (value->type == V_ASN1_NEG_INTEGER)
271 return 0;
272 *out = ASN1_INTEGER_get(value);
273 return 1;
274}
275
276#endif /* LIBRESSL_HAS_POLICY_DAG */
diff --git a/src/lib/libcrypto/x509/pcy_data.c b/src/lib/libcrypto/x509/pcy_data.c
deleted file mode 100644
index f0fdfe18ef..0000000000
--- a/src/lib/libcrypto/x509/pcy_data.c
+++ /dev/null
@@ -1,133 +0,0 @@
1/* $OpenBSD: pcy_data.c,v 1.2 2023/04/26 19:11:32 beck Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2004.
4 */
5/* ====================================================================
6 * Copyright (c) 2004 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <openssl/x509.h>
60#include <openssl/x509v3.h>
61
62#ifndef LIBRESSL_HAS_POLICY_DAG
63
64#include "pcy_int.h"
65
66/* Policy Node routines */
67
68void
69policy_data_free(X509_POLICY_DATA *data)
70{
71 ASN1_OBJECT_free(data->valid_policy);
72 /* Don't free qualifiers if shared */
73 if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS))
74 sk_POLICYQUALINFO_pop_free(data->qualifier_set,
75 POLICYQUALINFO_free);
76 sk_ASN1_OBJECT_pop_free(data->expected_policy_set, ASN1_OBJECT_free);
77 free(data);
78}
79
80/* Create a data based on an existing policy. If 'id' is NULL use the
81 * oid in the policy, otherwise use 'id'. This behaviour covers the two
82 * types of data in RFC3280: data with from a CertificatePolcies extension
83 * and additional data with just the qualifiers of anyPolicy and ID from
84 * another source.
85 */
86
87X509_POLICY_DATA *
88policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *cid, int crit)
89{
90 X509_POLICY_DATA *ret = NULL;
91 ASN1_OBJECT *id = NULL;
92
93 if (policy == NULL && cid == NULL)
94 return NULL;
95 if (cid != NULL) {
96 id = OBJ_dup(cid);
97 if (id == NULL)
98 return NULL;
99 }
100 ret = malloc(sizeof(X509_POLICY_DATA));
101 if (ret == NULL)
102 goto err;
103 ret->expected_policy_set = sk_ASN1_OBJECT_new_null();
104 if (ret->expected_policy_set == NULL)
105 goto err;
106
107 if (crit)
108 ret->flags = POLICY_DATA_FLAG_CRITICAL;
109 else
110 ret->flags = 0;
111
112 if (id != NULL)
113 ret->valid_policy = id;
114 else {
115 ret->valid_policy = policy->policyid;
116 policy->policyid = NULL;
117 }
118
119 if (policy != NULL) {
120 ret->qualifier_set = policy->qualifiers;
121 policy->qualifiers = NULL;
122 } else
123 ret->qualifier_set = NULL;
124
125 return ret;
126
127err:
128 free(ret);
129 ASN1_OBJECT_free(id);
130 return NULL;
131}
132
133#endif /* LIBRESSL_HAS_POLICY_DAG */
diff --git a/src/lib/libcrypto/x509/pcy_int.h b/src/lib/libcrypto/x509/pcy_int.h
deleted file mode 100644
index 43bd548f66..0000000000
--- a/src/lib/libcrypto/x509/pcy_int.h
+++ /dev/null
@@ -1,281 +0,0 @@
1/* $OpenBSD: pcy_int.h,v 1.5 2023/04/26 19:11:32 beck Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2004.
4 */
5/* ====================================================================
6 * Copyright (c) 2004 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#ifndef LIBRESSL_HAS_POLICY_DAG
60
61/* Needed to pull in the typedefs for X509_POLICY_* */
62#include "x509_local.h"
63
64__BEGIN_HIDDEN_DECLS
65
66typedef struct X509_POLICY_DATA_st X509_POLICY_DATA;
67
68DECLARE_STACK_OF(X509_POLICY_DATA)
69DECLARE_STACK_OF(X509_POLICY_NODE)
70
71#define sk_X509_POLICY_DATA_new(cmp) SKM_sk_new(X509_POLICY_DATA, (cmp))
72#define sk_X509_POLICY_DATA_new_null() SKM_sk_new_null(X509_POLICY_DATA)
73#define sk_X509_POLICY_DATA_free(st) SKM_sk_free(X509_POLICY_DATA, (st))
74#define sk_X509_POLICY_DATA_num(st) SKM_sk_num(X509_POLICY_DATA, (st))
75#define sk_X509_POLICY_DATA_value(st, i) SKM_sk_value(X509_POLICY_DATA, (st), (i))
76#define sk_X509_POLICY_DATA_set(st, i, val) SKM_sk_set(X509_POLICY_DATA, (st), (i), (val))
77#define sk_X509_POLICY_DATA_zero(st) SKM_sk_zero(X509_POLICY_DATA, (st))
78#define sk_X509_POLICY_DATA_push(st, val) SKM_sk_push(X509_POLICY_DATA, (st), (val))
79#define sk_X509_POLICY_DATA_unshift(st, val) SKM_sk_unshift(X509_POLICY_DATA, (st), (val))
80#define sk_X509_POLICY_DATA_find(st, val) SKM_sk_find(X509_POLICY_DATA, (st), (val))
81#define sk_X509_POLICY_DATA_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_DATA, (st), (val))
82#define sk_X509_POLICY_DATA_delete(st, i) SKM_sk_delete(X509_POLICY_DATA, (st), (i))
83#define sk_X509_POLICY_DATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_DATA, (st), (ptr))
84#define sk_X509_POLICY_DATA_insert(st, val, i) SKM_sk_insert(X509_POLICY_DATA, (st), (val), (i))
85#define sk_X509_POLICY_DATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_DATA, (st), (cmp))
86#define sk_X509_POLICY_DATA_dup(st) SKM_sk_dup(X509_POLICY_DATA, st)
87#define sk_X509_POLICY_DATA_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_DATA, (st), (free_func))
88#define sk_X509_POLICY_DATA_shift(st) SKM_sk_shift(X509_POLICY_DATA, (st))
89#define sk_X509_POLICY_DATA_pop(st) SKM_sk_pop(X509_POLICY_DATA, (st))
90#define sk_X509_POLICY_DATA_sort(st) SKM_sk_sort(X509_POLICY_DATA, (st))
91#define sk_X509_POLICY_DATA_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_DATA, (st))
92
93#define sk_X509_POLICY_NODE_new(cmp) SKM_sk_new(X509_POLICY_NODE, (cmp))
94#define sk_X509_POLICY_NODE_new_null() SKM_sk_new_null(X509_POLICY_NODE)
95#define sk_X509_POLICY_NODE_free(st) SKM_sk_free(X509_POLICY_NODE, (st))
96#define sk_X509_POLICY_NODE_num(st) SKM_sk_num(X509_POLICY_NODE, (st))
97#define sk_X509_POLICY_NODE_value(st, i) SKM_sk_value(X509_POLICY_NODE, (st), (i))
98#define sk_X509_POLICY_NODE_set(st, i, val) SKM_sk_set(X509_POLICY_NODE, (st), (i), (val))
99#define sk_X509_POLICY_NODE_zero(st) SKM_sk_zero(X509_POLICY_NODE, (st))
100#define sk_X509_POLICY_NODE_push(st, val) SKM_sk_push(X509_POLICY_NODE, (st), (val))
101#define sk_X509_POLICY_NODE_unshift(st, val) SKM_sk_unshift(X509_POLICY_NODE, (st), (val))
102#define sk_X509_POLICY_NODE_find(st, val) SKM_sk_find(X509_POLICY_NODE, (st), (val))
103#define sk_X509_POLICY_NODE_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_NODE, (st), (val))
104#define sk_X509_POLICY_NODE_delete(st, i) SKM_sk_delete(X509_POLICY_NODE, (st), (i))
105#define sk_X509_POLICY_NODE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_NODE, (st), (ptr))
106#define sk_X509_POLICY_NODE_insert(st, val, i) SKM_sk_insert(X509_POLICY_NODE, (st), (val), (i))
107#define sk_X509_POLICY_NODE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_NODE, (st), (cmp))
108#define sk_X509_POLICY_NODE_dup(st) SKM_sk_dup(X509_POLICY_NODE, st)
109#define sk_X509_POLICY_NODE_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_NODE, (st), (free_func))
110#define sk_X509_POLICY_NODE_shift(st) SKM_sk_shift(X509_POLICY_NODE, (st))
111#define sk_X509_POLICY_NODE_pop(st) SKM_sk_pop(X509_POLICY_NODE, (st))
112#define sk_X509_POLICY_NODE_sort(st) SKM_sk_sort(X509_POLICY_NODE, (st))
113#define sk_X509_POLICY_NODE_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_NODE, (st))
114
115/* This structure and the field names correspond to the Policy 'node' of
116 * RFC3280. NB this structure contains no pointers to parent or child
117 * data: X509_POLICY_NODE contains that. This means that the main policy data
118 * can be kept static and cached with the certificate.
119 */
120
121struct X509_POLICY_DATA_st {
122 unsigned int flags;
123 /* Policy OID and qualifiers for this data */
124 ASN1_OBJECT *valid_policy;
125 STACK_OF(POLICYQUALINFO) *qualifier_set;
126 STACK_OF(ASN1_OBJECT) *expected_policy_set;
127};
128
129/* X509_POLICY_DATA flags values */
130
131/* This flag indicates the structure has been mapped using a policy mapping
132 * extension. If policy mapping is not active its references get deleted.
133 */
134
135#define POLICY_DATA_FLAG_MAPPED 0x1
136
137/* This flag indicates the data doesn't correspond to a policy in Certificate
138 * Policies: it has been mapped to any policy.
139 */
140
141#define POLICY_DATA_FLAG_MAPPED_ANY 0x2
142
143/* AND with flags to see if any mapping has occurred */
144
145#define POLICY_DATA_FLAG_MAP_MASK 0x3
146
147/* qualifiers are shared and shouldn't be freed */
148
149#define POLICY_DATA_FLAG_SHARED_QUALIFIERS 0x4
150
151/* Parent node is an extra node and should be freed */
152
153#define POLICY_DATA_FLAG_EXTRA_NODE 0x8
154
155/* Corresponding CertificatePolicies is critical */
156
157#define POLICY_DATA_FLAG_CRITICAL 0x10
158
159/* This structure is cached with a certificate */
160
161struct X509_POLICY_CACHE_st {
162 /* anyPolicy data or NULL if no anyPolicy */
163 X509_POLICY_DATA *anyPolicy;
164 /* other policy data */
165 STACK_OF(X509_POLICY_DATA) *data;
166 /* If InhibitAnyPolicy present this is its value or -1 if absent. */
167 long any_skip;
168 /* If policyConstraints and requireExplicitPolicy present this is its
169 * value or -1 if absent.
170 */
171 long explicit_skip;
172 /* If policyConstraints and policyMapping present this is its
173 * value or -1 if absent.
174 */
175 long map_skip;
176};
177
178/*#define POLICY_CACHE_FLAG_CRITICAL POLICY_DATA_FLAG_CRITICAL*/
179
180/* This structure represents the relationship between nodes */
181
182struct X509_POLICY_NODE_st {
183 /* node data this refers to */
184 const X509_POLICY_DATA *data;
185 /* Parent node */
186 X509_POLICY_NODE *parent;
187 /* Number of child nodes */
188 int nchild;
189};
190
191struct X509_POLICY_LEVEL_st {
192 /* Cert for this level */
193 X509 *cert;
194 /* nodes at this level */
195 STACK_OF(X509_POLICY_NODE) *nodes;
196 /* anyPolicy node */
197 X509_POLICY_NODE *anyPolicy;
198 /* Extra data */
199 /*STACK_OF(X509_POLICY_DATA) *extra_data;*/
200 unsigned int flags;
201};
202
203struct X509_POLICY_TREE_st {
204 /* This is the tree 'level' data */
205 X509_POLICY_LEVEL *levels;
206 int nlevel;
207 /* Extra policy data when additional nodes (not from the certificate)
208 * are required.
209 */
210 STACK_OF(X509_POLICY_DATA) *extra_data;
211 /* This is the authority constained policy set */
212 STACK_OF(X509_POLICY_NODE) *auth_policies;
213 STACK_OF(X509_POLICY_NODE) *user_policies;
214 unsigned int flags;
215};
216
217/* Set if anyPolicy present in user policies */
218#define POLICY_FLAG_ANY_POLICY 0x2
219
220/* Useful macros */
221
222#define node_data_critical(data) (data->flags & POLICY_DATA_FLAG_CRITICAL)
223#define node_critical(node) node_data_critical(node->data)
224
225/* Internal functions */
226
227X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *id,
228 int crit);
229void policy_data_free(X509_POLICY_DATA *data);
230
231X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
232 const ASN1_OBJECT *id);
233int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps);
234
235
236STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void);
237
238void policy_cache_init(void);
239
240void policy_cache_free(X509_POLICY_CACHE *cache);
241
242X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
243 const X509_POLICY_NODE *parent, const ASN1_OBJECT *id);
244
245X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *sk,
246 const ASN1_OBJECT *id);
247
248int level_add_node(X509_POLICY_LEVEL *level,
249 const X509_POLICY_DATA *data, X509_POLICY_NODE *parent,
250 X509_POLICY_TREE *tree, X509_POLICY_NODE **nodep);
251void policy_node_free(X509_POLICY_NODE *node);
252int policy_node_match(const X509_POLICY_LEVEL *lvl,
253 const X509_POLICY_NODE *node, const ASN1_OBJECT *oid);
254
255const X509_POLICY_CACHE *policy_cache_set(X509 *x);
256
257int X509_policy_tree_level_count(const X509_POLICY_TREE *tree);
258X509_POLICY_LEVEL *
259 X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, int i);
260
261STACK_OF(X509_POLICY_NODE) *
262 X509_policy_tree_get0_policies(const X509_POLICY_TREE *tree);
263
264STACK_OF(X509_POLICY_NODE) *
265 X509_policy_tree_get0_user_policies(const X509_POLICY_TREE *tree);
266
267int X509_policy_level_node_count(X509_POLICY_LEVEL *level);
268
269X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i);
270
271const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node);
272
273STACK_OF(POLICYQUALINFO) *
274 X509_policy_node_get0_qualifiers(const X509_POLICY_NODE *node);
275const X509_POLICY_NODE *
276 X509_policy_node_get0_parent(const X509_POLICY_NODE *node);
277
278
279__END_HIDDEN_DECLS
280
281#endif /* LIBRESSL_HAS_POLICY_DAG */
diff --git a/src/lib/libcrypto/x509/pcy_lib.c b/src/lib/libcrypto/x509/pcy_lib.c
deleted file mode 100644
index 0c8978bd70..0000000000
--- a/src/lib/libcrypto/x509/pcy_lib.c
+++ /dev/null
@@ -1,170 +0,0 @@
1/* $OpenBSD: pcy_lib.c,v 1.4 2023/04/26 19:11:33 beck Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2004.
4 */
5/* ====================================================================
6 * Copyright (c) 2004 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <openssl/x509.h>
60#include <openssl/x509v3.h>
61
62#ifndef LIBRESSL_HAS_POLICY_DAG
63
64#include "pcy_int.h"
65
66/* accessor functions */
67
68/* X509_POLICY_TREE stuff */
69
70int
71X509_policy_tree_level_count(const X509_POLICY_TREE *tree)
72{
73 if (!tree)
74 return 0;
75 return tree->nlevel;
76}
77LCRYPTO_ALIAS(X509_policy_tree_level_count);
78
79X509_POLICY_LEVEL *
80X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, int i)
81{
82 if (!tree || (i < 0) || (i >= tree->nlevel))
83 return NULL;
84 return tree->levels + i;
85}
86LCRYPTO_ALIAS(X509_policy_tree_get0_level);
87
88STACK_OF(X509_POLICY_NODE) *
89X509_policy_tree_get0_policies(const X509_POLICY_TREE *tree)
90{
91 if (!tree)
92 return NULL;
93 return tree->auth_policies;
94}
95LCRYPTO_ALIAS(X509_policy_tree_get0_policies);
96
97STACK_OF(X509_POLICY_NODE) *
98X509_policy_tree_get0_user_policies(const X509_POLICY_TREE *tree)
99{
100 if (!tree)
101 return NULL;
102 if (tree->flags & POLICY_FLAG_ANY_POLICY)
103 return tree->auth_policies;
104 else
105 return tree->user_policies;
106}
107LCRYPTO_ALIAS(X509_policy_tree_get0_user_policies);
108
109/* X509_POLICY_LEVEL stuff */
110
111int
112X509_policy_level_node_count(X509_POLICY_LEVEL *level)
113{
114 int n;
115 if (!level)
116 return 0;
117 if (level->anyPolicy)
118 n = 1;
119 else
120 n = 0;
121 if (level->nodes)
122 n += sk_X509_POLICY_NODE_num(level->nodes);
123 return n;
124}
125LCRYPTO_ALIAS(X509_policy_level_node_count);
126
127X509_POLICY_NODE *
128X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i)
129{
130 if (!level)
131 return NULL;
132 if (level->anyPolicy) {
133 if (i == 0)
134 return level->anyPolicy;
135 i--;
136 }
137 return sk_X509_POLICY_NODE_value(level->nodes, i);
138}
139LCRYPTO_ALIAS(X509_policy_level_get0_node);
140
141/* X509_POLICY_NODE stuff */
142
143const ASN1_OBJECT *
144X509_policy_node_get0_policy(const X509_POLICY_NODE *node)
145{
146 if (!node)
147 return NULL;
148 return node->data->valid_policy;
149}
150LCRYPTO_ALIAS(X509_policy_node_get0_policy);
151
152STACK_OF(POLICYQUALINFO) *
153X509_policy_node_get0_qualifiers(const X509_POLICY_NODE *node)
154{
155 if (!node)
156 return NULL;
157 return node->data->qualifier_set;
158}
159LCRYPTO_ALIAS(X509_policy_node_get0_qualifiers);
160
161const X509_POLICY_NODE *
162X509_policy_node_get0_parent(const X509_POLICY_NODE *node)
163{
164 if (!node)
165 return NULL;
166 return node->parent;
167}
168LCRYPTO_ALIAS(X509_policy_node_get0_parent);
169
170#endif /* LIBRESSL_HAS_POLICY_DAG */
diff --git a/src/lib/libcrypto/x509/pcy_map.c b/src/lib/libcrypto/x509/pcy_map.c
deleted file mode 100644
index ffbc6f75f0..0000000000
--- a/src/lib/libcrypto/x509/pcy_map.c
+++ /dev/null
@@ -1,131 +0,0 @@
1/* $OpenBSD: pcy_map.c,v 1.4 2023/04/26 19:11:33 beck Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2004.
4 */
5/* ====================================================================
6 * Copyright (c) 2004 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <openssl/x509.h>
60#include <openssl/x509v3.h>
61
62#ifndef LIBRESSL_HAS_POLICY_DAG
63
64#include "pcy_int.h"
65#include "x509_local.h"
66
67/* Set policy mapping entries in cache.
68 * Note: this modifies the passed POLICY_MAPPINGS structure
69 */
70
71int
72policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
73{
74 POLICY_MAPPING *map;
75 X509_POLICY_DATA *data;
76 X509_POLICY_CACHE *cache = x->policy_cache;
77 int i;
78 int ret = 0;
79
80 if (sk_POLICY_MAPPING_num(maps) == 0) {
81 ret = -1;
82 goto bad_mapping;
83 }
84 for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++) {
85 map = sk_POLICY_MAPPING_value(maps, i);
86 /* Reject if map to or from anyPolicy */
87 if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy) ||
88 (OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy)) {
89 ret = -1;
90 goto bad_mapping;
91 }
92
93 /* Attempt to find matching policy data */
94 data = policy_cache_find_data(cache, map->issuerDomainPolicy);
95 /* If we don't have anyPolicy can't map */
96 if (!data && !cache->anyPolicy)
97 continue;
98
99 /* Create a NODE from anyPolicy */
100 if (!data) {
101 data = policy_data_new(NULL, map->issuerDomainPolicy,
102 cache->anyPolicy->flags &
103 POLICY_DATA_FLAG_CRITICAL);
104 if (!data)
105 goto bad_mapping;
106 data->qualifier_set = cache->anyPolicy->qualifier_set;
107 /*map->issuerDomainPolicy = NULL;*/
108 data->flags |= POLICY_DATA_FLAG_MAPPED_ANY;
109 data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
110 if (!sk_X509_POLICY_DATA_push(cache->data, data)) {
111 policy_data_free(data);
112 goto bad_mapping;
113 }
114 } else
115 data->flags |= POLICY_DATA_FLAG_MAPPED;
116 if (!sk_ASN1_OBJECT_push(data->expected_policy_set,
117 map->subjectDomainPolicy))
118 goto bad_mapping;
119 map->subjectDomainPolicy = NULL;
120 }
121
122 ret = 1;
123
124bad_mapping:
125 if (ret == -1)
126 x->ex_flags |= EXFLAG_INVALID_POLICY;
127 sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free);
128 return ret;
129}
130
131#endif /* LIBRESSL_HAS_POLICY_DAG */
diff --git a/src/lib/libcrypto/x509/pcy_node.c b/src/lib/libcrypto/x509/pcy_node.c
deleted file mode 100644
index 1daf7e2aff..0000000000
--- a/src/lib/libcrypto/x509/pcy_node.c
+++ /dev/null
@@ -1,204 +0,0 @@
1/* $OpenBSD: pcy_node.c,v 1.2 2023/04/26 19:11:33 beck Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2004.
4 */
5/* ====================================================================
6 * Copyright (c) 2004 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <openssl/asn1.h>
60#include <openssl/x509.h>
61#include <openssl/x509v3.h>
62
63#ifndef LIBRESSL_HAS_POLICY_DAG
64
65#include "pcy_int.h"
66
67static int
68node_cmp(const X509_POLICY_NODE * const *a, const X509_POLICY_NODE * const *b)
69{
70 return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy);
71}
72
73STACK_OF(X509_POLICY_NODE) *
74policy_node_cmp_new(void)
75{
76 return sk_X509_POLICY_NODE_new(node_cmp);
77}
78
79X509_POLICY_NODE *
80tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes, const ASN1_OBJECT *id)
81{
82 X509_POLICY_DATA n;
83 X509_POLICY_NODE l;
84 int idx;
85
86 n.valid_policy = (ASN1_OBJECT *)id;
87 l.data = &n;
88
89 idx = sk_X509_POLICY_NODE_find(nodes, &l);
90 if (idx == -1)
91 return NULL;
92
93 return sk_X509_POLICY_NODE_value(nodes, idx);
94}
95
96X509_POLICY_NODE *
97level_find_node(const X509_POLICY_LEVEL *level, const X509_POLICY_NODE *parent,
98 const ASN1_OBJECT *id)
99{
100 X509_POLICY_NODE *node;
101 int i;
102
103 for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) {
104 node = sk_X509_POLICY_NODE_value(level->nodes, i);
105 if (node->parent == parent) {
106 if (!OBJ_cmp(node->data->valid_policy, id))
107 return node;
108 }
109 }
110 return NULL;
111}
112
113
114int
115level_add_node(X509_POLICY_LEVEL *level, const X509_POLICY_DATA *data,
116 X509_POLICY_NODE *parent, X509_POLICY_TREE *tree, X509_POLICY_NODE **nodep)
117{
118 X509_POLICY_NODE *node = NULL;
119
120 if (level) {
121 node = malloc(sizeof(X509_POLICY_NODE));
122 if (!node)
123 goto node_error;
124 node->data = data;
125 node->parent = parent;
126 node->nchild = 0;
127 if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
128 if (level->anyPolicy)
129 goto node_error;
130 level->anyPolicy = node;
131 if (parent)
132 parent->nchild++;
133 } else {
134
135 if (!level->nodes)
136 level->nodes = policy_node_cmp_new();
137 if (!level->nodes)
138 goto node_error;
139 if (!sk_X509_POLICY_NODE_push(level->nodes, node))
140 goto node_error;
141 if (parent)
142 parent->nchild++;
143 }
144 }
145
146 if (tree) {
147 if (!tree->extra_data)
148 tree->extra_data = sk_X509_POLICY_DATA_new_null();
149 if (!tree->extra_data)
150 goto node_error_cond;
151 if (!sk_X509_POLICY_DATA_push(tree->extra_data, data))
152 goto node_error_cond;
153 }
154
155 if (nodep)
156 *nodep = node;
157
158 return 1;
159
160node_error_cond:
161 if (level)
162 node = NULL;
163node_error:
164 policy_node_free(node);
165 node = NULL;
166 if (nodep)
167 *nodep = node;
168 return 0;
169}
170
171void
172policy_node_free(X509_POLICY_NODE *node)
173{
174 free(node);
175}
176
177/* See if a policy node matches a policy OID. If mapping enabled look through
178 * expected policy set otherwise just valid policy.
179 */
180
181int
182policy_node_match(const X509_POLICY_LEVEL *lvl, const X509_POLICY_NODE *node,
183 const ASN1_OBJECT *oid)
184{
185 int i;
186 ASN1_OBJECT *policy_oid;
187 const X509_POLICY_DATA *x = node->data;
188
189 if ((lvl->flags & X509_V_FLAG_INHIBIT_MAP) ||
190 !(x->flags & POLICY_DATA_FLAG_MAP_MASK)) {
191 if (!OBJ_cmp(x->valid_policy, oid))
192 return 1;
193 return 0;
194 }
195
196 for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++) {
197 policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i);
198 if (!OBJ_cmp(policy_oid, oid))
199 return 1;
200 }
201 return 0;
202}
203
204#endif /* LIBRESSL_HAS_POLICY_DAG */
diff --git a/src/lib/libcrypto/x509/pcy_tree.c b/src/lib/libcrypto/x509/pcy_tree.c
deleted file mode 100644
index 4f253e3cd1..0000000000
--- a/src/lib/libcrypto/x509/pcy_tree.c
+++ /dev/null
@@ -1,705 +0,0 @@
1/* $OpenBSD: pcy_tree.c,v 1.8 2023/04/26 20:43:32 tb Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2004.
4 */
5/* ====================================================================
6 * Copyright (c) 2004 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <openssl/x509.h>
60#include <openssl/x509v3.h>
61
62#ifndef LIBRESSL_HAS_POLICY_DAG
63
64#include "pcy_int.h"
65#include "x509_local.h"
66
67/* Initialize policy tree. Return values:
68 * 0 Some internal error occurred.
69 * -1 Inconsistent or invalid extensions in certificates.
70 * 1 Tree initialized OK.
71 * 2 Policy tree is empty.
72 * 5 Tree OK and requireExplicitPolicy true.
73 * 6 Tree empty and requireExplicitPolicy true.
74 */
75
76static int
77tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, unsigned int flags)
78{
79 X509_POLICY_TREE *tree;
80 X509_POLICY_LEVEL *level;
81 const X509_POLICY_CACHE *cache;
82 X509_POLICY_DATA *data = NULL;
83 X509 *x;
84 int ret = 1;
85 int i, n;
86 int explicit_policy;
87 int any_skip;
88 int map_skip;
89
90 *ptree = NULL;
91 n = sk_X509_num(certs);
92
93 if (flags & X509_V_FLAG_EXPLICIT_POLICY)
94 explicit_policy = 0;
95 else
96 explicit_policy = n + 1;
97
98 if (flags & X509_V_FLAG_INHIBIT_ANY)
99 any_skip = 0;
100 else
101 any_skip = n + 1;
102
103 if (flags & X509_V_FLAG_INHIBIT_MAP)
104 map_skip = 0;
105 else
106 map_skip = n + 1;
107
108 /* Can't do anything with just a trust anchor */
109 if (n == 1)
110 return 1;
111 /* First setup policy cache in all certificates apart from the
112 * trust anchor. Note any bad cache results on the way. Also can
113 * calculate explicit_policy value at this point.
114 */
115 for (i = n - 2; i >= 0; i--) {
116 x = sk_X509_value(certs, i);
117 X509_check_purpose(x, -1, -1);
118 cache = policy_cache_set(x);
119 /* If cache NULL something bad happened: return immediately */
120 if (cache == NULL)
121 return 0;
122 /* If inconsistent extensions keep a note of it but continue */
123 if (x->ex_flags & EXFLAG_INVALID_POLICY)
124 ret = -1;
125 /* Otherwise if we have no data (hence no CertificatePolicies)
126 * and haven't already set an inconsistent code note it.
127 */
128 else if ((ret == 1) && !cache->data)
129 ret = 2;
130 if (explicit_policy > 0) {
131 if (!(x->ex_flags & EXFLAG_SI))
132 explicit_policy--;
133 if ((cache->explicit_skip != -1) &&
134 (cache->explicit_skip < explicit_policy))
135 explicit_policy = cache->explicit_skip;
136 }
137 }
138
139 if (ret != 1) {
140 if (ret == 2 && !explicit_policy)
141 return 6;
142 return ret;
143 }
144
145
146 /* If we get this far initialize the tree */
147
148 tree = malloc(sizeof(X509_POLICY_TREE));
149
150 if (!tree)
151 return 0;
152
153 tree->flags = 0;
154 tree->levels = calloc(n, sizeof(X509_POLICY_LEVEL));
155 tree->nlevel = 0;
156 tree->extra_data = NULL;
157 tree->auth_policies = NULL;
158 tree->user_policies = NULL;
159
160 if (!tree->levels) {
161 free(tree);
162 return 0;
163 }
164
165 tree->nlevel = n;
166
167 level = tree->levels;
168
169 /* Root data: initialize to anyPolicy */
170
171 data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
172
173 if (!data || !level_add_node(level, data, NULL, tree, NULL))
174 goto bad_tree;
175
176 for (i = n - 2; i >= 0; i--) {
177 level++;
178 x = sk_X509_value(certs, i);
179 cache = policy_cache_set(x);
180 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
181 level->cert = x;
182
183 if (!cache->anyPolicy)
184 level->flags |= X509_V_FLAG_INHIBIT_ANY;
185
186 /* Determine inhibit any and inhibit map flags */
187 if (any_skip == 0) {
188 /* Any matching allowed if certificate is self
189 * issued and not the last in the chain.
190 */
191 if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
192 level->flags |= X509_V_FLAG_INHIBIT_ANY;
193 } else {
194 if (!(x->ex_flags & EXFLAG_SI))
195 any_skip--;
196 if ((cache->any_skip >= 0) &&
197 (cache->any_skip < any_skip))
198 any_skip = cache->any_skip;
199 }
200
201 if (map_skip == 0)
202 level->flags |= X509_V_FLAG_INHIBIT_MAP;
203 else {
204 if (!(x->ex_flags & EXFLAG_SI))
205 map_skip--;
206 if ((cache->map_skip >= 0) &&
207 (cache->map_skip < map_skip))
208 map_skip = cache->map_skip;
209 }
210
211 }
212
213 *ptree = tree;
214
215 if (explicit_policy)
216 return 1;
217 else
218 return 5;
219
220bad_tree:
221 X509_policy_tree_free(tree);
222
223 return 0;
224}
225
226static int
227tree_link_matching_nodes(X509_POLICY_LEVEL *curr, const X509_POLICY_DATA *data)
228{
229 X509_POLICY_LEVEL *last = curr - 1;
230 X509_POLICY_NODE *node;
231 int i, matched = 0;
232
233 /* Iterate through all in nodes linking matches */
234 for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
235 node = sk_X509_POLICY_NODE_value(last->nodes, i);
236 if (policy_node_match(last, node, data->valid_policy)) {
237 if (!level_add_node(curr, data, node, NULL, NULL))
238 return 0;
239 matched = 1;
240 }
241 }
242 if (!matched && last->anyPolicy) {
243 if (!level_add_node(curr, data, last->anyPolicy, NULL, NULL))
244 return 0;
245 }
246 return 1;
247}
248
249/* This corresponds to RFC3280 6.1.3(d)(1):
250 * link any data from CertificatePolicies onto matching parent
251 * or anyPolicy if no match.
252 */
253
254static int
255tree_link_nodes(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache)
256{
257 int i;
258 X509_POLICY_DATA *data;
259
260 for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) {
261 data = sk_X509_POLICY_DATA_value(cache->data, i);
262 /* Look for matching nodes in previous level */
263 if (!tree_link_matching_nodes(curr, data))
264 return 0;
265 }
266 return 1;
267}
268
269/* This corresponds to RFC3280 6.1.3(d)(2):
270 * Create new data for any unmatched policies in the parent and link
271 * to anyPolicy.
272 */
273
274static int
275tree_add_unmatched(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache,
276 const ASN1_OBJECT *id, X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
277{
278 X509_POLICY_DATA *data;
279
280 if (id == NULL)
281 id = node->data->valid_policy;
282 /* Create a new node with qualifiers from anyPolicy and
283 * id from unmatched node.
284 */
285 data = policy_data_new(NULL, id, node_critical(node));
286
287 if (data == NULL)
288 return 0;
289 /* Curr may not have anyPolicy */
290 data->qualifier_set = cache->anyPolicy->qualifier_set;
291 data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
292 if (!level_add_node(curr, data, node, tree, NULL)) {
293 policy_data_free(data);
294 return 0;
295 }
296
297 return 1;
298}
299
300static int
301tree_link_unmatched(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache,
302 X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
303{
304 const X509_POLICY_LEVEL *last = curr - 1;
305 int i;
306
307 if ((last->flags & X509_V_FLAG_INHIBIT_MAP) ||
308 !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) {
309 /* If no policy mapping: matched if one child present */
310 if (node->nchild)
311 return 1;
312 if (!tree_add_unmatched(curr, cache, NULL, node, tree))
313 return 0;
314 /* Add it */
315 } else {
316 /* If mapping: matched if one child per expected policy set */
317 STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
318 if (node->nchild == sk_ASN1_OBJECT_num(expset))
319 return 1;
320 /* Locate unmatched nodes */
321 for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) {
322 ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
323 if (level_find_node(curr, node, oid))
324 continue;
325 if (!tree_add_unmatched(curr, cache, oid, node, tree))
326 return 0;
327 }
328 }
329
330 return 1;
331}
332
333static int
334tree_link_any(X509_POLICY_LEVEL *curr, const X509_POLICY_CACHE *cache,
335 X509_POLICY_TREE *tree)
336{
337 int i;
338 X509_POLICY_NODE *node;
339 X509_POLICY_LEVEL *last = curr - 1;
340
341 for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
342 node = sk_X509_POLICY_NODE_value(last->nodes, i);
343
344 if (!tree_link_unmatched(curr, cache, node, tree))
345 return 0;
346 }
347 /* Finally add link to anyPolicy */
348 if (last->anyPolicy) {
349 if (!level_add_node(curr, cache->anyPolicy,
350 last->anyPolicy, NULL, NULL))
351 return 0;
352 }
353 return 1;
354}
355
356/* Prune the tree: delete any child mapped child data on the current level
357 * then proceed up the tree deleting any data with no children. If we ever
358 * have no data on a level we can halt because the tree will be empty.
359 */
360
361static int
362tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
363{
364 STACK_OF(X509_POLICY_NODE) *nodes;
365 X509_POLICY_NODE *node;
366 int i;
367
368 nodes = curr->nodes;
369 if (curr->flags & X509_V_FLAG_INHIBIT_MAP) {
370 for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
371 node = sk_X509_POLICY_NODE_value(nodes, i);
372 /* Delete any mapped data: see RFC3280 XXXX */
373 if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) {
374 node->parent->nchild--;
375 free(node);
376 (void)sk_X509_POLICY_NODE_delete(nodes, i);
377 }
378 }
379 }
380
381 for (;;) {
382 --curr;
383 nodes = curr->nodes;
384 for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
385 node = sk_X509_POLICY_NODE_value(nodes, i);
386 if (node->nchild == 0) {
387 node->parent->nchild--;
388 free(node);
389 (void)sk_X509_POLICY_NODE_delete(nodes, i);
390 }
391 }
392 if (curr->anyPolicy && !curr->anyPolicy->nchild) {
393 if (curr->anyPolicy->parent)
394 curr->anyPolicy->parent->nchild--;
395 free(curr->anyPolicy);
396 curr->anyPolicy = NULL;
397 }
398 if (curr == tree->levels) {
399 /* If we zapped anyPolicy at top then tree is empty */
400 if (!curr->anyPolicy)
401 return 2;
402 return 1;
403 }
404 }
405
406 return 1;
407}
408
409static int
410tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes, X509_POLICY_NODE *pcy)
411{
412 if (!*pnodes) {
413 *pnodes = policy_node_cmp_new();
414 if (!*pnodes)
415 return 0;
416 } else if (sk_X509_POLICY_NODE_find(*pnodes, pcy) != -1)
417 return 1;
418
419 if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
420 return 0;
421
422 return 1;
423}
424
425/* Calculate the authority set based on policy tree.
426 * The 'pnodes' parameter is used as a store for the set of policy nodes
427 * used to calculate the user set. If the authority set is not anyPolicy
428 * then pnodes will just point to the authority set. If however the authority
429 * set is anyPolicy then the set of valid policies (other than anyPolicy)
430 * is store in pnodes. The return value of '2' is used in this case to indicate
431 * that pnodes should be freed.
432 */
433
434static int
435tree_calculate_authority_set(X509_POLICY_TREE *tree,
436 STACK_OF(X509_POLICY_NODE) **pnodes)
437{
438 X509_POLICY_LEVEL *curr;
439 X509_POLICY_NODE *node, *anyptr;
440 STACK_OF(X509_POLICY_NODE) **addnodes;
441 int i, j;
442
443 curr = tree->levels + tree->nlevel - 1;
444
445 /* If last level contains anyPolicy set is anyPolicy */
446 if (curr->anyPolicy) {
447 if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
448 return 0;
449 addnodes = pnodes;
450 } else
451 /* Add policies to authority set */
452 addnodes = &tree->auth_policies;
453
454 curr = tree->levels;
455 for (i = 1; i < tree->nlevel; i++) {
456 /* If no anyPolicy node on this this level it can't
457 * appear on lower levels so end search.
458 */
459 if (!(anyptr = curr->anyPolicy))
460 break;
461 curr++;
462 for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) {
463 node = sk_X509_POLICY_NODE_value(curr->nodes, j);
464 if ((node->parent == anyptr) &&
465 !tree_add_auth_node(addnodes, node))
466 return 0;
467 }
468 }
469
470 if (addnodes == pnodes)
471 return 2;
472
473 *pnodes = tree->auth_policies;
474
475 return 1;
476}
477
478static int
479tree_calculate_user_set(X509_POLICY_TREE *tree,
480 STACK_OF(ASN1_OBJECT) *policy_oids, STACK_OF(X509_POLICY_NODE) *auth_nodes)
481{
482 int i;
483 X509_POLICY_NODE *node;
484 ASN1_OBJECT *oid;
485 X509_POLICY_NODE *anyPolicy;
486 X509_POLICY_DATA *extra;
487
488 /* Check if anyPolicy present in authority constrained policy set:
489 * this will happen if it is a leaf node.
490 */
491
492 if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
493 return 1;
494
495 anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
496
497 for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
498 oid = sk_ASN1_OBJECT_value(policy_oids, i);
499 if (OBJ_obj2nid(oid) == NID_any_policy) {
500 tree->flags |= POLICY_FLAG_ANY_POLICY;
501 return 1;
502 }
503 }
504
505 for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
506 oid = sk_ASN1_OBJECT_value(policy_oids, i);
507 node = tree_find_sk(auth_nodes, oid);
508 if (!node) {
509 if (!anyPolicy)
510 continue;
511 /* Create a new node with policy ID from user set
512 * and qualifiers from anyPolicy.
513 */
514 extra = policy_data_new(NULL, oid,
515 node_critical(anyPolicy));
516 if (!extra)
517 return 0;
518 extra->qualifier_set = anyPolicy->data->qualifier_set;
519 extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS |
520 POLICY_DATA_FLAG_EXTRA_NODE;
521 (void) level_add_node(NULL, extra, anyPolicy->parent,
522 tree, &node);
523 }
524 if (!tree->user_policies) {
525 tree->user_policies = sk_X509_POLICY_NODE_new_null();
526 if (!tree->user_policies)
527 return 1;
528 }
529 if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
530 return 0;
531 }
532 return 1;
533}
534
535static int
536tree_evaluate(X509_POLICY_TREE *tree)
537{
538 int ret, i;
539 X509_POLICY_LEVEL *curr = tree->levels + 1;
540 const X509_POLICY_CACHE *cache;
541
542 for (i = 1; i < tree->nlevel; i++, curr++) {
543 cache = policy_cache_set(curr->cert);
544 if (!tree_link_nodes(curr, cache))
545 return 0;
546
547 if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) &&
548 !tree_link_any(curr, cache, tree))
549 return 0;
550 ret = tree_prune(tree, curr);
551 if (ret != 1)
552 return ret;
553 }
554
555 return 1;
556}
557
558static void
559exnode_free(X509_POLICY_NODE *node)
560{
561 if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
562 free(node);
563}
564
565void
566X509_policy_tree_free(X509_POLICY_TREE *tree)
567{
568 X509_POLICY_LEVEL *curr;
569 int i;
570
571 if (!tree)
572 return;
573
574 sk_X509_POLICY_NODE_free(tree->auth_policies);
575 sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
576
577 for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) {
578 X509_free(curr->cert);
579 if (curr->nodes)
580 sk_X509_POLICY_NODE_pop_free(curr->nodes,
581 policy_node_free);
582 if (curr->anyPolicy)
583 policy_node_free(curr->anyPolicy);
584 }
585
586 if (tree->extra_data)
587 sk_X509_POLICY_DATA_pop_free(tree->extra_data,
588 policy_data_free);
589
590 free(tree->levels);
591 free(tree);
592}
593LCRYPTO_ALIAS(X509_policy_tree_free);
594
595/* Application policy checking function.
596 * Return codes:
597 * 0 Internal Error.
598 * 1 Successful.
599 * -1 One or more certificates contain invalid or inconsistent extensions
600 * -2 User constrained policy set empty and requireExplicit true.
601 */
602
603int
604X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
605 STACK_OF(X509) *certs, STACK_OF(ASN1_OBJECT) *policy_oids,
606 unsigned int flags)
607{
608 int ret, ret2;
609 X509_POLICY_TREE *tree = NULL;
610 STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
611
612 *ptree = NULL;
613 *pexplicit_policy = 0;
614 ret = tree_init(&tree, certs, flags);
615
616 switch (ret) {
617
618 /* Tree empty requireExplicit False: OK */
619 case 2:
620 return 1;
621
622 /* Some internal error */
623 case -1:
624 return -1;
625
626 /* Some internal error */
627 case 0:
628 return 0;
629
630 /* Tree empty requireExplicit True: Error */
631
632 case 6:
633 *pexplicit_policy = 1;
634 return -2;
635
636 /* Tree OK requireExplicit True: OK and continue */
637 case 5:
638 *pexplicit_policy = 1;
639 break;
640
641 /* Tree OK: continue */
642
643 case 1:
644 if (!tree)
645 /*
646 * tree_init() returns success and a null tree
647 * if it's just looking at a trust anchor.
648 * I'm not sure that returning success here is
649 * correct, but I'm sure that reporting this
650 * as an internal error which our caller
651 * interprets as a malloc failure is wrong.
652 */
653 return 1;
654 break;
655 }
656
657 if (!tree)
658 goto error;
659 ret = tree_evaluate(tree);
660 if (ret <= 0)
661 goto error;
662
663 /* Return value 2 means tree empty */
664 if (ret == 2) {
665 X509_policy_tree_free(tree);
666 if (*pexplicit_policy)
667 return -2;
668 else
669 return 1;
670 }
671
672 /* Tree is not empty: continue */
673
674 ret = tree_calculate_authority_set(tree, &auth_nodes);
675 if (ret == 0)
676 goto error;
677
678 ret2 = tree_calculate_user_set(tree, policy_oids, auth_nodes);
679
680 /* Return value 2 means auth_nodes needs to be freed */
681 if (ret == 2)
682 sk_X509_POLICY_NODE_free(auth_nodes);
683
684 if (ret2 == 0)
685 goto error;
686
687 if (tree)
688 *ptree = tree;
689
690 if (*pexplicit_policy) {
691 nodes = X509_policy_tree_get0_user_policies(tree);
692 if (sk_X509_POLICY_NODE_num(nodes) <= 0)
693 return -2;
694 }
695
696 return 1;
697
698error:
699 X509_policy_tree_free(tree);
700
701 return 0;
702}
703LCRYPTO_ALIAS(X509_policy_check);
704
705#endif /* LIBRESSL_HAS_POLICY_DAG */