2
0

ex_data.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. * Copyright 1995-2020 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 "crypto/cryptlib.h"
  10. #include "internal/thread_once.h"
  11. /*
  12. * Each structure type (sometimes called a class), that supports
  13. * exdata has a stack of callbacks for each instance.
  14. */
  15. struct ex_callback_st {
  16. long argl; /* Arbitrary long */
  17. void *argp; /* Arbitrary void * */
  18. CRYPTO_EX_new *new_func;
  19. CRYPTO_EX_free *free_func;
  20. CRYPTO_EX_dup *dup_func;
  21. };
  22. /*
  23. * The state for each class. This could just be a typedef, but
  24. * a structure allows future changes.
  25. */
  26. typedef struct ex_callbacks_st {
  27. STACK_OF(EX_CALLBACK) *meth;
  28. } EX_CALLBACKS;
  29. static EX_CALLBACKS ex_data[CRYPTO_EX_INDEX__COUNT];
  30. static CRYPTO_RWLOCK *ex_data_lock = NULL;
  31. static CRYPTO_ONCE ex_data_init = CRYPTO_ONCE_STATIC_INIT;
  32. DEFINE_RUN_ONCE_STATIC(do_ex_data_init)
  33. {
  34. if (!OPENSSL_init_crypto(0, NULL))
  35. return 0;
  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] != NULL && storage[i]->new_func != NULL) {
  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. /*
  254. * Make sure the ex_data stack is at least |mx| elements long to avoid
  255. * issues in the for loop that follows; so go get the |mx|'th element
  256. * (if it does not exist CRYPTO_get_ex_data() returns NULL), and assign
  257. * to itself. This is normally a no-op; but ensures the stack is the
  258. * proper size
  259. */
  260. if (!CRYPTO_set_ex_data(to, mx - 1, CRYPTO_get_ex_data(to, mx - 1)))
  261. goto err;
  262. for (i = 0; i < mx; i++) {
  263. ptr = CRYPTO_get_ex_data(from, i);
  264. if (storage[i] != NULL && storage[i]->dup_func != NULL)
  265. if (!storage[i]->dup_func(to, from, &ptr, i,
  266. storage[i]->argl, storage[i]->argp))
  267. goto err;
  268. CRYPTO_set_ex_data(to, i, ptr);
  269. }
  270. toret = 1;
  271. err:
  272. if (storage != stack)
  273. OPENSSL_free(storage);
  274. return toret;
  275. }
  276. /*
  277. * Cleanup a CRYPTO_EX_DATA variable - including calling free() callbacks for
  278. * each index in the class used by this variable
  279. */
  280. void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
  281. {
  282. int mx, i;
  283. EX_CALLBACKS *ip;
  284. void *ptr;
  285. EX_CALLBACK *f;
  286. EX_CALLBACK *stack[10];
  287. EX_CALLBACK **storage = NULL;
  288. if ((ip = get_and_lock(class_index)) == NULL)
  289. goto err;
  290. mx = sk_EX_CALLBACK_num(ip->meth);
  291. if (mx > 0) {
  292. if (mx < (int)OSSL_NELEM(stack))
  293. storage = stack;
  294. else
  295. storage = OPENSSL_malloc(sizeof(*storage) * mx);
  296. if (storage != NULL)
  297. for (i = 0; i < mx; i++)
  298. storage[i] = sk_EX_CALLBACK_value(ip->meth, i);
  299. }
  300. CRYPTO_THREAD_unlock(ex_data_lock);
  301. for (i = 0; i < mx; i++) {
  302. if (storage != NULL)
  303. f = storage[i];
  304. else {
  305. CRYPTO_THREAD_write_lock(ex_data_lock);
  306. f = sk_EX_CALLBACK_value(ip->meth, i);
  307. CRYPTO_THREAD_unlock(ex_data_lock);
  308. }
  309. if (f != NULL && f->free_func != NULL) {
  310. ptr = CRYPTO_get_ex_data(ad, i);
  311. f->free_func(obj, ptr, ad, i, f->argl, f->argp);
  312. }
  313. }
  314. if (storage != stack)
  315. OPENSSL_free(storage);
  316. err:
  317. sk_void_free(ad->sk);
  318. ad->sk = NULL;
  319. }
  320. /*
  321. * For a given CRYPTO_EX_DATA variable, set the value corresponding to a
  322. * particular index in the class used by this variable
  323. */
  324. int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val)
  325. {
  326. int i;
  327. if (ad->sk == NULL) {
  328. if ((ad->sk = sk_void_new_null()) == NULL) {
  329. CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA, ERR_R_MALLOC_FAILURE);
  330. return 0;
  331. }
  332. }
  333. for (i = sk_void_num(ad->sk); i <= idx; ++i) {
  334. if (!sk_void_push(ad->sk, NULL)) {
  335. CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA, ERR_R_MALLOC_FAILURE);
  336. return 0;
  337. }
  338. }
  339. sk_void_set(ad->sk, idx, val);
  340. return 1;
  341. }
  342. /*
  343. * For a given CRYPTO_EX_DATA_ variable, get the value corresponding to a
  344. * particular index in the class used by this variable
  345. */
  346. void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx)
  347. {
  348. if (ad->sk == NULL || idx >= sk_void_num(ad->sk))
  349. return NULL;
  350. return sk_void_value(ad->sk, idx);
  351. }