2 * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
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
10 #include "crypto/cryptlib.h"
11 #include <openssl/conf.h>
12 #include "internal/thread_once.h"
13 #include "internal/property.h"
14 #include "internal/core.h"
16 struct ossl_lib_ctx_onfree_list_st
{
17 ossl_lib_ctx_onfree_fn
*fn
;
18 struct ossl_lib_ctx_onfree_list_st
*next
;
21 struct ossl_lib_ctx_st
{
26 * For most data in the OSSL_LIB_CTX we just use ex_data to store it. But
27 * that doesn't work for ex_data itself - so we store that directly.
29 OSSL_EX_DATA_GLOBAL global
;
31 /* Map internal static indexes to dynamically created indexes */
32 int dyn_indexes
[OSSL_LIB_CTX_MAX_INDEXES
];
34 /* Keep a separate lock for each index */
35 CRYPTO_RWLOCK
*index_locks
[OSSL_LIB_CTX_MAX_INDEXES
];
37 CRYPTO_RWLOCK
*oncelock
;
38 int run_once_done
[OSSL_LIB_CTX_MAX_RUN_ONCE
];
39 int run_once_ret
[OSSL_LIB_CTX_MAX_RUN_ONCE
];
40 struct ossl_lib_ctx_onfree_list_st
*onfreelist
;
43 int ossl_lib_ctx_write_lock(OSSL_LIB_CTX
*ctx
)
45 return CRYPTO_THREAD_write_lock(ossl_lib_ctx_get_concrete(ctx
)->lock
);
48 int ossl_lib_ctx_read_lock(OSSL_LIB_CTX
*ctx
)
50 return CRYPTO_THREAD_read_lock(ossl_lib_ctx_get_concrete(ctx
)->lock
);
53 int ossl_lib_ctx_unlock(OSSL_LIB_CTX
*ctx
)
55 return CRYPTO_THREAD_unlock(ossl_lib_ctx_get_concrete(ctx
)->lock
);
58 static int context_init(OSSL_LIB_CTX
*ctx
)
63 ctx
->lock
= CRYPTO_THREAD_lock_new();
64 if (ctx
->lock
== NULL
)
67 ctx
->oncelock
= CRYPTO_THREAD_lock_new();
68 if (ctx
->oncelock
== NULL
)
71 for (i
= 0; i
< OSSL_LIB_CTX_MAX_INDEXES
; i
++) {
72 ctx
->index_locks
[i
] = CRYPTO_THREAD_lock_new();
73 ctx
->dyn_indexes
[i
] = -1;
74 if (ctx
->index_locks
[i
] == NULL
)
78 /* OSSL_LIB_CTX is built on top of ex_data so we initialise that directly */
79 if (!ossl_do_ex_data_init(ctx
))
83 if (!ossl_crypto_new_ex_data_ex(ctx
, CRYPTO_EX_INDEX_OSSL_LIB_CTX
, NULL
,
85 ossl_crypto_cleanup_all_ex_data_int(ctx
);
89 /* Everything depends on properties, so we also pre-initialise that */
90 if (!ossl_property_parse_init(ctx
))
96 ossl_crypto_cleanup_all_ex_data_int(ctx
);
97 CRYPTO_THREAD_lock_free(ctx
->oncelock
);
98 CRYPTO_THREAD_lock_free(ctx
->lock
);
103 static int context_deinit(OSSL_LIB_CTX
*ctx
)
105 struct ossl_lib_ctx_onfree_list_st
*tmp
, *onfree
;
111 ossl_ctx_thread_stop(ctx
);
113 onfree
= ctx
->onfreelist
;
114 while (onfree
!= NULL
) {
117 onfree
= onfree
->next
;
120 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_OSSL_LIB_CTX
, NULL
, &ctx
->data
);
121 ossl_crypto_cleanup_all_ex_data_int(ctx
);
122 for (i
= 0; i
< OSSL_LIB_CTX_MAX_INDEXES
; i
++)
123 CRYPTO_THREAD_lock_free(ctx
->index_locks
[i
]);
125 CRYPTO_THREAD_lock_free(ctx
->oncelock
);
126 CRYPTO_THREAD_lock_free(ctx
->lock
);
132 /* The default default context */
133 static OSSL_LIB_CTX default_context_int
;
135 static CRYPTO_ONCE default_context_init
= CRYPTO_ONCE_STATIC_INIT
;
136 static CRYPTO_THREAD_LOCAL default_context_thread_local
;
138 DEFINE_RUN_ONCE_STATIC(default_context_do_init
)
140 return CRYPTO_THREAD_init_local(&default_context_thread_local
, NULL
)
141 && context_init(&default_context_int
);
144 void ossl_lib_ctx_default_deinit(void)
146 context_deinit(&default_context_int
);
149 static OSSL_LIB_CTX
*get_thread_default_context(void)
151 if (!RUN_ONCE(&default_context_init
, default_context_do_init
))
154 return CRYPTO_THREAD_get_local(&default_context_thread_local
);
157 static OSSL_LIB_CTX
*get_default_context(void)
159 OSSL_LIB_CTX
*current_defctx
= get_thread_default_context();
161 if (current_defctx
== NULL
)
162 current_defctx
= &default_context_int
;
163 return current_defctx
;
166 static int set_default_context(OSSL_LIB_CTX
*defctx
)
168 if (defctx
== &default_context_int
)
171 return CRYPTO_THREAD_set_local(&default_context_thread_local
, defctx
);
175 OSSL_LIB_CTX
*OSSL_LIB_CTX_new(void)
177 OSSL_LIB_CTX
*ctx
= OPENSSL_zalloc(sizeof(*ctx
));
179 if (ctx
!= NULL
&& !context_init(ctx
)) {
180 OSSL_LIB_CTX_free(ctx
);
187 int OSSL_LIB_CTX_load_config(OSSL_LIB_CTX
*ctx
, const char *config_file
)
189 return CONF_modules_load_file_ex(ctx
, config_file
, NULL
, 0) > 0;
193 void OSSL_LIB_CTX_free(OSSL_LIB_CTX
*ctx
)
195 if (ossl_lib_ctx_is_default(ctx
))
203 OSSL_LIB_CTX
*OSSL_LIB_CTX_get0_global_default(void)
205 if (!RUN_ONCE(&default_context_init
, default_context_do_init
))
208 return &default_context_int
;
211 OSSL_LIB_CTX
*OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX
*libctx
)
213 OSSL_LIB_CTX
*current_defctx
;
215 if ((current_defctx
= get_default_context()) != NULL
) {
217 set_default_context(libctx
);
218 return current_defctx
;
225 OSSL_LIB_CTX
*ossl_lib_ctx_get_concrete(OSSL_LIB_CTX
*ctx
)
229 return get_default_context();
234 int ossl_lib_ctx_is_default(OSSL_LIB_CTX
*ctx
)
237 if (ctx
== NULL
|| ctx
== get_default_context())
243 int ossl_lib_ctx_is_global_default(OSSL_LIB_CTX
*ctx
)
246 if (ossl_lib_ctx_get_concrete(ctx
) == &default_context_int
)
252 static void ossl_lib_ctx_generic_new(void *parent_ign
, void *ptr_ign
,
253 CRYPTO_EX_DATA
*ad
, int index
,
254 long argl_ign
, void *argp
)
256 const OSSL_LIB_CTX_METHOD
*meth
= argp
;
257 OSSL_LIB_CTX
*ctx
= ossl_crypto_ex_data_get_ossl_lib_ctx(ad
);
258 void *ptr
= meth
->new_func(ctx
);
261 if (!CRYPTO_THREAD_write_lock(ctx
->lock
))
263 * Can't return something, so best to hope that something will
267 CRYPTO_set_ex_data(ad
, index
, ptr
);
268 CRYPTO_THREAD_unlock(ctx
->lock
);
271 static void ossl_lib_ctx_generic_free(void *parent_ign
, void *ptr
,
272 CRYPTO_EX_DATA
*ad
, int index
,
273 long argl_ign
, void *argp
)
275 const OSSL_LIB_CTX_METHOD
*meth
= argp
;
277 meth
->free_func(ptr
);
280 /* Non-static so we can use it in context_internal_test */
281 static int ossl_lib_ctx_init_index(OSSL_LIB_CTX
*ctx
, int static_index
,
282 const OSSL_LIB_CTX_METHOD
*meth
)
286 ctx
= ossl_lib_ctx_get_concrete(ctx
);
290 idx
= ossl_crypto_get_ex_new_index_ex(ctx
, CRYPTO_EX_INDEX_OSSL_LIB_CTX
, 0,
292 ossl_lib_ctx_generic_new
,
293 NULL
, ossl_lib_ctx_generic_free
);
297 ctx
->dyn_indexes
[static_index
] = idx
;
301 void *ossl_lib_ctx_get_data(OSSL_LIB_CTX
*ctx
, int index
,
302 const OSSL_LIB_CTX_METHOD
*meth
)
307 ctx
= ossl_lib_ctx_get_concrete(ctx
);
311 if (!CRYPTO_THREAD_read_lock(ctx
->lock
))
313 dynidx
= ctx
->dyn_indexes
[index
];
314 CRYPTO_THREAD_unlock(ctx
->lock
);
317 if (!CRYPTO_THREAD_read_lock(ctx
->index_locks
[index
]))
319 if (!CRYPTO_THREAD_read_lock(ctx
->lock
)) {
320 CRYPTO_THREAD_unlock(ctx
->index_locks
[index
]);
323 data
= CRYPTO_get_ex_data(&ctx
->data
, dynidx
);
324 CRYPTO_THREAD_unlock(ctx
->lock
);
325 CRYPTO_THREAD_unlock(ctx
->index_locks
[index
]);
329 if (!CRYPTO_THREAD_write_lock(ctx
->index_locks
[index
]))
331 if (!CRYPTO_THREAD_write_lock(ctx
->lock
)) {
332 CRYPTO_THREAD_unlock(ctx
->index_locks
[index
]);
336 dynidx
= ctx
->dyn_indexes
[index
];
338 data
= CRYPTO_get_ex_data(&ctx
->data
, dynidx
);
339 CRYPTO_THREAD_unlock(ctx
->lock
);
340 CRYPTO_THREAD_unlock(ctx
->index_locks
[index
]);
344 if (!ossl_lib_ctx_init_index(ctx
, index
, meth
)) {
345 CRYPTO_THREAD_unlock(ctx
->lock
);
346 CRYPTO_THREAD_unlock(ctx
->index_locks
[index
]);
350 CRYPTO_THREAD_unlock(ctx
->lock
);
353 * The alloc call ensures there's a value there. We release the ctx->lock
354 * for this, because the allocation itself may recursively call
355 * ossl_lib_ctx_get_data for other indexes (never this one). The allocation
356 * will itself aquire the ctx->lock when it actually comes to store the
357 * allocated data (see ossl_lib_ctx_generic_new() above). We call
358 * ossl_crypto_alloc_ex_data_intern() here instead of CRYPTO_alloc_ex_data().
359 * They do the same thing except that the latter calls CRYPTO_get_ex_data()
360 * as well - which we must not do without holding the ctx->lock.
362 if (ossl_crypto_alloc_ex_data_intern(CRYPTO_EX_INDEX_OSSL_LIB_CTX
, NULL
,
363 &ctx
->data
, ctx
->dyn_indexes
[index
])) {
364 if (!CRYPTO_THREAD_read_lock(ctx
->lock
))
366 data
= CRYPTO_get_ex_data(&ctx
->data
, ctx
->dyn_indexes
[index
]);
367 CRYPTO_THREAD_unlock(ctx
->lock
);
371 CRYPTO_THREAD_unlock(ctx
->index_locks
[index
]);
375 OSSL_EX_DATA_GLOBAL
*ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX
*ctx
)
377 ctx
= ossl_lib_ctx_get_concrete(ctx
);
383 int ossl_lib_ctx_run_once(OSSL_LIB_CTX
*ctx
, unsigned int idx
,
384 ossl_lib_ctx_run_once_fn run_once_fn
)
386 int done
= 0, ret
= 0;
388 ctx
= ossl_lib_ctx_get_concrete(ctx
);
392 if (!CRYPTO_THREAD_read_lock(ctx
->oncelock
))
394 done
= ctx
->run_once_done
[idx
];
396 ret
= ctx
->run_once_ret
[idx
];
397 CRYPTO_THREAD_unlock(ctx
->oncelock
);
402 if (!CRYPTO_THREAD_write_lock(ctx
->oncelock
))
404 if (ctx
->run_once_done
[idx
]) {
405 ret
= ctx
->run_once_ret
[idx
];
406 CRYPTO_THREAD_unlock(ctx
->oncelock
);
410 ret
= run_once_fn(ctx
);
411 ctx
->run_once_done
[idx
] = 1;
412 ctx
->run_once_ret
[idx
] = ret
;
413 CRYPTO_THREAD_unlock(ctx
->oncelock
);
418 int ossl_lib_ctx_onfree(OSSL_LIB_CTX
*ctx
, ossl_lib_ctx_onfree_fn onfreefn
)
420 struct ossl_lib_ctx_onfree_list_st
*newonfree
421 = OPENSSL_malloc(sizeof(*newonfree
));
423 if (newonfree
== NULL
)
426 newonfree
->fn
= onfreefn
;
427 newonfree
->next
= ctx
->onfreelist
;
428 ctx
->onfreelist
= newonfree
;
433 const char *ossl_lib_ctx_get_descriptor(OSSL_LIB_CTX
*libctx
)
436 return "FIPS internal library context";
438 if (ossl_lib_ctx_is_global_default(libctx
))
439 return "Global default library context";
440 if (ossl_lib_ctx_is_default(libctx
))
441 return "Thread-local default library context";
442 return "Non-default library context";