If dynamically-loadable ENGINEs are linked against a shared-library version
[openssl.git] / crypto / engine / engine.h
index 0d35b0152dca6cf5552176b259a1c4bcf6f36733..77663742aaf84075a34d42c74cdb4c36ef6ec3ac 100644 (file)
@@ -567,17 +567,20 @@ void ENGINE_add_conf_module(void);
 /**************************/
 
 /* Binary/behaviour compatibility levels */
-#define OSSL_DYNAMIC_VERSION           (unsigned long)0x00010100
+#define OSSL_DYNAMIC_VERSION           (unsigned long)0x00010200
 /* 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
+#define OSSL_DYNAMIC_OLDEST            (unsigned long)0x00010200
 
 /* 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. */
+ * 'state' will be used/changed in all operations. The 'static_state' pointer
+ * allows the loaded library to know if it shares the same static data as the
+ * calling application (or library), and thus whether these callbacks need to be
+ * set or not. */
 typedef void *(*dyn_MEM_malloc_cb)(size_t);
 typedef void *(*dyn_MEM_realloc_cb)(void *, size_t);
 typedef void (*dyn_MEM_free_cb)(void *);
@@ -605,6 +608,7 @@ typedef struct st_dynamic_LOCK_fns {
        } dynamic_LOCK_fns;
 /* The top-level structure */
 typedef struct st_dynamic_fns {
+       void                                    *static_state;
        const ERR_FNS                           *err_fns;
        const CRYPTO_EX_DATA_IMPL               *ex_data_fns;
        dynamic_MEM_fns                         mem_fns;
@@ -645,6 +649,7 @@ 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(ENGINE_get_static_state() == fns->static_state) goto skip_cbs; \
                if(!CRYPTO_set_mem_functions(fns->mem_fns.malloc_cb, \
                        fns->mem_fns.realloc_cb, fns->mem_fns.free_cb)) \
                        return 0; \
@@ -656,9 +661,22 @@ typedef int (*dynamic_bind_engine)(ENGINE *e, const char *id,
                if(!CRYPTO_set_ex_data_implementation(fns->ex_data_fns)) \
                        return 0; \
                if(!ERR_set_implementation(fns->err_fns)) return 0; \
+       skip_cbs: \
                if(!fn(e,id)) return 0; \
                return 1; }
 
+/* If the loading application (or library) and the loaded ENGINE library share
+ * the same static data (eg. they're both dynamically linked to the same
+ * libcrypto.so) we need a way to avoid trying to set system callbacks - this
+ * would fail, and for the same reason that it's unnecessary to try. If the
+ * loaded ENGINE has (or gets from through the loader) its own copy of the
+ * libcrypto static data, we will need to set the callbacks. The easiest way to
+ * detect this is to have a function that returns a pointer to some static data
+ * and let the loading application and loaded ENGINE compare their respective
+ * values. */
+void *ENGINE_get_static_state(void);
+
+
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.