VirtualBox

source: vbox/trunk/src/libs/openssl-3.1.3/crypto/store/store_meth.c@ 101211

Last change on this file since 101211 was 101211, checked in by vboxsync, 17 months ago

openssl-3.1.3: Applied and adjusted our OpenSSL changes to 3.1.2. bugref:10527

File size: 15.2 KB
Line 
1/*
2 * Copyright 2020-2022 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 <openssl/crypto.h>
11#include "crypto/store.h"
12#include "internal/core.h"
13#include "internal/namemap.h"
14#include "internal/property.h"
15#include "internal/provider.h"
16#include "store_local.h"
17#include "crypto/context.h"
18
19int OSSL_STORE_LOADER_up_ref(OSSL_STORE_LOADER *loader)
20{
21 int ref = 0;
22
23 if (loader->prov != NULL)
24 CRYPTO_UP_REF(&loader->refcnt, &ref, loader->lock);
25 return 1;
26}
27
28void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader)
29{
30 if (loader != NULL && loader->prov != NULL) {
31 int i;
32
33 CRYPTO_DOWN_REF(&loader->refcnt, &i, loader->lock);
34 if (i > 0)
35 return;
36 ossl_provider_free(loader->prov);
37 CRYPTO_THREAD_lock_free(loader->lock);
38 }
39 OPENSSL_free(loader);
40}
41
42/*
43 * OSSL_STORE_LOADER_new() expects the scheme as a constant string,
44 * which we currently don't have, so we need an alternative allocator.
45 */
46static OSSL_STORE_LOADER *new_loader(OSSL_PROVIDER *prov)
47{
48 OSSL_STORE_LOADER *loader;
49
50 if ((loader = OPENSSL_zalloc(sizeof(*loader))) == NULL
51 || (loader->lock = CRYPTO_THREAD_lock_new()) == NULL) {
52 OPENSSL_free(loader);
53 return NULL;
54 }
55 loader->prov = prov;
56 ossl_provider_up_ref(prov);
57 loader->refcnt = 1;
58
59 return loader;
60}
61
62static int up_ref_loader(void *method)
63{
64 return OSSL_STORE_LOADER_up_ref(method);
65}
66
67static void free_loader(void *method)
68{
69 OSSL_STORE_LOADER_free(method);
70}
71
72/* Data to be passed through ossl_method_construct() */
73struct loader_data_st {
74 OSSL_LIB_CTX *libctx;
75 int scheme_id; /* For get_loader_from_store() */
76 const char *scheme; /* For get_loader_from_store() */
77 const char *propquery; /* For get_loader_from_store() */
78
79 OSSL_METHOD_STORE *tmp_store; /* For get_tmp_loader_store() */
80
81 unsigned int flag_construct_error_occurred : 1;
82};
83
84/*
85 * Generic routines to fetch / create OSSL_STORE methods with
86 * ossl_method_construct()
87 */
88
89/* Temporary loader method store, constructor and destructor */
90static void *get_tmp_loader_store(void *data)
91{
92 struct loader_data_st *methdata = data;
93
94 if (methdata->tmp_store == NULL)
95 methdata->tmp_store = ossl_method_store_new(methdata->libctx);
96 return methdata->tmp_store;
97}
98
99 static void dealloc_tmp_loader_store(void *store)
100{
101 if (store != NULL)
102 ossl_method_store_free(store);
103}
104
105/* Get the permanent loader store */
106static OSSL_METHOD_STORE *get_loader_store(OSSL_LIB_CTX *libctx)
107{
108 return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_STORE_LOADER_STORE_INDEX);
109}
110
111static int reserve_loader_store(void *store, void *data)
112{
113 struct loader_data_st *methdata = data;
114
115 if (store == NULL
116 && (store = get_loader_store(methdata->libctx)) == NULL)
117 return 0;
118
119 return ossl_method_lock_store(store);
120}
121
122static int unreserve_loader_store(void *store, void *data)
123{
124 struct loader_data_st *methdata = data;
125
126 if (store == NULL
127 && (store = get_loader_store(methdata->libctx)) == NULL)
128 return 0;
129
130 return ossl_method_unlock_store(store);
131}
132
133/* Get loader methods from a store, or put one in */
134static void *get_loader_from_store(void *store, const OSSL_PROVIDER **prov,
135 void *data)
136{
137 struct loader_data_st *methdata = data;
138 void *method = NULL;
139 int id;
140
141 if ((id = methdata->scheme_id) == 0) {
142 OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
143
144 id = ossl_namemap_name2num(namemap, methdata->scheme);
145 }
146
147 if (store == NULL
148 && (store = get_loader_store(methdata->libctx)) == NULL)
149 return NULL;
150
151 if (!ossl_method_store_fetch(store, id, methdata->propquery, prov, &method))
152 return NULL;
153 return method;
154}
155
156static int put_loader_in_store(void *store, void *method,
157 const OSSL_PROVIDER *prov,
158 const char *scheme, const char *propdef,
159 void *data)
160{
161 struct loader_data_st *methdata = data;
162 OSSL_NAMEMAP *namemap;
163 int id;
164
165 if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL
166 || (id = ossl_namemap_name2num(namemap, scheme)) == 0)
167 return 0;
168
169 if (store == NULL && (store = get_loader_store(methdata->libctx)) == NULL)
170 return 0;
171
172 return ossl_method_store_add(store, prov, id, propdef, method,
173 up_ref_loader, free_loader);
174}
175
176static void *loader_from_algorithm(int scheme_id, const OSSL_ALGORITHM *algodef,
177 OSSL_PROVIDER *prov)
178{
179 OSSL_STORE_LOADER *loader = NULL;
180 const OSSL_DISPATCH *fns = algodef->implementation;
181
182 if ((loader = new_loader(prov)) == NULL)
183 return NULL;
184 loader->scheme_id = scheme_id;
185 loader->propdef = algodef->property_definition;
186 loader->description = algodef->algorithm_description;
187
188 for (; fns->function_id != 0; fns++) {
189 switch (fns->function_id) {
190 case OSSL_FUNC_STORE_OPEN:
191 if (loader->p_open == NULL)
192 loader->p_open = OSSL_FUNC_store_open(fns);
193 break;
194 case OSSL_FUNC_STORE_ATTACH:
195 if (loader->p_attach == NULL)
196 loader->p_attach = OSSL_FUNC_store_attach(fns);
197 break;
198 case OSSL_FUNC_STORE_SETTABLE_CTX_PARAMS:
199 if (loader->p_settable_ctx_params == NULL)
200 loader->p_settable_ctx_params =
201 OSSL_FUNC_store_settable_ctx_params(fns);
202 break;
203 case OSSL_FUNC_STORE_SET_CTX_PARAMS:
204 if (loader->p_set_ctx_params == NULL)
205 loader->p_set_ctx_params = OSSL_FUNC_store_set_ctx_params(fns);
206 break;
207 case OSSL_FUNC_STORE_LOAD:
208 if (loader->p_load == NULL)
209 loader->p_load = OSSL_FUNC_store_load(fns);
210 break;
211 case OSSL_FUNC_STORE_EOF:
212 if (loader->p_eof == NULL)
213 loader->p_eof = OSSL_FUNC_store_eof(fns);
214 break;
215 case OSSL_FUNC_STORE_CLOSE:
216 if (loader->p_close == NULL)
217 loader->p_close = OSSL_FUNC_store_close(fns);
218 break;
219 case OSSL_FUNC_STORE_EXPORT_OBJECT:
220 if (loader->p_export_object == NULL)
221 loader->p_export_object = OSSL_FUNC_store_export_object(fns);
222 break;
223 }
224 }
225
226 if ((loader->p_open == NULL && loader->p_attach == NULL)
227 || loader->p_load == NULL
228 || loader->p_eof == NULL
229 || loader->p_close == NULL) {
230 /* Only set_ctx_params is optionaal */
231 OSSL_STORE_LOADER_free(loader);
232 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADER_INCOMPLETE);
233 return NULL;
234 }
235 return loader;
236}
237
238/*
239 * The core fetching functionality passes the scheme of the implementation.
240 * This function is responsible to getting an identity number for them,
241 * then call loader_from_algorithm() with that identity number.
242 */
243static void *construct_loader(const OSSL_ALGORITHM *algodef,
244 OSSL_PROVIDER *prov, void *data)
245{
246 /*
247 * This function is only called if get_loader_from_store() returned
248 * NULL, so it's safe to say that of all the spots to create a new
249 * namemap entry, this is it. Should the scheme already exist there, we
250 * know that ossl_namemap_add() will return its corresponding number.
251 */
252 struct loader_data_st *methdata = data;
253 OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
254 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
255 const char *scheme = algodef->algorithm_names;
256 int id = ossl_namemap_add_name(namemap, 0, scheme);
257 void *method = NULL;
258
259 if (id != 0)
260 method = loader_from_algorithm(id, algodef, prov);
261
262 /*
263 * Flag to indicate that there was actual construction errors. This
264 * helps inner_loader_fetch() determine what error it should
265 * record on inaccessible algorithms.
266 */
267 if (method == NULL)
268 methdata->flag_construct_error_occurred = 1;
269
270 return method;
271}
272
273/* Intermediary function to avoid ugly casts, used below */
274static void destruct_loader(void *method, void *data)
275{
276 OSSL_STORE_LOADER_free(method);
277}
278
279/* Fetching support. Can fetch by numeric identity or by scheme */
280static OSSL_STORE_LOADER *
281inner_loader_fetch(struct loader_data_st *methdata,
282 const char *scheme, const char *properties)
283{
284 OSSL_METHOD_STORE *store = get_loader_store(methdata->libctx);
285 OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
286 const char *const propq = properties != NULL ? properties : "";
287 void *method = NULL;
288 int unsupported, id;
289
290 if (store == NULL || namemap == NULL) {
291 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_INVALID_ARGUMENT);
292 return NULL;
293 }
294
295 /* If we haven't received a name id yet, try to get one for the name */
296 id = scheme != NULL ? ossl_namemap_name2num(namemap, scheme) : 0;
297
298 /*
299 * If we haven't found the name yet, chances are that the algorithm to
300 * be fetched is unsupported.
301 */
302 unsupported = id == 0;
303
304 if (id == 0
305 || !ossl_method_store_cache_get(store, NULL, id, propq, &method)) {
306 OSSL_METHOD_CONSTRUCT_METHOD mcm = {
307 get_tmp_loader_store,
308 reserve_loader_store,
309 unreserve_loader_store,
310 get_loader_from_store,
311 put_loader_in_store,
312 construct_loader,
313 destruct_loader
314 };
315 OSSL_PROVIDER *prov = NULL;
316
317 methdata->scheme_id = id;
318 methdata->scheme = scheme;
319 methdata->propquery = propq;
320 methdata->flag_construct_error_occurred = 0;
321 if ((method = ossl_method_construct(methdata->libctx, OSSL_OP_STORE,
322 &prov, 0 /* !force_cache */,
323 &mcm, methdata)) != NULL) {
324 /*
325 * If construction did create a method for us, we know that there
326 * is a correct scheme_id, since those have already been calculated
327 * in get_loader_from_store() and put_loader_in_store() above.
328 */
329 if (id == 0)
330 id = ossl_namemap_name2num(namemap, scheme);
331 ossl_method_store_cache_set(store, prov, id, propq, method,
332 up_ref_loader, free_loader);
333 }
334
335 /*
336 * If we never were in the constructor, the algorithm to be fetched
337 * is unsupported.
338 */
339 unsupported = !methdata->flag_construct_error_occurred;
340 }
341
342 if ((id != 0 || scheme != NULL) && method == NULL) {
343 int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
344 const char *helpful_msg =
345 unsupported
346 ? ( "No store loader found. For standard store loaders you need "
347 "at least one of the default or base providers available. "
348 "Did you forget to load them? Info: " )
349 : "";
350
351 if (scheme == NULL)
352 scheme = ossl_namemap_num2name(namemap, id, 0);
353 ERR_raise_data(ERR_LIB_OSSL_STORE, code,
354 "%s%s, Scheme (%s : %d), Properties (%s)",
355 helpful_msg,
356 ossl_lib_ctx_get_descriptor(methdata->libctx),
357 scheme == NULL ? "<null>" : scheme, id,
358 properties == NULL ? "<null>" : properties);
359 }
360
361 return method;
362}
363
364OSSL_STORE_LOADER *OSSL_STORE_LOADER_fetch(OSSL_LIB_CTX *libctx,
365 const char *scheme,
366 const char *properties)
367{
368 struct loader_data_st methdata;
369 void *method;
370
371 methdata.libctx = libctx;
372 methdata.tmp_store = NULL;
373 method = inner_loader_fetch(&methdata, scheme, properties);
374 dealloc_tmp_loader_store(methdata.tmp_store);
375 return method;
376}
377
378int ossl_store_loader_store_cache_flush(OSSL_LIB_CTX *libctx)
379{
380 OSSL_METHOD_STORE *store = get_loader_store(libctx);
381
382 if (store != NULL)
383 return ossl_method_store_cache_flush_all(store);
384 return 1;
385}
386
387int ossl_store_loader_store_remove_all_provided(const OSSL_PROVIDER *prov)
388{
389 OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
390 OSSL_METHOD_STORE *store = get_loader_store(libctx);
391
392 if (store != NULL)
393 return ossl_method_store_remove_all_provided(store, prov);
394 return 1;
395}
396
397/*
398 * Library of basic method functions
399 */
400
401const OSSL_PROVIDER *OSSL_STORE_LOADER_get0_provider(const OSSL_STORE_LOADER *loader)
402{
403 if (!ossl_assert(loader != NULL)) {
404 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER);
405 return 0;
406 }
407
408 return loader->prov;
409}
410
411const char *OSSL_STORE_LOADER_get0_properties(const OSSL_STORE_LOADER *loader)
412{
413 if (!ossl_assert(loader != NULL)) {
414 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER);
415 return 0;
416 }
417
418 return loader->propdef;
419}
420
421int ossl_store_loader_get_number(const OSSL_STORE_LOADER *loader)
422{
423 if (!ossl_assert(loader != NULL)) {
424 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER);
425 return 0;
426 }
427
428 return loader->scheme_id;
429}
430
431const char *OSSL_STORE_LOADER_get0_description(const OSSL_STORE_LOADER *loader)
432{
433 return loader->description;
434}
435
436int OSSL_STORE_LOADER_is_a(const OSSL_STORE_LOADER *loader, const char *name)
437{
438 if (loader->prov != NULL) {
439 OSSL_LIB_CTX *libctx = ossl_provider_libctx(loader->prov);
440 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
441
442 return ossl_namemap_name2num(namemap, name) == loader->scheme_id;
443 }
444 return 0;
445}
446
447struct do_one_data_st {
448 void (*user_fn)(OSSL_STORE_LOADER *loader, void *arg);
449 void *user_arg;
450};
451
452static void do_one(ossl_unused int id, void *method, void *arg)
453{
454 struct do_one_data_st *data = arg;
455
456 data->user_fn(method, data->user_arg);
457}
458
459void OSSL_STORE_LOADER_do_all_provided(OSSL_LIB_CTX *libctx,
460 void (*user_fn)(OSSL_STORE_LOADER *loader,
461 void *arg),
462 void *user_arg)
463{
464 struct loader_data_st methdata;
465 struct do_one_data_st data;
466
467 methdata.libctx = libctx;
468 methdata.tmp_store = NULL;
469 (void)inner_loader_fetch(&methdata, NULL, NULL /* properties */);
470
471 data.user_fn = user_fn;
472 data.user_arg = user_arg;
473 if (methdata.tmp_store != NULL)
474 ossl_method_store_do_all(methdata.tmp_store, &do_one, &data);
475 ossl_method_store_do_all(get_loader_store(libctx), &do_one, &data);
476 dealloc_tmp_loader_store(methdata.tmp_store);
477}
478
479int OSSL_STORE_LOADER_names_do_all(const OSSL_STORE_LOADER *loader,
480 void (*fn)(const char *name, void *data),
481 void *data)
482{
483 if (loader == NULL)
484 return 0;
485
486 if (loader->prov != NULL) {
487 OSSL_LIB_CTX *libctx = ossl_provider_libctx(loader->prov);
488 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
489
490 return ossl_namemap_doall_names(namemap, loader->scheme_id, fn, data);
491 }
492
493 return 1;
494}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette