aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLars Thorsen <[email protected]>2018-08-23 10:17:12 +0200
committerLars Thorsen <[email protected]>2018-08-23 10:17:12 +0200
commit4479223613dc6a0e82059c310b13fd072b9e31a3 (patch)
treeb4a9c8b3c92113d31353ba5a66b1813bc24d498c /lib
parent5ed84b869a3f54a7132932226a72b6f5dd6f7457 (diff)
parent8bb0d5d4049b6b2ec41f6cc3e154e9f688029bef (diff)
downloadotp-4479223613dc6a0e82059c310b13fd072b9e31a3.tar.gz
otp-4479223613dc6a0e82059c310b13fd072b9e31a3.tar.bz2
otp-4479223613dc6a0e82059c310b13fd072b9e31a3.zip
Merge branch 'maint-20' into maint
* maint-20: Updated OTP version Prepare release Updated the engine load functionality Clean up bag index tables Conflicts: OTP_VERSION lib/crypto/c_src/crypto.c lib/crypto/doc/src/notes.xml lib/crypto/vsn.mk lib/mnesia/doc/src/notes.xml lib/mnesia/vsn.mk otp_versions.table
Diffstat (limited to 'lib')
-rw-r--r--lib/crypto/c_src/crypto.c52
-rw-r--r--lib/crypto/doc/src/crypto.xml261
-rw-r--r--lib/crypto/doc/src/engine_load.xml31
-rw-r--r--lib/crypto/src/crypto.erl172
-rw-r--r--lib/crypto/test/engine_SUITE.erl278
-rw-r--r--lib/mnesia/src/mnesia_index.erl2
-rw-r--r--lib/mnesia/test/mnesia_evil_coverage_test.erl58
7 files changed, 745 insertions, 109 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 68d2c44b5e..72aa44e7db 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -537,6 +537,7 @@ static ERL_NIF_TERM engine_remove_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
static ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
/* helpers */
@@ -626,6 +627,7 @@ static ErlNifFunc nif_funcs[] = {
{"engine_get_first_nif", 0, engine_get_first_nif},
{"engine_get_next_nif", 1, engine_get_next_nif},
{"engine_get_id_nif", 1, engine_get_id_nif},
+ {"engine_get_name_nif", 1, engine_get_name_nif},
{"engine_get_all_methods_nif", 0, engine_get_all_methods_nif}
};
@@ -4967,7 +4969,7 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
} else {
/* non-evp rsa private decrypt */
i = RSA_private_decrypt(in_bin.size, in_bin.data,
- out_bin.data, rsa, crypt_opt.rsa_padding);
+ out_bin.data, rsa, crypt_opt.rsa_padding);
if (i > 0) {
ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i);
enif_realloc_binary(&out_bin, i);
@@ -4985,7 +4987,7 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
} else {
/* non-evp rsa public decrypt */
i = RSA_public_decrypt(in_bin.size, in_bin.data,
- out_bin.data, rsa, crypt_opt.rsa_padding);
+ out_bin.data, rsa, crypt_opt.rsa_padding);
if (i > 0) {
ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i);
enif_realloc_binary(&out_bin, i);
@@ -5103,7 +5105,7 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI
/ * Example of result:
{
Curve = {Field, Prime, Point, Order, CoFactor} =
- {
+ {
Field = {prime_field,<<255,...,255>>},
Prime = {<<255,...,252>>,
<<90,...,75>>,
@@ -5116,9 +5118,9 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI
Key = <<151,...,62>>
}
or
- {
+ {
Curve =
- {characteristic_two_field,
+ {characteristic_two_field,
M,
Basis = {tpbasis, _}
| {ppbasis, k1, k2, k3}
@@ -5131,7 +5133,7 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI
*/
#endif
}
-
+
if (pkey) EVP_PKEY_free(pkey);
return enif_make_badarg(env);
}
@@ -5312,7 +5314,7 @@ static ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const
error:
for(i = 0; cmds != NULL && cmds[i] != NULL; i++)
- enif_free(cmds[i]);
+ enif_free(cmds[i]);
enif_free(cmds);
return ret;
#else
@@ -5630,7 +5632,7 @@ static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
if (!engine_id) {
enif_alloc_binary(0, &engine_id_bin);
engine_id_bin.size = 0;
- return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_id_bin));
+ return enif_make_binary(env, &engine_id_bin);
}
size = strlen(engine_id);
@@ -5638,7 +5640,39 @@ static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
engine_id_bin.size = size;
memcpy(engine_id_bin.data, engine_id, size);
- return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_id_bin));
+ return enif_make_binary(env, &engine_id_bin);
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ ErlNifBinary engine_name_bin;
+ const char *engine_name;
+ int size;
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_get_id_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ engine_name = ENGINE_get_name(ctx->engine);
+ if (!engine_name) {
+ enif_alloc_binary(0, &engine_name_bin);
+ engine_name_bin.size = 0;
+ return enif_make_binary(env, &engine_name_bin);
+ }
+
+ size = strlen(engine_name);
+ enif_alloc_binary(size, &engine_name_bin);
+ engine_name_bin.size = size;
+ memcpy(engine_name_bin.data, engine_name, size);
+
+ return enif_make_binary(env, &engine_name_bin);
#else
return atom_notsup;
#endif
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 42e411a0e3..e6147ddffc 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -143,7 +143,7 @@
password => password()}</code>
<code>engine_ref() = term()</code>
- <p>The result of a call to <seealso marker="#engine_load-3">engine_load/3</seealso>.
+ <p>The result of a call to for example <seealso marker="#engine_load-3">engine_load/3</seealso>.
</p>
<code>key_id() = string() | binary()</code>
@@ -629,7 +629,7 @@
<desc>
<p>Fetches the corresponding public key from a private key stored in an Engine.
The key must be of the type indicated by the Type parameter.
- </p>
+ </p>
</desc>
</func>
@@ -1075,8 +1075,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<p>
Returns a list of all possible engine methods.
</p>
- <p>
- May throw exception notsup in case there is
+ <p>
+ May throw exception notsup in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1092,18 +1092,18 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<type>
<v>EngineId = unicode:chardata()</v>
<v>PreCmds, PostCmds = [{unicode:chardata(), unicode:chardata()}]</v>
- <v>Result = {ok, Engine::term()} | {error, Reason::term()}</v>
+ <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
</type>
<desc>
<p>
Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and
- an engine handle. This function is the same as calling <c>engine_load/4</c> with
- <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ an engine handle. This function is the same as calling <c>engine_load/4</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
returned if the engine can't be loaded.
</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
+ It may also throw the exception notsup in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1120,7 +1120,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<v>EngineId = unicode:chardata()</v>
<v>PreCmds, PostCmds = [{unicode:chardata(), unicode:chardata()}]</v>
<v>EngineMethods = [engine_method_type()]</v>
- <v>Result = {ok, Engine::term()} | {error, Reason::term()}</v>
+ <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
</type>
<desc>
<p>
@@ -1129,7 +1129,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</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
+ It may also throw the exception notsup in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1143,17 +1143,17 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<name>engine_unload(Engine) -> Result</name>
<fsummary>Dynamical load an encryption engine</fsummary>
<type>
- <v>Engine = term()</v>
+ <v>Engine = engine_ref()</v>
<v>Result = ok | {error, Reason::term()}</v>
</type>
<desc>
<p>
- Unloads the OpenSSL engine given by <c>EngineId</c>.
+ Unloads the OpenSSL engine given by <c>Engine</c>.
An error tuple is returned if the engine can't be unloaded.
</p>
<p>
The function throws a badarg if the parameter is in wrong format.
- It may also throw the exception notsup in case there is
+ It may also throw the exception notsup in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1164,19 +1164,24 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_list() -> Result</name>
- <fsummary>List the known engine ids</fsummary>
+ <name>engine_by_id(EngineId) -> Result</name>
+ <fsummary>Get a reference to an already loaded engine</fsummary>
<type>
- <v>Result = [EngineId::unicode:chardata()]</v>
+ <v>EngineID = unicode:chardata()engine_ref()</v>
+ <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
</type>
<desc>
- <p>List the id's of all engines in OpenSSL's internal list.</p>
<p>
- It may also throw the exception notsup in case there is
+ Get a reference to an already loaded engine with <c>EngineId</c>.
+ An error tuple is returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function throws a badarg if the parameter is in wrong format.
+ It may also throw the exception notsup in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
- See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
in the User's Guide.
</p>
</desc>
@@ -1186,7 +1191,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<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>Engine = engine_ref()</v>
<v>CmdName = unicode:chardata()</v>
<v>CmdArg = unicode:chardata()</v>
<v>Result = ok | {error, Reason::term()}</v>
@@ -1194,12 +1199,12 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<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
+ 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
+ It may also throw the exception notsup in case there is
no engine support in the underlying OpenSSL implementation.
</p>
</desc>
@@ -1209,7 +1214,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<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>Engine = engine_ref()</v>
<v>CmdName = unicode:chardata()</v>
<v>CmdArg = unicode:chardata()</v>
<v>Optional = boolean()</v>
@@ -1218,18 +1223,218 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<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
+ <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
+ 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_add(Engine) -> Result</name>
+ <fsummary>Add engine to OpenSSL internal list</fsummary>
+ <type>
+ <v>Engine = engine_ref()</v>
+ <v>Result = ok | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>Add the engine to OpenSSL's internal list.</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_remove(Engine) -> Result</name>
+ <fsummary>Remove engine to OpenSSL internal list</fsummary>
+ <type>
+ <v>Engine = engine_ref()</v>
+ <v>Result = ok | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>Remove the engine from OpenSSL's internal list.</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_get_id(Engine) -> EngineId</name>
+ <fsummary>Fetch engine ID</fsummary>
+ <type>
+ <v>Engine = engine_ref()</v>
+ <v>EngineId = unicode:chardata()</v>
+ </type>
+ <desc>
+ <p>Return the ID for the engine, or an empty binary if there is no id set.</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_get_name(Engine) -> EngineName</name>
+ <fsummary>Fetch engine name</fsummary>
+ <type>
+ <v>Engine = engine_ref()</v>
+ <v>EngineName = unicode:chardata()</v>
+ </type>
+ <desc>
+ <p>Return the name (eg a description) for the engine, or an empty binary if there is no name set.</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_list() -> Result</name>
+ <fsummary>List the known engine ids</fsummary>
+ <type>
+ <v>Result = [EngineId::unicode:chardata()]</v>
+ </type>
+ <desc>
+ <p>List the id's of all engines in OpenSSL's internal list.</p>
+ <p>
+ It may also throw the exception notsup in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ <p>
+ May throw exception notsup in case engine functionality is not supported by the underlying
+ OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>ensure_engine_loaded(EngineId, LibPath) -> Result</name>
+ <fsummary>Ensure encryption engine just loaded once</fsummary>
+ <type>
+ <v>EngineId = unicode:chardata()</v>
+ <v>LibPath = unicode:chardata()</v>
+ <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>
+ Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
+ implementing the engine. This function is the same as calling <c>ensure_engine_loaded/3</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ returned if the engine can't be loaded.
+ </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>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>ensure_engine_loaded(EngineId, LibPath, EngineMethods) -> Result</name>
+ <fsummary>Ensure encryption engine just loaded once</fsummary>
+ <type>
+ <v>EngineId = unicode:chardata()</v>
+ <v>LibPath = unicode:chardata()</v>
+ <v>EngineMethods = [engine_method_type()]</v>
+ <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>
+ Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
+ implementing the engine. This function differs from the normal engine_load in that sense it
+ also add the engine id to the internal list in OpenSSL. Then in the following calls to the function
+ it just fetch the reference to the engine instead of loading it again.
+ An error tuple is returned if the engine can't be loaded.
+ </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>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>ensure_engine_unloaded(Engine) -> Result</name>
+ <fsummary>Unload an engine loaded with the ensure function</fsummary>
+ <type>
+ <v>Engine = engine_ref()</v>
+ <v>Result = ok | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>
+ Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
+ It both removes the label from the OpenSSL internal engine list and unloads the engine.
+ This function is the same as calling <c>ensure_engine_unloaded/2</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ returned if the engine can't be unloaded.
+ </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>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>ensure_engine_unloaded(Engine, EngineMethods) -> Result</name>
+ <fsummary>Unload an engine loaded with the ensure function</fsummary>
+ <type>
+ <v>Engine = engine_ref()</v>
+ <v>EngineMethods = [engine_method_type()]</v>
+ <v>Result = ok | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>
+ Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
+ It both removes the label from the OpenSSL internal engine list and unloads the engine.
+ An error tuple is returned if the engine can't be unloaded.
+ </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>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
</desc>
</func>
diff --git a/lib/crypto/doc/src/engine_load.xml b/lib/crypto/doc/src/engine_load.xml
index e5c3f5d561..3d0aa0c32a 100644
--- a/lib/crypto/doc/src/engine_load.xml
+++ b/lib/crypto/doc/src/engine_load.xml
@@ -42,6 +42,9 @@
operations. The hardware implementation usually offers improved performance over its
software-based counterpart, which is known as cryptographic acceleration.
</p>
+ <note>
+ <p>The file name requirement on the engine dynamic library can differ between SSL versions.</p>
+ </note>
</section>
<section>
@@ -54,9 +57,6 @@
<code>
1> {ok, Engine} = crypto:engine_load(&lt;&lt;"otp_test_engine">>, [], []).
{ok, #Ref}</code>
- <note>
- <p>The file name requirement on the engine dynamic library can differ between SSL versions.</p>
- </note>
</section>
<section>
@@ -72,9 +72,6 @@
&lt;&lt;"LOAD">>],
[]).
{ok, #Ref}</code>
- <note>
- <p>The dynamic engine is not supported in LibreSSL from version 2.2.1</p>
- </note>
</section>
<section>
@@ -100,6 +97,28 @@ engine_method_pkey_meths, engine_method_pkey_asn1_meths].
</section>
<section>
+ <title>Load with the ensure loaded function</title>
+ <p>
+ This function makes sure the engine is loaded just once and the ID is added to the internal
+ engine list of OpenSSL. The following calls to the function will check if the ID is loaded
+ and then just get a new reference to the engine.
+ </p>
+ <code>
+ 5> {ok, Engine} = crypto:ensure_engine_loaded(&lt;&lt;"MD5">>,
+ &lt;&lt;"/some/path/otp_test_engine.so">>).
+ {ok, #Ref}</code>
+ <p>
+ To unload it use crypto:ensure_engine_unloaded/1 which removes the ID from the internal list
+ before unloading the engine.
+ </p>
+ <code>
+ 6> crypto:ensure_engine_unloaded(&lt;&lt;"MD5">>).
+ ok</code>
+ </section>
+
+
+
+ <section>
<title>List all engines currently loaded</title>
<code>
5> crypto:engine_list().
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 835cadce47..81ab4e5ea1 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -51,9 +51,18 @@
engine_load/3,
engine_load/4,
engine_unload/1,
+ engine_by_id/1,
engine_list/0,
engine_ctrl_cmd_string/3,
- engine_ctrl_cmd_string/4
+ engine_ctrl_cmd_string/4,
+ engine_add/1,
+ engine_remove/1,
+ engine_get_id/1,
+ engine_get_name/1,
+ ensure_engine_loaded/2,
+ ensure_engine_loaded/3,
+ ensure_engine_unloaded/1,
+ ensure_engine_unloaded/2
]).
-export_type([engine_ref/0,
@@ -482,7 +491,7 @@ sign(Algorithm, Type, Data, Key, Options) ->
-type engine_key_ref() :: #{engine := engine_ref(),
key_id := key_id(),
password => password(),
- term() => term()
+ term() => term()
}.
-type pk_algs() :: rsa | ecdsa | dss .
@@ -658,7 +667,7 @@ evp_compute_key_nif(_Curve, _OthersBin, _MyBin) -> ?nif_stub.
-type engine_method_type() :: engine_method_rsa | engine_method_dsa | engine_method_dh |
engine_method_rand | engine_method_ecdh | engine_method_ecdsa |
engine_method_ciphers | engine_method_digests | engine_method_store |
- engine_method_pkey_meths | engine_method_pkey_asn1_meths |
+ engine_method_pkey_meths | engine_method_pkey_asn1_meths |
engine_method_ec.
-type engine_ref() :: term().
@@ -675,7 +684,8 @@ engine_get_all_methods() ->
PreCmds::[{unicode:chardata(), unicode:chardata()}],
PostCmds::[{unicode:chardata(), unicode:chardata()}]) ->
{ok, Engine::engine_ref()} | {error, Reason::term()}.
-engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds), is_list(PostCmds) ->
+engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds),
+ is_list(PostCmds) ->
engine_load(EngineId, PreCmds, PostCmds, engine_get_all_methods()).
%%----------------------------------------------------------------------
@@ -692,28 +702,26 @@ engine_load(EngineId, PreCmds, PostCmds, EngineMethods) when is_list(PreCmds),
ok = notsup_to_error(engine_load_dynamic_nif()),
case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId))) of
{ok, Engine} ->
- ok = engine_load_1(Engine, PreCmds, PostCmds, EngineMethods),
- {ok, Engine};
+ engine_load_1(Engine, PreCmds, PostCmds, EngineMethods);
{error, Error1} ->
{error, Error1}
end
catch
- throw:Error2 ->
- Error2
+ throw:Error2 ->
+ Error2
end.
engine_load_1(Engine, PreCmds, PostCmds, EngineMethods) ->
try
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),
- ok
+ {ok, Engine}
catch
- throw:Error ->
- %% The engine couldn't initialise, release the structural reference
- ok = engine_free_nif(Engine),
- throw(Error)
+ throw:Error ->
+ %% The engine couldn't initialise, release the structural reference
+ ok = engine_free_nif(Engine),
+ throw(Error)
end.
engine_load_2(Engine, PostCmds, EngineMethods) ->
@@ -743,7 +751,6 @@ engine_unload(Engine, EngineMethods) ->
try
[ok = engine_nif_wrapper(engine_unregister_nif(Engine, engine_method_atom_to_int(Method))) ||
Method <- EngineMethods],
- ok = engine_nif_wrapper(engine_remove_nif(Engine)),
%% Release the functional reference from engine_init_nif
ok = engine_nif_wrapper(engine_finish_nif(Engine)),
%% Release the structural reference from engine_by_id_nif
@@ -754,6 +761,41 @@ engine_unload(Engine, EngineMethods) ->
end.
%%----------------------------------------------------------------------
+%% Function: engine_by_id/1
+%%----------------------------------------------------------------------
+engine_by_id(EngineId) ->
+ try
+ notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId)))
+ catch
+ throw:Error ->
+ Error
+ end.
+
+%%----------------------------------------------------------------------
+%% Function: engine_add/1
+%%----------------------------------------------------------------------
+engine_add(Engine) ->
+ notsup_to_error(engine_add_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_remove/1
+%%----------------------------------------------------------------------
+engine_remove(Engine) ->
+ notsup_to_error(engine_remove_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_get_id/1
+%%----------------------------------------------------------------------
+engine_get_id(Engine) ->
+ notsup_to_error(engine_get_id_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_get_name/1
+%%----------------------------------------------------------------------
+engine_get_name(Engine) ->
+ notsup_to_error(engine_get_name_nif(Engine)).
+
+%%----------------------------------------------------------------------
%% Function: engine_list/0
%%----------------------------------------------------------------------
-spec engine_list() ->
@@ -764,9 +806,9 @@ engine_list() ->
[];
{ok, Engine} ->
case notsup_to_error(engine_get_id_nif(Engine)) of
- {ok, <<>>} ->
+ <<>> ->
engine_list(Engine, []);
- {ok, EngineId} ->
+ EngineId ->
engine_list(Engine, [EngineId])
end
end.
@@ -777,9 +819,9 @@ engine_list(Engine0, IdList) ->
lists:reverse(IdList);
{ok, Engine1} ->
case notsup_to_error(engine_get_id_nif(Engine1)) of
- {ok, <<>>} ->
+ <<>> ->
engine_list(Engine1, IdList);
- {ok, EngineId} ->
+ EngineId ->
engine_list(Engine1, [EngineId |IdList])
end
end.
@@ -788,7 +830,7 @@ engine_list(Engine0, IdList) ->
%% Function: engine_ctrl_cmd_string/3
%%----------------------------------------------------------------------
-spec engine_ctrl_cmd_string(Engine::term(),
- CmdName::unicode:chardata(),
+ CmdName::unicode:chardata(),
CmdArg::unicode:chardata()) ->
ok | {error, Reason::term()}.
engine_ctrl_cmd_string(Engine, CmdName, CmdArg) ->
@@ -798,13 +840,13 @@ engine_ctrl_cmd_string(Engine, CmdName, CmdArg) ->
%% Function: engine_ctrl_cmd_string/4
%%----------------------------------------------------------------------
-spec engine_ctrl_cmd_string(Engine::term(),
- CmdName::unicode:chardata(),
+ 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}]),
+ case engine_ctrl_cmd_strings_nif(Engine,
+ ensure_bin_cmds([{CmdName, CmdArg}]),
bool_to_int(Optional)) of
ok ->
ok;
@@ -814,6 +856,82 @@ engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
{error, Error}
end.
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_loaded/2
+%% Special version of load that only uses dynamic engine to load
+%%----------------------------------------------------------------------
+ensure_engine_loaded(EngineId, LibPath) ->
+ ensure_engine_loaded(EngineId, LibPath, engine_get_all_methods()).
+
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_loaded/3
+%% Special version of load that only uses dynamic engine to load
+%%----------------------------------------------------------------------
+ensure_engine_loaded(EngineId, LibPath, EngineMethods) ->
+ try
+ List = crypto:engine_list(),
+ case lists:member(EngineId, List) of
+ true ->
+ notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId)));
+ false ->
+ ok = notsup_to_error(engine_load_dynamic_nif()),
+ case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(<<"dynamic">>))) of
+ {ok, Engine} ->
+ PreCommands = [{<<"SO_PATH">>, ensure_bin_chardata(LibPath)},
+ {<<"ID">>, ensure_bin_chardata(EngineId)},
+ <<"LOAD">>],
+ ensure_engine_loaded_1(Engine, PreCommands, EngineMethods);
+ {error, Error1} ->
+ {error, Error1}
+ end
+ end
+ catch
+ throw:Error2 ->
+ Error2
+ end.
+
+ensure_engine_loaded_1(Engine, PreCmds, Methods) ->
+ try
+ 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)),
+ ensure_engine_loaded_2(Engine, Methods),
+ {ok, Engine}
+ catch
+ throw:Error ->
+ %% The engine couldn't initialise, release the structural reference
+ ok = engine_free_nif(Engine),
+ throw(Error)
+ end.
+
+ensure_engine_loaded_2(Engine, Methods) ->
+ try
+ [ok = engine_nif_wrapper(engine_register_nif(Engine, engine_method_atom_to_int(Method))) ||
+ Method <- Methods],
+ ok
+ catch
+ throw:Error ->
+ %% The engine registration failed, release the functional reference
+ ok = engine_finish_nif(Engine),
+ throw(Error)
+ end.
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_unloaded/1
+%%----------------------------------------------------------------------
+ensure_engine_unloaded(Engine) ->
+ ensure_engine_unloaded(Engine, engine_get_all_methods()).
+
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_unloaded/2
+%%----------------------------------------------------------------------
+ensure_engine_unloaded(Engine, EngineMethods) ->
+ case engine_remove(Engine) of
+ ok ->
+ engine_unload(Engine, EngineMethods);
+ {error, E} ->
+ {error, E}
+ end.
+
%%--------------------------------------------------------------------
%%% On load
%%--------------------------------------------------------------------
@@ -886,7 +1004,7 @@ path2bin(Path) when is_list(Path) ->
max_bytes() ->
?MAX_BYTES_TO_NIF.
-notsup_to_error(notsup) ->
+notsup_to_error(notsup) ->
erlang:error(notsup);
notsup_to_error(Other) ->
Other.
@@ -1142,7 +1260,7 @@ privkey_to_pubkey(Alg, EngineMap) when Alg == rsa; Alg == dss; Alg == ecdsa ->
error:notsup ->
{error, notsup}
end.
-
+
privkey_to_pubkey_nif(_Alg, _EngineMap) -> ?nif_stub.
@@ -1308,6 +1426,7 @@ engine_unregister_nif(_Engine, _EngineMethod) -> ?nif_stub.
engine_get_first_nif() -> ?nif_stub.
engine_get_next_nif(_Engine) -> ?nif_stub.
engine_get_id_nif(_Engine) -> ?nif_stub.
+engine_get_name_nif(_Engine) -> ?nif_stub.
engine_get_all_methods_nif() -> ?nif_stub.
%%--------------------------------------------------------------------
@@ -1365,7 +1484,7 @@ get_test_engine() ->
Type = erlang:system_info(system_architecture),
LibDir = filename:join([code:priv_dir(crypto), "lib"]),
ArchDir = filename:join([LibDir, Type]),
- case filelib:is_dir(ArchDir) of
+ case filelib:is_dir(ArchDir) of
true -> check_otp_test_engine(ArchDir);
false -> check_otp_test_engine(LibDir)
end.
@@ -1383,4 +1502,3 @@ check_otp_test_engine(LibDir) ->
{error, notexist}
end
end.
-
diff --git a/lib/crypto/test/engine_SUITE.erl b/lib/crypto/test/engine_SUITE.erl
index f708d7272d..b083b30d70 100644
--- a/lib/crypto/test/engine_SUITE.erl
+++ b/lib/crypto/test/engine_SUITE.erl
@@ -39,6 +39,10 @@ all() ->
get_all_possible_methods,
engine_load_all_methods,
engine_load_some_methods,
+ multiple_engine_load,
+ engine_list,
+ get_id_and_name,
+ engine_by_id,
bad_arguments,
unknown_engine,
pre_command_fail_bad_value,
@@ -46,6 +50,7 @@ all() ->
failed_engine_init,
ctrl_cmd_string,
ctrl_cmd_string_optional,
+ ensure_load,
{group, engine_stored_key}
].
@@ -97,7 +102,7 @@ init_per_group(engine_stored_key, Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{error, notsup} ->
- {skip, "Engine not supported on this OpenSSL version"};
+ {skip, "Engine not supported on this SSL version"};
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"};
Other ->
@@ -132,11 +137,12 @@ get_all_possible_methods() ->
get_all_possible_methods(Config) when is_list(Config) ->
try
List = crypto:engine_get_all_methods(),
+ true = erlang:is_list(List),
ct:log("crypto:engine_get_all_methods() -> ~p\n", [List]),
ok
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
engine_load_all_methods()->
@@ -149,13 +155,12 @@ engine_load_all_methods(Config) when is_list(Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{ok, Engine} ->
- try
+ try
Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
Md5Hash1 = crypto:hash(md5, "Don't panic"),
Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
case crypto:engine_load(<<"dynamic">>,
[{<<"SO_PATH">>, Engine},
- {<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[]) of
{ok, E} ->
@@ -181,7 +186,7 @@ engine_load_all_methods(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end
end.
@@ -195,21 +200,20 @@ engine_load_some_methods(Config) when is_list(Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{ok, Engine} ->
- try
+ try
Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
Md5Hash1 = crypto:hash(md5, "Don't panic"),
Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
EngineMethods = crypto:engine_get_all_methods() --
- [engine_method_dh,engine_method_rand,
+ [engine_method_dh, engine_method_rand,
engine_method_ciphers, engine_method_store,
engine_method_pkey_meths, engine_method_pkey_asn1_meths],
case crypto:engine_load(<<"dynamic">>,
[{<<"SO_PATH">>, Engine},
- {<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[],
EngineMethods) of
- {ok, E} ->
+ {ok, E} ->
case crypto:hash(md5, "Don't panic") of
Md5Hash1 ->
ct:fail(fail_to_load_engine_still_original);
@@ -232,7 +236,168 @@ engine_load_some_methods(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+multiple_engine_load()->
+ [{doc, "Use a dummy md5 engine that does not implement md5"
+ "but rather returns a static binary to test that crypto:engine_load "
+ "functions works when called multiple times."}].
+
+multiple_engine_load(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
+ Md5Hash1 = crypto:hash(md5, "Don't panic"),
+ Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ {ok, E1} = crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []),
+ {ok, E2} = crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E2),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E1),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+engine_list()->
+ [{doc, "Test add and remove engine ID to the SSL internal engine list."}].
+
+engine_list(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ EngineList0 = crypto:engine_list(),
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ EngineList0 = crypto:engine_list(),
+ ok = crypto:engine_add(E),
+ [<<"MD5">>] = lists:subtract(crypto:engine_list(), EngineList0),
+ ok = crypto:engine_remove(E),
+ EngineList0 = crypto:engine_list(),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+get_id_and_name()->
+ [{doc, "Test fetching id and name from an engine."}].
+
+get_id_and_name(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ <<"MD5">> = crypto:engine_get_id(E),
+ <<"MD5 test engine">> = crypto:engine_get_name(E),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+engine_by_id()->
+ [{doc, "Test fetching a new reference the the engine when the"
+ "engine id is added to the SSL engine list."}].
+
+engine_by_id(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ case crypto:engine_by_id(<<"MD5">>) of
+ {error,bad_engine_id} ->
+ ok;
+ {ok, _} ->
+ ct:fail(fail_engine_found)
+ end,
+ ok = crypto:engine_add(E),
+ {ok, _E1} = crypto:engine_by_id(<<"MD5">>),
+ ok = crypto:engine_remove(E),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
end
end.
@@ -246,7 +411,7 @@ bad_arguments(Config) when is_list(Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{ok, Engine} ->
- try
+ try
try
crypto:engine_load(fail_engine, [], [])
catch
@@ -276,7 +441,7 @@ bad_arguments(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end
end.
@@ -289,7 +454,7 @@ unknown_engine(Config) when is_list(Config) ->
ok
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
pre_command_fail_bad_value() ->
@@ -311,7 +476,7 @@ pre_command_fail_bad_value(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
pre_command_fail_bad_key() ->
@@ -334,9 +499,9 @@ pre_command_fail_bad_key(Config) when is_list(Config) ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
failed_engine_init()->
@@ -352,18 +517,20 @@ failed_engine_init(Config) when is_list(Config) ->
[{<<"SO_PATH">>, Engine},
{<<"ID">>, <<"MD5">>}],
[]) of
- {error, add_engine_failed} ->
+ {error, engine_init_failed} ->
ok;
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
+%%-------------------------------------------------------------------------
+%% Test the optional flag in ctrl comands
ctrl_cmd_string()->
[{doc, "Test that a not known optional ctrl comand do not fail"}].
ctrl_cmd_string(Config) when is_list(Config) ->
@@ -377,22 +544,22 @@ ctrl_cmd_string(Config) when is_list(Config) ->
{<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[]) of
- {ok, E} ->
+ {ok, E} ->
case crypto:engine_ctrl_cmd_string(E, <<"TEST">>, <<"17">>) of
ok ->
ct:fail(fail_ctrl_cmd_should_fail);
- {error,ctrl_cmd_failed} ->
+ {error,ctrl_cmd_failed} ->
ok
end,
- ok = crypto:engine_unload(E);
+ ok = crypto:engine_unload(E);
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
- end.
+ {skip, "Engine not supported on this SSL version"}
+ end.
ctrl_cmd_string_optional()->
[{doc, "Test that a not known optional ctrl comand do not fail"}].
@@ -407,22 +574,63 @@ ctrl_cmd_string_optional(Config) when is_list(Config) ->
{<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[]) of
- {ok, E} ->
+ {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);
+ ok = crypto:engine_unload(E);
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
- end.
+ {skip, "Engine not supported on this SSL version"}
+ end.
+
+ensure_load()->
+ [{doc, "Test the special ensure load function."}].
+
+ensure_load(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
+ Md5Hash1 = crypto:hash(md5, "Don't panic"),
+ Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ case crypto:ensure_engine_loaded(<<"MD5">>, Engine) of
+ {ok, E} ->
+ {ok, _E1} = crypto:ensure_engine_loaded(<<"MD5">>, Engine),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:ensure_engine_unloaded(E),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
%%%----------------------------------------------------------------
%%% Pub/priv key storage tests. Thoose are for testing the crypto.erl
@@ -467,7 +675,7 @@ sign_verify_rsa_pwd_bad_pwd(Config) ->
_ -> {fail, "PWD prot pubkey sign succeded with no pwd!"}
catch
error:badarg -> ok
- end.
+ end.
priv_encrypt_pub_decrypt_rsa(Config) ->
Priv = #{engine => engine_ref(Config),
@@ -540,7 +748,7 @@ get_pub_from_priv_key_rsa_pwd_no_pwd(Config) ->
{skip, "RSA not supported"};
{error, Error} ->
{fail, {wrong_error,Error}};
- Pub ->
+ Pub ->
ct:log("rsa Pub = ~p",[Pub]),
{fail, "PWD prot pubkey fetch succeded although no pwd!"}
end.
@@ -556,7 +764,7 @@ get_pub_from_priv_key_rsa_pwd_bad_pwd(Config) ->
{skip, "RSA not supported"};
{error, Error} ->
{fail, {wrong_error,Error}};
- Pub ->
+ Pub ->
ct:log("rsa Pub = ~p",[Pub]),
{fail, "PWD prot pubkey fetch succeded with bad pwd!"}
end.
@@ -590,7 +798,7 @@ get_pub_from_priv_key_ecdsa(Config) ->
ct:log("ecdsa Pub = ~p",[Pub]),
sign_verify(ecdsa, sha, Priv, Pub)
end.
-
+
%%%================================================================
%%% Help for engine_stored_pub_priv_keys* test cases
%%%
diff --git a/lib/mnesia/src/mnesia_index.erl b/lib/mnesia/src/mnesia_index.erl
index 917ada65df..098265d5fc 100644
--- a/lib/mnesia/src/mnesia_index.erl
+++ b/lib/mnesia/src/mnesia_index.erl
@@ -155,7 +155,7 @@ del_object_bag_([IxK|IxKs], Found, Type, Tab, Key, Obj, Ixt) ->
bag ->
db_match_erase(Ixt, {IxK, Key});
ordered ->
- db_erase(Ixt, {{IxK, Key}})
+ db_erase(Ixt, {IxK, Key})
end;
_ ->
ok
diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl
index 77236940d4..a451c8d0c8 100644
--- a/lib/mnesia/test/mnesia_evil_coverage_test.erl
+++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl
@@ -35,7 +35,7 @@
replica_management/1, clear_table_during_load/1,
schema_availability/1, local_content/1,
replica_location/1, user_properties/1, unsupp_user_props/1,
- sorted_ets/1,
+ sorted_ets/1, index_cleanup/1,
change_table_access_mode/1, change_table_load_order/1,
set_master_nodes/1, offline_set_master_nodes/1,
dump_tables/1, dump_log/1, wait_for_tables/1, force_load_table/1,
@@ -49,7 +49,7 @@
record_name_dirty_access_disc_only/1,
record_name_dirty_access_xets/1]).
--export([info_check/8]).
+-export([info_check/8, index_size/1]).
-define(cleanup(N, Config),
mnesia_test_lib:prepare_test_case([{reload_appls, [mnesia]}],
@@ -73,7 +73,7 @@ all() ->
{group, table_sync}, user_properties, unsupp_user_props,
{group, record_name}, {group, snmp_access},
{group, subscriptions}, {group, iteration},
- {group, debug_support}, sorted_ets,
+ {group, debug_support}, sorted_ets, index_cleanup,
{mnesia_dirty_access_test, all},
{mnesia_trans_access_test, all},
{mnesia_evil_backup, all}].
@@ -2559,3 +2559,55 @@ sorted_ets(Config) when is_list(Config) ->
?match({atomic, [{rec,1,1}, {rec,2,1}]}, mnesia:transaction(TestIt)).
+index_cleanup(Config) when is_list(Config) ->
+ [N1, N2] = All = ?acquire_nodes(2, Config),
+ ?match({atomic, ok}, mnesia:create_table(i_set, [{type, set}, {ram_copies, [N1]}, {index, [val]},
+ {disc_only_copies, [N2]}])),
+ ?match({atomic, ok}, mnesia:create_table(i_bag, [{type, bag}, {ram_copies, [N1]}, {index, [val]},
+ {disc_only_copies, [N2]}])),
+ ?match({atomic, ok}, mnesia:create_table(i_oset, [{type, ordered_set}, {ram_copies, [N1, N2]},
+ {index, [val]}])),
+
+ Tabs = [i_set, i_bag, i_oset],
+
+ Add = fun(Tab) ->
+ Write = fun(Tab) ->
+ Recs = [{Tab, N, N rem 5} || N <- lists:seq(1,10)],
+ [ok = mnesia:write(Rec) || Rec <- Recs],
+ Recs
+ end,
+ {atomic, Recs} = mnesia:sync_transaction(Write, [Tab]),
+ lists:sort(Recs)
+ end,
+
+ IRead = fun(Tab) ->
+ Read = fun(Tab) ->
+ [mnesia:index_read(Tab, N, val) || N <- lists:seq(0,4)]
+ end,
+ {atomic, Recs} = mnesia:transaction(Read, [Tab]),
+ lists:sort(lists:flatten(Recs))
+ end,
+
+ Delete = fun(Rec) ->
+ Del = fun() -> mnesia:delete_object(Rec) end,
+ {atomic, ok} = mnesia:sync_transaction(Del),
+ ok
+ end,
+
+
+ Recs = [Add(Tab) || Tab <- Tabs],
+ ?match(Recs, [IRead(Tab) || Tab <- Tabs]),
+ [Delete(Rec) || Rec <- lists:flatten(Recs)],
+
+ [?match({Tab,0}, {Tab,mnesia:table_info(Tab, size)}) || Tab <- Tabs],
+
+ [?match({Tab,Node,0, _}, rpc:call(Node, ?MODULE, index_size, [Tab]))
+ || Node <- All, Tab <- Tabs],
+ ?verify_mnesia(All, []).
+
+index_size(Tab) ->
+ %% White box testing
+ case mnesia:table_info(Tab, index_info) of
+ {index, _, [{_, {ram, Ref}}=Dbg]} -> {Tab, node(), ets:info(Ref, size), Dbg};
+ {index, _, [{_, {dets, Ref}}=Dbg]} -> {Tab, node(), dets:info(Ref, size), Dbg}
+ end.