xref: /freebsd/crypto/openssl/crypto/init.c (revision b077aed3)
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(&register_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(&register_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