/* ENGINE flags that can be set by ENGINE_set_flags(). */
/* #define ENGINE_FLAGS_MALLOCED 0x0001 */ /* Not used */
+/* This flag is for ENGINEs that wish to handle the various 'CMD'-related
+ * control commands on their own. Without this flag, ENGINE_ctrl() handles these
+ * control commands on behalf of the ENGINE using their "cmd_defns" data. */
+#define ENGINE_FLAGS_MANUAL_CMD_CTRL (int)0x0002
+
+/* 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
+ * control command supports none of the _NUMERIC, _STRING, or _NO_INPUT options,
+ * then it is regarded as an "internal" control command - and not for use in
+ * config setting situations. As such, they're not available to the
+ * ENGINE_ctrl_cmd_string() function, only raw ENGINE_ctrl() access. Changes to
+ * this list of 'command types' should be reflected carefully in
+ * ENGINE_cmd_is_executable() and ENGINE_ctrl_cmd_string(). */
+
+/* accepts a 'long' input value (3rd parameter to ENGINE_ctrl) */
+#define ENGINE_CMD_FLAG_NUMERIC (unsigned int)0x0001
+/* accepts string input (cast from 'void*' to 'const char *', 4th parameter to
+ * ENGINE_ctrl) */
+#define ENGINE_CMD_FLAG_STRING (unsigned int)0x0002
+/* Indicates that the control command takes *no* input. Ie. the control command
+ * is unparameterised. */
+#define ENGINE_CMD_FLAG_NO_INPUT (unsigned int)0x0004
+
+/* NB: These 3 control commands are deprecated and should not be used. ENGINEs
+ * relying on these commands should compile conditional support for
+ * compatibility (eg. if these symbols are defined) but should also migrate the
+ * same functionality to their own ENGINE-specific control functions that can be
+ * "discovered" by calling applications. The fact these control commands
+ * wouldn't be "executable" (ie. usable by text-based config) doesn't change the
+ * fact that application code can find and use them without requiring per-ENGINE
+ * hacking. */
+
/* These flags are used to tell the ctrl function what should be done.
* All command numbers are shared between all engines, even if some don't
* make sense to some engines. In such a case, they do nothing but return
#define ENGINE_CTRL_HUP 3 /* Close and reinitialise any
handles/connections etc. */
+/* These control commands allow an application to deal with an arbitrary engine
+ * in a dynamic way. Warn: Negative return values indicate errors FOR THESE
+ * COMMANDS because zero is used to indicate 'end-of-list'. Other commands,
+ * including ENGINE-specific command types, return zero for an error.
+ *
+ * An ENGINE can choose to implement these ctrl functions, and can internally
+ * manage things however it chooses - it does so by setting the
+ * ENGINE_FLAGS_MANUAL_CMD_CTRL flag (using ENGINE_set_flags()). Otherwise the
+ * ENGINE_ctrl() code handles this on the ENGINE's behalf using the cmd_defns
+ * data (set using ENGINE_set_cmd_defns()). This means an ENGINE's ctrl()
+ * handler need only implement its own commands - the above "meta" commands will
+ * be taken care of. */
+
+/* Returns non-zero if the supplied ENGINE has a ctrl() handler. If "not", then
+ * all the remaining control commands will return failure, so it is worth
+ * checking this first if the caller is trying to "discover" the engine's
+ * capabilities and doesn't want errors generated unnecessarily. */
+#define ENGINE_CTRL_HAS_CTRL_FUNCTION 10
+/* Returns a positive command number for the first command supported by the
+ * engine. Returns zero if no ctrl commands are supported. */
+#define ENGINE_CTRL_GET_FIRST_CMD_TYPE 11
+/* The 'long' argument specifies a command implemented by the engine, and the
+ * return value is the next command supported, or zero if there are no more. */
+#define ENGINE_CTRL_GET_NEXT_CMD_TYPE 12
+/* The 'void*' argument is a command name (cast from 'const char *'), and the
+ * return value is the command that corresponds to it. */
+#define ENGINE_CTRL_GET_CMD_FROM_NAME 13
+/* The next two allow a command to be converted into its corresponding string
+ * form. In each case, the 'long' argument supplies the command. In the NAME_LEN
+ * case, the return value is the length of the command name (not counting a
+ * trailing EOL). In the NAME case, the 'void*' argument must be a string buffer
+ * large enough, and it will be populated with the name of the command (WITH a
+ * trailing EOL). */
+#define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD 14
+#define ENGINE_CTRL_GET_NAME_FROM_CMD 15
+/* The next two are similar but give a "short description" of a command. */
+#define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD 16
+#define ENGINE_CTRL_GET_DESC_FROM_CMD 17
+/* With this command, the return value is the OR'd combination of
+ * ENGINE_CMD_FLAG_*** values that indicate what kind of input a given
+ * engine-specific ctrl command expects. */
+#define ENGINE_CTRL_GET_CMD_FLAGS 18
+
+/* ENGINE implementations should start the numbering of their own control
+ * commands from this value. (ie. ENGINE_CMD_BASE, ENGINE_CMD_BASE + 1, etc). */
+#define ENGINE_CMD_BASE 200
+
+/* NB: These 2 nCipher "chil" control commands are deprecated, and their
+ * functionality is now available through ENGINE-specific control commands
+ * (exposed through the above-mentioned 'CMD'-handling). Code using these 2
+ * commands should be migrated to the more general command handling before these
+ * are removed. */
+
/* Flags specific to the nCipher "chil" engine */
#define ENGINE_CTRL_CHIL_SET_FORKCHECK 100
/* Depending on the value of the (long)i argument, this sets or
/* This prevents the initialisation function from providing mutex
* callbacks to the nCipher library. */
+/* If an ENGINE supports its own specific control commands and wishes the
+ * framework to handle the above 'ENGINE_CMD_***'-manipulation commands on its
+ * behalf, it should supply a null-terminated array of ENGINE_CMD_DEFN entries
+ * to ENGINE_set_cmd_defns(). It should also implement a ctrl() handler that
+ * supports the stated commands (ie. the "cmd_num" entries as described by the
+ * array). NB: The array must be ordered in increasing order of cmd_num.
+ * "null-terminated" means that the last ENGINE_CMD_DEFN element has cmd_num set
+ * to zero and/or cmd_name set to NULL. */
+typedef struct ENGINE_CMD_DEFN_st
+ {
+ unsigned int cmd_num; /* The command number */
+ const char *cmd_name; /* The command name itself */
+ const char *cmd_desc; /* A short description of the command */
+ unsigned int cmd_flags; /* The input the command expects */
+ } ENGINE_CMD_DEFN;
+
/* As we're missing a BIGNUM_METHOD, we need a couple of locally
* defined function types that engines can implement. */
/* Generic load_key function pointer */
typedef EVP_PKEY * (*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *, const char *);
-/* STRUCTURE functions ... all of these functions deal with pointers to
- * ENGINE structures where the pointers have a "structural reference".
- * This means that their reference is to allow access to the structure
- * but it does not imply that the structure is functional. To simply
- * increment or decrement the structural reference count, use ENGINE_new
- * and ENGINE_free. NB: This is not required when iterating using
- * ENGINE_get_next as it will automatically decrement the structural
- * reference count of the "current" ENGINE and increment the structural
- * reference count of the ENGINE it returns (unless it is NULL). */
+/* STRUCTURE functions ... all of these functions deal with pointers to ENGINE
+ * structures where the pointers have a "structural reference". This means that
+ * their reference is to allowed access to the structure but it does not imply
+ * that the structure is functional. To simply increment or decrement the
+ * structural reference count, use ENGINE_by_id and ENGINE_free. NB: This is not
+ * required when iterating using ENGINE_get_next as it will automatically
+ * decrement the structural reference count of the "current" ENGINE and
+ * increment the structural reference count of the ENGINE it returns (unless it
+ * is NULL). */
/* Get the first/last "ENGINE" type available. */
ENGINE *ENGINE_get_first(void);
void ENGINE_load_ubsec(void);
void ENGINE_load_builtin_engines(void);
+/* Send parametrised control commands to the engine. The possibilities to send
+ * down an integer, a pointer to data or a function pointer are provided. Any of
+ * the parameters may or may not be NULL, depending on the command number. In
+ * actuality, this function only requires a structural (rather than functional)
+ * reference to an engine, but many control commands may require the engine be
+ * functional. The caller should be aware of trying commands that require an
+ * operational ENGINE, and only use functional references in such situations. */
+int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
+
+/* This function tests if an ENGINE-specific command is usable as a "setting".
+ * Eg. in an application's config file that gets processed through
+ * ENGINE_ctrl_cmd_string(). If this returns zero, it is not available to
+ * ENGINE_ctrl_cmd_string(), only ENGINE_ctrl(). */
+int ENGINE_cmd_is_executable(ENGINE *e, int cmd);
+
+/* This function passes a command-name and argument to an ENGINE. The cmd_name
+ * is converted to a command number and the control command is called using
+ * 'arg' as an argument (unless the ENGINE doesn't support such a command, in
+ * which case no control command is called). The command is checked for input
+ * flags, and if necessary the argument will be converted to a numeric value. If
+ * cmd_optional is non-zero, then if the ENGINE doesn't support the given
+ * cmd_name the return value will be success anyway. This function is intended
+ * for applications to use so that users (or config files) can supply
+ * engine-specific config data to the ENGINE at run-time to control behaviour of
+ * specific engines. As such, it shouldn't be used for calling ENGINE_ctrl()
+ * functions that return data, deal with binary data, or that are otherwise
+ * supposed to be used directly through ENGINE_ctrl() in application code. Any
+ * "return" data from an ENGINE_ctrl() operation in this function will be lost -
+ * the return value is interpreted as failure if the return value is zero,
+ * success otherwise, and this function returns a boolean value as a result. In
+ * other words, vendors of 'ENGINE'-enabled devices should write ENGINE
+ * implementations with parameterisations that work in this scheme, so that
+ * compliant ENGINE-based applications can work consistently with the same
+ * configuration for the same ENGINE-enabled devices, across applications. */
+int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
+ int cmd_optional);
+
/* These functions are useful for manufacturing new ENGINE structures. They
* don't address reference counting at all - one uses them to populate an ENGINE
* structure with personalised implementations of things prior to using it
int ENGINE_set_load_privkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpriv_f);
int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f);
int ENGINE_set_flags(ENGINE *e, int flags);
+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 return values from within the ENGINE structure. These can be useful
ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e);
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);
/* FUNCTIONAL functions. These functions deal with ENGINE structures
* a corresponding call to ENGINE_free as it also releases a structural
* reference. */
int ENGINE_finish(ENGINE *e);
-/* Send control parametrised commands to the engine. The possibilities
- * to send down an integer, a pointer to data or a function pointer are
- * provided. Any of the parameters may or may not be NULL, depending
- * on the command number */
-/* WARNING: This is currently experimental and may change radically! */
-int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
/* The following functions handle keys that are stored in some secondary
* location, handled by the engine. The storage may be on a card or
/* Obligatory error function. */
void ERR_load_ENGINE_strings(void);
-/*
- * Error codes for all engine functions. NB: We use "generic"
- * function names instead of per-implementation ones because this
- * levels the playing field for externally implemented bootstrapped
- * support code. As the filename and line number is included, it's
- * more important to indicate the type of function, so that
- * bootstrapped code (that can't easily add its own errors in) can
- * use the same error codes too.
- */
-
/* 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.
*/
+void ERR_load_ENGINE_strings(void);
/* Error codes for the ENGINE functions. */
#define ENGINE_F_CSWIFT_RSA_MOD_EXP 104
#define ENGINE_F_ENGINE_ADD 105
#define ENGINE_F_ENGINE_BY_ID 106
+#define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE 170
#define ENGINE_F_ENGINE_CTRL 142
+#define ENGINE_F_ENGINE_CTRL_CMD_STRING 171
#define ENGINE_F_ENGINE_FINISH 107
#define ENGINE_F_ENGINE_FREE 108
#define ENGINE_F_ENGINE_GET_NEXT 115
#define ENGINE_F_HWCRHK_MOD_EXP_CRT 138
#define ENGINE_F_HWCRHK_RAND_BYTES 139
#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_FINISH 157
#define ENGINE_F_NURON_INIT 156
/* Reason codes. */
#define ENGINE_R_ALREADY_LOADED 100
+#define ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER 133
#define ENGINE_R_BIO_WAS_FREED 121
#define ENGINE_R_BN_CTX_FULL 101
#define ENGINE_R_BN_EXPAND_FAIL 102
#define ENGINE_R_CHIL_ERROR 123
+#define ENGINE_R_CMD_NOT_EXECUTABLE 134
+#define ENGINE_R_COMMAND_TAKES_INPUT 135
+#define ENGINE_R_COMMAND_TAKES_NO_INPUT 136
#define ENGINE_R_CONFLICTING_ENGINE_ID 103
#define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED 119
#define ENGINE_R_DSO_FAILURE 104
#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_CMD_NAME 137
+#define ENGINE_R_INVALID_CMD_NUMBER 138
#define ENGINE_R_MISSING_KEY_COMPONENTS 111
#define ENGINE_R_NOT_INITIALISED 117
#define ENGINE_R_NOT_LOADED 112
}
#endif
#endif
-
{ERR_PACK(0,ENGINE_F_CSWIFT_RSA_MOD_EXP,0), "CSWIFT_RSA_MOD_EXP"},
{ERR_PACK(0,ENGINE_F_ENGINE_ADD,0), "ENGINE_add"},
{ERR_PACK(0,ENGINE_F_ENGINE_BY_ID,0), "ENGINE_by_id"},
+{ERR_PACK(0,ENGINE_F_ENGINE_CMD_IS_EXECUTABLE,0), "ENGINE_cmd_is_executable"},
{ERR_PACK(0,ENGINE_F_ENGINE_CTRL,0), "ENGINE_ctrl"},
+{ERR_PACK(0,ENGINE_F_ENGINE_CTRL_CMD_STRING,0), "ENGINE_ctrl_cmd_string"},
{ERR_PACK(0,ENGINE_F_ENGINE_FINISH,0), "ENGINE_finish"},
{ERR_PACK(0,ENGINE_F_ENGINE_FREE,0), "ENGINE_free"},
{ERR_PACK(0,ENGINE_F_ENGINE_GET_NEXT,0), "ENGINE_get_next"},
{ERR_PACK(0,ENGINE_F_ENGINE_NEW,0), "ENGINE_new"},
{ERR_PACK(0,ENGINE_F_ENGINE_REMOVE,0), "ENGINE_remove"},
{ERR_PACK(0,ENGINE_F_ENGINE_SET_DEFAULT_TYPE,0), "ENGINE_SET_DEFAULT_TYPE"},
+{ERR_PACK(0,ENGINE_F_ENGINE_SET_ID,0), "ENGINE_set_id"},
+{ERR_PACK(0,ENGINE_F_ENGINE_SET_NAME,0), "ENGINE_set_name"},
{ERR_PACK(0,ENGINE_F_ENGINE_UNLOAD_KEY,0), "ENGINE_UNLOAD_KEY"},
{ERR_PACK(0,ENGINE_F_HWCRHK_CTRL,0), "HWCRHK_CTRL"},
{ERR_PACK(0,ENGINE_F_HWCRHK_FINISH,0), "HWCRHK_FINISH"},
{ERR_PACK(0,ENGINE_F_HWCRHK_MOD_EXP_CRT,0), "HWCRHK_MOD_EXP_CRT"},
{ERR_PACK(0,ENGINE_F_HWCRHK_RAND_BYTES,0), "HWCRHK_RAND_BYTES"},
{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_FINISH,0), "NURON_FINISH"},
{ERR_PACK(0,ENGINE_F_NURON_INIT,0), "NURON_INIT"},
static ERR_STRING_DATA ENGINE_str_reasons[]=
{
{ENGINE_R_ALREADY_LOADED ,"already loaded"},
+{ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER ,"argument is not a number"},
{ENGINE_R_BIO_WAS_FREED ,"bio was freed"},
{ENGINE_R_BN_CTX_FULL ,"BN_CTX full"},
{ENGINE_R_BN_EXPAND_FAIL ,"bn_expand fail"},
{ENGINE_R_CHIL_ERROR ,"chil error"},
+{ENGINE_R_CMD_NOT_EXECUTABLE ,"cmd not executable"},
+{ENGINE_R_COMMAND_TAKES_INPUT ,"command takes input"},
+{ENGINE_R_COMMAND_TAKES_NO_INPUT ,"command takes no input"},
{ENGINE_R_CONFLICTING_ENGINE_ID ,"conflicting engine id"},
{ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED ,"ctrl command not implemented"},
{ENGINE_R_DSO_FAILURE ,"DSO failure"},
{ENGINE_R_ID_OR_NAME_MISSING ,"'id' or 'name' missing"},
{ENGINE_R_INIT_FAILED ,"init failed"},
{ENGINE_R_INTERNAL_LIST_ERROR ,"internal list error"},
+{ENGINE_R_INVALID_CMD_NAME ,"invalid cmd name"},
+{ENGINE_R_INVALID_CMD_NUMBER ,"invalid cmd number"},
{ENGINE_R_MISSING_KEY_COMPONENTS ,"missing key components"},
{ENGINE_R_NOT_INITIALISED ,"not initialised"},
{ENGINE_R_NOT_LOADED ,"not loaded"},
ENGINE_CTRL_FUNC_PTR ctrl;
ENGINE_LOAD_KEY_PTR load_privkey;
ENGINE_LOAD_KEY_PTR load_pubkey;
+ const ENGINE_CMD_DEFN *cmd_defns;
int flags;
/* reference count on the structure itself */
int struct_ref;
* initialised to suitable start-up defaults. */
static int engine_def_flag = 0;
+/* When querying a ENGINE-specific control command's 'description', this string
+ * is used if the ENGINE_CMD_DEFN has cmd_desc set to NULL. */
+static const char *int_no_description = "";
+
/* This is used in certain static utility functions to save code
* repetition for per-algorithm functions. */
typedef enum {
return pkey;
}
+/* These internal functions handle 'CMD'-related control commands when the
+ * ENGINE in question has asked us to take care of it (ie. the ENGINE did not
+ * set the ENGINE_FLAGS_MANUAL_CMD_CTRL flag. */
+
+static int int_ctrl_cmd_is_null(const ENGINE_CMD_DEFN *defn)
+ {
+ if((defn->cmd_num == 0) || (defn->cmd_name == NULL))
+ return 1;
+ return 0;
+ }
+
+static int int_ctrl_cmd_by_name(const ENGINE_CMD_DEFN *defn, const char *s)
+ {
+ int idx = 0;
+ while(!int_ctrl_cmd_is_null(defn) && (strcmp(defn->cmd_name, s) != 0))
+ {
+ idx++;
+ defn++;
+ }
+ if(int_ctrl_cmd_is_null(defn))
+ /* The given name wasn't found */
+ return -1;
+ return idx;
+ }
+
+static int int_ctrl_cmd_by_num(const ENGINE_CMD_DEFN *defn, unsigned int num)
+ {
+ int idx = 0;
+ /* NB: It is stipulated that 'cmd_defn' lists are ordered by cmd_num. So
+ * our searches don't need to take any longer than necessary. */
+ while(!int_ctrl_cmd_is_null(defn) && (defn->cmd_num < num))
+ {
+ idx++;
+ defn++;
+ }
+ if(defn->cmd_num == num)
+ return idx;
+ /* The given cmd_num wasn't found */
+ return -1;
+ }
+
+static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p, void (*f)())
+ {
+ int idx;
+ char *s = (char *)p;
+ /* Take care of the easy one first (eg. it requires no searches) */
+ if(cmd == ENGINE_CTRL_GET_FIRST_CMD_TYPE)
+ {
+ if((e->cmd_defns == NULL) || int_ctrl_cmd_is_null(e->cmd_defns))
+ return 0;
+ return e->cmd_defns->cmd_num;
+ }
+ /* One or two commands require that "p" be a valid string buffer */
+ if((cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) ||
+ (cmd == ENGINE_CTRL_GET_NAME_FROM_CMD) ||
+ (cmd == ENGINE_CTRL_GET_DESC_FROM_CMD))
+ {
+ if(s == NULL)
+ {
+ ENGINEerr(ENGINE_F_INT_CTRL_HELPER,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+ }
+ /* Now handle cmd_name -> cmd_num conversion */
+ if(cmd == ENGINE_CTRL_GET_CMD_FROM_NAME)
+ {
+ if((e->cmd_defns == NULL) || ((idx = int_ctrl_cmd_by_name(
+ e->cmd_defns, s)) < 0))
+ {
+ ENGINEerr(ENGINE_F_INT_CTRL_HELPER,
+ ENGINE_R_INVALID_CMD_NAME);
+ return -1;
+ }
+ return e->cmd_defns[idx].cmd_num;
+ }
+ /* For the rest of the commands, the 'long' argument must specify a
+ * valie command number - so we need to conduct a search. */
+ if((e->cmd_defns == NULL) || ((idx = int_ctrl_cmd_by_num(e->cmd_defns,
+ (unsigned int)i)) < 0))
+ {
+ ENGINEerr(ENGINE_F_INT_CTRL_HELPER,
+ ENGINE_R_INVALID_CMD_NUMBER);
+ return -1;
+ }
+ /* Now the logic splits depending on command type */
+ switch(cmd)
+ {
+ case ENGINE_CTRL_GET_NEXT_CMD_TYPE:
+ idx++;
+ if(int_ctrl_cmd_is_null(e->cmd_defns + idx))
+ /* end-of-list */
+ return 0;
+ else
+ return e->cmd_defns[idx].cmd_num;
+ case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD:
+ return strlen(e->cmd_defns[idx].cmd_name);
+ case ENGINE_CTRL_GET_NAME_FROM_CMD:
+ return sprintf(s, "%s", e->cmd_defns[idx].cmd_name);
+ case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD:
+ if(e->cmd_defns[idx].cmd_desc)
+ return strlen(e->cmd_defns[idx].cmd_desc);
+ return strlen(int_no_description);
+ case ENGINE_CTRL_GET_DESC_FROM_CMD:
+ if(e->cmd_defns[idx].cmd_desc)
+ return sprintf(s, "%s", e->cmd_defns[idx].cmd_desc);
+ return sprintf(s, "%s", int_no_description);
+ case ENGINE_CTRL_GET_CMD_FLAGS:
+ return e->cmd_defns[idx].cmd_flags;
+ }
+ /* Shouldn't really be here ... */
+ ENGINEerr(ENGINE_F_INT_CTRL_HELPER,ENGINE_R_INTERNAL_LIST_ERROR);
+ return -1;
+ }
+
int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
{
int ctrl_exists, ref_exists;
}
CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
ref_exists = ((e->struct_ref > 0) ? 1 : 0);
- ctrl_exists = (e->ctrl ? 1 : 0);
CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ ctrl_exists = ((e->ctrl == NULL) ? 0 : 1);
if(!ref_exists)
{
ENGINEerr(ENGINE_F_ENGINE_CTRL,ENGINE_R_NO_REFERENCE);
return 0;
}
- if (!ctrl_exists)
+ /* Intercept any "root-level" commands before trying to hand them on to
+ * ctrl() handlers. */
+ switch(cmd)
+ {
+ case ENGINE_CTRL_HAS_CTRL_FUNCTION:
+ return ctrl_exists;
+ case ENGINE_CTRL_GET_FIRST_CMD_TYPE:
+ case ENGINE_CTRL_GET_NEXT_CMD_TYPE:
+ case ENGINE_CTRL_GET_CMD_FROM_NAME:
+ case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD:
+ case ENGINE_CTRL_GET_NAME_FROM_CMD:
+ case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD:
+ case ENGINE_CTRL_GET_DESC_FROM_CMD:
+ case ENGINE_CTRL_GET_CMD_FLAGS:
+ if(ctrl_exists && !(e->flags & ENGINE_FLAGS_MANUAL_CMD_CTRL))
+ return int_ctrl_helper(e,cmd,i,p,f);
+ if(!ctrl_exists)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL,ENGINE_R_NO_CONTROL_FUNCTION);
+ /* For these cmd-related functions, failure is indicated
+ * by a -1 return value (because 0 is used as a valid
+ * return in some places). */
+ return -1;
+ }
+ default:
+ break;
+ }
+ /* Anything else requires a ctrl() handler to exist. */
+ if(!ctrl_exists)
{
ENGINEerr(ENGINE_F_ENGINE_CTRL,ENGINE_R_NO_CONTROL_FUNCTION);
return 0;
return e->ctrl(e, cmd, i, p, f);
}
+int ENGINE_cmd_is_executable(ENGINE *e, int cmd)
+ {
+ int flags;
+ if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, cmd, NULL, NULL)) < 0)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CMD_IS_EXECUTABLE,
+ ENGINE_R_INVALID_CMD_NUMBER);
+ return 0;
+ }
+ if(!(flags & ENGINE_CMD_FLAG_NO_INPUT) &&
+ !(flags & ENGINE_CMD_FLAG_NUMERIC) &&
+ !(flags & ENGINE_CMD_FLAG_STRING))
+ return 0;
+ return 1;
+ }
+
+int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
+ int cmd_optional)
+ {
+ int num, flags;
+ long l;
+ char *ptr;
+ if((e == NULL) || (cmd_name == NULL))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if((e->ctrl == NULL) || ((num = ENGINE_ctrl(e,
+ ENGINE_CTRL_GET_CMD_FROM_NAME,
+ 0, (void *)cmd_name, NULL)) <= 0))
+ {
+ /* If the command didn't *have* to be supported, we fake
+ * success. This allows certain settings to be specified for
+ * multiple ENGINEs and only require a change of ENGINE id
+ * (without having to selectively apply settings). Eg. changing
+ * from a hardware device back to the regular software ENGINE
+ * without editing the config file, etc. */
+ if(cmd_optional)
+ {
+ ERR_clear_error();
+ return 1;
+ }
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_INVALID_CMD_NAME);
+ return 0;
+ }
+ if(!ENGINE_cmd_is_executable(e, num))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_CMD_NOT_EXECUTABLE);
+ return 0;
+ }
+ if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, NULL, NULL)) < 0)
+ {
+ /* Shouldn't happen, given that ENGINE_cmd_is_executable()
+ * returned success. */
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_INTERNAL_LIST_ERROR);
+ return 0;
+ }
+ /* If the command takes no input, there must be no input. And vice
+ * versa. */
+ if(flags & ENGINE_CMD_FLAG_NO_INPUT)
+ {
+ if(arg != NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_COMMAND_TAKES_NO_INPUT);
+ return 0;
+ }
+ /* We deliberately force the result of ENGINE_ctrl() to 0 or 1
+ * rather than returning it as "return data". This is to ensure
+ * usage of these commands is consistent across applications and
+ * that certain applications don't understand it one way, and
+ * others another. */
+ if(ENGINE_ctrl(e, num, 0, (void *)arg, NULL))
+ return 1;
+ return 0;
+ }
+ /* So, we require input */
+ if(arg == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_COMMAND_TAKES_INPUT);
+ return 0;
+ }
+ /* If it takes string input, that's easy */
+ if(flags & ENGINE_CMD_FLAG_STRING)
+ {
+ /* Same explanation as above */
+ if(ENGINE_ctrl(e, num, 0, (void *)arg, NULL))
+ return 1;
+ return 0;
+ }
+ /* If it doesn't take numeric either, then it is unsupported for use in
+ * a config-setting situation, which is what this function is for. This
+ * should never happen though, because ENGINE_cmd_is_executable() was
+ * used. */
+ if(!(flags & ENGINE_CMD_FLAG_NUMERIC))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_INTERNAL_LIST_ERROR);
+ return 0;
+ }
+ l = strtol(arg, &ptr, 10);
+ if((arg == ptr) || (*ptr != '\0'))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER);
+ return 0;
+ }
+ /* Force the result of the control command to 0 or 1, for the reasons
+ * mentioned before. */
+ if(ENGINE_ctrl(e, num, l, NULL, NULL))
+ return 1;
+ return 0;
+ }
+
static ENGINE *engine_get_default_type(ENGINE_TYPE t)
{
ENGINE *ret = NULL;
return 1;
}
+int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns)
+ {
+ e->cmd_defns = defns;
+ return 1;
+ }
+
int ENGINE_cpy(ENGINE *dest, const ENGINE *src)
{
if(ENGINE_set_id(dest, ENGINE_get_id(src)) &&
ENGINE_get_load_privkey_function(src)) &&
ENGINE_set_load_pubkey_function(dest,
ENGINE_get_load_pubkey_function(src)) &&
- ENGINE_set_flags(dest, ENGINE_get_flags(src)))
+ ENGINE_set_flags(dest, ENGINE_get_flags(src)) &&
+ ENGINE_set_cmd_defns(dest, ENGINE_get_cmd_defns(src)))
return 1;
return 0;
}
{
return e->flags;
}
+
+const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e)
+ {
+ return e->cmd_defns;
+ }