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