1 /* v3_lib.c */
2 /*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4 * 1999.
5 */
6 /* ====================================================================
7 * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 * software must display the following acknowledgment:
23 * "This product includes software developed by the OpenSSL Project
24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 * endorse or promote products derived from this software without
28 * prior written permission. For written permission, please contact
29 * licensing@OpenSSL.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 * nor may "OpenSSL" appear in their names without prior written
33 * permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 * acknowledgment:
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 *
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com). This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com).
57 *
58 */
59 /* X509 v3 extension utilities */
60
61 #include <stdio.h>
62
63 #include <openssl/conf.h>
64 #include <openssl/err.h>
65 #include <openssl/mem.h>
66 #include <openssl/obj.h>
67 #include <openssl/x509v3.h>
68
69 #include "../x509/internal.h"
70
71 #include "ext_dat.h"
72 static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL;
73
74 static void ext_list_free(X509V3_EXT_METHOD *ext);
75
ext_stack_cmp(const X509V3_EXT_METHOD ** a,const X509V3_EXT_METHOD ** b)76 static int ext_stack_cmp(const X509V3_EXT_METHOD **a,
77 const X509V3_EXT_METHOD **b)
78 {
79 return ((*a)->ext_nid - (*b)->ext_nid);
80 }
81
X509V3_EXT_add(X509V3_EXT_METHOD * ext)82 int X509V3_EXT_add(X509V3_EXT_METHOD *ext)
83 {
84 if (!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_stack_cmp))) {
85 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
86 ext_list_free(ext);
87 return 0;
88 }
89 if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
90 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
91 ext_list_free(ext);
92 return 0;
93 }
94 return 1;
95 }
96
ext_cmp(const void * void_a,const void * void_b)97 static int ext_cmp(const void *void_a, const void *void_b)
98 {
99 const X509V3_EXT_METHOD **a = (const X509V3_EXT_METHOD **)void_a;
100 const X509V3_EXT_METHOD **b = (const X509V3_EXT_METHOD **)void_b;
101 return ext_stack_cmp(a, b);
102 }
103
X509V3_EXT_get_nid(int nid)104 const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid)
105 {
106 X509V3_EXT_METHOD tmp;
107 const X509V3_EXT_METHOD *t = &tmp, *const *ret;
108 size_t idx;
109
110 if (nid < 0)
111 return NULL;
112 tmp.ext_nid = nid;
113 ret =
114 bsearch(&t, standard_exts, STANDARD_EXTENSION_COUNT,
115 sizeof(X509V3_EXT_METHOD *), ext_cmp);
116 if (ret)
117 return *ret;
118 if (!ext_list)
119 return NULL;
120
121 sk_X509V3_EXT_METHOD_sort(ext_list);
122 if (!sk_X509V3_EXT_METHOD_find(ext_list, &idx, &tmp))
123 return NULL;
124 return sk_X509V3_EXT_METHOD_value(ext_list, idx);
125 }
126
X509V3_EXT_get(const X509_EXTENSION * ext)127 const X509V3_EXT_METHOD *X509V3_EXT_get(const X509_EXTENSION *ext)
128 {
129 int nid;
130 if ((nid = OBJ_obj2nid(ext->object)) == NID_undef)
131 return NULL;
132 return X509V3_EXT_get_nid(nid);
133 }
134
X509V3_EXT_free(int nid,void * ext_data)135 int X509V3_EXT_free(int nid, void *ext_data)
136 {
137 const X509V3_EXT_METHOD *ext_method = X509V3_EXT_get_nid(nid);
138 if (ext_method == NULL) {
139 OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION);
140 return 0;
141 }
142
143 if (ext_method->it != NULL)
144 ASN1_item_free(ext_data, ASN1_ITEM_ptr(ext_method->it));
145 else if (ext_method->ext_free != NULL)
146 ext_method->ext_free(ext_data);
147 else {
148 OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION);
149 return 0;
150 }
151
152 return 1;
153 }
154
X509V3_EXT_add_list(X509V3_EXT_METHOD * extlist)155 int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist)
156 {
157 for (; extlist->ext_nid != -1; extlist++)
158 if (!X509V3_EXT_add(extlist))
159 return 0;
160 return 1;
161 }
162
X509V3_EXT_add_alias(int nid_to,int nid_from)163 int X509V3_EXT_add_alias(int nid_to, int nid_from)
164 {
165 const X509V3_EXT_METHOD *ext;
166 X509V3_EXT_METHOD *tmpext;
167
168 if (!(ext = X509V3_EXT_get_nid(nid_from))) {
169 OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NOT_FOUND);
170 return 0;
171 }
172 if (!
173 (tmpext =
174 (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) {
175 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
176 return 0;
177 }
178 *tmpext = *ext;
179 tmpext->ext_nid = nid_to;
180 tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
181 return X509V3_EXT_add(tmpext);
182 }
183
X509V3_EXT_cleanup(void)184 void X509V3_EXT_cleanup(void)
185 {
186 sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
187 ext_list = NULL;
188 }
189
ext_list_free(X509V3_EXT_METHOD * ext)190 static void ext_list_free(X509V3_EXT_METHOD *ext)
191 {
192 if (ext->ext_flags & X509V3_EXT_DYNAMIC)
193 OPENSSL_free(ext);
194 }
195
196 /*
197 * Legacy function: we don't need to add standard extensions any more because
198 * they are now kept in ext_dat.h.
199 */
200
X509V3_add_standard_extensions(void)201 int X509V3_add_standard_extensions(void)
202 {
203 return 1;
204 }
205
206 /* Return an extension internal structure */
207
X509V3_EXT_d2i(const X509_EXTENSION * ext)208 void *X509V3_EXT_d2i(const X509_EXTENSION *ext)
209 {
210 const X509V3_EXT_METHOD *method;
211 const unsigned char *p;
212
213 if (!(method = X509V3_EXT_get(ext)))
214 return NULL;
215 p = ext->value->data;
216 void *ret;
217 if (method->it) {
218 ret = ASN1_item_d2i(NULL, &p, ext->value->length,
219 ASN1_ITEM_ptr(method->it));
220 } else {
221 ret = method->d2i(NULL, &p, ext->value->length);
222 }
223 if (ret == NULL) {
224 return NULL;
225 }
226 /* Check for trailing data. */
227 if (p != ext->value->data + ext->value->length) {
228 if (method->it) {
229 ASN1_item_free(ret, ASN1_ITEM_ptr(method->it));
230 } else {
231 method->ext_free(ret);
232 }
233 OPENSSL_PUT_ERROR(X509V3, X509V3_R_TRAILING_DATA_IN_EXTENSION);
234 return NULL;
235 }
236 return ret;
237 }
238
X509V3_get_d2i(const STACK_OF (X509_EXTENSION)* extensions,int nid,int * out_critical,int * out_idx)239 void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *extensions, int nid,
240 int *out_critical, int *out_idx)
241 {
242 int lastpos;
243 size_t i;
244 X509_EXTENSION *ex, *found_ex = NULL;
245 if (!extensions) {
246 if (out_idx)
247 *out_idx = -1;
248 if (out_critical)
249 *out_critical = -1;
250 return NULL;
251 }
252 if (out_idx)
253 lastpos = *out_idx + 1;
254 else
255 lastpos = 0;
256 if (lastpos < 0)
257 lastpos = 0;
258 for (i = lastpos; i < sk_X509_EXTENSION_num(extensions); i++) {
259 ex = sk_X509_EXTENSION_value(extensions, i);
260 if (OBJ_obj2nid(ex->object) == nid) {
261 if (out_idx) {
262 /* TODO(https://crbug.com/boringssl/379): Consistently reject
263 * duplicate extensions. */
264 *out_idx = i;
265 found_ex = ex;
266 break;
267 } else if (found_ex) {
268 /* Found more than one */
269 if (out_critical)
270 *out_critical = -2;
271 return NULL;
272 }
273 found_ex = ex;
274 }
275 }
276 if (found_ex) {
277 /* Found it */
278 if (out_critical)
279 *out_critical = X509_EXTENSION_get_critical(found_ex);
280 return X509V3_EXT_d2i(found_ex);
281 }
282
283 /* Extension not found */
284 if (out_idx)
285 *out_idx = -1;
286 if (out_critical)
287 *out_critical = -1;
288 return NULL;
289 }
290
291 /*
292 * This function is a general extension append, replace and delete utility.
293 * The precise operation is governed by the 'flags' value. The 'crit' and
294 * 'value' arguments (if relevant) are the extensions internal structure.
295 */
296
X509V3_add1_i2d(STACK_OF (X509_EXTENSION)** x,int nid,void * value,int crit,unsigned long flags)297 int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
298 int crit, unsigned long flags)
299 {
300 int errcode, extidx = -1;
301 X509_EXTENSION *ext = NULL, *extmp;
302 STACK_OF(X509_EXTENSION) *ret = NULL;
303 unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
304
305 /*
306 * If appending we don't care if it exists, otherwise look for existing
307 * extension.
308 */
309 if (ext_op != X509V3_ADD_APPEND)
310 extidx = X509v3_get_ext_by_NID(*x, nid, -1);
311
312 /* See if extension exists */
313 if (extidx >= 0) {
314 /* If keep existing, nothing to do */
315 if (ext_op == X509V3_ADD_KEEP_EXISTING)
316 return 1;
317 /* If default then its an error */
318 if (ext_op == X509V3_ADD_DEFAULT) {
319 errcode = X509V3_R_EXTENSION_EXISTS;
320 goto err;
321 }
322 /* If delete, just delete it */
323 if (ext_op == X509V3_ADD_DELETE) {
324 if (!sk_X509_EXTENSION_delete(*x, extidx))
325 return -1;
326 return 1;
327 }
328 } else {
329 /*
330 * If replace existing or delete, error since extension must exist
331 */
332 if ((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
333 (ext_op == X509V3_ADD_DELETE)) {
334 errcode = X509V3_R_EXTENSION_NOT_FOUND;
335 goto err;
336 }
337 }
338
339 /*
340 * If we get this far then we have to create an extension: could have
341 * some flags for alternative encoding schemes...
342 */
343
344 ext = X509V3_EXT_i2d(nid, crit, value);
345
346 if (!ext) {
347 OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CREATING_EXTENSION);
348 return 0;
349 }
350
351 /* If extension exists replace it.. */
352 if (extidx >= 0) {
353 extmp = sk_X509_EXTENSION_value(*x, extidx);
354 X509_EXTENSION_free(extmp);
355 if (!sk_X509_EXTENSION_set(*x, extidx, ext))
356 return -1;
357 return 1;
358 }
359
360 if ((ret = *x) == NULL
361 && (ret = sk_X509_EXTENSION_new_null()) == NULL)
362 goto m_fail;
363 if (!sk_X509_EXTENSION_push(ret, ext))
364 goto m_fail;
365
366 *x = ret;
367 return 1;
368
369 m_fail:
370 if (ret != *x)
371 sk_X509_EXTENSION_free(ret);
372 X509_EXTENSION_free(ext);
373 return -1;
374
375 err:
376 if (!(flags & X509V3_ADD_SILENT))
377 OPENSSL_PUT_ERROR(X509V3, errcode);
378 return 0;
379 }
380