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