aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/crypto/c_src/crypto.c13
-rw-r--r--lib/crypto/doc/src/crypto.xml51
-rw-r--r--lib/crypto/src/crypto.erl42
-rw-r--r--lib/crypto/test/engine_SUITE.erl63
4 files changed, 161 insertions, 8 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 3914a48679..6957d25774 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -587,7 +587,7 @@ static ErlNifFunc nif_funcs[] = {
{"engine_finish_nif", 1, engine_finish_nif},
{"engine_free_nif", 1, engine_free_nif},
{"engine_load_dynamic_nif", 0, engine_load_dynamic_nif},
- {"engine_ctrl_cmd_strings_nif", 2, engine_ctrl_cmd_strings_nif},
+ {"engine_ctrl_cmd_strings_nif", 3, engine_ctrl_cmd_strings_nif},
{"engine_register_nif", 2, engine_register_nif},
{"engine_unregister_nif", 2, engine_unregister_nif},
{"engine_add_nif", 1, engine_add_nif},
@@ -4994,7 +4994,7 @@ static ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const
unsigned int cmds_len = 0;
char **cmds = NULL;
struct engine_ctx *ctx;
- int i;
+ int i, optional = 0;
// Get Engine
if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
@@ -5018,11 +5018,16 @@ static ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const
}
}
+ if(!enif_get_int(env, argv[2], &optional)) {
+ PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: Parameter optional not an integer");
+ return enif_make_badarg(env);
+ }
+
for(i = 0; i < cmds_len; i+=2) {
PRINTF_ERR2("Cmd: %s:%s\r\n",
cmds[i] ? cmds[i] : "(NULL)",
cmds[i+1] ? cmds[i+1] : "(NULL)");
- if(!ENGINE_ctrl_cmd_string(ctx->engine, cmds[i], cmds[i+1], 0)) {
+ if(!ENGINE_ctrl_cmd_string(ctx->engine, cmds[i], cmds[i+1], optional)) {
PRINTF_ERR2("Command failed: %s:%s\r\n",
cmds[i] ? cmds[i] : "(NULL)",
cmds[i+1] ? cmds[i+1] : "(NULL)");
@@ -5031,7 +5036,7 @@ static ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const
PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: {error, ctrl_cmd_failed}");
goto error;
}
-}
+ }
error:
for(i = 0; cmds != NULL && cmds[i] != NULL; i++)
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index dbc42812a8..464799b320 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -1060,6 +1060,57 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</desc>
</func>
+ <func>
+ <name>engine_ctrl_cmd_string(Engine, CmdName, CmdArg) -> Result</name>
+ <fsummary>Sends ctrl commands to an OpenSSL engine</fsummary>
+ <type>
+ <v>Engine = term()</v>
+ <v>CmdName = unicode:chardata()</v>
+ <v>CmdArg = unicode:chardata()</v>
+ <v>Result = ok | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>
+ Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>.
+ This function is the same as calling <c>engine_ctrl_cmd_string/4</c> with
+ <c>Optional</c> set to <c>false</c>.
+ </p>
+ <p>
+ The function throws a badarg if the parameters are in wrong format.
+ It may also throw the exception notsup in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) -> Result</name>
+ <fsummary>Sends ctrl commands to an OpenSSL engine</fsummary>
+ <type>
+ <v>Engine = term()</v>
+ <v>CmdName = unicode:chardata()</v>
+ <v>CmdArg = unicode:chardata()</v>
+ <v>Optional = boolean()</v>
+ <v>Result = ok | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>
+ Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>.
+ <c>Optional</c> is a boolean argument that can relax the semantics of the function.
+ If set to <c>true</c> it will only return failure if the ENGINE supported the given
+ command name but failed while executing it, if the ENGINE doesn't support the command
+ name it will simply return success without doing anything. In this case we assume
+ the user is only supplying commands specific to the given ENGINE so we set this to
+ <c>false</c>.
+ </p>
+ <p>
+ The function throws a badarg if the parameters are in wrong format.
+ It may also throw the exception notsup in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
</funcs>
<!-- Maybe put this in the users guide -->
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 641e526537..1a1b4f98b5 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -51,7 +51,9 @@
engine_load/3,
engine_load/4,
engine_unload/1,
- engine_list/0
+ engine_list/0,
+ engine_ctrl_cmd_string/3,
+ engine_ctrl_cmd_string/4
]).
-export_type([engine_ref/0,
@@ -648,7 +650,7 @@ engine_load(EngineId, PreCmds, PostCmds, EngineMethods) when is_list(PreCmds),
engine_load_1(Engine, PreCmds, PostCmds, EngineMethods) ->
try
- ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds))),
+ ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds), 0)),
ok = engine_nif_wrapper(engine_add_nif(Engine)),
ok = engine_nif_wrapper(engine_init_nif(Engine)),
engine_load_2(Engine, PostCmds, EngineMethods),
@@ -662,7 +664,7 @@ engine_load_1(Engine, PreCmds, PostCmds, EngineMethods) ->
engine_load_2(Engine, PostCmds, EngineMethods) ->
try
- ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PostCmds))),
+ ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PostCmds), 0)),
[ok = engine_nif_wrapper(engine_register_nif(Engine, engine_method_atom_to_int(Method))) ||
Method <- EngineMethods],
ok
@@ -728,6 +730,35 @@ engine_list(Engine0, IdList) ->
end
end.
+%%----------------------------------------------------------------------
+%% Function: engine_ctrl_cmd_string/3
+%%----------------------------------------------------------------------
+-spec engine_ctrl_cmd_string(Engine::term(),
+ CmdName::unicode:chardata(),
+ CmdArg::unicode:chardata()) ->
+ ok | {error, Reason::term()}.
+engine_ctrl_cmd_string(Engine, CmdName, CmdArg) ->
+ engine_ctrl_cmd_string(Engine, CmdName, CmdArg, false).
+
+%%----------------------------------------------------------------------
+%% Function: engine_ctrl_cmd_string/4
+%%----------------------------------------------------------------------
+-spec engine_ctrl_cmd_string(Engine::term(),
+ CmdName::unicode:chardata(),
+ CmdArg::unicode:chardata(),
+ Optional::boolean()) ->
+ ok | {error, Reason::term()}.
+engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
+ case engine_ctrl_cmd_strings_nif(Engine,
+ ensure_bin_cmds([{CmdName, CmdArg}]),
+ bool_to_int(Optional)) of
+ ok ->
+ ok;
+ notsup ->
+ erlang:error(notsup);
+ {error, Error} ->
+ {error, Error}
+ end.
%%--------------------------------------------------------------------
%%% On load
@@ -1227,7 +1258,7 @@ engine_init_nif(_Engine) -> ?nif_stub.
engine_finish_nif(_Engine) -> ?nif_stub.
engine_free_nif(_Engine) -> ?nif_stub.
engine_load_dynamic_nif() -> ?nif_stub.
-engine_ctrl_cmd_strings_nif(_Engine, _Cmds) -> ?nif_stub.
+engine_ctrl_cmd_strings_nif(_Engine, _Cmds, _Optional) -> ?nif_stub.
engine_add_nif(_Engine) -> ?nif_stub.
engine_remove_nif(_Engine) -> ?nif_stub.
engine_register_nif(_Engine, _EngineMethod) -> ?nif_stub.
@@ -1270,6 +1301,9 @@ engine_methods_convert_to_bitmask(engine_method_none, _BitMask) ->
engine_methods_convert_to_bitmask([M |Ms], BitMask) ->
engine_methods_convert_to_bitmask(Ms, BitMask bor engine_method_atom_to_int(M)).
+bool_to_int(true) -> 1;
+bool_to_int(false) -> 0.
+
engine_method_atom_to_int(engine_method_rsa) -> 16#0001;
engine_method_atom_to_int(engine_method_dsa) -> 16#0002;
engine_method_atom_to_int(engine_method_dh) -> 16#0004;
diff --git a/lib/crypto/test/engine_SUITE.erl b/lib/crypto/test/engine_SUITE.erl
index 06cce832ac..f206f967c7 100644
--- a/lib/crypto/test/engine_SUITE.erl
+++ b/lib/crypto/test/engine_SUITE.erl
@@ -44,6 +44,8 @@ all() ->
pre_command_fail_bad_value,
pre_command_fail_bad_key,
failed_engine_init,
+ ctrl_cmd_string,
+ ctrl_cmd_string_optional,
{group, engine_stored_key}
].
@@ -354,6 +356,67 @@ failed_engine_init(Config) when is_list(Config) ->
{skip, "Engine not supported on this OpenSSL version"}
end.
+
+ctrl_cmd_string()->
+ [{doc, "Test that a not known optional ctrl comand do not fail"}].
+ctrl_cmd_string(Config) when is_list(Config) ->
+ try
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ {<<"ID">>, <<"MD5">>},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ case crypto:engine_ctrl_cmd_string(E, <<"TEST">>, <<"17">>) of
+ ok ->
+ ct:fail(fail_ctrl_cmd_should_fail);
+ {error,ctrl_cmd_failed} ->
+ ok
+ end,
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this OpenSSL version"}
+ end.
+
+ctrl_cmd_string_optional()->
+ [{doc, "Test that a not known optional ctrl comand do not fail"}].
+ctrl_cmd_string_optional(Config) when is_list(Config) ->
+ try
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ {<<"ID">>, <<"MD5">>},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ case crypto:engine_ctrl_cmd_string(E, <<"TEST">>, <<"17">>, true) of
+ ok ->
+ ok;
+ _ ->
+ ct:fail(fail_ctrl_cmd_string)
+ end,
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this OpenSSL version"}
+ end.
+
%%%----------------------------------------------------------------
%%% Pub/priv key storage tests. Thoose are for testing the crypto.erl
%%% support for using priv/pub keys stored in an engine.