* 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
/* 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);
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
#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
ENGINE *ENGINE_by_id(const char *id)
{
- ENGINE *iterator = NULL;
+ ENGINE *iterator = NULL, *cp = NULL;
if(id == NULL)
{
ENGINEerr(ENGINE_F_ENGINE_BY_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)
}
memset(ret, 0, sizeof(ENGINE));
ret->struct_ref = 1;
+ CRYPTO_new_ex_data(engine_ex_data_stack, ret, &ret->ex_data);
return ret;
}
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;