ex_data.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /*
  2. * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the OpenSSL license (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 "internal/cryptlib_int.h"
  10. #include "internal/thread_once.h"
  11. #include <openssl/lhash.h>
  12. /*
  13. * Each structure type (sometimes called a class), that supports
  14. * exdata has a stack of callbacks for each instance.
  15. */
  16. struct ex_callback_st {
  17. long argl; /* Arbitrary long */
  18. void *argp; /* Arbitrary void * */
  19. CRYPTO_EX_new *new_func;
  20. CRYPTO_EX_free *free_func;
  21. CRYPTO_EX_dup *dup_func;
  22. };
  23. /*
  24. * The state for each class. This could just be a typedef, but
  25. * a structure allows future changes.
  26. */
  27. typedef struct ex_callbacks_st {
  28. STACK_OF(EX_CALLBACK) *meth;
  29. } EX_CALLBACKS;
  30. static EX_CALLBACKS ex_data[CRYPTO_EX_INDEX__COUNT];
  31. static CRYPTO_RWLOCK *ex_data_lock = NULL;
  32. static CRYPTO_ONCE ex_data_init = CRYPTO_ONCE_STATIC_INIT;
  33. DEFINE_RUN_ONCE_STATIC(do_ex_data_init)
  34. {
  35. OPENSSL_init_crypto(0, NULL);
  36. ex_data_lock = CRYPTO_THREAD_lock_new();
  37. return ex_data_lock != NULL;
  38. }
  39. /*
  40. * Return the EX_CALLBACKS from the |ex_data| array that corresponds to
  41. * a given class. On success, *holds the lock.*
  42. */
  43. static EX_CALLBACKS *get_and_lock(int class_index)
  44. {
  45. EX_CALLBACKS *ip;
  46. if (class_index < 0 || class_index >= CRYPTO_EX_INDEX__COUNT) {
  47. CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_PASSED_INVALID_ARGUMENT);
  48. return NULL;
  49. }
  50. if (!RUN_ONCE(&ex_data_init, do_ex_data_init)) {
  51. CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_MALLOC_FAILURE);
  52. return NULL;
  53. }
  54. if (ex_data_lock == NULL) {
  55. /*
  56. * This can happen in normal operation when using CRYPTO_mem_leaks().
  57. * The CRYPTO_mem_leaks() function calls OPENSSL_cleanup() which cleans
  58. * up the locks. Subsequently the BIO that CRYPTO_mem_leaks() uses gets
  59. * freed, which also attempts to free the ex_data. However
  60. * CRYPTO_mem_leaks() ensures that the ex_data is freed early (i.e.
  61. * before OPENSSL_cleanup() is called), so if we get here we can safely
  62. * ignore this operation. We just treat it as an error.
  63. */
  64. return NULL;
  65. }
  66. ip = &ex_data[class_index];
  67. CRYPTO_THREAD_write_lock(ex_data_lock);
  68. return ip;
  69. }
  70. static void cleanup_cb(EX_CALLBACK *funcs)
  71. {
  72. OPENSSL_free(funcs);
  73. }
  74. /*
  75. * Release all "ex_data" state to prevent memory leaks. This can't be made
  76. * thread-safe without overhauling a lot of stuff, and shouldn't really be
  77. * called under potential race-conditions anyway (it's for program shutdown
  78. * after all).
  79. */
  80. void crypto_cleanup_all_ex_data_int(void)
  81. {
  82. int i;
  83. for (i = 0; i < CRYPTO_EX_INDEX__COUNT; ++i) {
  84. EX_CALLBACKS *ip = &ex_data[i];
  85. sk_EX_CALLBACK_pop_free(ip->meth, cleanup_cb);
  86. ip->meth = NULL;
  87. }
  88. CRYPTO_THREAD_lock_free(ex_data_lock);
  89. ex_data_lock = NULL;
  90. }
  91. /*
  92. * Unregister a new index by replacing the callbacks with no-ops.
  93. * Any in-use instances are leaked.
  94. */
  95. static void dummy_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
  96. long argl, void *argp)
  97. {
  98. }
  99. static void dummy_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
  100. long argl, void *argp)
  101. {
  102. }
  103. static int dummy_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
  104. void *from_d, int idx,
  105. long argl, void *argp)
  106. {
  107. return 1;
  108. }
  109. int CRYPTO_free_ex_index(int class_index, int idx)
  110. {
  111. EX_CALLBACKS *ip = get_and_lock(class_index);
  112. EX_CALLBACK *a;
  113. int toret = 0;
  114. if (ip == NULL)
  115. return 0;
  116. if (idx < 0 || idx >= sk_EX_CALLBACK_num(ip->meth))
  117. goto err;
  118. a = sk_EX_CALLBACK_value(ip->meth, idx);
  119. if (a == NULL)
  120. goto err;
  121. a->new_func = dummy_new;
  122. a->dup_func = dummy_dup;
  123. a->free_func = dummy_free;
  124. toret = 1;
  125. err:
  126. CRYPTO_THREAD_unlock(ex_data_lock);
  127. return toret;
  128. }
  129. /*
  130. * Register a new index.
  131. */
  132. int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
  133. CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
  134. CRYPTO_EX_free *free_func)
  135. {
  136. int toret = -1;
  137. EX_CALLBACK *a;
  138. EX_CALLBACKS *ip = get_and_lock(class_index);
  139. if (ip == NULL)
  140. return -1;
  141. if (ip->meth == NULL) {
  142. ip->meth = sk_EX_CALLBACK_new_null();
  143. /* We push an initial value on the stack because the SSL
  144. * "app_data" routines use ex_data index zero. See RT 3710. */
  145. if (ip->meth == NULL
  146. || !sk_EX_CALLBACK_push(ip->meth, NULL)) {
  147. CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE);
  148. goto err;
  149. }
  150. }
  151. a = (EX_CALLBACK *)OPENSSL_malloc(sizeof(*a));
  152. if (a == NULL) {
  153. CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE);
  154. goto err;
  155. }
  156. a->argl = argl;
  157. a->argp = argp;
  158. a->new_func = new_func;
  159. a->dup_func = dup_func;
  160. a->free_func = free_func;
  161. if (!sk_EX_CALLBACK_push(ip->meth, NULL)) {
  162. CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE);
  163. OPENSSL_free(a);
  164. goto err;
  165. }
  166. toret = sk_EX_CALLBACK_num(ip->meth) - 1;
  167. (void)sk_EX_CALLBACK_set(ip->meth, toret, a);
  168. err:
  169. CRYPTO_THREAD_unlock(ex_data_lock);
  170. return toret;
  171. }
  172. /*
  173. * Initialise a new CRYPTO_EX_DATA for use in a particular class - including
  174. * calling new() callbacks for each index in the class used by this variable
  175. * Thread-safe by copying a class's array of "EX_CALLBACK" entries
  176. * in the lock, then using them outside the lock. Note this only applies
  177. * to the global "ex_data" state (ie. class definitions), not 'ad' itself.
  178. */
  179. int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
  180. {
  181. int mx, i;
  182. void *ptr;
  183. EX_CALLBACK **storage = NULL;
  184. EX_CALLBACK *stack[10];
  185. EX_CALLBACKS *ip = get_and_lock(class_index);
  186. if (ip == NULL)
  187. return 0;
  188. ad->sk = NULL;
  189. mx = sk_EX_CALLBACK_num(ip->meth);
  190. if (mx > 0) {
  191. if (mx < (int)OSSL_NELEM(stack))
  192. storage = stack;
  193. else
  194. storage = OPENSSL_malloc(sizeof(*storage) * mx);
  195. if (storage != NULL)
  196. for (i = 0; i < mx; i++)
  197. storage[i] = sk_EX_CALLBACK_value(ip->meth, i);
  198. }
  199. CRYPTO_THREAD_unlock(ex_data_lock);
  200. if (mx > 0 && storage == NULL) {
  201. CRYPTOerr(CRYPTO_F_CRYPTO_NEW_EX_DATA, ERR_R_MALLOC_FAILURE);
  202. return 0;
  203. }
  204. for (i = 0; i < mx; i++) {
  205. if (storage[i] && storage[i]->new_func) {
  206. ptr = CRYPTO_get_ex_data(ad, i);
  207. storage[i]->new_func(obj, ptr, ad, i,
  208. storage[i]->argl, storage[i]->argp);
  209. }
  210. }
  211. if (storage != stack)
  212. OPENSSL_free(storage);
  213. return 1;
  214. }
  215. /*
  216. * Duplicate a CRYPTO_EX_DATA variable - including calling dup() callbacks
  217. * for each index in the class used by this variable
  218. */
  219. int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
  220. const CRYPTO_EX_DATA *from)
  221. {
  222. int mx, j, i;
  223. void *ptr;
  224. EX_CALLBACK *stack[10];
  225. EX_CALLBACK **storage = NULL;
  226. EX_CALLBACKS *ip;
  227. int toret = 0;
  228. if (from->sk == NULL)
  229. /* Nothing to copy over */
  230. return 1;
  231. if ((ip = get_and_lock(class_index)) == NULL)
  232. return 0;
  233. mx = sk_EX_CALLBACK_num(ip->meth);
  234. j = sk_void_num(from->sk);
  235. if (j < mx)
  236. mx = j;
  237. if (mx > 0) {
  238. if (mx < (int)OSSL_NELEM(stack))
  239. storage = stack;
  240. else
  241. storage = OPENSSL_malloc(sizeof(*storage) * mx);
  242. if (storage != NULL)
  243. for (i = 0; i < mx; i++)
  244. storage[i] = sk_EX_CALLBACK_value(ip->meth, i);
  245. }
  246. CRYPTO_THREAD_unlock(ex_data_lock);
  247. if (mx == 0)
  248. return 1;
  249. if (storage == NULL) {
  250. CRYPTOerr(CRYPTO_F_CRYPTO_DUP_EX_DATA, ERR_R_MALLOC_FAILURE);
  251. return 0;
  252. }
  253. if (!CRYPTO_set_ex_data(to, mx - 1, NULL))
  254. goto err;
  255. for (i = 0; i < mx; i++) {
  256. ptr = CRYPTO_get_ex_data(from, i);
  257. if (storage[i] && storage[i]->dup_func)
  258. if (!storage[i]->dup_func(to, from, &ptr, i,
  259. storage[i]->argl, storage[i]->argp))
  260. goto err;
  261. CRYPTO_set_ex_data(to, i, ptr);
  262. }
  263. toret = 1;
  264. err:
  265. if (storage != stack)
  266. OPENSSL_free(storage);
  267. return toret;
  268. }
  269. /*
  270. * Cleanup a CRYPTO_EX_DATA variable - including calling free() callbacks for
  271. * each index in the class used by this variable
  272. */
  273. void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
  274. {
  275. int mx, i;
  276. EX_CALLBACKS *ip;
  277. void *ptr;
  278. EX_CALLBACK *f;
  279. EX_CALLBACK *stack[10];
  280. EX_CALLBACK **storage = NULL;
  281. if ((ip = get_and_lock(class_index)) == NULL)
  282. goto err;
  283. mx = sk_EX_CALLBACK_num(ip->meth);
  284. if (mx > 0) {
  285. if (mx < (int)OSSL_NELEM(stack))
  286. storage = stack;
  287. else
  288. storage = OPENSSL_malloc(sizeof(*storage) * mx);
  289. if (storage != NULL)
  290. for (i = 0; i < mx; i++)
  291. storage[i] = sk_EX_CALLBACK_value(ip->meth, i);
  292. }
  293. CRYPTO_THREAD_unlock(ex_data_lock);
  294. for (i = 0; i < mx; i++) {
  295. if (storage != NULL)
  296. f = storage[i];
  297. else {
  298. CRYPTO_THREAD_write_lock(ex_data_lock);
  299. f = sk_EX_CALLBACK_value(ip->meth, i);
  300. CRYPTO_THREAD_unlock(ex_data_lock);
  301. }
  302. if (f != NULL && f->free_func != NULL) {
  303. ptr = CRYPTO_get_ex_data(ad, i);
  304. f->free_func(obj, ptr, ad, i, f->argl, f->argp);
  305. }
  306. }
  307. if (storage != stack)
  308. OPENSSL_free(storage);
  309. err:
  310. sk_void_free(ad->sk);
  311. ad->sk = NULL;
  312. }
  313. /*
  314. * For a given CRYPTO_EX_DATA variable, set the value corresponding to a
  315. * particular index in the class used by this variable
  316. */
  317. int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val)
  318. {
  319. int i;
  320. if (ad->sk == NULL) {
  321. if ((ad->sk = sk_void_new_null()) == NULL) {
  322. CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA, ERR_R_MALLOC_FAILURE);
  323. return 0;
  324. }
  325. }
  326. for (i = sk_void_num(ad->sk); i <= idx; ++i) {
  327. if (!sk_void_push(ad->sk, NULL)) {
  328. CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA, ERR_R_MALLOC_FAILURE);
  329. return 0;
  330. }
  331. }
  332. sk_void_set(ad->sk, idx, val);
  333. return 1;
  334. }
  335. /*
  336. * For a given CRYPTO_EX_DATA_ variable, get the value corresponding to a
  337. * particular index in the class used by this variable
  338. */
  339. void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx)
  340. {
  341. if (ad->sk == NULL || idx >= sk_void_num(ad->sk))
  342. return NULL;
  343. return sk_void_value(ad->sk, idx);
  344. }