1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2010-2020. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21 #include "engine.h"
22
23 #ifdef HAS_ENGINE_SUPPORT
24 struct engine_ctx {
25 ENGINE *engine;
26 int is_functional;
27 char *id;
28 };
29
30 #define ERROR_Term(Env, ReasonTerm) enif_make_tuple2((Env), atom_error, (ReasonTerm))
31 #define ERROR_Atom(Env, ReasonString) ERROR_Term((Env), enif_make_atom((Env),(ReasonString)))
32
33 static ErlNifResourceType* engine_ctx_rtype;
34
35 static int get_engine_load_cmd_list(ErlNifEnv* env, const ERL_NIF_TERM term, char **cmds, int i);
36 static int zero_terminate(ErlNifBinary bin, char **buf);
37
engine_ctx_dtor(ErlNifEnv * env,struct engine_ctx * ctx)38 static void engine_ctx_dtor(ErlNifEnv* env, struct engine_ctx* ctx) {
39 if (ctx == NULL)
40 return;
41
42 PRINTF_ERR0("engine_ctx_dtor");
43 if(ctx->id) {
44 PRINTF_ERR1(" non empty ctx->id=%s", ctx->id);
45 enif_free(ctx->id);
46 } else
47 PRINTF_ERR0(" empty ctx->id=NULL");
48
49 if (ctx->engine) {
50 if (ctx->is_functional)
51 ENGINE_finish(ctx->engine);
52 ENGINE_free(ctx->engine);
53 }
54 }
55
get_engine_and_key_id(ErlNifEnv * env,ERL_NIF_TERM key,char ** id,ENGINE ** e)56 int get_engine_and_key_id(ErlNifEnv *env, ERL_NIF_TERM key, char ** id, ENGINE **e)
57 {
58 ERL_NIF_TERM engine_res, key_id_term;
59 struct engine_ctx *ctx;
60 ErlNifBinary key_id_bin;
61
62 if (!enif_get_map_value(env, key, atom_engine, &engine_res))
63 goto err;
64 if (!enif_get_resource(env, engine_res, engine_ctx_rtype, (void**)&ctx))
65 goto err;
66 if (!enif_get_map_value(env, key, atom_key_id, &key_id_term))
67 goto err;
68 if (!enif_inspect_binary(env, key_id_term, &key_id_bin))
69 goto err;
70
71 *e = ctx->engine;
72 return zero_terminate(key_id_bin, id);
73
74 err:
75 return 0;
76 }
77
get_key_password(ErlNifEnv * env,ERL_NIF_TERM key)78 char *get_key_password(ErlNifEnv *env, ERL_NIF_TERM key) {
79 ERL_NIF_TERM tmp_term;
80 ErlNifBinary pwd_bin;
81 char *pwd = NULL;
82
83 if (!enif_get_map_value(env, key, atom_password, &tmp_term))
84 goto err;
85 if (!enif_inspect_binary(env, tmp_term, &pwd_bin))
86 goto err;
87 if (!zero_terminate(pwd_bin, &pwd))
88 goto err;
89
90 return pwd;
91
92 err:
93 return NULL;
94 }
95
zero_terminate(ErlNifBinary bin,char ** buf)96 static int zero_terminate(ErlNifBinary bin, char **buf) {
97 if ((*buf = enif_alloc(bin.size + 1)) == NULL)
98 goto err;
99
100 memcpy(*buf, bin.data, bin.size);
101 *(*buf + bin.size) = 0;
102
103 return 1;
104
105 err:
106 return 0;
107 }
108 #endif /* HAS_ENGINE_SUPPORT */
109
init_engine_ctx(ErlNifEnv * env)110 int init_engine_ctx(ErlNifEnv *env) {
111 #ifdef HAS_ENGINE_SUPPORT
112 engine_ctx_rtype = enif_open_resource_type(env, NULL, "ENGINE_CTX",
113 (ErlNifResourceDtor*) engine_ctx_dtor,
114 ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
115 NULL);
116 if (engine_ctx_rtype == NULL) {
117 PRINTF_ERR0("CRYPTO: Could not open resource type 'ENGINE_CTX'");
118 return 0;
119 }
120 #endif
121
122 return 1;
123 }
124
engine_by_id_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])125 ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
126 {/* (EngineId) */
127 #ifdef HAS_ENGINE_SUPPORT
128 ERL_NIF_TERM ret, result;
129 ErlNifBinary engine_id_bin;
130 char *engine_id = NULL;
131 ENGINE *engine;
132 struct engine_ctx *ctx = NULL;
133
134 // Get Engine Id
135 ASSERT(argc == 1);
136
137 if (!enif_inspect_binary(env, argv[0], &engine_id_bin))
138 goto bad_arg;
139
140 if ((engine_id = enif_alloc(engine_id_bin.size+1)) == NULL)
141 goto err;
142 (void) memcpy(engine_id, engine_id_bin.data, engine_id_bin.size);
143 engine_id[engine_id_bin.size] = '\0';
144
145 if ((engine = ENGINE_by_id(engine_id)) == NULL) {
146 PRINTF_ERR0("engine_by_id_nif Leaved: {error, bad_engine_id}");
147 ret = ERROR_Atom(env, "bad_engine_id");
148 goto done;
149 }
150
151 if ((ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx))) == NULL)
152 goto err;
153 ctx->engine = engine;
154 ctx->is_functional = 0;
155 ctx->id = engine_id;
156 /* ctx now owns engine_id */
157 engine_id = NULL;
158
159 result = enif_make_resource(env, ctx);
160 ret = enif_make_tuple2(env, atom_ok, result);
161 goto done;
162
163 bad_arg:
164 err:
165 ret = enif_make_badarg(env);
166
167 done:
168 if (engine_id)
169 enif_free(engine_id);
170 if (ctx)
171 enif_release_resource(ctx);
172 return ret;
173
174 #else
175 return atom_notsup;
176 #endif
177 }
178
engine_init_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])179 ERL_NIF_TERM engine_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
180 {/* (Engine) */
181 #ifdef HAS_ENGINE_SUPPORT
182 struct engine_ctx *ctx;
183
184 // Get Engine
185 ASSERT(argc == 1);
186
187 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx))
188 goto bad_arg;
189
190 if (!ENGINE_init(ctx->engine))
191 return ERROR_Atom(env, "engine_init_failed");
192 ctx->is_functional = 1;
193 return atom_ok;
194
195 bad_arg:
196 return enif_make_badarg(env);
197
198 #else
199 return atom_notsup;
200 #endif
201 }
202
engine_free_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])203 ERL_NIF_TERM engine_free_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
204 {/* (Engine) */
205 #ifdef HAS_ENGINE_SUPPORT
206 struct engine_ctx *ctx;
207
208 // Get Engine
209 ASSERT(argc == 1);
210
211 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx))
212 goto bad_arg;
213
214 if (ctx->engine) {
215 if (ctx->is_functional) {
216 if (!ENGINE_finish(ctx->engine))
217 goto err;
218 ctx->is_functional = 0;
219 }
220 if (!ENGINE_free(ctx->engine))
221 goto err;
222 ctx->engine = NULL;
223 }
224 else {
225 ASSERT(!ctx->is_functional);
226 }
227 return atom_ok;
228
229 bad_arg:
230 err:
231 return enif_make_badarg(env);
232 #else
233 return atom_notsup;
234 #endif
235 }
236
engine_load_dynamic_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])237 ERL_NIF_TERM engine_load_dynamic_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
238 {/* () */
239 #ifdef HAS_ENGINE_SUPPORT
240 ASSERT(argc == 0);
241
242 ENGINE_load_dynamic();
243 return atom_ok;
244 #else
245 return atom_notsup;
246 #endif
247 }
248
engine_ctrl_cmd_strings_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])249 ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
250 {/* (Engine, Commands, Optional) */
251 #ifdef HAS_ENGINE_SUPPORT
252 ERL_NIF_TERM ret;
253 unsigned int cmds_len = 0;
254 char **cmds = NULL;
255 struct engine_ctx *ctx;
256 unsigned int i;
257 int optional = 0;
258 int cmds_loaded = 0;
259
260 // Get Engine
261 ASSERT(argc == 3);
262
263 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
264 || !ctx->engine)
265 goto bad_arg;
266
267 PRINTF_ERR1("Engine Id: %s\r\n", ENGINE_get_id(ctx->engine));
268 // Get Command List
269 if (!enif_get_list_length(env, argv[1], &cmds_len))
270 goto bad_arg;
271
272 if (cmds_len > (UINT_MAX / 2) - 1)
273 goto err;
274 cmds_len *= 2; // Key-Value list from erlang
275
276 if ((size_t)cmds_len + 1 > SIZE_MAX / sizeof(char*))
277 goto err;
278 if ((cmds = enif_alloc((cmds_len + 1) * sizeof(char*))) == NULL)
279 goto err;
280 if (get_engine_load_cmd_list(env, argv[1], cmds, 0))
281 goto err;
282 cmds_loaded = 1;
283 if (!enif_get_int(env, argv[2], &optional))
284 goto err;
285
286 for(i = 0; i < cmds_len; i+=2) {
287 PRINTF_ERR2("Cmd: %s:%s\r\n",
288 cmds[i] ? cmds[i] : "(NULL)",
289 cmds[i+1] ? cmds[i+1] : "(NULL)");
290 if(!ENGINE_ctrl_cmd_string(ctx->engine, cmds[i], cmds[i+1], optional)) {
291 PRINTF_ERR2("Command failed: %s:%s\r\n",
292 cmds[i] ? cmds[i] : "(NULL)",
293 cmds[i+1] ? cmds[i+1] : "(NULL)");
294 goto cmd_failed;
295 }
296 }
297 ret = atom_ok;
298 goto done;
299
300 bad_arg:
301 err:
302 ret = enif_make_badarg(env);
303 goto done;
304
305 cmd_failed:
306 ret = ERROR_Atom(env, "ctrl_cmd_failed");
307
308 done:
309 if (cmds_loaded) {
310 for (i = 0; cmds != NULL && cmds[i] != NULL; i++)
311 enif_free(cmds[i]);
312 }
313
314 if (cmds != NULL)
315 enif_free(cmds);
316
317 return ret;
318
319 #else
320 return atom_notsup;
321 #endif
322 }
323
engine_add_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])324 ERL_NIF_TERM engine_add_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
325 {/* (Engine) */
326 #ifdef HAS_ENGINE_SUPPORT
327 struct engine_ctx *ctx;
328
329 // Get Engine
330 ASSERT(argc == 1);
331
332 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
333 || !ctx->engine)
334 goto bad_arg;
335
336 if (!ENGINE_add(ctx->engine))
337 goto failed;
338
339 return atom_ok;
340
341 bad_arg:
342 return enif_make_badarg(env);
343
344 failed:
345 return ERROR_Atom(env, "add_engine_failed");
346
347 #else
348 return atom_notsup;
349 #endif
350 }
351
engine_remove_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])352 ERL_NIF_TERM engine_remove_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
353 {/* (Engine) */
354 #ifdef HAS_ENGINE_SUPPORT
355 struct engine_ctx *ctx;
356
357 // Get Engine
358 ASSERT(argc == 1);
359
360 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
361 || !ctx->engine)
362 goto bad_arg;
363
364 if (!ENGINE_remove(ctx->engine))
365 goto failed;
366
367 return atom_ok;
368
369 bad_arg:
370 return enif_make_badarg(env);
371
372 failed:
373 return ERROR_Atom(env, "remove_engine_failed");
374 #else
375 return atom_notsup;
376 #endif
377 }
378
engine_register_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])379 ERL_NIF_TERM engine_register_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
380 {/* (Engine, EngineMethod) */
381 #ifdef HAS_ENGINE_SUPPORT
382 struct engine_ctx *ctx;
383 unsigned int method;
384
385 // Get Engine
386 ASSERT(argc == 2);
387
388 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
389 || !ctx->engine)
390 goto bad_arg;
391 if (!enif_get_uint(env, argv[1], &method))
392 goto bad_arg;
393
394 switch(method)
395 {
396 #ifdef ENGINE_METHOD_RSA
397 case ENGINE_METHOD_RSA:
398 if (!ENGINE_register_RSA(ctx->engine))
399 goto failed;
400 break;
401 #endif
402 #ifdef ENGINE_METHOD_DSA
403 case ENGINE_METHOD_DSA:
404 if (!ENGINE_register_DSA(ctx->engine))
405 goto failed;
406 break;
407 #endif
408 #ifdef ENGINE_METHOD_DH
409 case ENGINE_METHOD_DH:
410 if (!ENGINE_register_DH(ctx->engine))
411 goto failed;
412 break;
413 #endif
414 #ifdef ENGINE_METHOD_RAND
415 case ENGINE_METHOD_RAND:
416 if (!ENGINE_register_RAND(ctx->engine))
417 goto failed;
418 break;
419 #endif
420 #ifdef ENGINE_METHOD_ECDH
421 case ENGINE_METHOD_ECDH:
422 if (!ENGINE_register_ECDH(ctx->engine))
423 goto failed;
424 break;
425 #endif
426 #ifdef ENGINE_METHOD_ECDSA
427 case ENGINE_METHOD_ECDSA:
428 if (!ENGINE_register_ECDSA(ctx->engine))
429 goto failed;
430 break;
431 #endif
432 #ifdef ENGINE_METHOD_STORE
433 case ENGINE_METHOD_STORE:
434 if (!ENGINE_register_STORE(ctx->engine))
435 goto failed;
436 break;
437 #endif
438 #ifdef ENGINE_METHOD_CIPHERS
439 case ENGINE_METHOD_CIPHERS:
440 if (!ENGINE_register_ciphers(ctx->engine))
441 goto failed;
442 break;
443 #endif
444 #ifdef ENGINE_METHOD_DIGESTS
445 case ENGINE_METHOD_DIGESTS:
446 if (!ENGINE_register_digests(ctx->engine))
447 goto failed;
448 break;
449 #endif
450 #ifdef ENGINE_METHOD_PKEY_METHS
451 case ENGINE_METHOD_PKEY_METHS:
452 if (!ENGINE_register_pkey_meths(ctx->engine))
453 goto failed;
454 break;
455 #endif
456 #ifdef ENGINE_METHOD_PKEY_ASN1_METHS
457 case ENGINE_METHOD_PKEY_ASN1_METHS:
458 if (!ENGINE_register_pkey_asn1_meths(ctx->engine))
459 goto failed;
460 break;
461 #endif
462 #ifdef ENGINE_METHOD_EC
463 case ENGINE_METHOD_EC:
464 if (!ENGINE_register_EC(ctx->engine))
465 goto failed;
466 break;
467 #endif
468 default:
469 return ERROR_Atom(env, "engine_method_not_supported");
470 }
471
472 return atom_ok;
473
474 bad_arg:
475 return enif_make_badarg(env);
476
477 failed:
478 return ERROR_Atom(env, "register_engine_failed");
479
480 #else
481 return atom_notsup;
482 #endif
483 }
484
engine_unregister_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])485 ERL_NIF_TERM engine_unregister_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
486 {/* (Engine, EngineMethod) */
487 #ifdef HAS_ENGINE_SUPPORT
488 struct engine_ctx *ctx;
489 unsigned int method;
490
491 // Get Engine
492 ASSERT(argc == 2);
493
494 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
495 || !ctx->engine)
496 goto bad_arg;
497 if (!enif_get_uint(env, argv[1], &method))
498 goto bad_arg;
499
500 switch(method)
501 {
502 #ifdef ENGINE_METHOD_RSA
503 case ENGINE_METHOD_RSA:
504 ENGINE_unregister_RSA(ctx->engine);
505 break;
506 #endif
507 #ifdef ENGINE_METHOD_DSA
508 case ENGINE_METHOD_DSA:
509 ENGINE_unregister_DSA(ctx->engine);
510 break;
511 #endif
512 #ifdef ENGINE_METHOD_DH
513 case ENGINE_METHOD_DH:
514 ENGINE_unregister_DH(ctx->engine);
515 break;
516 #endif
517 #ifdef ENGINE_METHOD_RAND
518 case ENGINE_METHOD_RAND:
519 ENGINE_unregister_RAND(ctx->engine);
520 break;
521 #endif
522 #ifdef ENGINE_METHOD_ECDH
523 case ENGINE_METHOD_ECDH:
524 ENGINE_unregister_ECDH(ctx->engine);
525 break;
526 #endif
527 #ifdef ENGINE_METHOD_ECDSA
528 case ENGINE_METHOD_ECDSA:
529 ENGINE_unregister_ECDSA(ctx->engine);
530 break;
531 #endif
532 #ifdef ENGINE_METHOD_STORE
533 case ENGINE_METHOD_STORE:
534 ENGINE_unregister_STORE(ctx->engine);
535 break;
536 #endif
537 #ifdef ENGINE_METHOD_CIPHERS
538 case ENGINE_METHOD_CIPHERS:
539 ENGINE_unregister_ciphers(ctx->engine);
540 break;
541 #endif
542 #ifdef ENGINE_METHOD_DIGESTS
543 case ENGINE_METHOD_DIGESTS:
544 ENGINE_unregister_digests(ctx->engine);
545 break;
546 #endif
547 #ifdef ENGINE_METHOD_PKEY_METHS
548 case ENGINE_METHOD_PKEY_METHS:
549 ENGINE_unregister_pkey_meths(ctx->engine);
550 break;
551 #endif
552 #ifdef ENGINE_METHOD_PKEY_ASN1_METHS
553 case ENGINE_METHOD_PKEY_ASN1_METHS:
554 ENGINE_unregister_pkey_asn1_meths(ctx->engine);
555 break;
556 #endif
557 #ifdef ENGINE_METHOD_EC
558 case ENGINE_METHOD_EC:
559 ENGINE_unregister_EC(ctx->engine);
560 break;
561 #endif
562 default:
563 break;
564 }
565
566 return atom_ok;
567
568 bad_arg:
569 return enif_make_badarg(env);
570
571 #else
572 return atom_notsup;
573 #endif
574 }
575
engine_get_first_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])576 ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
577 {/* () */
578 #ifdef HAS_ENGINE_SUPPORT
579 ERL_NIF_TERM ret, result;
580 ENGINE *engine;
581 ErlNifBinary engine_bin;
582 struct engine_ctx *ctx = NULL;
583
584 ASSERT(argc == 0);
585
586 if ((engine = ENGINE_get_first()) == NULL) {
587 if (!enif_alloc_binary(0, &engine_bin))
588 goto err;
589 engine_bin.size = 0;
590 return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_bin));
591 }
592
593 if ((ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx))) == NULL)
594 goto err;
595 ctx->is_functional = 0;
596 ctx->engine = engine;
597 ctx->id = NULL;
598
599 result = enif_make_resource(env, ctx);
600 ret = enif_make_tuple2(env, atom_ok, result);
601 goto done;
602
603 err:
604 ret = enif_make_badarg(env);
605
606 done:
607 if (ctx)
608 enif_release_resource(ctx);
609 return ret;
610
611 #else
612 return atom_notsup;
613 #endif
614 }
615
engine_get_next_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])616 ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
617 {/* (Engine) */
618 #ifdef HAS_ENGINE_SUPPORT
619 ERL_NIF_TERM ret, result;
620 ENGINE *engine;
621 ErlNifBinary engine_bin;
622 struct engine_ctx *ctx, *next_ctx = NULL;
623
624 // Get Engine
625 ASSERT(argc == 1);
626
627 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
628 || !ctx->engine)
629 goto bad_arg;
630
631 if (ctx->is_functional) {
632 ENGINE_finish(ctx->engine);
633 ctx->is_functional = 0;
634 }
635 engine = ENGINE_get_next(ctx->engine);
636 ctx->engine = NULL;
637
638 if (engine == NULL) {
639 if (!enif_alloc_binary(0, &engine_bin))
640 goto err;
641 engine_bin.size = 0;
642 return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_bin));
643 }
644
645 if ((next_ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx))) == NULL)
646 goto err;
647 next_ctx->engine = engine;
648 next_ctx->is_functional = 0;
649 next_ctx->id = NULL;
650
651 result = enif_make_resource(env, next_ctx);
652 ret = enif_make_tuple2(env, atom_ok, result);
653 goto done;
654
655 bad_arg:
656 err:
657 ret = enif_make_badarg(env);
658
659 done:
660 if (next_ctx)
661 enif_release_resource(next_ctx);
662 return ret;
663
664 #else
665 return atom_notsup;
666 #endif
667 }
668
engine_get_id_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])669 ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
670 {/* (Engine) */
671 #ifdef HAS_ENGINE_SUPPORT
672 ErlNifBinary engine_id_bin;
673 const char *engine_id;
674 size_t size;
675 struct engine_ctx *ctx = NULL;
676
677 // Get Engine
678 ASSERT(argc == 1);
679
680 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
681 || !ctx->engine)
682 goto bad_arg;
683
684 if ((engine_id = ENGINE_get_id(ctx->engine)) == NULL) {
685 if (!enif_alloc_binary(0, &engine_id_bin))
686 goto err;
687 engine_id_bin.size = 0;
688 return enif_make_binary(env, &engine_id_bin);
689 }
690
691 size = strlen(engine_id);
692 if (!enif_alloc_binary(size, &engine_id_bin))
693 goto err;
694 engine_id_bin.size = size;
695 memcpy(engine_id_bin.data, engine_id, size);
696
697 return enif_make_binary(env, &engine_id_bin);
698
699 bad_arg:
700 err:
701 return enif_make_badarg(env);
702
703 #else
704 return atom_notsup;
705 #endif
706 }
707
engine_get_name_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])708 ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
709 {/* (Engine) */
710 #ifdef HAS_ENGINE_SUPPORT
711 ErlNifBinary engine_name_bin;
712 const char *engine_name;
713 size_t size;
714 struct engine_ctx *ctx;
715
716 // Get Engine
717 ASSERT(argc == 1);
718
719 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
720 || !ctx->engine)
721 goto bad_arg;
722
723 if ((engine_name = ENGINE_get_name(ctx->engine)) == NULL) {
724 if (!enif_alloc_binary(0, &engine_name_bin))
725 goto err;
726 engine_name_bin.size = 0;
727 return enif_make_binary(env, &engine_name_bin);
728 }
729
730 size = strlen(engine_name);
731 if (!enif_alloc_binary(size, &engine_name_bin))
732 goto err;
733 engine_name_bin.size = size;
734 memcpy(engine_name_bin.data, engine_name, size);
735
736 return enif_make_binary(env, &engine_name_bin);
737
738 bad_arg:
739 err:
740 return enif_make_badarg(env);
741
742 #else
743 return atom_notsup;
744 #endif
745 }
746
747 #ifdef HAS_ENGINE_SUPPORT
get_engine_load_cmd_list(ErlNifEnv * env,const ERL_NIF_TERM term,char ** cmds,int i)748 static int get_engine_load_cmd_list(ErlNifEnv* env, const ERL_NIF_TERM term, char **cmds, int i)
749 {
750 ERL_NIF_TERM head, tail;
751 const ERL_NIF_TERM *tmp_tuple;
752 ErlNifBinary tmpbin;
753 int arity;
754 char *tuple1 = NULL, *tuple2 = NULL;
755
756 if (enif_is_empty_list(env, term)) {
757 cmds[i] = NULL;
758 return 0;
759 }
760
761 if (!enif_get_list_cell(env, term, &head, &tail))
762 goto err;
763 if (!enif_get_tuple(env, head, &arity, &tmp_tuple))
764 goto err;
765 if (arity != 2)
766 goto err;
767 if (!enif_inspect_binary(env, tmp_tuple[0], &tmpbin))
768 goto err;
769
770 if ((tuple1 = enif_alloc(tmpbin.size + 1)) == NULL)
771 goto err;
772
773 (void) memcpy(tuple1, tmpbin.data, tmpbin.size);
774 tuple1[tmpbin.size] = '\0';
775 cmds[i] = tuple1;
776 i++;
777
778 if (!enif_inspect_binary(env, tmp_tuple[1], &tmpbin))
779 goto err;
780
781 if (tmpbin.size == 0) {
782 cmds[i] = NULL;
783 } else {
784 if ((tuple2 = enif_alloc(tmpbin.size + 1)) == NULL)
785 goto err;
786 (void) memcpy(tuple2, tmpbin.data, tmpbin.size);
787 tuple2[tmpbin.size] = '\0';
788 cmds[i] = tuple2;
789 }
790 i++;
791 return get_engine_load_cmd_list(env, tail, cmds, i);
792
793 err:
794 if (tuple1 != NULL) {
795 i--;
796 enif_free(tuple1);
797 }
798 cmds[i] = NULL;
799 return -1;
800 }
801 #endif /* HAS_ENGINE_SUPPORT */
802
engine_get_all_methods_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])803 ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
804 {/* () */
805 #ifdef HAS_ENGINE_SUPPORT
806 ERL_NIF_TERM method_array[12];
807 unsigned int i = 0;
808
809 ASSERT(argc == 0);
810
811 #ifdef ENGINE_METHOD_RSA
812 method_array[i++] = atom_engine_method_rsa;
813 #endif
814 #ifdef ENGINE_METHOD_DSA
815 method_array[i++] = atom_engine_method_dsa;
816 #endif
817 #ifdef ENGINE_METHOD_DH
818 method_array[i++] = atom_engine_method_dh;
819 #endif
820 #ifdef ENGINE_METHOD_RAND
821 method_array[i++] = atom_engine_method_rand;
822 #endif
823 #ifdef ENGINE_METHOD_ECDH
824 method_array[i++] = atom_engine_method_ecdh;
825 #endif
826 #ifdef ENGINE_METHOD_ECDSA
827 method_array[i++] = atom_engine_method_ecdsa;
828 #endif
829 #ifdef ENGINE_METHOD_STORE
830 method_array[i++] = atom_engine_method_store;
831 #endif
832 #ifdef ENGINE_METHOD_CIPHERS
833 method_array[i++] = atom_engine_method_ciphers;
834 #endif
835 #ifdef ENGINE_METHOD_DIGESTS
836 method_array[i++] = atom_engine_method_digests;
837 #endif
838 #ifdef ENGINE_METHOD_PKEY_METHS
839 method_array[i++] = atom_engine_method_pkey_meths;
840 #endif
841 #ifdef ENGINE_METHOD_PKEY_ASN1_METHS
842 method_array[i++] = atom_engine_method_pkey_asn1_meths;
843 #endif
844 #ifdef ENGINE_METHOD_EC
845 method_array[i++] = atom_engine_method_ec;
846 #endif
847
848 return enif_make_list_from_array(env, method_array, i);
849 #else
850 return atom_notsup;
851 #endif
852 }
853