16f9291ceSJung-uk Kim /*
2*6f1af0d7SPierre Pronchery * Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
45c87c606SMark Murray *
5b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
6e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy
7e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at
8e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html
93b4e3dcbSSimon L. B. Nielsen */
105c87c606SMark Murray
11b077aed3SPierre Pronchery /* We need to use some engine deprecated APIs */
12b077aed3SPierre Pronchery #define OPENSSL_SUPPRESS_DEPRECATED
13b077aed3SPierre Pronchery
1417f01e99SJung-uk Kim #include "eng_local.h"
155c87c606SMark Murray
166f9291ceSJung-uk Kim /*
176f9291ceSJung-uk Kim * The linked-list of pointers to engine types. engine_list_head incorporates
186f9291ceSJung-uk Kim * an implicit structural reference but engine_list_tail does not - the
19e71b7053SJung-uk Kim * latter is a computational optimization and only points to something that
20e71b7053SJung-uk Kim * is already pointed to by its predecessor in the list (or engine_list_head
216f9291ceSJung-uk Kim * itself). In the same way, the use of the "prev" pointer in each ENGINE is
226f9291ceSJung-uk Kim * to save excessive list iteration, it doesn't correspond to an extra
236f9291ceSJung-uk Kim * structural reference. Hence, engine_list_head, and each non-null "next"
246f9291ceSJung-uk Kim * pointer account for the list itself assuming exactly 1 structural
256f9291ceSJung-uk Kim * reference on each list member.
266f9291ceSJung-uk Kim */
275c87c606SMark Murray static ENGINE *engine_list_head = NULL;
285c87c606SMark Murray static ENGINE *engine_list_tail = NULL;
295c87c606SMark Murray
306f9291ceSJung-uk Kim /*
31b2bf0c7eSJung-uk Kim * The linked list of currently loaded dynamic engines.
32b2bf0c7eSJung-uk Kim */
33b2bf0c7eSJung-uk Kim static ENGINE *engine_dyn_list_head = NULL;
34b2bf0c7eSJung-uk Kim static ENGINE *engine_dyn_list_tail = NULL;
35b2bf0c7eSJung-uk Kim
36b2bf0c7eSJung-uk Kim /*
376f9291ceSJung-uk Kim * This cleanup function is only needed internally. If it should be called,
38e71b7053SJung-uk Kim * we register it with the "engine_cleanup_int()" stack to be called during
396f9291ceSJung-uk Kim * cleanup.
406f9291ceSJung-uk Kim */
415c87c606SMark Murray
engine_list_cleanup(void)425c87c606SMark Murray static void engine_list_cleanup(void)
435c87c606SMark Murray {
445c87c606SMark Murray ENGINE *iterator = engine_list_head;
455c87c606SMark Murray
466f9291ceSJung-uk Kim while (iterator != NULL) {
475c87c606SMark Murray ENGINE_remove(iterator);
485c87c606SMark Murray iterator = engine_list_head;
495c87c606SMark Murray }
505c87c606SMark Murray return;
515c87c606SMark Murray }
525c87c606SMark Murray
536f9291ceSJung-uk Kim /*
546f9291ceSJung-uk Kim * These static functions starting with a lower case "engine_" always take
55e71b7053SJung-uk Kim * place when global_engine_lock has been locked up.
566f9291ceSJung-uk Kim */
engine_list_add(ENGINE * e)575c87c606SMark Murray static int engine_list_add(ENGINE *e)
585c87c606SMark Murray {
595c87c606SMark Murray int conflict = 0;
605c87c606SMark Murray ENGINE *iterator = NULL;
615c87c606SMark Murray
626f9291ceSJung-uk Kim if (e == NULL) {
63b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
645c87c606SMark Murray return 0;
655c87c606SMark Murray }
665c87c606SMark Murray iterator = engine_list_head;
676f9291ceSJung-uk Kim while (iterator && !conflict) {
685c87c606SMark Murray conflict = (strcmp(iterator->id, e->id) == 0);
695c87c606SMark Murray iterator = iterator->next;
705c87c606SMark Murray }
716f9291ceSJung-uk Kim if (conflict) {
72b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ENGINE_R_CONFLICTING_ENGINE_ID);
735c87c606SMark Murray return 0;
745c87c606SMark Murray }
756f9291ceSJung-uk Kim if (engine_list_head == NULL) {
765c87c606SMark Murray /* We are adding to an empty list. */
776f9291ceSJung-uk Kim if (engine_list_tail) {
78b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
795c87c606SMark Murray return 0;
805c87c606SMark Murray }
816f9291ceSJung-uk Kim /*
826f9291ceSJung-uk Kim * The first time the list allocates, we should register the cleanup.
836f9291ceSJung-uk Kim */
84*6f1af0d7SPierre Pronchery if (!engine_cleanup_add_last(engine_list_cleanup)) {
85*6f1af0d7SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
86*6f1af0d7SPierre Pronchery return 0;
87*6f1af0d7SPierre Pronchery }
88*6f1af0d7SPierre Pronchery engine_list_head = e;
89*6f1af0d7SPierre Pronchery e->prev = NULL;
906f9291ceSJung-uk Kim } else {
915c87c606SMark Murray /* We are adding to the tail of an existing list. */
926f9291ceSJung-uk Kim if ((engine_list_tail == NULL) || (engine_list_tail->next != NULL)) {
93b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
945c87c606SMark Murray return 0;
955c87c606SMark Murray }
965c87c606SMark Murray engine_list_tail->next = e;
975c87c606SMark Murray e->prev = engine_list_tail;
985c87c606SMark Murray }
996f9291ceSJung-uk Kim /*
1006f9291ceSJung-uk Kim * Having the engine in the list assumes a structural reference.
1016f9291ceSJung-uk Kim */
1025c87c606SMark Murray e->struct_ref++;
103b077aed3SPierre Pronchery ENGINE_REF_PRINT(e, 0, 1);
1045c87c606SMark Murray /* However it came to be, e is the last item in the list. */
1055c87c606SMark Murray engine_list_tail = e;
1065c87c606SMark Murray e->next = NULL;
1075c87c606SMark Murray return 1;
1085c87c606SMark Murray }
1095c87c606SMark Murray
engine_list_remove(ENGINE * e)1105c87c606SMark Murray static int engine_list_remove(ENGINE *e)
1115c87c606SMark Murray {
1125c87c606SMark Murray ENGINE *iterator;
1135c87c606SMark Murray
1146f9291ceSJung-uk Kim if (e == NULL) {
115b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
1165c87c606SMark Murray return 0;
1175c87c606SMark Murray }
1185c87c606SMark Murray /* We need to check that e is in our linked list! */
1195c87c606SMark Murray iterator = engine_list_head;
1205c87c606SMark Murray while (iterator && (iterator != e))
1215c87c606SMark Murray iterator = iterator->next;
1226f9291ceSJung-uk Kim if (iterator == NULL) {
123b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ENGINE_IS_NOT_IN_LIST);
1245c87c606SMark Murray return 0;
1255c87c606SMark Murray }
1265c87c606SMark Murray /* un-link e from the chain. */
1275c87c606SMark Murray if (e->next)
1285c87c606SMark Murray e->next->prev = e->prev;
1295c87c606SMark Murray if (e->prev)
1305c87c606SMark Murray e->prev->next = e->next;
1315c87c606SMark Murray /* Correct our head/tail if necessary. */
1325c87c606SMark Murray if (engine_list_head == e)
1335c87c606SMark Murray engine_list_head = e->next;
1345c87c606SMark Murray if (engine_list_tail == e)
1355c87c606SMark Murray engine_list_tail = e->prev;
1365c87c606SMark Murray engine_free_util(e, 0);
1375c87c606SMark Murray return 1;
1385c87c606SMark Murray }
1395c87c606SMark Murray
140b2bf0c7eSJung-uk Kim /* Add engine to dynamic engine list. */
engine_add_dynamic_id(ENGINE * e,ENGINE_DYNAMIC_ID dynamic_id,int not_locked)141b2bf0c7eSJung-uk Kim int engine_add_dynamic_id(ENGINE *e, ENGINE_DYNAMIC_ID dynamic_id,
142b2bf0c7eSJung-uk Kim int not_locked)
143b2bf0c7eSJung-uk Kim {
144b2bf0c7eSJung-uk Kim int result = 0;
145b2bf0c7eSJung-uk Kim ENGINE *iterator = NULL;
146b2bf0c7eSJung-uk Kim
147b2bf0c7eSJung-uk Kim if (e == NULL)
148b2bf0c7eSJung-uk Kim return 0;
149b2bf0c7eSJung-uk Kim
150b2bf0c7eSJung-uk Kim if (e->dynamic_id == NULL && dynamic_id == NULL)
151b2bf0c7eSJung-uk Kim return 0;
152b2bf0c7eSJung-uk Kim
153b2bf0c7eSJung-uk Kim if (not_locked && !CRYPTO_THREAD_write_lock(global_engine_lock))
154b2bf0c7eSJung-uk Kim return 0;
155b2bf0c7eSJung-uk Kim
156b2bf0c7eSJung-uk Kim if (dynamic_id != NULL) {
157b2bf0c7eSJung-uk Kim iterator = engine_dyn_list_head;
158b2bf0c7eSJung-uk Kim while (iterator != NULL) {
159b2bf0c7eSJung-uk Kim if (iterator->dynamic_id == dynamic_id)
160b2bf0c7eSJung-uk Kim goto err;
161b2bf0c7eSJung-uk Kim iterator = iterator->next;
162b2bf0c7eSJung-uk Kim }
163b2bf0c7eSJung-uk Kim if (e->dynamic_id != NULL)
164b2bf0c7eSJung-uk Kim goto err;
165b2bf0c7eSJung-uk Kim e->dynamic_id = dynamic_id;
166b2bf0c7eSJung-uk Kim }
167b2bf0c7eSJung-uk Kim
168b2bf0c7eSJung-uk Kim if (engine_dyn_list_head == NULL) {
169b2bf0c7eSJung-uk Kim /* We are adding to an empty list. */
170b2bf0c7eSJung-uk Kim if (engine_dyn_list_tail != NULL)
171b2bf0c7eSJung-uk Kim goto err;
172b2bf0c7eSJung-uk Kim engine_dyn_list_head = e;
173b2bf0c7eSJung-uk Kim e->prev_dyn = NULL;
174b2bf0c7eSJung-uk Kim } else {
175b2bf0c7eSJung-uk Kim /* We are adding to the tail of an existing list. */
176b2bf0c7eSJung-uk Kim if (engine_dyn_list_tail == NULL
177b2bf0c7eSJung-uk Kim || engine_dyn_list_tail->next_dyn != NULL)
178b2bf0c7eSJung-uk Kim goto err;
179b2bf0c7eSJung-uk Kim engine_dyn_list_tail->next_dyn = e;
180b2bf0c7eSJung-uk Kim e->prev_dyn = engine_dyn_list_tail;
181b2bf0c7eSJung-uk Kim }
182b2bf0c7eSJung-uk Kim
183b2bf0c7eSJung-uk Kim engine_dyn_list_tail = e;
184b2bf0c7eSJung-uk Kim e->next_dyn = NULL;
185b2bf0c7eSJung-uk Kim result = 1;
186b2bf0c7eSJung-uk Kim
187b2bf0c7eSJung-uk Kim err:
188b2bf0c7eSJung-uk Kim if (not_locked)
189b2bf0c7eSJung-uk Kim CRYPTO_THREAD_unlock(global_engine_lock);
190b2bf0c7eSJung-uk Kim return result;
191b2bf0c7eSJung-uk Kim }
192b2bf0c7eSJung-uk Kim
193b2bf0c7eSJung-uk Kim /* Remove engine from dynamic engine list. */
engine_remove_dynamic_id(ENGINE * e,int not_locked)194b2bf0c7eSJung-uk Kim void engine_remove_dynamic_id(ENGINE *e, int not_locked)
195b2bf0c7eSJung-uk Kim {
196b2bf0c7eSJung-uk Kim if (e == NULL || e->dynamic_id == NULL)
197b2bf0c7eSJung-uk Kim return;
198b2bf0c7eSJung-uk Kim
199b2bf0c7eSJung-uk Kim if (not_locked && !CRYPTO_THREAD_write_lock(global_engine_lock))
200b2bf0c7eSJung-uk Kim return;
201b2bf0c7eSJung-uk Kim
202b2bf0c7eSJung-uk Kim e->dynamic_id = NULL;
203b2bf0c7eSJung-uk Kim
204b2bf0c7eSJung-uk Kim /* un-link e from the chain. */
205b2bf0c7eSJung-uk Kim if (e->next_dyn != NULL)
206b2bf0c7eSJung-uk Kim e->next_dyn->prev_dyn = e->prev_dyn;
207b2bf0c7eSJung-uk Kim if (e->prev_dyn != NULL)
208b2bf0c7eSJung-uk Kim e->prev_dyn->next_dyn = e->next_dyn;
209b2bf0c7eSJung-uk Kim /* Correct our head/tail if necessary. */
210b2bf0c7eSJung-uk Kim if (engine_dyn_list_head == e)
211b2bf0c7eSJung-uk Kim engine_dyn_list_head = e->next_dyn;
212b2bf0c7eSJung-uk Kim if (engine_dyn_list_tail == e)
213b2bf0c7eSJung-uk Kim engine_dyn_list_tail = e->prev_dyn;
214b2bf0c7eSJung-uk Kim
215b2bf0c7eSJung-uk Kim if (not_locked)
216b2bf0c7eSJung-uk Kim CRYPTO_THREAD_unlock(global_engine_lock);
217b2bf0c7eSJung-uk Kim }
218b2bf0c7eSJung-uk Kim
2195c87c606SMark Murray /* Get the first/last "ENGINE" type available. */
ENGINE_get_first(void)2205c87c606SMark Murray ENGINE *ENGINE_get_first(void)
2215c87c606SMark Murray {
2225c87c606SMark Murray ENGINE *ret;
2235c87c606SMark Murray
224e71b7053SJung-uk Kim if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
225b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
226e71b7053SJung-uk Kim return NULL;
227e71b7053SJung-uk Kim }
228e71b7053SJung-uk Kim
229b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(global_engine_lock))
230b077aed3SPierre Pronchery return NULL;
2315c87c606SMark Murray ret = engine_list_head;
2326f9291ceSJung-uk Kim if (ret) {
2335c87c606SMark Murray ret->struct_ref++;
234b077aed3SPierre Pronchery ENGINE_REF_PRINT(ret, 0, 1);
2355c87c606SMark Murray }
236e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(global_engine_lock);
2375c87c606SMark Murray return ret;
2385c87c606SMark Murray }
2395c87c606SMark Murray
ENGINE_get_last(void)2405c87c606SMark Murray ENGINE *ENGINE_get_last(void)
2415c87c606SMark Murray {
2425c87c606SMark Murray ENGINE *ret;
2435c87c606SMark Murray
244e71b7053SJung-uk Kim if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
245b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
246e71b7053SJung-uk Kim return NULL;
247e71b7053SJung-uk Kim }
248e71b7053SJung-uk Kim
249b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(global_engine_lock))
250b077aed3SPierre Pronchery return NULL;
2515c87c606SMark Murray ret = engine_list_tail;
2526f9291ceSJung-uk Kim if (ret) {
2535c87c606SMark Murray ret->struct_ref++;
254b077aed3SPierre Pronchery ENGINE_REF_PRINT(ret, 0, 1);
2555c87c606SMark Murray }
256e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(global_engine_lock);
2575c87c606SMark Murray return ret;
2585c87c606SMark Murray }
2595c87c606SMark Murray
2605c87c606SMark Murray /* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
ENGINE_get_next(ENGINE * e)2615c87c606SMark Murray ENGINE *ENGINE_get_next(ENGINE *e)
2625c87c606SMark Murray {
2635c87c606SMark Murray ENGINE *ret = NULL;
2646f9291ceSJung-uk Kim if (e == NULL) {
265b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
266b077aed3SPierre Pronchery return NULL;
2675c87c606SMark Murray }
268b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(global_engine_lock))
269b077aed3SPierre Pronchery return NULL;
2705c87c606SMark Murray ret = e->next;
2716f9291ceSJung-uk Kim if (ret) {
272e71b7053SJung-uk Kim /* Return a valid structural reference to the next ENGINE */
2735c87c606SMark Murray ret->struct_ref++;
274b077aed3SPierre Pronchery ENGINE_REF_PRINT(ret, 0, 1);
2755c87c606SMark Murray }
276e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(global_engine_lock);
2775c87c606SMark Murray /* Release the structural reference to the previous ENGINE */
2785c87c606SMark Murray ENGINE_free(e);
2795c87c606SMark Murray return ret;
2805c87c606SMark Murray }
2815c87c606SMark Murray
ENGINE_get_prev(ENGINE * e)2825c87c606SMark Murray ENGINE *ENGINE_get_prev(ENGINE *e)
2835c87c606SMark Murray {
2845c87c606SMark Murray ENGINE *ret = NULL;
2856f9291ceSJung-uk Kim if (e == NULL) {
286b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
287b077aed3SPierre Pronchery return NULL;
2885c87c606SMark Murray }
289b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(global_engine_lock))
290b077aed3SPierre Pronchery return NULL;
2915c87c606SMark Murray ret = e->prev;
2926f9291ceSJung-uk Kim if (ret) {
2935c87c606SMark Murray /* Return a valid structural reference to the next ENGINE */
2945c87c606SMark Murray ret->struct_ref++;
295b077aed3SPierre Pronchery ENGINE_REF_PRINT(ret, 0, 1);
2965c87c606SMark Murray }
297e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(global_engine_lock);
2985c87c606SMark Murray /* Release the structural reference to the previous ENGINE */
2995c87c606SMark Murray ENGINE_free(e);
3005c87c606SMark Murray return ret;
3015c87c606SMark Murray }
3025c87c606SMark Murray
3035c87c606SMark Murray /* Add another "ENGINE" type into the list. */
ENGINE_add(ENGINE * e)3045c87c606SMark Murray int ENGINE_add(ENGINE *e)
3055c87c606SMark Murray {
3065c87c606SMark Murray int to_return = 1;
3076f9291ceSJung-uk Kim if (e == NULL) {
308b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
3095c87c606SMark Murray return 0;
3105c87c606SMark Murray }
3116f9291ceSJung-uk Kim if ((e->id == NULL) || (e->name == NULL)) {
312b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ID_OR_NAME_MISSING);
31380815a77SJung-uk Kim return 0;
3145c87c606SMark Murray }
315b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(global_engine_lock))
316b077aed3SPierre Pronchery return 0;
3176f9291ceSJung-uk Kim if (!engine_list_add(e)) {
318b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
3195c87c606SMark Murray to_return = 0;
3205c87c606SMark Murray }
321e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(global_engine_lock);
3225c87c606SMark Murray return to_return;
3235c87c606SMark Murray }
3245c87c606SMark Murray
3255c87c606SMark Murray /* Remove an existing "ENGINE" type from the array. */
ENGINE_remove(ENGINE * e)3265c87c606SMark Murray int ENGINE_remove(ENGINE *e)
3275c87c606SMark Murray {
3285c87c606SMark Murray int to_return = 1;
3296f9291ceSJung-uk Kim if (e == NULL) {
330b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
3315c87c606SMark Murray return 0;
3325c87c606SMark Murray }
333b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(global_engine_lock))
334b077aed3SPierre Pronchery return 0;
3356f9291ceSJung-uk Kim if (!engine_list_remove(e)) {
336b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
3375c87c606SMark Murray to_return = 0;
3385c87c606SMark Murray }
339e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(global_engine_lock);
3405c87c606SMark Murray return to_return;
3415c87c606SMark Murray }
3425c87c606SMark Murray
engine_cpy(ENGINE * dest,const ENGINE * src)3435c87c606SMark Murray static void engine_cpy(ENGINE *dest, const ENGINE *src)
3445c87c606SMark Murray {
3455c87c606SMark Murray dest->id = src->id;
3465c87c606SMark Murray dest->name = src->name;
3475c87c606SMark Murray dest->rsa_meth = src->rsa_meth;
3485c87c606SMark Murray #ifndef OPENSSL_NO_DSA
3495c87c606SMark Murray dest->dsa_meth = src->dsa_meth;
3505c87c606SMark Murray #endif
3515c87c606SMark Murray #ifndef OPENSSL_NO_DH
3525c87c606SMark Murray dest->dh_meth = src->dh_meth;
3535c87c606SMark Murray #endif
354e71b7053SJung-uk Kim #ifndef OPENSSL_NO_EC
355e71b7053SJung-uk Kim dest->ec_meth = src->ec_meth;
3563b4e3dcbSSimon L. B. Nielsen #endif
3575c87c606SMark Murray dest->rand_meth = src->rand_meth;
3585c87c606SMark Murray dest->ciphers = src->ciphers;
3595c87c606SMark Murray dest->digests = src->digests;
3601f13597dSJung-uk Kim dest->pkey_meths = src->pkey_meths;
3615c87c606SMark Murray dest->destroy = src->destroy;
3625c87c606SMark Murray dest->init = src->init;
3635c87c606SMark Murray dest->finish = src->finish;
3645c87c606SMark Murray dest->ctrl = src->ctrl;
3655c87c606SMark Murray dest->load_privkey = src->load_privkey;
3665c87c606SMark Murray dest->load_pubkey = src->load_pubkey;
3675c87c606SMark Murray dest->cmd_defns = src->cmd_defns;
3685c87c606SMark Murray dest->flags = src->flags;
369b2bf0c7eSJung-uk Kim dest->dynamic_id = src->dynamic_id;
370b2bf0c7eSJung-uk Kim engine_add_dynamic_id(dest, NULL, 0);
3715c87c606SMark Murray }
3725c87c606SMark Murray
ENGINE_by_id(const char * id)3735c87c606SMark Murray ENGINE *ENGINE_by_id(const char *id)
3745c87c606SMark Murray {
3755c87c606SMark Murray ENGINE *iterator;
3763b4e3dcbSSimon L. B. Nielsen char *load_dir = NULL;
3776f9291ceSJung-uk Kim if (id == NULL) {
378b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
3795c87c606SMark Murray return NULL;
3805c87c606SMark Murray }
381b077aed3SPierre Pronchery ENGINE_load_builtin_engines();
382b077aed3SPierre Pronchery
383e71b7053SJung-uk Kim if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
384b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
385e71b7053SJung-uk Kim return NULL;
386e71b7053SJung-uk Kim }
387e71b7053SJung-uk Kim
388b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(global_engine_lock))
389b077aed3SPierre Pronchery return NULL;
3905c87c606SMark Murray iterator = engine_list_head;
3915c87c606SMark Murray while (iterator && (strcmp(id, iterator->id) != 0))
3925c87c606SMark Murray iterator = iterator->next;
393e71b7053SJung-uk Kim if (iterator != NULL) {
3946f9291ceSJung-uk Kim /*
3956f9291ceSJung-uk Kim * We need to return a structural reference. If this is an ENGINE
3966f9291ceSJung-uk Kim * type that returns copies, make a duplicate - otherwise increment
3976f9291ceSJung-uk Kim * the existing ENGINE's reference count.
3986f9291ceSJung-uk Kim */
3996f9291ceSJung-uk Kim if (iterator->flags & ENGINE_FLAGS_BY_ID_COPY) {
4005c87c606SMark Murray ENGINE *cp = ENGINE_new();
401e71b7053SJung-uk Kim if (cp == NULL)
4025c87c606SMark Murray iterator = NULL;
4036f9291ceSJung-uk Kim else {
4045c87c606SMark Murray engine_cpy(cp, iterator);
4055c87c606SMark Murray iterator = cp;
4065c87c606SMark Murray }
4076f9291ceSJung-uk Kim } else {
4085c87c606SMark Murray iterator->struct_ref++;
409b077aed3SPierre Pronchery ENGINE_REF_PRINT(iterator, 0, 1);
4105c87c606SMark Murray }
4115c87c606SMark Murray }
412e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(global_engine_lock);
413e71b7053SJung-uk Kim if (iterator != NULL)
4146f9291ceSJung-uk Kim return iterator;
4156f9291ceSJung-uk Kim /*
416e71b7053SJung-uk Kim * Prevent infinite recursion if we're looking for the dynamic engine.
4176f9291ceSJung-uk Kim */
4186f9291ceSJung-uk Kim if (strcmp(id, "dynamic")) {
419c9cf7b5cSJung-uk Kim if ((load_dir = ossl_safe_getenv("OPENSSL_ENGINES")) == NULL)
4206f9291ceSJung-uk Kim load_dir = ENGINESDIR;
4213b4e3dcbSSimon L. B. Nielsen iterator = ENGINE_by_id("dynamic");
4223b4e3dcbSSimon L. B. Nielsen if (!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) ||
4233b4e3dcbSSimon L. B. Nielsen !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) ||
4243b4e3dcbSSimon L. B. Nielsen !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD",
4253b4e3dcbSSimon L. B. Nielsen load_dir, 0) ||
426560ede85SJung-uk Kim !ENGINE_ctrl_cmd_string(iterator, "LIST_ADD", "1", 0) ||
4273b4e3dcbSSimon L. B. Nielsen !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0))
4283b4e3dcbSSimon L. B. Nielsen goto notfound;
4293b4e3dcbSSimon L. B. Nielsen return iterator;
4303b4e3dcbSSimon L. B. Nielsen }
4313b4e3dcbSSimon L. B. Nielsen notfound:
432a3ddd25aSSimon L. B. Nielsen ENGINE_free(iterator);
433b077aed3SPierre Pronchery ERR_raise_data(ERR_LIB_ENGINE, ENGINE_R_NO_SUCH_ENGINE, "id=%s", id);
4343b4e3dcbSSimon L. B. Nielsen return NULL;
4353b4e3dcbSSimon L. B. Nielsen /* EEK! Experimental code ends */
4365c87c606SMark Murray }
4375c87c606SMark Murray
ENGINE_up_ref(ENGINE * e)4385c87c606SMark Murray int ENGINE_up_ref(ENGINE *e)
4395c87c606SMark Murray {
440e71b7053SJung-uk Kim int i;
4416f9291ceSJung-uk Kim if (e == NULL) {
442b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
4435c87c606SMark Murray return 0;
4445c87c606SMark Murray }
445e71b7053SJung-uk Kim CRYPTO_UP_REF(&e->struct_ref, &i, global_engine_lock);
4465c87c606SMark Murray return 1;
4475c87c606SMark Murray }
448