This change adds a new ENGINE called "dynamic" that allows new ENGINE

implementations to be loaded from self-contained shared-libraries. It also
provides (in engine.h) definitions and macros to help implement a
self-contained ENGINE. Version control is handled in a way whereby the
loader or loadee can veto the load depending on any objections it has with
each other's declared interface level. The way this is currently
implemented assumes a veto will only take place when one side notices the
other's interface level is too *old*. If the other side is newer, it should
be assumed the newer version knows better whether to veto the load or not.
Version checking (like other "dynamic" settings) can be controlled using
the "dynamic" ENGINE's control commands. Also, the semantics for the
loading allow a shared-library ENGINE implementation to handle differing
interface levels on the fly (eg. loading secondary shared-libraries
depending on the versions required).

Code will be added soon to the existing ENGINEs to illustrate how they can
be built as external libraries rather than building statically into
libcrypto.

NB: Applications wanting to support "dynamic"-loadable ENGINEs will need to
add support for ENGINE "control commands". See apps/engine.c for an example
of this, and use "apps/openssl engine -vvvv" to test or experiment.
This commit is contained in:
Geoff Thorpe
2001-09-03 19:15:29 +00:00
parent 5b16639538
commit 9391f97715
6 changed files with 531 additions and 6 deletions

View File

@@ -73,6 +73,7 @@
#include <openssl/rand.h>
#include <openssl/ui.h>
#include <openssl/symhacks.h>
#include <openssl/err.h>
#ifdef __cplusplus
extern "C" {
@@ -487,6 +488,78 @@ void ENGINE_load_engine_ciphers(ENGINE *e);
* doesn't have it */
const EVP_CIPHER *ENGINE_get_cipher_by_name(ENGINE *e,const char *name);
/**************************/
/* DYNAMIC ENGINE SUPPORT */
/**************************/
/* Binary/behaviour compatibility levels */
#define OSSL_DYNAMIC_VERSION (unsigned long)0x00010100
/* Binary versions older than this are too old for us (whether we're a loader or
* a loadee) */
#define OSSL_DYNAMIC_OLDEST (unsigned long)0x00010100
/* When compiling an ENGINE entirely as an external shared library, loadable by
* the "dynamic" ENGINE, these types are needed. The 'dynamic_fns' structure
* type provides the calling application's (or library's) error functionality
* and memory management function pointers to the loaded library. These should
* be used/set in the loaded library code so that the loading application's
* 'state' will be used/changed in all operations. */
typedef void *(*dynamic_MEM_malloc_cb)(size_t);
typedef void *(*dynamic_MEM_realloc_cb)(void *, size_t);
typedef void (*dynamic_MEM_free_cb)(void *);
typedef struct st_dynamic_MEM_fns {
dynamic_MEM_malloc_cb malloc_cb;
dynamic_MEM_realloc_cb realloc_cb;
dynamic_MEM_free_cb free_cb;
} dynamic_MEM_fns;
typedef struct st_dynamic_fns {
const ERR_FNS *err_fns;
const CRYPTO_EX_DATA_IMPL *ex_data_fns;
dynamic_MEM_fns mem_fns;
} dynamic_fns;
/* The version checking function should be of this prototype. NB: The
* ossl_version value passed in is the OSSL_DYNAMIC_VERSION of the loading code.
* If this function returns zero, it indicates a (potential) version
* incompatibility and the loaded library doesn't believe it can proceed.
* Otherwise, the returned value is the (latest) version supported by the
* loading library. The loader may still decide that the loaded code's version
* is unsatisfactory and could veto the load. The function is expected to
* be implemented with the symbol name "v_check", and a default implementation
* can be fully instantiated with IMPLEMENT_DYNAMIC_CHECK_FN(). */
typedef unsigned long (*dynamic_v_check_fn)(unsigned long ossl_version);
#define IMPLEMENT_DYNAMIC_CHECK_FN() \
unsigned long v_check(unsigned long v) { \
if(v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \
return 0; }
/* This function is passed the ENGINE structure to initialise with its own
* function and command settings. It should not adjust the structural or
* functional reference counts. If this function returns zero, (a) the load will
* be aborted, (b) the previous ENGINE state will be memcpy'd back onto the
* structure, and (c) the shared library will be unloaded. So implementations
* should do their own internal cleanup in failure circumstances otherwise they
* could leak. The 'id' parameter, if non-NULL, represents the ENGINE id that
* the loader is looking for. If this is NULL, the shared library can choose to
* return failure or to initialise a 'default' ENGINE. If non-NULL, the shared
* library must initialise only an ENGINE matching the passed 'id'. The function
* is expected to be implemented with the symbol name "bind_engine". A standard
* implementation can be instantiated with IMPLEMENT_DYNAMIC_BIND_FN(fn) where
* the parameter 'fn' is a callback function that populates the ENGINE structure
* and returns an int value (zero for failure). 'fn' should have prototype;
* [static] int fn(ENGINE *e, const char *id); */
typedef int (*dynamic_bind_engine)(ENGINE *e, const char *id,
const dynamic_fns *fns);
#define IMPLEMENT_DYNAMIC_BIND_FN(fn) \
int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \
if(!CRYPTO_set_mem_functions(fns->mem_fns.malloc_cb, \
fns->mem_fns.realloc_cb, fns->mem_fns.free_cb)) \
return 0; \
if(!CRYPTO_set_ex_data_implementation(fns->ex_data_fns)) \
return 0; \
if(!ERR_set_implementation(fns->err_fns)) return 0; \
if(!fn(e,id)) return 0; \
return 1; }
/* Obligatory error function. */
void ERR_load_ENGINE_strings(void);
@@ -513,6 +586,9 @@ void ERR_load_ENGINE_strings(void);
#define ENGINE_F_CSWIFT_MOD_EXP 102
#define ENGINE_F_CSWIFT_MOD_EXP_CRT 103
#define ENGINE_F_CSWIFT_RSA_MOD_EXP 104
#define ENGINE_F_DYNAMIC_CTRL 180
#define ENGINE_F_DYNAMIC_GET_DATA_CTX 181
#define ENGINE_F_DYNAMIC_LOAD 182
#define ENGINE_F_ENGINE_ADD 105
#define ENGINE_F_ENGINE_BY_ID 106
#define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE 170
@@ -552,6 +628,7 @@ void ERR_load_ENGINE_strings(void);
#define ENGINE_F_NURON_FINISH 157
#define ENGINE_F_NURON_INIT 156
#define ENGINE_F_NURON_MOD_EXP 158
#define ENGINE_F_SET_DATA_CTX 183
#define ENGINE_F_UBSEC_CTRL 176
#define ENGINE_F_UBSEC_DSA_SIGN 163
#define ENGINE_F_UBSEC_DSA_VERIFY 164
@@ -586,6 +663,7 @@ void ERR_load_ENGINE_strings(void);
#define ENGINE_R_ID_OR_NAME_MISSING 108
#define ENGINE_R_INIT_FAILED 109
#define ENGINE_R_INTERNAL_LIST_ERROR 110
#define ENGINE_R_INVALID_ARGUMENT 143
#define ENGINE_R_INVALID_CMD_NAME 137
#define ENGINE_R_INVALID_CMD_NUMBER 138
#define ENGINE_R_MISSING_KEY_COMPONENTS 111
@@ -593,6 +671,7 @@ void ERR_load_ENGINE_strings(void);
#define ENGINE_R_NOT_LOADED 112
#define ENGINE_R_NO_CALLBACK 127
#define ENGINE_R_NO_CONTROL_FUNCTION 120
#define ENGINE_R_NO_INDEX 144
#define ENGINE_R_NO_KEY 124
#define ENGINE_R_NO_LOAD_FUNCTION 125
#define ENGINE_R_NO_REFERENCE 130
@@ -605,6 +684,7 @@ void ERR_load_ENGINE_strings(void);
#define ENGINE_R_RSA_NOT_IMPLEMENTED 141
#define ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL 122
#define ENGINE_R_UNIT_FAILURE 115
#define ENGINE_R_VERSION_INCOMPATIBILITY 145
#ifdef __cplusplus
}