2 * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
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
10 #include "internal/cryptlib_int.h"
11 #include "internal/thread_once.h"
14 * Each structure type (sometimes called a class), that supports
15 * exdata has a stack of callbacks for each instance.
17 struct ex_callback_st
{
18 long argl
; /* Arbitrary long */
19 void *argp
; /* Arbitrary void * */
20 CRYPTO_EX_new
*new_func
;
21 CRYPTO_EX_free
*free_func
;
22 CRYPTO_EX_dup
*dup_func
;
26 * The state for each class. This could just be a typedef, but
27 * a structure allows future changes.
29 typedef struct ex_callbacks_st
{
30 STACK_OF(EX_CALLBACK
) *meth
;
33 static EX_CALLBACKS ex_data
[CRYPTO_EX_INDEX__COUNT
];
35 static CRYPTO_RWLOCK
*ex_data_lock
= NULL
;
36 static CRYPTO_ONCE ex_data_init
= CRYPTO_ONCE_STATIC_INIT
;
38 DEFINE_RUN_ONCE_STATIC(do_ex_data_init
)
40 OPENSSL_init_crypto(0, NULL
);
41 ex_data_lock
= CRYPTO_THREAD_lock_new();
42 return ex_data_lock
!= NULL
;
46 * Return the EX_CALLBACKS from the |ex_data| array that corresponds to
47 * a given class. On success, *holds the lock.*
49 static EX_CALLBACKS
*get_and_lock(int class_index
)
53 if (class_index
< 0 || class_index
>= CRYPTO_EX_INDEX__COUNT
) {
54 CRYPTOerr(CRYPTO_F_GET_AND_LOCK
, ERR_R_PASSED_INVALID_ARGUMENT
);
58 if (!RUN_ONCE(&ex_data_init
, do_ex_data_init
)) {
59 CRYPTOerr(CRYPTO_F_GET_AND_LOCK
, ERR_R_MALLOC_FAILURE
);
63 if (ex_data_lock
== NULL
) {
65 * This can happen in normal operation when using CRYPTO_mem_leaks().
66 * The CRYPTO_mem_leaks() function calls OPENSSL_cleanup() which cleans
67 * up the locks. Subsequently the BIO that CRYPTO_mem_leaks() uses gets
68 * freed, which also attempts to free the ex_data. However
69 * CRYPTO_mem_leaks() ensures that the ex_data is freed early (i.e.
70 * before OPENSSL_cleanup() is called), so if we get here we can safely
71 * ignore this operation. We just treat it as an error.
76 ip
= &ex_data
[class_index
];
77 CRYPTO_THREAD_write_lock(ex_data_lock
);
81 static void cleanup_cb(EX_CALLBACK
*funcs
)
87 * Release all "ex_data" state to prevent memory leaks. This can't be made
88 * thread-safe without overhauling a lot of stuff, and shouldn't really be
89 * called under potential race-conditions anyway (it's for program shutdown
92 void crypto_cleanup_all_ex_data_int(void)
96 for (i
= 0; i
< CRYPTO_EX_INDEX__COUNT
; ++i
) {
97 EX_CALLBACKS
*ip
= &ex_data
[i
];
99 sk_EX_CALLBACK_pop_free(ip
->meth
, cleanup_cb
);
103 CRYPTO_THREAD_lock_free(ex_data_lock
);
109 * Unregister a new index by replacing the callbacks with no-ops.
110 * Any in-use instances are leaked.
112 static void dummy_new(void *parent
, void *ptr
, CRYPTO_EX_DATA
*ad
, int idx
,
113 long argl
, void *argp
)
117 static void dummy_free(void *parent
, void *ptr
, CRYPTO_EX_DATA
*ad
, int idx
,
118 long argl
, void *argp
)
122 static int dummy_dup(CRYPTO_EX_DATA
*to
, const CRYPTO_EX_DATA
*from
,
123 void *from_d
, int idx
,
124 long argl
, void *argp
)
129 int CRYPTO_free_ex_index(int class_index
, int idx
)
131 EX_CALLBACKS
*ip
= get_and_lock(class_index
);
137 if (idx
< 0 || idx
>= sk_EX_CALLBACK_num(ip
->meth
))
139 a
= sk_EX_CALLBACK_value(ip
->meth
, idx
);
142 a
->new_func
= dummy_new
;
143 a
->dup_func
= dummy_dup
;
144 a
->free_func
= dummy_free
;
147 CRYPTO_THREAD_unlock(ex_data_lock
);
152 * Register a new index.
154 int CRYPTO_get_ex_new_index(int class_index
, long argl
, void *argp
,
155 CRYPTO_EX_new
*new_func
, CRYPTO_EX_dup
*dup_func
,
156 CRYPTO_EX_free
*free_func
)
160 EX_CALLBACKS
*ip
= get_and_lock(class_index
);
165 if (ip
->meth
== NULL
) {
166 ip
->meth
= sk_EX_CALLBACK_new_null();
167 /* We push an initial value on the stack because the SSL
168 * "app_data" routines use ex_data index zero. See RT 3710. */
170 || !sk_EX_CALLBACK_push(ip
->meth
, NULL
)) {
171 CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX
, ERR_R_MALLOC_FAILURE
);
176 a
= (EX_CALLBACK
*)OPENSSL_malloc(sizeof(*a
));
178 CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX
, ERR_R_MALLOC_FAILURE
);
183 a
->new_func
= new_func
;
184 a
->dup_func
= dup_func
;
185 a
->free_func
= free_func
;
187 if (!sk_EX_CALLBACK_push(ip
->meth
, NULL
)) {
188 CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX
, ERR_R_MALLOC_FAILURE
);
192 toret
= sk_EX_CALLBACK_num(ip
->meth
) - 1;
193 (void)sk_EX_CALLBACK_set(ip
->meth
, toret
, a
);
196 CRYPTO_THREAD_unlock(ex_data_lock
);
201 * Initialise a new CRYPTO_EX_DATA for use in a particular class - including
202 * calling new() callbacks for each index in the class used by this variable
203 * Thread-safe by copying a class's array of "EX_CALLBACK" entries
204 * in the lock, then using them outside the lock. Note this only applies
205 * to the global "ex_data" state (ie. class definitions), not 'ad' itself.
207 int CRYPTO_new_ex_data(int class_index
, void *obj
, CRYPTO_EX_DATA
*ad
)
211 EX_CALLBACK
**storage
= NULL
;
212 EX_CALLBACK
*stack
[10];
213 EX_CALLBACKS
*ip
= get_and_lock(class_index
);
220 mx
= sk_EX_CALLBACK_num(ip
->meth
);
222 if (mx
< (int)OSSL_NELEM(stack
))
225 storage
= OPENSSL_malloc(sizeof(*storage
) * mx
);
227 for (i
= 0; i
< mx
; i
++)
228 storage
[i
] = sk_EX_CALLBACK_value(ip
->meth
, i
);
230 CRYPTO_THREAD_unlock(ex_data_lock
);
232 if (mx
> 0 && storage
== NULL
) {
233 CRYPTOerr(CRYPTO_F_CRYPTO_NEW_EX_DATA
, ERR_R_MALLOC_FAILURE
);
236 for (i
= 0; i
< mx
; i
++) {
237 if (storage
[i
] && storage
[i
]->new_func
) {
238 ptr
= CRYPTO_get_ex_data(ad
, i
);
239 storage
[i
]->new_func(obj
, ptr
, ad
, i
,
240 storage
[i
]->argl
, storage
[i
]->argp
);
243 if (storage
!= stack
)
244 OPENSSL_free(storage
);
249 * Duplicate a CRYPTO_EX_DATA variable - including calling dup() callbacks
250 * for each index in the class used by this variable
252 int CRYPTO_dup_ex_data(int class_index
, CRYPTO_EX_DATA
*to
,
253 const CRYPTO_EX_DATA
*from
)
257 EX_CALLBACK
*stack
[10];
258 EX_CALLBACK
**storage
= NULL
;
262 if (from
->sk
== NULL
)
263 /* Nothing to copy over */
265 if ((ip
= get_and_lock(class_index
)) == NULL
)
268 mx
= sk_EX_CALLBACK_num(ip
->meth
);
269 j
= sk_void_num(from
->sk
);
273 if (mx
< (int)OSSL_NELEM(stack
))
276 storage
= OPENSSL_malloc(sizeof(*storage
) * mx
);
278 for (i
= 0; i
< mx
; i
++)
279 storage
[i
] = sk_EX_CALLBACK_value(ip
->meth
, i
);
281 CRYPTO_THREAD_unlock(ex_data_lock
);
285 if (storage
== NULL
) {
286 CRYPTOerr(CRYPTO_F_CRYPTO_DUP_EX_DATA
, ERR_R_MALLOC_FAILURE
);
290 * Make sure the ex_data stack is at least |mx| elements long to avoid
291 * issues in the for loop that follows; so go get the |mx|'th element
292 * (if it does not exist CRYPTO_get_ex_data() returns NULL), and assign
293 * to itself. This is normally a no-op; but ensures the stack is the
296 if (!CRYPTO_set_ex_data(to
, mx
- 1, CRYPTO_get_ex_data(to
, mx
- 1)))
299 for (i
= 0; i
< mx
; i
++) {
300 ptr
= CRYPTO_get_ex_data(from
, i
);
301 if (storage
[i
] && storage
[i
]->dup_func
)
302 if (!storage
[i
]->dup_func(to
, from
, &ptr
, i
,
303 storage
[i
]->argl
, storage
[i
]->argp
))
305 CRYPTO_set_ex_data(to
, i
, ptr
);
309 if (storage
!= stack
)
310 OPENSSL_free(storage
);
316 * Cleanup a CRYPTO_EX_DATA variable - including calling free() callbacks for
317 * each index in the class used by this variable
319 void CRYPTO_free_ex_data(int class_index
, void *obj
, CRYPTO_EX_DATA
*ad
)
325 EX_CALLBACK
*stack
[10];
326 EX_CALLBACK
**storage
= NULL
;
328 if ((ip
= get_and_lock(class_index
)) == NULL
)
331 mx
= sk_EX_CALLBACK_num(ip
->meth
);
333 if (mx
< (int)OSSL_NELEM(stack
))
336 storage
= OPENSSL_malloc(sizeof(*storage
) * mx
);
338 for (i
= 0; i
< mx
; i
++)
339 storage
[i
] = sk_EX_CALLBACK_value(ip
->meth
, i
);
341 CRYPTO_THREAD_unlock(ex_data_lock
);
343 for (i
= 0; i
< mx
; i
++) {
347 CRYPTO_THREAD_write_lock(ex_data_lock
);
348 f
= sk_EX_CALLBACK_value(ip
->meth
, i
);
349 CRYPTO_THREAD_unlock(ex_data_lock
);
351 if (f
!= NULL
&& f
->free_func
!= NULL
) {
352 ptr
= CRYPTO_get_ex_data(ad
, i
);
353 f
->free_func(obj
, ptr
, ad
, i
, f
->argl
, f
->argp
);
357 if (storage
!= stack
)
358 OPENSSL_free(storage
);
360 sk_void_free(ad
->sk
);
365 * For a given CRYPTO_EX_DATA variable, set the value corresponding to a
366 * particular index in the class used by this variable
368 int CRYPTO_set_ex_data(CRYPTO_EX_DATA
*ad
, int idx
, void *val
)
372 if (ad
->sk
== NULL
) {
373 if ((ad
->sk
= sk_void_new_null()) == NULL
) {
374 CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA
, ERR_R_MALLOC_FAILURE
);
379 for (i
= sk_void_num(ad
->sk
); i
<= idx
; ++i
) {
380 if (!sk_void_push(ad
->sk
, NULL
)) {
381 CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA
, ERR_R_MALLOC_FAILURE
);
385 sk_void_set(ad
->sk
, idx
, val
);
390 * For a given CRYPTO_EX_DATA_ variable, get the value corresponding to a
391 * particular index in the class used by this variable
393 void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA
*ad
, int idx
)
395 if (ad
->sk
== NULL
|| idx
>= sk_void_num(ad
->sk
))
397 return sk_void_value(ad
->sk
, idx
);