context.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. * Copyright 2019 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 "internal/thread_once.h"
  11. #include "internal/property.h"
  12. struct openssl_ctx_onfree_list_st {
  13. openssl_ctx_onfree_fn *fn;
  14. struct openssl_ctx_onfree_list_st *next;
  15. };
  16. struct openssl_ctx_st {
  17. CRYPTO_RWLOCK *lock;
  18. CRYPTO_EX_DATA data;
  19. /*
  20. * For most data in the OPENSSL_CTX we just use ex_data to store it. But
  21. * that doesn't work for ex_data itself - so we store that directly.
  22. */
  23. OSSL_EX_DATA_GLOBAL global;
  24. /* Map internal static indexes to dynamically created indexes */
  25. int dyn_indexes[OPENSSL_CTX_MAX_INDEXES];
  26. /* Keep a separate lock for each index */
  27. CRYPTO_RWLOCK *index_locks[OPENSSL_CTX_MAX_INDEXES];
  28. CRYPTO_RWLOCK *oncelock;
  29. int run_once_done[OPENSSL_CTX_MAX_RUN_ONCE];
  30. int run_once_ret[OPENSSL_CTX_MAX_RUN_ONCE];
  31. struct openssl_ctx_onfree_list_st *onfreelist;
  32. };
  33. #ifndef FIPS_MODE
  34. static OPENSSL_CTX default_context_int;
  35. /* Always points at default_context_int if it has been initialised */
  36. static OPENSSL_CTX *default_context = NULL;
  37. #endif
  38. static int context_init(OPENSSL_CTX *ctx)
  39. {
  40. size_t i;
  41. int exdata_done = 0;
  42. ctx->lock = CRYPTO_THREAD_lock_new();
  43. if (ctx->lock == NULL)
  44. return 0;
  45. ctx->oncelock = CRYPTO_THREAD_lock_new();
  46. if (ctx->oncelock == NULL)
  47. goto err;
  48. for (i = 0; i < OPENSSL_CTX_MAX_INDEXES; i++) {
  49. ctx->index_locks[i] = CRYPTO_THREAD_lock_new();
  50. ctx->dyn_indexes[i] = -1;
  51. if (ctx->index_locks[i] == NULL)
  52. goto err;
  53. }
  54. /* OPENSSL_CTX is built on top of ex_data so we initialise that directly */
  55. if (!do_ex_data_init(ctx))
  56. goto err;
  57. exdata_done = 1;
  58. if (!crypto_new_ex_data_ex(ctx, CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,
  59. &ctx->data)) {
  60. crypto_cleanup_all_ex_data_int(ctx);
  61. goto err;
  62. }
  63. /* Everything depends on properties, so we also pre-initialise that */
  64. if (!ossl_property_parse_init(ctx))
  65. goto err;
  66. return 1;
  67. err:
  68. if (exdata_done)
  69. crypto_cleanup_all_ex_data_int(ctx);
  70. CRYPTO_THREAD_lock_free(ctx->oncelock);
  71. CRYPTO_THREAD_lock_free(ctx->lock);
  72. ctx->lock = NULL;
  73. return 0;
  74. }
  75. static int context_deinit(OPENSSL_CTX *ctx)
  76. {
  77. struct openssl_ctx_onfree_list_st *tmp, *onfree;
  78. int i;
  79. if (ctx == NULL)
  80. return 1;
  81. ossl_ctx_thread_stop(ctx);
  82. onfree = ctx->onfreelist;
  83. while (onfree != NULL) {
  84. onfree->fn(ctx);
  85. tmp = onfree;
  86. onfree = onfree->next;
  87. OPENSSL_free(tmp);
  88. }
  89. CRYPTO_free_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL, &ctx->data);
  90. crypto_cleanup_all_ex_data_int(ctx);
  91. for (i = 0; i < OPENSSL_CTX_MAX_INDEXES; i++)
  92. CRYPTO_THREAD_lock_free(ctx->index_locks[i]);
  93. CRYPTO_THREAD_lock_free(ctx->oncelock);
  94. CRYPTO_THREAD_lock_free(ctx->lock);
  95. ctx->lock = NULL;
  96. return 1;
  97. }
  98. #ifndef FIPS_MODE
  99. void openssl_ctx_default_deinit(void)
  100. {
  101. context_deinit(default_context);
  102. }
  103. static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT;
  104. DEFINE_RUN_ONCE_STATIC(do_default_context_init)
  105. {
  106. if (context_init(&default_context_int))
  107. default_context = &default_context_int;
  108. return 1;
  109. }
  110. #endif
  111. OPENSSL_CTX *OPENSSL_CTX_new(void)
  112. {
  113. OPENSSL_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
  114. if (ctx != NULL && !context_init(ctx)) {
  115. OPENSSL_CTX_free(ctx);
  116. ctx = NULL;
  117. }
  118. return ctx;
  119. }
  120. void OPENSSL_CTX_free(OPENSSL_CTX *ctx)
  121. {
  122. if (ctx != NULL)
  123. context_deinit(ctx);
  124. OPENSSL_free(ctx);
  125. }
  126. OPENSSL_CTX *openssl_ctx_get_concrete(OPENSSL_CTX *ctx)
  127. {
  128. #ifndef FIPS_MODE
  129. if (ctx == NULL) {
  130. if (!RUN_ONCE(&default_context_init, do_default_context_init))
  131. return 0;
  132. return default_context;
  133. }
  134. #endif
  135. return ctx;
  136. }
  137. static void openssl_ctx_generic_new(void *parent_ign, void *ptr_ign,
  138. CRYPTO_EX_DATA *ad, int index,
  139. long argl_ign, void *argp)
  140. {
  141. const OPENSSL_CTX_METHOD *meth = argp;
  142. void *ptr = meth->new_func(crypto_ex_data_get_openssl_ctx(ad));
  143. if (ptr != NULL)
  144. CRYPTO_set_ex_data(ad, index, ptr);
  145. }
  146. static void openssl_ctx_generic_free(void *parent_ign, void *ptr,
  147. CRYPTO_EX_DATA *ad, int index,
  148. long argl_ign, void *argp)
  149. {
  150. const OPENSSL_CTX_METHOD *meth = argp;
  151. meth->free_func(ptr);
  152. }
  153. /* Non-static so we can use it in context_internal_test */
  154. static int openssl_ctx_init_index(OPENSSL_CTX *ctx, int static_index,
  155. const OPENSSL_CTX_METHOD *meth)
  156. {
  157. int idx;
  158. ctx = openssl_ctx_get_concrete(ctx);
  159. if (ctx == NULL)
  160. return 0;
  161. idx = crypto_get_ex_new_index_ex(ctx, CRYPTO_EX_INDEX_OPENSSL_CTX, 0,
  162. (void *)meth,
  163. openssl_ctx_generic_new,
  164. NULL, openssl_ctx_generic_free);
  165. if (idx < 0)
  166. return 0;
  167. ctx->dyn_indexes[static_index] = idx;
  168. return 1;
  169. }
  170. void *openssl_ctx_get_data(OPENSSL_CTX *ctx, int index,
  171. const OPENSSL_CTX_METHOD *meth)
  172. {
  173. void *data = NULL;
  174. int dynidx;
  175. ctx = openssl_ctx_get_concrete(ctx);
  176. if (ctx == NULL)
  177. return NULL;
  178. CRYPTO_THREAD_read_lock(ctx->lock);
  179. dynidx = ctx->dyn_indexes[index];
  180. CRYPTO_THREAD_unlock(ctx->lock);
  181. if (dynidx != -1) {
  182. CRYPTO_THREAD_read_lock(ctx->index_locks[index]);
  183. data = CRYPTO_get_ex_data(&ctx->data, dynidx);
  184. CRYPTO_THREAD_unlock(ctx->index_locks[index]);
  185. return data;
  186. }
  187. CRYPTO_THREAD_write_lock(ctx->index_locks[index]);
  188. CRYPTO_THREAD_write_lock(ctx->lock);
  189. dynidx = ctx->dyn_indexes[index];
  190. if (dynidx != -1) {
  191. CRYPTO_THREAD_unlock(ctx->lock);
  192. data = CRYPTO_get_ex_data(&ctx->data, dynidx);
  193. CRYPTO_THREAD_unlock(ctx->index_locks[index]);
  194. return data;
  195. }
  196. if (!openssl_ctx_init_index(ctx, index, meth)) {
  197. CRYPTO_THREAD_unlock(ctx->lock);
  198. CRYPTO_THREAD_unlock(ctx->index_locks[index]);
  199. return NULL;
  200. }
  201. CRYPTO_THREAD_unlock(ctx->lock);
  202. /* The alloc call ensures there's a value there */
  203. if (CRYPTO_alloc_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,
  204. &ctx->data, ctx->dyn_indexes[index]))
  205. data = CRYPTO_get_ex_data(&ctx->data, ctx->dyn_indexes[index]);
  206. CRYPTO_THREAD_unlock(ctx->index_locks[index]);
  207. return data;
  208. }
  209. OSSL_EX_DATA_GLOBAL *openssl_ctx_get_ex_data_global(OPENSSL_CTX *ctx)
  210. {
  211. ctx = openssl_ctx_get_concrete(ctx);
  212. if (ctx == NULL)
  213. return NULL;
  214. return &ctx->global;
  215. }
  216. int openssl_ctx_run_once(OPENSSL_CTX *ctx, unsigned int idx,
  217. openssl_ctx_run_once_fn run_once_fn)
  218. {
  219. int done = 0, ret = 0;
  220. ctx = openssl_ctx_get_concrete(ctx);
  221. if (ctx == NULL)
  222. return 0;
  223. CRYPTO_THREAD_read_lock(ctx->oncelock);
  224. done = ctx->run_once_done[idx];
  225. if (done)
  226. ret = ctx->run_once_ret[idx];
  227. CRYPTO_THREAD_unlock(ctx->oncelock);
  228. if (done)
  229. return ret;
  230. CRYPTO_THREAD_write_lock(ctx->oncelock);
  231. if (ctx->run_once_done[idx]) {
  232. ret = ctx->run_once_ret[idx];
  233. CRYPTO_THREAD_unlock(ctx->oncelock);
  234. return ret;
  235. }
  236. ret = run_once_fn(ctx);
  237. ctx->run_once_done[idx] = 1;
  238. ctx->run_once_ret[idx] = ret;
  239. CRYPTO_THREAD_unlock(ctx->oncelock);
  240. return ret;
  241. }
  242. int openssl_ctx_onfree(OPENSSL_CTX *ctx, openssl_ctx_onfree_fn onfreefn)
  243. {
  244. struct openssl_ctx_onfree_list_st *newonfree
  245. = OPENSSL_malloc(sizeof(*newonfree));
  246. if (newonfree == NULL)
  247. return 0;
  248. newonfree->fn = onfreefn;
  249. newonfree->next = ctx->onfreelist;
  250. ctx->onfreelist = newonfree;
  251. return 1;
  252. }