1b077aed3SPierre Pronchery /* 2*a7148ab3SEnji Cooper * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. 3b077aed3SPierre Pronchery * 4b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 5b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy 6b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at 7b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html 8b077aed3SPierre Pronchery */ 9b077aed3SPierre Pronchery 10b077aed3SPierre Pronchery #include "crypto/cryptlib.h" 11b077aed3SPierre Pronchery #include <openssl/conf.h> 12b077aed3SPierre Pronchery #include "internal/thread_once.h" 13b077aed3SPierre Pronchery #include "internal/property.h" 14b077aed3SPierre Pronchery #include "internal/core.h" 15b077aed3SPierre Pronchery #include "internal/bio.h" 16b077aed3SPierre Pronchery #include "internal/provider.h" 17b077aed3SPierre Pronchery #include "crypto/ctype.h" 18b077aed3SPierre Pronchery #include "crypto/rand.h" 19b077aed3SPierre Pronchery 20b077aed3SPierre Pronchery struct ossl_lib_ctx_onfree_list_st { 21b077aed3SPierre Pronchery ossl_lib_ctx_onfree_fn *fn; 22b077aed3SPierre Pronchery struct ossl_lib_ctx_onfree_list_st *next; 23b077aed3SPierre Pronchery }; 24b077aed3SPierre Pronchery 25b077aed3SPierre Pronchery struct ossl_lib_ctx_st { 26b077aed3SPierre Pronchery CRYPTO_RWLOCK *lock; 27b077aed3SPierre Pronchery CRYPTO_EX_DATA data; 28b077aed3SPierre Pronchery 29b077aed3SPierre Pronchery /* 30b077aed3SPierre Pronchery * For most data in the OSSL_LIB_CTX we just use ex_data to store it. But 31b077aed3SPierre Pronchery * that doesn't work for ex_data itself - so we store that directly. 32b077aed3SPierre Pronchery */ 33b077aed3SPierre Pronchery OSSL_EX_DATA_GLOBAL global; 34b077aed3SPierre Pronchery 35b077aed3SPierre Pronchery /* Map internal static indexes to dynamically created indexes */ 36b077aed3SPierre Pronchery int dyn_indexes[OSSL_LIB_CTX_MAX_INDEXES]; 37b077aed3SPierre Pronchery 38b077aed3SPierre Pronchery /* Keep a separate lock for each index */ 39b077aed3SPierre Pronchery CRYPTO_RWLOCK *index_locks[OSSL_LIB_CTX_MAX_INDEXES]; 40b077aed3SPierre Pronchery 41b077aed3SPierre Pronchery CRYPTO_RWLOCK *oncelock; 42b077aed3SPierre Pronchery int run_once_done[OSSL_LIB_CTX_MAX_RUN_ONCE]; 43b077aed3SPierre Pronchery int run_once_ret[OSSL_LIB_CTX_MAX_RUN_ONCE]; 44b077aed3SPierre Pronchery struct ossl_lib_ctx_onfree_list_st *onfreelist; 45b077aed3SPierre Pronchery unsigned int ischild:1; 46b077aed3SPierre Pronchery }; 47b077aed3SPierre Pronchery 48b077aed3SPierre Pronchery int ossl_lib_ctx_write_lock(OSSL_LIB_CTX *ctx) 49b077aed3SPierre Pronchery { 50b077aed3SPierre Pronchery return CRYPTO_THREAD_write_lock(ossl_lib_ctx_get_concrete(ctx)->lock); 51b077aed3SPierre Pronchery } 52b077aed3SPierre Pronchery 53b077aed3SPierre Pronchery int ossl_lib_ctx_read_lock(OSSL_LIB_CTX *ctx) 54b077aed3SPierre Pronchery { 55b077aed3SPierre Pronchery return CRYPTO_THREAD_read_lock(ossl_lib_ctx_get_concrete(ctx)->lock); 56b077aed3SPierre Pronchery } 57b077aed3SPierre Pronchery 58b077aed3SPierre Pronchery int ossl_lib_ctx_unlock(OSSL_LIB_CTX *ctx) 59b077aed3SPierre Pronchery { 60b077aed3SPierre Pronchery return CRYPTO_THREAD_unlock(ossl_lib_ctx_get_concrete(ctx)->lock); 61b077aed3SPierre Pronchery } 62b077aed3SPierre Pronchery 63b077aed3SPierre Pronchery int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx) 64b077aed3SPierre Pronchery { 65b077aed3SPierre Pronchery ctx = ossl_lib_ctx_get_concrete(ctx); 66b077aed3SPierre Pronchery 67b077aed3SPierre Pronchery if (ctx == NULL) 68b077aed3SPierre Pronchery return 0; 69b077aed3SPierre Pronchery return ctx->ischild; 70b077aed3SPierre Pronchery } 71b077aed3SPierre Pronchery 72b077aed3SPierre Pronchery static int context_init(OSSL_LIB_CTX *ctx) 73b077aed3SPierre Pronchery { 74b077aed3SPierre Pronchery size_t i; 75b077aed3SPierre Pronchery int exdata_done = 0; 76b077aed3SPierre Pronchery 77b077aed3SPierre Pronchery ctx->lock = CRYPTO_THREAD_lock_new(); 78b077aed3SPierre Pronchery if (ctx->lock == NULL) 79b077aed3SPierre Pronchery return 0; 80b077aed3SPierre Pronchery 81b077aed3SPierre Pronchery ctx->oncelock = CRYPTO_THREAD_lock_new(); 82b077aed3SPierre Pronchery if (ctx->oncelock == NULL) 83b077aed3SPierre Pronchery goto err; 84b077aed3SPierre Pronchery 85b077aed3SPierre Pronchery for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++) { 86b077aed3SPierre Pronchery ctx->index_locks[i] = CRYPTO_THREAD_lock_new(); 87b077aed3SPierre Pronchery ctx->dyn_indexes[i] = -1; 88b077aed3SPierre Pronchery if (ctx->index_locks[i] == NULL) 89b077aed3SPierre Pronchery goto err; 90b077aed3SPierre Pronchery } 91b077aed3SPierre Pronchery 92b077aed3SPierre Pronchery /* OSSL_LIB_CTX is built on top of ex_data so we initialise that directly */ 93b077aed3SPierre Pronchery if (!ossl_do_ex_data_init(ctx)) 94b077aed3SPierre Pronchery goto err; 95b077aed3SPierre Pronchery exdata_done = 1; 96b077aed3SPierre Pronchery 97b077aed3SPierre Pronchery if (!ossl_crypto_new_ex_data_ex(ctx, CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL, 98b077aed3SPierre Pronchery &ctx->data)) 99b077aed3SPierre Pronchery goto err; 100b077aed3SPierre Pronchery 101b077aed3SPierre Pronchery /* Everything depends on properties, so we also pre-initialise that */ 102b077aed3SPierre Pronchery if (!ossl_property_parse_init(ctx)) 103b077aed3SPierre Pronchery goto err; 104b077aed3SPierre Pronchery 105b077aed3SPierre Pronchery return 1; 106b077aed3SPierre Pronchery err: 107b077aed3SPierre Pronchery if (exdata_done) 108b077aed3SPierre Pronchery ossl_crypto_cleanup_all_ex_data_int(ctx); 109b077aed3SPierre Pronchery for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++) 110b077aed3SPierre Pronchery CRYPTO_THREAD_lock_free(ctx->index_locks[i]); 111b077aed3SPierre Pronchery CRYPTO_THREAD_lock_free(ctx->oncelock); 112b077aed3SPierre Pronchery CRYPTO_THREAD_lock_free(ctx->lock); 113b077aed3SPierre Pronchery memset(ctx, '\0', sizeof(*ctx)); 114b077aed3SPierre Pronchery return 0; 115b077aed3SPierre Pronchery } 116b077aed3SPierre Pronchery 117b077aed3SPierre Pronchery static int context_deinit(OSSL_LIB_CTX *ctx) 118b077aed3SPierre Pronchery { 119b077aed3SPierre Pronchery struct ossl_lib_ctx_onfree_list_st *tmp, *onfree; 120b077aed3SPierre Pronchery int i; 121b077aed3SPierre Pronchery 122b077aed3SPierre Pronchery if (ctx == NULL) 123b077aed3SPierre Pronchery return 1; 124b077aed3SPierre Pronchery 125b077aed3SPierre Pronchery ossl_ctx_thread_stop(ctx); 126b077aed3SPierre Pronchery 127b077aed3SPierre Pronchery onfree = ctx->onfreelist; 128b077aed3SPierre Pronchery while (onfree != NULL) { 129b077aed3SPierre Pronchery onfree->fn(ctx); 130b077aed3SPierre Pronchery tmp = onfree; 131b077aed3SPierre Pronchery onfree = onfree->next; 132b077aed3SPierre Pronchery OPENSSL_free(tmp); 133b077aed3SPierre Pronchery } 134b077aed3SPierre Pronchery CRYPTO_free_ex_data(CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL, &ctx->data); 135b077aed3SPierre Pronchery ossl_crypto_cleanup_all_ex_data_int(ctx); 136b077aed3SPierre Pronchery for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++) 137b077aed3SPierre Pronchery CRYPTO_THREAD_lock_free(ctx->index_locks[i]); 138b077aed3SPierre Pronchery 139b077aed3SPierre Pronchery CRYPTO_THREAD_lock_free(ctx->oncelock); 140b077aed3SPierre Pronchery CRYPTO_THREAD_lock_free(ctx->lock); 141b077aed3SPierre Pronchery ctx->lock = NULL; 142b077aed3SPierre Pronchery return 1; 143b077aed3SPierre Pronchery } 144b077aed3SPierre Pronchery 145b077aed3SPierre Pronchery #ifndef FIPS_MODULE 146b077aed3SPierre Pronchery /* The default default context */ 147b077aed3SPierre Pronchery static OSSL_LIB_CTX default_context_int; 148b077aed3SPierre Pronchery 149b077aed3SPierre Pronchery static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT; 150b077aed3SPierre Pronchery static CRYPTO_THREAD_LOCAL default_context_thread_local; 151b077aed3SPierre Pronchery 152b077aed3SPierre Pronchery DEFINE_RUN_ONCE_STATIC(default_context_do_init) 153b077aed3SPierre Pronchery { 154b077aed3SPierre Pronchery return CRYPTO_THREAD_init_local(&default_context_thread_local, NULL) 155b077aed3SPierre Pronchery && context_init(&default_context_int); 156b077aed3SPierre Pronchery } 157b077aed3SPierre Pronchery 158b077aed3SPierre Pronchery void ossl_lib_ctx_default_deinit(void) 159b077aed3SPierre Pronchery { 160b077aed3SPierre Pronchery context_deinit(&default_context_int); 161b077aed3SPierre Pronchery CRYPTO_THREAD_cleanup_local(&default_context_thread_local); 162b077aed3SPierre Pronchery } 163b077aed3SPierre Pronchery 164b077aed3SPierre Pronchery static OSSL_LIB_CTX *get_thread_default_context(void) 165b077aed3SPierre Pronchery { 166b077aed3SPierre Pronchery if (!RUN_ONCE(&default_context_init, default_context_do_init)) 167b077aed3SPierre Pronchery return NULL; 168b077aed3SPierre Pronchery 169b077aed3SPierre Pronchery return CRYPTO_THREAD_get_local(&default_context_thread_local); 170b077aed3SPierre Pronchery } 171b077aed3SPierre Pronchery 172b077aed3SPierre Pronchery static OSSL_LIB_CTX *get_default_context(void) 173b077aed3SPierre Pronchery { 174b077aed3SPierre Pronchery OSSL_LIB_CTX *current_defctx = get_thread_default_context(); 175b077aed3SPierre Pronchery 176b077aed3SPierre Pronchery if (current_defctx == NULL) 177b077aed3SPierre Pronchery current_defctx = &default_context_int; 178b077aed3SPierre Pronchery return current_defctx; 179b077aed3SPierre Pronchery } 180b077aed3SPierre Pronchery 181b077aed3SPierre Pronchery static int set_default_context(OSSL_LIB_CTX *defctx) 182b077aed3SPierre Pronchery { 183b077aed3SPierre Pronchery if (defctx == &default_context_int) 184b077aed3SPierre Pronchery defctx = NULL; 185b077aed3SPierre Pronchery 186b077aed3SPierre Pronchery return CRYPTO_THREAD_set_local(&default_context_thread_local, defctx); 187b077aed3SPierre Pronchery } 188b077aed3SPierre Pronchery #endif 189b077aed3SPierre Pronchery 190b077aed3SPierre Pronchery OSSL_LIB_CTX *OSSL_LIB_CTX_new(void) 191b077aed3SPierre Pronchery { 192b077aed3SPierre Pronchery OSSL_LIB_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); 193b077aed3SPierre Pronchery 194b077aed3SPierre Pronchery if (ctx != NULL && !context_init(ctx)) { 195b077aed3SPierre Pronchery OPENSSL_free(ctx); 196b077aed3SPierre Pronchery ctx = NULL; 197b077aed3SPierre Pronchery } 198b077aed3SPierre Pronchery return ctx; 199b077aed3SPierre Pronchery } 200b077aed3SPierre Pronchery 201b077aed3SPierre Pronchery #ifndef FIPS_MODULE 202b077aed3SPierre Pronchery OSSL_LIB_CTX *OSSL_LIB_CTX_new_from_dispatch(const OSSL_CORE_HANDLE *handle, 203b077aed3SPierre Pronchery const OSSL_DISPATCH *in) 204b077aed3SPierre Pronchery { 205b077aed3SPierre Pronchery OSSL_LIB_CTX *ctx = OSSL_LIB_CTX_new(); 206b077aed3SPierre Pronchery 207b077aed3SPierre Pronchery if (ctx == NULL) 208b077aed3SPierre Pronchery return NULL; 209b077aed3SPierre Pronchery 210b077aed3SPierre Pronchery if (!ossl_bio_init_core(ctx, in)) { 211b077aed3SPierre Pronchery OSSL_LIB_CTX_free(ctx); 212b077aed3SPierre Pronchery return NULL; 213b077aed3SPierre Pronchery } 214b077aed3SPierre Pronchery 215b077aed3SPierre Pronchery return ctx; 216b077aed3SPierre Pronchery } 217b077aed3SPierre Pronchery 218b077aed3SPierre Pronchery OSSL_LIB_CTX *OSSL_LIB_CTX_new_child(const OSSL_CORE_HANDLE *handle, 219b077aed3SPierre Pronchery const OSSL_DISPATCH *in) 220b077aed3SPierre Pronchery { 221b077aed3SPierre Pronchery OSSL_LIB_CTX *ctx = OSSL_LIB_CTX_new_from_dispatch(handle, in); 222b077aed3SPierre Pronchery 223b077aed3SPierre Pronchery if (ctx == NULL) 224b077aed3SPierre Pronchery return NULL; 225b077aed3SPierre Pronchery 226b077aed3SPierre Pronchery if (!ossl_provider_init_as_child(ctx, handle, in)) { 227b077aed3SPierre Pronchery OSSL_LIB_CTX_free(ctx); 228b077aed3SPierre Pronchery return NULL; 229b077aed3SPierre Pronchery } 230b077aed3SPierre Pronchery ctx->ischild = 1; 231b077aed3SPierre Pronchery 232b077aed3SPierre Pronchery return ctx; 233b077aed3SPierre Pronchery } 234b077aed3SPierre Pronchery 235b077aed3SPierre Pronchery int OSSL_LIB_CTX_load_config(OSSL_LIB_CTX *ctx, const char *config_file) 236b077aed3SPierre Pronchery { 237b077aed3SPierre Pronchery return CONF_modules_load_file_ex(ctx, config_file, NULL, 0) > 0; 238b077aed3SPierre Pronchery } 239b077aed3SPierre Pronchery #endif 240b077aed3SPierre Pronchery 241b077aed3SPierre Pronchery void OSSL_LIB_CTX_free(OSSL_LIB_CTX *ctx) 242b077aed3SPierre Pronchery { 243*a7148ab3SEnji Cooper if (ctx == NULL || ossl_lib_ctx_is_default(ctx)) 244b077aed3SPierre Pronchery return; 245b077aed3SPierre Pronchery 246b077aed3SPierre Pronchery #ifndef FIPS_MODULE 247b077aed3SPierre Pronchery if (ctx->ischild) 248b077aed3SPierre Pronchery ossl_provider_deinit_child(ctx); 249b077aed3SPierre Pronchery #endif 250b077aed3SPierre Pronchery context_deinit(ctx); 251b077aed3SPierre Pronchery OPENSSL_free(ctx); 252b077aed3SPierre Pronchery } 253b077aed3SPierre Pronchery 254b077aed3SPierre Pronchery #ifndef FIPS_MODULE 255b077aed3SPierre Pronchery OSSL_LIB_CTX *OSSL_LIB_CTX_get0_global_default(void) 256b077aed3SPierre Pronchery { 257b077aed3SPierre Pronchery if (!RUN_ONCE(&default_context_init, default_context_do_init)) 258b077aed3SPierre Pronchery return NULL; 259b077aed3SPierre Pronchery 260b077aed3SPierre Pronchery return &default_context_int; 261b077aed3SPierre Pronchery } 262b077aed3SPierre Pronchery 263b077aed3SPierre Pronchery OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *libctx) 264b077aed3SPierre Pronchery { 265b077aed3SPierre Pronchery OSSL_LIB_CTX *current_defctx; 266b077aed3SPierre Pronchery 267b077aed3SPierre Pronchery if ((current_defctx = get_default_context()) != NULL) { 268b077aed3SPierre Pronchery if (libctx != NULL) 269b077aed3SPierre Pronchery set_default_context(libctx); 270b077aed3SPierre Pronchery return current_defctx; 271b077aed3SPierre Pronchery } 272b077aed3SPierre Pronchery 273b077aed3SPierre Pronchery return NULL; 274b077aed3SPierre Pronchery } 275b077aed3SPierre Pronchery 276b077aed3SPierre Pronchery void ossl_release_default_drbg_ctx(void) 277b077aed3SPierre Pronchery { 278b077aed3SPierre Pronchery int dynidx = default_context_int.dyn_indexes[OSSL_LIB_CTX_DRBG_INDEX]; 279b077aed3SPierre Pronchery 280b077aed3SPierre Pronchery /* early release of the DRBG in global default libctx, no locking */ 281b077aed3SPierre Pronchery if (dynidx != -1) { 282b077aed3SPierre Pronchery void *data; 283b077aed3SPierre Pronchery 284b077aed3SPierre Pronchery data = CRYPTO_get_ex_data(&default_context_int.data, dynidx); 285b077aed3SPierre Pronchery ossl_rand_ctx_free(data); 286b077aed3SPierre Pronchery CRYPTO_set_ex_data(&default_context_int.data, dynidx, NULL); 287b077aed3SPierre Pronchery } 288b077aed3SPierre Pronchery } 289b077aed3SPierre Pronchery #endif 290b077aed3SPierre Pronchery 291b077aed3SPierre Pronchery OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx) 292b077aed3SPierre Pronchery { 293b077aed3SPierre Pronchery #ifndef FIPS_MODULE 294b077aed3SPierre Pronchery if (ctx == NULL) 295b077aed3SPierre Pronchery return get_default_context(); 296b077aed3SPierre Pronchery #endif 297b077aed3SPierre Pronchery return ctx; 298b077aed3SPierre Pronchery } 299b077aed3SPierre Pronchery 300b077aed3SPierre Pronchery int ossl_lib_ctx_is_default(OSSL_LIB_CTX *ctx) 301b077aed3SPierre Pronchery { 302b077aed3SPierre Pronchery #ifndef FIPS_MODULE 303b077aed3SPierre Pronchery if (ctx == NULL || ctx == get_default_context()) 304b077aed3SPierre Pronchery return 1; 305b077aed3SPierre Pronchery #endif 306b077aed3SPierre Pronchery return 0; 307b077aed3SPierre Pronchery } 308b077aed3SPierre Pronchery 309b077aed3SPierre Pronchery int ossl_lib_ctx_is_global_default(OSSL_LIB_CTX *ctx) 310b077aed3SPierre Pronchery { 311b077aed3SPierre Pronchery #ifndef FIPS_MODULE 312b077aed3SPierre Pronchery if (ossl_lib_ctx_get_concrete(ctx) == &default_context_int) 313b077aed3SPierre Pronchery return 1; 314b077aed3SPierre Pronchery #endif 315b077aed3SPierre Pronchery return 0; 316b077aed3SPierre Pronchery } 317b077aed3SPierre Pronchery 318b077aed3SPierre Pronchery static void ossl_lib_ctx_generic_new(void *parent_ign, void *ptr_ign, 319b077aed3SPierre Pronchery CRYPTO_EX_DATA *ad, int index, 320b077aed3SPierre Pronchery long argl_ign, void *argp) 321b077aed3SPierre Pronchery { 322b077aed3SPierre Pronchery const OSSL_LIB_CTX_METHOD *meth = argp; 323b077aed3SPierre Pronchery OSSL_LIB_CTX *ctx = ossl_crypto_ex_data_get_ossl_lib_ctx(ad); 324b077aed3SPierre Pronchery void *ptr = meth->new_func(ctx); 325b077aed3SPierre Pronchery 326b077aed3SPierre Pronchery if (ptr != NULL) { 327b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(ctx->lock)) 328b077aed3SPierre Pronchery /* 329b077aed3SPierre Pronchery * Can't return something, so best to hope that something will 330b077aed3SPierre Pronchery * fail later. :( 331b077aed3SPierre Pronchery */ 332b077aed3SPierre Pronchery return; 333b077aed3SPierre Pronchery CRYPTO_set_ex_data(ad, index, ptr); 334b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->lock); 335b077aed3SPierre Pronchery } 336b077aed3SPierre Pronchery } 337b077aed3SPierre Pronchery static void ossl_lib_ctx_generic_free(void *parent_ign, void *ptr, 338b077aed3SPierre Pronchery CRYPTO_EX_DATA *ad, int index, 339b077aed3SPierre Pronchery long argl_ign, void *argp) 340b077aed3SPierre Pronchery { 341b077aed3SPierre Pronchery const OSSL_LIB_CTX_METHOD *meth = argp; 342b077aed3SPierre Pronchery 343b077aed3SPierre Pronchery meth->free_func(ptr); 344b077aed3SPierre Pronchery } 345b077aed3SPierre Pronchery 346b077aed3SPierre Pronchery static int ossl_lib_ctx_init_index(OSSL_LIB_CTX *ctx, int static_index, 347b077aed3SPierre Pronchery const OSSL_LIB_CTX_METHOD *meth) 348b077aed3SPierre Pronchery { 349b077aed3SPierre Pronchery int idx; 350b077aed3SPierre Pronchery 351b077aed3SPierre Pronchery ctx = ossl_lib_ctx_get_concrete(ctx); 352b077aed3SPierre Pronchery if (ctx == NULL) 353b077aed3SPierre Pronchery return 0; 354b077aed3SPierre Pronchery 355b077aed3SPierre Pronchery idx = ossl_crypto_get_ex_new_index_ex(ctx, CRYPTO_EX_INDEX_OSSL_LIB_CTX, 0, 356b077aed3SPierre Pronchery (void *)meth, 357b077aed3SPierre Pronchery ossl_lib_ctx_generic_new, 358b077aed3SPierre Pronchery NULL, ossl_lib_ctx_generic_free, 359b077aed3SPierre Pronchery meth->priority); 360b077aed3SPierre Pronchery if (idx < 0) 361b077aed3SPierre Pronchery return 0; 362b077aed3SPierre Pronchery 363b077aed3SPierre Pronchery ctx->dyn_indexes[static_index] = idx; 364b077aed3SPierre Pronchery return 1; 365b077aed3SPierre Pronchery } 366b077aed3SPierre Pronchery 367b077aed3SPierre Pronchery void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index, 368b077aed3SPierre Pronchery const OSSL_LIB_CTX_METHOD *meth) 369b077aed3SPierre Pronchery { 370b077aed3SPierre Pronchery void *data = NULL; 371b077aed3SPierre Pronchery int dynidx; 372b077aed3SPierre Pronchery 373b077aed3SPierre Pronchery ctx = ossl_lib_ctx_get_concrete(ctx); 374b077aed3SPierre Pronchery if (ctx == NULL) 375b077aed3SPierre Pronchery return NULL; 376b077aed3SPierre Pronchery 377b077aed3SPierre Pronchery if (!CRYPTO_THREAD_read_lock(ctx->lock)) 378b077aed3SPierre Pronchery return NULL; 379b077aed3SPierre Pronchery dynidx = ctx->dyn_indexes[index]; 380b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->lock); 381b077aed3SPierre Pronchery 382b077aed3SPierre Pronchery if (dynidx != -1) { 383b077aed3SPierre Pronchery if (!CRYPTO_THREAD_read_lock(ctx->index_locks[index])) 384b077aed3SPierre Pronchery return NULL; 385b077aed3SPierre Pronchery if (!CRYPTO_THREAD_read_lock(ctx->lock)) { 386b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->index_locks[index]); 387b077aed3SPierre Pronchery return NULL; 388b077aed3SPierre Pronchery } 389b077aed3SPierre Pronchery data = CRYPTO_get_ex_data(&ctx->data, dynidx); 390b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->lock); 391b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->index_locks[index]); 392b077aed3SPierre Pronchery return data; 393b077aed3SPierre Pronchery } 394b077aed3SPierre Pronchery 395b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(ctx->index_locks[index])) 396b077aed3SPierre Pronchery return NULL; 397b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(ctx->lock)) { 398b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->index_locks[index]); 399b077aed3SPierre Pronchery return NULL; 400b077aed3SPierre Pronchery } 401b077aed3SPierre Pronchery 402b077aed3SPierre Pronchery dynidx = ctx->dyn_indexes[index]; 403b077aed3SPierre Pronchery if (dynidx != -1) { 404b077aed3SPierre Pronchery data = CRYPTO_get_ex_data(&ctx->data, dynidx); 405b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->lock); 406b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->index_locks[index]); 407b077aed3SPierre Pronchery return data; 408b077aed3SPierre Pronchery } 409b077aed3SPierre Pronchery 410b077aed3SPierre Pronchery if (!ossl_lib_ctx_init_index(ctx, index, meth)) { 411b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->lock); 412b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->index_locks[index]); 413b077aed3SPierre Pronchery return NULL; 414b077aed3SPierre Pronchery } 415b077aed3SPierre Pronchery 416b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->lock); 417b077aed3SPierre Pronchery 418b077aed3SPierre Pronchery /* 419b077aed3SPierre Pronchery * The alloc call ensures there's a value there. We release the ctx->lock 420b077aed3SPierre Pronchery * for this, because the allocation itself may recursively call 421b077aed3SPierre Pronchery * ossl_lib_ctx_get_data for other indexes (never this one). The allocation 422b077aed3SPierre Pronchery * will itself aquire the ctx->lock when it actually comes to store the 423b077aed3SPierre Pronchery * allocated data (see ossl_lib_ctx_generic_new() above). We call 424b077aed3SPierre Pronchery * ossl_crypto_alloc_ex_data_intern() here instead of CRYPTO_alloc_ex_data(). 425b077aed3SPierre Pronchery * They do the same thing except that the latter calls CRYPTO_get_ex_data() 426b077aed3SPierre Pronchery * as well - which we must not do without holding the ctx->lock. 427b077aed3SPierre Pronchery */ 428b077aed3SPierre Pronchery if (ossl_crypto_alloc_ex_data_intern(CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL, 429b077aed3SPierre Pronchery &ctx->data, ctx->dyn_indexes[index])) { 430b077aed3SPierre Pronchery if (!CRYPTO_THREAD_read_lock(ctx->lock)) 431b077aed3SPierre Pronchery goto end; 432b077aed3SPierre Pronchery data = CRYPTO_get_ex_data(&ctx->data, ctx->dyn_indexes[index]); 433b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->lock); 434b077aed3SPierre Pronchery } 435b077aed3SPierre Pronchery 436b077aed3SPierre Pronchery end: 437b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->index_locks[index]); 438b077aed3SPierre Pronchery return data; 439b077aed3SPierre Pronchery } 440b077aed3SPierre Pronchery 441b077aed3SPierre Pronchery OSSL_EX_DATA_GLOBAL *ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX *ctx) 442b077aed3SPierre Pronchery { 443b077aed3SPierre Pronchery ctx = ossl_lib_ctx_get_concrete(ctx); 444b077aed3SPierre Pronchery if (ctx == NULL) 445b077aed3SPierre Pronchery return NULL; 446b077aed3SPierre Pronchery return &ctx->global; 447b077aed3SPierre Pronchery } 448b077aed3SPierre Pronchery 449b077aed3SPierre Pronchery int ossl_lib_ctx_run_once(OSSL_LIB_CTX *ctx, unsigned int idx, 450b077aed3SPierre Pronchery ossl_lib_ctx_run_once_fn run_once_fn) 451b077aed3SPierre Pronchery { 452b077aed3SPierre Pronchery int done = 0, ret = 0; 453b077aed3SPierre Pronchery 454b077aed3SPierre Pronchery ctx = ossl_lib_ctx_get_concrete(ctx); 455b077aed3SPierre Pronchery if (ctx == NULL) 456b077aed3SPierre Pronchery return 0; 457b077aed3SPierre Pronchery 458b077aed3SPierre Pronchery if (!CRYPTO_THREAD_read_lock(ctx->oncelock)) 459b077aed3SPierre Pronchery return 0; 460b077aed3SPierre Pronchery done = ctx->run_once_done[idx]; 461b077aed3SPierre Pronchery if (done) 462b077aed3SPierre Pronchery ret = ctx->run_once_ret[idx]; 463b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->oncelock); 464b077aed3SPierre Pronchery 465b077aed3SPierre Pronchery if (done) 466b077aed3SPierre Pronchery return ret; 467b077aed3SPierre Pronchery 468b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(ctx->oncelock)) 469b077aed3SPierre Pronchery return 0; 470b077aed3SPierre Pronchery if (ctx->run_once_done[idx]) { 471b077aed3SPierre Pronchery ret = ctx->run_once_ret[idx]; 472b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->oncelock); 473b077aed3SPierre Pronchery return ret; 474b077aed3SPierre Pronchery } 475b077aed3SPierre Pronchery 476b077aed3SPierre Pronchery ret = run_once_fn(ctx); 477b077aed3SPierre Pronchery ctx->run_once_done[idx] = 1; 478b077aed3SPierre Pronchery ctx->run_once_ret[idx] = ret; 479b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(ctx->oncelock); 480b077aed3SPierre Pronchery 481b077aed3SPierre Pronchery return ret; 482b077aed3SPierre Pronchery } 483b077aed3SPierre Pronchery 484b077aed3SPierre Pronchery int ossl_lib_ctx_onfree(OSSL_LIB_CTX *ctx, ossl_lib_ctx_onfree_fn onfreefn) 485b077aed3SPierre Pronchery { 486b077aed3SPierre Pronchery struct ossl_lib_ctx_onfree_list_st *newonfree 487b077aed3SPierre Pronchery = OPENSSL_malloc(sizeof(*newonfree)); 488b077aed3SPierre Pronchery 489b077aed3SPierre Pronchery if (newonfree == NULL) 490b077aed3SPierre Pronchery return 0; 491b077aed3SPierre Pronchery 492b077aed3SPierre Pronchery newonfree->fn = onfreefn; 493b077aed3SPierre Pronchery newonfree->next = ctx->onfreelist; 494b077aed3SPierre Pronchery ctx->onfreelist = newonfree; 495b077aed3SPierre Pronchery 496b077aed3SPierre Pronchery return 1; 497b077aed3SPierre Pronchery } 498b077aed3SPierre Pronchery 499b077aed3SPierre Pronchery const char *ossl_lib_ctx_get_descriptor(OSSL_LIB_CTX *libctx) 500b077aed3SPierre Pronchery { 501b077aed3SPierre Pronchery #ifdef FIPS_MODULE 502b077aed3SPierre Pronchery return "FIPS internal library context"; 503b077aed3SPierre Pronchery #else 504b077aed3SPierre Pronchery if (ossl_lib_ctx_is_global_default(libctx)) 505b077aed3SPierre Pronchery return "Global default library context"; 506b077aed3SPierre Pronchery if (ossl_lib_ctx_is_default(libctx)) 507b077aed3SPierre Pronchery return "Thread-local default library context"; 508b077aed3SPierre Pronchery return "Non-default library context"; 509b077aed3SPierre Pronchery #endif 510b077aed3SPierre Pronchery } 511