diff options
author | Rich Salz <rsalz@akamai.com> | 2015-07-21 16:06:03 +0200 |
---|---|---|
committer | Rich Salz <rsalz@openssl.org> | 2015-12-01 17:48:37 +0100 |
commit | e6390acac925f952cfd06ccdbba0b273b8f71551 (patch) | |
tree | 219e865d2b4e0a2b362429e56829d5caf1b69ced /crypto/ex_data.c | |
parent | Remove BN_init (diff) | |
download | openssl-e6390acac925f952cfd06ccdbba0b273b8f71551.tar.xz openssl-e6390acac925f952cfd06ccdbba0b273b8f71551.zip |
ex_data part 2: doc fixes and CRYPTO_free_ex_index.
Add CRYPTO_free_ex_index (for shared libraries)
Unify and complete the documentation for all "ex_data" API's and objects.
Replace xxx_get_ex_new_index functions with a macro.
Added an exdata test.
Renamed the ex_data internal datatypes.
Reviewed-by: Matt Caswell <matt@openssl.org>
Diffstat (limited to 'crypto/ex_data.c')
-rw-r--r-- | crypto/ex_data.c | 141 |
1 files changed, 95 insertions, 46 deletions
diff --git a/crypto/ex_data.c b/crypto/ex_data.c index 29d8071eef..5bf8e1e5cd 100644 --- a/crypto/ex_data.c +++ b/crypto/ex_data.c @@ -112,48 +112,53 @@ #include <openssl/lhash.h> -typedef struct { + +/* + * Each structure type (sometimes called a class), that supports + * exdata has a stack of callbacks for each instance. + */ +typedef struct ex_callback_st { long argl; /* Arbitary long */ void *argp; /* Arbitary void * */ CRYPTO_EX_new *new_func; CRYPTO_EX_free *free_func; CRYPTO_EX_dup *dup_func; -} CRYPTO_EX_DATA_FUNCS; +} EX_CALLBACK; -DECLARE_STACK_OF(CRYPTO_EX_DATA_FUNCS) +DECLARE_STACK_OF(EX_CALLBACK) /* - * State for each class; could just be a typedef, but this allows future - * changes. + * The state for each class. This could just be a typedef, but + * a structure allows future changes. */ -typedef struct { - STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth; -} EX_CLASS_ITEM; +typedef struct ex_callbacks_st { + STACK_OF(EX_CALLBACK) *meth; +} EX_CALLBACKS; -static EX_CLASS_ITEM ex_data[CRYPTO_EX_INDEX__COUNT]; +static EX_CALLBACKS ex_data[CRYPTO_EX_INDEX__COUNT]; /* - * Return the EX_CLASS_ITEM from the "ex_data" array that corresponds to + * Return the EX_CALLBACKS from the |ex_data| array that corresponds to * a given class. On success, *holds the lock.* */ -static EX_CLASS_ITEM *def_get_class(int class_index) +static EX_CALLBACKS *get_and_lock(int class_index) { - EX_CLASS_ITEM *ip; + EX_CALLBACKS *ip; if (class_index < 0 || class_index >= CRYPTO_EX_INDEX__COUNT) { - CRYPTOerr(CRYPTO_F_DEF_GET_CLASS, ERR_R_MALLOC_FAILURE); + CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_MALLOC_FAILURE); return NULL; } ip = &ex_data[class_index]; CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); if (ip->meth == NULL) { - ip->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null(); + ip->meth = sk_EX_CALLBACK_new_null(); /* We push an initial value on the stack because the SSL * "app_data" routines use ex_data index zero. See RT 3710. */ if (ip->meth == NULL - || !sk_CRYPTO_EX_DATA_FUNCS_push(ip->meth, NULL)) { - CRYPTOerr(CRYPTO_F_DEF_GET_CLASS, ERR_R_MALLOC_FAILURE); + || !sk_EX_CALLBACK_push(ip->meth, NULL)) { + CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_MALLOC_FAILURE); CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); return NULL; } @@ -161,7 +166,7 @@ static EX_CLASS_ITEM *def_get_class(int class_index) return ip; } -static void cleanup_cb(CRYPTO_EX_DATA_FUNCS *funcs) +static void cleanup_cb(EX_CALLBACK *funcs) { OPENSSL_free(funcs); } @@ -177,27 +182,71 @@ void CRYPTO_cleanup_all_ex_data(void) int i; for (i = 0; i < CRYPTO_EX_INDEX__COUNT; ++i) { - EX_CLASS_ITEM *ip = &ex_data[i]; + EX_CALLBACKS *ip = &ex_data[i]; - sk_CRYPTO_EX_DATA_FUNCS_pop_free(ip->meth, cleanup_cb); + sk_EX_CALLBACK_pop_free(ip->meth, cleanup_cb); ip->meth = NULL; } } + +/* + * Unregister a new index by replacing the callbacks with no-ops. + * Any in-use instances are leaked. + */ +static void dummy_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, + long argl, void *argp) +{ +} + +static void dummy_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, + long argl, void *argp) +{ +} + +static int dummy_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, + void *from_d, int idx, + long argl, void *argp) +{ + return 0; +} + +int CRYPTO_free_ex_index(int class_index, int idx) +{ + EX_CALLBACKS *ip = get_and_lock(class_index); + EX_CALLBACK *a; + int toret = 0; + + if (ip == NULL) + return 0; + if (idx < 0 || idx >= sk_EX_CALLBACK_num(ip->meth)) + goto err; + a = sk_EX_CALLBACK_value(ip->meth, idx); + if (a == NULL) + goto err; + a->new_func = dummy_new; + a->dup_func = dummy_dup; + a->free_func = dummy_free; + toret = 1; +err: + CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); + return toret; +} + /* - * Inside an existing class, get/register a new index. + * Register a new index. */ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { int toret = -1; - CRYPTO_EX_DATA_FUNCS *a; - EX_CLASS_ITEM *ip = def_get_class(class_index); + EX_CALLBACK *a; + EX_CALLBACKS *ip = get_and_lock(class_index); - if (!ip) + if (ip == NULL) return -1; - a = (CRYPTO_EX_DATA_FUNCS *)OPENSSL_malloc(sizeof(*a)); + a = (EX_CALLBACK *)OPENSSL_malloc(sizeof(*a)); if (a == NULL) { CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE); goto err; @@ -208,13 +257,13 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, a->dup_func = dup_func; a->free_func = free_func; - if (!sk_CRYPTO_EX_DATA_FUNCS_push(ip->meth, NULL)) { + if (!sk_EX_CALLBACK_push(ip->meth, NULL)) { CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE); OPENSSL_free(a); goto err; } - toret = sk_CRYPTO_EX_DATA_FUNCS_num(ip->meth) - 1; - (void)sk_CRYPTO_EX_DATA_FUNCS_set(ip->meth, toret, a); + toret = sk_EX_CALLBACK_num(ip->meth) - 1; + (void)sk_EX_CALLBACK_set(ip->meth, toret, a); err: CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); @@ -224,7 +273,7 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, /* * Initialise a new CRYPTO_EX_DATA for use in a particular class - including * calling new() callbacks for each index in the class used by this variable - * Thread-safe by copying a class's array of "CRYPTO_EX_DATA_FUNCS" entries + * Thread-safe by copying a class's array of "EX_CALLBACK" entries * in the lock, then using them outside the lock. Note this only applies * to the global "ex_data" state (ie. class definitions), not 'ad' itself. */ @@ -232,16 +281,16 @@ int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) { int mx, i; void *ptr; - CRYPTO_EX_DATA_FUNCS **storage = NULL; - CRYPTO_EX_DATA_FUNCS *stack[10]; - EX_CLASS_ITEM *ip = def_get_class(class_index); + EX_CALLBACK **storage = NULL; + EX_CALLBACK *stack[10]; + EX_CALLBACKS *ip = get_and_lock(class_index); - if (!ip) + if (ip == NULL) return 0; ad->sk = NULL; - mx = sk_CRYPTO_EX_DATA_FUNCS_num(ip->meth); + mx = sk_EX_CALLBACK_num(ip->meth); if (mx > 0) { if (mx < (int)OSSL_NELEM(stack)) storage = stack; @@ -249,7 +298,7 @@ int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) storage = OPENSSL_malloc(sizeof(*storage) * mx); if (storage != NULL) for (i = 0; i < mx; i++) - storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(ip->meth, i); + storage[i] = sk_EX_CALLBACK_value(ip->meth, i); } CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); @@ -278,17 +327,17 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, { int mx, j, i; char *ptr; - CRYPTO_EX_DATA_FUNCS *stack[10]; - CRYPTO_EX_DATA_FUNCS **storage = NULL; - EX_CLASS_ITEM *ip; + EX_CALLBACK *stack[10]; + EX_CALLBACK **storage = NULL; + EX_CALLBACKS *ip; if (from->sk == NULL) /* Nothing to copy over */ return 1; - if ((ip = def_get_class(class_index)) == NULL) + if ((ip = get_and_lock(class_index)) == NULL) return 0; - mx = sk_CRYPTO_EX_DATA_FUNCS_num(ip->meth); + mx = sk_EX_CALLBACK_num(ip->meth); j = sk_void_num(from->sk); if (j < mx) mx = j; @@ -299,7 +348,7 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, storage = OPENSSL_malloc(sizeof(*storage) * mx); if (storage != NULL) for (i = 0; i < mx; i++) - storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(ip->meth, i); + storage[i] = sk_EX_CALLBACK_value(ip->meth, i); } CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); @@ -328,15 +377,15 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) { int mx, i; - EX_CLASS_ITEM *ip; + EX_CALLBACKS *ip; void *ptr; - CRYPTO_EX_DATA_FUNCS *stack[10]; - CRYPTO_EX_DATA_FUNCS **storage = NULL; + EX_CALLBACK *stack[10]; + EX_CALLBACK **storage = NULL; - if ((ip = def_get_class(class_index)) == NULL) + if ((ip = get_and_lock(class_index)) == NULL) return; - mx = sk_CRYPTO_EX_DATA_FUNCS_num(ip->meth); + mx = sk_EX_CALLBACK_num(ip->meth); if (mx > 0) { if (mx < (int)OSSL_NELEM(stack)) storage = stack; @@ -344,7 +393,7 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) storage = OPENSSL_malloc(sizeof(*storage) * mx); if (storage != NULL) for (i = 0; i < mx; i++) - storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(ip->meth, i); + storage[i] = sk_EX_CALLBACK_value(ip->meth, i); } CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); |