2 * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
10 #include "eng_local.h"
13 * When querying a ENGINE-specific control command's 'description', this
14 * string is used if the ENGINE_CMD_DEFN has cmd_desc set to NULL.
16 static const char *int_no_description
= "";
19 * These internal functions handle 'CMD'-related control commands when the
20 * ENGINE in question has asked us to take care of it (ie. the ENGINE did not
21 * set the ENGINE_FLAGS_MANUAL_CMD_CTRL flag.
24 static int int_ctrl_cmd_is_null(const ENGINE_CMD_DEFN
*defn
)
26 if ((defn
->cmd_num
== 0) || (defn
->cmd_name
== NULL
))
31 static int int_ctrl_cmd_by_name(const ENGINE_CMD_DEFN
*defn
, const char *s
)
34 while (!int_ctrl_cmd_is_null(defn
) && (strcmp(defn
->cmd_name
, s
) != 0)) {
38 if (int_ctrl_cmd_is_null(defn
))
39 /* The given name wasn't found */
44 static int int_ctrl_cmd_by_num(const ENGINE_CMD_DEFN
*defn
, unsigned int num
)
48 * NB: It is stipulated that 'cmd_defn' lists are ordered by cmd_num. So
49 * our searches don't need to take any longer than necessary.
51 while (!int_ctrl_cmd_is_null(defn
) && (defn
->cmd_num
< num
)) {
55 if (defn
->cmd_num
== num
)
57 /* The given cmd_num wasn't found */
61 static int int_ctrl_helper(ENGINE
*e
, int cmd
, long i
, void *p
,
66 const ENGINE_CMD_DEFN
*cdp
;
68 /* Take care of the easy one first (eg. it requires no searches) */
69 if (cmd
== ENGINE_CTRL_GET_FIRST_CMD_TYPE
) {
70 if ((e
->cmd_defns
== NULL
) || int_ctrl_cmd_is_null(e
->cmd_defns
))
72 return e
->cmd_defns
->cmd_num
;
74 /* One or two commands require that "p" be a valid string buffer */
75 if ((cmd
== ENGINE_CTRL_GET_CMD_FROM_NAME
) ||
76 (cmd
== ENGINE_CTRL_GET_NAME_FROM_CMD
) ||
77 (cmd
== ENGINE_CTRL_GET_DESC_FROM_CMD
)) {
79 ENGINEerr(ENGINE_F_INT_CTRL_HELPER
, ERR_R_PASSED_NULL_PARAMETER
);
83 /* Now handle cmd_name -> cmd_num conversion */
84 if (cmd
== ENGINE_CTRL_GET_CMD_FROM_NAME
) {
85 if ((e
->cmd_defns
== NULL
)
86 || ((idx
= int_ctrl_cmd_by_name(e
->cmd_defns
, s
)) < 0)) {
87 ENGINEerr(ENGINE_F_INT_CTRL_HELPER
, ENGINE_R_INVALID_CMD_NAME
);
90 return e
->cmd_defns
[idx
].cmd_num
;
93 * For the rest of the commands, the 'long' argument must specify a valid
94 * command number - so we need to conduct a search.
96 if ((e
->cmd_defns
== NULL
)
97 || ((idx
= int_ctrl_cmd_by_num(e
->cmd_defns
, (unsigned int)i
)) < 0)) {
98 ENGINEerr(ENGINE_F_INT_CTRL_HELPER
, ENGINE_R_INVALID_CMD_NUMBER
);
101 /* Now the logic splits depending on command type */
102 cdp
= &e
->cmd_defns
[idx
];
104 case ENGINE_CTRL_GET_NEXT_CMD_TYPE
:
106 return int_ctrl_cmd_is_null(cdp
) ? 0 : cdp
->cmd_num
;
107 case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD
:
108 return strlen(cdp
->cmd_name
);
109 case ENGINE_CTRL_GET_NAME_FROM_CMD
:
110 return strlen(strcpy(s
, cdp
->cmd_name
));
111 case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD
:
112 return strlen(cdp
->cmd_desc
== NULL
? int_no_description
114 case ENGINE_CTRL_GET_DESC_FROM_CMD
:
115 return strlen(strcpy(s
, cdp
->cmd_desc
== NULL
? int_no_description
117 case ENGINE_CTRL_GET_CMD_FLAGS
:
118 return cdp
->cmd_flags
;
120 /* Shouldn't really be here ... */
121 ENGINEerr(ENGINE_F_INT_CTRL_HELPER
, ENGINE_R_INTERNAL_LIST_ERROR
);
125 int ENGINE_ctrl(ENGINE
*e
, int cmd
, long i
, void *p
, void (*f
) (void))
127 int ctrl_exists
, ref_exists
;
129 ENGINEerr(ENGINE_F_ENGINE_CTRL
, ERR_R_PASSED_NULL_PARAMETER
);
132 CRYPTO_THREAD_write_lock(global_engine_lock
);
133 ref_exists
= ((e
->struct_ref
> 0) ? 1 : 0);
134 CRYPTO_THREAD_unlock(global_engine_lock
);
135 ctrl_exists
= ((e
->ctrl
== NULL
) ? 0 : 1);
137 ENGINEerr(ENGINE_F_ENGINE_CTRL
, ENGINE_R_NO_REFERENCE
);
141 * Intercept any "root-level" commands before trying to hand them on to
145 case ENGINE_CTRL_HAS_CTRL_FUNCTION
:
147 case ENGINE_CTRL_GET_FIRST_CMD_TYPE
:
148 case ENGINE_CTRL_GET_NEXT_CMD_TYPE
:
149 case ENGINE_CTRL_GET_CMD_FROM_NAME
:
150 case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD
:
151 case ENGINE_CTRL_GET_NAME_FROM_CMD
:
152 case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD
:
153 case ENGINE_CTRL_GET_DESC_FROM_CMD
:
154 case ENGINE_CTRL_GET_CMD_FLAGS
:
155 if (ctrl_exists
&& !(e
->flags
& ENGINE_FLAGS_MANUAL_CMD_CTRL
))
156 return int_ctrl_helper(e
, cmd
, i
, p
, f
);
158 ENGINEerr(ENGINE_F_ENGINE_CTRL
, ENGINE_R_NO_CONTROL_FUNCTION
);
160 * For these cmd-related functions, failure is indicated by a -1
161 * return value (because 0 is used as a valid return in some
169 /* Anything else requires a ctrl() handler to exist. */
171 ENGINEerr(ENGINE_F_ENGINE_CTRL
, ENGINE_R_NO_CONTROL_FUNCTION
);
174 return e
->ctrl(e
, cmd
, i
, p
, f
);
177 int ENGINE_cmd_is_executable(ENGINE
*e
, int cmd
)
181 ENGINE_ctrl(e
, ENGINE_CTRL_GET_CMD_FLAGS
, cmd
, NULL
, NULL
)) < 0) {
182 ENGINEerr(ENGINE_F_ENGINE_CMD_IS_EXECUTABLE
,
183 ENGINE_R_INVALID_CMD_NUMBER
);
186 if (!(flags
& ENGINE_CMD_FLAG_NO_INPUT
) &&
187 !(flags
& ENGINE_CMD_FLAG_NUMERIC
) &&
188 !(flags
& ENGINE_CMD_FLAG_STRING
))
193 int ENGINE_ctrl_cmd(ENGINE
*e
, const char *cmd_name
,
194 long i
, void *p
, void (*f
) (void), int cmd_optional
)
198 if (e
== NULL
|| cmd_name
== NULL
) {
199 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD
, ERR_R_PASSED_NULL_PARAMETER
);
203 || (num
= ENGINE_ctrl(e
, ENGINE_CTRL_GET_CMD_FROM_NAME
,
204 0, (void *)cmd_name
, NULL
)) <= 0) {
206 * If the command didn't *have* to be supported, we fake success.
207 * This allows certain settings to be specified for multiple ENGINEs
208 * and only require a change of ENGINE id (without having to
209 * selectively apply settings). Eg. changing from a hardware device
210 * back to the regular software ENGINE without editing the config
217 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD
, ENGINE_R_INVALID_CMD_NAME
);
221 * Force the result of the control command to 0 or 1, for the reasons
224 if (ENGINE_ctrl(e
, num
, i
, p
, f
) > 0)
229 int ENGINE_ctrl_cmd_string(ENGINE
*e
, const char *cmd_name
, const char *arg
,
236 if (e
== NULL
|| cmd_name
== NULL
) {
237 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING
, ERR_R_PASSED_NULL_PARAMETER
);
241 || (num
= ENGINE_ctrl(e
, ENGINE_CTRL_GET_CMD_FROM_NAME
,
242 0, (void *)cmd_name
, NULL
)) <= 0) {
244 * If the command didn't *have* to be supported, we fake success.
245 * This allows certain settings to be specified for multiple ENGINEs
246 * and only require a change of ENGINE id (without having to
247 * selectively apply settings). Eg. changing from a hardware device
248 * back to the regular software ENGINE without editing the config
255 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING
, ENGINE_R_INVALID_CMD_NAME
);
258 if (!ENGINE_cmd_is_executable(e
, num
)) {
259 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING
,
260 ENGINE_R_CMD_NOT_EXECUTABLE
);
264 flags
= ENGINE_ctrl(e
, ENGINE_CTRL_GET_CMD_FLAGS
, num
, NULL
, NULL
);
267 * Shouldn't happen, given that ENGINE_cmd_is_executable() returned
270 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING
,
271 ENGINE_R_INTERNAL_LIST_ERROR
);
275 * If the command takes no input, there must be no input. And vice versa.
277 if (flags
& ENGINE_CMD_FLAG_NO_INPUT
) {
279 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING
,
280 ENGINE_R_COMMAND_TAKES_NO_INPUT
);
284 * We deliberately force the result of ENGINE_ctrl() to 0 or 1 rather
285 * than returning it as "return data". This is to ensure usage of
286 * these commands is consistent across applications and that certain
287 * applications don't understand it one way, and others another.
289 if (ENGINE_ctrl(e
, num
, 0, (void *)arg
, NULL
) > 0)
293 /* So, we require input */
295 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING
,
296 ENGINE_R_COMMAND_TAKES_INPUT
);
299 /* If it takes string input, that's easy */
300 if (flags
& ENGINE_CMD_FLAG_STRING
) {
301 /* Same explanation as above */
302 if (ENGINE_ctrl(e
, num
, 0, (void *)arg
, NULL
) > 0)
307 * If it doesn't take numeric either, then it is unsupported for use in a
308 * config-setting situation, which is what this function is for. This
309 * should never happen though, because ENGINE_cmd_is_executable() was
312 if (!(flags
& ENGINE_CMD_FLAG_NUMERIC
)) {
313 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING
,
314 ENGINE_R_INTERNAL_LIST_ERROR
);
317 l
= strtol(arg
, &ptr
, 10);
318 if ((arg
== ptr
) || (*ptr
!= '\0')) {
319 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING
,
320 ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER
);
324 * Force the result of the control command to 0 or 1, for the reasons
327 if (ENGINE_ctrl(e
, num
, l
, NULL
, NULL
) > 0)