Re-introduce legacy EVP_PKEY types for provided keys
[openssl.git] / crypto / dso / dso_lib.c
1 /*
2  * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include "dso_local.h"
11 #include "internal/refcount.h"
12
13 DEFINE_STACK_OF(void)
14
15 static DSO_METHOD *default_DSO_meth = NULL;
16
17 static DSO *DSO_new_method(DSO_METHOD *meth)
18 {
19     DSO *ret;
20
21     if (default_DSO_meth == NULL) {
22         /*
23          * We default to DSO_METH_openssl() which in turn defaults to
24          * stealing the "best available" method. Will fallback to
25          * DSO_METH_null() in the worst case.
26          */
27         default_DSO_meth = DSO_METHOD_openssl();
28     }
29     ret = OPENSSL_zalloc(sizeof(*ret));
30     if (ret == NULL) {
31         DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
32         return NULL;
33     }
34     ret->meth_data = sk_void_new_null();
35     if (ret->meth_data == NULL) {
36         /* sk_new doesn't generate any errors so we do */
37         DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
38         OPENSSL_free(ret);
39         return NULL;
40     }
41     ret->meth = default_DSO_meth;
42     ret->references = 1;
43     ret->lock = CRYPTO_THREAD_lock_new();
44     if (ret->lock == NULL) {
45         DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
46         sk_void_free(ret->meth_data);
47         OPENSSL_free(ret);
48         return NULL;
49     }
50
51     if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
52         DSO_free(ret);
53         ret = NULL;
54     }
55
56     return ret;
57 }
58
59 DSO *DSO_new(void)
60 {
61     return DSO_new_method(NULL);
62 }
63
64 int DSO_free(DSO *dso)
65 {
66     int i;
67
68     if (dso == NULL)
69         return 1;
70
71     if (CRYPTO_DOWN_REF(&dso->references, &i, dso->lock) <= 0)
72         return 0;
73
74     REF_PRINT_COUNT("DSO", dso);
75     if (i > 0)
76         return 1;
77     REF_ASSERT_ISNT(i < 0);
78
79     if ((dso->flags & DSO_FLAG_NO_UNLOAD_ON_FREE) == 0) {
80         if ((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) {
81             DSOerr(DSO_F_DSO_FREE, DSO_R_UNLOAD_FAILED);
82             return 0;
83         }
84     }
85
86     if ((dso->meth->finish != NULL) && !dso->meth->finish(dso)) {
87         DSOerr(DSO_F_DSO_FREE, DSO_R_FINISH_FAILED);
88         return 0;
89     }
90
91     sk_void_free(dso->meth_data);
92     OPENSSL_free(dso->filename);
93     OPENSSL_free(dso->loaded_filename);
94     CRYPTO_THREAD_lock_free(dso->lock);
95     OPENSSL_free(dso);
96     return 1;
97 }
98
99 int DSO_flags(DSO *dso)
100 {
101     return ((dso == NULL) ? 0 : dso->flags);
102 }
103
104 int DSO_up_ref(DSO *dso)
105 {
106     int i;
107
108     if (dso == NULL) {
109         DSOerr(DSO_F_DSO_UP_REF, ERR_R_PASSED_NULL_PARAMETER);
110         return 0;
111     }
112
113     if (CRYPTO_UP_REF(&dso->references, &i, dso->lock) <= 0)
114         return 0;
115
116     REF_PRINT_COUNT("DSO", dso);
117     REF_ASSERT_ISNT(i < 2);
118     return ((i > 1) ? 1 : 0);
119 }
120
121 DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags)
122 {
123     DSO *ret;
124     int allocated = 0;
125
126     if (dso == NULL) {
127         ret = DSO_new_method(meth);
128         if (ret == NULL) {
129             DSOerr(DSO_F_DSO_LOAD, ERR_R_MALLOC_FAILURE);
130             goto err;
131         }
132         allocated = 1;
133         /* Pass the provided flags to the new DSO object */
134         if (DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) {
135             DSOerr(DSO_F_DSO_LOAD, DSO_R_CTRL_FAILED);
136             goto err;
137         }
138     } else
139         ret = dso;
140     /* Don't load if we're currently already loaded */
141     if (ret->filename != NULL) {
142         DSOerr(DSO_F_DSO_LOAD, DSO_R_DSO_ALREADY_LOADED);
143         goto err;
144     }
145     /*
146      * filename can only be NULL if we were passed a dso that already has one
147      * set.
148      */
149     if (filename != NULL)
150         if (!DSO_set_filename(ret, filename)) {
151             DSOerr(DSO_F_DSO_LOAD, DSO_R_SET_FILENAME_FAILED);
152             goto err;
153         }
154     filename = ret->filename;
155     if (filename == NULL) {
156         DSOerr(DSO_F_DSO_LOAD, DSO_R_NO_FILENAME);
157         goto err;
158     }
159     if (ret->meth->dso_load == NULL) {
160         DSOerr(DSO_F_DSO_LOAD, DSO_R_UNSUPPORTED);
161         goto err;
162     }
163     if (!ret->meth->dso_load(ret)) {
164         DSOerr(DSO_F_DSO_LOAD, DSO_R_LOAD_FAILED);
165         goto err;
166     }
167     /* Load succeeded */
168     return ret;
169  err:
170     if (allocated)
171         DSO_free(ret);
172     return NULL;
173 }
174
175 DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname)
176 {
177     DSO_FUNC_TYPE ret = NULL;
178
179     if ((dso == NULL) || (symname == NULL)) {
180         DSOerr(DSO_F_DSO_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
181         return NULL;
182     }
183     if (dso->meth->dso_bind_func == NULL) {
184         DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_UNSUPPORTED);
185         return NULL;
186     }
187     if ((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) {
188         DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_SYM_FAILURE);
189         return NULL;
190     }
191     /* Success */
192     return ret;
193 }
194
195 /*
196  * I don't really like these *_ctrl functions very much to be perfectly
197  * honest. For one thing, I think I have to return a negative value for any
198  * error because possible DSO_ctrl() commands may return values such as
199  * "size"s that can legitimately be zero (making the standard
200  * "if (DSO_cmd(...))" form that works almost everywhere else fail at odd
201  * times. I'd prefer "output" values to be passed by reference and the return
202  * value as success/failure like usual ... but we conform when we must... :-)
203  */
204 long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg)
205 {
206     if (dso == NULL) {
207         DSOerr(DSO_F_DSO_CTRL, ERR_R_PASSED_NULL_PARAMETER);
208         return -1;
209     }
210     /*
211      * We should intercept certain generic commands and only pass control to
212      * the method-specific ctrl() function if it's something we don't handle.
213      */
214     switch (cmd) {
215     case DSO_CTRL_GET_FLAGS:
216         return dso->flags;
217     case DSO_CTRL_SET_FLAGS:
218         dso->flags = (int)larg;
219         return 0;
220     case DSO_CTRL_OR_FLAGS:
221         dso->flags |= (int)larg;
222         return 0;
223     default:
224         break;
225     }
226     if ((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) {
227         DSOerr(DSO_F_DSO_CTRL, DSO_R_UNSUPPORTED);
228         return -1;
229     }
230     return dso->meth->dso_ctrl(dso, cmd, larg, parg);
231 }
232
233 const char *DSO_get_filename(DSO *dso)
234 {
235     if (dso == NULL) {
236         DSOerr(DSO_F_DSO_GET_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
237         return NULL;
238     }
239     return dso->filename;
240 }
241
242 int DSO_set_filename(DSO *dso, const char *filename)
243 {
244     char *copied;
245
246     if ((dso == NULL) || (filename == NULL)) {
247         DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
248         return 0;
249     }
250     if (dso->loaded_filename) {
251         DSOerr(DSO_F_DSO_SET_FILENAME, DSO_R_DSO_ALREADY_LOADED);
252         return 0;
253     }
254     /* We'll duplicate filename */
255     copied = OPENSSL_strdup(filename);
256     if (copied == NULL) {
257         DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_MALLOC_FAILURE);
258         return 0;
259     }
260     OPENSSL_free(dso->filename);
261     dso->filename = copied;
262     return 1;
263 }
264
265 char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2)
266 {
267     char *result = NULL;
268
269     if (dso == NULL || filespec1 == NULL) {
270         DSOerr(DSO_F_DSO_MERGE, ERR_R_PASSED_NULL_PARAMETER);
271         return NULL;
272     }
273     if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
274         if (dso->merger != NULL)
275             result = dso->merger(dso, filespec1, filespec2);
276         else if (dso->meth->dso_merger != NULL)
277             result = dso->meth->dso_merger(dso, filespec1, filespec2);
278     }
279     return result;
280 }
281
282 char *DSO_convert_filename(DSO *dso, const char *filename)
283 {
284     char *result = NULL;
285
286     if (dso == NULL) {
287         DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
288         return NULL;
289     }
290     if (filename == NULL)
291         filename = dso->filename;
292     if (filename == NULL) {
293         DSOerr(DSO_F_DSO_CONVERT_FILENAME, DSO_R_NO_FILENAME);
294         return NULL;
295     }
296     if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
297         if (dso->name_converter != NULL)
298             result = dso->name_converter(dso, filename);
299         else if (dso->meth->dso_name_converter != NULL)
300             result = dso->meth->dso_name_converter(dso, filename);
301     }
302     if (result == NULL) {
303         result = OPENSSL_strdup(filename);
304         if (result == NULL) {
305             DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_MALLOC_FAILURE);
306             return NULL;
307         }
308     }
309     return result;
310 }
311
312 int DSO_pathbyaddr(void *addr, char *path, int sz)
313 {
314     DSO_METHOD *meth = default_DSO_meth;
315     if (meth == NULL)
316         meth = DSO_METHOD_openssl();
317     if (meth->pathbyaddr == NULL) {
318         DSOerr(DSO_F_DSO_PATHBYADDR, DSO_R_UNSUPPORTED);
319         return -1;
320     }
321     return (*meth->pathbyaddr) (addr, path, sz);
322 }
323
324 DSO *DSO_dsobyaddr(void *addr, int flags)
325 {
326     DSO *ret = NULL;
327     char *filename = NULL;
328     int len = DSO_pathbyaddr(addr, NULL, 0);
329
330     if (len < 0)
331         return NULL;
332
333     filename = OPENSSL_malloc(len);
334     if (filename != NULL
335             && DSO_pathbyaddr(addr, filename, len) == len)
336         ret = DSO_load(NULL, filename, NULL, flags);
337
338     OPENSSL_free(filename);
339     return ret;
340 }
341
342 void *DSO_global_lookup(const char *name)
343 {
344     DSO_METHOD *meth = default_DSO_meth;
345     if (meth == NULL)
346         meth = DSO_METHOD_openssl();
347     if (meth->globallookup == NULL) {
348         DSOerr(DSO_F_DSO_GLOBAL_LOOKUP, DSO_R_UNSUPPORTED);
349         return NULL;
350     }
351     return (*meth->globallookup) (name);
352 }