Some more tweaks to ENGINE code.
authorGeoff Thorpe <geoff@openssl.org>
Thu, 19 Apr 2001 01:45:40 +0000 (01:45 +0000)
committerGeoff Thorpe <geoff@openssl.org>
Thu, 19 Apr 2001 01:45:40 +0000 (01:45 +0000)
This change adds some basic control commands to the existing ENGINEs
(except the software 'openssl' engine). All these engines currently load
shared-libraries for hardware APIs, so they've all been given "SO_PATH"
commands that will configure the chosen ENGINE to load its shared library
from the given path. Eg. by calling;
    ENGINE_ctrl_cmd_string(e, "SO_PATH", <path>, 0).

The nCipher 'chil' ENGINE has also had "FORK_CHECK" and "THREAD_LOCKING"
commands added so these settings could be handled via application-level
configuration rather than in application source code.

Changes to "openssl engine" to test and examine these control commands will
be made shortly. It will also provide the necessary tips to application
programs wanting to support these dynamic control commands.

crypto/engine/engine.h
crypto/engine/engine_err.c
crypto/engine/hw_atalla.c
crypto/engine/hw_cswift.c
crypto/engine/hw_ncipher.c
crypto/engine/hw_nuron.c
crypto/engine/hw_ubsec.c

index 3e729098046a285d83d7297ee4082d85697ae724..48300fe769d48328e061220f18f33c34aa024416 100644 (file)
@@ -422,10 +422,12 @@ void ERR_load_ENGINE_strings(void);
 /* Error codes for the ENGINE functions. */
 
 /* Function codes. */
+#define ENGINE_F_ATALLA_CTRL                            173
 #define ENGINE_F_ATALLA_FINISH                          159
 #define ENGINE_F_ATALLA_INIT                            160
 #define ENGINE_F_ATALLA_MOD_EXP                                 161
 #define ENGINE_F_ATALLA_RSA_MOD_EXP                     162
+#define ENGINE_F_CSWIFT_CTRL                            174
 #define ENGINE_F_CSWIFT_DSA_SIGN                        133
 #define ENGINE_F_CSWIFT_DSA_VERIFY                      134
 #define ENGINE_F_CSWIFT_FINISH                          100
@@ -465,9 +467,11 @@ void ERR_load_ENGINE_strings(void);
 #define ENGINE_F_HWCRHK_RSA_MOD_EXP                     140
 #define ENGINE_F_INT_CTRL_HELPER                        172
 #define ENGINE_F_LOG_MESSAGE                            141
+#define ENGINE_F_NURON_CTRL                             175
 #define ENGINE_F_NURON_FINISH                           157
 #define ENGINE_F_NURON_INIT                             156
 #define ENGINE_F_NURON_MOD_EXP                          158
+#define ENGINE_F_UBSEC_CTRL                             176
 #define ENGINE_F_UBSEC_DSA_SIGN                                 163
 #define ENGINE_F_UBSEC_DSA_VERIFY                       164
 #define ENGINE_F_UBSEC_FINISH                           165
index 11c738ea741eba295e1f7bfc537dfdec8d43d8c4..24202a1bee2a43c68a5cd529a86b8f58893a5c12 100644 (file)
 #ifndef OPENSSL_NO_ERR
 static ERR_STRING_DATA ENGINE_str_functs[]=
        {
+{ERR_PACK(0,ENGINE_F_ATALLA_CTRL,0),   "ATALLA_CTRL"},
 {ERR_PACK(0,ENGINE_F_ATALLA_FINISH,0), "ATALLA_FINISH"},
 {ERR_PACK(0,ENGINE_F_ATALLA_INIT,0),   "ATALLA_INIT"},
 {ERR_PACK(0,ENGINE_F_ATALLA_MOD_EXP,0),        "ATALLA_MOD_EXP"},
 {ERR_PACK(0,ENGINE_F_ATALLA_RSA_MOD_EXP,0),    "ATALLA_RSA_MOD_EXP"},
+{ERR_PACK(0,ENGINE_F_CSWIFT_CTRL,0),   "CSWIFT_CTRL"},
 {ERR_PACK(0,ENGINE_F_CSWIFT_DSA_SIGN,0),       "CSWIFT_DSA_SIGN"},
 {ERR_PACK(0,ENGINE_F_CSWIFT_DSA_VERIFY,0),     "CSWIFT_DSA_VERIFY"},
 {ERR_PACK(0,ENGINE_F_CSWIFT_FINISH,0), "CSWIFT_FINISH"},
@@ -109,9 +111,11 @@ static ERR_STRING_DATA ENGINE_str_functs[]=
 {ERR_PACK(0,ENGINE_F_HWCRHK_RSA_MOD_EXP,0),    "HWCRHK_RSA_MOD_EXP"},
 {ERR_PACK(0,ENGINE_F_INT_CTRL_HELPER,0),       "INT_CTRL_HELPER"},
 {ERR_PACK(0,ENGINE_F_LOG_MESSAGE,0),   "LOG_MESSAGE"},
+{ERR_PACK(0,ENGINE_F_NURON_CTRL,0),    "NURON_CTRL"},
 {ERR_PACK(0,ENGINE_F_NURON_FINISH,0),  "NURON_FINISH"},
 {ERR_PACK(0,ENGINE_F_NURON_INIT,0),    "NURON_INIT"},
 {ERR_PACK(0,ENGINE_F_NURON_MOD_EXP,0), "NURON_MOD_EXP"},
+{ERR_PACK(0,ENGINE_F_UBSEC_CTRL,0),    "UBSEC_CTRL"},
 {ERR_PACK(0,ENGINE_F_UBSEC_DSA_SIGN,0),        "UBSEC_DSA_SIGN"},
 {ERR_PACK(0,ENGINE_F_UBSEC_DSA_VERIFY,0),      "UBSEC_DSA_VERIFY"},
 {ERR_PACK(0,ENGINE_F_UBSEC_FINISH,0),  "UBSEC_FINISH"},
index e3407e73c7fccc55895c8a7043fe6eb62366e4f0..8bf702aac0b1331ad492bccefcec1f2047c49088 100644 (file)
@@ -73,6 +73,7 @@
 
 static int atalla_init(ENGINE *e);
 static int atalla_finish(ENGINE *e);
+static int atalla_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
 
 /* BIGNUM stuff */
 static int atalla_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
@@ -98,6 +99,15 @@ static int atalla_mod_exp_dh(const DH *dh, BIGNUM *r,
                const BIGNUM *a, const BIGNUM *p,
                const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
 
+/* The definitions for control commands specific to this engine */
+#define ATALLA_CMD_SO_PATH             ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN atalla_cmd_defns[] = {
+       {ATALLA_CMD_SO_PATH,
+               "SO_PATH",
+               "Specifies the path to the 'atasi' shared library",
+               ENGINE_CMD_FLAG_STRING},
+       {0, NULL, NULL, 0}
+       };
 
 /* Our internal RSA_METHOD that we provide pointers to */
 static RSA_METHOD atalla_rsa =
@@ -166,7 +176,9 @@ ENGINE *ENGINE_atalla()
                        !ENGINE_set_DH(ret, &atalla_dh) ||
                        !ENGINE_set_BN_mod_exp(ret, atalla_mod_exp) ||
                        !ENGINE_set_init_function(ret, atalla_init) ||
-                       !ENGINE_set_finish_function(ret, atalla_finish))
+                       !ENGINE_set_finish_function(ret, atalla_finish) ||
+                       !ENGINE_set_ctrl_function(ret, atalla_ctrl) ||
+                       !ENGINE_set_cmd_defns(ret, atalla_cmd_defns))
                {
                ENGINE_free(ret);
                return NULL;
@@ -220,7 +232,8 @@ static tfnASI_GetPerformanceStatistics *p_Atalla_GetPerformanceStatistics = NULL
  * atasi.dll on win32). For the purposes of testing, I have created a symbollic
  * link called "libatasi.so" so that we can use native name-translation - a
  * better solution will be needed. */
-static const char *ATALLA_LIBNAME = "atasi";
+static const char def_ATALLA_LIBNAME[] = "atasi";
+static const char *ATALLA_LIBNAME = def_ATALLA_LIBNAME;
 static const char *ATALLA_F1 = "ASI_GetHardwareConfig";
 static const char *ATALLA_F2 = "ASI_RSAPrivateKeyOpFn";
 static const char *ATALLA_F3 = "ASI_GetPerformanceStatistics";
@@ -304,6 +317,31 @@ static int atalla_finish(ENGINE *e)
        return 1;
        }
 
+static int atalla_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+       {
+       int initialised = ((atalla_dso == NULL) ? 0 : 1);
+       switch(cmd)
+               {
+       case ATALLA_CMD_SO_PATH:
+               if(p == NULL)
+                       {
+                       ENGINEerr(ENGINE_F_ATALLA_CTRL,ERR_R_PASSED_NULL_PARAMETER);
+                       return 0;
+                       }
+               if(initialised)
+                       {
+                       ENGINEerr(ENGINE_F_ATALLA_CTRL,ENGINE_R_ALREADY_LOADED);
+                       return 0;
+                       }
+               ATALLA_LIBNAME = (const char *)p;
+               return 1;
+       default:
+               break;
+               }
+       ENGINEerr(ENGINE_F_ATALLA_CTRL,ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+       return 0;
+       }
+
 static int atalla_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
                        const BIGNUM *m, BN_CTX *ctx)
        {
index e9f62f61d3a9a37ec603af5e20a68733c8864b77..15983525e1b9057c1ed1b9d411f02cb8e19fdc9b 100644 (file)
@@ -83,8 +83,9 @@
 #include "vendor_defns/cswift.h"
 #endif
 
-static int cswift_init(ENGINE *);
-static int cswift_finish(ENGINE *);
+static int cswift_init(ENGINE *e);
+static int cswift_finish(ENGINE *e);
+static int cswift_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
 
 /* BIGNUM stuff */
 static int cswift_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
@@ -110,6 +111,15 @@ static int cswift_mod_exp_dh(const DH *dh, BIGNUM *r,
                const BIGNUM *a, const BIGNUM *p,
                const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
 
+/* The definitions for control commands specific to this engine */
+#define CSWIFT_CMD_SO_PATH             ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN cswift_cmd_defns[] = {
+       {CSWIFT_CMD_SO_PATH,
+               "SO_PATH",
+               "Specifies the path to the 'cswift' shared library",
+               ENGINE_CMD_FLAG_STRING},
+       {0, NULL, NULL, 0}
+       };
 
 /* Our internal RSA_METHOD that we provide pointers to */
 static RSA_METHOD cswift_rsa =
@@ -178,7 +188,9 @@ ENGINE *ENGINE_cswift()
                        !ENGINE_set_BN_mod_exp(ret, &cswift_mod_exp) ||
                        !ENGINE_set_BN_mod_exp_crt(ret, &cswift_mod_exp_crt) ||
                        !ENGINE_set_init_function(ret, cswift_init) ||
-                       !ENGINE_set_finish_function(ret, cswift_finish))
+                       !ENGINE_set_finish_function(ret, cswift_finish) ||
+                       !ENGINE_set_ctrl_function(ret, cswift_ctrl) ||
+                       !ENGINE_set_cmd_defns(ret, cswift_cmd_defns))
                {
                ENGINE_free(ret);
                return NULL;
@@ -219,7 +231,8 @@ t_swSimpleRequest *p_CSwift_SimpleRequest = NULL;
 t_swReleaseAccContext *p_CSwift_ReleaseAccContext = NULL;
 
 /* Used in the DSO operations. */
-static const char *CSWIFT_LIBNAME = "swift";
+static const char def_CSWIFT_LIBNAME[] = "swift";
+static const char *CSWIFT_LIBNAME = def_CSWIFT_LIBNAME;
 static const char *CSWIFT_F1 = "swAcquireAccContext";
 static const char *CSWIFT_F2 = "swAttachKeyParam";
 static const char *CSWIFT_F3 = "swSimpleRequest";
@@ -326,6 +339,33 @@ static int cswift_finish(ENGINE *e)
        return 1;
        }
 
+static int cswift_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+       {
+       int initialised = ((cswift_dso == NULL) ? 0 : 1);
+       switch(cmd)
+               {
+       case CSWIFT_CMD_SO_PATH:
+               if(p == NULL)
+                       {
+                       ENGINEerr(ENGINE_F_CSWIFT_CTRL,
+                               ERR_R_PASSED_NULL_PARAMETER);
+                       return 0;
+                       }
+               if(initialised)
+                       {
+                       ENGINEerr(ENGINE_F_CSWIFT_CTRL,
+                               ENGINE_R_ALREADY_LOADED);
+                       return 0;
+                       }
+               CSWIFT_LIBNAME = (const char *)p;
+               return 1;
+       default:
+               break;
+               }
+       ENGINEerr(ENGINE_F_CSWIFT_CTRL,ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+       return 0;
+       }
+
 /* Un petit mod_exp */
 static int cswift_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
                        const BIGNUM *m, BN_CTX *ctx)
index 792893a2fdda55c9485a8cfb95c68cb2b7dc5b71..dc645d554b3d0cd8f5a6fb3725533c6fdfb3936f 100644 (file)
@@ -126,6 +126,26 @@ static int hwcrhk_get_pass(const char *prompt_info,
        HWCryptoHook_CallerContext *cactx);
 static void hwcrhk_log_message(void *logstr, const char *message);
 
+/* The definitions for control commands specific to this engine */
+#define HWCRHK_CMD_SO_PATH             ENGINE_CMD_BASE
+#define HWCRHK_CMD_FORK_CHECK          (ENGINE_CMD_BASE + 1)
+#define HWCRHK_CMD_THREAD_LOCKING      (ENGINE_CMD_BASE + 2)
+static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
+       {HWCRHK_CMD_SO_PATH,
+               "SO_PATH",
+               "Specifies the path to the 'hwcrhk' shared library",
+               ENGINE_CMD_FLAG_STRING},
+       {HWCRHK_CMD_FORK_CHECK,
+               "FORK_CHECK",
+               "Turns fork() checking on or off (boolean)",
+               ENGINE_CMD_FLAG_NUMERIC},
+       {HWCRHK_CMD_THREAD_LOCKING,
+               "THREAD_LOCKING",
+               "Turns thread-safe locking on or off (boolean)",
+               ENGINE_CMD_FLAG_NUMERIC},
+       {0, NULL, NULL, 0}
+       };
+
 /* Our internal RSA_METHOD that we provide pointers to */
 static RSA_METHOD hwcrhk_rsa =
        {
@@ -289,7 +309,8 @@ ENGINE *ENGINE_ncipher()
                        !ENGINE_set_finish_function(ret, hwcrhk_finish) ||
                        !ENGINE_set_ctrl_function(ret, hwcrhk_ctrl) ||
                        !ENGINE_set_load_privkey_function(ret, hwcrhk_load_privkey) ||
-                       !ENGINE_set_load_pubkey_function(ret, hwcrhk_load_pubkey))
+                       !ENGINE_set_load_pubkey_function(ret, hwcrhk_load_pubkey) ||
+                       !ENGINE_set_cmd_defns(ret, hwcrhk_cmd_defns))
                {
                ENGINE_free(ret);
                return NULL;
@@ -337,7 +358,8 @@ static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
 
 /* Used in the DSO operations. */
-static const char *HWCRHK_LIBNAME = "nfhwcrhk";
+static const char def_HWCRHK_LIBNAME[] = "nfhwcrhk";
+static const char *HWCRHK_LIBNAME = def_HWCRHK_LIBNAME;
 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
@@ -513,6 +535,19 @@ static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
 
        switch(cmd)
                {
+       case HWCRHK_CMD_SO_PATH:
+               if(hwcrhk_dso)
+                       {
+                       ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_ALREADY_LOADED);
+                       return 0;
+                       }
+               if(p == NULL)
+                       {
+                       ENGINEerr(ENGINE_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
+                       return 0;
+                       }
+               HWCRHK_LIBNAME = (const char *)p;
+               return 1;
        case ENGINE_CTRL_SET_LOGSTREAM:
                {
                BIO *bio = (BIO *)p;
@@ -538,6 +573,7 @@ static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
        /* this enables or disables the "SimpleForkCheck" flag used in the
         * initialisation structure. */
        case ENGINE_CTRL_CHIL_SET_FORKCHECK:
+       case HWCRHK_CMD_FORK_CHECK:
                CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
                if(i)
                        hwcrhk_globals.flags |=
@@ -557,6 +593,11 @@ static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
                disable_mutex_callbacks = 1;
                CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
                break;
+       case HWCRHK_CMD_THREAD_LOCKING:
+               CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+               disable_mutex_callbacks = ((i == 0) ? 0 : 1);
+               CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+               break;
 
        /* The command isn't understood by this engine */
        default:
index d85de3f9acb6e5e6e575262c459c644e5081ae52..d5697dade667904b2b11870d7642c7bf96469d97 100644 (file)
 #ifndef OPENSSL_NO_HW
 #ifndef OPENSSL_NO_HW_NURON
 
-static const char *NURON_LIBNAME = "nuronssl";
+static const char def_NURON_LIBNAME[] = "nuronssl";
+static const char *NURON_LIBNAME = def_NURON_LIBNAME;
 static const char *NURON_F1 = "nuron_mod_exp";
 
+/* The definitions for control commands specific to this engine */
+#define NURON_CMD_SO_PATH              ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN nuron_cmd_defns[] = {
+       {NURON_CMD_SO_PATH,
+               "SO_PATH",
+               "Specifies the path to the 'nuronssl' shared library",
+               ENGINE_CMD_FLAG_STRING},
+       {0, NULL, NULL, 0}
+       };
+
 typedef int tfnModExp(BIGNUM *r,const BIGNUM *a,const BIGNUM *p,const BIGNUM *m);
 static tfnModExp *pfnModExp = NULL;
 
@@ -82,7 +93,7 @@ static int nuron_init(ENGINE *e)
                return 0;
                }
 
-       pvDSOHandle=DSO_load(NULL, NURON_LIBNAME, NULL,
+       pvDSOHandle = DSO_load(NULL, NURON_LIBNAME, NULL,
                DSO_FLAG_NAME_TRANSLATION_EXT_ONLY);
        if(!pvDSOHandle)
                {
@@ -90,7 +101,7 @@ static int nuron_init(ENGINE *e)
                return 0;
                }
 
-       pfnModExp=(tfnModExp *)DSO_bind_func(pvDSOHandle, NURON_F1);
+       pfnModExp = (tfnModExp *)DSO_bind_func(pvDSOHandle, NURON_F1);
        if(!pfnModExp)
                {
                ENGINEerr(ENGINE_F_NURON_INIT,ENGINE_R_DSO_FUNCTION_NOT_FOUND);
@@ -117,6 +128,31 @@ static int nuron_finish(ENGINE *e)
        return 1;
        }
 
+static int nuron_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+       {
+       int initialised = ((pvDSOHandle == NULL) ? 0 : 1);
+       switch(cmd)
+               {
+       case NURON_CMD_SO_PATH:
+               if(p == NULL)
+                       {
+                       ENGINEerr(ENGINE_F_NURON_CTRL,ERR_R_PASSED_NULL_PARAMETER);
+                       return 0;
+                       }
+               if(initialised)
+                       {
+                       ENGINEerr(ENGINE_F_NURON_CTRL,ENGINE_R_ALREADY_LOADED);
+                       return 0;
+                       }
+               NURON_LIBNAME = (const char *)p;
+               return 1;
+       default:
+               break;
+               }
+       ENGINEerr(ENGINE_F_NURON_CTRL,ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+       return 0;
+}
+
 static int nuron_mod_exp(BIGNUM *r,const BIGNUM *a,const BIGNUM *p,
                         const BIGNUM *m,BN_CTX *ctx)
        {
@@ -250,7 +286,9 @@ ENGINE *ENGINE_nuron()
                        !ENGINE_set_DH(ret, &nuron_dh) ||
                        !ENGINE_set_BN_mod_exp(ret, nuron_mod_exp) ||
                        !ENGINE_set_init_function(ret, nuron_init) ||
-                       !ENGINE_set_finish_function(ret, nuron_finish))
+                       !ENGINE_set_finish_function(ret, nuron_finish) ||
+                       !ENGINE_set_ctrl_function(ret, nuron_ctrl) ||
+                       !ENGINE_set_cmd_defns(ret, nuron_cmd_defns))
                {
                ENGINE_free(ret);
                return NULL;
index a05211f27ab4dbf4a4398a43b48bc2ab211b6080..d9481355680e060ab31310bb358eaec212bd7ea7 100644 (file)
@@ -75,6 +75,7 @@
 
 static int ubsec_init(ENGINE *e);
 static int ubsec_finish(ENGINE *e);
+static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
 static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
                const BIGNUM *m, BN_CTX *ctx);
 static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
@@ -104,7 +105,16 @@ static int ubsec_dh_generate_key(DH *dh);
 static int ubsec_rand_bytes(unsigned char *buf, int num);
 static int ubsec_rand_status(void);
 #endif
+
+#define UBSEC_CMD_SO_PATH              ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN ubsec_cmd_defns[] = {
+       {UBSEC_CMD_SO_PATH,
+               "SO_PATH",
+               "Specifies the path to the 'ubsec' shared library",
+               ENGINE_CMD_FLAG_STRING},
+       {0, NULL, NULL, 0}
+       };
+
 /* Our internal RSA_METHOD that we provide pointers to */
 
 static RSA_METHOD ubsec_rsa =
@@ -175,7 +185,9 @@ ENGINE *ENGINE_ubsec()
                        !ENGINE_set_BN_mod_exp(ret, ubsec_mod_exp) ||
                        !ENGINE_set_BN_mod_exp_crt(ret, ubsec_mod_exp_crt) ||
                        !ENGINE_set_init_function(ret, ubsec_init) ||
-                       !ENGINE_set_finish_function(ret, ubsec_finish))
+                       !ENGINE_set_finish_function(ret, ubsec_finish) ||
+                       !ENGINE_set_ctrl_function(ret, ubsec_ctrl) ||
+                       !ENGINE_set_cmd_defns(ret, ubsec_cmd_defns))
                {
                ENGINE_free(ret);
                return NULL;
@@ -373,6 +385,31 @@ static int ubsec_finish(ENGINE *e)
        return 1;
        }
 
+static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+       {
+       int initialised = ((ubsec_dso == NULL) ? 0 : 1);
+       switch(cmd)
+               {
+       case UBSEC_CMD_SO_PATH:
+               if(p == NULL)
+                       {
+                       ENGINEerr(ENGINE_F_UBSEC_CTRL,ERR_R_PASSED_NULL_PARAMETER);
+                       return 0;
+                       }
+               if(initialised)
+                       {
+                       ENGINEerr(ENGINE_F_UBSEC_CTRL,ENGINE_R_ALREADY_LOADED);
+                       return 0;
+                       }
+               UBSEC_LIBNAME = (const char *)p;
+               return 1;
+       default:
+               break;
+               }
+       ENGINEerr(ENGINE_F_UBSEC_CTRL,ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+       return 0;
+       }
+
 static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
                const BIGNUM *m, BN_CTX *ctx)
        {