]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/x509/pcy_cache.c
Update copyright year
[thirdparty/openssl.git] / crypto / x509 / pcy_cache.c
CommitLineData
0f113f3e 1/*
454afd98 2 * Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
4acc3e90 3 *
4286ca47 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
d2e9e320
RS
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
4acc3e90
DSH
8 */
9
b39fc560 10#include "internal/cryptlib.h"
4acc3e90
DSH
11#include <openssl/x509.h>
12#include <openssl/x509v3.h>
25f2138b 13#include "crypto/x509.h"
4acc3e90 14
706457b7 15#include "pcy_local.h"
4acc3e90 16
852c2ed2
RS
17DEFINE_STACK_OF(POLICYINFO)
18
0f113f3e
MC
19static int policy_data_cmp(const X509_POLICY_DATA *const *a,
20 const X509_POLICY_DATA *const *b);
4acc3e90
DSH
21static int policy_cache_set_int(long *out, ASN1_INTEGER *value);
22
0f113f3e
MC
23/*
24 * Set cache entry according to CertificatePolicies extension. Note: this
25 * destroys the passed CERTIFICATEPOLICIES structure.
4acc3e90
DSH
26 */
27
28static int policy_cache_create(X509 *x,
0f113f3e
MC
29 CERTIFICATEPOLICIES *policies, int crit)
30{
5b37fef0 31 int i, num, ret = 0;
0f113f3e
MC
32 X509_POLICY_CACHE *cache = x->policy_cache;
33 X509_POLICY_DATA *data = NULL;
34 POLICYINFO *policy;
7fcdbd83 35
5b37fef0 36 if ((num = sk_POLICYINFO_num(policies)) <= 0)
0f113f3e
MC
37 goto bad_policy;
38 cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp);
7fcdbd83
F
39 if (cache->data == NULL) {
40 X509V3err(X509V3_F_POLICY_CACHE_CREATE, ERR_R_MALLOC_FAILURE);
41 goto just_cleanup;
42 }
5b37fef0 43 for (i = 0; i < num; i++) {
0f113f3e
MC
44 policy = sk_POLICYINFO_value(policies, i);
45 data = policy_data_new(policy, NULL, crit);
7fcdbd83
F
46 if (data == NULL) {
47 X509V3err(X509V3_F_POLICY_CACHE_CREATE, ERR_R_MALLOC_FAILURE);
48 goto just_cleanup;
49 }
0f113f3e
MC
50 /*
51 * Duplicate policy OIDs are illegal: reject if matches found.
52 */
53 if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
54 if (cache->anyPolicy) {
55 ret = -1;
56 goto bad_policy;
57 }
58 cache->anyPolicy = data;
5b37fef0 59 } else if (sk_X509_POLICY_DATA_find(cache->data, data) >=0 ) {
0f113f3e
MC
60 ret = -1;
61 goto bad_policy;
7fcdbd83
F
62 } else if (!sk_X509_POLICY_DATA_push(cache->data, data)) {
63 X509V3err(X509V3_F_POLICY_CACHE_CREATE, ERR_R_MALLOC_FAILURE);
0f113f3e 64 goto bad_policy;
7fcdbd83 65 }
0f113f3e
MC
66 data = NULL;
67 }
68 ret = 1;
7fcdbd83 69
0f113f3e
MC
70 bad_policy:
71 if (ret == -1)
72 x->ex_flags |= EXFLAG_INVALID_POLICY;
25aaa98a 73 policy_data_free(data);
7fcdbd83 74 just_cleanup:
0f113f3e
MC
75 sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
76 if (ret <= 0) {
77 sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
78 cache->data = NULL;
79 }
80 return ret;
81}
4acc3e90 82
4acc3e90 83static int policy_cache_new(X509 *x)
0f113f3e
MC
84{
85 X509_POLICY_CACHE *cache;
86 ASN1_INTEGER *ext_any = NULL;
87 POLICY_CONSTRAINTS *ext_pcons = NULL;
88 CERTIFICATEPOLICIES *ext_cpols = NULL;
89 POLICY_MAPPINGS *ext_pmaps = NULL;
90 int i;
7d6df9e9
P
91
92 if (x->policy_cache != NULL)
93 return 1;
b4faea50 94 cache = OPENSSL_malloc(sizeof(*cache));
7fcdbd83
F
95 if (cache == NULL) {
96 X509V3err(X509V3_F_POLICY_CACHE_NEW, ERR_R_MALLOC_FAILURE);
0f113f3e 97 return 0;
7fcdbd83 98 }
0f113f3e
MC
99 cache->anyPolicy = NULL;
100 cache->data = NULL;
101 cache->any_skip = -1;
102 cache->explicit_skip = -1;
103 cache->map_skip = -1;
4acc3e90 104
0f113f3e 105 x->policy_cache = cache;
4acc3e90 106
0f113f3e
MC
107 /*
108 * Handle requireExplicitPolicy *first*. Need to process this even if we
109 * don't have any policies.
110 */
111 ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL);
4acc3e90 112
0f113f3e
MC
113 if (!ext_pcons) {
114 if (i != -1)
115 goto bad_cache;
116 } else {
117 if (!ext_pcons->requireExplicitPolicy
118 && !ext_pcons->inhibitPolicyMapping)
119 goto bad_cache;
120 if (!policy_cache_set_int(&cache->explicit_skip,
121 ext_pcons->requireExplicitPolicy))
122 goto bad_cache;
123 if (!policy_cache_set_int(&cache->map_skip,
124 ext_pcons->inhibitPolicyMapping))
125 goto bad_cache;
126 }
4acc3e90 127
0f113f3e 128 /* Process CertificatePolicies */
4acc3e90 129
0f113f3e
MC
130 ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
131 /*
132 * If no CertificatePolicies extension or problem decoding then there is
133 * no point continuing because the valid policies will be NULL.
134 */
135 if (!ext_cpols) {
136 /* If not absent some problem with extension */
137 if (i != -1)
138 goto bad_cache;
139 return 1;
140 }
4acc3e90 141
0f113f3e 142 i = policy_cache_create(x, ext_cpols, i);
4acc3e90 143
0f113f3e 144 /* NB: ext_cpols freed by policy_cache_set_policies */
4acc3e90 145
0f113f3e
MC
146 if (i <= 0)
147 return i;
4acc3e90 148
0f113f3e 149 ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL);
4acc3e90 150
0f113f3e
MC
151 if (!ext_pmaps) {
152 /* If not absent some problem with extension */
153 if (i != -1)
154 goto bad_cache;
155 } else {
156 i = policy_cache_set_mapping(x, ext_pmaps);
157 if (i <= 0)
158 goto bad_cache;
159 }
4acc3e90 160
0f113f3e 161 ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL);
4acc3e90 162
0f113f3e
MC
163 if (!ext_any) {
164 if (i != -1)
165 goto bad_cache;
166 } else if (!policy_cache_set_int(&cache->any_skip, ext_any))
167 goto bad_cache;
66696478 168 goto just_cleanup;
4acc3e90 169
0f113f3e 170 bad_cache:
66696478 171 x->ex_flags |= EXFLAG_INVALID_POLICY;
4acc3e90 172
66696478 173 just_cleanup:
25aaa98a 174 POLICY_CONSTRAINTS_free(ext_pcons);
2ace7450 175 ASN1_INTEGER_free(ext_any);
0f113f3e 176 return 1;
4acc3e90 177
4acc3e90
DSH
178}
179
180void policy_cache_free(X509_POLICY_CACHE *cache)
0f113f3e
MC
181{
182 if (!cache)
183 return;
25aaa98a 184 policy_data_free(cache->anyPolicy);
222561fe 185 sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
0f113f3e
MC
186 OPENSSL_free(cache);
187}
4acc3e90
DSH
188
189const X509_POLICY_CACHE *policy_cache_set(X509 *x)
0f113f3e 190{
4acc3e90 191
0f113f3e 192 if (x->policy_cache == NULL) {
c001ce33 193 CRYPTO_THREAD_write_lock(x->lock);
0f113f3e 194 policy_cache_new(x);
c001ce33 195 CRYPTO_THREAD_unlock(x->lock);
0f113f3e 196 }
4acc3e90 197
0f113f3e 198 return x->policy_cache;
4acc3e90 199
0f113f3e 200}
4acc3e90
DSH
201
202X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
0f113f3e
MC
203 const ASN1_OBJECT *id)
204{
205 int idx;
206 X509_POLICY_DATA tmp;
207 tmp.valid_policy = (ASN1_OBJECT *)id;
208 idx = sk_X509_POLICY_DATA_find(cache->data, &tmp);
0f113f3e
MC
209 return sk_X509_POLICY_DATA_value(cache->data, idx);
210}
4acc3e90 211
0f113f3e
MC
212static int policy_data_cmp(const X509_POLICY_DATA *const *a,
213 const X509_POLICY_DATA *const *b)
214{
215 return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy);
216}
4acc3e90
DSH
217
218static int policy_cache_set_int(long *out, ASN1_INTEGER *value)
0f113f3e
MC
219{
220 if (value == NULL)
221 return 1;
222 if (value->type == V_ASN1_NEG_INTEGER)
223 return 0;
224 *out = ASN1_INTEGER_get(value);
225 return 1;
226}