aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crypto/c_src/engine.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/crypto/c_src/engine.c')
-rw-r--r--lib/crypto/c_src/engine.c720
1 files changed, 720 insertions, 0 deletions
diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c
new file mode 100644
index 0000000000..dc8e1828ce
--- /dev/null
+++ b/lib/crypto/c_src/engine.c
@@ -0,0 +1,720 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2010-2018. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "engine.h"
+
+#ifdef HAS_ENGINE_SUPPORT
+struct engine_ctx {
+ ENGINE *engine;
+ char *id;
+};
+
+static ErlNifResourceType* engine_ctx_rtype;
+
+static int get_engine_load_cmd_list(ErlNifEnv* env, const ERL_NIF_TERM term, char **cmds, int i);
+static int zero_terminate(ErlNifBinary bin, char **buf);
+
+static void engine_ctx_dtor(ErlNifEnv* env, struct engine_ctx* ctx) {
+ PRINTF_ERR0("engine_ctx_dtor");
+ if(ctx->id) {
+ PRINTF_ERR1(" non empty ctx->id=%s", ctx->id);
+ enif_free(ctx->id);
+ } else
+ PRINTF_ERR0(" empty ctx->id=NULL");
+}
+
+int get_engine_and_key_id(ErlNifEnv *env, ERL_NIF_TERM key, char ** id, ENGINE **e)
+{
+ ERL_NIF_TERM engine_res, key_id_term;
+ struct engine_ctx *ctx;
+ ErlNifBinary key_id_bin;
+
+ if (!enif_get_map_value(env, key, atom_engine, &engine_res) ||
+ !enif_get_resource(env, engine_res, engine_ctx_rtype, (void**)&ctx) ||
+ !enif_get_map_value(env, key, atom_key_id, &key_id_term) ||
+ !enif_inspect_binary(env, key_id_term, &key_id_bin)) {
+ return 0;
+ }
+ else {
+ *e = ctx->engine;
+ return zero_terminate(key_id_bin, id);
+ }
+}
+
+char *get_key_password(ErlNifEnv *env, ERL_NIF_TERM key) {
+ ERL_NIF_TERM tmp_term;
+ ErlNifBinary pwd_bin;
+ char *pwd = NULL;
+ if (enif_get_map_value(env, key, atom_password, &tmp_term) &&
+ enif_inspect_binary(env, tmp_term, &pwd_bin) &&
+ zero_terminate(pwd_bin, &pwd)
+ ) return pwd;
+
+ return NULL;
+}
+
+static int zero_terminate(ErlNifBinary bin, char **buf) {
+ *buf = enif_alloc(bin.size+1);
+ if (!*buf)
+ return 0;
+ memcpy(*buf, bin.data, bin.size);
+ *(*buf+bin.size) = 0;
+ return 1;
+}
+#endif /* HAS_ENGINE_SUPPORT */
+
+int init_engine_ctx(ErlNifEnv *env) {
+#ifdef HAS_ENGINE_SUPPORT
+ engine_ctx_rtype = enif_open_resource_type(env, NULL, "ENGINE_CTX",
+ (ErlNifResourceDtor*) engine_ctx_dtor,
+ ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
+ NULL);
+ if (engine_ctx_rtype == NULL) {
+ PRINTF_ERR0("CRYPTO: Could not open resource type 'ENGINE_CTX'");
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+
+ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (EngineId) */
+#ifdef HAS_ENGINE_SUPPORT
+ ERL_NIF_TERM ret;
+ ErlNifBinary engine_id_bin;
+ char *engine_id;
+ ENGINE *engine;
+ struct engine_ctx *ctx;
+
+ // Get Engine Id
+ if(!enif_inspect_binary(env, argv[0], &engine_id_bin)) {
+ PRINTF_ERR0("engine_by_id_nif Leaved: badarg");
+ return enif_make_badarg(env);
+ } else {
+ engine_id = enif_alloc(engine_id_bin.size+1);
+ (void) memcpy(engine_id, engine_id_bin.data, engine_id_bin.size);
+ engine_id[engine_id_bin.size] = '\0';
+ }
+
+ engine = ENGINE_by_id(engine_id);
+ if(!engine) {
+ enif_free(engine_id);
+ PRINTF_ERR0("engine_by_id_nif Leaved: {error, bad_engine_id}");
+ return enif_make_tuple2(env, atom_error, atom_bad_engine_id);
+ }
+
+ ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx));
+ ctx->engine = engine;
+ ctx->id = engine_id;
+
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
+
+ return enif_make_tuple2(env, atom_ok, ret);
+#else
+ return atom_notsup;
+#endif
+}
+
+ERL_NIF_TERM engine_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ ERL_NIF_TERM ret = atom_ok;
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_init_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+ if (!ENGINE_init(ctx->engine)) {
+ //ERR_print_errors_fp(stderr);
+ PRINTF_ERR0("engine_init_nif Leaved: {error, engine_init_failed}");
+ return enif_make_tuple2(env, atom_error, atom_engine_init_failed);
+ }
+
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
+ERL_NIF_TERM engine_free_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_free_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ ENGINE_free(ctx->engine);
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+ERL_NIF_TERM engine_finish_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_finish_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ ENGINE_finish(ctx->engine);
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+ERL_NIF_TERM engine_load_dynamic_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* () */
+#ifdef HAS_ENGINE_SUPPORT
+ ENGINE_load_dynamic();
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine, Commands) */
+#ifdef HAS_ENGINE_SUPPORT
+ ERL_NIF_TERM ret = atom_ok;
+ unsigned int cmds_len = 0;
+ char **cmds = NULL;
+ struct engine_ctx *ctx;
+ int i, optional = 0;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ PRINTF_ERR1("Engine Id: %s\r\n", ENGINE_get_id(ctx->engine));
+
+ // Get Command List
+ if(!enif_get_list_length(env, argv[1], &cmds_len)) {
+ PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: Bad Command List");
+ return enif_make_badarg(env);
+ } else {
+ cmds_len *= 2; // Key-Value list from erlang
+ cmds = enif_alloc((cmds_len+1)*sizeof(char*));
+ if(get_engine_load_cmd_list(env, argv[1], cmds, 0)) {
+ PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: Couldn't read Command List");
+ ret = enif_make_badarg(env);
+ goto error;
+ }
+ }
+
+ 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], optional)) {
+ PRINTF_ERR2("Command failed: %s:%s\r\n",
+ cmds[i] ? cmds[i] : "(NULL)",
+ cmds[i+1] ? cmds[i+1] : "(NULL)");
+ //ENGINE_free(ctx->engine);
+ ret = enif_make_tuple2(env, atom_error, atom_ctrl_cmd_failed);
+ PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: {error, ctrl_cmd_failed}");
+ goto error;
+ }
+ }
+
+ error:
+ for(i = 0; cmds != NULL && cmds[i] != NULL; i++)
+ enif_free(cmds[i]);
+ enif_free(cmds);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
+ERL_NIF_TERM engine_add_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_add_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ if (!ENGINE_add(ctx->engine)) {
+ PRINTF_ERR0("engine_add_nif Leaved: {error, add_engine_failed}");
+ return enif_make_tuple2(env, atom_error, atom_add_engine_failed);
+ }
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+ERL_NIF_TERM engine_remove_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_remove_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ if (!ENGINE_remove(ctx->engine)) {
+ PRINTF_ERR0("engine_remove_nif Leaved: {error, remove_engine_failed}");
+ return enif_make_tuple2(env, atom_error, atom_remove_engine_failed);
+ }
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+ERL_NIF_TERM engine_register_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine, EngineMethod) */
+#ifdef HAS_ENGINE_SUPPORT
+ struct engine_ctx *ctx;
+ unsigned int method;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_register_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+ // Get Method
+ if (!enif_get_uint(env, argv[1], &method)) {
+ PRINTF_ERR0("engine_register_nif Leaved: Parameter Method not an uint");
+ return enif_make_badarg(env);
+ }
+
+ switch(method)
+ {
+#ifdef ENGINE_METHOD_RSA
+ case ENGINE_METHOD_RSA:
+ if (!ENGINE_register_RSA(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DSA
+ case ENGINE_METHOD_DSA:
+ if (!ENGINE_register_DSA(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DH
+ case ENGINE_METHOD_DH:
+ if (!ENGINE_register_DH(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_RAND
+ case ENGINE_METHOD_RAND:
+ if (!ENGINE_register_RAND(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_ECDH
+ case ENGINE_METHOD_ECDH:
+ if (!ENGINE_register_ECDH(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_ECDSA
+ case ENGINE_METHOD_ECDSA:
+ if (!ENGINE_register_ECDSA(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_STORE
+ case ENGINE_METHOD_STORE:
+ if (!ENGINE_register_STORE(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_CIPHERS
+ case ENGINE_METHOD_CIPHERS:
+ if (!ENGINE_register_ciphers(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DIGESTS
+ case ENGINE_METHOD_DIGESTS:
+ if (!ENGINE_register_digests(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_PKEY_METHS
+ case ENGINE_METHOD_PKEY_METHS:
+ if (!ENGINE_register_pkey_meths(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_PKEY_ASN1_METHS
+ case ENGINE_METHOD_PKEY_ASN1_METHS:
+ if (!ENGINE_register_pkey_asn1_meths(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_EC
+ case ENGINE_METHOD_EC:
+ if (!ENGINE_register_EC(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+ default:
+ return enif_make_tuple2(env, atom_error, atom_engine_method_not_supported);
+ break;
+ }
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+ERL_NIF_TERM engine_unregister_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine, EngineMethod) */
+#ifdef HAS_ENGINE_SUPPORT
+ struct engine_ctx *ctx;
+ unsigned int method;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_unregister_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+ // Get Method
+ if (!enif_get_uint(env, argv[1], &method)) {
+ PRINTF_ERR0("engine_unregister_nif Leaved: Parameter Method not an uint");
+ return enif_make_badarg(env);
+ }
+
+ switch(method)
+ {
+#ifdef ENGINE_METHOD_RSA
+ case ENGINE_METHOD_RSA:
+ ENGINE_unregister_RSA(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DSA
+ case ENGINE_METHOD_DSA:
+ ENGINE_unregister_DSA(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DH
+ case ENGINE_METHOD_DH:
+ ENGINE_unregister_DH(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_RAND
+ case ENGINE_METHOD_RAND:
+ ENGINE_unregister_RAND(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_ECDH
+ case ENGINE_METHOD_ECDH:
+ ENGINE_unregister_ECDH(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_ECDSA
+ case ENGINE_METHOD_ECDSA:
+ ENGINE_unregister_ECDSA(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_STORE
+ case ENGINE_METHOD_STORE:
+ ENGINE_unregister_STORE(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_CIPHERS
+ case ENGINE_METHOD_CIPHERS:
+ ENGINE_unregister_ciphers(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DIGESTS
+ case ENGINE_METHOD_DIGESTS:
+ ENGINE_unregister_digests(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_PKEY_METHS
+ case ENGINE_METHOD_PKEY_METHS:
+ ENGINE_unregister_pkey_meths(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_PKEY_ASN1_METHS
+ case ENGINE_METHOD_PKEY_ASN1_METHS:
+ ENGINE_unregister_pkey_asn1_meths(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_EC
+ case ENGINE_METHOD_EC:
+ ENGINE_unregister_EC(ctx->engine);
+ break;
+#endif
+ default:
+ break;
+ }
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ ERL_NIF_TERM ret;
+ ENGINE *engine;
+ ErlNifBinary engine_bin;
+ struct engine_ctx *ctx;
+
+ engine = ENGINE_get_first();
+ if(!engine) {
+ enif_alloc_binary(0, &engine_bin);
+ engine_bin.size = 0;
+ return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_bin));
+ }
+
+ ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx));
+ ctx->engine = engine;
+ ctx->id = NULL;
+
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
+
+ return enif_make_tuple2(env, atom_ok, ret);
+#else
+ return atom_notsup;
+#endif
+}
+
+ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ ERL_NIF_TERM ret;
+ ENGINE *engine;
+ ErlNifBinary engine_bin;
+ struct engine_ctx *ctx, *next_ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_get_next_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+ engine = ENGINE_get_next(ctx->engine);
+ if (!engine) {
+ enif_alloc_binary(0, &engine_bin);
+ engine_bin.size = 0;
+ return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_bin));
+ }
+
+ next_ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx));
+ next_ctx->engine = engine;
+ next_ctx->id = NULL;
+
+ ret = enif_make_resource(env, next_ctx);
+ enif_release_resource(next_ctx);
+
+ return enif_make_tuple2(env, atom_ok, ret);
+#else
+ return atom_notsup;
+#endif
+}
+
+ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ ErlNifBinary engine_id_bin;
+ const char *engine_id;
+ 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_id = ENGINE_get_id(ctx->engine);
+ if (!engine_id) {
+ enif_alloc_binary(0, &engine_id_bin);
+ engine_id_bin.size = 0;
+ return enif_make_binary(env, &engine_id_bin);
+ }
+
+ size = strlen(engine_id);
+ enif_alloc_binary(size, &engine_id_bin);
+ engine_id_bin.size = size;
+ memcpy(engine_id_bin.data, engine_id, size);
+
+ return enif_make_binary(env, &engine_id_bin);
+#else
+ return atom_notsup;
+#endif
+}
+
+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
+}
+
+#ifdef HAS_ENGINE_SUPPORT
+static int get_engine_load_cmd_list(ErlNifEnv* env, const ERL_NIF_TERM term, char **cmds, int i)
+{
+ ERL_NIF_TERM head, tail;
+ const ERL_NIF_TERM *tmp_tuple;
+ ErlNifBinary tmpbin;
+ int arity;
+ char* tmpstr;
+
+ if(!enif_is_empty_list(env, term)) {
+ if(!enif_get_list_cell(env, term, &head, &tail)) {
+ cmds[i] = NULL;
+ return -1;
+ } else {
+ if(!enif_get_tuple(env, head, &arity, &tmp_tuple) || arity != 2) {
+ cmds[i] = NULL;
+ return -1;
+ } else {
+ if(!enif_inspect_binary(env, tmp_tuple[0], &tmpbin)) {
+ cmds[i] = NULL;
+ return -1;
+ } else {
+ tmpstr = enif_alloc(tmpbin.size+1);
+ (void) memcpy(tmpstr, tmpbin.data, tmpbin.size);
+ tmpstr[tmpbin.size] = '\0';
+ cmds[i++] = tmpstr;
+ }
+ if(!enif_inspect_binary(env, tmp_tuple[1], &tmpbin)) {
+ cmds[i] = NULL;
+ return -1;
+ } else {
+ if(tmpbin.size == 0)
+ cmds[i++] = NULL;
+ else {
+ tmpstr = enif_alloc(tmpbin.size+1);
+ (void) memcpy(tmpstr, tmpbin.data, tmpbin.size);
+ tmpstr[tmpbin.size] = '\0';
+ cmds[i++] = tmpstr;
+ }
+ }
+ return get_engine_load_cmd_list(env, tail, cmds, i);
+ }
+ }
+ } else {
+ cmds[i] = NULL;
+ return 0;
+ }
+}
+#endif /* HAS_ENGINE_SUPPORT */
+
+ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* () */
+#ifdef HAS_ENGINE_SUPPORT
+ ERL_NIF_TERM method_array[12];
+ int i = 0;
+
+#ifdef ENGINE_METHOD_RSA
+ method_array[i++] = atom_engine_method_rsa;
+#endif
+#ifdef ENGINE_METHOD_DSA
+ method_array[i++] = atom_engine_method_dsa;
+#endif
+#ifdef ENGINE_METHOD_DH
+ method_array[i++] = atom_engine_method_dh;
+#endif
+#ifdef ENGINE_METHOD_RAND
+ method_array[i++] = atom_engine_method_rand;
+#endif
+#ifdef ENGINE_METHOD_ECDH
+ method_array[i++] = atom_engine_method_ecdh;
+#endif
+#ifdef ENGINE_METHOD_ECDSA
+ method_array[i++] = atom_engine_method_ecdsa;
+#endif
+#ifdef ENGINE_METHOD_STORE
+ method_array[i++] = atom_engine_method_store;
+#endif
+#ifdef ENGINE_METHOD_CIPHERS
+ method_array[i++] = atom_engine_method_ciphers;
+#endif
+#ifdef ENGINE_METHOD_DIGESTS
+ method_array[i++] = atom_engine_method_digests;
+#endif
+#ifdef ENGINE_METHOD_PKEY_METHS
+ method_array[i++] = atom_engine_method_pkey_meths;
+#endif
+#ifdef ENGINE_METHOD_PKEY_ASN1_METHS
+ method_array[i++] = atom_engine_method_pkey_asn1_meths;
+#endif
+#ifdef ENGINE_METHOD_EC
+ method_array[i++] = atom_engine_method_ec;
+#endif
+
+ return enif_make_list_from_array(env, method_array, i);
+#else
+ return atom_notsup;
+#endif
+}