v3_lib.c
Go to the documentation of this file.
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 
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 
83 {
84  if (!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_stack_cmp))) {
87  return 0;
88  }
89  if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
92  return 0;
93  }
94  return 1;
95 }
96 
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 
105 {
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 =
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 
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 
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) {
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 {
149  return 0;
150  }
151 
152  return 1;
153 }
154 
156 {
157  for (; extlist->ext_nid != -1; extlist++)
158  if (!X509V3_EXT_add(extlist))
159  return 0;
160  return 1;
161 }
162 
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))) {
170  return 0;
171  }
172  if (!
173  (tmpext =
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 
185 {
186  sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
187  ext_list = NULL;
188 }
189 
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 
202 {
203  return 1;
204 }
205 
206 /* Return an extension internal structure */
207 
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) {
230  } else {
231  method->ext_free(ret);
232  }
234  return NULL;
235  }
236  return ret;
237 }
238 
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 
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)) {
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) {
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);
373  return -1;
374 
375  err:
376  if (!(flags & X509V3_ADD_SILENT))
377  OPENSSL_PUT_ERROR(X509V3, errcode);
378  return 0;
379 }
ext_list_free
static void ext_list_free(X509V3_EXT_METHOD *ext)
Definition: v3_lib.c:190
X509V3_EXT_i2d
#define X509V3_EXT_i2d
Definition: boringssl_prefix_symbols.h:2224
X509V3_EXT_add
int X509V3_EXT_add(X509V3_EXT_METHOD *ext)
Definition: v3_lib.c:82
ext_dat.h
OPENSSL_PUT_ERROR
#define OPENSSL_PUT_ERROR(library, reason)
Definition: err.h:423
ext
void * ext
Definition: x509v3.h:87
X509V3_EXT_get
const X509V3_EXT_METHOD * X509V3_EXT_get(const X509_EXTENSION *ext)
Definition: v3_lib.c:127
X509V3_ADD_DELETE
#define X509V3_ADD_DELETE
Definition: x509v3.h:761
error_ref_leak.err
err
Definition: error_ref_leak.py:35
X509V3_EXT_free
int X509V3_EXT_free(int nid, void *ext_data)
Definition: v3_lib.c:135
X509V3_ADD_DEFAULT
#define X509V3_ADD_DEFAULT
Definition: x509v3.h:740
X509V3_R_TRAILING_DATA_IN_EXTENSION
#define X509V3_R_TRAILING_DATA_IN_EXTENSION
Definition: x509v3.h:1018
x509v3.h
X509V3_EXT_d2i
void * X509V3_EXT_d2i(const X509_EXTENSION *ext)
Definition: v3_lib.c:208
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
xds_manager.p
p
Definition: xds_manager.py:60
ASN1_ITEM_ptr
#define ASN1_ITEM_ptr(iptr)
Definition: asn1.h:316
v3_ext_method::ext_flags
int ext_flags
Definition: x509v3.h:104
X509_extension_st
Definition: third_party/boringssl-with-bazel/src/crypto/x509/internal.h:117
ex
OPENSSL_EXPORT X509_EXTENSION * ex
Definition: x509.h:1418
X509V3_R_ERROR_CREATING_EXTENSION
#define X509V3_R_ERROR_CREATING_EXTENSION
Definition: x509v3.h:963
X509V3_EXT_add_alias
int X509V3_EXT_add_alias(int nid_to, int nid_from)
Definition: v3_lib.c:163
X509V3_ADD_APPEND
#define X509V3_ADD_APPEND
Definition: x509v3.h:744
OPENSSL_malloc
#define OPENSSL_malloc
Definition: boringssl_prefix_symbols.h:1885
X509_extension_st::object
ASN1_OBJECT * object
Definition: third_party/boringssl-with-bazel/src/crypto/x509/internal.h:118
OBJ_obj2nid
#define OBJ_obj2nid
Definition: boringssl_prefix_symbols.h:1857
X509V3_R_EXTENSION_EXISTS
#define X509V3_R_EXTENSION_EXISTS
Definition: x509v3.h:966
X509V3_EXT_get_nid
const X509V3_EXT_METHOD * X509V3_EXT_get_nid(int nid)
Definition: v3_lib.c:104
X509v3_get_ext_by_NID
#define X509v3_get_ext_by_NID
Definition: boringssl_prefix_symbols.h:2747
err.h
X509V3_ADD_REPLACE_EXISTING
#define X509V3_ADD_REPLACE_EXISTING
Definition: x509v3.h:752
NID_undef
#define NID_undef
Definition: nid.h:85
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
conf.extensions
list extensions
Definition: doc/python/sphinx/conf.py:54
conf.h
X509_EXTENSION_free
#define X509_EXTENSION_free
Definition: boringssl_prefix_symbols.h:2336
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
X509V3_get_d2i
void * X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *extensions, int nid, int *out_critical, int *out_idx)
Definition: v3_lib.c:239
setup.idx
idx
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:197
nid
int nid
Definition: cipher_extra.c:71
v3_ext_method::it
ASN1_ITEM_EXP * it
Definition: x509v3.h:106
value
const char * value
Definition: hpack_parser_table.cc:165
STANDARD_EXTENSION_COUNT
#define STANDARD_EXTENSION_COUNT
Definition: ext_dat.h:134
standard_exts
static const X509V3_EXT_METHOD *const standard_exts[]
Definition: ext_dat.h:87
X509V3_EXT_add_list
int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist)
Definition: v3_lib.c:155
STACK_OF
static STACK_OF(X509V3_EXT_METHOD)
Definition: v3_lib.c:72
X509V3_add_standard_extensions
int X509V3_add_standard_extensions(void)
Definition: v3_lib.c:201
absl::flags_internal
Definition: abseil-cpp/absl/flags/commandlineflag.h:40
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
X509V3_ADD_SILENT
#define X509V3_ADD_SILENT
Definition: x509v3.h:767
X509V3_EXT_DYNAMIC
#define X509V3_EXT_DYNAMIC
Definition: x509v3.h:153
obj.h
X509V3_add1_i2d
int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, int crit, unsigned long flags)
Definition: v3_lib.c:297
X509V3_EXT_cleanup
void X509V3_EXT_cleanup(void)
Definition: v3_lib.c:184
v3_ext_method
Definition: x509v3.h:102
X509V3_ADD_KEEP_EXISTING
#define X509V3_ADD_KEEP_EXISTING
Definition: x509v3.h:756
mem.h
autogen_x86imm.tmp
tmp
Definition: autogen_x86imm.py:12
ASN1_item_free
#define ASN1_item_free
Definition: boringssl_prefix_symbols.h:746
X509_EXTENSION_get_critical
#define X509_EXTENSION_get_critical
Definition: boringssl_prefix_symbols.h:2337
X509V3_ADD_OP_MASK
#define X509V3_ADD_OP_MASK
Definition: x509v3.h:736
X509V3_R_CANNOT_FIND_FREE_FUNCTION
#define X509V3_R_CANNOT_FIND_FREE_FUNCTION
Definition: x509v3.h:958
method
NSString * method
Definition: ProtoMethod.h:28
OPENSSL_free
#define OPENSSL_free
Definition: boringssl_prefix_symbols.h:1869
X509V3_R_EXTENSION_NOT_FOUND
#define X509V3_R_EXTENSION_NOT_FOUND
Definition: x509v3.h:968
ASN1_item_d2i
#define ASN1_item_d2i
Definition: boringssl_prefix_symbols.h:737
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
v3_ext_method::ext_free
X509V3_EXT_FREE ext_free
Definition: x509v3.h:109
ERR_R_MALLOC_FAILURE
#define ERR_R_MALLOC_FAILURE
Definition: err.h:371
ext_cmp
static int ext_cmp(const void *void_a, const void *void_b)
Definition: v3_lib.c:97
v3_ext_method::ext_nid
int ext_nid
Definition: x509v3.h:103


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:49