X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fengine%2Feng_table.c;h=4fde9481852c0e47c7d2062182b72207db01cc21;hp=c69a84a8bf4c26422dfc70504454016bef35852d;hb=ea5003bd1eecc79e2b3e9fad302d5c4ab326e2ad;hpb=3a8a0a3945688dea8fa1136db53e2dbfef3b0a9e diff --git a/crypto/engine/eng_table.c b/crypto/engine/eng_table.c index c69a84a8bf..4fde948185 100644 --- a/crypto/engine/eng_table.c +++ b/crypto/engine/eng_table.c @@ -52,49 +52,41 @@ * */ +#include "cryptlib.h" #include -#include +#include #include "eng_int.h" -/* This is the type of item in the 'implementation' table. Each 'nid' hashes to - * a (potentially NULL) ENGINE_PILE structure which contains a stack of ENGINE* - * pointers. These pointers aren't references, because they're inserted and - * removed during ENGINE creation and ENGINE destruction. They point to ENGINEs - * that *exist* (ie. have a structural reference count greater than zero) rather - * than ENGINEs that are *functional*. Each pointer in those stacks are to - * ENGINEs that implements the algorithm corresponding to each 'nid'. */ - /* The type of the items in the table */ typedef struct st_engine_pile { - /* The 'nid' of the algorithm/mode this ENGINE_PILE structure represents - * */ + /* The 'nid' of this algorithm/mode */ int nid; - /* A stack of ENGINE pointers for ENGINEs that support this - * algorithm/mode. In the event that 'funct' is NULL, the first entry in - * this stack that initialises will be set as 'funct' and assumed as the - * default for operations of this type. */ + /* ENGINEs that implement this algorithm/mode. */ STACK_OF(ENGINE) *sk; /* The default ENGINE to perform this algorithm/mode. */ ENGINE *funct; - /* This value optimises engine_table_select(). If it is called it sets - * this value to 1. Any changes to this ENGINE_PILE resets it to zero. - * As such, no ENGINE_init() thrashing is done unless ENGINEs - * continually register (and/or unregister). */ + /* Zero if 'sk' is newer than the cached 'funct', non-zero otherwise */ int uptodate; } ENGINE_PILE; -/* The type of the hash table of ENGINE_PILE structures such that each are - * unique and keyed by the 'nid' value. */ +DECLARE_LHASH_OF(ENGINE_PILE); + +/* The type exposed in eng_int.h */ struct st_engine_table { - LHASH piles; + LHASH_OF(ENGINE_PILE) piles; }; /* ENGINE_TABLE */ -/* This value stores global options controlling behaviour of (mostly) the - * engine_table_select() function. It's a bitmask of flag values of the form - * ENGINE_TABLE_FLAG_*** (as defined in engine.h) and is controlled by the - * ENGINE_[get|set]_table_flags() function. */ + +typedef struct st_engine_pile_doall + { + engine_table_doall_cb *cb; + void *arg; + } ENGINE_PILE_DOALL; + + +/* Global flags (ENGINE_TABLE_FLAG_***). */ static unsigned int table_flags = 0; /* API function manipulating 'table_flags' */ @@ -102,6 +94,7 @@ unsigned int ENGINE_get_table_flags(void) { return table_flags; } + void ENGINE_set_table_flags(unsigned int flags) { table_flags = flags; @@ -112,21 +105,21 @@ static unsigned long engine_pile_hash(const ENGINE_PILE *c) { return c->nid; } + static int engine_pile_cmp(const ENGINE_PILE *a, const ENGINE_PILE *b) { return a->nid - b->nid; } -static IMPLEMENT_LHASH_HASH_FN(engine_pile_hash, const ENGINE_PILE *) -static IMPLEMENT_LHASH_COMP_FN(engine_pile_cmp, const ENGINE_PILE *) +static IMPLEMENT_LHASH_HASH_FN(engine_pile, ENGINE_PILE) +static IMPLEMENT_LHASH_COMP_FN(engine_pile, ENGINE_PILE) + static int int_table_check(ENGINE_TABLE **t, int create) { - LHASH *lh; - if(*t) - return 1; - if(!create) - return 0; - if((lh = lh_new(LHASH_HASH_FN(engine_pile_hash), - LHASH_COMP_FN(engine_pile_cmp))) == NULL) + LHASH_OF(ENGINE_PILE) *lh; + + if(*t) return 1; + if(!create) return 0; + if((lh = lh_ENGINE_PILE_new()) == NULL) return 0; *t = (ENGINE_TABLE *)lh; return 1; @@ -150,12 +143,11 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, while(num_nids--) { tmplate.nid = *nids; - fnd = lh_retrieve(&(*table)->piles, &tmplate); + fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate); if(!fnd) { fnd = OPENSSL_malloc(sizeof(ENGINE_PILE)); - if(!fnd) - goto end; + if(!fnd) goto end; fnd->uptodate = 1; fnd->nid = *nids; fnd->sk = sk_ENGINE_new_null(); @@ -164,11 +156,11 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, OPENSSL_free(fnd); goto end; } - fnd->funct= NULL; - lh_insert(&(*table)->piles, fnd); + fnd->funct = NULL; + (void)lh_ENGINE_PILE_insert(&(*table)->piles, fnd); } /* A registration shouldn't add duplciate entries */ - sk_ENGINE_delete_ptr(fnd->sk, e); + (void)sk_ENGINE_delete_ptr(fnd->sk, e); /* if 'setdefault', this ENGINE goes to the head of the list */ if(!sk_ENGINE_push(fnd->sk, e)) goto end; @@ -185,6 +177,7 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, if(fnd->funct) engine_unlocked_finish(fnd->funct, 0); fnd->funct = e; + fnd->uptodate = 1; } nids++; } @@ -193,14 +186,13 @@ end: CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); return ret; } -static void int_unregister_cb(ENGINE_PILE *pile, ENGINE *e) +static void int_unregister_cb_doall_arg(ENGINE_PILE *pile, ENGINE *e) { int n; /* Iterate the 'c->sk' stack removing any occurance of 'e' */ while((n = sk_ENGINE_find(pile->sk, e)) >= 0) { - sk_ENGINE_delete(pile->sk, n); - /* "touch" this ENGINE_CIPHER */ + (void)sk_ENGINE_delete(pile->sk, n); pile->uptodate = 0; } if(pile->funct == e) @@ -209,39 +201,41 @@ static void int_unregister_cb(ENGINE_PILE *pile, ENGINE *e) pile->funct = NULL; } } -static IMPLEMENT_LHASH_DOALL_ARG_FN(int_unregister_cb,ENGINE_PILE *,ENGINE *) +static IMPLEMENT_LHASH_DOALL_ARG_FN(int_unregister_cb, ENGINE_PILE, ENGINE) + void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e) { CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); if(int_table_check(table, 0)) - lh_doall_arg(&(*table)->piles, - LHASH_DOALL_ARG_FN(int_unregister_cb), e); + lh_ENGINE_PILE_doall_arg(&(*table)->piles, + LHASH_DOALL_ARG_FN(int_unregister_cb), + ENGINE, e); CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); } -static void int_cleanup_cb(ENGINE_PILE *p) +static void int_cleanup_cb_doall(ENGINE_PILE *p) { sk_ENGINE_free(p->sk); if(p->funct) engine_unlocked_finish(p->funct, 0); OPENSSL_free(p); } -static IMPLEMENT_LHASH_DOALL_FN(int_cleanup_cb,ENGINE_PILE *) +static IMPLEMENT_LHASH_DOALL_FN(int_cleanup_cb, ENGINE_PILE) + void engine_table_cleanup(ENGINE_TABLE **table) { CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); if(*table) { - lh_doall(&(*table)->piles, LHASH_DOALL_FN(int_cleanup_cb)); - lh_free(&(*table)->piles); + lh_ENGINE_PILE_doall(&(*table)->piles, + LHASH_DOALL_FN(int_cleanup_cb)); + lh_ENGINE_PILE_free(&(*table)->piles); *table = NULL; } CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); } -/* Exposed API function to get a functional reference from the implementation - * table (ie. try to get a functional reference from the tabled structural - * references) for a given cipher 'nid' */ +/* return a functional reference for a given 'nid' */ #ifndef ENGINE_TABLE_DEBUG ENGINE *engine_table_select(ENGINE_TABLE **table, int nid) #else @@ -252,25 +246,22 @@ ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, in ENGINE_PILE tmplate, *fnd=NULL; int initres, loop = 0; - /* If 'engine_ciphers' is NULL, then it's absolutely *sure* that no - * ENGINEs have registered any implementations! */ if(!(*table)) { #ifdef ENGINE_TABLE_DEBUG - fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no " - "registered for anything!\n", f, l, nid); + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, nothing " + "registered!\n", f, l, nid); #endif return NULL; } + ERR_set_mark(); CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); /* Check again inside the lock otherwise we could race against cleanup * operations. But don't worry about a fprintf(stderr). */ - if(!int_table_check(table, 0)) - goto end; + if(!int_table_check(table, 0)) goto end; tmplate.nid = nid; - fnd = lh_retrieve(&(*table)->piles, &tmplate); - if(!fnd) - goto end; + fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate); + if(!fnd) goto end; if(fnd->funct && engine_unlocked_init(fnd->funct)) { #ifdef ENGINE_TABLE_DEBUG @@ -296,34 +287,19 @@ trynext: #endif goto end; } -#if 0 - /* Don't need to get a reference if we hold the lock. If the locking has - * to change in future, that would be different ... */ - ret->struct_ref++; engine_ref_debug(ret, 0, 1) -#endif - /* Try and initialise the ENGINE if it's already functional *or* if the - * ENGINE_TABLE_FLAG_NOINIT flag is not set. */ + /* Try to initialise the ENGINE? */ if((ret->funct_ref > 0) || !(table_flags & ENGINE_TABLE_FLAG_NOINIT)) initres = engine_unlocked_init(ret); else initres = 0; -#if 0 - /* Release the structural reference */ - ret->struct_ref--; engine_ref_debug(ret, 0, -1); -#endif if(initres) { - /* If we didn't have a default (functional reference) for this - * 'nid' (or we had one but for whatever reason we're now - * initialising a different one), use this opportunity to set - * 'funct'. */ + /* Update 'funct' */ if((fnd->funct != ret) && engine_unlocked_init(ret)) { /* If there was a previous default we release it. */ if(fnd->funct) engine_unlocked_finish(fnd->funct, 0); - /* We got an extra functional reference for the - * per-'nid' default */ fnd->funct = ret; #ifdef ENGINE_TABLE_DEBUG fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, " @@ -338,13 +314,9 @@ trynext: } goto trynext; end: - /* Whatever happened - we should "untouch" our uptodate file seeing as - * we have tried our best to find a functional reference for 'nid'. If - * it failed, it is unlikely to succeed again until some future - * registrations (or unregistrations) have taken place that affect that - * 'nid'. */ - if(fnd) - fnd->uptodate = 1; + /* If it failed, it is unlikely to succeed again until some future + * registrations have taken place. In all cases, we cache. */ + if(fnd) fnd->uptodate = 1; #ifdef ENGINE_TABLE_DEBUG if(ret) fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching " @@ -356,6 +328,24 @@ end: CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); /* Whatever happened, any failed init()s are not failures in this * context, so clear our error state. */ - ERR_clear_error(); + ERR_pop_to_mark(); return ret; } + +/* Table enumeration */ + +static void int_cb_doall_arg(ENGINE_PILE *pile, ENGINE_PILE_DOALL *dall) + { + dall->cb(pile->nid, pile->sk, pile->funct, dall->arg); + } +static IMPLEMENT_LHASH_DOALL_ARG_FN(int_cb, ENGINE_PILE,ENGINE_PILE_DOALL) + +void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb, + void *arg) + { + ENGINE_PILE_DOALL dall; + dall.cb = cb; + dall.arg = arg; + lh_ENGINE_PILE_doall_arg(&table->piles, LHASH_DOALL_ARG_FN(int_cb), + ENGINE_PILE_DOALL, &dall); + }