diff options
author | Geoff Thorpe <geoff@openssl.org> | 2001-04-26 19:35:44 +0000 |
---|---|---|
committer | Geoff Thorpe <geoff@openssl.org> | 2001-04-26 19:35:44 +0000 |
commit | 0ce5f3e4f5ec8ca806e92fa79c06e670239662fa (patch) | |
tree | e794768b93fe1dbf9f9b67bd94c6e2b24a58644b /crypto | |
parent | 21023745e248c8e03273a063e0c99cbe86cb9cea (diff) |
This adds 2 things to the ENGINE code.
* "ex_data" - a CRYPTO_EX_DATA structure in the ENGINE structure itself
that allows an ENGINE to store its own information there rather than in
global variables. It follows the declarations and implementations used
in RSA code, for better or worse. However there's a problem when storing
state with ENGINEs because, unlike related structure types in OpenSSL,
there is no ENGINE-vs-ENGINE_METHOD separation. Because of what ENGINE
is, it has method pointers as its structure elements ... which leads
to;
* ENGINE_FLAGS_BY_ID_COPY - if an ENGINE should not be used just as a
reference to an "implementation" (eg. to get to a hardware device), but
should also be able to maintain state, then this flag can be set by the
ENGINE implementation. The result is that any call to ENGINE_by_id()
will not result in the existing ENGINE being returned (with its
structural reference count incremented) but instead a new copy of the
ENGINE will be returned that can maintain its own state independantly of
any other copies returned in the past or future. Eg. key-generation
might involve a series of ENGINE-specific control commands to set
algorithms, sizes, module-keys, ids, ACLs, etc. A final command could
generate the key. An ENGINE doing this would *have* to declare
ENGINE_FLAGS_BY_ID_COPY so that the state of that process can be
maintained "per-handle" and unaffected by other code having a reference
to the same ENGINE structure.
Diffstat (limited to 'crypto')
-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; |