This is never used and we can make the built-in one performant. Change-Id: I6fc7639ba852349933789e73762bc3fa1341b2ff Reviewed-on: https://boringssl-review.googlesource.com/4370 Reviewed-by: Adam Langley <agl@google.com>kris/onging/CECPQ3_patch15
@@ -143,7 +143,6 @@ add_library( | |||
thread_pthread.c | |||
thread_win.c | |||
ex_data.c | |||
ex_data_impl.c | |||
time_support.c | |||
directory_posix.c | |||
directory_win.c | |||
@@ -1,18 +0,0 @@ | |||
/* Copyright (c) 2014, Google Inc. | |||
* | |||
* Permission to use, copy, modify, and/or distribute this software for any | |||
* purpose with or without fee is hereby granted, provided that the above | |||
* copyright notice and this permission notice appear in all copies. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | |||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ | |||
#define CRYPTO_F_CRYPTO_set_ex_data 100 | |||
#define CRYPTO_F_get_class 101 | |||
#define CRYPTO_F_get_new_index 102 | |||
#define CRYPTO_F_get_func_pointers 103 |
@@ -1,4 +1,4 @@ | |||
CRYPTO,function,100,CRYPTO_set_ex_data | |||
CRYPTO,function,101,get_class | |||
CRYPTO,function,102,get_func_pointers | |||
CRYPTO,function,103,get_new_index | |||
CRYPTO,function,100,CRYPTO_get_ex_new_index | |||
CRYPTO,function,101,CRYPTO_set_ex_data | |||
CRYPTO,function,102,get_class | |||
CRYPTO,function,103,get_func_pointers |
@@ -111,43 +111,147 @@ | |||
#include <assert.h> | |||
#include <string.h> | |||
#include <openssl/crypto.h> | |||
#include <openssl/err.h> | |||
#include <openssl/lhash.h> | |||
#include <openssl/mem.h> | |||
#include <openssl/stack.h> | |||
#include <openssl/thread.h> | |||
#include "crypto_error.h" | |||
#include "internal.h" | |||
/* global_impl is the implementation that we use at runtime. */ | |||
static const CRYPTO_EX_DATA_IMPL *global_impl = NULL; | |||
typedef struct crypto_ex_data_func_st { | |||
long argl; /* Arbitary long */ | |||
void *argp; /* Arbitary void pointer */ | |||
CRYPTO_EX_new *new_func; | |||
CRYPTO_EX_free *free_func; | |||
CRYPTO_EX_dup *dup_func; | |||
} CRYPTO_EX_DATA_FUNCS; | |||
/* global_impl_once protects the call to |global_impl_init|. */ | |||
static CRYPTO_once_t global_impl_once = CRYPTO_ONCE_INIT; | |||
typedef struct st_ex_class_item { | |||
STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth; | |||
int class_value; | |||
} EX_CLASS_ITEM; | |||
/* global_user_set_impl is a pointer to a user provided implementation. If this | |||
* is non-NULL at the point of the first use of ex_data, |global_impl| will be | |||
* set to this value. */ | |||
static const CRYPTO_EX_DATA_IMPL *global_user_set_impl = NULL; | |||
static CRYPTO_once_t global_classes_once = CRYPTO_ONCE_INIT; | |||
static struct CRYPTO_STATIC_MUTEX global_classes_lock = | |||
CRYPTO_STATIC_MUTEX_INIT; | |||
static LHASH_OF(EX_CLASS_ITEM) *global_classes = NULL; | |||
/* ex_data_default_impl is a the default implementation, defined in | |||
* ex_data_impl.c. */ | |||
extern const CRYPTO_EX_DATA_IMPL ex_data_default_impl; | |||
static struct CRYPTO_STATIC_MUTEX global_next_class_lock = | |||
CRYPTO_STATIC_MUTEX_INIT; | |||
static int global_next_class = 100; | |||
/* global_impl_init is called once in order to set |global_impl|. */ | |||
static void global_impl_init(void) { | |||
global_impl = global_user_set_impl; | |||
if (global_impl == NULL) { | |||
global_impl = &ex_data_default_impl; | |||
/* class_hash is a hash function used by an LHASH of |EX_CLASS_ITEM| | |||
* structures. */ | |||
static uint32_t class_hash(const EX_CLASS_ITEM *a) { | |||
return a->class_value; | |||
} | |||
/* class_cmp is a comparison function for an LHASH of |EX_CLASS_ITEM| | |||
* structures. */ | |||
static int class_cmp(const EX_CLASS_ITEM *a, const EX_CLASS_ITEM *b) { | |||
return a->class_value - b->class_value; | |||
} | |||
/* data_funcs_free is a callback function from |sk_pop_free| that frees a | |||
* |CRYPTO_EX_DATA_FUNCS|. */ | |||
static void data_funcs_free(CRYPTO_EX_DATA_FUNCS *funcs) { | |||
OPENSSL_free(funcs); | |||
} | |||
/* class_free is a callback function from lh_doall to free the EX_CLASS_ITEM | |||
* structures. */ | |||
static void class_free(EX_CLASS_ITEM *item) { | |||
sk_CRYPTO_EX_DATA_FUNCS_pop_free(item->meth, data_funcs_free); | |||
OPENSSL_free(item); | |||
} | |||
static void global_classes_init(void) { | |||
global_classes = lh_EX_CLASS_ITEM_new(class_hash, class_cmp); | |||
} | |||
static EX_CLASS_ITEM *get_class(int class_value) { | |||
EX_CLASS_ITEM template, *class_item; | |||
int ok = 0; | |||
CRYPTO_once(&global_classes_once, global_classes_init); | |||
if (global_classes == NULL) { | |||
return NULL; | |||
} | |||
CRYPTO_STATIC_MUTEX_lock_write(&global_classes_lock); | |||
template.class_value = class_value; | |||
class_item = lh_EX_CLASS_ITEM_retrieve(global_classes, &template); | |||
if (class_item != NULL) { | |||
ok = 1; | |||
} else { | |||
class_item = OPENSSL_malloc(sizeof(EX_CLASS_ITEM)); | |||
if (class_item) { | |||
class_item->class_value = class_value; | |||
class_item->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null(); | |||
if (class_item->meth != NULL) { | |||
EX_CLASS_ITEM *old_data; | |||
ok = lh_EX_CLASS_ITEM_insert(global_classes, &old_data, class_item); | |||
assert(old_data == NULL); | |||
} | |||
} | |||
} | |||
CRYPTO_STATIC_MUTEX_unlock(&global_classes_lock); | |||
if (!ok) { | |||
if (class_item) { | |||
if (class_item->meth) { | |||
sk_CRYPTO_EX_DATA_FUNCS_free(class_item->meth); | |||
} | |||
OPENSSL_free(class_item); | |||
class_item = NULL; | |||
} | |||
OPENSSL_PUT_ERROR(CRYPTO, get_class, ERR_R_MALLOC_FAILURE); | |||
} | |||
return class_item; | |||
} | |||
int CRYPTO_get_ex_new_index(int class_value, long argl, void *argp, | |||
CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, | |||
CRYPTO_EX_free *free_func) { | |||
CRYPTO_once(&global_impl_once, global_impl_init); | |||
return global_impl->get_new_index(class_value, argl, argp, new_func, dup_func, | |||
free_func); | |||
EX_CLASS_ITEM *const item = get_class(class_value); | |||
CRYPTO_EX_DATA_FUNCS *funcs; | |||
int ret = -1; | |||
if (!item) { | |||
return -1; | |||
} | |||
funcs = OPENSSL_malloc(sizeof(CRYPTO_EX_DATA_FUNCS)); | |||
if (funcs == NULL) { | |||
OPENSSL_PUT_ERROR(CRYPTO, CRYPTO_get_ex_new_index, ERR_R_MALLOC_FAILURE); | |||
return -1; | |||
} | |||
funcs->argl = argl; | |||
funcs->argp = argp; | |||
funcs->new_func = new_func; | |||
funcs->dup_func = dup_func; | |||
funcs->free_func = free_func; | |||
CRYPTO_STATIC_MUTEX_lock_write(&global_classes_lock); | |||
if (!sk_CRYPTO_EX_DATA_FUNCS_push(item->meth, funcs)) { | |||
OPENSSL_PUT_ERROR(CRYPTO, CRYPTO_get_ex_new_index, ERR_R_MALLOC_FAILURE); | |||
OPENSSL_free(funcs); | |||
goto err; | |||
} | |||
ret = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth) - 1; | |||
err: | |||
CRYPTO_STATIC_MUTEX_unlock(&global_classes_lock); | |||
return ret; | |||
} | |||
int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int index, void *val) { | |||
@@ -182,39 +286,135 @@ void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx) { | |||
return sk_void_value(ad->sk, idx); | |||
} | |||
/* get_func_pointers takes a copy of the CRYPTO_EX_DATA_FUNCS pointers, if any, | |||
* for the given class. If there are some pointers, it sets |*out| to point to | |||
* a fresh stack of them. Otherwise it sets |*out| to NULL. It returns one on | |||
* success or zero on error. */ | |||
static int get_func_pointers(STACK_OF(CRYPTO_EX_DATA_FUNCS) **out, | |||
int class_value) { | |||
EX_CLASS_ITEM *const item = get_class(class_value); | |||
size_t n; | |||
if (!item) { | |||
return 0; | |||
} | |||
*out = NULL; | |||
/* CRYPTO_EX_DATA_FUNCS structures are static once set, so we can take a | |||
* shallow copy of the list under lock and then use the structures without | |||
* the lock held. */ | |||
CRYPTO_STATIC_MUTEX_lock_read(&global_classes_lock); | |||
n = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth); | |||
if (n > 0) { | |||
*out = sk_CRYPTO_EX_DATA_FUNCS_dup(item->meth); | |||
} | |||
CRYPTO_STATIC_MUTEX_unlock(&global_classes_lock); | |||
if (n > 0 && *out == NULL) { | |||
OPENSSL_PUT_ERROR(CRYPTO, get_func_pointers, ERR_R_MALLOC_FAILURE); | |||
return 0; | |||
} | |||
return 1; | |||
} | |||
int CRYPTO_ex_data_new_class(void) { | |||
CRYPTO_once(&global_impl_once, global_impl_init); | |||
return global_impl->new_class(); | |||
CRYPTO_STATIC_MUTEX_lock_write(&global_next_class_lock); | |||
const int ret = global_next_class++; | |||
CRYPTO_STATIC_MUTEX_unlock(&global_next_class_lock); | |||
return ret; | |||
} | |||
int CRYPTO_new_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) { | |||
CRYPTO_once(&global_impl_once, global_impl_init); | |||
return global_impl->new_ex_data(class_value, obj, ad); | |||
STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; | |||
size_t i; | |||
ad->sk = NULL; | |||
if (!get_func_pointers(&func_pointers, class_value)) { | |||
return 0; | |||
} | |||
for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) { | |||
CRYPTO_EX_DATA_FUNCS *func_pointer = | |||
sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i); | |||
if (func_pointer->new_func) { | |||
func_pointer->new_func(obj, NULL, ad, i, func_pointer->argl, | |||
func_pointer->argp); | |||
} | |||
} | |||
sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers); | |||
return 1; | |||
} | |||
int CRYPTO_dup_ex_data(int class_value, CRYPTO_EX_DATA *to, | |||
const CRYPTO_EX_DATA *from) { | |||
CRYPTO_once(&global_impl_once, global_impl_init); | |||
return global_impl->dup_ex_data(class_value, to, from); | |||
STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; | |||
size_t i; | |||
if (!from->sk) { | |||
/* In this case, |from| is blank, which is also the initial state of |to|, | |||
* so there's nothing to do. */ | |||
return 1; | |||
} | |||
if (!get_func_pointers(&func_pointers, class_value)) { | |||
return 0; | |||
} | |||
for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) { | |||
CRYPTO_EX_DATA_FUNCS *func_pointer = | |||
sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i); | |||
void *ptr = CRYPTO_get_ex_data(from, i); | |||
if (func_pointer->dup_func) { | |||
func_pointer->dup_func(to, from, &ptr, i, func_pointer->argl, | |||
func_pointer->argp); | |||
} | |||
CRYPTO_set_ex_data(to, i, ptr); | |||
} | |||
sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers); | |||
return 1; | |||
} | |||
void CRYPTO_free_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) { | |||
CRYPTO_once(&global_impl_once, global_impl_init); | |||
global_impl->free_ex_data(class_value, obj, ad); | |||
} | |||
STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; | |||
size_t i; | |||
const CRYPTO_EX_DATA_IMPL *CRYPTO_get_ex_data_implementation(void) { | |||
CRYPTO_once(&global_impl_once, global_impl_init); | |||
return global_impl; | |||
} | |||
if (!get_func_pointers(&func_pointers, class_value)) { | |||
return; | |||
} | |||
for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) { | |||
CRYPTO_EX_DATA_FUNCS *func_pointer = | |||
sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i); | |||
if (func_pointer->free_func) { | |||
void *ptr = CRYPTO_get_ex_data(ad, i); | |||
func_pointer->free_func(obj, ptr, ad, i, func_pointer->argl, | |||
func_pointer->argp); | |||
} | |||
} | |||
sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers); | |||
int CRYPTO_set_ex_data_implementation(const CRYPTO_EX_DATA_IMPL *impl) { | |||
global_user_set_impl = impl; | |||
CRYPTO_once(&global_impl_once, global_impl_init); | |||
return (global_impl == impl); | |||
if (ad->sk) { | |||
sk_void_free(ad->sk); | |||
ad->sk = NULL; | |||
} | |||
} | |||
void CRYPTO_cleanup_all_ex_data(void) { | |||
CRYPTO_once(&global_impl_once, global_impl_init); | |||
global_impl->cleanup(); | |||
CRYPTO_once(&global_classes_once, global_classes_init); | |||
if (global_classes != NULL) { | |||
lh_EX_CLASS_ITEM_doall(global_classes, class_free); | |||
lh_EX_CLASS_ITEM_free(global_classes); | |||
} | |||
global_classes = NULL; | |||
} |
@@ -1,389 +0,0 @@ | |||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | |||
* All rights reserved. | |||
* | |||
* This package is an SSL implementation written | |||
* by Eric Young (eay@cryptsoft.com). | |||
* The implementation was written so as to conform with Netscapes SSL. | |||
* | |||
* This library is free for commercial and non-commercial use as long as | |||
* the following conditions are aheared to. The following conditions | |||
* apply to all code found in this distribution, be it the RC4, RSA, | |||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation | |||
* included with this distribution is covered by the same copyright terms | |||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). | |||
* | |||
* Copyright remains Eric Young's, and as such any Copyright notices in | |||
* the code are not to be removed. | |||
* If this package is used in a product, Eric Young should be given attribution | |||
* as the author of the parts of the library used. | |||
* This can be in the form of a textual message at program startup or | |||
* in documentation (online or textual) provided with the package. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 3. All advertising materials mentioning features or use of this software | |||
* must display the following acknowledgement: | |||
* "This product includes cryptographic software written by | |||
* Eric Young (eay@cryptsoft.com)" | |||
* The word 'cryptographic' can be left out if the rouines from the library | |||
* being used are not cryptographic related :-). | |||
* 4. If you include any Windows specific code (or a derivative thereof) from | |||
* the apps directory (application code) you must include an acknowledgement: | |||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND | |||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* | |||
* The licence and distribution terms for any publically available version or | |||
* derivative of this code cannot be changed. i.e. this code cannot simply be | |||
* copied and put under another distribution licence | |||
* [including the GNU Public Licence.] | |||
*/ | |||
/* ==================================================================== | |||
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. All advertising materials mentioning features or use of this | |||
* software must display the following acknowledgment: | |||
* "This product includes software developed by the OpenSSL Project | |||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | |||
* | |||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |||
* endorse or promote products derived from this software without | |||
* prior written permission. For written permission, please contact | |||
* openssl-core@openssl.org. | |||
* | |||
* 5. Products derived from this software may not be called "OpenSSL" | |||
* nor may "OpenSSL" appear in their names without prior written | |||
* permission of the OpenSSL Project. | |||
* | |||
* 6. Redistributions of any form whatsoever must retain the following | |||
* acknowledgment: | |||
* "This product includes software developed by the OpenSSL Project | |||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)" | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |||
* OF THE POSSIBILITY OF SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This product includes cryptographic software written by Eric Young | |||
* (eay@cryptsoft.com). This product includes software written by Tim | |||
* Hudson (tjh@cryptsoft.com). */ | |||
#include <openssl/ex_data.h> | |||
#include <assert.h> | |||
#include <openssl/err.h> | |||
#include <openssl/lhash.h> | |||
#include <openssl/mem.h> | |||
#include <openssl/stack.h> | |||
#include <openssl/thread.h> | |||
#include "crypto_error.h" | |||
#include "internal.h" | |||
typedef struct crypto_ex_data_func_st { | |||
long argl; /* Arbitary long */ | |||
void *argp; /* Arbitary void pointer */ | |||
CRYPTO_EX_new *new_func; | |||
CRYPTO_EX_free *free_func; | |||
CRYPTO_EX_dup *dup_func; | |||
} CRYPTO_EX_DATA_FUNCS; | |||
typedef struct st_ex_class_item { | |||
STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth; | |||
int class_value; | |||
} EX_CLASS_ITEM; | |||
static CRYPTO_once_t global_classes_once = CRYPTO_ONCE_INIT; | |||
static struct CRYPTO_STATIC_MUTEX global_classes_lock = | |||
CRYPTO_STATIC_MUTEX_INIT; | |||
static LHASH_OF(EX_CLASS_ITEM) *global_classes = NULL; | |||
static struct CRYPTO_STATIC_MUTEX global_next_class_lock = | |||
CRYPTO_STATIC_MUTEX_INIT; | |||
static int global_next_class = 100; | |||
static int new_class(void) { | |||
CRYPTO_STATIC_MUTEX_lock_write(&global_next_class_lock); | |||
const int ret = global_next_class++; | |||
CRYPTO_STATIC_MUTEX_unlock(&global_next_class_lock); | |||
return ret; | |||
} | |||
/* class_hash is a hash function used by an LHASH of |EX_CLASS_ITEM| | |||
* structures. */ | |||
static uint32_t class_hash(const EX_CLASS_ITEM *a) { | |||
return a->class_value; | |||
} | |||
/* class_cmp is a comparison function for an LHASH of |EX_CLASS_ITEM| | |||
* structures. */ | |||
static int class_cmp(const EX_CLASS_ITEM *a, const EX_CLASS_ITEM *b) { | |||
return a->class_value - b->class_value; | |||
} | |||
/* data_funcs_free is a callback function from |sk_pop_free| that frees a | |||
* |CRYPTO_EX_DATA_FUNCS|. */ | |||
static void data_funcs_free(CRYPTO_EX_DATA_FUNCS *funcs) { | |||
OPENSSL_free(funcs); | |||
} | |||
/* class_free is a callback function from lh_doall to free the EX_CLASS_ITEM | |||
* structures. */ | |||
static void class_free(EX_CLASS_ITEM *item) { | |||
sk_CRYPTO_EX_DATA_FUNCS_pop_free(item->meth, data_funcs_free); | |||
OPENSSL_free(item); | |||
} | |||
static void global_classes_init(void) { | |||
global_classes = lh_EX_CLASS_ITEM_new(class_hash, class_cmp); | |||
} | |||
static void cleanup(void) { | |||
CRYPTO_once(&global_classes_once, global_classes_init); | |||
if (global_classes != NULL) { | |||
lh_EX_CLASS_ITEM_doall(global_classes, class_free); | |||
lh_EX_CLASS_ITEM_free(global_classes); | |||
} | |||
global_classes = NULL; | |||
} | |||
static EX_CLASS_ITEM *get_class(int class_value) { | |||
EX_CLASS_ITEM template, *class_item; | |||
int ok = 0; | |||
CRYPTO_once(&global_classes_once, global_classes_init); | |||
if (global_classes == NULL) { | |||
return NULL; | |||
} | |||
CRYPTO_STATIC_MUTEX_lock_write(&global_classes_lock); | |||
template.class_value = class_value; | |||
class_item = lh_EX_CLASS_ITEM_retrieve(global_classes, &template); | |||
if (class_item != NULL) { | |||
ok = 1; | |||
} else { | |||
class_item = OPENSSL_malloc(sizeof(EX_CLASS_ITEM)); | |||
if (class_item) { | |||
class_item->class_value = class_value; | |||
class_item->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null(); | |||
if (class_item->meth != NULL) { | |||
EX_CLASS_ITEM *old_data; | |||
ok = lh_EX_CLASS_ITEM_insert(global_classes, &old_data, class_item); | |||
assert(old_data == NULL); | |||
} | |||
} | |||
} | |||
CRYPTO_STATIC_MUTEX_unlock(&global_classes_lock); | |||
if (!ok) { | |||
if (class_item) { | |||
if (class_item->meth) { | |||
sk_CRYPTO_EX_DATA_FUNCS_free(class_item->meth); | |||
} | |||
OPENSSL_free(class_item); | |||
class_item = NULL; | |||
} | |||
OPENSSL_PUT_ERROR(CRYPTO, get_class, ERR_R_MALLOC_FAILURE); | |||
} | |||
return class_item; | |||
} | |||
static int get_new_index(int class_value, long argl, void *argp, | |||
CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, | |||
CRYPTO_EX_free *free_func) { | |||
EX_CLASS_ITEM *const item = get_class(class_value); | |||
CRYPTO_EX_DATA_FUNCS *funcs; | |||
int ret = -1; | |||
if (!item) { | |||
return -1; | |||
} | |||
funcs = OPENSSL_malloc(sizeof(CRYPTO_EX_DATA_FUNCS)); | |||
if (funcs == NULL) { | |||
OPENSSL_PUT_ERROR(CRYPTO, get_new_index, ERR_R_MALLOC_FAILURE); | |||
return -1; | |||
} | |||
funcs->argl = argl; | |||
funcs->argp = argp; | |||
funcs->new_func = new_func; | |||
funcs->dup_func = dup_func; | |||
funcs->free_func = free_func; | |||
CRYPTO_STATIC_MUTEX_lock_write(&global_classes_lock); | |||
if (!sk_CRYPTO_EX_DATA_FUNCS_push(item->meth, funcs)) { | |||
OPENSSL_PUT_ERROR(CRYPTO, get_new_index, ERR_R_MALLOC_FAILURE); | |||
OPENSSL_free(funcs); | |||
goto err; | |||
} | |||
ret = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth) - 1; | |||
err: | |||
CRYPTO_STATIC_MUTEX_unlock(&global_classes_lock); | |||
return ret; | |||
} | |||
/* get_func_pointers takes a copy of the CRYPTO_EX_DATA_FUNCS pointers, if any, | |||
* for the given class. If there are some pointers, it sets |*out| to point to | |||
* a fresh stack of them. Otherwise it sets |*out| to NULL. It returns one on | |||
* success or zero on error. */ | |||
static int get_func_pointers(STACK_OF(CRYPTO_EX_DATA_FUNCS) **out, | |||
int class_value) { | |||
EX_CLASS_ITEM *const item = get_class(class_value); | |||
size_t n; | |||
if (!item) { | |||
return 0; | |||
} | |||
*out = NULL; | |||
/* CRYPTO_EX_DATA_FUNCS structures are static once set, so we can take a | |||
* shallow copy of the list under lock and then use the structures without | |||
* the lock held. */ | |||
CRYPTO_STATIC_MUTEX_lock_read(&global_classes_lock); | |||
n = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth); | |||
if (n > 0) { | |||
*out = sk_CRYPTO_EX_DATA_FUNCS_dup(item->meth); | |||
} | |||
CRYPTO_STATIC_MUTEX_unlock(&global_classes_lock); | |||
if (n > 0 && *out == NULL) { | |||
OPENSSL_PUT_ERROR(CRYPTO, get_func_pointers, ERR_R_MALLOC_FAILURE); | |||
return 0; | |||
} | |||
return 1; | |||
} | |||
static int new_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) { | |||
STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; | |||
size_t i; | |||
ad->sk = NULL; | |||
if (!get_func_pointers(&func_pointers, class_value)) { | |||
return 0; | |||
} | |||
for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) { | |||
CRYPTO_EX_DATA_FUNCS *func_pointer = | |||
sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i); | |||
if (func_pointer->new_func) { | |||
func_pointer->new_func(obj, NULL, ad, i, func_pointer->argl, | |||
func_pointer->argp); | |||
} | |||
} | |||
sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers); | |||
return 1; | |||
} | |||
static int dup_ex_data(int class_value, CRYPTO_EX_DATA *to, | |||
const CRYPTO_EX_DATA *from) { | |||
STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; | |||
size_t i; | |||
if (!from->sk) { | |||
/* In this case, |from| is blank, which is also the initial state of |to|, | |||
* so there's nothing to do. */ | |||
return 1; | |||
} | |||
if (!get_func_pointers(&func_pointers, class_value)) { | |||
return 0; | |||
} | |||
for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) { | |||
CRYPTO_EX_DATA_FUNCS *func_pointer = | |||
sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i); | |||
void *ptr = CRYPTO_get_ex_data(from, i); | |||
if (func_pointer->dup_func) { | |||
func_pointer->dup_func(to, from, &ptr, i, func_pointer->argl, | |||
func_pointer->argp); | |||
} | |||
CRYPTO_set_ex_data(to, i, ptr); | |||
} | |||
sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers); | |||
return 1; | |||
} | |||
static void free_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) { | |||
STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; | |||
size_t i; | |||
if (!get_func_pointers(&func_pointers, class_value)) { | |||
return; | |||
} | |||
for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) { | |||
CRYPTO_EX_DATA_FUNCS *func_pointer = | |||
sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i); | |||
if (func_pointer->free_func) { | |||
void *ptr = CRYPTO_get_ex_data(ad, i); | |||
func_pointer->free_func(obj, ptr, ad, i, func_pointer->argl, | |||
func_pointer->argp); | |||
} | |||
} | |||
sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers); | |||
if (ad->sk) { | |||
sk_void_free(ad->sk); | |||
ad->sk = NULL; | |||
} | |||
} | |||
const CRYPTO_EX_DATA_IMPL ex_data_default_impl = { | |||
new_class, cleanup, get_new_index, new_ex_data, dup_ex_data, free_ex_data}; |
@@ -166,21 +166,6 @@ extern "C" { | |||
#define OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS | |||
#endif | |||
/* st_CRYPTO_EX_DATA_IMPL contains an ex_data implementation. See the comments | |||
* in ex_data.h for details of the behaviour of each of the functions. */ | |||
struct st_CRYPTO_EX_DATA_IMPL { | |||
int (*new_class)(void); | |||
void (*cleanup)(void); | |||
int (*get_new_index)(int class_value, long argl, void *argp, | |||
CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, | |||
CRYPTO_EX_free *free_func); | |||
int (*new_ex_data)(int class_value, void *obj, CRYPTO_EX_DATA *ad); | |||
int (*dup_ex_data)(int class_value, CRYPTO_EX_DATA *to, | |||
const CRYPTO_EX_DATA *from); | |||
void (*free_ex_data)(int class_value, void *obj, CRYPTO_EX_DATA *ad); | |||
}; | |||
#if defined(_MSC_VER) | |||
#define OPENSSL_U64(x) x##UI64 | |||
@@ -50,9 +50,9 @@ OPENSSL_EXPORT const char *SSLeay(void); | |||
} /* extern C */ | |||
#endif | |||
#define CRYPTO_F_CRYPTO_set_ex_data 100 | |||
#define CRYPTO_F_get_class 101 | |||
#define CRYPTO_F_get_func_pointers 102 | |||
#define CRYPTO_F_get_new_index 103 | |||
#define CRYPTO_F_CRYPTO_get_ex_new_index 100 | |||
#define CRYPTO_F_CRYPTO_set_ex_data 101 | |||
#define CRYPTO_F_get_class 102 | |||
#define CRYPTO_F_get_func_pointers 103 | |||
#endif /* OPENSSL_HEADER_CRYPTO_H */ |
@@ -262,23 +262,6 @@ OPENSSL_EXPORT void CRYPTO_free_ex_data(int class_value, void *obj, | |||
CRYPTO_EX_DATA *ad); | |||
/* Handling different ex_data implementations. */ | |||
/* CRYPTO_EX_DATA_IMPL is the opaque type of an implementation of ex_data. */ | |||
typedef struct st_CRYPTO_EX_DATA_IMPL CRYPTO_EX_DATA_IMPL; | |||
/* CRYPTO_get_ex_data_implementation returns the current implementation of | |||
* ex_data. */ | |||
OPENSSL_EXPORT const CRYPTO_EX_DATA_IMPL *CRYPTO_get_ex_data_implementation( | |||
void); | |||
/* CRYPTO_set_ex_data_implementation sets the implementation of ex_data to use, | |||
* unless ex_data has already been used and the default implementation | |||
* installed. It returns one on success and zero otherwise. */ | |||
OPENSSL_EXPORT int CRYPTO_set_ex_data_implementation( | |||
const CRYPTO_EX_DATA_IMPL *impl); | |||
/* Private functions. */ | |||
/* CRYPTO_cleanup_all_ex_data cleans up all ex_data state. It assumes that no | |||