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 || ctx->is_functional)
213 goto bad_arg;
214
215 if (!ENGINE_free(ctx->engine))
216 goto err;
217 ctx->engine = NULL;
218 return atom_ok;
219
220 bad_arg:
221 err:
222 return enif_make_badarg(env);
223 #else
224 return atom_notsup;
225 #endif
226 }
227
engine_finish_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])228 ERL_NIF_TERM engine_finish_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
229 {/* (Engine) */
230 #ifdef HAS_ENGINE_SUPPORT
231 struct engine_ctx *ctx;
232
233 // Get Engine
234 ASSERT(argc == 1);
235
236 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
237 || !ctx->is_functional)
238 goto bad_arg;
239
240 if (!ENGINE_finish(ctx->engine))
241 goto err;
242 ctx->is_functional = 0;
243 return atom_ok;
244
245 bad_arg:
246 err:
247 return enif_make_badarg(env);
248
249 #else
250 return atom_notsup;
251 #endif
252 }
253
engine_load_dynamic_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])254 ERL_NIF_TERM engine_load_dynamic_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
255 {/* () */
256 #ifdef HAS_ENGINE_SUPPORT
257 ASSERT(argc == 0);
258
259 ENGINE_load_dynamic();
260 return atom_ok;
261 #else
262 return atom_notsup;
263 #endif
264 }
265
engine_ctrl_cmd_strings_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])266 ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
267 {/* (Engine, Commands, Optional) */
268 #ifdef HAS_ENGINE_SUPPORT
269 ERL_NIF_TERM ret;
270 unsigned int cmds_len = 0;
271 char **cmds = NULL;
272 struct engine_ctx *ctx;
273 unsigned int i;
274 int optional = 0;
275 int cmds_loaded = 0;
276
277 // Get Engine
278 ASSERT(argc == 3);
279
280 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
281 || !ctx->engine)
282 goto bad_arg;
283
284 PRINTF_ERR1("Engine Id: %s\r\n", ENGINE_get_id(ctx->engine));
285 // Get Command List
286 if (!enif_get_list_length(env, argv[1], &cmds_len))
287 goto bad_arg;
288
289 if (cmds_len > (UINT_MAX / 2) - 1)
290 goto err;
291 cmds_len *= 2; // Key-Value list from erlang
292
293 if ((size_t)cmds_len + 1 > SIZE_MAX / sizeof(char*))
294 goto err;
295 if ((cmds = enif_alloc((cmds_len + 1) * sizeof(char*))) == NULL)
296 goto err;
297 if (get_engine_load_cmd_list(env, argv[1], cmds, 0))
298 goto err;
299 cmds_loaded = 1;
300 if (!enif_get_int(env, argv[2], &optional))
301 goto err;
302
303 for(i = 0; i < cmds_len; i+=2) {
304 PRINTF_ERR2("Cmd: %s:%s\r\n",
305 cmds[i] ? cmds[i] : "(NULL)",
306 cmds[i+1] ? cmds[i+1] : "(NULL)");
307 if(!ENGINE_ctrl_cmd_string(ctx->engine, cmds[i], cmds[i+1], optional)) {
308 PRINTF_ERR2("Command failed: %s:%s\r\n",
309 cmds[i] ? cmds[i] : "(NULL)",
310 cmds[i+1] ? cmds[i+1] : "(NULL)");
311 goto cmd_failed;
312 }
313 }
314 ret = atom_ok;
315 goto done;
316
317 bad_arg:
318 err:
319 ret = enif_make_badarg(env);
320 goto done;
321
322 cmd_failed:
323 ret = ERROR_Atom(env, "ctrl_cmd_failed");
324
325 done:
326 if (cmds_loaded) {
327 for (i = 0; cmds != NULL && cmds[i] != NULL; i++)
328 enif_free(cmds[i]);
329 }
330
331 if (cmds != NULL)
332 enif_free(cmds);
333
334 return ret;
335
336 #else
337 return atom_notsup;
338 #endif
339 }
340
engine_add_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])341 ERL_NIF_TERM engine_add_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
342 {/* (Engine) */
343 #ifdef HAS_ENGINE_SUPPORT
344 struct engine_ctx *ctx;
345
346 // Get Engine
347 ASSERT(argc == 1);
348
349 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
350 || !ctx->engine)
351 goto bad_arg;
352
353 if (!ENGINE_add(ctx->engine))
354 goto failed;
355
356 return atom_ok;
357
358 bad_arg:
359 return enif_make_badarg(env);
360
361 failed:
362 return ERROR_Atom(env, "add_engine_failed");
363
364 #else
365 return atom_notsup;
366 #endif
367 }
368
engine_remove_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])369 ERL_NIF_TERM engine_remove_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
370 {/* (Engine) */
371 #ifdef HAS_ENGINE_SUPPORT
372 struct engine_ctx *ctx;
373
374 // Get Engine
375 ASSERT(argc == 1);
376
377 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
378 || !ctx->engine)
379 goto bad_arg;
380
381 if (!ENGINE_remove(ctx->engine))
382 goto failed;
383
384 return atom_ok;
385
386 bad_arg:
387 return enif_make_badarg(env);
388
389 failed:
390 return ERROR_Atom(env, "remove_engine_failed");
391 #else
392 return atom_notsup;
393 #endif
394 }
395
engine_register_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])396 ERL_NIF_TERM engine_register_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
397 {/* (Engine, EngineMethod) */
398 #ifdef HAS_ENGINE_SUPPORT
399 struct engine_ctx *ctx;
400 unsigned int method;
401
402 // Get Engine
403 ASSERT(argc == 2);
404
405 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
406 || !ctx->engine)
407 goto bad_arg;
408 if (!enif_get_uint(env, argv[1], &method))
409 goto bad_arg;
410
411 switch(method)
412 {
413 #ifdef ENGINE_METHOD_RSA
414 case ENGINE_METHOD_RSA:
415 if (!ENGINE_register_RSA(ctx->engine))
416 goto failed;
417 break;
418 #endif
419 #ifdef ENGINE_METHOD_DSA
420 case ENGINE_METHOD_DSA:
421 if (!ENGINE_register_DSA(ctx->engine))
422 goto failed;
423 break;
424 #endif
425 #ifdef ENGINE_METHOD_DH
426 case ENGINE_METHOD_DH:
427 if (!ENGINE_register_DH(ctx->engine))
428 goto failed;
429 break;
430 #endif
431 #ifdef ENGINE_METHOD_RAND
432 case ENGINE_METHOD_RAND:
433 if (!ENGINE_register_RAND(ctx->engine))
434 goto failed;
435 break;
436 #endif
437 #ifdef ENGINE_METHOD_ECDH
438 case ENGINE_METHOD_ECDH:
439 if (!ENGINE_register_ECDH(ctx->engine))
440 goto failed;
441 break;
442 #endif
443 #ifdef ENGINE_METHOD_ECDSA
444 case ENGINE_METHOD_ECDSA:
445 if (!ENGINE_register_ECDSA(ctx->engine))
446 goto failed;
447 break;
448 #endif
449 #ifdef ENGINE_METHOD_STORE
450 case ENGINE_METHOD_STORE:
451 if (!ENGINE_register_STORE(ctx->engine))
452 goto failed;
453 break;
454 #endif
455 #ifdef ENGINE_METHOD_CIPHERS
456 case ENGINE_METHOD_CIPHERS:
457 if (!ENGINE_register_ciphers(ctx->engine))
458 goto failed;
459 break;
460 #endif
461 #ifdef ENGINE_METHOD_DIGESTS
462 case ENGINE_METHOD_DIGESTS:
463 if (!ENGINE_register_digests(ctx->engine))
464 goto failed;
465 break;
466 #endif
467 #ifdef ENGINE_METHOD_PKEY_METHS
468 case ENGINE_METHOD_PKEY_METHS:
469 if (!ENGINE_register_pkey_meths(ctx->engine))
470 goto failed;
471 break;
472 #endif
473 #ifdef ENGINE_METHOD_PKEY_ASN1_METHS
474 case ENGINE_METHOD_PKEY_ASN1_METHS:
475 if (!ENGINE_register_pkey_asn1_meths(ctx->engine))
476 goto failed;
477 break;
478 #endif
479 #ifdef ENGINE_METHOD_EC
480 case ENGINE_METHOD_EC:
481 if (!ENGINE_register_EC(ctx->engine))
482 goto failed;
483 break;
484 #endif
485 default:
486 return ERROR_Atom(env, "engine_method_not_supported");
487 }
488
489 return atom_ok;
490
491 bad_arg:
492 return enif_make_badarg(env);
493
494 failed:
495 return ERROR_Atom(env, "register_engine_failed");
496
497 #else
498 return atom_notsup;
499 #endif
500 }
501
engine_unregister_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])502 ERL_NIF_TERM engine_unregister_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
503 {/* (Engine, EngineMethod) */
504 #ifdef HAS_ENGINE_SUPPORT
505 struct engine_ctx *ctx;
506 unsigned int method;
507
508 // Get Engine
509 ASSERT(argc == 2);
510
511 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
512 || !ctx->engine)
513 goto bad_arg;
514 if (!enif_get_uint(env, argv[1], &method))
515 goto bad_arg;
516
517 switch(method)
518 {
519 #ifdef ENGINE_METHOD_RSA
520 case ENGINE_METHOD_RSA:
521 ENGINE_unregister_RSA(ctx->engine);
522 break;
523 #endif
524 #ifdef ENGINE_METHOD_DSA
525 case ENGINE_METHOD_DSA:
526 ENGINE_unregister_DSA(ctx->engine);
527 break;
528 #endif
529 #ifdef ENGINE_METHOD_DH
530 case ENGINE_METHOD_DH:
531 ENGINE_unregister_DH(ctx->engine);
532 break;
533 #endif
534 #ifdef ENGINE_METHOD_RAND
535 case ENGINE_METHOD_RAND:
536 ENGINE_unregister_RAND(ctx->engine);
537 break;
538 #endif
539 #ifdef ENGINE_METHOD_ECDH
540 case ENGINE_METHOD_ECDH:
541 ENGINE_unregister_ECDH(ctx->engine);
542 break;
543 #endif
544 #ifdef ENGINE_METHOD_ECDSA
545 case ENGINE_METHOD_ECDSA:
546 ENGINE_unregister_ECDSA(ctx->engine);
547 break;
548 #endif
549 #ifdef ENGINE_METHOD_STORE
550 case ENGINE_METHOD_STORE:
551 ENGINE_unregister_STORE(ctx->engine);
552 break;
553 #endif
554 #ifdef ENGINE_METHOD_CIPHERS
555 case ENGINE_METHOD_CIPHERS:
556 ENGINE_unregister_ciphers(ctx->engine);
557 break;
558 #endif
559 #ifdef ENGINE_METHOD_DIGESTS
560 case ENGINE_METHOD_DIGESTS:
561 ENGINE_unregister_digests(ctx->engine);
562 break;
563 #endif
564 #ifdef ENGINE_METHOD_PKEY_METHS
565 case ENGINE_METHOD_PKEY_METHS:
566 ENGINE_unregister_pkey_meths(ctx->engine);
567 break;
568 #endif
569 #ifdef ENGINE_METHOD_PKEY_ASN1_METHS
570 case ENGINE_METHOD_PKEY_ASN1_METHS:
571 ENGINE_unregister_pkey_asn1_meths(ctx->engine);
572 break;
573 #endif
574 #ifdef ENGINE_METHOD_EC
575 case ENGINE_METHOD_EC:
576 ENGINE_unregister_EC(ctx->engine);
577 break;
578 #endif
579 default:
580 break;
581 }
582
583 return atom_ok;
584
585 bad_arg:
586 return enif_make_badarg(env);
587
588 #else
589 return atom_notsup;
590 #endif
591 }
592
engine_get_first_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])593 ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
594 {/* () */
595 #ifdef HAS_ENGINE_SUPPORT
596 ERL_NIF_TERM ret, result;
597 ENGINE *engine;
598 ErlNifBinary engine_bin;
599 struct engine_ctx *ctx = NULL;
600
601 ASSERT(argc == 0);
602
603 if ((engine = ENGINE_get_first()) == NULL) {
604 if (!enif_alloc_binary(0, &engine_bin))
605 goto err;
606 engine_bin.size = 0;
607 return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_bin));
608 }
609
610 if ((ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx))) == NULL)
611 goto err;
612 ctx->is_functional = 0;
613 ctx->engine = engine;
614 ctx->id = NULL;
615
616 result = enif_make_resource(env, ctx);
617 ret = enif_make_tuple2(env, atom_ok, result);
618 goto done;
619
620 err:
621 ret = enif_make_badarg(env);
622
623 done:
624 if (ctx)
625 enif_release_resource(ctx);
626 return ret;
627
628 #else
629 return atom_notsup;
630 #endif
631 }
632
engine_get_next_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])633 ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
634 {/* (Engine) */
635 #ifdef HAS_ENGINE_SUPPORT
636 ERL_NIF_TERM ret, result;
637 ENGINE *engine;
638 ErlNifBinary engine_bin;
639 struct engine_ctx *ctx, *next_ctx = NULL;
640
641 // Get Engine
642 ASSERT(argc == 1);
643
644 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
645 || !ctx->engine)
646 goto bad_arg;
647
648 engine = ENGINE_get_next(ctx->engine);
649 ctx->engine = NULL;
650
651 if (engine == NULL) {
652 if (!enif_alloc_binary(0, &engine_bin))
653 goto err;
654 engine_bin.size = 0;
655 return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_bin));
656 }
657
658 if ((next_ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx))) == NULL)
659 goto err;
660 next_ctx->engine = engine;
661 next_ctx->is_functional = 0;
662 next_ctx->id = NULL;
663
664 result = enif_make_resource(env, next_ctx);
665 ret = enif_make_tuple2(env, atom_ok, result);
666 goto done;
667
668 bad_arg:
669 err:
670 ret = enif_make_badarg(env);
671
672 done:
673 if (next_ctx)
674 enif_release_resource(next_ctx);
675 return ret;
676
677 #else
678 return atom_notsup;
679 #endif
680 }
681
engine_get_id_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])682 ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
683 {/* (Engine) */
684 #ifdef HAS_ENGINE_SUPPORT
685 ErlNifBinary engine_id_bin;
686 const char *engine_id;
687 size_t size;
688 struct engine_ctx *ctx = NULL;
689
690 // Get Engine
691 ASSERT(argc == 1);
692
693 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
694 || !ctx->engine)
695 goto bad_arg;
696
697 if ((engine_id = ENGINE_get_id(ctx->engine)) == NULL) {
698 if (!enif_alloc_binary(0, &engine_id_bin))
699 goto err;
700 engine_id_bin.size = 0;
701 return enif_make_binary(env, &engine_id_bin);
702 }
703
704 size = strlen(engine_id);
705 if (!enif_alloc_binary(size, &engine_id_bin))
706 goto err;
707 engine_id_bin.size = size;
708 memcpy(engine_id_bin.data, engine_id, size);
709
710 return enif_make_binary(env, &engine_id_bin);
711
712 bad_arg:
713 err:
714 return enif_make_badarg(env);
715
716 #else
717 return atom_notsup;
718 #endif
719 }
720
engine_get_name_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])721 ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
722 {/* (Engine) */
723 #ifdef HAS_ENGINE_SUPPORT
724 ErlNifBinary engine_name_bin;
725 const char *engine_name;
726 size_t size;
727 struct engine_ctx *ctx;
728
729 // Get Engine
730 ASSERT(argc == 1);
731
732 if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
733 || !ctx->engine)
734 goto bad_arg;
735
736 if ((engine_name = ENGINE_get_name(ctx->engine)) == NULL) {
737 if (!enif_alloc_binary(0, &engine_name_bin))
738 goto err;
739 engine_name_bin.size = 0;
740 return enif_make_binary(env, &engine_name_bin);
741 }
742
743 size = strlen(engine_name);
744 if (!enif_alloc_binary(size, &engine_name_bin))
745 goto err;
746 engine_name_bin.size = size;
747 memcpy(engine_name_bin.data, engine_name, size);
748
749 return enif_make_binary(env, &engine_name_bin);
750
751 bad_arg:
752 err:
753 return enif_make_badarg(env);
754
755 #else
756 return atom_notsup;
757 #endif
758 }
759
760 #ifdef HAS_ENGINE_SUPPORT
get_engine_load_cmd_list(ErlNifEnv * env,const ERL_NIF_TERM term,char ** cmds,int i)761 static int get_engine_load_cmd_list(ErlNifEnv* env, const ERL_NIF_TERM term, char **cmds, int i)
762 {
763 ERL_NIF_TERM head, tail;
764 const ERL_NIF_TERM *tmp_tuple;
765 ErlNifBinary tmpbin;
766 int arity;
767 char *tuple1 = NULL, *tuple2 = NULL;
768
769 if (enif_is_empty_list(env, term)) {
770 cmds[i] = NULL;
771 return 0;
772 }
773
774 if (!enif_get_list_cell(env, term, &head, &tail))
775 goto err;
776 if (!enif_get_tuple(env, head, &arity, &tmp_tuple))
777 goto err;
778 if (arity != 2)
779 goto err;
780 if (!enif_inspect_binary(env, tmp_tuple[0], &tmpbin))
781 goto err;
782
783 if ((tuple1 = enif_alloc(tmpbin.size + 1)) == NULL)
784 goto err;
785
786 (void) memcpy(tuple1, tmpbin.data, tmpbin.size);
787 tuple1[tmpbin.size] = '\0';
788 cmds[i] = tuple1;
789 i++;
790
791 if (!enif_inspect_binary(env, tmp_tuple[1], &tmpbin))
792 goto err;
793
794 if (tmpbin.size == 0) {
795 cmds[i] = NULL;
796 } else {
797 if ((tuple2 = enif_alloc(tmpbin.size + 1)) == NULL)
798 goto err;
799 (void) memcpy(tuple2, tmpbin.data, tmpbin.size);
800 tuple2[tmpbin.size] = '\0';
801 cmds[i] = tuple2;
802 }
803 i++;
804 return get_engine_load_cmd_list(env, tail, cmds, i);
805
806 err:
807 if (tuple1 != NULL) {
808 i--;
809 enif_free(tuple1);
810 }
811 cmds[i] = NULL;
812 return -1;
813 }
814 #endif /* HAS_ENGINE_SUPPORT */
815
engine_get_all_methods_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])816 ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
817 {/* () */
818 #ifdef HAS_ENGINE_SUPPORT
819 ERL_NIF_TERM method_array[12];
820 unsigned int i = 0;
821
822 ASSERT(argc == 0);
823
824 #ifdef ENGINE_METHOD_RSA
825 method_array[i++] = atom_engine_method_rsa;
826 #endif
827 #ifdef ENGINE_METHOD_DSA
828 method_array[i++] = atom_engine_method_dsa;
829 #endif
830 #ifdef ENGINE_METHOD_DH
831 method_array[i++] = atom_engine_method_dh;
832 #endif
833 #ifdef ENGINE_METHOD_RAND
834 method_array[i++] = atom_engine_method_rand;
835 #endif
836 #ifdef ENGINE_METHOD_ECDH
837 method_array[i++] = atom_engine_method_ecdh;
838 #endif
839 #ifdef ENGINE_METHOD_ECDSA
840 method_array[i++] = atom_engine_method_ecdsa;
841 #endif
842 #ifdef ENGINE_METHOD_STORE
843 method_array[i++] = atom_engine_method_store;
844 #endif
845 #ifdef ENGINE_METHOD_CIPHERS
846 method_array[i++] = atom_engine_method_ciphers;
847 #endif
848 #ifdef ENGINE_METHOD_DIGESTS
849 method_array[i++] = atom_engine_method_digests;
850 #endif
851 #ifdef ENGINE_METHOD_PKEY_METHS
852 method_array[i++] = atom_engine_method_pkey_meths;
853 #endif
854 #ifdef ENGINE_METHOD_PKEY_ASN1_METHS
855 method_array[i++] = atom_engine_method_pkey_asn1_meths;
856 #endif
857 #ifdef ENGINE_METHOD_EC
858 method_array[i++] = atom_engine_method_ec;
859 #endif
860
861 return enif_make_list_from_array(env, method_array, i);
862 #else
863 return atom_notsup;
864 #endif
865 }
866