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"
15 #include "internal/bio.h"
17 struct ossl_lib_ctx_onfree_list_st
{
18 ossl_lib_ctx_onfree_fn
*fn
;
19 struct ossl_lib_ctx_onfree_list_st
*next
;
22 struct ossl_lib_ctx_st
{
27 * For most data in the OSSL_LIB_CTX we just use ex_data to store it. But
28 * that doesn't work for ex_data itself - so we store that directly.
30 OSSL_EX_DATA_GLOBAL global
;
32 /* Map internal static indexes to dynamically created indexes */
33 int dyn_indexes
[OSSL_LIB_CTX_MAX_INDEXES
];
35 /* Keep a separate lock for each index */
36 CRYPTO_RWLOCK
*index_locks
[OSSL_LIB_CTX_MAX_INDEXES
];
38 CRYPTO_RWLOCK
*oncelock
;
39 int run_once_done
[OSSL_LIB_CTX_MAX_RUN_ONCE
];
40 int run_once_ret
[OSSL_LIB_CTX_MAX_RUN_ONCE
];
41 struct ossl_lib_ctx_onfree_list_st
*onfreelist
;
44 int ossl_lib_ctx_write_lock(OSSL_LIB_CTX
*ctx
)
46 return CRYPTO_THREAD_write_lock(ossl_lib_ctx_get_concrete(ctx
)->lock
);
49 int ossl_lib_ctx_read_lock(OSSL_LIB_CTX
*ctx
)
51 return CRYPTO_THREAD_read_lock(ossl_lib_ctx_get_concrete(ctx
)->lock
);
54 int ossl_lib_ctx_unlock(OSSL_LIB_CTX
*ctx
)
56 return CRYPTO_THREAD_unlock(ossl_lib_ctx_get_concrete(ctx
)->lock
);
59 static int context_init(OSSL_LIB_CTX
*ctx
)
64 ctx
->lock
= CRYPTO_THREAD_lock_new();
65 if (ctx
->lock
== NULL
)
68 ctx
->oncelock
= CRYPTO_THREAD_lock_new();
69 if (ctx
->oncelock
== NULL
)
72 for (i
= 0; i
< OSSL_LIB_CTX_MAX_INDEXES
; i
++) {
73 ctx
->index_locks
[i
] = CRYPTO_THREAD_lock_new();
74 ctx
->dyn_indexes
[i
] = -1;
75 if (ctx
->index_locks
[i
] == NULL
)
79 /* OSSL_LIB_CTX is built on top of ex_data so we initialise that directly */
80 if (!ossl_do_ex_data_init(ctx
))
84 if (!ossl_crypto_new_ex_data_ex(ctx
, CRYPTO_EX_INDEX_OSSL_LIB_CTX
, NULL
,
86 ossl_crypto_cleanup_all_ex_data_int(ctx
);
90 /* Everything depends on properties, so we also pre-initialise that */
91 if (!ossl_property_parse_init(ctx
))
97 ossl_crypto_cleanup_all_ex_data_int(ctx
);
98 CRYPTO_THREAD_lock_free(ctx
->oncelock
);
99 CRYPTO_THREAD_lock_free(ctx
->lock
);
104 static int context_deinit(OSSL_LIB_CTX
*ctx
)
106 struct ossl_lib_ctx_onfree_list_st
*tmp
, *onfree
;
112 ossl_ctx_thread_stop(ctx
);
114 onfree
= ctx
->onfreelist
;
115 while (onfree
!= NULL
) {
118 onfree
= onfree
->next
;
121 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_OSSL_LIB_CTX
, NULL
, &ctx
->data
);
122 ossl_crypto_cleanup_all_ex_data_int(ctx
);
123 for (i
= 0; i
< OSSL_LIB_CTX_MAX_INDEXES
; i
++)
124 CRYPTO_THREAD_lock_free(ctx
->index_locks
[i
]);
126 CRYPTO_THREAD_lock_free(ctx
->oncelock
);
127 CRYPTO_THREAD_lock_free(ctx
->lock
);
133 /* The default default context */
134 static OSSL_LIB_CTX default_context_int
;
136 static CRYPTO_ONCE default_context_init
= CRYPTO_ONCE_STATIC_INIT
;
137 static CRYPTO_THREAD_LOCAL default_context_thread_local
;
139 DEFINE_RUN_ONCE_STATIC(default_context_do_init
)
141 return CRYPTO_THREAD_init_local(&default_context_thread_local
, NULL
)
142 && context_init(&default_context_int
);
145 void ossl_lib_ctx_default_deinit(void)
147 context_deinit(&default_context_int
);
150 static OSSL_LIB_CTX
*get_thread_default_context(void)
152 if (!RUN_ONCE(&default_context_init
, default_context_do_init
))
155 return CRYPTO_THREAD_get_local(&default_context_thread_local
);
158 static OSSL_LIB_CTX
*get_default_context(void)
160 OSSL_LIB_CTX
*current_defctx
= get_thread_default_context();
162 if (current_defctx
== NULL
)
163 current_defctx
= &default_context_int
;
164 return current_defctx
;
167 static int set_default_context(OSSL_LIB_CTX
*defctx
)
169 if (defctx
== &default_context_int
)
172 return CRYPTO_THREAD_set_local(&default_context_thread_local
, defctx
);
176 OSSL_LIB_CTX
*OSSL_LIB_CTX_new(void)
178 OSSL_LIB_CTX
*ctx
= OPENSSL_zalloc(sizeof(*ctx
));
180 if (ctx
!= NULL
&& !context_init(ctx
)) {
181 OSSL_LIB_CTX_free(ctx
);
188 OSSL_LIB_CTX
*OSSL_LIB_CTX_new_from_dispatch(const OSSL_DISPATCH
*in
)
190 OSSL_LIB_CTX
*ctx
= OSSL_LIB_CTX_new();
195 if (!ossl_bio_init_core(ctx
, in
)) {
196 OSSL_LIB_CTX_free(ctx
);
203 int OSSL_LIB_CTX_load_config(OSSL_LIB_CTX
*ctx
, const char *config_file
)
205 return CONF_modules_load_file_ex(ctx
, config_file
, NULL
, 0) > 0;
209 void OSSL_LIB_CTX_free(OSSL_LIB_CTX
*ctx
)
211 if (ossl_lib_ctx_is_default(ctx
))
219 OSSL_LIB_CTX
*OSSL_LIB_CTX_get0_global_default(void)
221 if (!RUN_ONCE(&default_context_init
, default_context_do_init
))
224 return &default_context_int
;
227 OSSL_LIB_CTX
*OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX
*libctx
)
229 OSSL_LIB_CTX
*current_defctx
;
231 if ((current_defctx
= get_default_context()) != NULL
) {
233 set_default_context(libctx
);
234 return current_defctx
;
241 OSSL_LIB_CTX
*ossl_lib_ctx_get_concrete(OSSL_LIB_CTX
*ctx
)
245 return get_default_context();
250 int ossl_lib_ctx_is_default(OSSL_LIB_CTX
*ctx
)
253 if (ctx
== NULL
|| ctx
== get_default_context())
259 int ossl_lib_ctx_is_global_default(OSSL_LIB_CTX
*ctx
)
262 if (ossl_lib_ctx_get_concrete(ctx
) == &default_context_int
)
268 static void ossl_lib_ctx_generic_new(void *parent_ign
, void *ptr_ign
,
269 CRYPTO_EX_DATA
*ad
, int index
,
270 long argl_ign
, void *argp
)
272 const OSSL_LIB_CTX_METHOD
*meth
= argp
;
273 OSSL_LIB_CTX
*ctx
= ossl_crypto_ex_data_get_ossl_lib_ctx(ad
);
274 void *ptr
= meth
->new_func(ctx
);
277 if (!CRYPTO_THREAD_write_lock(ctx
->lock
))
279 * Can't return something, so best to hope that something will
283 CRYPTO_set_ex_data(ad
, index
, ptr
);
284 CRYPTO_THREAD_unlock(ctx
->lock
);
287 static void ossl_lib_ctx_generic_free(void *parent_ign
, void *ptr
,
288 CRYPTO_EX_DATA
*ad
, int index
,
289 long argl_ign
, void *argp
)
291 const OSSL_LIB_CTX_METHOD
*meth
= argp
;
293 meth
->free_func(ptr
);
296 static int ossl_lib_ctx_init_index(OSSL_LIB_CTX
*ctx
, int static_index
,
297 const OSSL_LIB_CTX_METHOD
*meth
)
301 ctx
= ossl_lib_ctx_get_concrete(ctx
);
305 idx
= ossl_crypto_get_ex_new_index_ex(ctx
, CRYPTO_EX_INDEX_OSSL_LIB_CTX
, 0,
307 ossl_lib_ctx_generic_new
,
308 NULL
, ossl_lib_ctx_generic_free
,
313 ctx
->dyn_indexes
[static_index
] = idx
;
317 void *ossl_lib_ctx_get_data(OSSL_LIB_CTX
*ctx
, int index
,
318 const OSSL_LIB_CTX_METHOD
*meth
)
323 ctx
= ossl_lib_ctx_get_concrete(ctx
);
327 if (!CRYPTO_THREAD_read_lock(ctx
->lock
))
329 dynidx
= ctx
->dyn_indexes
[index
];
330 CRYPTO_THREAD_unlock(ctx
->lock
);
333 if (!CRYPTO_THREAD_read_lock(ctx
->index_locks
[index
]))
335 if (!CRYPTO_THREAD_read_lock(ctx
->lock
)) {
336 CRYPTO_THREAD_unlock(ctx
->index_locks
[index
]);
339 data
= CRYPTO_get_ex_data(&ctx
->data
, dynidx
);
340 CRYPTO_THREAD_unlock(ctx
->lock
);
341 CRYPTO_THREAD_unlock(ctx
->index_locks
[index
]);
345 if (!CRYPTO_THREAD_write_lock(ctx
->index_locks
[index
]))
347 if (!CRYPTO_THREAD_write_lock(ctx
->lock
)) {
348 CRYPTO_THREAD_unlock(ctx
->index_locks
[index
]);
352 dynidx
= ctx
->dyn_indexes
[index
];
354 data
= CRYPTO_get_ex_data(&ctx
->data
, dynidx
);
355 CRYPTO_THREAD_unlock(ctx
->lock
);
356 CRYPTO_THREAD_unlock(ctx
->index_locks
[index
]);
360 if (!ossl_lib_ctx_init_index(ctx
, index
, meth
)) {
361 CRYPTO_THREAD_unlock(ctx
->lock
);
362 CRYPTO_THREAD_unlock(ctx
->index_locks
[index
]);
366 CRYPTO_THREAD_unlock(ctx
->lock
);
369 * The alloc call ensures there's a value there. We release the ctx->lock
370 * for this, because the allocation itself may recursively call
371 * ossl_lib_ctx_get_data for other indexes (never this one). The allocation
372 * will itself aquire the ctx->lock when it actually comes to store the
373 * allocated data (see ossl_lib_ctx_generic_new() above). We call
374 * ossl_crypto_alloc_ex_data_intern() here instead of CRYPTO_alloc_ex_data().
375 * They do the same thing except that the latter calls CRYPTO_get_ex_data()
376 * as well - which we must not do without holding the ctx->lock.
378 if (ossl_crypto_alloc_ex_data_intern(CRYPTO_EX_INDEX_OSSL_LIB_CTX
, NULL
,
379 &ctx
->data
, ctx
->dyn_indexes
[index
])) {
380 if (!CRYPTO_THREAD_read_lock(ctx
->lock
))
382 data
= CRYPTO_get_ex_data(&ctx
->data
, ctx
->dyn_indexes
[index
]);
383 CRYPTO_THREAD_unlock(ctx
->lock
);
387 CRYPTO_THREAD_unlock(ctx
->index_locks
[index
]);
391 OSSL_EX_DATA_GLOBAL
*ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX
*ctx
)
393 ctx
= ossl_lib_ctx_get_concrete(ctx
);
399 int ossl_lib_ctx_run_once(OSSL_LIB_CTX
*ctx
, unsigned int idx
,
400 ossl_lib_ctx_run_once_fn run_once_fn
)
402 int done
= 0, ret
= 0;
404 ctx
= ossl_lib_ctx_get_concrete(ctx
);
408 if (!CRYPTO_THREAD_read_lock(ctx
->oncelock
))
410 done
= ctx
->run_once_done
[idx
];
412 ret
= ctx
->run_once_ret
[idx
];
413 CRYPTO_THREAD_unlock(ctx
->oncelock
);
418 if (!CRYPTO_THREAD_write_lock(ctx
->oncelock
))
420 if (ctx
->run_once_done
[idx
]) {
421 ret
= ctx
->run_once_ret
[idx
];
422 CRYPTO_THREAD_unlock(ctx
->oncelock
);
426 ret
= run_once_fn(ctx
);
427 ctx
->run_once_done
[idx
] = 1;
428 ctx
->run_once_ret
[idx
] = ret
;
429 CRYPTO_THREAD_unlock(ctx
->oncelock
);
434 int ossl_lib_ctx_onfree(OSSL_LIB_CTX
*ctx
, ossl_lib_ctx_onfree_fn onfreefn
)
436 struct ossl_lib_ctx_onfree_list_st
*newonfree
437 = OPENSSL_malloc(sizeof(*newonfree
));
439 if (newonfree
== NULL
)
442 newonfree
->fn
= onfreefn
;
443 newonfree
->next
= ctx
->onfreelist
;
444 ctx
->onfreelist
= newonfree
;
449 const char *ossl_lib_ctx_get_descriptor(OSSL_LIB_CTX
*libctx
)
452 return "FIPS internal library context";
454 if (ossl_lib_ctx_is_global_default(libctx
))
455 return "Global default library context";
456 if (ossl_lib_ctx_is_default(libctx
))
457 return "Thread-local default library context";
458 return "Non-default library context";