X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Finit.c;h=e73c9bafbda3e0adbe60f43e5fd66d9bd5102a43;hp=265d54d807290cd114bfe071e85f3ba97f169a76;hb=a2f27fd750b9ae62a571a9212c7154889100bdb0;hpb=689f112d9806fa4a0c2f8c108226639455bc770d diff --git a/crypto/init.c b/crypto/init.c index 265d54d807..e73c9bafbd 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -1,37 +1,58 @@ /* - * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ -#include +#include "e_os.h" +#include "internal/cryptlib_int.h" #include -#include -#include +#include "internal/rand_int.h" +#include "internal/bio.h" #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "internal/evp_int.h" +#include "internal/conf.h" +#include "internal/async.h" +#include "internal/engine.h" +#include "internal/comp.h" +#include "internal/err.h" +#include "internal/err_int.h" +#include "internal/objects.h" #include #include -#include -#include +#include "internal/thread_once.h" +#include "internal/dso_conf.h" +#include "internal/dso.h" +#include "internal/store.h" +#include static int stopped = 0; -static void ossl_init_thread_stop(struct thread_local_inits_st *locals); +/* + * Since per-thread-specific-data destructors are not universally + * available, i.e. not on Windows, only below CRYPTO_THREAD_LOCAL key + * is assumed to have destructor associated. And then an effort is made + * to call this single destructor on non-pthread platform[s]. + * + * Initial value is "impossible". It is used as guard value to shortcut + * destructor for threads terminating before libcrypto is initialized or + * after it's de-initialized. Access to the key doesn't have to be + * serialized for the said threads, because they didn't use libcrypto + * and it doesn't matter if they pick "impossible" or derefernce real + * key value and pull NULL past initialization in the first thread that + * intends to use libcrypto. + */ +static union { + long sane; + CRYPTO_THREAD_LOCAL value; +} destructor_key = { -1 }; -static CRYPTO_THREAD_LOCAL threadstopkey; +static void ossl_init_thread_stop(struct thread_local_inits_st *locals); -static void ossl_init_thread_stop_wrap(void *local) +static void ossl_init_thread_destructor(void *local) { ossl_init_thread_stop((struct thread_local_inits_st *)local); } @@ -39,14 +60,17 @@ static void ossl_init_thread_stop_wrap(void *local) static struct thread_local_inits_st *ossl_init_get_thread_local(int alloc) { struct thread_local_inits_st *local = - CRYPTO_THREAD_get_local(&threadstopkey); - - if (local == NULL && alloc) { - local = OPENSSL_zalloc(sizeof *local); - CRYPTO_THREAD_set_local(&threadstopkey, local); - } - if (!alloc) { - CRYPTO_THREAD_set_local(&threadstopkey, NULL); + CRYPTO_THREAD_get_local(&destructor_key.value); + + if (alloc) { + if (local == NULL + && (local = OPENSSL_zalloc(sizeof(*local))) != NULL + && !CRYPTO_THREAD_set_local(&destructor_key.value, local)) { + OPENSSL_free(local); + return NULL; + } + } else { + CRYPTO_THREAD_set_local(&destructor_key.value, NULL); } return local; @@ -65,34 +89,80 @@ static CRYPTO_ONCE base = CRYPTO_ONCE_STATIC_INIT; static int base_inited = 0; DEFINE_RUN_ONCE_STATIC(ossl_init_base) { -#ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_base: Setting up stop handlers\n"); -#endif + CRYPTO_THREAD_LOCAL key; + + if (ossl_trace_init() == 0) + return 0; + + OSSL_TRACE(INIT, "ossl_init_base: setting up stop handlers\n"); #ifndef OPENSSL_NO_CRYPTO_MDEBUG ossl_malloc_setup_failures(); #endif - /* - * We use a dummy thread local key here. We use the destructor to detect - * when the thread is going to stop (where that feature is available) - */ - CRYPTO_THREAD_init_local(&threadstopkey, ossl_init_thread_stop_wrap); -#ifndef OPENSSL_SYS_UEFI - atexit(OPENSSL_cleanup); -#endif - if ((init_lock = CRYPTO_THREAD_lock_new()) == NULL) + if (!CRYPTO_THREAD_init_local(&key, ossl_init_thread_destructor)) return 0; + if ((init_lock = CRYPTO_THREAD_lock_new()) == NULL) + goto err; OPENSSL_cpuid_setup(); - /* - * BIG FAT WARNING! - * Everything needed to be initialized in this function before threads - * come along MUST happen before base_inited is set to 1, or we will - * see race conditions. - */ + destructor_key.value = key; base_inited = 1; + return 1; + +err: + OSSL_TRACE(INIT, "ossl_init_base failed!\n"); + CRYPTO_THREAD_lock_free(init_lock); + init_lock = NULL; -#if !defined(OPENSSL_NO_DSO) && !defined(OPENSSL_USE_NODELETE) -# ifdef DSO_WIN32 + CRYPTO_THREAD_cleanup_local(&key); + return 0; +} + +static CRYPTO_ONCE register_atexit = CRYPTO_ONCE_STATIC_INIT; +#if !defined(OPENSSL_SYS_UEFI) && defined(_WIN32) +static int win32atexit(void) +{ + OPENSSL_cleanup(); + return 0; +} +#endif + +DEFINE_RUN_ONCE_STATIC(ossl_init_register_atexit) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_register_atexit()\n"); +#endif +#ifndef OPENSSL_SYS_UEFI +# ifdef _WIN32 + /* We use _onexit() in preference because it gets called on DLL unload */ + if (_onexit(win32atexit) == NULL) + return 0; +# else + if (atexit(OPENSSL_cleanup) != 0) + return 0; +# endif +#endif + + return 1; +} + +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_register_atexit, + ossl_init_register_atexit) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_no_register_atexit ok!\n"); +#endif + /* Do nothing in this case */ + return 1; +} + +static CRYPTO_ONCE load_crypto_nodelete = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete) +{ + OSSL_TRACE(INIT, "ossl_init_load_crypto_nodelete()\n"); + +#if !defined(OPENSSL_USE_NODELETE) \ + && !defined(OPENSSL_NO_PINSHARED) +# if defined(DSO_WIN32) && !defined(_WIN32_WCE) { HMODULE handle = NULL; BOOL ret; @@ -102,20 +172,34 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_base) | GET_MODULE_HANDLE_EX_FLAG_PIN, (void *)&base_inited, &handle); + OSSL_TRACE1(INIT, + "ossl_init_load_crypto_nodelete: " + "obtained DSO reference? %s\n", + (ret == TRUE ? "No!" : "Yes.")); return (ret == TRUE) ? 1 : 0; } -# else +# elif !defined(DSO_NONE) /* * Deliberately leak a reference to ourselves. This will force the library * to remain loaded until the atexit() handler is run at process exit. */ { - DSO *dso = NULL; + DSO *dso; + void *err; + + if (!err_shelve_state(&err)) + return 0; - ERR_set_mark(); dso = DSO_dsobyaddr(&base_inited, DSO_FLAG_NO_UNLOAD_ON_FREE); + /* + * In case of No!, it is uncertain our exit()-handlers can still be + * called. After dlclose() the whole library might have been unloaded + * already. + */ + OSSL_TRACE1(INIT, "obtained DSO reference? %s\n", + (dso == NULL ? "No!" : "Yes.")); DSO_free(dso); - ERR_pop_to_mark(); + err_unshelve_state(err); } # endif #endif @@ -125,12 +209,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_base) static CRYPTO_ONCE load_crypto_strings = CRYPTO_ONCE_STATIC_INIT; static int load_crypto_strings_inited = 0; -DEFINE_RUN_ONCE_STATIC(ossl_init_no_load_crypto_strings) -{ - /* Do nothing in this case */ - return 1; -} - DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings) { int ret = 1; @@ -139,16 +217,20 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings) * pulling in all the error strings during static linking */ #if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT) -# ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_strings: " - "err_load_crypto_strings_int()\n"); -# endif + OSSL_TRACE(INIT, "err_load_crypto_strings_int()\n"); ret = err_load_crypto_strings_int(); load_crypto_strings_inited = 1; -#endif +#endif return ret; } +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_crypto_strings, + ossl_init_load_crypto_strings) +{ + /* Do nothing in this case */ + return 1; +} + static CRYPTO_ONCE add_all_ciphers = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers) { @@ -157,15 +239,19 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers) * pulling in all the ciphers during static linking */ #ifndef OPENSSL_NO_AUTOALGINIT -# ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_ciphers: " - "openssl_add_all_ciphers_int()\n"); -# endif + OSSL_TRACE(INIT, "openssl_add_all_ciphers_int()\n"); openssl_add_all_ciphers_int(); #endif return 1; } +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_ciphers, + ossl_init_add_all_ciphers) +{ + /* Do nothing */ + return 1; +} + static CRYPTO_ONCE add_all_digests = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests) { @@ -174,16 +260,54 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests) * pulling in all the ciphers during static linking */ #ifndef OPENSSL_NO_AUTOALGINIT -# ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_digests: " - "openssl_add_all_digests()\n"); -# endif + OSSL_TRACE(INIT, "openssl_add_all_digests()\n"); openssl_add_all_digests_int(); #endif return 1; } -DEFINE_RUN_ONCE_STATIC(ossl_init_no_add_algs) +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_digests, + ossl_init_add_all_digests) +{ + /* Do nothing */ + return 1; +} + +static CRYPTO_ONCE add_all_macs = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_macs) +{ + /* + * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time + * pulling in all the macs during static linking + */ +#ifndef OPENSSL_NO_AUTOALGINIT + OSSL_TRACE(INIT, "openssl_add_all_macs_int()\n"); + openssl_add_all_macs_int(); +#endif + return 1; +} + +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_macs, ossl_init_add_all_macs) +{ + /* Do nothing */ + return 1; +} + +static CRYPTO_ONCE add_all_kdfs = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_kdfs) +{ + /* + * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time + * pulling in all the macs during static linking + */ +#ifndef OPENSSL_NO_AUTOALGINIT + OSSL_TRACE(INIT, "openssl_add_all_kdfs_int()\n"); + openssl_add_all_kdfs_int(); +#endif + return 1; +} + +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_kdfs, ossl_init_add_all_kdfs) { /* Do nothing */ return 1; @@ -191,24 +315,16 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_no_add_algs) static CRYPTO_ONCE config = CRYPTO_ONCE_STATIC_INIT; static int config_inited = 0; -static const char *appname; +static const OPENSSL_INIT_SETTINGS *conf_settings = NULL; DEFINE_RUN_ONCE_STATIC(ossl_init_config) { -#ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, - "OPENSSL_INIT: ossl_init_config: openssl_config(%s)\n", - appname == NULL ? "NULL" : appname); -#endif - openssl_config_int(appname); + int ret = openssl_config_int(conf_settings); config_inited = 1; - return 1; + return ret; } -DEFINE_RUN_ONCE_STATIC(ossl_init_no_config) +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_config, ossl_init_config) { -#ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, - "OPENSSL_INIT: ossl_init_config: openssl_no_config_int()\n"); -#endif + OSSL_TRACE(INIT, "openssl_no_config_int()\n"); openssl_no_config_int(); config_inited = 1; return 1; @@ -218,9 +334,7 @@ static CRYPTO_ONCE async = CRYPTO_ONCE_STATIC_INIT; static int async_inited = 0; DEFINE_RUN_ONCE_STATIC(ossl_init_async) { -#ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_async: async_init()\n"); -#endif + OSSL_TRACE(INIT, "async_init()\n"); if (!async_init()) return 0; async_inited = 1; @@ -231,35 +345,15 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_async) static CRYPTO_ONCE engine_openssl = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_engine_openssl) { -# ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_openssl: " - "engine_load_openssl_int()\n"); -# endif + OSSL_TRACE(INIT, "engine_load_openssl_int()\n"); engine_load_openssl_int(); return 1; } -# if !defined(OPENSSL_NO_HW) && \ - (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(HAVE_CRYPTODEV)) -static CRYPTO_ONCE engine_cryptodev = CRYPTO_ONCE_STATIC_INIT; -DEFINE_RUN_ONCE_STATIC(ossl_init_engine_cryptodev) -{ -# ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_cryptodev: " - "engine_load_cryptodev_int()\n"); -# endif - engine_load_cryptodev_int(); - return 1; -} -# endif - # ifndef OPENSSL_NO_RDRAND static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_engine_rdrand) { -# ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_rdrand: " - "engine_load_rdrand_int()\n"); -# endif + OSSL_TRACE(INIT, "engine_load_rdrand_int()\n"); engine_load_rdrand_int(); return 1; } @@ -267,22 +361,25 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_rdrand) static CRYPTO_ONCE engine_dynamic = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_engine_dynamic) { -# ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_dynamic: " - "engine_load_dynamic_int()\n"); -# endif + OSSL_TRACE(INIT, "engine_load_dynamic_int()\n"); engine_load_dynamic_int(); return 1; } # ifndef OPENSSL_NO_STATIC_ENGINE -# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) +# ifndef OPENSSL_NO_DEVCRYPTOENG +static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto) +{ + OSSL_TRACE(INIT, "engine_load_devcrypto_int()\n"); + engine_load_devcrypto_int(); + return 1; +} +# endif +# if !defined(OPENSSL_NO_PADLOCKENG) static CRYPTO_ONCE engine_padlock = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock) { -# ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_padlock: " - "engine_load_padlock_int()\n"); -# endif + OSSL_TRACE(INIT, "engine_load_padlock_int()\n"); engine_load_padlock_int(); return 1; } @@ -291,10 +388,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock) static CRYPTO_ONCE engine_capi = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_engine_capi) { -# ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_capi: " - "engine_load_capi_int()\n"); -# endif + OSSL_TRACE(INIT, "engine_load_capi_int()\n"); engine_load_capi_int(); return 1; } @@ -303,10 +397,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_capi) static CRYPTO_ONCE engine_afalg = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_engine_afalg) { -# ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_afalg: " - "engine_load_afalg_int()\n"); -# endif + OSSL_TRACE(INIT, "engine_load_afalg_int()\n"); engine_load_afalg_int(); return 1; } @@ -333,59 +424,74 @@ static void ossl_init_thread_stop(struct thread_local_inits_st *locals) return; if (locals->async) { -#ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: " - "ASYNC_cleanup_thread()\n"); -#endif - ASYNC_cleanup_thread(); + OSSL_TRACE(INIT, "async_delete_thread_state()\n"); + async_delete_thread_state(); } if (locals->err_state) { -#ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: " - "err_delete_thread_state()\n"); -#endif + OSSL_TRACE(INIT, "err_delete_thread_state()\n"); err_delete_thread_state(); } + if (locals->rand) { + OSSL_TRACE(INIT, "drbg_delete_thread_state()\n"); + drbg_delete_thread_state(); + } + OPENSSL_free(locals); } void OPENSSL_thread_stop(void) { - ossl_init_thread_stop( - (struct thread_local_inits_st *)ossl_init_get_thread_local(0)); + if (destructor_key.sane != -1) + ossl_init_thread_stop(ossl_init_get_thread_local(0)); } int ossl_init_thread_start(uint64_t opts) { - struct thread_local_inits_st *locals = ossl_init_get_thread_local(1); + struct thread_local_inits_st *locals; + + if (!OPENSSL_init_crypto(0, NULL)) + return 0; + + locals = ossl_init_get_thread_local(1); if (locals == NULL) return 0; if (opts & OPENSSL_INIT_THREAD_ASYNC) { -#ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: " - "marking thread for async\n"); -#endif + OSSL_TRACE(INIT, + "ossl_init_thread_start: " + "marking thread for async\n"); locals->async = 1; } if (opts & OPENSSL_INIT_THREAD_ERR_STATE) { -#ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: " - "marking thread for err_state\n"); -#endif + OSSL_TRACE(INIT, + "ossl_init_thread_start: " + "marking thread for err_state\n"); locals->err_state = 1; } + if (opts & OPENSSL_INIT_THREAD_RAND) { + OSSL_TRACE(INIT, + "ossl_init_thread_start: " + "marking thread for rand\n"); + locals->rand = 1; + } + return 1; } void OPENSSL_cleanup(void) { OPENSSL_INIT_STOP *currhandler, *lasthandler; + CRYPTO_THREAD_LOCAL key; + + /* + * TODO(3.0): This function needs looking at with a view to moving most/all + * of this into onfree handlers in OPENSSL_CTX. + */ /* If we've not been inited then no need to deinit */ if (!base_inited) @@ -412,6 +518,7 @@ void OPENSSL_cleanup(void) stop_handlers = NULL; CRYPTO_THREAD_lock_free(init_lock); + init_lock = NULL; /* * We assume we are single-threaded for this function, i.e. no race @@ -420,76 +527,70 @@ void OPENSSL_cleanup(void) #ifndef OPENSSL_NO_COMP if (zlib_inited) { -#ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " - "comp_zlib_cleanup_int()\n"); -#endif + OSSL_TRACE(INIT, "OPENSSL_cleanup: comp_zlib_cleanup_int()\n"); comp_zlib_cleanup_int(); } #endif if (async_inited) { -# ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " - "async_deinit()\n"); -# endif + OSSL_TRACE(INIT, "OPENSSL_cleanup: async_deinit()\n"); async_deinit(); } if (load_crypto_strings_inited) { -#ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " - "err_free_strings_int()\n"); -#endif + OSSL_TRACE(INIT, "OPENSSL_cleanup: err_free_strings_int()\n"); err_free_strings_int(); } - CRYPTO_THREAD_cleanup_local(&threadstopkey); + key = destructor_key.value; + destructor_key.sane = -1; + CRYPTO_THREAD_cleanup_local(&key); -#ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " - "rand_cleanup_int()\n"); - fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " - "conf_modules_free_int()\n"); -#ifndef OPENSSL_NO_ENGINE - fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " - "engine_cleanup_int()\n"); -#endif - fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " - "crypto_cleanup_all_ex_data_int()\n"); - fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " - "bio_sock_cleanup_int()\n"); - fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " - "bio_cleanup()\n"); - fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " - "evp_cleanup_int()\n"); - fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " - "obj_cleanup_int()\n"); - fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " - "err_cleanup()\n"); -#endif /* * Note that cleanup order is important: * - rand_cleanup_int could call an ENGINE's RAND cleanup function so * must be called before engine_cleanup_int() * - ENGINEs use CRYPTO_EX_DATA and therefore, must be cleaned up - * before the ex data handlers are wiped in CRYPTO_cleanup_all_ex_data(). + * before the ex data handlers are wiped during default openssl_ctx deinit. * - conf_modules_free_int() can end up in ENGINE code so must be called * before engine_cleanup_int() * - ENGINEs and additional EVP algorithms might use added OIDs names so * obj_cleanup_int() must be called last */ + OSSL_TRACE(INIT, "OPENSSL_cleanup: rand_cleanup_int()\n"); rand_cleanup_int(); + + OSSL_TRACE(INIT, "OPENSSL_cleanup: conf_modules_free_int()\n"); conf_modules_free_int(); + #ifndef OPENSSL_NO_ENGINE + OSSL_TRACE(INIT, "OPENSSL_cleanup: engine_cleanup_int()\n"); engine_cleanup_int(); #endif - crypto_cleanup_all_ex_data_int(); + OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_store_cleanup_int()\n"); + ossl_store_cleanup_int(); + + OSSL_TRACE(INIT, "OPENSSL_cleanup: openssl_ctx_default_deinit()\n"); + openssl_ctx_default_deinit(); + + OSSL_TRACE(INIT, "OPENSSL_cleanup: bio_cleanup()\n"); bio_cleanup(); + + OSSL_TRACE(INIT, "OPENSSL_cleanup: evp_cleanup_int()\n"); evp_cleanup_int(); + + OSSL_TRACE(INIT, "OPENSSL_cleanup: obj_cleanup_int()\n"); obj_cleanup_int(); + + OSSL_TRACE(INIT, "OPENSSL_cleanup: err_int()\n"); err_cleanup(); + OSSL_TRACE(INIT, "OPENSSL_cleanup: CRYPTO_secure_malloc_done()\n"); + CRYPTO_secure_malloc_done(); + + OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_trace_cleanup()\n"); + ossl_trace_cleanup(); + base_inited = 0; } @@ -500,27 +601,55 @@ void OPENSSL_cleanup(void) */ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) { - static int stoperrset = 0; + /* + * TODO(3.0): This function needs looking at with a view to moving most/all + * of this into OPENSSL_CTX. + */ if (stopped) { - if (!stoperrset) { - /* - * We only ever set this once to avoid getting into an infinite - * loop where the error system keeps trying to init and fails so - * sets an error etc - */ - stoperrset = 1; + if (!(opts & OPENSSL_INIT_BASE_ONLY)) CRYPTOerr(CRYPTO_F_OPENSSL_INIT_CRYPTO, ERR_R_INIT_FAIL); - } return 0; } - if (!base_inited && !RUN_ONCE(&base, ossl_init_base)) + /* + * When the caller specifies OPENSSL_INIT_BASE_ONLY, that should be the + * *only* option specified. With that option we return immediately after + * doing the requested limited initialization. Note that + * err_shelve_state() called by us via ossl_init_load_crypto_nodelete() + * re-enters OPENSSL_init_crypto() with OPENSSL_INIT_BASE_ONLY, but with + * base already initialized this is a harmless NOOP. + * + * If we remain the only caller of err_shelve_state() the recursion should + * perhaps be removed, but if in doubt, it can be left in place. + */ + if (!RUN_ONCE(&base, ossl_init_base)) + return 0; + + if (opts & OPENSSL_INIT_BASE_ONLY) + return 1; + + /* + * Now we don't always set up exit handlers, the INIT_BASE_ONLY calls + * should not have the side-effect of setting up exit handlers, and + * therefore, this code block is below the INIT_BASE_ONLY-conditioned early + * return above. + */ + if ((opts & OPENSSL_INIT_NO_ATEXIT) != 0) { + if (!RUN_ONCE_ALT(®ister_atexit, ossl_init_no_register_atexit, + ossl_init_register_atexit)) + return 0; + } else if (!RUN_ONCE(®ister_atexit, ossl_init_register_atexit)) { + return 0; + } + + if (!RUN_ONCE(&load_crypto_nodelete, ossl_init_load_crypto_nodelete)) return 0; if ((opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS) - && !RUN_ONCE(&load_crypto_strings, - ossl_init_no_load_crypto_strings)) + && !RUN_ONCE_ALT(&load_crypto_strings, + ossl_init_no_load_crypto_strings, + ossl_init_load_crypto_strings)) return 0; if ((opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS) @@ -528,7 +657,8 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) return 0; if ((opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS) - && !RUN_ONCE(&add_all_ciphers, ossl_init_no_add_algs)) + && !RUN_ONCE_ALT(&add_all_ciphers, ossl_init_no_add_all_ciphers, + ossl_init_add_all_ciphers)) return 0; if ((opts & OPENSSL_INIT_ADD_ALL_CIPHERS) @@ -536,24 +666,48 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) return 0; if ((opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS) - && !RUN_ONCE(&add_all_digests, ossl_init_no_add_algs)) + && !RUN_ONCE_ALT(&add_all_digests, ossl_init_no_add_all_digests, + ossl_init_add_all_digests)) return 0; if ((opts & OPENSSL_INIT_ADD_ALL_DIGESTS) && !RUN_ONCE(&add_all_digests, ossl_init_add_all_digests)) return 0; + if ((opts & OPENSSL_INIT_NO_ADD_ALL_MACS) + && !RUN_ONCE_ALT(&add_all_macs, ossl_init_no_add_all_macs, + ossl_init_add_all_macs)) + return 0; + + if ((opts & OPENSSL_INIT_ADD_ALL_MACS) + && !RUN_ONCE(&add_all_macs, ossl_init_add_all_macs)) + return 0; + + if ((opts & OPENSSL_INIT_NO_ADD_ALL_KDFS) + && !RUN_ONCE_ALT(&add_all_kdfs, ossl_init_no_add_all_kdfs, + ossl_init_add_all_kdfs)) + return 0; + + if ((opts & OPENSSL_INIT_ADD_ALL_KDFS) + && !RUN_ONCE(&add_all_kdfs, ossl_init_add_all_kdfs)) + return 0; + + if ((opts & OPENSSL_INIT_ATFORK) + && !openssl_init_fork_handlers()) + return 0; + if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG) - && !RUN_ONCE(&config, ossl_init_no_config)) + && !RUN_ONCE_ALT(&config, ossl_init_no_config, ossl_init_config)) return 0; if (opts & OPENSSL_INIT_LOAD_CONFIG) { int ret; CRYPTO_THREAD_write_lock(init_lock); - appname = (settings == NULL) ? NULL : settings->appname; + conf_settings = settings; ret = RUN_ONCE(&config, ossl_init_config); + conf_settings = NULL; CRYPTO_THREAD_unlock(init_lock); - if (!ret) + if (ret <= 0) return 0; } @@ -565,12 +719,6 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) if ((opts & OPENSSL_INIT_ENGINE_OPENSSL) && !RUN_ONCE(&engine_openssl, ossl_init_engine_openssl)) return 0; -# if !defined(OPENSSL_NO_HW) && \ - (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(HAVE_CRYPTODEV)) - if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV) - && !RUN_ONCE(&engine_cryptodev, ossl_init_engine_cryptodev)) - return 0; -# endif # ifndef OPENSSL_NO_RDRAND if ((opts & OPENSSL_INIT_ENGINE_RDRAND) && !RUN_ONCE(&engine_rdrand, ossl_init_engine_rdrand)) @@ -580,7 +728,12 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) && !RUN_ONCE(&engine_dynamic, ossl_init_engine_dynamic)) return 0; # ifndef OPENSSL_NO_STATIC_ENGINE -# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) +# ifndef OPENSSL_NO_DEVCRYPTOENG + if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV) + && !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto)) + return 0; +# endif +# if !defined(OPENSSL_NO_PADLOCKENG) if ((opts & OPENSSL_INIT_ENGINE_PADLOCK) && !RUN_ONCE(&engine_padlock, ossl_init_engine_padlock)) return 0; @@ -616,7 +769,8 @@ int OPENSSL_atexit(void (*handler)(void)) { OPENSSL_INIT_STOP *newhand; -#if !defined(OPENSSL_NO_DSO) && !defined(OPENSSL_USE_NODELETE) +#if !defined(OPENSSL_USE_NODELETE)\ + && !defined(OPENSSL_NO_PINSHARED) { union { void *sym; @@ -624,7 +778,7 @@ int OPENSSL_atexit(void (*handler)(void)) } handlersym; handlersym.func = handler; -# ifdef DSO_WIN32 +# if defined(DSO_WIN32) && !defined(_WIN32_WCE) { HMODULE handle = NULL; BOOL ret; @@ -640,18 +794,22 @@ int OPENSSL_atexit(void (*handler)(void)) if (!ret) return 0; } -# else +# elif !defined(DSO_NONE) /* * Deliberately leak a reference to the handler. This will force the * library/code containing the handler to remain loaded until we run the * atexit handler. If -znodelete has been used then this is - * unneccessary. + * unnecessary. */ { DSO *dso = NULL; ERR_set_mark(); dso = DSO_dsobyaddr(handlersym.sym, DSO_FLAG_NO_UNLOAD_ON_FREE); + /* See same code above in ossl_init_base() for an explanation. */ + OSSL_TRACE1(INIT, + "atexit: obtained DSO reference? %s\n", + (dso == NULL ? "No!" : "Yes.")); DSO_free(dso); ERR_pop_to_mark(); } @@ -659,9 +817,10 @@ int OPENSSL_atexit(void (*handler)(void)) } #endif - newhand = OPENSSL_malloc(sizeof(*newhand)); - if (newhand == NULL) + if ((newhand = OPENSSL_malloc(sizeof(*newhand))) == NULL) { + CRYPTOerr(CRYPTO_F_OPENSSL_ATEXIT, ERR_R_MALLOC_FAILURE); return 0; + } newhand->handler = handler; newhand->next = stop_handlers; @@ -669,3 +828,30 @@ int OPENSSL_atexit(void (*handler)(void)) return 1; } + +#ifdef OPENSSL_SYS_UNIX +/* + * The following three functions are for OpenSSL developers. This is + * where we set/reset state across fork (called via pthread_atfork when + * it exists, or manually by the application when it doesn't). + * + * WARNING! If you put code in either OPENSSL_fork_parent or + * OPENSSL_fork_child, you MUST MAKE SURE that they are async-signal- + * safe. See this link, for example: + * http://man7.org/linux/man-pages/man7/signal-safety.7.html + */ + +void OPENSSL_fork_prepare(void) +{ +} + +void OPENSSL_fork_parent(void) +{ +} + +void OPENSSL_fork_child(void) +{ + rand_fork(); + /* TODO(3.0): Inform all providers about a fork event */ +} +#endif