• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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