diff --git a/Configure b/Configure index 97df83c0db..ba21c4f85f 100755 --- a/Configure +++ b/Configure @@ -227,6 +227,7 @@ my @disablables = ( "aes", "asm", "async", + "autoalginit", "bf", "camellia", "capieng", @@ -741,7 +742,8 @@ foreach (sort (keys %disabled)) my ($ALGO, $algo); ($ALGO = $algo = $_) =~ tr/[\-a-z]/[_A-Z]/; - if (/^asm$/ || /^err$/ || /^hw$/ || /^hw-/ || /^async$/) + if (/^asm$/ || /^err$/ || /^hw$/ || /^hw-/ || /^async$/ + || /^autoalginit/) { push @{$config{openssl_other_defines}}, "OPENSSL_NO_$ALGO"; print " OPENSSL_NO_$ALGO"; diff --git a/crypto/Makefile.in b/crypto/Makefile.in index 8d69c28830..de98f4a1a7 100644 --- a/crypto/Makefile.in +++ b/crypto/Makefile.in @@ -34,10 +34,10 @@ LIB= $(TOP)/libcrypto.a SHARED_LIB= libcrypto$(SHLIB_EXT) LIBSRC= cryptlib.c mem.c mem_clr.c mem_dbg.c cversion.c ex_data.c cpt_err.c \ ebcdic.c uid.c o_time.c o_str.c o_dir.c thr_id.c lock.c fips_ers.c \ - o_init.c o_fips.c mem_sec.c + o_init.c o_fips.c mem_sec.c init.c LIBOBJ= cryptlib.o mem.o mem_dbg.o cversion.o ex_data.o cpt_err.o \ ebcdic.o uid.o o_time.o o_str.o o_dir.o thr_id.o lock.o fips_ers.o \ - o_init.o o_fips.o mem_sec.o $(CPUID_OBJ) + o_init.o o_fips.o mem_sec.o init.o $(CPUID_OBJ) SRC= $(LIBSRC) diff --git a/crypto/include/internal/cryptlib_int.h b/crypto/include/internal/cryptlib_int.h new file mode 100644 index 0000000000..2906921a09 --- /dev/null +++ b/crypto/include/internal/cryptlib_int.h @@ -0,0 +1,79 @@ +/* + * Written by Matt Caswell for the OpenSSL project. + */ +/* ==================================================================== + * Copyright (c) 2016 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +/* This file is not scanned by mkdef.pl, whereas cryptlib.h is */ + +struct thread_local_inits_st { + int async; + int err_state; +}; +void *ossl_init_get_thread_local(int alloc); +int ossl_init_thread_start(uint64_t opts); +void ossl_init_thread_stop(struct thread_local_inits_st *locals); +/* + * OPENSSL_INIT flags. The primary list of these is in crypto.h. Flags below + * are those ommitted from crypto.h because they are "reserverd for internal + * use". + */ +# define OPENSSL_INIT_ZLIB 0x010000 + +/* OPENSSL_INIT_THREAD flags */ +# define OPENSSL_INIT_THREAD_ASYNC 0x01 +# define OPENSSL_INIT_THREAD_ERR_STATE 0x02 + diff --git a/crypto/init.c b/crypto/init.c new file mode 100644 index 0000000000..8950ff6797 --- /dev/null +++ b/crypto/init.c @@ -0,0 +1,775 @@ +/* + * Written by Matt Caswell for the OpenSSL project. + */ +/* ==================================================================== + * Copyright (c) 2016 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#if defined(OPENSSL_SYS_WINDOWS) && !defined(_WIN32_WINNT) +/* + * We default to requiring Windows Vista, Windows Server 2008 or later. We can + * support lower versions if _WIN32_WINNT is explicity defined to something + * less + */ +# define _WIN32_WINNT 0x0600 +#endif + +#include +#include +#include +#if 0 +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#if 0 +#include +#endif +#include + +/* Implement "once" functionality */ +#if !defined(OPENSSL_THREADS) +typedef int OPENSSL_INIT_ONCE; +# define OPENSSL_INIT_ONCE_STATIC_INIT 0 +# define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) (*(once) = 0) + +static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void)) +{ + if (*once == OPENSSL_INIT_ONCE_STATIC_INIT) { + *once = 1; + init(); + } +} + +static int ossl_init_setup_thread_stop(void) +{ + /* + * There are no threads to stop. Do nothing. + */ + return 1; +} + +static void ossl_init_thread_stop_cleanup(void) +{ +} + +static struct thread_local_inits_st *local = NULL; +void *ossl_init_get_thread_local(int alloc) +{ + if (local == NULL && alloc) + local = OPENSSL_zalloc(sizeof(*local)); + return local; +} + +#elif defined(OPENSSL_SYS_WINDOWS) + +# include + +# if _WIN32_WINNT < 0x0600 + +/* + * Versions before 0x0600 (Windows Vista, Windows Server 2008 or later) do not + * have InitOnceExecuteOnce, so we fall back to using a spinlock instead. + */ +typedef LONG OPENSSL_INIT_ONCE; +# define OPENSSL_INIT_ONCE_STATIC_INIT 0 +# define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) (*(once) = 0) + +# define ONCE_UNINITED 0 +# define ONCE_ININIT 1 +# define ONCE_DONE 2 + +static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void)) +{ + LONG volatile *lock = (LONG *)once; + LONG result; + + if (*lock == ONCE_DONE) + return; + + do { + result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED); + if (result == ONCE_UNINITED) { + init(); + *lock = ONCE_DONE; + return; + } + } while (result == ONCE_ININIT); +} + +# else + +typedef INIT_ONCE OPENSSL_INIT_ONCE; +# define OPENSSL_INIT_ONCE_STATIC_INIT INIT_ONCE_STATIC_INIT +# define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) \ + InitOnceInitialize((PINIT_ONCE)(once)) + +static BOOL CALLBACK once_cb(PINIT_ONCE once, PVOID initfp, PVOID *unused) +{ + void (*init)(void) = initfp; + + init(); + + return TRUE; +} + +static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void)) +{ + InitOnceExecuteOnce((INIT_ONCE *)once, once_cb, init, NULL); +} +# endif + +DWORD threadstopkey = TLS_OUT_OF_INDEXES; + +static int ossl_init_setup_thread_stop(void) +{ + /* + * We use a dummy thread local key here. We use the destructor to detect + * when the thread is going to stop + */ + threadstopkey = TlsAlloc(); + if (threadstopkey == TLS_OUT_OF_INDEXES) + return 0; + + return 1; +} + +static void ossl_init_thread_stop_cleanup(void) +{ + if (threadstopkey != TLS_OUT_OF_INDEXES) { + TlsFree(threadstopkey); + } +} + +void *ossl_init_get_thread_local(int alloc) +{ + struct thread_local_inits_st *local = TlsGetValue(threadstopkey); + + if (local == NULL && alloc) { + local = OPENSSL_zalloc(sizeof *local); + TlsSetValue(threadstopkey, local); + } + + return local; +} + +#else /* pthreads */ +# include + +pthread_key_t threadstopkey; + +typedef pthread_once_t OPENSSL_INIT_ONCE; +# define OPENSSL_INIT_ONCE_STATIC_INIT PTHREAD_ONCE_INIT +# define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) (*(once) = PTHREAD_ONCE_INIT) + +static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void)) +{ + pthread_once(once, init); +} + +static void ossl_init_thread_stop_wrap(void *local) +{ + ossl_init_thread_stop((struct thread_local_inits_st *)local); +} + +static int ossl_init_setup_thread_stop(void) +{ + /* + * We use a dummy thread local key here. We use the destructor to detect + * when the thread is going to stop + */ + return (pthread_key_create(&threadstopkey, + ossl_init_thread_stop_wrap) == 0); +} + +static void ossl_init_thread_stop_cleanup(void) +{ +} + +void *ossl_init_get_thread_local(int alloc) +{ + struct thread_local_inits_st *local = pthread_getspecific(threadstopkey); + + if (local == NULL && alloc) { + local = OPENSSL_zalloc(sizeof *local); + pthread_setspecific(threadstopkey, local); + } + + return local; +} + +#endif + +struct ossl_init_stop_st { + void (*handler)(void); + OPENSSL_INIT_STOP *next; +}; + +static OPENSSL_INIT_STOP *stop_handlers = NULL; + +static OPENSSL_INIT_ONCE base = OPENSSL_INIT_ONCE_STATIC_INIT; +static int base_inited = 0; +static void ossl_init_base(void) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_base: Setting up stop handlers\n"); +#endif + ossl_init_setup_thread_stop(); + atexit(OPENSSL_INIT_library_stop); + OPENSSL_cpuid_setup(); + base_inited = 1; +} + +static OPENSSL_INIT_ONCE load_crypto_strings = OPENSSL_INIT_ONCE_STATIC_INIT; +static int load_crypto_strings_inited = 0; +static void ossl_init_no_load_crypto_strings(void) +{ + /* Do nothing in this case */ + return; +} + +static void ossl_init_load_crypto_strings(void) +{ +#ifndef OPENSSL_NO_ERR +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_strings: " + "err_load_crypto_strings_intern()\n"); +# endif +#if 0 + err_load_crypto_strings_intern(); +#endif +#endif + load_crypto_strings_inited = 1; +} + +static OPENSSL_INIT_ONCE add_all_ciphers = OPENSSL_INIT_ONCE_STATIC_INIT; +static void ossl_init_add_all_ciphers(void) +{ + /* + * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time + * 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_internal()\n"); +# endif +#if 0 + openssl_add_all_ciphers_internal(); +#endif +# ifndef OPENSSL_NO_ENGINE +# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV) + ENGINE_setup_bsd_cryptodev(); +# endif +# endif +#endif +} + +static OPENSSL_INIT_ONCE add_all_digests = OPENSSL_INIT_ONCE_STATIC_INIT; +static void ossl_init_add_all_digests(void) +{ + /* + * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time + * 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_internal()\n"); +# endif +#if 0 + openssl_add_all_digests_internal(); +#endif +# ifndef OPENSSL_NO_ENGINE +# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV) + ENGINE_setup_bsd_cryptodev(); +# endif +# endif +#endif +} + +static void ossl_init_no_add_algs(void) +{ + /* Do nothing */ + return; +} + +static OPENSSL_INIT_ONCE config = OPENSSL_INIT_ONCE_STATIC_INIT; +static int config_inited = 0; +static const char *config_filename; +static void ossl_init_config(void) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, + "OPENSSL_INIT: ossl_init_config: openssl_config_internal(%s)\n", + config_filename==NULL?"NULL":config_filename); +#endif +#if 0 + openssl_config_internal(config_filename); +#endif + config_inited = 1; +} +static void ossl_init_no_config(void) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, + "OPENSSL_INIT: ossl_init_config: openssl_no_config_internal()\n"); +#endif +#if 0 + openssl_no_config_internal(); +#endif + config_inited = 1; +} + +static OPENSSL_INIT_ONCE async = OPENSSL_INIT_ONCE_STATIC_INIT; +static int async_inited = 0; +static void ossl_init_async(void) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_async: async_init()\n"); +#endif +#if 0 + async_init(); +#endif + async_inited = 1; +} + +#ifndef OPENSSL_NO_ENGINE +static int engine_inited = 0; +static OPENSSL_INIT_ONCE engine_openssl = OPENSSL_INIT_ONCE_STATIC_INIT; +static void ossl_init_engine_openssl(void) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_openssl: " + "engine_load_openssl_internal()\n"); +# endif +#if 0 + engine_load_openssl_internal(); +#endif + engine_inited = 1; +} +# if !defined(OPENSSL_NO_HW) && \ + (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)) +static OPENSSL_INIT_ONCE engine_cryptodev = OPENSSL_INIT_ONCE_STATIC_INIT; +static void ossl_init_engine_cryptodev(void) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_cryptodev: " + "engine_load_cryptodev_internal()\n"); +# endif +#if 0 + engine_load_cryptodev_internal(); +#endif + engine_inited = 1; +} +# endif + +# ifndef OPENSSL_NO_RDRAND +static OPENSSL_INIT_ONCE engine_rdrand = OPENSSL_INIT_ONCE_STATIC_INIT; +static void ossl_init_engine_rdrand(void) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_rdrand: " + "engine_load_rdrand_internal()\n"); +# endif +#if 0 + engine_load_rdrand_internal(); +#endif + engine_inited = 1; +} +# endif +static OPENSSL_INIT_ONCE engine_dynamic = OPENSSL_INIT_ONCE_STATIC_INIT; +static void ossl_init_engine_dynamic(void) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_dynamic: " + "engine_load_dynamic_internal()\n"); +# endif +#if 0 + engine_load_dynamic_internal(); +#endif + engine_inited = 1; +} +# ifndef OPENSSL_NO_STATIC_ENGINE +# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) +static OPENSSL_INIT_ONCE engine_padlock = OPENSSL_INIT_ONCE_STATIC_INIT; +static void ossl_init_engine_padlock(void) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_padlock: " + "engine_load_padlock_internal()\n"); +# endif +#if 0 + engine_load_padlock_internal(); +#endif + engine_inited = 1; +} +# endif +# if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG) +static OPENSSL_INIT_ONCE engine_capi = OPENSSL_INIT_ONCE_STATIC_INIT; +static void ossl_init_engine_capi(void) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_capi: " + "engine_load_capi_internal()\n"); +# endif +#if 0 + engine_load_capi_internal(); +#endif + engine_inited = 1; +} +# endif +static OPENSSL_INIT_ONCE engine_dasync = OPENSSL_INIT_ONCE_STATIC_INIT; +static void ossl_init_engine_dasync(void) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_dasync: " + "engine_load_dasync_internal()\n"); +# endif +#if 0 + engine_load_dasync_internal(); +#endif + engine_inited = 1; +} +# endif +#endif + +static OPENSSL_INIT_ONCE zlib = OPENSSL_INIT_ONCE_STATIC_INIT; +static int zlib_inited = 0; +static void ossl_init_zlib(void) +{ + /* Do nothing - we need to know about this for the later cleanup */ + zlib_inited = 1; +} + +void ossl_init_thread_stop(struct thread_local_inits_st *locals) +{ + /* Can't do much about this */ + if (locals == NULL) + return; + + if (locals->async) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: " + "ASYNC_cleanup_thread()\n"); +#endif + ASYNC_cleanup_thread(); + } + + if (locals->err_state) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: " + "ERR_remove_thread_state(NULL)\n"); +#endif + ERR_remove_thread_state(NULL); + } + + OPENSSL_free(locals); + ossl_init_thread_stop_cleanup(); +} + +int ossl_init_thread_start(uint64_t opts) +{ + struct thread_local_inits_st *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 + 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 + locals->err_state = 1; + } + + return 1; +} + +void OPENSSL_INIT_library_stop(void) +{ + OPENSSL_INIT_STOP *currhandler, *lasthandler; + + /* + * Thread stop may not get automatically called by the thread library for + * the very last thread in some situations, so call it directly. + */ + ossl_init_thread_stop(ossl_init_get_thread_local(0)); + + currhandler = stop_handlers; + while (currhandler != NULL) { + currhandler->handler(); + lasthandler = currhandler; + currhandler = currhandler->next; + OPENSSL_free(lasthandler); + } + stop_handlers = NULL; + /* + * We assume we are single-threaded for this function, i.e. no race + * conditions for the various "*_inited" vars below. + */ + + if (zlib_inited) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: " + "COMP_zlib_cleanup()\n"); +#endif + COMP_zlib_cleanup(); + zlib_inited = 0; + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&zlib); + } + +#ifndef OPENSSL_NO_ENGINE + if (engine_inited) { +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: " + "ENGINE_cleanup()\n"); +# endif + ENGINE_cleanup(); + engine_inited = 0; + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_openssl); +# if !defined(OPENSSL_NO_HW) && \ + (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)) + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_cryptodev); +# endif +# ifndef OPENSSL_NO_RDRAND + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_rdrand); +# endif + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_dynamic); +# ifndef OPENSSL_NO_STATIC_ENGINE +# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_padlock); +# endif +# if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG) + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_capi); +# endif + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_dasync); +# endif + } +#endif + + async_inited = 0; + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&async); + + config_inited = 0; + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&config); + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&add_all_ciphers); + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&add_all_digests); + + if (load_crypto_strings_inited) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: " + "ERR_free_strings()\n"); +#endif + ERR_free_strings(); + load_crypto_strings_inited = 0; + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&load_crypto_strings); + } + + if (base_inited) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: " + "CRYPTO_cleanup_all_ex_data()\n"); + fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: " + "EVP_cleanup()\n"); + fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: " + "CONF_modules_free()\n"); + fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: " + "RAND_cleanup()\n"); +#endif + CRYPTO_cleanup_all_ex_data(); + EVP_cleanup(); + CONF_modules_free(); + RAND_cleanup(); + base_inited = 0; + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&base); + } +} + +static const OPENSSL_INIT_SETTINGS *ossl_init_get_setting( + const OPENSSL_INIT_SETTINGS *settings, int name) +{ + if (settings == NULL) + return NULL; + + while (settings->name != OPENSSL_INIT_SET_END) { + if (settings->name == name) + return settings; + settings++; + } + + return NULL; +} + +/* + * If this function is called with a non NULL settings value then it must be + * called prior to any threads making calls to any OpenSSL functions, + * i.e. passing a non-null settings value is assumed to be single-threaded. + */ +void OPENSSL_INIT_crypto_library_start(uint64_t opts, + const OPENSSL_INIT_SETTINGS *settings) +{ + ossl_init_once_run(&base, ossl_init_base); + + if (opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS) + ossl_init_once_run(&load_crypto_strings, + ossl_init_no_load_crypto_strings); + + if (opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS) + ossl_init_once_run(&load_crypto_strings, ossl_init_load_crypto_strings); + + if (opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS) + ossl_init_once_run(&add_all_ciphers, ossl_init_no_add_algs); + + if (opts & OPENSSL_INIT_ADD_ALL_CIPHERS) + ossl_init_once_run(&add_all_ciphers, ossl_init_add_all_ciphers); + + if (opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS) + ossl_init_once_run(&add_all_digests, ossl_init_no_add_algs); + + if (opts & OPENSSL_INIT_ADD_ALL_DIGESTS) + ossl_init_once_run(&add_all_digests, ossl_init_add_all_digests); + + if (opts & OPENSSL_INIT_NO_LOAD_CONFIG) { + ossl_init_once_run(&config, ossl_init_no_config); + } + + if (opts & OPENSSL_INIT_LOAD_CONFIG) { + if (settings != NULL) { + const OPENSSL_INIT_SETTINGS *curr; + curr = ossl_init_get_setting(settings, + OPENSSL_INIT_SET_CONF_FILENAME); + config_filename = curr == NULL ? NULL : curr->value.type_string; + } + ossl_init_once_run(&config, ossl_init_config); + } + + if (opts & OPENSSL_INIT_ASYNC) { + ossl_init_once_run(&async, ossl_init_async); + } + +#ifndef OPENSSL_NO_ENGINE + if (opts & OPENSSL_INIT_ENGINE_OPENSSL) { + ossl_init_once_run(&engine_openssl, ossl_init_engine_openssl); + } +# if !defined(OPENSSL_NO_HW) && \ + (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)) + if (opts & OPENSSL_INIT_ENGINE_CRYPTODEV) { + ossl_init_once_run(&engine_cryptodev, ossl_init_engine_cryptodev); + } +# endif +# ifndef OPENSSL_NO_RDRAND + if (opts & OPENSSL_INIT_ENGINE_RDRAND) { + ossl_init_once_run(&engine_rdrand, ossl_init_engine_rdrand); + } +# endif + if (opts & OPENSSL_INIT_ENGINE_DYNAMIC) { + ossl_init_once_run(&engine_dynamic, ossl_init_engine_dynamic); + } +# ifndef OPENSSL_NO_STATIC_ENGINE +# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) + if (opts & OPENSSL_INIT_ENGINE_PADLOCK) { + ossl_init_once_run(&engine_padlock, ossl_init_engine_padlock); + } +# endif +# if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG) + if (opts & OPENSSL_INIT_ENGINE_CAPI) { + ossl_init_once_run(&engine_capi, ossl_init_engine_capi); + } +# endif + if (opts & OPENSSL_INIT_ENGINE_DASYNC) { + ossl_init_once_run(&engine_dasync, ossl_init_engine_dasync); + } +# endif + if (opts & (OPENSSL_INIT_ENGINE_ALL_BUILTIN + | OPENSSL_INIT_ENGINE_DASYNC | OPENSSL_INIT_ENGINE_OPENSSL)) { + ENGINE_register_all_complete(); + } +#endif + + if (opts & OPENSSL_INIT_ZLIB) { + ossl_init_once_run(&zlib, ossl_init_zlib); + } +} + +int OPENSSL_INIT_register_stop_handler(void (*handler)(void)) +{ + OPENSSL_INIT_STOP *newhand; + + newhand = OPENSSL_malloc(sizeof(*newhand)); + if (newhand == NULL) + return 0; + + newhand->handler = handler; + newhand->next = stop_handlers; + stop_handlers = newhand; + + return 1; +} + + diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h index 1251aa13d9..dd1089dc6c 100644 --- a/include/openssl/crypto.h +++ b/include/openssl/crypto.h @@ -546,6 +546,61 @@ int CRYPTO_memcmp(const volatile void * volatile in_a, const volatile void * volatile in_b, size_t len); +/* Standard initialisation options */ +# define OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS 0x000001 +# define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x000002 +# define OPENSSL_INIT_ADD_ALL_CIPHERS 0x000004 +# define OPENSSL_INIT_ADD_ALL_DIGESTS 0x000008 +# define OPENSSL_INIT_NO_ADD_ALL_CIPHERS 0x000010 +# define OPENSSL_INIT_NO_ADD_ALL_DIGESTS 0x000020 +# define OPENSSL_INIT_LOAD_CONFIG 0x000040 +# define OPENSSL_INIT_NO_LOAD_CONFIG 0x000080 +# define OPENSSL_INIT_ASYNC 0x000100 +# define OPENSSL_INIT_ENGINE_RDRAND 0x000200 +# define OPENSSL_INIT_ENGINE_DYNAMIC 0x000400 +# define OPENSSL_INIT_ENGINE_OPENSSL 0x000800 +# define OPENSSL_INIT_ENGINE_CRYPTODEV 0x001000 +# define OPENSSL_INIT_ENGINE_CAPI 0x002000 +# define OPENSSL_INIT_ENGINE_PADLOCK 0x004000 +# define OPENSSL_INIT_ENGINE_DASYNC 0x008000 +/* OPENSSL_INIT flag 0x010000 reserved for internal use */ +/* Max OPENSSL_INIT flag value is 0x80000000 */ + +/* openssl and dasync not counted as builtin */ +# define OPENSSL_INIT_ENGINE_ALL_BUILTIN \ + (OPENSSL_INIT_ENGINE_RDRAND | OPENSSL_INIT_ENGINE_DYNAMIC \ + | OPENSSL_INIT_ENGINE_CRYPTODEV | OPENSSL_INIT_ENGINE_CAPI | \ + OPENSSL_INIT_ENGINE_PADLOCK) + + + +/* Optional settings for initialisation */ +# define OPENSSL_INIT_SET_END 0 +# define OPENSSL_INIT_SET_CONF_FILENAME 1 + +typedef struct ossl_init_settings_st { + int name; + union { + int type_int; + long type_long; + int32_t type_int32_t; + uint32_t type_uint32_t; + int64_t type_int64_t; + uint64_t type_uint64_t; + size_t type_size_t; + const char *type_string; + void *type_void_ptr; + } value; +} OPENSSL_INIT_SETTINGS; + +typedef struct ossl_init_stop_st OPENSSL_INIT_STOP; + +/* Library initialisation functions */ +void OPENSSL_INIT_library_stop(void); +void OPENSSL_INIT_crypto_library_start(uint64_t opts, + const OPENSSL_INIT_SETTINGS *settings); +int OPENSSL_INIT_register_stop_handler(void (*handler)(void)); + /* BEGIN ERROR CODES */ /* * The following lines are auto generated by the script mkerr.pl. Any changes diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 7bc46c5f78..ac61ccbdbb 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -1927,6 +1927,15 @@ int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (SSL *s, void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex); __owur void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx); +#define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x0100000000 +#define OPENSSL_INIT_LOAD_SSL_STRINGS 0x0200000000 + +#define OPENSSL_INIT_SSL_DEFAULT \ + (OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS) + +void OPENSSL_INIT_ssl_library_start(uint64_t opts, + const OPENSSL_INIT_SETTINGS *settings); + # ifndef OPENSSL_NO_UNIT_TEST __owur const struct openssl_ssl_test_functions *SSL_test_functions(void); # endif diff --git a/ssl/Makefile.in b/ssl/Makefile.in index 586d287944..f9beee4c15 100644 --- a/ssl/Makefile.in +++ b/ssl/Makefile.in @@ -25,7 +25,7 @@ LIBSRC= \ statem/statem_dtls.c d1_srtp.c \ ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \ ssl_ciph.c ssl_stat.c ssl_rsa.c \ - ssl_asn1.c ssl_txt.c ssl_algs.c ssl_conf.c ssl_mcnf.c \ + ssl_asn1.c ssl_txt.c ssl_algs.c ssl_init.c ssl_conf.c ssl_mcnf.c \ bio_ssl.c ssl_err.c t1_reneg.c tls_srp.c t1_trce.c ssl_utst.c \ record/ssl3_buffer.c record/ssl3_record.c record/dtls1_bitmap.c \ statem/statem.c @@ -38,7 +38,7 @@ LIBOBJ= \ statem/statem_dtls.o d1_srtp.o\ ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \ ssl_ciph.o ssl_stat.o ssl_rsa.o \ - ssl_asn1.o ssl_txt.o ssl_algs.o ssl_conf.o ssl_mcnf.o \ + ssl_asn1.o ssl_txt.o ssl_algs.o ssl_init.o ssl_conf.o ssl_mcnf.o \ bio_ssl.o ssl_err.o t1_reneg.o tls_srp.o t1_trce.o ssl_utst.o \ record/ssl3_buffer.o record/ssl3_record.o record/dtls1_bitmap.o \ statem/statem.o diff --git a/ssl/ssl_init.c b/ssl/ssl_init.c new file mode 100644 index 0000000000..f1014135a1 --- /dev/null +++ b/ssl/ssl_init.c @@ -0,0 +1,320 @@ +/* + * Written by Matt Caswell for the OpenSSL project. + */ +/* ==================================================================== + * Copyright (c) 2016 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#if defined(OPENSSL_SYS_WINDOWS) && !defined(_WIN32_WINNT) +/* + * We default to requiring Windows Vista, Windows Server 2008 or later. We can + * support lower versions if _WIN32_WINNT is explicity defined to something + * less + */ +# define _WIN32_WINNT 0x0600 +#endif + +#include +#include +#include "ssl_locl.h" + +/* Implement "once" functionality */ +#if !defined(OPENSSL_THREADS) +typedef int OPENSSL_INIT_ONCE; +# define OPENSSL_INIT_ONCE_STATIC_INIT 0 +# define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) (*(once) = 0) + +static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void)) +{ + if (*once == OPENSSL_INIT_ONCE_STATIC_INIT) { + *once = 1; + init(); + } +} +#elif defined(OPENSSL_SYS_WINDOWS) +# include + +# if _WIN32_WINNT < 0x0600 + +/* + * Versions before 0x0600 (Windows Vista, Windows Server 2008 or later) do not + * have InitOnceExecuteOnce, so we fall back to using a spinlock instead. + */ +typedef LONG OPENSSL_INIT_ONCE; +# define OPENSSL_INIT_ONCE_STATIC_INIT 0 +# define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) (*(once) = 0) + +# define ONCE_UNINITED 0 +# define ONCE_ININIT 1 +# define ONCE_DONE 2 + +static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void)) +{ + LONG volatile *lock = (LONG *)once; + LONG result; + + if (*lock == ONCE_DONE) + return; + + do { + result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED); + if (result == ONCE_UNINITED) { + init(); + *lock = ONCE_DONE; + return; + } + } while (result == ONCE_ININIT); +} + +# else + +typedef INIT_ONCE OPENSSL_INIT_ONCE; +# define OPENSSL_INIT_ONCE_STATIC_INIT INIT_ONCE_STATIC_INIT +# define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) \ + InitOnceInitialize((PINIT_ONCE)(once)) + +static BOOL CALLBACK once_cb(PINIT_ONCE once, PVOID initfp, PVOID *unused) +{ + void (*init)(void) = initfp; + + init(); + + return TRUE; +} + +static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void)) +{ + InitOnceExecuteOnce((INIT_ONCE *)once, once_cb, init, NULL); +} +# endif +#else /* pthreads */ +# include + +typedef pthread_once_t OPENSSL_INIT_ONCE; +# define OPENSSL_INIT_ONCE_STATIC_INIT PTHREAD_ONCE_INIT +# define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) (*(once) = PTHREAD_ONCE_INIT) + +static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void)) +{ + pthread_once(once, init); +} +#endif + +static void ssl_library_stop(void); + +static OPENSSL_INIT_ONCE ssl_base = OPENSSL_INIT_ONCE_STATIC_INIT; +static int ssl_base_inited = 0; +static void ossl_init_ssl_base(void) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: " + "Adding SSL ciphers and digests\n"); +#endif +#ifndef OPENSSL_NO_DES + EVP_add_cipher(EVP_des_cbc()); + EVP_add_cipher(EVP_des_ede3_cbc()); +#endif +#ifndef OPENSSL_NO_IDEA + EVP_add_cipher(EVP_idea_cbc()); +#endif +#ifndef OPENSSL_NO_RC4 + EVP_add_cipher(EVP_rc4()); +# ifndef OPENSSL_NO_MD5 + EVP_add_cipher(EVP_rc4_hmac_md5()); +# endif +#endif +#ifndef OPENSSL_NO_RC2 + EVP_add_cipher(EVP_rc2_cbc()); + /* + * Not actually used for SSL/TLS but this makes PKCS#12 work if an + * application only calls SSL_library_init(). + */ + EVP_add_cipher(EVP_rc2_40_cbc()); +#endif +#ifndef OPENSSL_NO_AES + EVP_add_cipher(EVP_aes_128_cbc()); + EVP_add_cipher(EVP_aes_192_cbc()); + EVP_add_cipher(EVP_aes_256_cbc()); + EVP_add_cipher(EVP_aes_128_gcm()); + EVP_add_cipher(EVP_aes_256_gcm()); + EVP_add_cipher(EVP_aes_128_ccm()); + EVP_add_cipher(EVP_aes_256_ccm()); + EVP_add_cipher(EVP_aes_128_cbc_hmac_sha1()); + EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1()); + EVP_add_cipher(EVP_aes_128_cbc_hmac_sha256()); + EVP_add_cipher(EVP_aes_256_cbc_hmac_sha256()); +#endif +#ifndef OPENSSL_NO_CAMELLIA + EVP_add_cipher(EVP_camellia_128_cbc()); + EVP_add_cipher(EVP_camellia_256_cbc()); +#endif +#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) + EVP_add_cipher(EVP_chacha20_poly1305()); +#endif + +#ifndef OPENSSL_NO_SEED + EVP_add_cipher(EVP_seed_cbc()); +#endif + +#ifndef OPENSSL_NO_MD5 + EVP_add_digest(EVP_md5()); + EVP_add_digest_alias(SN_md5, "ssl3-md5"); +# ifndef OPENSSL_NO_SHA + EVP_add_digest(EVP_md5_sha1()); +# endif +#endif + EVP_add_digest(EVP_sha1()); /* RSA with sha1 */ + EVP_add_digest_alias(SN_sha1, "ssl3-sha1"); + EVP_add_digest_alias(SN_sha1WithRSAEncryption, SN_sha1WithRSA); + EVP_add_digest(EVP_sha224()); + EVP_add_digest(EVP_sha256()); + EVP_add_digest(EVP_sha384()); + EVP_add_digest(EVP_sha512()); +#ifndef OPENSSL_NO_COMP +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: " + "SSL_COMP_get_compression_methods()\n"); +#endif + /* + * This will initialise the built-in compression algorithms. The value + * returned is a STACK_OF(SSL_COMP), but that can be discarded safely + */ + SSL_COMP_get_compression_methods(); +#endif + /* initialize cipher/digest methods table */ + ssl_load_ciphers(); + +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: " + "SSL_add_ssl_module()\n"); +#endif + SSL_add_ssl_module(); + /* + * We ignore an error return here. Not much we can do - but not that bad + * either. We can still safely continue. + */ + OPENSSL_INIT_register_stop_handler(ssl_library_stop); + ssl_base_inited = 1; +} + +static OPENSSL_INIT_ONCE ssl_strings = OPENSSL_INIT_ONCE_STATIC_INIT; +static int ssl_strings_inited = 0; +static void ossl_init_load_ssl_strings(void) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_load_ssl_strings: " + "ERR_load_SSL_strings()\n"); +#endif + ERR_load_SSL_strings(); + ssl_strings_inited = 1; +} + +static void ossl_init_no_load_ssl_strings(void) +{ + /* Do nothing in this case */ + return; +} + +static void ssl_library_stop(void) +{ + if (ssl_base_inited) { +#ifndef OPENSSL_NO_COMP +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ssl_library_stop: " + "SSL_COMP_free_compression_methods()\n"); +#endif + SSL_COMP_free_compression_methods(); + ssl_base_inited = 0; + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&ssl_base); +#endif + } + + if (ssl_strings_inited) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ssl_library_stop: " + "ERR_free_strings()\n"); +#endif + /* + * If both crypto and ssl error strings are inited we will end up + * calling ERR_free_strings() twice - but that's ok. The second time + * will be a no-op. It's easier to do that than to try and track + * between the two libraries whether they have both been inited. + */ + ERR_free_strings(); + ssl_strings_inited = 0; + OPENSSL_INIT_ONCE_DYNAMIC_INIT(&ssl_strings); + } +} + +/* + * If this function is called with a non NULL settings value then it must be + * called prior to any threads making calls to any OpenSSL functions, + * i.e. passing a non-null settings value is assumed to be single-threaded. + */ +void OPENSSL_INIT_ssl_library_start(uint64_t opts, + const OPENSSL_INIT_SETTINGS *settings) +{ + OPENSSL_INIT_crypto_library_start(opts | OPENSSL_INIT_ADD_ALL_CIPHERS + | OPENSSL_INIT_ADD_ALL_DIGESTS, settings); + + ossl_init_once_run(&ssl_base, ossl_init_ssl_base); + + if (opts & OPENSSL_INIT_NO_LOAD_SSL_STRINGS) + ossl_init_once_run(&ssl_strings, ossl_init_no_load_ssl_strings); + + if (opts & OPENSSL_INIT_LOAD_SSL_STRINGS) + ossl_init_once_run(&ssl_strings, ossl_init_load_ssl_strings); +} + diff --git a/util/libeay.num b/util/libeay.num index e0f95590b7..b937a44dba 100755 --- a/util/libeay.num +++ b/util/libeay.num @@ -4812,3 +4812,6 @@ PKCS8_get_attr 5206 1_1_0 EXIST::FUNCTION: PKCS12_SAFEBAG_get0_attr 5207 1_1_0 EXIST::FUNCTION: PKCS12_get0_mac 5208 1_1_0 EXIST::FUNCTION: PKCS12_SAFEBAG_get0_pkcs8 5209 1_1_0 EXIST::FUNCTION: +OPENSSL_INIT_library_stop 5210 1_1_0 EXIST::FUNCTION: +OPENSSL_INIT_register_stop_handler 5211 1_1_0 EXIST::FUNCTION: +OPENSSL_INIT_crypto_library_start 5212 1_1_0 EXIST::FUNCTION: diff --git a/util/mk1mf.pl b/util/mk1mf.pl index ed1d0e1959..e7cbea883d 100755 --- a/util/mk1mf.pl +++ b/util/mk1mf.pl @@ -142,7 +142,8 @@ and [options] can be one of no-engine - No engine no-egd - No EGD no-hw - No hw - no-async - No Async (use NULL) + no-async - No Async (use NULL) + no-autoalginit - Don't auto load algorithms in libcrypto nasm - Use NASM for x86 asm nw-nasm - Use NASM x86 asm for NetWare nw-mwasm - Use Metrowerks x86 asm for NetWare @@ -298,6 +299,7 @@ $cflags.=" -DOPENSSL_NO_GOST" if $no_gost; $cflags.=" -DOPENSSL_NO_ENGINE" if $no_engine; $cflags.=" -DOPENSSL_NO_HW" if $no_hw; $cflags.=" -DOPENSSL_NO_ASYNC" if $no_async; +$cflags.=" -DOPENSSL_NO_AUTOALGINIT" if $no_autoalginit; $cflags.=" -DOPENSSL_FIPS" if $fips; $cflags.=" -DOPENSSL_NO_JPAKE" if $no_jpake; $cflags.=" -DOPENSSL_NO_EC2M" if $no_ec2m; @@ -1414,6 +1416,7 @@ sub read_options "no-egd" => 0, "no-hw" => \$no_hw, "no-async" => \$no_async, + "no-autoalginit" => \$no_autoalginit, "just-ssl" => [\$no_rc2, \$no_idea, \$no_des, \$no_bf, \$no_cast, \$no_md2, \$no_mdc2, \$no_dsa, \$no_dh, diff --git a/util/ssleay.num b/util/ssleay.num index d320e3bbd4..e06ae98f56 100755 --- a/util/ssleay.num +++ b/util/ssleay.num @@ -437,3 +437,4 @@ SSL_up_ref 471 1_1_0 EXIST::FUNCTION: SSL_CTX_up_ref 472 1_1_0 EXIST::FUNCTION: DTLSv1_listen 473 1_1_0 EXIST::FUNCTION: SSL_get0_verified_chain 474 1_1_0 EXIST::FUNCTION: +OPENSSL_INIT_ssl_library_start 475 1_1_0 EXIST::FUNCTION: