context.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /*
  2. * Copyright 2019-2020 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. #include "crypto/cryptlib.h"
  10. #include <openssl/conf.h>
  11. #include "internal/thread_once.h"
  12. #include "internal/property.h"
  13. struct ossl_lib_ctx_onfree_list_st {
  14. ossl_lib_ctx_onfree_fn *fn;
  15. struct ossl_lib_ctx_onfree_list_st *next;
  16. };
  17. struct ossl_lib_ctx_st {
  18. CRYPTO_RWLOCK *lock;
  19. CRYPTO_EX_DATA data;
  20. /*
  21. * For most data in the OSSL_LIB_CTX we just use ex_data to store it. But
  22. * that doesn't work for ex_data itself - so we store that directly.
  23. */
  24. OSSL_EX_DATA_GLOBAL global;
  25. /* Map internal static indexes to dynamically created indexes */
  26. int dyn_indexes[OSSL_LIB_CTX_MAX_INDEXES];
  27. /* Keep a separate lock for each index */
  28. CRYPTO_RWLOCK *index_locks[OSSL_LIB_CTX_MAX_INDEXES];
  29. CRYPTO_RWLOCK *oncelock;
  30. int run_once_done[OSSL_LIB_CTX_MAX_RUN_ONCE];
  31. int run_once_ret[OSSL_LIB_CTX_MAX_RUN_ONCE];
  32. struct ossl_lib_ctx_onfree_list_st *onfreelist;
  33. };
  34. static int context_init(OSSL_LIB_CTX *ctx)
  35. {
  36. size_t i;
  37. int exdata_done = 0;
  38. ctx->lock = CRYPTO_THREAD_lock_new();
  39. if (ctx->lock == NULL)
  40. return 0;
  41. ctx->oncelock = CRYPTO_THREAD_lock_new();
  42. if (ctx->oncelock == NULL)
  43. goto err;
  44. for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++) {
  45. ctx->index_locks[i] = CRYPTO_THREAD_lock_new();
  46. ctx->dyn_indexes[i] = -1;
  47. if (ctx->index_locks[i] == NULL)
  48. goto err;
  49. }
  50. /* OSSL_LIB_CTX is built on top of ex_data so we initialise that directly */
  51. if (!do_ex_data_init(ctx))
  52. goto err;
  53. exdata_done = 1;
  54. if (!crypto_new_ex_data_ex(ctx, CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL,
  55. &ctx->data)) {
  56. crypto_cleanup_all_ex_data_int(ctx);
  57. goto err;
  58. }
  59. /* Everything depends on properties, so we also pre-initialise that */
  60. if (!ossl_property_parse_init(ctx))
  61. goto err;
  62. return 1;
  63. err:
  64. if (exdata_done)
  65. crypto_cleanup_all_ex_data_int(ctx);
  66. CRYPTO_THREAD_lock_free(ctx->oncelock);
  67. CRYPTO_THREAD_lock_free(ctx->lock);
  68. ctx->lock = NULL;
  69. return 0;
  70. }
  71. static int context_deinit(OSSL_LIB_CTX *ctx)
  72. {
  73. struct ossl_lib_ctx_onfree_list_st *tmp, *onfree;
  74. int i;
  75. if (ctx == NULL)
  76. return 1;
  77. ossl_ctx_thread_stop(ctx);
  78. onfree = ctx->onfreelist;
  79. while (onfree != NULL) {
  80. onfree->fn(ctx);
  81. tmp = onfree;
  82. onfree = onfree->next;
  83. OPENSSL_free(tmp);
  84. }
  85. CRYPTO_free_ex_data(CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL, &ctx->data);
  86. crypto_cleanup_all_ex_data_int(ctx);
  87. for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++)
  88. CRYPTO_THREAD_lock_free(ctx->index_locks[i]);
  89. CRYPTO_THREAD_lock_free(ctx->oncelock);
  90. CRYPTO_THREAD_lock_free(ctx->lock);
  91. ctx->lock = NULL;
  92. return 1;
  93. }
  94. #ifndef FIPS_MODULE
  95. /* The default default context */
  96. static OSSL_LIB_CTX default_context_int;
  97. static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT;
  98. static CRYPTO_THREAD_LOCAL default_context_thread_local;
  99. DEFINE_RUN_ONCE_STATIC(default_context_do_init)
  100. {
  101. return CRYPTO_THREAD_init_local(&default_context_thread_local, NULL)
  102. && context_init(&default_context_int);
  103. }
  104. void ossl_lib_ctx_default_deinit(void)
  105. {
  106. context_deinit(&default_context_int);
  107. }
  108. static OSSL_LIB_CTX *get_thread_default_context(void)
  109. {
  110. if (!RUN_ONCE(&default_context_init, default_context_do_init))
  111. return NULL;
  112. return CRYPTO_THREAD_get_local(&default_context_thread_local);
  113. }
  114. static OSSL_LIB_CTX *get_default_context(void)
  115. {
  116. OSSL_LIB_CTX *current_defctx = get_thread_default_context();
  117. if (current_defctx == NULL)
  118. current_defctx = &default_context_int;
  119. return current_defctx;
  120. }
  121. static int set_default_context(OSSL_LIB_CTX *defctx)
  122. {
  123. if (defctx == &default_context_int)
  124. defctx = NULL;
  125. return CRYPTO_THREAD_set_local(&default_context_thread_local, defctx);
  126. }
  127. #endif
  128. OSSL_LIB_CTX *OSSL_LIB_CTX_new(void)
  129. {
  130. OSSL_LIB_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
  131. if (ctx != NULL && !context_init(ctx)) {
  132. OSSL_LIB_CTX_free(ctx);
  133. ctx = NULL;
  134. }
  135. return ctx;
  136. }
  137. #ifndef FIPS_MODULE
  138. int OSSL_LIB_CTX_load_config(OSSL_LIB_CTX *ctx, const char *config_file)
  139. {
  140. return CONF_modules_load_file_ex(ctx, config_file, NULL, 0) > 0;
  141. }
  142. #endif
  143. void OSSL_LIB_CTX_free(OSSL_LIB_CTX *ctx)
  144. {
  145. if (ossl_lib_ctx_is_default(ctx))
  146. return;
  147. context_deinit(ctx);
  148. OPENSSL_free(ctx);
  149. }
  150. OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *libctx)
  151. {
  152. #ifndef FIPS_MODULE
  153. OSSL_LIB_CTX *current_defctx;
  154. if ((current_defctx = get_default_context()) != NULL
  155. && set_default_context(libctx))
  156. return current_defctx;
  157. #endif
  158. return NULL;
  159. }
  160. OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx)
  161. {
  162. #ifndef FIPS_MODULE
  163. if (ctx == NULL)
  164. return get_default_context();
  165. #endif
  166. return ctx;
  167. }
  168. int ossl_lib_ctx_is_default(OSSL_LIB_CTX *ctx)
  169. {
  170. #ifndef FIPS_MODULE
  171. if (ctx == NULL || ctx == get_default_context())
  172. return 1;
  173. #endif
  174. return 0;
  175. }
  176. int ossl_lib_ctx_is_global_default(OSSL_LIB_CTX *ctx)
  177. {
  178. #ifndef FIPS_MODULE
  179. if (ossl_lib_ctx_get_concrete(ctx) == &default_context_int)
  180. return 1;
  181. #endif
  182. return 0;
  183. }
  184. static void ossl_lib_ctx_generic_new(void *parent_ign, void *ptr_ign,
  185. CRYPTO_EX_DATA *ad, int index,
  186. long argl_ign, void *argp)
  187. {
  188. const OSSL_LIB_CTX_METHOD *meth = argp;
  189. void *ptr = meth->new_func(crypto_ex_data_get_ossl_lib_ctx(ad));
  190. if (ptr != NULL)
  191. CRYPTO_set_ex_data(ad, index, ptr);
  192. }
  193. static void ossl_lib_ctx_generic_free(void *parent_ign, void *ptr,
  194. CRYPTO_EX_DATA *ad, int index,
  195. long argl_ign, void *argp)
  196. {
  197. const OSSL_LIB_CTX_METHOD *meth = argp;
  198. meth->free_func(ptr);
  199. }
  200. /* Non-static so we can use it in context_internal_test */
  201. static int ossl_lib_ctx_init_index(OSSL_LIB_CTX *ctx, int static_index,
  202. const OSSL_LIB_CTX_METHOD *meth)
  203. {
  204. int idx;
  205. ctx = ossl_lib_ctx_get_concrete(ctx);
  206. if (ctx == NULL)
  207. return 0;
  208. idx = crypto_get_ex_new_index_ex(ctx, CRYPTO_EX_INDEX_OSSL_LIB_CTX, 0,
  209. (void *)meth,
  210. ossl_lib_ctx_generic_new,
  211. NULL, ossl_lib_ctx_generic_free);
  212. if (idx < 0)
  213. return 0;
  214. ctx->dyn_indexes[static_index] = idx;
  215. return 1;
  216. }
  217. void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index,
  218. const OSSL_LIB_CTX_METHOD *meth)
  219. {
  220. void *data = NULL;
  221. int dynidx;
  222. ctx = ossl_lib_ctx_get_concrete(ctx);
  223. if (ctx == NULL)
  224. return NULL;
  225. CRYPTO_THREAD_read_lock(ctx->lock);
  226. dynidx = ctx->dyn_indexes[index];
  227. CRYPTO_THREAD_unlock(ctx->lock);
  228. if (dynidx != -1) {
  229. CRYPTO_THREAD_read_lock(ctx->index_locks[index]);
  230. data = CRYPTO_get_ex_data(&ctx->data, dynidx);
  231. CRYPTO_THREAD_unlock(ctx->index_locks[index]);
  232. return data;
  233. }
  234. CRYPTO_THREAD_write_lock(ctx->index_locks[index]);
  235. CRYPTO_THREAD_write_lock(ctx->lock);
  236. dynidx = ctx->dyn_indexes[index];
  237. if (dynidx != -1) {
  238. CRYPTO_THREAD_unlock(ctx->lock);
  239. data = CRYPTO_get_ex_data(&ctx->data, dynidx);
  240. CRYPTO_THREAD_unlock(ctx->index_locks[index]);
  241. return data;
  242. }
  243. if (!ossl_lib_ctx_init_index(ctx, index, meth)) {
  244. CRYPTO_THREAD_unlock(ctx->lock);
  245. CRYPTO_THREAD_unlock(ctx->index_locks[index]);
  246. return NULL;
  247. }
  248. CRYPTO_THREAD_unlock(ctx->lock);
  249. /* The alloc call ensures there's a value there */
  250. if (CRYPTO_alloc_ex_data(CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL,
  251. &ctx->data, ctx->dyn_indexes[index]))
  252. data = CRYPTO_get_ex_data(&ctx->data, ctx->dyn_indexes[index]);
  253. CRYPTO_THREAD_unlock(ctx->index_locks[index]);
  254. return data;
  255. }
  256. OSSL_EX_DATA_GLOBAL *ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX *ctx)
  257. {
  258. ctx = ossl_lib_ctx_get_concrete(ctx);
  259. if (ctx == NULL)
  260. return NULL;
  261. return &ctx->global;
  262. }
  263. int ossl_lib_ctx_run_once(OSSL_LIB_CTX *ctx, unsigned int idx,
  264. ossl_lib_ctx_run_once_fn run_once_fn)
  265. {
  266. int done = 0, ret = 0;
  267. ctx = ossl_lib_ctx_get_concrete(ctx);
  268. if (ctx == NULL)
  269. return 0;
  270. CRYPTO_THREAD_read_lock(ctx->oncelock);
  271. done = ctx->run_once_done[idx];
  272. if (done)
  273. ret = ctx->run_once_ret[idx];
  274. CRYPTO_THREAD_unlock(ctx->oncelock);
  275. if (done)
  276. return ret;
  277. CRYPTO_THREAD_write_lock(ctx->oncelock);
  278. if (ctx->run_once_done[idx]) {
  279. ret = ctx->run_once_ret[idx];
  280. CRYPTO_THREAD_unlock(ctx->oncelock);
  281. return ret;
  282. }
  283. ret = run_once_fn(ctx);
  284. ctx->run_once_done[idx] = 1;
  285. ctx->run_once_ret[idx] = ret;
  286. CRYPTO_THREAD_unlock(ctx->oncelock);
  287. return ret;
  288. }
  289. int ossl_lib_ctx_onfree(OSSL_LIB_CTX *ctx, ossl_lib_ctx_onfree_fn onfreefn)
  290. {
  291. struct ossl_lib_ctx_onfree_list_st *newonfree
  292. = OPENSSL_malloc(sizeof(*newonfree));
  293. if (newonfree == NULL)
  294. return 0;
  295. newonfree->fn = onfreefn;
  296. newonfree->next = ctx->onfreelist;
  297. ctx->onfreelist = newonfree;
  298. return 1;
  299. }