1e71b7053SJung-uk Kim /*
234252e89SJung-uk Kim * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim *
4*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy
6e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html
8e71b7053SJung-uk Kim */
9e71b7053SJung-uk Kim
10*b077aed3SPierre Pronchery /* We need to use some engine deprecated APIs */
11*b077aed3SPierre Pronchery #define OPENSSL_SUPPRESS_DEPRECATED
12*b077aed3SPierre Pronchery
13e71b7053SJung-uk Kim #include "e_os.h"
1417f01e99SJung-uk Kim #include "crypto/cryptlib.h"
15e71b7053SJung-uk Kim #include <openssl/err.h>
1617f01e99SJung-uk Kim #include "crypto/rand.h"
17e71b7053SJung-uk Kim #include "internal/bio.h"
18e71b7053SJung-uk Kim #include <openssl/evp.h>
1917f01e99SJung-uk Kim #include "crypto/evp.h"
20e71b7053SJung-uk Kim #include "internal/conf.h"
2117f01e99SJung-uk Kim #include "crypto/async.h"
2217f01e99SJung-uk Kim #include "crypto/engine.h"
23e71b7053SJung-uk Kim #include "internal/comp.h"
24e71b7053SJung-uk Kim #include "internal/err.h"
2517f01e99SJung-uk Kim #include "crypto/err.h"
2617f01e99SJung-uk Kim #include "crypto/objects.h"
27e71b7053SJung-uk Kim #include <stdlib.h>
28e71b7053SJung-uk Kim #include <assert.h>
29e71b7053SJung-uk Kim #include "internal/thread_once.h"
3017f01e99SJung-uk Kim #include "crypto/dso_conf.h"
31e71b7053SJung-uk Kim #include "internal/dso.h"
3217f01e99SJung-uk Kim #include "crypto/store.h"
33*b077aed3SPierre Pronchery #include <openssl/cmp_util.h> /* for OSSL_CMP_log_close() */
34*b077aed3SPierre Pronchery #include <openssl/trace.h>
35*b077aed3SPierre Pronchery #include "crypto/ctype.h"
36e71b7053SJung-uk Kim
37e71b7053SJung-uk Kim static int stopped = 0;
38*b077aed3SPierre Pronchery static uint64_t optsdone = 0;
39e71b7053SJung-uk Kim
40e71b7053SJung-uk Kim typedef struct ossl_init_stop_st OPENSSL_INIT_STOP;
41e71b7053SJung-uk Kim struct ossl_init_stop_st {
42e71b7053SJung-uk Kim void (*handler)(void);
43e71b7053SJung-uk Kim OPENSSL_INIT_STOP *next;
44e71b7053SJung-uk Kim };
45e71b7053SJung-uk Kim
46e71b7053SJung-uk Kim static OPENSSL_INIT_STOP *stop_handlers = NULL;
47*b077aed3SPierre Pronchery /* Guards access to the optsdone variable on platforms without atomics */
48*b077aed3SPierre Pronchery static CRYPTO_RWLOCK *optsdone_lock = NULL;
49*b077aed3SPierre Pronchery /* Guards simultaneous INIT_LOAD_CONFIG calls with non-NULL settings */
50e71b7053SJung-uk Kim static CRYPTO_RWLOCK *init_lock = NULL;
51*b077aed3SPierre Pronchery static CRYPTO_THREAD_LOCAL in_init_config_local;
52e71b7053SJung-uk Kim
53e71b7053SJung-uk Kim static CRYPTO_ONCE base = CRYPTO_ONCE_STATIC_INIT;
54e71b7053SJung-uk Kim static int base_inited = 0;
DEFINE_RUN_ONCE_STATIC(ossl_init_base)55e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_base)
56e71b7053SJung-uk Kim {
57*b077aed3SPierre Pronchery /* no need to init trace */
58e71b7053SJung-uk Kim
59*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "ossl_init_base: setting up stop handlers\n");
60e71b7053SJung-uk Kim #ifndef OPENSSL_NO_CRYPTO_MDEBUG
61e71b7053SJung-uk Kim ossl_malloc_setup_failures();
62e71b7053SJung-uk Kim #endif
63*b077aed3SPierre Pronchery
64*b077aed3SPierre Pronchery if ((optsdone_lock = CRYPTO_THREAD_lock_new()) == NULL
65*b077aed3SPierre Pronchery || (init_lock = CRYPTO_THREAD_lock_new()) == NULL)
66e71b7053SJung-uk Kim goto err;
67*b077aed3SPierre Pronchery
68e71b7053SJung-uk Kim OPENSSL_cpuid_setup();
69e71b7053SJung-uk Kim
70*b077aed3SPierre Pronchery if (!ossl_init_thread())
71*b077aed3SPierre Pronchery goto err;
72*b077aed3SPierre Pronchery
73*b077aed3SPierre Pronchery if (!CRYPTO_THREAD_init_local(&in_init_config_local, NULL))
74*b077aed3SPierre Pronchery goto err;
75*b077aed3SPierre Pronchery
76e71b7053SJung-uk Kim base_inited = 1;
77e71b7053SJung-uk Kim return 1;
78e71b7053SJung-uk Kim
79e71b7053SJung-uk Kim err:
80*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "ossl_init_base failed!\n");
81*b077aed3SPierre Pronchery CRYPTO_THREAD_lock_free(optsdone_lock);
82*b077aed3SPierre Pronchery optsdone_lock = NULL;
83e71b7053SJung-uk Kim CRYPTO_THREAD_lock_free(init_lock);
84e71b7053SJung-uk Kim init_lock = NULL;
85e71b7053SJung-uk Kim
86e71b7053SJung-uk Kim return 0;
87e71b7053SJung-uk Kim }
88e71b7053SJung-uk Kim
896935a639SJung-uk Kim static CRYPTO_ONCE register_atexit = CRYPTO_ONCE_STATIC_INIT;
906935a639SJung-uk Kim #if !defined(OPENSSL_SYS_UEFI) && defined(_WIN32)
win32atexit(void)916935a639SJung-uk Kim static int win32atexit(void)
926935a639SJung-uk Kim {
936935a639SJung-uk Kim OPENSSL_cleanup();
946935a639SJung-uk Kim return 0;
956935a639SJung-uk Kim }
966935a639SJung-uk Kim #endif
976935a639SJung-uk Kim
DEFINE_RUN_ONCE_STATIC(ossl_init_register_atexit)986935a639SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_register_atexit)
996935a639SJung-uk Kim {
1006935a639SJung-uk Kim #ifdef OPENSSL_INIT_DEBUG
1016935a639SJung-uk Kim fprintf(stderr, "OPENSSL_INIT: ossl_init_register_atexit()\n");
1026935a639SJung-uk Kim #endif
1036935a639SJung-uk Kim #ifndef OPENSSL_SYS_UEFI
104*b077aed3SPierre Pronchery # if defined(_WIN32) && !defined(__BORLANDC__)
1056935a639SJung-uk Kim /* We use _onexit() in preference because it gets called on DLL unload */
1066935a639SJung-uk Kim if (_onexit(win32atexit) == NULL)
1076935a639SJung-uk Kim return 0;
1086935a639SJung-uk Kim # else
1096935a639SJung-uk Kim if (atexit(OPENSSL_cleanup) != 0)
1106935a639SJung-uk Kim return 0;
1116935a639SJung-uk Kim # endif
1126935a639SJung-uk Kim #endif
1136935a639SJung-uk Kim
1146935a639SJung-uk Kim return 1;
1156935a639SJung-uk Kim }
1166935a639SJung-uk Kim
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_register_atexit,ossl_init_register_atexit)1176935a639SJung-uk Kim DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_register_atexit,
1186935a639SJung-uk Kim ossl_init_register_atexit)
1196935a639SJung-uk Kim {
1206935a639SJung-uk Kim #ifdef OPENSSL_INIT_DEBUG
1216935a639SJung-uk Kim fprintf(stderr, "OPENSSL_INIT: ossl_init_no_register_atexit ok!\n");
1226935a639SJung-uk Kim #endif
1236935a639SJung-uk Kim /* Do nothing in this case */
1246935a639SJung-uk Kim return 1;
1256935a639SJung-uk Kim }
1266935a639SJung-uk Kim
127e71b7053SJung-uk Kim static CRYPTO_ONCE load_crypto_nodelete = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete)128e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete)
129e71b7053SJung-uk Kim {
130*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "ossl_init_load_crypto_nodelete()\n");
131*b077aed3SPierre Pronchery
132610a21fdSJung-uk Kim #if !defined(OPENSSL_USE_NODELETE) \
1336935a639SJung-uk Kim && !defined(OPENSSL_NO_PINSHARED)
134610a21fdSJung-uk Kim # if defined(DSO_WIN32) && !defined(_WIN32_WCE)
135e71b7053SJung-uk Kim {
136e71b7053SJung-uk Kim HMODULE handle = NULL;
137e71b7053SJung-uk Kim BOOL ret;
138e71b7053SJung-uk Kim
139e71b7053SJung-uk Kim /* We don't use the DSO route for WIN32 because there is a better way */
140e71b7053SJung-uk Kim ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
141e71b7053SJung-uk Kim | GET_MODULE_HANDLE_EX_FLAG_PIN,
142e71b7053SJung-uk Kim (void *)&base_inited, &handle);
143e71b7053SJung-uk Kim
144*b077aed3SPierre Pronchery OSSL_TRACE1(INIT,
145*b077aed3SPierre Pronchery "ossl_init_load_crypto_nodelete: "
146*b077aed3SPierre Pronchery "obtained DSO reference? %s\n",
147e71b7053SJung-uk Kim (ret == TRUE ? "No!" : "Yes."));
148e71b7053SJung-uk Kim return (ret == TRUE) ? 1 : 0;
149e71b7053SJung-uk Kim }
150610a21fdSJung-uk Kim # elif !defined(DSO_NONE)
151e71b7053SJung-uk Kim /*
152e71b7053SJung-uk Kim * Deliberately leak a reference to ourselves. This will force the library
153e71b7053SJung-uk Kim * to remain loaded until the atexit() handler is run at process exit.
154e71b7053SJung-uk Kim */
155e71b7053SJung-uk Kim {
156e71b7053SJung-uk Kim DSO *dso;
157e71b7053SJung-uk Kim void *err;
158e71b7053SJung-uk Kim
159e71b7053SJung-uk Kim if (!err_shelve_state(&err))
160e71b7053SJung-uk Kim return 0;
161e71b7053SJung-uk Kim
162e71b7053SJung-uk Kim dso = DSO_dsobyaddr(&base_inited, DSO_FLAG_NO_UNLOAD_ON_FREE);
163e71b7053SJung-uk Kim /*
164e71b7053SJung-uk Kim * In case of No!, it is uncertain our exit()-handlers can still be
165e71b7053SJung-uk Kim * called. After dlclose() the whole library might have been unloaded
166e71b7053SJung-uk Kim * already.
167e71b7053SJung-uk Kim */
168*b077aed3SPierre Pronchery OSSL_TRACE1(INIT, "obtained DSO reference? %s\n",
169*b077aed3SPierre Pronchery (dso == NULL ? "No!" : "Yes."));
170e71b7053SJung-uk Kim DSO_free(dso);
171e71b7053SJung-uk Kim err_unshelve_state(err);
172e71b7053SJung-uk Kim }
173e71b7053SJung-uk Kim # endif
174e71b7053SJung-uk Kim #endif
175e71b7053SJung-uk Kim
176e71b7053SJung-uk Kim return 1;
177e71b7053SJung-uk Kim }
178e71b7053SJung-uk Kim
179e71b7053SJung-uk Kim static CRYPTO_ONCE load_crypto_strings = CRYPTO_ONCE_STATIC_INIT;
18034252e89SJung-uk Kim
DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings)181e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings)
182e71b7053SJung-uk Kim {
183e71b7053SJung-uk Kim int ret = 1;
184e71b7053SJung-uk Kim /*
185e71b7053SJung-uk Kim * OPENSSL_NO_AUTOERRINIT is provided here to prevent at compile time
186e71b7053SJung-uk Kim * pulling in all the error strings during static linking
187e71b7053SJung-uk Kim */
188e71b7053SJung-uk Kim #if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT)
189*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "ossl_err_load_crypto_strings()\n");
190*b077aed3SPierre Pronchery ret = ossl_err_load_crypto_strings();
191e71b7053SJung-uk Kim #endif
192e71b7053SJung-uk Kim return ret;
193e71b7053SJung-uk Kim }
194e71b7053SJung-uk Kim
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_crypto_strings,ossl_init_load_crypto_strings)1956935a639SJung-uk Kim DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_crypto_strings,
1966935a639SJung-uk Kim ossl_init_load_crypto_strings)
1976935a639SJung-uk Kim {
1986935a639SJung-uk Kim /* Do nothing in this case */
1996935a639SJung-uk Kim return 1;
2006935a639SJung-uk Kim }
2016935a639SJung-uk Kim
202e71b7053SJung-uk Kim static CRYPTO_ONCE add_all_ciphers = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers)203e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers)
204e71b7053SJung-uk Kim {
205e71b7053SJung-uk Kim /*
206e71b7053SJung-uk Kim * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
207e71b7053SJung-uk Kim * pulling in all the ciphers during static linking
208e71b7053SJung-uk Kim */
209e71b7053SJung-uk Kim #ifndef OPENSSL_NO_AUTOALGINIT
210*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "openssl_add_all_ciphers_int()\n");
211e71b7053SJung-uk Kim openssl_add_all_ciphers_int();
212e71b7053SJung-uk Kim #endif
213e71b7053SJung-uk Kim return 1;
214e71b7053SJung-uk Kim }
215e71b7053SJung-uk Kim
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_ciphers,ossl_init_add_all_ciphers)2166935a639SJung-uk Kim DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_ciphers,
2176935a639SJung-uk Kim ossl_init_add_all_ciphers)
2186935a639SJung-uk Kim {
2196935a639SJung-uk Kim /* Do nothing */
2206935a639SJung-uk Kim return 1;
2216935a639SJung-uk Kim }
2226935a639SJung-uk Kim
223e71b7053SJung-uk Kim static CRYPTO_ONCE add_all_digests = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests)224e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests)
225e71b7053SJung-uk Kim {
226e71b7053SJung-uk Kim /*
227e71b7053SJung-uk Kim * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
228e71b7053SJung-uk Kim * pulling in all the ciphers during static linking
229e71b7053SJung-uk Kim */
230e71b7053SJung-uk Kim #ifndef OPENSSL_NO_AUTOALGINIT
231*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "openssl_add_all_digests()\n");
232e71b7053SJung-uk Kim openssl_add_all_digests_int();
233e71b7053SJung-uk Kim #endif
234e71b7053SJung-uk Kim return 1;
235e71b7053SJung-uk Kim }
236e71b7053SJung-uk Kim
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_digests,ossl_init_add_all_digests)2376935a639SJung-uk Kim DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_digests,
2386935a639SJung-uk Kim ossl_init_add_all_digests)
239e71b7053SJung-uk Kim {
240e71b7053SJung-uk Kim /* Do nothing */
241e71b7053SJung-uk Kim return 1;
242e71b7053SJung-uk Kim }
243e71b7053SJung-uk Kim
244e71b7053SJung-uk Kim static CRYPTO_ONCE config = CRYPTO_ONCE_STATIC_INIT;
245e71b7053SJung-uk Kim static int config_inited = 0;
2466935a639SJung-uk Kim static const OPENSSL_INIT_SETTINGS *conf_settings = NULL;
DEFINE_RUN_ONCE_STATIC(ossl_init_config)247e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_config)
248e71b7053SJung-uk Kim {
249*b077aed3SPierre Pronchery int ret = ossl_config_int(NULL);
250*b077aed3SPierre Pronchery
251*b077aed3SPierre Pronchery config_inited = 1;
252*b077aed3SPierre Pronchery return ret;
253*b077aed3SPierre Pronchery }
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_config_settings,ossl_init_config)254*b077aed3SPierre Pronchery DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_config_settings, ossl_init_config)
255*b077aed3SPierre Pronchery {
256*b077aed3SPierre Pronchery int ret = ossl_config_int(conf_settings);
257*b077aed3SPierre Pronchery
258e71b7053SJung-uk Kim config_inited = 1;
2596935a639SJung-uk Kim return ret;
260e71b7053SJung-uk Kim }
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_config,ossl_init_config)2616935a639SJung-uk Kim DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_config, ossl_init_config)
262e71b7053SJung-uk Kim {
263*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "ossl_no_config_int()\n");
264*b077aed3SPierre Pronchery ossl_no_config_int();
265e71b7053SJung-uk Kim config_inited = 1;
266e71b7053SJung-uk Kim return 1;
267e71b7053SJung-uk Kim }
268e71b7053SJung-uk Kim
269e71b7053SJung-uk Kim static CRYPTO_ONCE async = CRYPTO_ONCE_STATIC_INIT;
270e71b7053SJung-uk Kim static int async_inited = 0;
DEFINE_RUN_ONCE_STATIC(ossl_init_async)271e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_async)
272e71b7053SJung-uk Kim {
273*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "async_init()\n");
274e71b7053SJung-uk Kim if (!async_init())
275e71b7053SJung-uk Kim return 0;
276e71b7053SJung-uk Kim async_inited = 1;
277e71b7053SJung-uk Kim return 1;
278e71b7053SJung-uk Kim }
279e71b7053SJung-uk Kim
280e71b7053SJung-uk Kim #ifndef OPENSSL_NO_ENGINE
281e71b7053SJung-uk Kim static CRYPTO_ONCE engine_openssl = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_openssl)282e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_engine_openssl)
283e71b7053SJung-uk Kim {
284*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "engine_load_openssl_int()\n");
285e71b7053SJung-uk Kim engine_load_openssl_int();
286e71b7053SJung-uk Kim return 1;
287e71b7053SJung-uk Kim }
288e71b7053SJung-uk Kim # ifndef OPENSSL_NO_RDRAND
289e71b7053SJung-uk Kim static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_rdrand)290e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_engine_rdrand)
291e71b7053SJung-uk Kim {
292*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "engine_load_rdrand_int()\n");
293e71b7053SJung-uk Kim engine_load_rdrand_int();
294e71b7053SJung-uk Kim return 1;
295e71b7053SJung-uk Kim }
296e71b7053SJung-uk Kim # endif
297e71b7053SJung-uk Kim static CRYPTO_ONCE engine_dynamic = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_dynamic)298e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_engine_dynamic)
299e71b7053SJung-uk Kim {
300*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "engine_load_dynamic_int()\n");
301e71b7053SJung-uk Kim engine_load_dynamic_int();
302e71b7053SJung-uk Kim return 1;
303e71b7053SJung-uk Kim }
304e71b7053SJung-uk Kim # ifndef OPENSSL_NO_STATIC_ENGINE
305*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_DEVCRYPTOENG
306*b077aed3SPierre Pronchery static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto)307*b077aed3SPierre Pronchery DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto)
308*b077aed3SPierre Pronchery {
309*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "engine_load_devcrypto_int()\n");
310*b077aed3SPierre Pronchery engine_load_devcrypto_int();
311*b077aed3SPierre Pronchery return 1;
312*b077aed3SPierre Pronchery }
313*b077aed3SPierre Pronchery # endif
314*b077aed3SPierre Pronchery # if !defined(OPENSSL_NO_PADLOCKENG)
315e71b7053SJung-uk Kim static CRYPTO_ONCE engine_padlock = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock)316e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock)
317e71b7053SJung-uk Kim {
318*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "engine_load_padlock_int()\n");
319e71b7053SJung-uk Kim engine_load_padlock_int();
320e71b7053SJung-uk Kim return 1;
321e71b7053SJung-uk Kim }
322e71b7053SJung-uk Kim # endif
323e71b7053SJung-uk Kim # if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
324e71b7053SJung-uk Kim static CRYPTO_ONCE engine_capi = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_capi)325e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_engine_capi)
326e71b7053SJung-uk Kim {
327*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "engine_load_capi_int()\n");
328e71b7053SJung-uk Kim engine_load_capi_int();
329e71b7053SJung-uk Kim return 1;
330e71b7053SJung-uk Kim }
331e71b7053SJung-uk Kim # endif
332e71b7053SJung-uk Kim # if !defined(OPENSSL_NO_AFALGENG)
333e71b7053SJung-uk Kim static CRYPTO_ONCE engine_afalg = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_afalg)334e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ossl_init_engine_afalg)
335e71b7053SJung-uk Kim {
336*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "engine_load_afalg_int()\n");
337e71b7053SJung-uk Kim engine_load_afalg_int();
338e71b7053SJung-uk Kim return 1;
339e71b7053SJung-uk Kim }
340e71b7053SJung-uk Kim # endif
341e71b7053SJung-uk Kim # endif
342e71b7053SJung-uk Kim #endif
343e71b7053SJung-uk Kim
OPENSSL_cleanup(void)344e71b7053SJung-uk Kim void OPENSSL_cleanup(void)
345e71b7053SJung-uk Kim {
346e71b7053SJung-uk Kim OPENSSL_INIT_STOP *currhandler, *lasthandler;
347*b077aed3SPierre Pronchery
348*b077aed3SPierre Pronchery /*
349*b077aed3SPierre Pronchery * At some point we should consider looking at this function with a view to
350*b077aed3SPierre Pronchery * moving most/all of this into onfree handlers in OSSL_LIB_CTX.
351*b077aed3SPierre Pronchery */
352e71b7053SJung-uk Kim
353e71b7053SJung-uk Kim /* If we've not been inited then no need to deinit */
354e71b7053SJung-uk Kim if (!base_inited)
355e71b7053SJung-uk Kim return;
356e71b7053SJung-uk Kim
357e71b7053SJung-uk Kim /* Might be explicitly called and also by atexit */
358e71b7053SJung-uk Kim if (stopped)
359e71b7053SJung-uk Kim return;
360e71b7053SJung-uk Kim stopped = 1;
361e71b7053SJung-uk Kim
362e71b7053SJung-uk Kim /*
363e71b7053SJung-uk Kim * Thread stop may not get automatically called by the thread library for
364e71b7053SJung-uk Kim * the very last thread in some situations, so call it directly.
365e71b7053SJung-uk Kim */
366*b077aed3SPierre Pronchery OPENSSL_thread_stop();
367e71b7053SJung-uk Kim
368e71b7053SJung-uk Kim currhandler = stop_handlers;
369e71b7053SJung-uk Kim while (currhandler != NULL) {
370e71b7053SJung-uk Kim currhandler->handler();
371e71b7053SJung-uk Kim lasthandler = currhandler;
372e71b7053SJung-uk Kim currhandler = currhandler->next;
373e71b7053SJung-uk Kim OPENSSL_free(lasthandler);
374e71b7053SJung-uk Kim }
375e71b7053SJung-uk Kim stop_handlers = NULL;
376e71b7053SJung-uk Kim
377*b077aed3SPierre Pronchery CRYPTO_THREAD_lock_free(optsdone_lock);
378*b077aed3SPierre Pronchery optsdone_lock = NULL;
379e71b7053SJung-uk Kim CRYPTO_THREAD_lock_free(init_lock);
380e71b7053SJung-uk Kim init_lock = NULL;
381e71b7053SJung-uk Kim
382*b077aed3SPierre Pronchery CRYPTO_THREAD_cleanup_local(&in_init_config_local);
383*b077aed3SPierre Pronchery
384e71b7053SJung-uk Kim /*
385e71b7053SJung-uk Kim * We assume we are single-threaded for this function, i.e. no race
386e71b7053SJung-uk Kim * conditions for the various "*_inited" vars below.
387e71b7053SJung-uk Kim */
388e71b7053SJung-uk Kim
389e71b7053SJung-uk Kim #ifndef OPENSSL_NO_COMP
390*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_comp_zlib_cleanup()\n");
391*b077aed3SPierre Pronchery ossl_comp_zlib_cleanup();
392e71b7053SJung-uk Kim #endif
393e71b7053SJung-uk Kim
394e71b7053SJung-uk Kim if (async_inited) {
395*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: async_deinit()\n");
396e71b7053SJung-uk Kim async_deinit();
397e71b7053SJung-uk Kim }
398e71b7053SJung-uk Kim
399e71b7053SJung-uk Kim /*
400e71b7053SJung-uk Kim * Note that cleanup order is important:
401*b077aed3SPierre Pronchery * - ossl_rand_cleanup_int could call an ENGINE's RAND cleanup function so
402e71b7053SJung-uk Kim * must be called before engine_cleanup_int()
403e71b7053SJung-uk Kim * - ENGINEs use CRYPTO_EX_DATA and therefore, must be cleaned up
404*b077aed3SPierre Pronchery * before the ex data handlers are wiped during default ossl_lib_ctx deinit.
405*b077aed3SPierre Pronchery * - ossl_config_modules_free() can end up in ENGINE code so must be called
406e71b7053SJung-uk Kim * before engine_cleanup_int()
407e71b7053SJung-uk Kim * - ENGINEs and additional EVP algorithms might use added OIDs names so
408*b077aed3SPierre Pronchery * ossl_obj_cleanup_int() must be called last
409e71b7053SJung-uk Kim */
410*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_rand_cleanup_int()\n");
411*b077aed3SPierre Pronchery ossl_rand_cleanup_int();
412*b077aed3SPierre Pronchery
413*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_config_modules_free()\n");
414*b077aed3SPierre Pronchery ossl_config_modules_free();
415*b077aed3SPierre Pronchery
416e71b7053SJung-uk Kim #ifndef OPENSSL_NO_ENGINE
417*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: engine_cleanup_int()\n");
418e71b7053SJung-uk Kim engine_cleanup_int();
419e71b7053SJung-uk Kim #endif
420*b077aed3SPierre Pronchery
421*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_DEPRECATED_3_0
422*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_store_cleanup_int()\n");
423e71b7053SJung-uk Kim ossl_store_cleanup_int();
424*b077aed3SPierre Pronchery #endif
425*b077aed3SPierre Pronchery
426*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_lib_ctx_default_deinit()\n");
427*b077aed3SPierre Pronchery ossl_lib_ctx_default_deinit();
428*b077aed3SPierre Pronchery
429*b077aed3SPierre Pronchery ossl_cleanup_thread();
430*b077aed3SPierre Pronchery
431*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: bio_cleanup()\n");
432e71b7053SJung-uk Kim bio_cleanup();
433*b077aed3SPierre Pronchery
434*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: evp_cleanup_int()\n");
435e71b7053SJung-uk Kim evp_cleanup_int();
436*b077aed3SPierre Pronchery
437*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_obj_cleanup_int()\n");
438*b077aed3SPierre Pronchery ossl_obj_cleanup_int();
439*b077aed3SPierre Pronchery
440*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: err_int()\n");
441e71b7053SJung-uk Kim err_cleanup();
442e71b7053SJung-uk Kim
443*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: CRYPTO_secure_malloc_done()\n");
444e71b7053SJung-uk Kim CRYPTO_secure_malloc_done();
445e71b7053SJung-uk Kim
446*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_CMP
447*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: OSSL_CMP_log_close()\n");
448*b077aed3SPierre Pronchery OSSL_CMP_log_close();
449*b077aed3SPierre Pronchery #endif
450*b077aed3SPierre Pronchery
451*b077aed3SPierre Pronchery OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_trace_cleanup()\n");
452*b077aed3SPierre Pronchery ossl_trace_cleanup();
453*b077aed3SPierre Pronchery
454e71b7053SJung-uk Kim base_inited = 0;
455e71b7053SJung-uk Kim }
456e71b7053SJung-uk Kim
457e71b7053SJung-uk Kim /*
458e71b7053SJung-uk Kim * If this function is called with a non NULL settings value then it must be
459e71b7053SJung-uk Kim * called prior to any threads making calls to any OpenSSL functions,
460e71b7053SJung-uk Kim * i.e. passing a non-null settings value is assumed to be single-threaded.
461e71b7053SJung-uk Kim */
OPENSSL_init_crypto(uint64_t opts,const OPENSSL_INIT_SETTINGS * settings)462e71b7053SJung-uk Kim int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
463e71b7053SJung-uk Kim {
464*b077aed3SPierre Pronchery uint64_t tmp;
465*b077aed3SPierre Pronchery int aloaddone = 0;
466*b077aed3SPierre Pronchery
467*b077aed3SPierre Pronchery /* Applications depend on 0 being returned when cleanup was already done */
468e71b7053SJung-uk Kim if (stopped) {
469e71b7053SJung-uk Kim if (!(opts & OPENSSL_INIT_BASE_ONLY))
470*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_CRYPTO, ERR_R_INIT_FAIL);
471e71b7053SJung-uk Kim return 0;
472e71b7053SJung-uk Kim }
473e71b7053SJung-uk Kim
4746935a639SJung-uk Kim /*
475*b077aed3SPierre Pronchery * We ignore failures from this function. It is probably because we are
476*b077aed3SPierre Pronchery * on a platform that doesn't support lockless atomic loads (we may not
477*b077aed3SPierre Pronchery * have created optsdone_lock yet so we can't use it). This is just an
478*b077aed3SPierre Pronchery * optimisation to skip the full checks in this function if we don't need
479*b077aed3SPierre Pronchery * to, so we carry on regardless in the event of failure.
480*b077aed3SPierre Pronchery *
481*b077aed3SPierre Pronchery * There could be a race here with other threads, so that optsdone has not
482*b077aed3SPierre Pronchery * been updated yet, even though the options have in fact been initialised.
483*b077aed3SPierre Pronchery * This doesn't matter - it just means we will run the full function
484*b077aed3SPierre Pronchery * unnecessarily - but all the critical code is contained in RUN_ONCE
485*b077aed3SPierre Pronchery * functions anyway so we are safe.
486*b077aed3SPierre Pronchery */
487*b077aed3SPierre Pronchery if (CRYPTO_atomic_load(&optsdone, &tmp, NULL)) {
488*b077aed3SPierre Pronchery if ((tmp & opts) == opts)
489*b077aed3SPierre Pronchery return 1;
490*b077aed3SPierre Pronchery aloaddone = 1;
491*b077aed3SPierre Pronchery }
492*b077aed3SPierre Pronchery
493*b077aed3SPierre Pronchery /*
494*b077aed3SPierre Pronchery * At some point we should look at this function with a view to moving
495*b077aed3SPierre Pronchery * most/all of this into OSSL_LIB_CTX.
496*b077aed3SPierre Pronchery *
4976935a639SJung-uk Kim * When the caller specifies OPENSSL_INIT_BASE_ONLY, that should be the
4986935a639SJung-uk Kim * *only* option specified. With that option we return immediately after
4996935a639SJung-uk Kim * doing the requested limited initialization. Note that
5006935a639SJung-uk Kim * err_shelve_state() called by us via ossl_init_load_crypto_nodelete()
5016935a639SJung-uk Kim * re-enters OPENSSL_init_crypto() with OPENSSL_INIT_BASE_ONLY, but with
5026935a639SJung-uk Kim * base already initialized this is a harmless NOOP.
5036935a639SJung-uk Kim *
5046935a639SJung-uk Kim * If we remain the only caller of err_shelve_state() the recursion should
5056935a639SJung-uk Kim * perhaps be removed, but if in doubt, it can be left in place.
5066935a639SJung-uk Kim */
507e71b7053SJung-uk Kim if (!RUN_ONCE(&base, ossl_init_base))
508e71b7053SJung-uk Kim return 0;
509*b077aed3SPierre Pronchery
5106935a639SJung-uk Kim if (opts & OPENSSL_INIT_BASE_ONLY)
5116935a639SJung-uk Kim return 1;
512e71b7053SJung-uk Kim
5136935a639SJung-uk Kim /*
514*b077aed3SPierre Pronchery * optsdone_lock should definitely be set up now, so we can now repeat the
515*b077aed3SPierre Pronchery * same check from above but be sure that it will work even on platforms
516*b077aed3SPierre Pronchery * without lockless CRYPTO_atomic_load
517*b077aed3SPierre Pronchery */
518*b077aed3SPierre Pronchery if (!aloaddone) {
519*b077aed3SPierre Pronchery if (!CRYPTO_atomic_load(&optsdone, &tmp, optsdone_lock))
520*b077aed3SPierre Pronchery return 0;
521*b077aed3SPierre Pronchery if ((tmp & opts) == opts)
522*b077aed3SPierre Pronchery return 1;
523*b077aed3SPierre Pronchery }
524*b077aed3SPierre Pronchery
525*b077aed3SPierre Pronchery /*
5266935a639SJung-uk Kim * Now we don't always set up exit handlers, the INIT_BASE_ONLY calls
5276935a639SJung-uk Kim * should not have the side-effect of setting up exit handlers, and
5286935a639SJung-uk Kim * therefore, this code block is below the INIT_BASE_ONLY-conditioned early
5296935a639SJung-uk Kim * return above.
5306935a639SJung-uk Kim */
5316935a639SJung-uk Kim if ((opts & OPENSSL_INIT_NO_ATEXIT) != 0) {
5326935a639SJung-uk Kim if (!RUN_ONCE_ALT(®ister_atexit, ossl_init_no_register_atexit,
5336935a639SJung-uk Kim ossl_init_register_atexit))
5346935a639SJung-uk Kim return 0;
5356935a639SJung-uk Kim } else if (!RUN_ONCE(®ister_atexit, ossl_init_register_atexit)) {
5366935a639SJung-uk Kim return 0;
5376935a639SJung-uk Kim }
5386935a639SJung-uk Kim
5396935a639SJung-uk Kim if (!RUN_ONCE(&load_crypto_nodelete, ossl_init_load_crypto_nodelete))
540e71b7053SJung-uk Kim return 0;
541e71b7053SJung-uk Kim
542e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS)
5436935a639SJung-uk Kim && !RUN_ONCE_ALT(&load_crypto_strings,
5446935a639SJung-uk Kim ossl_init_no_load_crypto_strings,
5456935a639SJung-uk Kim ossl_init_load_crypto_strings))
546e71b7053SJung-uk Kim return 0;
547e71b7053SJung-uk Kim
548e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS)
549e71b7053SJung-uk Kim && !RUN_ONCE(&load_crypto_strings, ossl_init_load_crypto_strings))
550e71b7053SJung-uk Kim return 0;
551e71b7053SJung-uk Kim
552e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS)
5536935a639SJung-uk Kim && !RUN_ONCE_ALT(&add_all_ciphers, ossl_init_no_add_all_ciphers,
5546935a639SJung-uk Kim ossl_init_add_all_ciphers))
555e71b7053SJung-uk Kim return 0;
556e71b7053SJung-uk Kim
557e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_ADD_ALL_CIPHERS)
558e71b7053SJung-uk Kim && !RUN_ONCE(&add_all_ciphers, ossl_init_add_all_ciphers))
559e71b7053SJung-uk Kim return 0;
560e71b7053SJung-uk Kim
561e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS)
5626935a639SJung-uk Kim && !RUN_ONCE_ALT(&add_all_digests, ossl_init_no_add_all_digests,
5636935a639SJung-uk Kim ossl_init_add_all_digests))
564e71b7053SJung-uk Kim return 0;
565e71b7053SJung-uk Kim
566e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_ADD_ALL_DIGESTS)
567e71b7053SJung-uk Kim && !RUN_ONCE(&add_all_digests, ossl_init_add_all_digests))
568e71b7053SJung-uk Kim return 0;
569e71b7053SJung-uk Kim
570e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_ATFORK)
571e71b7053SJung-uk Kim && !openssl_init_fork_handlers())
572e71b7053SJung-uk Kim return 0;
573e71b7053SJung-uk Kim
574e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG)
5756935a639SJung-uk Kim && !RUN_ONCE_ALT(&config, ossl_init_no_config, ossl_init_config))
576e71b7053SJung-uk Kim return 0;
577e71b7053SJung-uk Kim
578e71b7053SJung-uk Kim if (opts & OPENSSL_INIT_LOAD_CONFIG) {
579*b077aed3SPierre Pronchery int loading = CRYPTO_THREAD_get_local(&in_init_config_local) != NULL;
580*b077aed3SPierre Pronchery
581*b077aed3SPierre Pronchery /* If called recursively from OBJ_ calls, just skip it. */
582*b077aed3SPierre Pronchery if (!loading) {
583e71b7053SJung-uk Kim int ret;
584*b077aed3SPierre Pronchery
585*b077aed3SPierre Pronchery if (!CRYPTO_THREAD_set_local(&in_init_config_local, (void *)-1))
586*b077aed3SPierre Pronchery return 0;
587*b077aed3SPierre Pronchery if (settings == NULL) {
588e71b7053SJung-uk Kim ret = RUN_ONCE(&config, ossl_init_config);
589*b077aed3SPierre Pronchery } else {
590*b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(init_lock))
591*b077aed3SPierre Pronchery return 0;
592*b077aed3SPierre Pronchery conf_settings = settings;
593*b077aed3SPierre Pronchery ret = RUN_ONCE_ALT(&config, ossl_init_config_settings,
594*b077aed3SPierre Pronchery ossl_init_config);
5956935a639SJung-uk Kim conf_settings = NULL;
596e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(init_lock);
597*b077aed3SPierre Pronchery }
598*b077aed3SPierre Pronchery
599610a21fdSJung-uk Kim if (ret <= 0)
600e71b7053SJung-uk Kim return 0;
601e71b7053SJung-uk Kim }
602*b077aed3SPierre Pronchery }
603e71b7053SJung-uk Kim
604e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_ASYNC)
605e71b7053SJung-uk Kim && !RUN_ONCE(&async, ossl_init_async))
606e71b7053SJung-uk Kim return 0;
607e71b7053SJung-uk Kim
608e71b7053SJung-uk Kim #ifndef OPENSSL_NO_ENGINE
609e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_ENGINE_OPENSSL)
610e71b7053SJung-uk Kim && !RUN_ONCE(&engine_openssl, ossl_init_engine_openssl))
611e71b7053SJung-uk Kim return 0;
612e71b7053SJung-uk Kim # ifndef OPENSSL_NO_RDRAND
613e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_ENGINE_RDRAND)
614e71b7053SJung-uk Kim && !RUN_ONCE(&engine_rdrand, ossl_init_engine_rdrand))
615e71b7053SJung-uk Kim return 0;
616e71b7053SJung-uk Kim # endif
617e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_ENGINE_DYNAMIC)
618e71b7053SJung-uk Kim && !RUN_ONCE(&engine_dynamic, ossl_init_engine_dynamic))
619e71b7053SJung-uk Kim return 0;
620e71b7053SJung-uk Kim # ifndef OPENSSL_NO_STATIC_ENGINE
621*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_DEVCRYPTOENG
622*b077aed3SPierre Pronchery if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV)
623*b077aed3SPierre Pronchery && !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto))
624*b077aed3SPierre Pronchery return 0;
625*b077aed3SPierre Pronchery # endif
626*b077aed3SPierre Pronchery # if !defined(OPENSSL_NO_PADLOCKENG)
627e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_ENGINE_PADLOCK)
628e71b7053SJung-uk Kim && !RUN_ONCE(&engine_padlock, ossl_init_engine_padlock))
629e71b7053SJung-uk Kim return 0;
630e71b7053SJung-uk Kim # endif
631e71b7053SJung-uk Kim # if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
632e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_ENGINE_CAPI)
633e71b7053SJung-uk Kim && !RUN_ONCE(&engine_capi, ossl_init_engine_capi))
634e71b7053SJung-uk Kim return 0;
635e71b7053SJung-uk Kim # endif
636e71b7053SJung-uk Kim # if !defined(OPENSSL_NO_AFALGENG)
637e71b7053SJung-uk Kim if ((opts & OPENSSL_INIT_ENGINE_AFALG)
638e71b7053SJung-uk Kim && !RUN_ONCE(&engine_afalg, ossl_init_engine_afalg))
639e71b7053SJung-uk Kim return 0;
640e71b7053SJung-uk Kim # endif
641e71b7053SJung-uk Kim # endif
642e71b7053SJung-uk Kim if (opts & (OPENSSL_INIT_ENGINE_ALL_BUILTIN
643e71b7053SJung-uk Kim | OPENSSL_INIT_ENGINE_OPENSSL
644e71b7053SJung-uk Kim | OPENSSL_INIT_ENGINE_AFALG)) {
645e71b7053SJung-uk Kim ENGINE_register_all_complete();
646e71b7053SJung-uk Kim }
647e71b7053SJung-uk Kim #endif
648e71b7053SJung-uk Kim
649*b077aed3SPierre Pronchery if (!CRYPTO_atomic_or(&optsdone, opts, &tmp, optsdone_lock))
650e71b7053SJung-uk Kim return 0;
651e71b7053SJung-uk Kim
652e71b7053SJung-uk Kim return 1;
653e71b7053SJung-uk Kim }
654e71b7053SJung-uk Kim
OPENSSL_atexit(void (* handler)(void))655e71b7053SJung-uk Kim int OPENSSL_atexit(void (*handler)(void))
656e71b7053SJung-uk Kim {
657e71b7053SJung-uk Kim OPENSSL_INIT_STOP *newhand;
658e71b7053SJung-uk Kim
659610a21fdSJung-uk Kim #if !defined(OPENSSL_USE_NODELETE)\
6606935a639SJung-uk Kim && !defined(OPENSSL_NO_PINSHARED)
661e71b7053SJung-uk Kim {
662*b077aed3SPierre Pronchery # if defined(DSO_WIN32) && !defined(_WIN32_WCE)
663*b077aed3SPierre Pronchery HMODULE handle = NULL;
664*b077aed3SPierre Pronchery BOOL ret;
665e71b7053SJung-uk Kim union {
666e71b7053SJung-uk Kim void *sym;
667e71b7053SJung-uk Kim void (*func)(void);
668e71b7053SJung-uk Kim } handlersym;
669e71b7053SJung-uk Kim
670e71b7053SJung-uk Kim handlersym.func = handler;
671e71b7053SJung-uk Kim
672e71b7053SJung-uk Kim /*
673e71b7053SJung-uk Kim * We don't use the DSO route for WIN32 because there is a better
674e71b7053SJung-uk Kim * way
675e71b7053SJung-uk Kim */
676e71b7053SJung-uk Kim ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
677e71b7053SJung-uk Kim | GET_MODULE_HANDLE_EX_FLAG_PIN,
678e71b7053SJung-uk Kim handlersym.sym, &handle);
679e71b7053SJung-uk Kim
680e71b7053SJung-uk Kim if (!ret)
681e71b7053SJung-uk Kim return 0;
682610a21fdSJung-uk Kim # elif !defined(DSO_NONE)
683e71b7053SJung-uk Kim /*
684e71b7053SJung-uk Kim * Deliberately leak a reference to the handler. This will force the
685e71b7053SJung-uk Kim * library/code containing the handler to remain loaded until we run the
686e71b7053SJung-uk Kim * atexit handler. If -znodelete has been used then this is
687e71b7053SJung-uk Kim * unnecessary.
688e71b7053SJung-uk Kim */
689e71b7053SJung-uk Kim DSO *dso = NULL;
690*b077aed3SPierre Pronchery union {
691*b077aed3SPierre Pronchery void *sym;
692*b077aed3SPierre Pronchery void (*func)(void);
693*b077aed3SPierre Pronchery } handlersym;
694*b077aed3SPierre Pronchery
695*b077aed3SPierre Pronchery handlersym.func = handler;
696e71b7053SJung-uk Kim
697e71b7053SJung-uk Kim ERR_set_mark();
698e71b7053SJung-uk Kim dso = DSO_dsobyaddr(handlersym.sym, DSO_FLAG_NO_UNLOAD_ON_FREE);
699e71b7053SJung-uk Kim /* See same code above in ossl_init_base() for an explanation. */
700*b077aed3SPierre Pronchery OSSL_TRACE1(INIT,
701*b077aed3SPierre Pronchery "atexit: obtained DSO reference? %s\n",
702*b077aed3SPierre Pronchery (dso == NULL ? "No!" : "Yes."));
703e71b7053SJung-uk Kim DSO_free(dso);
704e71b7053SJung-uk Kim ERR_pop_to_mark();
705e71b7053SJung-uk Kim # endif
706e71b7053SJung-uk Kim }
707e71b7053SJung-uk Kim #endif
708e71b7053SJung-uk Kim
709e71b7053SJung-uk Kim if ((newhand = OPENSSL_malloc(sizeof(*newhand))) == NULL) {
710*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
711e71b7053SJung-uk Kim return 0;
712e71b7053SJung-uk Kim }
713e71b7053SJung-uk Kim
714e71b7053SJung-uk Kim newhand->handler = handler;
715e71b7053SJung-uk Kim newhand->next = stop_handlers;
716e71b7053SJung-uk Kim stop_handlers = newhand;
717e71b7053SJung-uk Kim
718e71b7053SJung-uk Kim return 1;
719e71b7053SJung-uk Kim }
720e71b7053SJung-uk Kim
721