From 9f33fc63c6219dd43db438d2ffaca480f1b4bb5d Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Wed, 15 Apr 2015 17:29:53 -0400 Subject: [PATCH] Remove hash table lookups from ex_data. 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 --- crypto/dh/dh.c | 16 ++-- crypto/dsa/dsa.c | 16 ++-- crypto/ec/ec_key.c | 20 +++-- crypto/ex_data.c | 155 +++++++-------------------------- crypto/internal.h | 70 +++++++-------- crypto/rsa/rsa.c | 16 ++-- crypto/x509/x509_vfy.c | 17 ++-- crypto/x509/x_x509.c | 15 +++- include/openssl/ex_data.h | 5 +- include/openssl/lhash.h | 1 - include/openssl/lhash_macros.h | 40 --------- ssl/ssl_lib.c | 27 ++++-- ssl/ssl_sess.c | 14 ++- 13 files changed, 161 insertions(+), 251 deletions(-) diff --git a/crypto/dh/dh.c b/crypto/dh/dh.c index 86804bf8..77ebb1d1 100644 --- a/crypto/dh/dh.c +++ b/crypto/dh/dh.c @@ -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) { diff --git a/crypto/dsa/dsa.c b/crypto/dsa/dsa.c index c5809562..78e41549 100644 --- a/crypto/dsa/dsa.c +++ b/crypto/dsa/dsa.c @@ -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) { diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index a11a4398..0f4e666b 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -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) { diff --git a/crypto/ex_data.c b/crypto/ex_data.c index 8f54a901..8f199fd3 100644 --- a/crypto/ex_data.c +++ b/crypto/ex_data.c @@ -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) {} diff --git a/crypto/internal.h b/crypto/internal.h index faceefca..9cb8573c 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -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) diff --git a/crypto/rsa/rsa.c b/crypto/rsa/rsa.c index 48be5953..650249c7 100644 --- a/crypto/rsa/rsa.c +++ b/crypto/rsa/rsa.c @@ -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) { diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index dae33762..a0cd9fc2 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -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)); } diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c index 035b2f4f..234494d0 100644 --- a/crypto/x509/x_x509.c +++ b/crypto/x509/x_x509.c @@ -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) diff --git a/include/openssl/ex_data.h b/include/openssl/ex_data.h index fa9de398..2303eb42 100644 --- a/include/openssl/ex_data.h +++ b/include/openssl/ex_data.h @@ -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 { diff --git a/include/openssl/lhash.h b/include/openssl/lhash.h index 02e51ca1..d2ee982e 100644 --- a/include/openssl/lhash.h +++ b/include/openssl/lhash.h @@ -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 diff --git a/include/openssl/lhash_macros.h b/include/openssl/lhash_macros.h index 018856ab..1d981073 100644 --- a/include/openssl/lhash_macros.h +++ b/include/openssl/lhash_macros.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( \ diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 257ffbc6..97a94a2e 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -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) { diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index de210f5a..4db1f035 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -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);