diff options
-rw-r--r-- | crypto/engine/engine.h | 15 | ||||
-rw-r--r-- | crypto/engine/engine_int.h | 2 | ||||
-rw-r--r-- | crypto/engine/engine_list.c | 51 |
3 files changed, 65 insertions, 3 deletions
diff --git a/crypto/engine/engine.h b/crypto/engine/engine.h index e129cde70c..258ec6ec43 100644 --- a/crypto/engine/engine.h +++ b/crypto/engine/engine.h @@ -108,6 +108,15 @@ typedef void DH_METHOD; * control commands on behalf of the ENGINE using their "cmd_defns" data. */ #define ENGINE_FLAGS_MANUAL_CMD_CTRL (int)0x0002 +/* This flag is for ENGINEs who return new duplicate structures when found via + * "ENGINE_by_id()". When an ENGINE must store state (eg. if ENGINE_ctrl() + * commands are called in sequence as part of some stateful process like + * key-generation setup and execution), it can set this flag - then each attempt + * to obtain the ENGINE will result in it being copied into a new structure. + * Normally, ENGINEs don't declare this flag so ENGINE_by_id() just increments + * the existing ENGINE's structural reference count. */ +#define ENGINE_FLAGS_BY_ID_COPY (int)0x0004 + /* ENGINEs can support their own command types, and these flags are used in * ENGINE_CTRL_GET_CMD_FLAGS to indicate to the caller what kind of input each * command expects. Currently only numeric and string input is supported. If a @@ -349,6 +358,11 @@ int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns); /* Copies across all ENGINE methods and pointers. NB: This does *not* change * reference counts however. */ int ENGINE_cpy(ENGINE *dest, const ENGINE *src); +/* These functions (and the "get" function lower down) allow control over any + * per-structure ENGINE data. */ +int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg); /* Cleans the internal engine structure. This should only be used when the * application is about to exit. */ void ENGINE_cleanup(void); @@ -372,6 +386,7 @@ ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e); ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e); const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e); int ENGINE_get_flags(const ENGINE *e); +void *ENGINE_get_ex_data(const ENGINE *e, int idx); /* FUNCTIONAL functions. These functions deal with ENGINE structures * that have (or will) be initialised for use. Broadly speaking, the diff --git a/crypto/engine/engine_int.h b/crypto/engine/engine_int.h index addf6b533b..d44f648559 100644 --- a/crypto/engine/engine_int.h +++ b/crypto/engine/engine_int.h @@ -96,6 +96,8 @@ struct engine_st * simply to cope with (de)allocation of this structure. Hence, * running_ref <= struct_ref at all times. */ int funct_ref; + /* A place to store per-key data */ + CRYPTO_EX_DATA ex_data; /* Used to maintain the linked-list of engines. */ struct engine_st *prev; struct engine_st *next; diff --git a/crypto/engine/engine_list.c b/crypto/engine/engine_list.c index 2ca667e85d..0f6e9bb242 100644 --- a/crypto/engine/engine_list.c +++ b/crypto/engine/engine_list.c @@ -61,6 +61,14 @@ #include "engine_int.h" #include <openssl/engine.h> +/* Weird "ex_data" handling. Some have suggested there's some problems with the + * CRYPTO_EX_DATA code (or model), but for now I'm implementing it exactly as + * it's done in crypto/rsa/. That way the usage and documentation of that can be + * used to assist here, and any changes or fixes made there should similarly map + * over here quite straightforwardly. */ +static int engine_ex_data_num = 0; +static STACK_OF(CRYPTO_EX_DATA_FUNCS) *engine_ex_data_stack = NULL; + /* The linked-list of pointers to engine types. engine_list_head * incorporates an implicit structural reference but engine_list_tail * does not - the latter is a computational niceity and only points @@ -308,7 +316,7 @@ int ENGINE_remove(ENGINE *e) ENGINE *ENGINE_by_id(const char *id) { - ENGINE *iterator = NULL; + ENGINE *iterator = NULL, *cp = NULL; if(id == NULL) { ENGINEerr(ENGINE_F_ENGINE_BY_ID, @@ -325,8 +333,24 @@ ENGINE *ENGINE_by_id(const char *id) while(iterator && (strcmp(id, iterator->id) != 0)) iterator = iterator->next; if(iterator) - /* We need to return a structural reference */ - iterator->struct_ref++; + { + /* We need to return a structural reference. If this is + * a "dynamic" ENGINE type, make a duplicate - otherwise + * increment the existing ENGINE's reference count. */ + if(iterator->flags & ENGINE_FLAGS_BY_ID_COPY) + { + cp = ENGINE_new(); + if(!cp) + iterator = NULL; + else + { + ENGINE_cpy(cp, iterator); + iterator = cp; + } + } + else + iterator->struct_ref++; + } } CRYPTO_r_unlock(CRYPTO_LOCK_ENGINE); if(iterator == NULL) @@ -347,6 +371,7 @@ ENGINE *ENGINE_new(void) } memset(ret, 0, sizeof(ENGINE)); ret->struct_ref = 1; + CRYPTO_new_ex_data(engine_ex_data_stack, ret, &ret->ex_data); return ret; } @@ -372,10 +397,30 @@ int ENGINE_free(ENGINE *e) abort(); } #endif + CRYPTO_free_ex_data(engine_ex_data_stack, e, &e->ex_data); OPENSSL_free(e); return 1; } +int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) + { + engine_ex_data_num++; + return(CRYPTO_get_ex_new_index(engine_ex_data_num - 1, + &engine_ex_data_stack, argl, argp, + new_func, dup_func, free_func)); + } + +int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg) + { + return(CRYPTO_set_ex_data(&e->ex_data, idx, arg)); + } + +void *ENGINE_get_ex_data(const ENGINE *e, int idx) + { + return(CRYPTO_get_ex_data(&e->ex_data, idx)); + } + void ENGINE_cleanup(void) { ENGINE *iterator = engine_list_head; |