Instead, each module defines a static CRYPTO_EX_DATA_CLASS to hold the values. This makes CRYPTO_cleanup_all_ex_data a no-op as spreading the CRYPTO_EX_DATA_CLASSes across modules (and across crypto and ssl) makes cleanup slightly trickier. We can make it do something if needbe, but it's probably not worth the trouble. Change-Id: Ib6f6fd39a51d8ba88649f0fa29c66db540610c76 Reviewed-on: https://boringssl-review.googlesource.com/4375 Reviewed-by: Adam Langley <agl@google.com>kris/onging/CECPQ3_patch15
@@ -71,6 +71,8 @@ | |||
extern const DH_METHOD DH_default_method; | |||
static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; | |||
DH *DH_new(void) { return DH_new_method(NULL); } | |||
DH *DH_new_method(const ENGINE *engine) { | |||
@@ -94,13 +96,13 @@ DH *DH_new_method(const ENGINE *engine) { | |||
CRYPTO_MUTEX_init(&dh->method_mont_p_lock); | |||
dh->references = 1; | |||
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data)) { | |||
if (!CRYPTO_new_ex_data(&g_ex_data_class, dh, &dh->ex_data)) { | |||
OPENSSL_free(dh); | |||
return NULL; | |||
} | |||
if (dh->meth->init && !dh->meth->init(dh)) { | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data); | |||
CRYPTO_free_ex_data(&g_ex_data_class, dh, &dh->ex_data); | |||
METHOD_unref(dh->meth); | |||
OPENSSL_free(dh); | |||
return NULL; | |||
@@ -123,7 +125,7 @@ void DH_free(DH *dh) { | |||
} | |||
METHOD_unref(dh->meth); | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data); | |||
CRYPTO_free_ex_data(&g_ex_data_class, dh, &dh->ex_data); | |||
if (dh->method_mont_p) BN_MONT_CTX_free(dh->method_mont_p); | |||
if (dh->p != NULL) BN_clear_free(dh->p); | |||
@@ -234,8 +236,12 @@ DH *DHparams_dup(const DH *dh) { | |||
int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, | |||
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { | |||
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DH, argl, argp, new_func, | |||
dup_func, free_func); | |||
int index; | |||
if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func, | |||
dup_func, free_func)) { | |||
return -1; | |||
} | |||
return index; | |||
} | |||
int DH_set_ex_data(DH *d, int idx, void *arg) { | |||
@@ -75,6 +75,8 @@ | |||
extern const DSA_METHOD DSA_default_method; | |||
static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; | |||
DSA *DSA_new(void) { return DSA_new_method(NULL); } | |||
DSA *DSA_new_method(const ENGINE *engine) { | |||
@@ -100,14 +102,14 @@ DSA *DSA_new_method(const ENGINE *engine) { | |||
CRYPTO_MUTEX_init(&dsa->method_mont_p_lock); | |||
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data)) { | |||
if (!CRYPTO_new_ex_data(&g_ex_data_class, dsa, &dsa->ex_data)) { | |||
METHOD_unref(dsa->meth); | |||
OPENSSL_free(dsa); | |||
return NULL; | |||
} | |||
if (dsa->meth->init && !dsa->meth->init(dsa)) { | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data); | |||
CRYPTO_free_ex_data(&g_ex_data_class, dsa, &dsa->ex_data); | |||
METHOD_unref(dsa->meth); | |||
OPENSSL_free(dsa); | |||
return NULL; | |||
@@ -130,7 +132,7 @@ void DSA_free(DSA *dsa) { | |||
} | |||
METHOD_unref(dsa->meth); | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data); | |||
CRYPTO_free_ex_data(&g_ex_data_class, dsa, &dsa->ex_data); | |||
if (dsa->p != NULL) { | |||
BN_clear_free(dsa->p); | |||
@@ -321,8 +323,12 @@ int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx, BIGNUM **out_kinv, | |||
int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, | |||
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { | |||
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, argl, argp, new_func, | |||
dup_func, free_func); | |||
int index; | |||
if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func, | |||
dup_func, free_func)) { | |||
return -1; | |||
} | |||
return index; | |||
} | |||
int DSA_set_ex_data(DSA *d, int idx, void *arg) { | |||
@@ -80,6 +80,8 @@ | |||
#include "../internal.h" | |||
static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; | |||
EC_KEY *EC_KEY_new(void) { return EC_KEY_new_method(NULL); } | |||
EC_KEY *EC_KEY_new_method(const ENGINE *engine) { | |||
@@ -102,7 +104,7 @@ EC_KEY *EC_KEY_new_method(const ENGINE *engine) { | |||
ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; | |||
ret->references = 1; | |||
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data)) { | |||
if (!CRYPTO_new_ex_data(&g_ex_data_class, ret, &ret->ex_data)) { | |||
goto err1; | |||
} | |||
@@ -113,7 +115,7 @@ EC_KEY *EC_KEY_new_method(const ENGINE *engine) { | |||
return ret; | |||
err2: | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data); | |||
CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data); | |||
err1: | |||
if (ret->ecdsa_meth) { | |||
METHOD_unref(ret->ecdsa_meth); | |||
@@ -161,7 +163,7 @@ void EC_KEY_free(EC_KEY *r) { | |||
BN_clear_free(r->priv_key); | |||
} | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data); | |||
CRYPTO_free_ex_data(&g_ex_data_class, r, &r->ex_data); | |||
OPENSSL_cleanse((void *)r, sizeof(EC_KEY)); | |||
OPENSSL_free(r); | |||
@@ -208,8 +210,8 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) { | |||
} | |||
} | |||
/* copy method/extra data */ | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, dest, &dest->ex_data); | |||
if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, &dest->ex_data, | |||
CRYPTO_free_ex_data(&g_ex_data_class, dest, &dest->ex_data); | |||
if (!CRYPTO_dup_ex_data(&g_ex_data_class, &dest->ex_data, | |||
&src->ex_data)) { | |||
return NULL; | |||
} | |||
@@ -505,8 +507,12 @@ err: | |||
int EC_KEY_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, | |||
CRYPTO_EX_dup *dup_func, | |||
CRYPTO_EX_free *free_func) { | |||
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_EC_KEY, argl, argp, new_func, | |||
dup_func, free_func); | |||
int index; | |||
if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func, | |||
dup_func, free_func)) { | |||
return -1; | |||
} | |||
return index; | |||
} | |||
int EC_KEY_set_ex_data(EC_KEY *d, int idx, void *arg) { | |||
@@ -121,112 +121,25 @@ | |||
#include "internal.h" | |||
typedef struct crypto_ex_data_func_st { | |||
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; | |||
/* 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, | |||
int CRYPTO_get_ex_new_index(CRYPTO_EX_DATA_CLASS *ex_data_class, int *out_index, | |||
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; | |||
} | |||
int ret = 0; | |||
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; | |||
return 0; | |||
} | |||
funcs->argl = argl; | |||
@@ -235,18 +148,24 @@ int CRYPTO_get_ex_new_index(int class_value, long argl, void *argp, | |||
funcs->dup_func = dup_func; | |||
funcs->free_func = free_func; | |||
CRYPTO_STATIC_MUTEX_lock_write(&global_classes_lock); | |||
CRYPTO_STATIC_MUTEX_lock_write(&ex_data_class->lock); | |||
if (!sk_CRYPTO_EX_DATA_FUNCS_push(item->meth, funcs)) { | |||
if (ex_data_class->meth == NULL) { | |||
ex_data_class->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null(); | |||
} | |||
if (ex_data_class->meth == NULL || | |||
!sk_CRYPTO_EX_DATA_FUNCS_push(ex_data_class->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; | |||
*out_index = sk_CRYPTO_EX_DATA_FUNCS_num(ex_data_class->meth) - 1; | |||
ret = 1; | |||
err: | |||
CRYPTO_STATIC_MUTEX_unlock(&global_classes_lock); | |||
CRYPTO_STATIC_MUTEX_unlock(&ex_data_class->lock); | |||
return ret; | |||
} | |||
@@ -287,25 +206,20 @@ void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx) { | |||
* 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); | |||
CRYPTO_EX_DATA_CLASS *ex_data_class) { | |||
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); | |||
CRYPTO_STATIC_MUTEX_lock_read(&ex_data_class->lock); | |||
n = sk_CRYPTO_EX_DATA_FUNCS_num(ex_data_class->meth); | |||
if (n > 0) { | |||
*out = sk_CRYPTO_EX_DATA_FUNCS_dup(item->meth); | |||
*out = sk_CRYPTO_EX_DATA_FUNCS_dup(ex_data_class->meth); | |||
} | |||
CRYPTO_STATIC_MUTEX_unlock(&global_classes_lock); | |||
CRYPTO_STATIC_MUTEX_unlock(&ex_data_class->lock); | |||
if (n > 0 && *out == NULL) { | |||
OPENSSL_PUT_ERROR(CRYPTO, get_func_pointers, ERR_R_MALLOC_FAILURE); | |||
@@ -315,13 +229,14 @@ static int get_func_pointers(STACK_OF(CRYPTO_EX_DATA_FUNCS) **out, | |||
return 1; | |||
} | |||
int CRYPTO_new_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) { | |||
int CRYPTO_new_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, 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)) { | |||
if (!get_func_pointers(&func_pointers, ex_data_class)) { | |||
return 0; | |||
} | |||
@@ -339,7 +254,7 @@ int CRYPTO_new_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) { | |||
return 1; | |||
} | |||
int CRYPTO_dup_ex_data(int class_value, CRYPTO_EX_DATA *to, | |||
int CRYPTO_dup_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, CRYPTO_EX_DATA *to, | |||
const CRYPTO_EX_DATA *from) { | |||
STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; | |||
size_t i; | |||
@@ -350,7 +265,7 @@ int CRYPTO_dup_ex_data(int class_value, CRYPTO_EX_DATA *to, | |||
return 1; | |||
} | |||
if (!get_func_pointers(&func_pointers, class_value)) { | |||
if (!get_func_pointers(&func_pointers, ex_data_class)) { | |||
return 0; | |||
} | |||
@@ -370,11 +285,12 @@ int CRYPTO_dup_ex_data(int class_value, CRYPTO_EX_DATA *to, | |||
return 1; | |||
} | |||
void CRYPTO_free_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) { | |||
void CRYPTO_free_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, 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)) { | |||
if (!get_func_pointers(&func_pointers, ex_data_class)) { | |||
return; | |||
} | |||
@@ -396,13 +312,4 @@ void CRYPTO_free_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) { | |||
} | |||
} | |||
void CRYPTO_cleanup_all_ex_data(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; | |||
} | |||
void CRYPTO_cleanup_all_ex_data(void) {} |
@@ -453,64 +453,54 @@ OPENSSL_EXPORT int CRYPTO_set_thread_local( | |||
/* ex_data */ | |||
/* CRYPTO_get_ex_new_index allocates a new index for ex_data linked with | |||
* objects of the given |class|. This should not be called directly, rather | |||
* each class of object should provide a wrapper function that sets | |||
* |class_value| correctly. | |||
* | |||
* The |class_value| argument should be one of |CRYPTO_EX_INDEX_*|. | |||
* | |||
* TODO(fork): replace the class_value with a pointer to EX_CLASS_ITEM. Saves | |||
* having that hash table and some of the lock-bouncing. Maybe have every | |||
* module have a private global EX_CLASS_ITEM somewhere and any direct callers | |||
* of CRYPTO_{get,set}_ex_data{,_index} would have to always call the | |||
* wrappers. */ | |||
OPENSSL_EXPORT int CRYPTO_get_ex_new_index(int class_value, long argl, | |||
typedef struct crypto_ex_data_func_st CRYPTO_EX_DATA_FUNCS; | |||
/* CRYPTO_EX_DATA_CLASS tracks the ex_indices registered for a type which | |||
* supports ex_data. It should defined as a static global within the module | |||
* which defines that type. */ | |||
typedef struct { | |||
struct CRYPTO_STATIC_MUTEX lock; | |||
STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth; | |||
} CRYPTO_EX_DATA_CLASS; | |||
#define CRYPTO_EX_DATA_CLASS_INIT {CRYPTO_STATIC_MUTEX_INIT, NULL} | |||
/* CRYPTO_get_ex_new_index allocates a new index for |ex_data_class| and writes | |||
* it to |*out_index|. Each class of object should provide a wrapper function | |||
* that uses the correct |CRYPTO_EX_DATA_CLASS|. It returns one on success and | |||
* zero otherwise. */ | |||
OPENSSL_EXPORT int CRYPTO_get_ex_new_index(CRYPTO_EX_DATA_CLASS *ex_data_class, | |||
int *out_index, long argl, | |||
void *argp, CRYPTO_EX_new *new_func, | |||
CRYPTO_EX_dup *dup_func, | |||
CRYPTO_EX_free *free_func); | |||
/* CRYPTO_set_ex_data sets an extra data pointer on a given object. This should | |||
* not be called directly, rather each class of object should provide a wrapper | |||
* function. */ | |||
/* CRYPTO_set_ex_data sets an extra data pointer on a given object. Each class | |||
* of object should provide a wrapper function. */ | |||
OPENSSL_EXPORT int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int index, void *val); | |||
/* CRYPTO_set_ex_data return an extra data pointer for a given object, or NULL | |||
* if no such index exists. This should not be called directly, rather each | |||
* class of object should provide a wrapper function. */ | |||
/* CRYPTO_get_ex_data returns an extra data pointer for a given object, or NULL | |||
* if no such index exists. Each class of object should provide a wrapper | |||
* function. */ | |||
OPENSSL_EXPORT void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int index); | |||
/* CRYPTO_EX_INDEX_* are the built-in classes of objects. | |||
* | |||
* TODO(fork): WARNING: these are called "INDEX", but they aren't! */ | |||
enum { | |||
CRYPTO_EX_INDEX_SSL, | |||
CRYPTO_EX_INDEX_SSL_CTX, | |||
CRYPTO_EX_INDEX_SSL_SESSION, | |||
CRYPTO_EX_INDEX_X509_STORE_CTX, | |||
CRYPTO_EX_INDEX_RSA, | |||
CRYPTO_EX_INDEX_DSA, | |||
CRYPTO_EX_INDEX_DH, | |||
CRYPTO_EX_INDEX_X509, | |||
CRYPTO_EX_INDEX_EC_KEY, | |||
}; | |||
/* CRYPTO_new_ex_data initialises a newly allocated |CRYPTO_EX_DATA| which is | |||
* embedded inside of |obj| which is of class |class_value|. Returns one on | |||
* embedded inside of |obj| which is of class |ex_data_class|. Returns one on | |||
* success and zero otherwise. */ | |||
OPENSSL_EXPORT int CRYPTO_new_ex_data(int class_value, void *obj, | |||
CRYPTO_EX_DATA *ad); | |||
OPENSSL_EXPORT int CRYPTO_new_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, | |||
void *obj, CRYPTO_EX_DATA *ad); | |||
/* CRYPTO_dup_ex_data duplicates |from| into a freshly allocated | |||
* |CRYPTO_EX_DATA|, |to|. Both of which are inside objects of the given | |||
* class. It returns one on success and zero otherwise. */ | |||
OPENSSL_EXPORT int CRYPTO_dup_ex_data(int class_value, CRYPTO_EX_DATA *to, | |||
OPENSSL_EXPORT int CRYPTO_dup_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, | |||
CRYPTO_EX_DATA *to, | |||
const CRYPTO_EX_DATA *from); | |||
/* CRYPTO_free_ex_data frees |ad|, which is embedded inside |obj|, which is an | |||
* object of the given class. */ | |||
OPENSSL_EXPORT void CRYPTO_free_ex_data(int class_value, void *obj, | |||
CRYPTO_EX_DATA *ad); | |||
OPENSSL_EXPORT void CRYPTO_free_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, | |||
void *obj, CRYPTO_EX_DATA *ad); | |||
#if defined(__cplusplus) | |||
@@ -72,6 +72,8 @@ | |||
extern const RSA_METHOD RSA_default_method; | |||
static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; | |||
RSA *RSA_new(void) { return RSA_new_method(NULL); } | |||
RSA *RSA_new_method(const ENGINE *engine) { | |||
@@ -96,14 +98,14 @@ RSA *RSA_new_method(const ENGINE *engine) { | |||
rsa->flags = rsa->meth->flags; | |||
CRYPTO_MUTEX_init(&rsa->lock); | |||
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, rsa, &rsa->ex_data)) { | |||
if (!CRYPTO_new_ex_data(&g_ex_data_class, rsa, &rsa->ex_data)) { | |||
METHOD_unref(rsa->meth); | |||
OPENSSL_free(rsa); | |||
return NULL; | |||
} | |||
if (rsa->meth->init && !rsa->meth->init(rsa)) { | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, rsa, &rsa->ex_data); | |||
CRYPTO_free_ex_data(&g_ex_data_class, rsa, &rsa->ex_data); | |||
METHOD_unref(rsa->meth); | |||
OPENSSL_free(rsa); | |||
return NULL; | |||
@@ -128,7 +130,7 @@ void RSA_free(RSA *rsa) { | |||
} | |||
METHOD_unref(rsa->meth); | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, rsa, &rsa->ex_data); | |||
CRYPTO_free_ex_data(&g_ex_data_class, rsa, &rsa->ex_data); | |||
if (rsa->n != NULL) { | |||
BN_clear_free(rsa->n); | |||
@@ -285,8 +287,12 @@ int RSA_supports_digest(const RSA *rsa, const EVP_MD *md) { | |||
int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, | |||
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { | |||
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, argl, argp, new_func, | |||
dup_func, free_func); | |||
int index; | |||
if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func, | |||
dup_func, free_func)) { | |||
return -1; | |||
} | |||
return index; | |||
} | |||
int RSA_set_ex_data(RSA *d, int idx, void *arg) { | |||
@@ -72,6 +72,8 @@ | |||
#include "../internal.h" | |||
static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; | |||
/* CRL score values */ | |||
/* No unhandled critical extensions */ | |||
@@ -2054,8 +2056,13 @@ int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_fu | |||
{ | |||
/* This function is (usually) called only once, by | |||
* SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). */ | |||
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, argl, argp, | |||
new_func, dup_func, free_func); | |||
int index; | |||
if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, | |||
new_func, dup_func, free_func)) | |||
{ | |||
return -1; | |||
} | |||
return index; | |||
} | |||
int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data) | |||
@@ -2225,7 +2232,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, | |||
ctx->cert=x509; | |||
ctx->untrusted=chain; | |||
if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, | |||
if(!CRYPTO_new_ex_data(&g_ex_data_class, ctx, | |||
&ctx->ex_data)) | |||
{ | |||
goto err; | |||
@@ -2316,7 +2323,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, | |||
err: | |||
if (ex_data_allocated) | |||
{ | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &ctx->ex_data); | |||
CRYPTO_free_ex_data(&g_ex_data_class, ctx, &ctx->ex_data); | |||
} | |||
if (ctx->param != NULL) | |||
{ | |||
@@ -2357,7 +2364,7 @@ void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) | |||
sk_X509_pop_free(ctx->chain,X509_free); | |||
ctx->chain=NULL; | |||
} | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data)); | |||
CRYPTO_free_ex_data(&g_ex_data_class, ctx, &(ctx->ex_data)); | |||
memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA)); | |||
} | |||
@@ -68,6 +68,8 @@ | |||
#include "../internal.h" | |||
static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; | |||
ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = { | |||
ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0), | |||
ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER), | |||
@@ -102,7 +104,7 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, | |||
ret->akid = NULL; | |||
ret->aux = NULL; | |||
ret->crldp = NULL; | |||
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data); | |||
CRYPTO_new_ex_data(&g_ex_data_class, ret, &ret->ex_data); | |||
break; | |||
case ASN1_OP_D2I_POST: | |||
@@ -111,7 +113,7 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, | |||
break; | |||
case ASN1_OP_FREE_POST: | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data); | |||
CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data); | |||
X509_CERT_AUX_free(ret->aux); | |||
ASN1_OCTET_STRING_free(ret->skid); | |||
AUTHORITY_KEYID_free(ret->akid); | |||
@@ -147,8 +149,13 @@ X509 *X509_up_ref(X509 *x) | |||
int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, | |||
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) | |||
{ | |||
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509, argl, argp, | |||
new_func, dup_func, free_func); | |||
int index; | |||
if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, | |||
new_func, dup_func, free_func)) | |||
{ | |||
return -1; | |||
} | |||
return index; | |||
} | |||
int X509_set_ex_data(X509 *r, int idx, void *arg) | |||
@@ -197,10 +197,9 @@ typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from, | |||
void **from_d, int index, long argl, void *argp); | |||
/* Private functions. */ | |||
/* Deprecated functions. */ | |||
/* CRYPTO_cleanup_all_ex_data cleans up all ex_data state. It assumes that no | |||
* other threads are executing code that might call ex_data functions. */ | |||
/* CRYPTO_cleanup_all_ex_data does nothing. */ | |||
OPENSSL_EXPORT void CRYPTO_cleanup_all_ex_data(void); | |||
struct crypto_ex_data_st { | |||
@@ -96,7 +96,6 @@ extern "C" { | |||
* | |||
* LHASH_OF:ASN1_OBJECT | |||
* LHASH_OF:CONF_VALUE | |||
* LHASH_OF:EX_CLASS_ITEM | |||
* LHASH_OF:SSL_SESSION */ | |||
#define IN_LHASH_H | |||
@@ -92,46 +92,6 @@ | |||
void (*)(CONF_VALUE *, void *), func), \ | |||
arg); | |||
/* EX_CLASS_ITEM */ | |||
#define lh_EX_CLASS_ITEM_new(hash, comp) \ | |||
((LHASH_OF(EX_CLASS_ITEM) *)lh_new( \ | |||
CHECKED_CAST(lhash_hash_func, uint32_t (*)(const EX_CLASS_ITEM *), \ | |||
hash), \ | |||
CHECKED_CAST(lhash_cmp_func, \ | |||
int (*)(const EX_CLASS_ITEM *a, const EX_CLASS_ITEM *b), \ | |||
comp))) | |||
#define lh_EX_CLASS_ITEM_free(lh) \ | |||
lh_free(CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh)); | |||
#define lh_EX_CLASS_ITEM_num_items(lh) \ | |||
lh_num_items(CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh)) | |||
#define lh_EX_CLASS_ITEM_retrieve(lh, data) \ | |||
((EX_CLASS_ITEM *)lh_retrieve( \ | |||
CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh), \ | |||
CHECKED_CAST(void *, EX_CLASS_ITEM *, data))) | |||
#define lh_EX_CLASS_ITEM_insert(lh, old_data, data) \ | |||
lh_insert(CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh), \ | |||
CHECKED_CAST(void **, EX_CLASS_ITEM **, old_data), \ | |||
CHECKED_CAST(void *, EX_CLASS_ITEM *, data)) | |||
#define lh_EX_CLASS_ITEM_delete(lh, data) \ | |||
((EX_CLASS_ITEM *)lh_delete( \ | |||
CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh), \ | |||
CHECKED_CAST(void *, EX_CLASS_ITEM *, data))) | |||
#define lh_EX_CLASS_ITEM_doall(lh, func) \ | |||
lh_doall(CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh), \ | |||
CHECKED_CAST(void (*)(void *), void (*)(EX_CLASS_ITEM *), func)); | |||
#define lh_EX_CLASS_ITEM_doall_arg(lh, func, arg) \ | |||
lh_doall_arg(CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh), \ | |||
CHECKED_CAST(void (*)(void *, void *), \ | |||
void (*)(EX_CLASS_ITEM *, void *), func), \ | |||
arg); | |||
/* SSL_SESSION */ | |||
#define lh_SSL_SESSION_new(hash, comp) \ | |||
((LHASH_OF(SSL_SESSION) *)lh_new( \ | |||
@@ -161,6 +161,9 @@ OPENSSL_COMPILE_ASSERT(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION == | |||
SSL_AD_NO_RENEGOTIATION + SSL_AD_REASON_OFFSET, | |||
ssl_alert_reason_code_mismatch); | |||
static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl = CRYPTO_EX_DATA_CLASS_INIT; | |||
static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl_ctx = CRYPTO_EX_DATA_CLASS_INIT; | |||
int SSL_clear(SSL *s) { | |||
if (s->method == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, SSL_clear, SSL_R_NO_METHOD_SPECIFIED); | |||
@@ -339,7 +342,7 @@ SSL *SSL_new(SSL_CTX *ctx) { | |||
s->rwstate = SSL_NOTHING; | |||
s->rstate = SSL_ST_READ_HEADER; | |||
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); | |||
CRYPTO_new_ex_data(&g_ex_data_class_ssl, s, &s->ex_data); | |||
s->psk_identity_hint = NULL; | |||
if (ctx->psk_identity_hint) { | |||
@@ -542,7 +545,7 @@ void SSL_free(SSL *s) { | |||
X509_VERIFY_PARAM_free(s->param); | |||
} | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); | |||
CRYPTO_free_ex_data(&g_ex_data_class_ssl, s, &s->ex_data); | |||
if (s->bbio != NULL) { | |||
/* If the buffering BIO is in place, pop it off */ | |||
@@ -1833,7 +1836,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) { | |||
goto err; | |||
} | |||
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data); | |||
CRYPTO_new_ex_data(&g_ex_data_class_ssl_ctx, ret, &ret->ex_data); | |||
ret->extra_certs = NULL; | |||
@@ -1905,7 +1908,7 @@ void SSL_CTX_free(SSL_CTX *a) { | |||
SSL_CTX_flush_sessions(a, 0); | |||
} | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data); | |||
CRYPTO_free_ex_data(&g_ex_data_class_ssl_ctx, a, &a->ex_data); | |||
if (a->sessions != NULL) { | |||
lh_SSL_SESSION_free(a->sessions); | |||
@@ -2548,8 +2551,12 @@ long SSL_get_verify_result(const SSL *ssl) { return ssl->verify_result; } | |||
int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, | |||
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { | |||
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, argl, argp, new_func, | |||
dup_func, free_func); | |||
int index; | |||
if (!CRYPTO_get_ex_new_index(&g_ex_data_class_ssl, &index, argl, argp, | |||
new_func, dup_func, free_func)) { | |||
return -1; | |||
} | |||
return index; | |||
} | |||
int SSL_set_ex_data(SSL *s, int idx, void *arg) { | |||
@@ -2563,8 +2570,12 @@ void *SSL_get_ex_data(const SSL *s, int idx) { | |||
int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, | |||
CRYPTO_EX_dup *dup_func, | |||
CRYPTO_EX_free *free_func) { | |||
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, argl, argp, new_func, | |||
dup_func, free_func); | |||
int index; | |||
if (!CRYPTO_get_ex_new_index(&g_ex_data_class_ssl_ctx, &index, argl, argp, | |||
new_func, dup_func, free_func)) { | |||
return -1; | |||
} | |||
return index; | |||
} | |||
int SSL_CTX_set_ex_data(SSL_CTX *s, int idx, void *arg) { | |||
@@ -150,6 +150,8 @@ | |||
* that it needs to asynchronously fetch session information. */ | |||
static const char g_pending_session_magic = 0; | |||
static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; | |||
static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); | |||
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s); | |||
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); | |||
@@ -172,8 +174,12 @@ SSL_SESSION *SSL_get1_session(SSL *ssl) { | |||
int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, | |||
CRYPTO_EX_dup *dup_func, | |||
CRYPTO_EX_free *free_func) { | |||
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp, | |||
new_func, dup_func, free_func); | |||
int index; | |||
if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func, | |||
dup_func, free_func)) { | |||
return -1; | |||
} | |||
return index; | |||
} | |||
int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) { | |||
@@ -198,7 +204,7 @@ SSL_SESSION *SSL_SESSION_new(void) { | |||
ss->references = 1; | |||
ss->timeout = SSL_DEFAULT_SESSION_TIMEOUT; | |||
ss->time = (unsigned long)time(NULL); | |||
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); | |||
CRYPTO_new_ex_data(&g_ex_data_class, ss, &ss->ex_data); | |||
return ss; | |||
} | |||
@@ -622,7 +628,7 @@ void SSL_SESSION_free(SSL_SESSION *ss) { | |||
return; | |||
} | |||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); | |||
CRYPTO_free_ex_data(&g_ex_data_class, ss, &ss->ex_data); | |||
OPENSSL_cleanse(ss->master_key, sizeof ss->master_key); | |||
OPENSSL_cleanse(ss->session_id, sizeof ss->session_id); | |||