7ea1ef675aa0e5b3e759f4e778a2e388c803bd52
[openssl.git] / crypto / engine / eng_list.c
1 /*
2  * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
3  * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
4  *
5  * Licensed under the Apache License 2.0 (the "License").  You may not use
6  * this file except in compliance with the License.  You can obtain a copy
7  * in the file LICENSE in the source distribution or at
8  * https://www.openssl.org/source/license.html
9  */
10
11 /* We need to use some engine deprecated APIs */
12 #define OPENSSL_SUPPRESS_DEPRECATED
13
14 #include "eng_local.h"
15
16 /*
17  * The linked-list of pointers to engine types. engine_list_head incorporates
18  * an implicit structural reference but engine_list_tail does not - the
19  * latter is a computational optimization and only points to something that
20  * is already pointed to by its predecessor in the list (or engine_list_head
21  * itself). In the same way, the use of the "prev" pointer in each ENGINE is
22  * to save excessive list iteration, it doesn't correspond to an extra
23  * structural reference. Hence, engine_list_head, and each non-null "next"
24  * pointer account for the list itself assuming exactly 1 structural
25  * reference on each list member.
26  */
27 static ENGINE *engine_list_head = NULL;
28 static ENGINE *engine_list_tail = NULL;
29
30 /*
31  * This cleanup function is only needed internally. If it should be called,
32  * we register it with the "engine_cleanup_int()" stack to be called during
33  * cleanup.
34  */
35
36 static void engine_list_cleanup(void)
37 {
38     ENGINE *iterator = engine_list_head;
39
40     while (iterator != NULL) {
41         ENGINE_remove(iterator);
42         iterator = engine_list_head;
43     }
44     return;
45 }
46
47 /*
48  * These static functions starting with a lower case "engine_" always take
49  * place when global_engine_lock has been locked up.
50  */
51 static int engine_list_add(ENGINE *e)
52 {
53     int conflict = 0;
54     ENGINE *iterator = NULL;
55
56     if (e == NULL) {
57         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
58         return 0;
59     }
60     iterator = engine_list_head;
61     while (iterator && !conflict) {
62         conflict = (strcmp(iterator->id, e->id) == 0);
63         iterator = iterator->next;
64     }
65     if (conflict) {
66         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_CONFLICTING_ENGINE_ID);
67         return 0;
68     }
69     if (engine_list_head == NULL) {
70         /* We are adding to an empty list. */
71         if (engine_list_tail) {
72             ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
73             return 0;
74         }
75         engine_list_head = e;
76         e->prev = NULL;
77         /*
78          * The first time the list allocates, we should register the cleanup.
79          */
80         engine_cleanup_add_last(engine_list_cleanup);
81     } else {
82         /* We are adding to the tail of an existing list. */
83         if ((engine_list_tail == NULL) || (engine_list_tail->next != NULL)) {
84             ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
85             return 0;
86         }
87         engine_list_tail->next = e;
88         e->prev = engine_list_tail;
89     }
90     /*
91      * Having the engine in the list assumes a structural reference.
92      */
93     e->struct_ref++;
94     engine_ref_debug(e, 0, 1);
95     /* However it came to be, e is the last item in the list. */
96     engine_list_tail = e;
97     e->next = NULL;
98     return 1;
99 }
100
101 static int engine_list_remove(ENGINE *e)
102 {
103     ENGINE *iterator;
104
105     if (e == NULL) {
106         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
107         return 0;
108     }
109     /* We need to check that e is in our linked list! */
110     iterator = engine_list_head;
111     while (iterator && (iterator != e))
112         iterator = iterator->next;
113     if (iterator == NULL) {
114         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ENGINE_IS_NOT_IN_LIST);
115         return 0;
116     }
117     /* un-link e from the chain. */
118     if (e->next)
119         e->next->prev = e->prev;
120     if (e->prev)
121         e->prev->next = e->next;
122     /* Correct our head/tail if necessary. */
123     if (engine_list_head == e)
124         engine_list_head = e->next;
125     if (engine_list_tail == e)
126         engine_list_tail = e->prev;
127     engine_free_util(e, 0);
128     return 1;
129 }
130
131 /* Get the first/last "ENGINE" type available. */
132 ENGINE *ENGINE_get_first(void)
133 {
134     ENGINE *ret;
135
136     if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
137         ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
138         return NULL;
139     }
140
141     if (!CRYPTO_THREAD_write_lock(global_engine_lock))
142         return NULL;
143     ret = engine_list_head;
144     if (ret) {
145         ret->struct_ref++;
146         engine_ref_debug(ret, 0, 1);
147     }
148     CRYPTO_THREAD_unlock(global_engine_lock);
149     return ret;
150 }
151
152 ENGINE *ENGINE_get_last(void)
153 {
154     ENGINE *ret;
155
156     if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
157         ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
158         return NULL;
159     }
160
161     if (!CRYPTO_THREAD_write_lock(global_engine_lock))
162         return NULL;
163     ret = engine_list_tail;
164     if (ret) {
165         ret->struct_ref++;
166         engine_ref_debug(ret, 0, 1);
167     }
168     CRYPTO_THREAD_unlock(global_engine_lock);
169     return ret;
170 }
171
172 /* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
173 ENGINE *ENGINE_get_next(ENGINE *e)
174 {
175     ENGINE *ret = NULL;
176     if (e == NULL) {
177         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
178         return NULL;
179     }
180     if (!CRYPTO_THREAD_write_lock(global_engine_lock))
181         return NULL;
182     ret = e->next;
183     if (ret) {
184         /* Return a valid structural reference to the next ENGINE */
185         ret->struct_ref++;
186         engine_ref_debug(ret, 0, 1);
187     }
188     CRYPTO_THREAD_unlock(global_engine_lock);
189     /* Release the structural reference to the previous ENGINE */
190     ENGINE_free(e);
191     return ret;
192 }
193
194 ENGINE *ENGINE_get_prev(ENGINE *e)
195 {
196     ENGINE *ret = NULL;
197     if (e == NULL) {
198         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
199         return NULL;
200     }
201     if (!CRYPTO_THREAD_write_lock(global_engine_lock))
202         return NULL;
203     ret = e->prev;
204     if (ret) {
205         /* Return a valid structural reference to the next ENGINE */
206         ret->struct_ref++;
207         engine_ref_debug(ret, 0, 1);
208     }
209     CRYPTO_THREAD_unlock(global_engine_lock);
210     /* Release the structural reference to the previous ENGINE */
211     ENGINE_free(e);
212     return ret;
213 }
214
215 /* Add another "ENGINE" type into the list. */
216 int ENGINE_add(ENGINE *e)
217 {
218     int to_return = 1;
219     if (e == NULL) {
220         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
221         return 0;
222     }
223     if ((e->id == NULL) || (e->name == NULL)) {
224         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ID_OR_NAME_MISSING);
225         return 0;
226     }
227     if (!CRYPTO_THREAD_write_lock(global_engine_lock))
228         return 0;
229     if (!engine_list_add(e)) {
230         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
231         to_return = 0;
232     }
233     CRYPTO_THREAD_unlock(global_engine_lock);
234     return to_return;
235 }
236
237 /* Remove an existing "ENGINE" type from the array. */
238 int ENGINE_remove(ENGINE *e)
239 {
240     int to_return = 1;
241     if (e == NULL) {
242         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
243         return 0;
244     }
245     if (!CRYPTO_THREAD_write_lock(global_engine_lock))
246         return 0;
247     if (!engine_list_remove(e)) {
248         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
249         to_return = 0;
250     }
251     CRYPTO_THREAD_unlock(global_engine_lock);
252     return to_return;
253 }
254
255 static void engine_cpy(ENGINE *dest, const ENGINE *src)
256 {
257     dest->id = src->id;
258     dest->name = src->name;
259     dest->rsa_meth = src->rsa_meth;
260 #ifndef OPENSSL_NO_DSA
261     dest->dsa_meth = src->dsa_meth;
262 #endif
263 #ifndef OPENSSL_NO_DH
264     dest->dh_meth = src->dh_meth;
265 #endif
266 #ifndef OPENSSL_NO_EC
267     dest->ec_meth = src->ec_meth;
268 #endif
269     dest->rand_meth = src->rand_meth;
270     dest->ciphers = src->ciphers;
271     dest->digests = src->digests;
272     dest->pkey_meths = src->pkey_meths;
273     dest->destroy = src->destroy;
274     dest->init = src->init;
275     dest->finish = src->finish;
276     dest->ctrl = src->ctrl;
277     dest->load_privkey = src->load_privkey;
278     dest->load_pubkey = src->load_pubkey;
279     dest->cmd_defns = src->cmd_defns;
280     dest->flags = src->flags;
281 }
282
283 ENGINE *ENGINE_by_id(const char *id)
284 {
285     ENGINE *iterator;
286     char *load_dir = NULL;
287     if (id == NULL) {
288         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
289         return NULL;
290     }
291     ENGINE_load_builtin_engines();
292
293     if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
294         ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
295         return NULL;
296     }
297
298     if (!CRYPTO_THREAD_write_lock(global_engine_lock))
299         return NULL;
300     iterator = engine_list_head;
301     while (iterator && (strcmp(id, iterator->id) != 0))
302         iterator = iterator->next;
303     if (iterator != NULL) {
304         /*
305          * We need to return a structural reference. If this is an ENGINE
306          * type that returns copies, make a duplicate - otherwise increment
307          * the existing ENGINE's reference count.
308          */
309         if (iterator->flags & ENGINE_FLAGS_BY_ID_COPY) {
310             ENGINE *cp = ENGINE_new();
311             if (cp == NULL)
312                 iterator = NULL;
313             else {
314                 engine_cpy(cp, iterator);
315                 iterator = cp;
316             }
317         } else {
318             iterator->struct_ref++;
319             engine_ref_debug(iterator, 0, 1);
320         }
321     }
322     CRYPTO_THREAD_unlock(global_engine_lock);
323     if (iterator != NULL)
324         return iterator;
325     /*
326      * Prevent infinite recursion if we're looking for the dynamic engine.
327      */
328     if (strcmp(id, "dynamic")) {
329         if ((load_dir = ossl_safe_getenv("OPENSSL_ENGINES")) == NULL)
330             load_dir = ENGINESDIR;
331         iterator = ENGINE_by_id("dynamic");
332         if (!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) ||
333             !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) ||
334             !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD",
335                                     load_dir, 0) ||
336             !ENGINE_ctrl_cmd_string(iterator, "LIST_ADD", "1", 0) ||
337             !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0))
338             goto notfound;
339         return iterator;
340     }
341  notfound:
342     ENGINE_free(iterator);
343     ERR_raise_data(ERR_LIB_ENGINE, ENGINE_R_NO_SUCH_ENGINE, "id=%s", id);
344     return NULL;
345     /* EEK! Experimental code ends */
346 }
347
348 int ENGINE_up_ref(ENGINE *e)
349 {
350     int i;
351     if (e == NULL) {
352         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
353         return 0;
354     }
355     CRYPTO_UP_REF(&e->struct_ref, &i, global_engine_lock);
356     return 1;
357 }