[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Tue Feb 9 15:16:32 UTC 2016


The branch master has been updated
       via  35d8fa563c9abc80c6e8d87396ab48dbd1a4c78d (commit)
       via  722cba232150ff4d7c3ea5cae0d1e90e38a5d7d3 (commit)
       via  dde2cde4ed65bf38d743d6938d040dba7473df24 (commit)
       via  5c858c5915b1ce751b729dc7a3eef812766ced4a (commit)
       via  bf24111bb2cf37b609fecdbe81660ecfd460e998 (commit)
       via  8b75603cc0ce8f4d9deb7218fbd905d3fc73a4c0 (commit)
       via  498abff0ae907dce08f37a1353976755e8c8120e (commit)
       via  71567a6f418ed1dc42d4c5ec57f72d3119b75966 (commit)
       via  8793f012f11416abd300aa524057c863e8c16dd5 (commit)
       via  b9f757074d470ec6b031f348581160e48202b85c (commit)
       via  7fa792d14d06cdaca18f225b1d2d8daf8ed24fd7 (commit)
       via  7b9f8f7f03eda2faa1cdd42ed29a0b70e60eaf59 (commit)
       via  b184e3ef73200cb3b7914a603b43a5b8a074c85f (commit)
      from  bc66265da8f4c8830cfaf229c985bc391075aa9d (commit)


- Log -----------------------------------------------------------------
commit 35d8fa563c9abc80c6e8d87396ab48dbd1a4c78d
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 9 13:12:34 2016 +0000

    Updates for auto init/deinit review comments
    
    Fixes for the auto-init/deinit code based on review comments
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 722cba232150ff4d7c3ea5cae0d1e90e38a5d7d3
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 9 12:04:03 2016 +0000

    Add a CHANGES entry for auto-init and de-init
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit dde2cde4ed65bf38d743d6938d040dba7473df24
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 9 11:55:41 2016 +0000

    Correct copyright date for internal header file
    
    The newly added internal async.h header file had last years date in it.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 5c858c5915b1ce751b729dc7a3eef812766ced4a
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 9 11:09:10 2016 +0000

    Update build.info files for auto-init/de-init
    
    Various Makefile.in files have changes for auto-init/de-init. Make the
    equivalent changes in build.info.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit bf24111bb2cf37b609fecdbe81660ecfd460e998
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 9 10:55:21 2016 +0000

    Avoid a race condition in loading config settings
    
    A race condition can occur when sending config settings to
    OPENSSL_INIT_crypto_library_start()
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 8b75603cc0ce8f4d9deb7218fbd905d3fc73a4c0
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 9 10:17:59 2016 +0000

    Provide documentation for auto-init/auto-deinit
    
    Provide some man pages for auto-init/deinit. Also update the INSTALL
    documentation for information on the new Configure options implemented as
    part of this.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 498abff0ae907dce08f37a1353976755e8c8120e
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 9 09:39:07 2016 +0000

    Add an OPENSSL_NO_AUTOERRINIT option
    
    This option disables automatic loading of the crypto/ssl error strings in
    order to keep statically linked executable file size down
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 71567a6f418ed1dc42d4c5ec57f72d3119b75966
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 9 09:13:45 2016 +0000

    Provide a thread stop API
    
    Add the OPENSSL_INIT_thread_stop() function.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 8793f012f11416abd300aa524057c863e8c16dd5
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 8 16:45:35 2016 +0000

    Clean up the tests for auto-init/de-init
    
    Remove the need to explicitly initialise/deinitialise for the tests
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit b9f757074d470ec6b031f348581160e48202b85c
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 8 16:44:58 2016 +0000

    Get the apps to use auto-init/de-init
    
    Clean up the apps so that we make use of the new auto-init/de-init feature.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 7fa792d14d06cdaca18f225b1d2d8daf8ed24fd7
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 8 16:44:26 2016 +0000

    Auto init/de-init libssl
    
    Building on the pervious commit to auto initialise and de-initialise libssl
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 7b9f8f7f03eda2faa1cdd42ed29a0b70e60eaf59
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 8 16:43:03 2016 +0000

    Auto init/deinit libcrypto
    
    This builds on the previous commit to auto initialise/deinitialise
    libcrypto.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit b184e3ef73200cb3b7914a603b43a5b8a074c85f
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 9 11:26:14 2016 +0000

    Provide framework for auto initialise/deinitialise of the library
    
    This commit provides the basis and core code for an auto initialisation
    and deinitialisation framework for libcrypto and libssl. The intention is
    to remove the need (in many circumstances) to call explicit initialise and
    deinitialise functions. Explicit initialisation will still be an option,
    and if non-default initialisation is needed then it will be required.
    Similarly for de-initialisation (although this will be a lot easier since
    it will bring all de-initialisation into a single function).
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

-----------------------------------------------------------------------

Summary of changes:
 CHANGES                                            |   6 +
 Configure                                          |   5 +-
 INSTALL                                            |  17 +
 apps/openssl.c                                     |  34 +-
 apps/s_client.c                                    |   4 -
 apps/s_server.c                                    |   4 -
 crypto/Makefile.in                                 |   4 +-
 crypto/async/arch/async_null.c                     |   5 -
 crypto/async/arch/async_null.h                     |   2 +-
 crypto/async/arch/async_posix.c                    |   8 -
 crypto/async/arch/async_posix.h                    |   2 +-
 crypto/async/arch/async_win.c                      |  42 +-
 crypto/async/arch/async_win.h                      |   2 +-
 crypto/async/async.c                               | 119 ++--
 crypto/async/async_locl.h                          |   3 +-
 crypto/build.info                                  |   2 +-
 crypto/comp/c_zlib.c                               |   2 +
 crypto/conf/conf_sap.c                             |  13 +-
 crypto/cryptlib.c                                  |   3 +-
 crypto/engine/eng_cryptodev.c                      |   9 +-
 crypto/engine/eng_dyn.c                            |   3 +-
 crypto/engine/eng_int.h                            |   3 +-
 crypto/engine/eng_openssl.c                        |   4 +-
 crypto/engine/eng_rdrand.c                         |   7 +-
 crypto/err/err.c                                   |   6 +-
 crypto/err/err_all.c                               |   3 +-
 crypto/evp/Makefile.in                             |   8 +-
 crypto/evp/build.info                              |   4 +-
 crypto/evp/c_all.c                                 |  80 ---
 crypto/evp/c_allc.c                                |   3 +-
 crypto/evp/c_alld.c                                |   3 +-
 crypto/evp/evp_acnf.c                              |  72 --
 crypto/evp/names.c                                 |  16 +
 .../pem2.h => crypto/include/internal/async.h      |  21 +-
 .../pem2.h => crypto/include/internal/conf.h       |  22 +-
 .../internal/{bn_conf.h.in => cryptlib_int.h}      |  31 +-
 .../pem2.h => crypto/include/internal/engine.h     |  25 +-
 test/nptest.c => crypto/include/internal/err.h     |  18 +-
 crypto/include/internal/evp_int.h                  |   4 +
 crypto/init.c                                      | 747 +++++++++++++++++++++
 crypto/lock.c                                      |   3 +-
 doc/crypto/OPENSSL_INIT_crypto_library_start.pod   | 227 +++++++
 doc/ssl/OPENSSL_INIT_ssl_library_start.pod         |  80 +++
 engines/e_capi.c                                   |   7 +-
 engines/e_dasync.c                                 |   5 +-
 engines/e_ossltest.c                               |   1 +
 engines/e_padlock.c                                |   4 +-
 include/openssl/async.h                            |   2 -
 include/openssl/conf.h                             |   3 +-
 include/openssl/crypto.h                           |  61 +-
 include/openssl/engine.h                           |  29 +-
 include/openssl/err.h                              |   5 +-
 include/openssl/evp.h                              |  22 +-
 include/openssl/ssl.h                              |  16 +-
 include/openssl/symhacks.h                         |   4 -
 ssl/Makefile.in                                    |   8 +-
 ssl/build.info                                     |   4 +-
 ssl/ssl-lib.com                                    |   4 +-
 ssl/ssl_algs.c                                     | 137 ----
 ssl/ssl_err2.c                                     |  68 --
 ssl/ssl_init.c                                     | 317 +++++++++
 ssl/ssl_lib.c                                      |   2 +
 test/asynctest.c                                   |  36 +-
 test/bntest.c                                      |   2 +-
 test/clienthellotest.c                             |   7 -
 test/danetest.c                                    |  10 -
 test/dsatest.c                                     |   5 +-
 test/ecdhtest.c                                    |   3 +-
 test/ecdsatest.c                                   |   5 +-
 test/ectest.c                                      |   7 -
 test/enginetest.c                                  |   6 +-
 test/evp_extra_test.c                              |   8 -
 test/evp_test.c                                    |   8 +-
 test/exptest.c                                     |   5 +-
 test/heartbeat_test.c                              |   3 -
 test/jpaketest.c                                   |   5 -
 test/methtest.c                                    |   1 -
 test/p5_crpt2_test.c                               |  13 +-
 test/rsa_test.c                                    |   3 -
 test/srptest.c                                     |   4 -
 test/ssltest.c                                     |  12 -
 test/verify_extra_test.c                           |   7 -
 util/libeay.num                                    |  54 +-
 util/mk1mf.pl                                      |   8 +-
 util/ssleay.num                                    |   5 +-
 85 files changed, 1790 insertions(+), 802 deletions(-)
 delete mode 100644 crypto/evp/c_all.c
 delete mode 100644 crypto/evp/evp_acnf.c
 copy include/openssl/pem2.h => crypto/include/internal/async.h (89%)
 copy include/openssl/pem2.h => crypto/include/internal/conf.h (89%)
 copy crypto/include/internal/{bn_conf.h.in => cryptlib_int.h} (79%)
 copy include/openssl/pem2.h => crypto/include/internal/engine.h (87%)
 copy test/nptest.c => crypto/include/internal/err.h (90%)
 create mode 100644 crypto/init.c
 create mode 100644 doc/crypto/OPENSSL_INIT_crypto_library_start.pod
 create mode 100644 doc/ssl/OPENSSL_INIT_ssl_library_start.pod
 delete mode 100644 ssl/ssl_algs.c
 delete mode 100644 ssl/ssl_err2.c
 create mode 100644 ssl/ssl_init.c

diff --git a/CHANGES b/CHANGES
index 9060abe..d0bd6ac 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,12 @@
  _______________
 
  Changes between 1.0.2f and 1.1.0  [xx XXX xxxx]
+  *) Added support for auto-initialisation and de-initialisation of the library.
+     OpenSSL no longer requires explicit init or deinit routines to be called,
+     except in certain circumstances. See the
+     OPENSSL_INIT_crypto_library_start() and OPENSSL_INIT_ssl_library_start()
+     man pages for further information.
+     [Matt Caswell]
 
   *) The arguments to the DTLSv1_listen function have changed. Specifically the
      "peer" argument is now expected to be a BIO_ADDR object.
diff --git a/Configure b/Configure
index 97df83c..c81a661 100755
--- a/Configure
+++ b/Configure
@@ -227,6 +227,8 @@ my @disablables = (
     "aes",
     "asm",
     "async",
+    "autoalginit",
+    "autoerrinit",
     "bf",
     "camellia",
     "capieng",
@@ -741,7 +743,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/ || /^autoerrinit/)
 			{
 			push @{$config{openssl_other_defines}}, "OPENSSL_NO_$ALGO";
 			print " OPENSSL_NO_$ALGO";
diff --git a/INSTALL b/INSTALL
index f11d7cf..520de7b 100644
--- a/INSTALL
+++ b/INSTALL
@@ -51,6 +51,19 @@
   --openssldir=DIR Directory for OpenSSL files. If no prefix is specified,
                 the library files and binaries are also installed there.
 
+  no-autoalginit Don't automatically load all supported ciphers and digests.
+                Typically OpenSSL will make available all of its supported
+                ciphers and digests. For a statically linked application this
+                may be undesirable if small executable size is an objective.
+                This only affects libcrypto. Ciphers and digests will have to be
+                loaded manually using EVP_add_cipher() and EVP_add_digest() if
+                this option is used.
+
+  no-autoerrinit Don't automatically load all libcrypto/libssl error strings.
+                Typically OpenSSL will automatically load human readable error
+                strings. For a statically linked application this may be
+                undesirable if small executable size is an objective.
+
   no-threads    Don't try to build with support for multi-threaded
                 applications.
 
@@ -327,6 +340,10 @@
  you can still use "no-threads" to suppress an annoying warning message
  from the Configure script.)
 
+ OpenSSL provides built-in support for two threading models: pthreads (found on
+ most UNIX/Linux systems), and Windows threads. No other threading models are
+ supported. If your platform does not provide pthreads or Windows threads then
+ you should Configure with the "no-threads" option.
 
  Note on shared libraries
  ------------------------
diff --git a/apps/openssl.c b/apps/openssl.c
index b8da88a..e558b71 100644
--- a/apps/openssl.c
+++ b/apps/openssl.c
@@ -170,44 +170,19 @@ static int apps_startup()
 #ifdef SIGPIPE
     signal(SIGPIPE, SIG_IGN);
 #endif
-    ERR_load_crypto_strings();
-    ERR_load_SSL_strings();
 
-    OPENSSL_load_builtin_modules();
-    SSL_add_ssl_module();
-#ifndef OPENSSL_NO_ENGINE
-    ENGINE_load_builtin_engines();
-#endif
-    if (!app_load_modules(NULL)) {
-        ERR_print_errors(bio_err);
-        BIO_printf(bio_err, "Error loading default configuration\n");
-        return 0;
-    }
+    /* Set non-default library initialisation settings */
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ENGINE_ALL_BUILTIN
+                                      | OPENSSL_INIT_LOAD_CONFIG, NULL);
 
-    OpenSSL_add_all_algorithms();
-    OpenSSL_add_ssl_algorithms();
     setup_ui_method();
-    /*SSL_library_init();*/
+
     return 1;
 }
 
 static void apps_shutdown()
 {
-#ifndef OPENSSL_NO_ENGINE
-    ENGINE_cleanup();
-#endif
     destroy_ui_method();
-    CONF_modules_unload(1);
-#ifndef OPENSSL_NO_COMP
-    COMP_zlib_cleanup();
-    SSL_COMP_free_compression_methods();
-#endif
-    OBJ_cleanup();
-    EVP_cleanup();
-    CRYPTO_cleanup_all_ex_data();
-    ERR_remove_thread_state(NULL);
-    RAND_cleanup();
-    ERR_free_strings();
 }
 
 static char *make_config_name()
@@ -317,7 +292,6 @@ int main(int argc, char *argv[])
     if (getenv("OPENSSL_FIPS")) {
 #ifdef OPENSSL_FIPS
         if (!FIPS_mode_set(1)) {
-            ERR_load_crypto_strings();
             ERR_print_errors(bio_err);
             return 1;
         }
diff --git a/apps/s_client.c b/apps/s_client.c
index 8fe1612..c122c1a 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -1504,7 +1504,6 @@ int s_client_main(int argc, char **argv)
 
     if (async) {
         SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC);
-        ASYNC_init(1, 0, 0);
     }
 
     if (!config_ctx(cctx, ssl_args, ctx, jpake_secret == NULL))
@@ -2420,9 +2419,6 @@ int s_client_main(int argc, char **argv)
             print_stuff(bio_c_out, con, 1);
         SSL_free(con);
     }
-    if (async) {
-        ASYNC_cleanup(1);
-    }
 #if !defined(OPENSSL_NO_NEXTPROTONEG)
     OPENSSL_free(next_proto.data);
 #endif
diff --git a/apps/s_server.c b/apps/s_server.c
index f07c8f6..3685586 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -1721,7 +1721,6 @@ int s_server_main(int argc, char *argv[])
 
     if (async) {
         SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC);
-        ASYNC_init(1, 0, 0);
     }
 
 #ifndef OPENSSL_NO_SRTP
@@ -2026,9 +2025,6 @@ int s_server_main(int argc, char *argv[])
     bio_s_out = NULL;
     BIO_free(bio_s_msg);
     bio_s_msg = NULL;
-    if (async) {
-        ASYNC_cleanup(1);
-    }
     return (ret);
 }
 
diff --git a/crypto/Makefile.in b/crypto/Makefile.in
index 8d69c28..de98f4a 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/async/arch/async_null.c b/crypto/async/arch/async_null.c
index d3f686f..2b1d28e 100644
--- a/crypto/async/arch/async_null.c
+++ b/crypto/async/arch/async_null.c
@@ -80,11 +80,6 @@ int async_global_init(void)
     return 0;
 }
 
-int async_local_init(void)
-{
-    return 0;
-}
-
 void async_local_cleanup(void)
 {
 }
diff --git a/crypto/async/arch/async_null.h b/crypto/async/arch/async_null.h
index 93887ae..4cd0a8b 100644
--- a/crypto/async/arch/async_null.h
+++ b/crypto/async/arch/async_null.h
@@ -66,7 +66,7 @@ typedef struct async_fibre_st {
 
 
 # define async_set_ctx(nctx)                    0
-# define async_get_ctx()                        ((async_ctx *)NULL)
+# define async_arch_get_ctx()                   ((async_ctx *)NULL)
 # define async_fibre_swapcontext(o,n,r)         0
 # define async_fibre_makecontext(c)             0
 # define async_fibre_free(f)
diff --git a/crypto/async/arch/async_posix.c b/crypto/async/arch/async_posix.c
index 1df77cc..57cce7b 100644
--- a/crypto/async/arch/async_posix.c
+++ b/crypto/async/arch/async_posix.c
@@ -72,14 +72,6 @@ int async_global_init(void)
     return 1;
 }
 
-int async_local_init(void)
-{
-    if (!async_set_ctx(NULL) || ! async_set_pool(NULL))
-        return 0;
-
-    return 1;
-}
-
 void async_local_cleanup(void)
 {
 }
diff --git a/crypto/async/arch/async_posix.h b/crypto/async/arch/async_posix.h
index 85d033f..7f1bdd1 100644
--- a/crypto/async/arch/async_posix.h
+++ b/crypto/async/arch/async_posix.h
@@ -78,7 +78,7 @@ typedef struct async_fibre_st {
 } async_fibre;
 
 #  define async_set_ctx(nctx)  (pthread_setspecific(posixctx , (nctx)) == 0)
-#  define async_get_ctx()      ((async_ctx *)pthread_getspecific(posixctx))
+#  define async_arch_get_ctx() ((async_ctx *)pthread_getspecific(posixctx))
 #  define async_set_pool(p)    (pthread_setspecific(posixpool , (p)) == 0)
 #  define async_get_pool()     ((async_pool *)pthread_getspecific(posixpool))
 
diff --git a/crypto/async/arch/async_win.c b/crypto/async/arch/async_win.c
index f3de79a..3f3a005 100644
--- a/crypto/async/arch/async_win.c
+++ b/crypto/async/arch/async_win.c
@@ -66,7 +66,6 @@ struct winpool {
 
 static DWORD asyncwinpool = 0;
 static DWORD asyncwinctx = 0;
-static DWORD asyncwindispatch = 0;
 
 
 void async_start_func(void);
@@ -75,33 +74,22 @@ int async_global_init(void)
 {
     asyncwinpool = TlsAlloc();
     asyncwinctx = TlsAlloc();
-    asyncwindispatch = TlsAlloc();
-    if (asyncwinpool == TLS_OUT_OF_INDEXES || asyncwinctx == TLS_OUT_OF_INDEXES
-            || asyncwindispatch == TLS_OUT_OF_INDEXES) {
+    if (asyncwinpool == TLS_OUT_OF_INDEXES
+            || asyncwinctx == TLS_OUT_OF_INDEXES) {
         if (asyncwinpool != TLS_OUT_OF_INDEXES) {
             TlsFree(asyncwinpool);
         }
         if (asyncwinctx != TLS_OUT_OF_INDEXES) {
             TlsFree(asyncwinctx);
         }
-        if (asyncwindispatch != TLS_OUT_OF_INDEXES) {
-            TlsFree(asyncwindispatch);
-        }
         return 0;
     }
     return 1;
 }
 
-int async_local_init(void)
-{
-    return (TlsSetValue(asyncwinpool, NULL) != 0)
-        && (TlsSetValue(asyncwinctx, NULL) != 0)
-        && (TlsSetValue(asyncwindispatch, NULL) != 0);
-}
-
 void async_local_cleanup(void)
 {
-    async_ctx *ctx = async_get_ctx();
+    async_ctx *ctx = async_arch_get_ctx();
     if (ctx != NULL) {
         async_fibre *fibre = &ctx->dispatcher;
         if(fibre != NULL && fibre->fibre != NULL && fibre->converted) {
@@ -115,32 +103,24 @@ void async_global_cleanup(void)
 {
     TlsFree(asyncwinpool);
     TlsFree(asyncwinctx);
-    TlsFree(asyncwindispatch);
     asyncwinpool = 0;
     asyncwinctx = 0;
-    asyncwindispatch = 0;
 }
 
 int async_fibre_init_dispatcher(async_fibre *fibre)
 {
     LPVOID dispatcher;
 
-    dispatcher = (LPVOID)TlsGetValue(asyncwindispatch);
-    if (dispatcher == NULL) {
-        fibre->fibre = ConvertThreadToFiber(NULL);
-        if (fibre->fibre == NULL) {
-            fibre->converted = 0;
-            fibre->fibre = GetCurrentFiber();
-            if (fibre->fibre == NULL)
-                return 0;
-        } else {
-            fibre->converted = 1;
-        }
-        if (TlsSetValue(asyncwindispatch, (LPVOID)fibre->fibre) == 0)
+    fibre->fibre = ConvertThreadToFiber(NULL);
+    if (fibre->fibre == NULL) {
+        fibre->converted = 0;
+        fibre->fibre = GetCurrentFiber();
+        if (fibre->fibre == NULL)
             return 0;
     } else {
-        fibre->fibre = dispatcher;
+        fibre->converted = 1;
     }
+
     return 1;
 }
 
@@ -196,7 +176,7 @@ int async_set_pool(async_pool *pool)
     return TlsSetValue(asyncwinpool, (LPVOID)pool) != 0;
 }
 
-async_ctx *async_get_ctx(void)
+async_ctx *async_arch_get_ctx(void)
 {
     return (async_ctx *)TlsGetValue(asyncwinctx);
 }
diff --git a/crypto/async/arch/async_win.h b/crypto/async/arch/async_win.h
index fa345cb..87e30a4 100644
--- a/crypto/async/arch/async_win.h
+++ b/crypto/async/arch/async_win.h
@@ -73,7 +73,7 @@ typedef struct async_fibre_st {
         ((c)->fibre = CreateFiber(0, async_start_func_win, 0))
 # define async_fibre_free(f)             (DeleteFiber((f)->fibre))
 
-async_ctx *async_get_ctx(void);
+async_ctx *async_arch_get_ctx(void);
 int async_set_ctx(async_ctx *ctx);
 
 int async_fibre_init_dispatcher(async_fibre *fibre);
diff --git a/crypto/async/async.c b/crypto/async/async.c
index 9d68a7c..024aaf6 100644
--- a/crypto/async/async.c
+++ b/crypto/async/async.c
@@ -62,6 +62,7 @@
 #include "async_locl.h"
 
 #include <openssl/err.h>
+#include <internal/cryptlib_int.h>
 #include <string.h>
 
 #define ASYNC_JOB_RUNNING   0
@@ -94,6 +95,12 @@ err:
     return NULL;
 }
 
+static async_ctx *async_get_ctx(void)
+{
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ASYNC, NULL);
+    return async_arch_get_ctx();
+}
+
 static int async_ctx_free(void)
 {
     async_ctx *ctx;
@@ -191,16 +198,17 @@ static void async_release_job(ASYNC_JOB *job) {
 void async_start_func(void)
 {
     ASYNC_JOB *job;
+    async_ctx *ctx = async_get_ctx();
 
     while (1) {
         /* Run the job */
-        job = async_get_ctx()->currjob;
+        job = ctx->currjob;
         job->ret = job->func(job->funcargs);
 
         /* Stop the job */
         job->status = ASYNC_JOB_STOPPING;
         if (!async_fibre_swapcontext(&job->fibrectx,
-                                     &async_get_ctx()->dispatcher, 1)) {
+                                     &ctx->dispatcher, 1)) {
             /*
              * Should not happen. Getting here will close the thread...can't do
              * much about it
@@ -213,36 +221,39 @@ void async_start_func(void)
 int ASYNC_start_job(ASYNC_JOB **job, int *ret, int (*func)(void *),
                          void *args, size_t size)
 {
-    if (async_get_ctx() == NULL && async_ctx_new() == NULL) {
+    async_ctx *ctx = async_get_ctx();
+    if (ctx == NULL)
+        ctx = async_ctx_new();
+    if (ctx == NULL) {
         return ASYNC_ERR;
     }
 
     if (*job) {
-        async_get_ctx()->currjob = *job;
+        ctx->currjob = *job;
     }
 
     for (;;) {
-        if (async_get_ctx()->currjob != NULL) {
-            if (async_get_ctx()->currjob->status == ASYNC_JOB_STOPPING) {
-                *ret = async_get_ctx()->currjob->ret;
-                async_release_job(async_get_ctx()->currjob);
-                async_get_ctx()->currjob = NULL;
+        if (ctx->currjob != NULL) {
+            if (ctx->currjob->status == ASYNC_JOB_STOPPING) {
+                *ret = ctx->currjob->ret;
+                async_release_job(ctx->currjob);
+                ctx->currjob = NULL;
                 *job = NULL;
                 return ASYNC_FINISH;
             }
 
-            if (async_get_ctx()->currjob->status == ASYNC_JOB_PAUSING) {
-                *job = async_get_ctx()->currjob;
-                async_get_ctx()->currjob->status = ASYNC_JOB_PAUSED;
-                async_get_ctx()->currjob = NULL;
+            if (ctx->currjob->status == ASYNC_JOB_PAUSING) {
+                *job = ctx->currjob;
+                ctx->currjob->status = ASYNC_JOB_PAUSED;
+                ctx->currjob = NULL;
                 return ASYNC_PAUSE;
             }
 
-            if (async_get_ctx()->currjob->status == ASYNC_JOB_PAUSED) {
-                async_get_ctx()->currjob = *job;
+            if (ctx->currjob->status == ASYNC_JOB_PAUSED) {
+                ctx->currjob = *job;
                 /* Resume previous job */
-                if (!async_fibre_swapcontext(&async_get_ctx()->dispatcher,
-                        &async_get_ctx()->currjob->fibrectx, 1)) {
+                if (!async_fibre_swapcontext(&ctx->dispatcher,
+                        &ctx->currjob->fibrectx, 1)) {
                     ASYNCerr(ASYNC_F_ASYNC_START_JOB,
                              ASYNC_R_FAILED_TO_SWAP_CONTEXT);
                     goto err;
@@ -252,41 +263,41 @@ int ASYNC_start_job(ASYNC_JOB **job, int *ret, int (*func)(void *),
 
             /* Should not happen */
             ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_INTERNAL_ERROR);
-            async_release_job(async_get_ctx()->currjob);
-            async_get_ctx()->currjob = NULL;
+            async_release_job(ctx->currjob);
+            ctx->currjob = NULL;
             *job = NULL;
             return ASYNC_ERR;
         }
 
         /* Start a new job */
-        if ((async_get_ctx()->currjob = async_get_pool_job()) == NULL) {
+        if ((ctx->currjob = async_get_pool_job()) == NULL) {
             return ASYNC_NO_JOBS;
         }
 
         if (args != NULL) {
-            async_get_ctx()->currjob->funcargs = OPENSSL_malloc(size);
-            if (async_get_ctx()->currjob->funcargs == NULL) {
+            ctx->currjob->funcargs = OPENSSL_malloc(size);
+            if (ctx->currjob->funcargs == NULL) {
                 ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_MALLOC_FAILURE);
-                async_release_job(async_get_ctx()->currjob);
-                async_get_ctx()->currjob = NULL;
+                async_release_job(ctx->currjob);
+                ctx->currjob = NULL;
                 return ASYNC_ERR;
             }
-            memcpy(async_get_ctx()->currjob->funcargs, args, size);
+            memcpy(ctx->currjob->funcargs, args, size);
         } else {
-            async_get_ctx()->currjob->funcargs = NULL;
+            ctx->currjob->funcargs = NULL;
         }
 
-        async_get_ctx()->currjob->func = func;
-        if (!async_fibre_swapcontext(&async_get_ctx()->dispatcher,
-                &async_get_ctx()->currjob->fibrectx, 1)) {
+        ctx->currjob->func = func;
+        if (!async_fibre_swapcontext(&ctx->dispatcher,
+                &ctx->currjob->fibrectx, 1)) {
             ASYNCerr(ASYNC_F_ASYNC_START_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
             goto err;
         }
     }
 
 err:
-    async_release_job(async_get_ctx()->currjob);
-    async_get_ctx()->currjob = NULL;
+    async_release_job(ctx->currjob);
+    ctx->currjob = NULL;
     *job = NULL;
     return ASYNC_ERR;
 }
@@ -295,10 +306,11 @@ err:
 int ASYNC_pause_job(void)
 {
     ASYNC_JOB *job;
+    async_ctx *ctx = async_get_ctx();
 
-    if (async_get_ctx() == NULL
-            || async_get_ctx()->currjob == NULL
-            || async_get_ctx()->blocked) {
+    if (ctx == NULL
+            || ctx->currjob == NULL
+            || ctx->blocked) {
         /*
          * Could be we've deliberately not been started within a job so this is
          * counted as success.
@@ -306,11 +318,11 @@ int ASYNC_pause_job(void)
         return 1;
     }
 
-    job = async_get_ctx()->currjob;
+    job = ctx->currjob;
     job->status = ASYNC_JOB_PAUSING;
 
     if (!async_fibre_swapcontext(&job->fibrectx,
-                                 &async_get_ctx()->dispatcher, 1)) {
+                                 &ctx->dispatcher, 1)) {
         ASYNCerr(ASYNC_F_ASYNC_PAUSE_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
         return 0;
     }
@@ -331,14 +343,11 @@ static void async_empty_pool(async_pool *pool)
     } while (job);
 }
 
-int ASYNC_init(int init_thread, size_t max_size, size_t init_size)
+int async_init(void)
 {
     if (!async_global_init())
         return 0;
 
-    if (init_thread)
-        return ASYNC_init_thread(max_size, init_size);
-
     return 1;
 }
 
@@ -352,10 +361,12 @@ int ASYNC_init_thread(size_t max_size, size_t init_size)
         return 0;
     }
 
-    if (!async_local_init()) {
-        ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ASYNC_R_INIT_FAILED);
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ASYNC, NULL);
+    if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ASYNC)) {
+        ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE);
         return 0;
     }
+
     pool = OPENSSL_zalloc(sizeof *pool);
     if (pool == NULL) {
         ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE);
@@ -417,16 +428,6 @@ void ASYNC_cleanup_thread(void)
     async_free_pool_internal(async_get_pool());
 }
 
-void ASYNC_cleanup(int cleanupthread)
-{
-    /*
-     * We don't actually have any global cleanup at the moment so just cleanup
-     * the thread
-     */
-    if (cleanupthread)
-        ASYNC_cleanup_thread();
-}
-
 ASYNC_JOB *ASYNC_get_current_job(void)
 {
     async_ctx *ctx;
@@ -464,25 +465,25 @@ void ASYNC_clear_wake(ASYNC_JOB *job)
 
 void ASYNC_block_pause(void)
 {
-    if (async_get_ctx() == NULL
-            || async_get_ctx()->currjob == NULL) {
+    async_ctx *ctx = async_get_ctx();
+    if (ctx == NULL || ctx->currjob == NULL) {
         /*
          * We're not in a job anyway so ignore this
          */
         return;
     }
-    async_get_ctx()->blocked++;
+    ctx->blocked++;
 }
 
 void ASYNC_unblock_pause(void)
 {
-    if (async_get_ctx() == NULL
-            || async_get_ctx()->currjob == NULL) {
+    async_ctx *ctx = async_get_ctx();
+    if (ctx == NULL || ctx->currjob == NULL) {
         /*
          * We're not in a job anyway so ignore this
          */
         return;
     }
-    if(async_get_ctx()->blocked > 0)
-        async_get_ctx()->blocked--;
+    if(ctx->blocked > 0)
+        ctx->blocked--;
 }
diff --git a/crypto/async/async_locl.h b/crypto/async/async_locl.h
index 0710f9e..53a192b 100644
--- a/crypto/async/async_locl.h
+++ b/crypto/async/async_locl.h
@@ -59,7 +59,7 @@
 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 #endif
 
-#include <openssl/async.h>
+#include <internal/async.h>
 #include <openssl/crypto.h>
 
 typedef struct async_ctx_st async_ctx;
@@ -95,7 +95,6 @@ struct async_pool_st {
 };
 
 int async_global_init(void);
-int async_local_init(void);
 void async_local_cleanup(void);
 void async_global_cleanup(void);
 void async_start_func(void);
diff --git a/crypto/build.info b/crypto/build.info
index c3faa50..f8ae4bd 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -2,7 +2,7 @@ LIBS=../libcrypto
 SOURCE[../libcrypto]=\
         cryptlib.c mem.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 {- $target{cpuid_asm_src} -}
+        o_init.c o_fips.c mem_sec.c init.c {- $target{cpuid_asm_src} -}
 EXTRA=  ../ms/uplink-x86.pl ../ms/uplink.c ../ms/applink.c \
         x86cpuid.pl x86_64cpuid.pl ia64cpuid.S \
         ppccpuid.pl pariscid.pl alphacpuid.pl arm64cpuid.pl armv4cpuid.pl
diff --git a/crypto/comp/c_zlib.c b/crypto/comp/c_zlib.c
index a2a811d..899dadf 100644
--- a/crypto/comp/c_zlib.c
+++ b/crypto/comp/c_zlib.c
@@ -58,6 +58,7 @@
 #include <openssl/objects.h>
 #include <openssl/comp.h>
 #include <openssl/err.h>
+#include <internal/cryptlib_int.h>
 #include "comp_lcl.h"
 
 COMP_METHOD *COMP_zlib(void);
@@ -290,6 +291,7 @@ COMP_METHOD *COMP_zlib(void)
                 zlib_loaded++;
             if (zlib_loaded)
                 meth = &zlib_stateful_method;
+            OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ZLIB, NULL);
         }
     }
 #endif
diff --git a/crypto/conf/conf_sap.c b/crypto/conf/conf_sap.c
index fead451..ff19167 100644
--- a/crypto/conf/conf_sap.c
+++ b/crypto/conf/conf_sap.c
@@ -59,7 +59,7 @@
 #include <stdio.h>
 #include <openssl/crypto.h>
 #include "internal/cryptlib.h"
-#include <openssl/conf.h>
+#include <internal/conf.h>
 #include <openssl/dso.h>
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
@@ -77,6 +77,15 @@ static int openssl_configured = 0;
 
 void OPENSSL_config(const char *config_name)
 {
+    const OPENSSL_INIT_SETTINGS settings[2] = {
+        { OPENSSL_INIT_SET_CONF_FILENAME, .value.type_string = config_name },
+        { OPENSSL_INIT_SET_END, .value.type_int = 0 }
+    };
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_LOAD_CONFIG, settings);
+}
+
+void openssl_config_internal(const char *config_name)
+{
     if (openssl_configured)
         return;
 
@@ -94,7 +103,7 @@ void OPENSSL_config(const char *config_name)
     openssl_configured = 1;
 }
 
-void OPENSSL_no_config()
+void openssl_no_config_internal(void)
 {
     openssl_configured = 1;
 }
diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c
index bd58d35..b530818 100644
--- a/crypto/cryptlib.c
+++ b/crypto/cryptlib.c
@@ -113,7 +113,7 @@
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
 
-#include "internal/cryptlib.h"
+#include "internal/cryptlib_int.h"
 #include <openssl/safestack.h>
 
 #if     defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
@@ -234,6 +234,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
     case DLL_THREAD_ATTACH:
         break;
     case DLL_THREAD_DETACH:
+        OPENSSL_INIT_thread_stop();
         break;
     case DLL_PROCESS_DETACH:
         break;
diff --git a/crypto/engine/eng_cryptodev.c b/crypto/engine/eng_cryptodev.c
index eb8a8bb..eb25790 100644
--- a/crypto/engine/eng_cryptodev.c
+++ b/crypto/engine/eng_cryptodev.c
@@ -27,9 +27,10 @@
  */
 
 #include <openssl/objects.h>
-#include <openssl/engine.h>
+#include <internal/engine.h>
 #include <openssl/evp.h>
 #include <openssl/bn.h>
+#include <openssl/crypto.h>
 
 #if (defined(__unix__) || defined(unix)) && !defined(USG) && \
         (defined(OpenBSD) || defined(__FreeBSD__))
@@ -64,7 +65,7 @@
 
 #ifndef HAVE_CRYPTODEV
 
-void ENGINE_load_cryptodev(void)
+void engine_load_cryptodev_internal(void)
 {
     /* This is a NOP on platforms without /dev/crypto */
     return;
@@ -136,7 +137,7 @@ static int cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key,
 #endif
 static int cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p,
                           void (*f) (void));
-void ENGINE_load_cryptodev(void);
+void engine_load_cryptodev_internal(void);
 
 static const ENGINE_CMD_DEFN cryptodev_defns[] = {
     {0, NULL, NULL, 0}
@@ -1619,7 +1620,7 @@ cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
     return (1);
 }
 
-void ENGINE_load_cryptodev(void)
+void engine_load_cryptodev_internal(void)
 {
     ENGINE *engine = ENGINE_new();
     int fd;
diff --git a/crypto/engine/eng_dyn.c b/crypto/engine/eng_dyn.c
index 607317b..3ca2480 100644
--- a/crypto/engine/eng_dyn.c
+++ b/crypto/engine/eng_dyn.c
@@ -58,6 +58,7 @@
 
 #include "eng_int.h"
 #include <openssl/dso.h>
+#include <openssl/crypto.h>
 
 /*
  * Shared libraries implementing ENGINEs for use by the "dynamic" ENGINE
@@ -294,7 +295,7 @@ static ENGINE *engine_dynamic(void)
     return ret;
 }
 
-void ENGINE_load_dynamic(void)
+void engine_load_dynamic_internal(void)
 {
     ENGINE *toadd = engine_dynamic();
     if (!toadd)
diff --git a/crypto/engine/eng_int.h b/crypto/engine/eng_int.h
index 804214d..9d58d93 100644
--- a/crypto/engine/eng_int.h
+++ b/crypto/engine/eng_int.h
@@ -65,8 +65,7 @@
 # define HEADER_ENGINE_INT_H
 
 # include "internal/cryptlib.h"
-/* Take public definitions from engine.h */
-# include <openssl/engine.h>
+# include <internal/engine.h>
 
 #ifdef  __cplusplus
 extern "C" {
diff --git a/crypto/engine/eng_openssl.c b/crypto/engine/eng_openssl.c
index 8540673..152c188 100644
--- a/crypto/engine/eng_openssl.c
+++ b/crypto/engine/eng_openssl.c
@@ -64,7 +64,7 @@
 #include <stdio.h>
 #include <openssl/crypto.h>
 #include "internal/cryptlib.h"
-#include <openssl/engine.h>
+#include <internal/engine.h>
 #include <openssl/dso.h>
 #include <openssl/pem.h>
 #include <openssl/evp.h>
@@ -196,7 +196,7 @@ static ENGINE *engine_openssl(void)
     return ret;
 }
 
-void ENGINE_load_openssl(void)
+void engine_load_openssl_internal(void)
 {
     ENGINE *toadd = engine_openssl();
     if (!toadd)
diff --git a/crypto/engine/eng_rdrand.c b/crypto/engine/eng_rdrand.c
index 48726e2..1be10db 100644
--- a/crypto/engine/eng_rdrand.c
+++ b/crypto/engine/eng_rdrand.c
@@ -51,9 +51,10 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <openssl/engine.h>
+#include <internal/engine.h>
 #include <openssl/rand.h>
 #include <openssl/err.h>
+#include <openssl/crypto.h>
 
 #if (defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
      defined(__x86_64) || defined(__x86_64__) || \
@@ -129,7 +130,7 @@ static ENGINE *ENGINE_rdrand(void)
     return ret;
 }
 
-void ENGINE_load_rdrand(void)
+void engine_load_rdrand_internal(void)
 {
     extern unsigned int OPENSSL_ia32cap_P[];
 
@@ -143,7 +144,7 @@ void ENGINE_load_rdrand(void)
     }
 }
 #else
-void ENGINE_load_rdrand(void)
+void engine_load_rdrand_internal(void)
 {
 }
 #endif
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 64f8adc..7e8bcc1 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -111,7 +111,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
-#include "internal/cryptlib.h"
+#include <internal/cryptlib_int.h>
 #include <openssl/lhash.h>
 #include <openssl/crypto.h>
 #include <openssl/buffer.h>
@@ -894,6 +894,10 @@ ERR_STATE *ERR_get_state(void)
          * the first one that we just replaced.
          */
         ERR_STATE_free(tmpp);
+        OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_LOAD_CRYPTO_STRINGS,
+                                          NULL);
+        /* Ignore failures from this */
+        ossl_init_thread_start(OPENSSL_INIT_THREAD_ERR_STATE);
     }
     return ret;
 }
diff --git a/crypto/err/err_all.c b/crypto/err/err_all.c
index 6309733..ffb1b83 100644
--- a/crypto/err/err_all.c
+++ b/crypto/err/err_all.c
@@ -56,6 +56,7 @@
  */
 
 #include <stdio.h>
+#include <internal/err.h>
 #include <openssl/asn1.h>
 #include <openssl/bn.h>
 #ifndef OPENSSL_NO_EC
@@ -103,7 +104,7 @@
 #include <internal/ct_int.h>
 #include <openssl/async.h>
 
-void ERR_load_crypto_strings(void)
+void err_load_crypto_strings_intern(void)
 {
 #ifdef OPENSSL_FIPS
     FIPS_set_error_callbacks(ERR_put_error, ERR_add_error_vdata);
diff --git a/crypto/evp/Makefile.in b/crypto/evp/Makefile.in
index 8771a20..61e8929 100644
--- a/crypto/evp/Makefile.in
+++ b/crypto/evp/Makefile.in
@@ -15,7 +15,7 @@ CFLAGS= $(INCLUDES) $(CFLAG)
 GENERAL=Makefile
 
 LIB=$(TOP)/libcrypto.a
-LIBSRC= encode.c digest.c evp_enc.c evp_key.c evp_acnf.c evp_cnf.c \
+LIBSRC= encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \
 	e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\
 	e_rc4.c e_aes.c names.c e_seed.c \
 	e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c \
@@ -23,13 +23,13 @@ LIBSRC= encode.c digest.c evp_enc.c evp_key.c evp_acnf.c evp_cnf.c \
 	m_md5_sha1.c m_mdc2.c m_ripemd.c \
 	p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \
 	bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
-	c_all.c c_allc.c c_alld.c evp_lib.c bio_ok.c \
+	c_allc.c c_alld.c evp_lib.c bio_ok.c \
 	evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c scrypt.c \
 	e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
 	e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
 	e_chacha20_poly1305.c cmeth_lib.c
 
-LIBOBJ=	encode.o digest.o evp_enc.o evp_key.o evp_acnf.o evp_cnf.o \
+LIBOBJ=	encode.o digest.o evp_enc.o evp_key.o evp_cnf.o \
 	e_des.o e_bf.o e_idea.o e_des3.o e_camellia.o\
 	e_rc4.o e_aes.o names.o e_seed.o \
 	e_xcbc_d.o e_rc2.o e_cast.o e_rc5.o \
@@ -37,7 +37,7 @@ LIBOBJ=	encode.o digest.o evp_enc.o evp_key.o evp_acnf.o evp_cnf.o \
 	m_md5_sha1.o m_mdc2.o m_ripemd.o \
 	p_open.o p_seal.o p_sign.o p_verify.o p_lib.o p_enc.o p_dec.o \
 	bio_md.o bio_b64.o bio_enc.o evp_err.o e_null.o \
-	c_all.o c_allc.o c_alld.o evp_lib.o bio_ok.o \
+	c_allc.o c_alld.o evp_lib.o bio_ok.o \
 	evp_pkey.o evp_pbe.o p5_crpt.o p5_crpt2.o scrypt.o \
 	e_old.o pmeth_lib.o pmeth_fn.o pmeth_gn.o m_sigver.o \
 	e_aes_cbc_hmac_sha1.o e_aes_cbc_hmac_sha256.o e_rc4_hmac_md5.o \
diff --git a/crypto/evp/build.info b/crypto/evp/build.info
index cf71e8c..3116afa 100644
--- a/crypto/evp/build.info
+++ b/crypto/evp/build.info
@@ -1,6 +1,6 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]=\
-        encode.c digest.c evp_enc.c evp_key.c evp_acnf.c evp_cnf.c \
+        encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \
         e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\
         e_rc4.c e_aes.c names.c e_seed.c \
         e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c \
@@ -8,7 +8,7 @@ SOURCE[../../libcrypto]=\
         m_md5_sha1.c m_mdc2.c m_ripemd.c \
         p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \
         bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
-        c_all.c c_allc.c c_alld.c evp_lib.c bio_ok.c \
+        c_allc.c c_alld.c evp_lib.c bio_ok.c \
         evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c scrypt.c \
         e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
         e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
diff --git a/crypto/evp/c_all.c b/crypto/evp/c_all.c
deleted file mode 100644
index 6dd2bc7..0000000
--- a/crypto/evp/c_all.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay at cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh at cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * 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 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 acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay at cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh at cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS 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 AUTHOR OR 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.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/evp.h>
-#ifndef OPENSSL_NO_ENGINE
-# include <openssl/engine.h>
-#endif
-
-void OPENSSL_add_all_algorithms_noconf(void)
-{
-    /*
-     * For the moment OPENSSL_cpuid_setup does something
-     * only on IA-32, but we reserve the option for all
-     * platforms...
-     */
-    OPENSSL_cpuid_setup();
-    OpenSSL_add_all_ciphers();
-    OpenSSL_add_all_digests();
-#ifndef OPENSSL_NO_ENGINE
-# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
-    ENGINE_setup_bsd_cryptodev();
-# endif
-#endif
-}
diff --git a/crypto/evp/c_allc.c b/crypto/evp/c_allc.c
index b59c33e..be6baf6 100644
--- a/crypto/evp/c_allc.c
+++ b/crypto/evp/c_allc.c
@@ -58,10 +58,11 @@
 #include <stdio.h>
 #include "internal/cryptlib.h"
 #include <openssl/evp.h>
+#include <internal/evp_int.h>
 #include <openssl/pkcs12.h>
 #include <openssl/objects.h>
 
-void OpenSSL_add_all_ciphers(void)
+void openssl_add_all_ciphers_internal(void)
 {
 
 #ifndef OPENSSL_NO_DES
diff --git a/crypto/evp/c_alld.c b/crypto/evp/c_alld.c
index 4309a0c..e28ba3d 100644
--- a/crypto/evp/c_alld.c
+++ b/crypto/evp/c_alld.c
@@ -58,10 +58,11 @@
 #include <stdio.h>
 #include "internal/cryptlib.h"
 #include <openssl/evp.h>
+#include <internal/evp_int.h>
 #include <openssl/pkcs12.h>
 #include <openssl/objects.h>
 
-void OpenSSL_add_all_digests(void)
+void openssl_add_all_digests_internal(void)
 {
 #ifndef OPENSSL_NO_MD4
     EVP_add_digest(EVP_md4());
diff --git a/crypto/evp/evp_acnf.c b/crypto/evp/evp_acnf.c
deleted file mode 100644
index 285be1f..0000000
--- a/crypto/evp/evp_acnf.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Written by Stephen Henson (steve at openssl.org) for the OpenSSL project
- * 2001.
- */
-/* ====================================================================
- * Copyright (c) 2001 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
- *    licensing at 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 at cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh at cryptsoft.com).
- *
- */
-
-#include "internal/cryptlib.h"
-#include <openssl/evp.h>
-#include <openssl/conf.h>
-
-/*
- * Load all algorithms and configure OpenSSL. This function is called
- * automatically when OPENSSL_LOAD_CONF is set.
- */
-
-void OPENSSL_add_all_algorithms_conf(void)
-{
-    OPENSSL_add_all_algorithms_noconf();
-    OPENSSL_config(NULL);
-}
diff --git a/crypto/evp/names.c b/crypto/evp/names.c
index 610e0f5..97a37a5 100644
--- a/crypto/evp/names.c
+++ b/crypto/evp/names.c
@@ -110,6 +110,8 @@ const EVP_CIPHER *EVP_get_cipherbyname(const char *name)
 {
     const EVP_CIPHER *cp;
 
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL);
+
     cp = (const EVP_CIPHER *)OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH);
     return (cp);
 }
@@ -118,6 +120,8 @@ const EVP_MD *EVP_get_digestbyname(const char *name)
 {
     const EVP_MD *cp;
 
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
+
     cp = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH);
     return (cp);
 }
@@ -161,6 +165,9 @@ void EVP_CIPHER_do_all(void (*fn) (const EVP_CIPHER *ciph,
                        void *arg)
 {
     struct doall_cipher dc;
+
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL);
+
     dc.fn = fn;
     dc.arg = arg;
     OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc);
@@ -171,6 +178,9 @@ void EVP_CIPHER_do_all_sorted(void (*fn) (const EVP_CIPHER *ciph,
                                           void *x), void *arg)
 {
     struct doall_cipher dc;
+
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL);
+
     dc.fn = fn;
     dc.arg = arg;
     OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc);
@@ -196,6 +206,9 @@ void EVP_MD_do_all(void (*fn) (const EVP_MD *md,
                    void *arg)
 {
     struct doall_md dc;
+
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
+
     dc.fn = fn;
     dc.arg = arg;
     OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
@@ -206,6 +219,9 @@ void EVP_MD_do_all_sorted(void (*fn) (const EVP_MD *md,
                                       void *x), void *arg)
 {
     struct doall_md dc;
+
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
+
     dc.fn = fn;
     dc.arg = arg;
     OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
diff --git a/include/openssl/pem2.h b/crypto/include/internal/async.h
similarity index 89%
copy from include/openssl/pem2.h
copy to crypto/include/internal/async.h
index 84897d5..e5d426b 100644
--- a/include/openssl/pem2.h
+++ b/crypto/include/internal/async.h
@@ -1,5 +1,8 @@
+/*
+ * Written by Matt Caswell for the OpenSSL project
+ */
 /* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ * 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
@@ -52,19 +55,7 @@
  *
  */
 
-/*
- * This header only exists to break a circular dependency between pem and err
- * Ben 30 Jan 1999.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <openssl/async.h>
 
-#ifndef HEADER_PEM_H
-void ERR_load_PEM_strings(void);
-#endif
+int async_init(void);
 
-#ifdef __cplusplus
-}
-#endif
diff --git a/include/openssl/pem2.h b/crypto/include/internal/conf.h
similarity index 89%
copy from include/openssl/pem2.h
copy to crypto/include/internal/conf.h
index 84897d5..8feaf62 100644
--- a/include/openssl/pem2.h
+++ b/crypto/include/internal/conf.h
@@ -1,5 +1,8 @@
+/*
+ * Written by Matt Caswell for the OpenSSL project
+ */
 /* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 2015 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
@@ -52,19 +55,8 @@
  *
  */
 
-/*
- * This header only exists to break a circular dependency between pem and err
- * Ben 30 Jan 1999.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <openssl/conf.h>
 
-#ifndef HEADER_PEM_H
-void ERR_load_PEM_strings(void);
-#endif
+void openssl_config_internal(const char *config_name);
+void openssl_no_config_internal(void);
 
-#ifdef __cplusplus
-}
-#endif
diff --git a/crypto/include/internal/bn_conf.h.in b/crypto/include/internal/cryptlib_int.h
similarity index 79%
copy from crypto/include/internal/bn_conf.h.in
copy to crypto/include/internal/cryptlib_int.h
index 5ebd55d..36c0a10 100644
--- a/crypto/include/internal/bn_conf.h.in
+++ b/crypto/include/internal/cryptlib_int.h
@@ -1,4 +1,6 @@
-{- join("\n",map { "/* $_ */" } @autowarntext) -}
+/*
+ * Written by Matt Caswell for the OpenSSL project.
+ */
 /* ====================================================================
  * Copyright (c) 2016 The OpenSSL Project.  All rights reserved.
  *
@@ -53,17 +55,24 @@
  *
  */
 
-#ifndef HEADER_BN_CONF_H
-# define HEADER_BN_CONF_H
+#include <internal/cryptlib.h>
 
-# if !defined(OPENSSL_SYS_UEFI)
+/* This file is not scanned by mkdef.pl, whereas cryptlib.h is */
 
-/* Should we define BN_DIV2W here? */
+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);
+/*
+ * 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
 
-/* Only one for the following should be defined */
-{- $config{b64l} ? "#define" : "#undef" -} SIXTY_FOUR_BIT_LONG
-{- $config{b64}  ? "#define" : "#undef" -} SIXTY_FOUR_BIT
-{- $config{b32}  ? "#define" : "#undef" -} THIRTY_TWO_BIT
-# endif
+/* OPENSSL_INIT_THREAD flags */
+# define OPENSSL_INIT_THREAD_ASYNC           0x01
+# define OPENSSL_INIT_THREAD_ERR_STATE       0x02
 
-#endif
diff --git a/include/openssl/pem2.h b/crypto/include/internal/engine.h
similarity index 87%
copy from include/openssl/pem2.h
copy to crypto/include/internal/engine.h
index 84897d5..4b70e55 100644
--- a/include/openssl/pem2.h
+++ b/crypto/include/internal/engine.h
@@ -1,5 +1,5 @@
 /* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ * 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
@@ -52,19 +52,12 @@
  *
  */
 
-/*
- * This header only exists to break a circular dependency between pem and err
- * Ben 30 Jan 1999.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef HEADER_PEM_H
-void ERR_load_PEM_strings(void);
-#endif
+#include <openssl/engine.h>
 
-#ifdef __cplusplus
-}
-#endif
+void engine_load_openssl_internal(void);
+void engine_load_cryptodev_internal(void);
+void engine_load_rdrand_internal(void);
+void engine_load_dynamic_internal(void);
+void engine_load_padlock_internal(void);
+void engine_load_capi_internal(void);
+void engine_load_dasync_internal(void);
diff --git a/test/nptest.c b/crypto/include/internal/err.h
similarity index 90%
copy from test/nptest.c
copy to crypto/include/internal/err.h
index 9528851..aa48019 100644
--- a/test/nptest.c
+++ b/crypto/include/internal/err.h
@@ -1,5 +1,8 @@
+/*
+ * Written by Matt Caswell for the OpenSSL project.
+ */
 /* ====================================================================
- * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
+ * 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
@@ -52,15 +55,4 @@
  *
  */
 
-
-#include <stdio.h>
-#include <string.h>
-
-int main()
-{
-    char *p = NULL;
-    char bytes[sizeof(p)];
-
-    memset(bytes, 0, sizeof bytes);
-    return memcmp(&p, bytes, sizeof(bytes)) == 0 ? 0 : 1;
-}
+void err_load_crypto_strings_intern(void);
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index 24c6870..2c9b2a3 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -415,3 +415,7 @@ struct evp_pkey_st {
     int save_parameters;
     STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
 } /* EVP_PKEY */ ;
+
+
+void openssl_add_all_ciphers_internal(void);
+void openssl_add_all_digests_internal(void);
diff --git a/crypto/init.c b/crypto/init.c
new file mode 100644
index 0000000..b9cc6a1
--- /dev/null
+++ b/crypto/init.c
@@ -0,0 +1,747 @@
+/*
+ * 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+#include <internal/cryptlib_int.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <internal/evp_int.h>
+#include <internal/conf.h>
+#include <internal/async.h>
+#include <internal/engine.h>
+#include <openssl/comp.h>
+#include <internal/err.h>
+#include <stdlib.h>
+
+static void ossl_init_thread_stop(struct thread_local_inits_st *locals);
+
+/* 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 <windows.h>
+
+# 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.h>
+
+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)
+{
+    /*
+     * OPENSSL_NO_AUTOERRINIT is provided here to prevent at compile time
+     * 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_intern()\n");
+# endif
+    err_load_crypto_strings_intern();
+#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
+    openssl_add_all_ciphers_internal();
+# 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
+    openssl_add_all_digests_internal();
+# 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
+    openssl_config_internal(config_filename);
+    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
+    openssl_no_config_internal();
+    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
+    async_init();
+    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
+    engine_load_openssl_internal();
+    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
+    engine_load_cryptodev_internal();
+    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
+    engine_load_rdrand_internal();
+    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
+    engine_load_dynamic_internal();
+    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
+    engine_load_padlock_internal();
+    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
+    engine_load_capi_internal();
+    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
+    engine_load_dasync_internal();
+    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;
+}
+
+static 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();
+}
+
+void OPENSSL_INIT_thread_stop(void)
+{
+    ossl_init_thread_stop(
+        (struct thread_local_inits_st *)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);
+
+    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) {
+        CRYPTO_w_lock(CRYPTO_LOCK_INIT);
+        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;
+        } else {
+            config_filename = NULL;
+        }
+        ossl_init_once_run(&config, ossl_init_config);
+        CRYPTO_w_unlock(CRYPTO_LOCK_INIT);
+    }
+
+    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/crypto/lock.c b/crypto/lock.c
index 2ac74b5..0925214 100644
--- a/crypto/lock.c
+++ b/crypto/lock.c
@@ -163,7 +163,8 @@ static const char *const lock_names[CRYPTO_NUM_LOCKS] = {
     "comp",
     "fips",
     "fips2",
-#if CRYPTO_NUM_LOCKS != 41
+    "init",
+#if CRYPTO_NUM_LOCKS != 42
 # error "Inconsistency between crypto.h and cryptlib.c"
 #endif
 };
diff --git a/doc/crypto/OPENSSL_INIT_crypto_library_start.pod b/doc/crypto/OPENSSL_INIT_crypto_library_start.pod
new file mode 100644
index 0000000..16f95fe
--- /dev/null
+++ b/doc/crypto/OPENSSL_INIT_crypto_library_start.pod
@@ -0,0 +1,227 @@
+=pod
+
+=head1 NAME
+
+OPENSSL_INIT_crypto_library_start, OPENSSL_INIT_library_stop,
+OPENSSL_INIT_register_stop_handler, OPENSSL_INIT_thread_stop - OpenSSL
+initialisation and deinitialisation functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/crypto.h>
+
+ 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));
+ void OPENSSL_INIT_thread_stop(void);
+
+=head1 DESCRIPTION
+
+During normal operation OpenSSL (libcrypto) will allocate various resources at
+start up that must, subsequently, be freed on close down of the library.
+Additionally some resources are allocated on a per thread basis (if the
+application is multi-threaded), and these resources must be freed prior to the
+thread closing.
+
+As of version 1.1.0 OpenSSL will automatically allocate all resources that it
+needs so no explicit initialisation is required. Similarly it will also
+automatically deinitialise as required.
+
+However, there way be situations when explicit initialisation is desirable or
+needed, for example when some non-default initialisation is required. The
+function OPENSSL_INIT_crypto_library_start() can be used for this purpose for
+libcrypto (see also L<OPENSSL_INIT_ssl_library_start(3)> for the libssl
+equivalent).
+
+Numerous internal OpenSSL functions call OPENSSL_INIT_crypto_library_start().
+Therefore, in order to perform non-default initialisation,
+OPENSSL_INIT_crypto_library_start() MUST be called by application code prior to
+any other OpenSSL function calls.
+
+The B<opts> parameter specifies which aspects of libcrypto should be
+initialised. Valid options are:
+
+=over 4
+
+=item OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS
+
+Suppress automatic loading of the libcrypto error strings. With this option the
+library will not automatically call ERR_load_crypto_strings(). This option is
+not a default option. Once selected subsequent calls to
+OPENSSL_INIT_crypto_library_start() with the option
+B<OPENSSL_INIT_LOAD_CRYPTO_STRINGS> will be ignored. Applications may call
+ERR_load_crypto_strings() directly if they wish even if this option has been
+selected. If they do so then they must also explicitly call ERR_free_strings()
+on application close down.
+
+=item OPENSSL_INIT_LOAD_CRYPTO_STRINGS
+
+Automatic loading of the libcrypto error strings. With this option the
+library will automatically call ERR_load_crypto_strings(). This option is a
+default option. Once selected subsequent calls to
+OPENSSL_INIT_crypto_library_start() with the option
+B<OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS> will be ignored.
+
+=item OPENSSL_INIT_ADD_ALL_CIPHERS
+
+With this option the library will automatically load and make available all
+libcrypto ciphers. This option is a default option. Once selected subsequent
+calls to OPENSSL_INIT_crypto_library_start() with the option
+B<OPENSSL_INIT_NO_ADD_ALL_CIPHERS> will be ignored.
+
+=item OPENSSL_INIT_ADD_ALL_DIGESTS
+
+With this option the library will automatically load and make available all
+libcrypto digests. This option is a default option. Once selected subsequent
+calls to OPENSSL_INIT_crypto_library_start() with the option
+B<OPENSSL_INIT_NO_ADD_ALL_CIPHERS> will be ignored.
+
+=item OPENSSL_INIT_NO_ADD_ALL_CIPHERS
+
+With this option the library will suppress automatic loading of libcrypto
+ciphers. This option is not a default option. Once selected subsequent
+calls to OPENSSL_INIT_crypto_library_start() with the option
+B<OPENSSL_INIT_ADD_ALL_CIPHERS> will be ignored.
+
+=item OPENSSL_INIT_NO_ADD_ALL_DIGESTS
+
+With this option the library will suppress automatic loading of libcrypto
+digests. This option is not a default option. Once selected subsequent
+calls to OPENSSL_INIT_crypto_library_start() with the option
+B<OPENSSL_INIT_ADD_ALL_DIGESTS> will be ignored.
+
+=item OPENSSL_INIT_LOAD_CONFIG
+
+With this option an OpenSSL configuration file will be automatically loaded and
+used by calling OPENSSL_config(). This is not a default option.
+
+=item OPENSSL_INIT_NO_LOAD_CONFIG
+
+With this option the loading of OpenSSL configuration files will be suppressed.
+It is the equivalent of calling OPENSSL_no_config(). This is not a default
+option.
+
+=item OPENSSL_INIT_ASYNC
+
+With this option the library with automatically initialise the libcrypto async
+sub-library (see L<ASYNC_start_job(3)>). This is a default option.
+
+=item OPENSSL_INIT_ENGINE_RDRAND
+
+With this option the library will automatically load and initialise the
+RDRAND engine (if available). This not a default option.
+
+=item OPENSSL_INIT_ENGINE_DYNAMIC
+
+With this option the library will automatically load and initialise the
+dynamic engine. This not a default option.
+
+=item OPENSSL_INIT_ENGINE_OPENSSL
+
+With this option the library will automatically load and initialise the
+openssl engine. This not a default option.
+
+=item OPENSSL_INIT_ENGINE_CRYPTODEV
+
+With this option the library will automatically load and initialise the
+cryptodev engine (if available). This not a default option.
+
+=item OPENSSL_INIT_ENGINE_CAPI
+
+With this option the library will automatically load and initialise the
+CAPI engine (if available). This not a default option.
+
+=item OPENSSL_INIT_ENGINE_PADLOCK
+
+With this option the library will automatically load and initialise the
+padlock engine (if available). This not a default option.
+
+=item OPENSSL_INIT_ENGINE_DASYNC
+
+With this option the library will automatically load and initialise the
+DASYNC engine. This not a default option.
+
+=item OPENSSL_INIT_ENGINE_ALL_BUILTIN
+
+With this option the library will automatically load and initialise all the
+built in engines listed above with the exception of the openssl and dasync
+engines. This not a default option.
+
+=back
+
+Multiple options may be combined together in a single call to
+OPENSSL_INIT_start_library(). For example:
+
+ OPENSSL_INIT_start_library(OPENSSL_INIT_NO_ADD_ALL_CIPHERS
+                            | OPENSSL_INIT_NO_ADD_ALL_DIGESTS, NULL);
+
+
+The B<settings> parameter to OPENSSL_INIT_start_library() may be used to
+provide optional settings values to an option. Currently the only option this
+applies to is OPENSSL_INIT_LOAD_CONFIG. This provides the optional
+OPENSSL_INIT_SET_CONF_FILENAME parameter to provide a filename to load
+configuration from. If no filename is provided then the system default
+configuration file is assumed. For example
+
+ const OPENSSL_INIT_SETTINGS settings[2] = {
+     { OPENSSL_INIT_SET_CONF_FILENAME, .value.type_string = "myconf.cnf" },
+     { OPENSSL_INIT_SET_END, .value.type_int = 0 }
+ };
+ OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_LOAD_CONFIG, settings);
+
+The B<settings> parameter must be an array of OPENSSL_INIT_SETTINGS values
+terminated with an OPENSSL_INIT_SET_END entry.
+
+The OPENSSL_INIT_library_stop() function deinitialises OpenSSL (both libcrypto
+and libssl). All resources allocated by OpenSSL are freed. Typically there
+should be no need to call this function directly as it is initiated
+automatically on application exit. This is done via the standard C library
+L<atexit(3)> function. In the event that the application will close in a manner
+that will not call the registered atexit() handlers then the application should
+call OPENSSL_INIT_library_stop() directly. Developers of libraries using OpenSSL
+are discouraged from calling this function and should instead, typically, rely
+on auto-deinitialisation. This is to avoid error conditions where both an
+application and a library it depends on both use OpenSSL, and the library
+deinitialises it before the application has finished using it.
+
+The OPENSSL_INIT_register_stop_handler() function enables the registration of a
+function to be called during OPENSSL_INIT_library_stop(). Stop handlers are
+called after deinitialisation of resources local to a thread, but before other
+process wide resources are freed. In the event that multiple stop handlers are
+registered, no guarantees are made about the order of execution.
+
+The OPENSSL_INIT_thread_stop() function deallocates resources associated
+with the current thread. Typically this function will be called automatically by
+the library when the thread exits. This should only be called directly if
+resources should be freed at an earlier time, or under the circumstances
+described in the NOTES section below.
+
+=head1 NOTES
+
+Resources local to a thread are deallocated automatically when the thread exits
+(e.g. in a pthreads environment, when pthread_exit() is called). On Windows
+platforms this is done in response to a DLL_THREAD_DETACH message being sent to
+the libeay32.dll entry point. Some windows functions may cause threads to exit
+without sending this message (for example ExitProcess()). If the application
+uses such functions, then the application must free up OpenSSL resources
+directly via a call to OPENSSL_INIT_thread_stop(). Similarly this message will
+also not be sent if OpenSSL is linked statically, and therefore applications
+using static linking should also call OPENSSL_INIT_thread_stop().
+
+=head1 RETURN VALUES
+
+The function OPENSSL_INIT_register_stop_handler() returns 1 on success or 0 on
+error.
+
+=head1 SEE ALSO
+
+L<OPENSSL_INIT_ssl_library_start(3)>
+
+=head1 HISTORY
+
+The OPENSSL_INIT_library_stop, OPENSSL_INIT_crypto_library_start,
+OPENSSL_INIT_register_stop_handler and OPENSSL_INIT_thread_stop functions were
+added in OpenSSL 1.1.0.
+
+=cut
diff --git a/doc/ssl/OPENSSL_INIT_ssl_library_start.pod b/doc/ssl/OPENSSL_INIT_ssl_library_start.pod
new file mode 100644
index 0000000..c0f598d
--- /dev/null
+++ b/doc/ssl/OPENSSL_INIT_ssl_library_start.pod
@@ -0,0 +1,80 @@
+=pod
+
+=head1 NAME
+
+OPENSSL_INIT_ssl_library_start - OpenSSL (libssl and libcrypto) initialisation
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ void OPENSSL_INIT_ssl_library_start(uint64_t opts,
+                                     const OPENSSL_INIT_SETTINGS *settings);
+
+=head1 DESCRIPTION
+
+During normal operation OpenSSL (libssl and libcrypto) will allocate various
+resources at start up that must, subsequently, be freed on close down of the
+library. Additionally some resources are allocated on a per thread basis (if the
+application is multi-threaded), and these resources must be freed prior to the
+thread closing.
+
+As of version 1.1.0 OpenSSL will automatically allocate all resources that it
+needs so no explicit initialisation is required. Similarly it will also
+automatically deinitialise as required.
+
+However, there way be situations when explicit initialisation is desirable or
+needed, for example when some non-default initialisation is required. The
+function OPENSSL_INIT_ssl_library_start() can be used for this purpose. Calling
+this function will explicitly initialise BOTH libcrypto and libssl. To
+explicitly initialise ONLY libcrypto see the
+L<OPENSSL_INIT_crypto_library_start(3)> function.
+
+Numerous internal OpenSSL functions call OPENSSL_INIT_ssl_library_start().
+Therefore, in order to perform non-default initialisation,
+OPENSSL_INIT_ssl_library_start() MUST be called by application code prior to
+any other OpenSSL function calls.
+
+The B<opts> parameter specifies which aspects of libssl and libcrypto should be
+initialised. Valid options for libcrypto are described on the
+L<OPENSSL_INIT_crypto_library_start(3)> page. In addition to any libcrypto
+specific option the following libssl options can also be used:
+
+=over 4
+
+=item OPENSSL_INIT_NO_LOAD_SSL_STRINGS
+
+Suppress automatic loading of the libssl error strings. With this option the
+library will not automatically call ERR_load_SSL_strings(). This option is
+not a default option. Once selected subsequent calls to
+OPENSSL_INIT_ssl_library_start() with the option
+B<OPENSSL_INIT_LOAD_SSL_STRINGS> will be ignored. Applications may call
+ERR_load_SSL_strings() directly if they wish even if this option has been
+selected. If they do so then they must also explicitly call ERR_free_strings()
+on application close down.
+
+=item OPENSSL_INIT_LOAD_SSL_STRINGS
+
+Automatic loading of the libssl error strings. With this option the
+library will automatically call ERR_load_SSL_strings(). This option is a
+default option. Once selected subsequent calls to
+OPENSSL_INIT_ssl_library_start() with the option
+B<OPENSSL_INIT_LOAD_SSL_STRINGS> will be ignored.
+
+=back
+
+The B<settings> parameter specifies optional settings values to an option.
+Currently no such settings are available for libssl specific options. However
+these settings will also be passed internally to a call to
+L<OPENSSL_INIT_crypto_library_start(3)>, so this parameter can also be used to
+provide libcrypto settings values.
+
+=head1 SEE ALSO
+
+L<OPENSSL_INIT_crypto_library_start(3)>
+
+=head1 HISTORY
+
+The OPENSSL_INIT_ssl_library_start function was added in OpenSSL 1.1.0.
+
+=cut
diff --git a/engines/e_capi.c b/engines/e_capi.c
index d3c9b8b..62c4ad3 100644
--- a/engines/e_capi.c
+++ b/engines/e_capi.c
@@ -187,6 +187,8 @@ static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
 static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
 # endif
 
+void engine_load_capi_internal(void);
+
 typedef PCCERT_CONTEXT(WINAPI *CERTDLG) (HCERTSTORE, HWND, LPCWSTR,
                                          LPCWSTR, DWORD, DWORD, void *);
 typedef HWND(WINAPI *GETCONSWIN) (void);
@@ -592,7 +594,7 @@ static ENGINE *engine_capi(void)
     return ret;
 }
 
-void ENGINE_load_capi(void)
+void engine_load_capi_internal(void)
 {
     /* Copied from eng_[openssl|dyn].c */
     ENGINE *toadd = engine_capi();
@@ -1874,7 +1876,8 @@ OPENSSL_EXPORT
 
 IMPLEMENT_DYNAMIC_CHECK_FN()
 # else
-void ENGINE_load_capi(void)
+void engine_load_capi_internal(void);
+void engine_load_capi_internal(void)
 {
 }
 # endif
diff --git a/engines/e_dasync.c b/engines/e_dasync.c
index 2f18d07..cca9f5e 100644
--- a/engines/e_dasync.c
+++ b/engines/e_dasync.c
@@ -59,6 +59,7 @@
 #include <openssl/evp.h>
 #include <openssl/async.h>
 #include <openssl/bn.h>
+#include <openssl/crypto.h>
 
 #define DASYNC_LIB_NAME "DASYNC"
 #include "e_dasync_err.c"
@@ -72,7 +73,7 @@ static const char *engine_dasync_name = "Dummy Async engine support";
 static int dasync_destroy(ENGINE *e);
 static int dasync_init(ENGINE *e);
 static int dasync_finish(ENGINE *e);
-void ENGINE_load_dasync(void);
+void engine_load_dasync_internal(void);
 
 
 /* Set up digests. Just SHA1 for now */
@@ -210,7 +211,7 @@ static ENGINE *engine_dasync(void)
     return ret;
 }
 
-void ENGINE_load_dasync(void)
+void engine_load_dasync_internal(void)
 {
     ENGINE *toadd = engine_dasync();
     if (!toadd)
diff --git a/engines/e_ossltest.c b/engines/e_ossltest.c
index a31e5a9..e641a44 100644
--- a/engines/e_ossltest.c
+++ b/engines/e_ossltest.c
@@ -66,6 +66,7 @@
 #include <openssl/evp.h>
 #include <openssl/modes.h>
 #include <openssl/aes.h>
+#include <openssl/crypto.h>
 
 #define OSSLTEST_LIB_NAME "OSSLTEST"
 #include "e_ossltest_err.c"
diff --git a/engines/e_padlock.c b/engines/e_padlock.c
index e5eecee..00732ed 100644
--- a/engines/e_padlock.c
+++ b/engines/e_padlock.c
@@ -112,8 +112,8 @@ static ENGINE *ENGINE_padlock(void);
 #  endif
 
 #  ifdef OPENSSL_NO_DYNAMIC_ENGINE
-
-void ENGINE_load_padlock(void)
+void engine_load_padlock_internal(void);
+void engine_load_padlock_internal(void)
 {
 /* On non-x86 CPUs it just returns. */
 #   ifdef COMPILE_HW_PADLOCK
diff --git a/include/openssl/async.h b/include/openssl/async.h
index 5ddfafb..8ec9b00 100644
--- a/include/openssl/async.h
+++ b/include/openssl/async.h
@@ -74,8 +74,6 @@ typedef struct async_job_st ASYNC_JOB;
 #define ASYNC_PAUSE    2
 #define ASYNC_FINISH   3
 
-int ASYNC_init(int init_thread, size_t max_size, size_t init_size);
-void ASYNC_cleanup(int cleanupthread);
 int ASYNC_init_thread(size_t max_size, size_t init_size);
 void ASYNC_cleanup_thread(void);
 
diff --git a/include/openssl/conf.h b/include/openssl/conf.h
index 6598107..9144c6d 100644
--- a/include/openssl/conf.h
+++ b/include/openssl/conf.h
@@ -138,7 +138,8 @@ int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out);
 int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out);
 
 void OPENSSL_config(const char *config_name);
-void OPENSSL_no_config(void);
+#define OPENSSL_no_config() \
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_NO_LOAD_CONFIG, NULL)
 
 /*
  * New conf code.  The semantics are different from the functions above. If
diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h
index 1251aa1..a5501c9 100644
--- a/include/openssl/crypto.h
+++ b/include/openssl/crypto.h
@@ -1,5 +1,5 @@
 /* ====================================================================
- * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-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
@@ -205,7 +205,8 @@ extern "C" {
 # define CRYPTO_LOCK_COMP                38
 # define CRYPTO_LOCK_FIPS                39
 # define CRYPTO_LOCK_FIPS2               40
-# define CRYPTO_NUM_LOCKS                41
+# define CRYPTO_LOCK_INIT                41
+# define CRYPTO_NUM_LOCKS                42
 
 # define CRYPTO_LOCK             1
 # define CRYPTO_UNLOCK           2
@@ -546,6 +547,62 @@ 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));
+void OPENSSL_INIT_thread_stop(void);
+
 /* BEGIN ERROR CODES */
 /*
  * The following lines are auto generated by the script mkerr.pl. Any changes
diff --git a/include/openssl/engine.h b/include/openssl/engine.h
index 58b2d7c..b5b4d07 100644
--- a/include/openssl/engine.h
+++ b/include/openssl/engine.h
@@ -387,23 +387,22 @@ int ENGINE_remove(ENGINE *e);
 /* Retrieve an engine from the list by its unique "id" value. */
 ENGINE *ENGINE_by_id(const char *id);
 /* Add all the built-in engines. */
-void ENGINE_load_openssl(void);
-void ENGINE_load_dynamic(void);
+#define ENGINE_load_openssl() \
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ENGINE_OPENSSL, NULL)
+#define ENGINE_load_dynamic() \
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ENGINE_DYNAMIC, NULL)
 # ifndef OPENSSL_NO_STATIC_ENGINE
-void ENGINE_load_4758cca(void);
-void ENGINE_load_aep(void);
-void ENGINE_load_atalla(void);
-void ENGINE_load_chil(void);
-void ENGINE_load_cswift(void);
-void ENGINE_load_nuron(void);
-void ENGINE_load_sureware(void);
-void ENGINE_load_ubsec(void);
-void ENGINE_load_padlock(void);
-void ENGINE_load_capi(void);
-void ENGINE_load_dasync(void);
+# define ENGINE_load_padlock() \
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ENGINE_PADLOCK, NULL)
+#define ENGINE_load_capi() \
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ENGINE_CAPI, NULL)
+#define ENGINE_load_dasync() \
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ENGINE_DASYNC, NULL)
 # endif
-void ENGINE_load_cryptodev(void);
-void ENGINE_load_rdrand(void);
+#define ENGINE_load_cryptodev() \
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ENGINE_CRYPTODEV, NULL)
+#define ENGINE_load_rdrand() \
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ENGINE_RDRAND, NULL)
 void ENGINE_load_builtin_engines(void);
 
 /*
diff --git a/include/openssl/err.h b/include/openssl/err.h
index 8baf6b7..f8742a4 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -354,7 +354,10 @@ void ERR_add_error_vdata(int num, va_list args);
 void ERR_load_strings(int lib, ERR_STRING_DATA str[]);
 void ERR_unload_strings(int lib, ERR_STRING_DATA str[]);
 void ERR_load_ERR_strings(void);
-void ERR_load_crypto_strings(void);
+
+#define ERR_load_crypto_strings() \
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
+
 void ERR_free_strings(void);
 
 void ERR_remove_thread_state(const CRYPTO_THREADID *tid);
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index a0d0d67..e3c75e9 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -870,19 +870,29 @@ const EVP_CIPHER *EVP_seed_cfb128(void);
 const EVP_CIPHER *EVP_seed_ofb(void);
 # endif
 
-void OPENSSL_add_all_algorithms_noconf(void);
-void OPENSSL_add_all_algorithms_conf(void);
+#  define OPENSSL_add_all_algorithms_conf() \
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ADD_ALL_CIPHERS \
+                                      | OPENSSL_INIT_ADD_ALL_DIGESTS \
+                                      | OPENSSL_INIT_LOAD_CONFIG, NULL)
+#  define OPENSSL_add_all_algorithms_noconf() \
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ADD_ALL_CIPHERS \
+                                      | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)
 
 # ifdef OPENSSL_LOAD_CONF
 #  define OpenSSL_add_all_algorithms() \
-                OPENSSL_add_all_algorithms_conf()
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ADD_ALL_CIPHERS \
+                                      | OPENSSL_INIT_ADD_ALL_DIGESTS \
+                                      | OPENSSL_INIT_LOAD_CONFIG, NULL)
 # else
 #  define OpenSSL_add_all_algorithms() \
-                OPENSSL_add_all_algorithms_noconf()
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ADD_ALL_CIPHERS \
+                                      | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)
 # endif
 
-void OpenSSL_add_all_ciphers(void);
-void OpenSSL_add_all_digests(void);
+#  define OpenSSL_add_all_ciphers() \
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL)
+#  define OpenSSL_add_all_digests() \
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)
 
 int EVP_add_cipher(const EVP_CIPHER *cipher);
 int EVP_add_digest(const EVP_MD *digest);
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 7bc46c5..51e5f99 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1443,7 +1443,10 @@ __owur int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
 int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
                                        const char *dir);
 
-void SSL_load_error_strings(void);
+#define SSL_load_error_strings() \
+    OPENSSL_INIT_ssl_library_start(OPENSSL_INIT_LOAD_SSL_STRINGS \
+                                   | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
+
 __owur const char *SSL_state_string(const SSL *s);
 __owur const char *SSL_rstate_string(const SSL *s);
 __owur const char *SSL_state_string_long(const SSL *s);
@@ -1673,7 +1676,7 @@ void SSL_set_accept_state(SSL *s);
 
 __owur long SSL_get_default_timeout(const SSL *s);
 
-int SSL_library_init(void);
+#define SSL_library_init() OPENSSL_INIT_ssl_library_start(0, NULL)
 
 __owur char *SSL_CIPHER_description(const SSL_CIPHER *, char *buf, int size);
 __owur STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk);
@@ -1927,6 +1930,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/include/openssl/symhacks.h b/include/openssl/symhacks.h
index 8e0edfc..f78a584 100644
--- a/include/openssl/symhacks.h
+++ b/include/openssl/symhacks.h
@@ -220,10 +220,6 @@
 #  define OCSP_SINGLERESP_get_ext_by_critical     OCSP_SINGLERESP_get_ext_by_crit
 
 /* Hack some long EVP names */
-#  undef OPENSSL_add_all_algorithms_noconf
-#  define OPENSSL_add_all_algorithms_noconf       OPENSSL_add_all_algo_noconf
-#  undef OPENSSL_add_all_algorithms_conf
-#  define OPENSSL_add_all_algorithms_conf         OPENSSL_add_all_algo_conf
 #  undef EVP_PKEY_meth_set_verify_recover
 #  define EVP_PKEY_meth_set_verify_recover        EVP_PKEY_meth_set_vrfy_recover
 
diff --git a/ssl/Makefile.in b/ssl/Makefile.in
index 586d287..cf507ae 100644
--- a/ssl/Makefile.in
+++ b/ssl/Makefile.in
@@ -23,9 +23,9 @@ LIBSRC=	\
 	methods.c   t1_lib.c  t1_enc.c t1_ext.c \
 	d1_lib.c  record/rec_layer_d1.c d1_msg.c \
 	statem/statem_dtls.c d1_srtp.c \
-	ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
+	ssl_lib.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_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
@@ -36,9 +36,9 @@ LIBOBJ= \
 	methods.o   t1_lib.o  t1_enc.o t1_ext.o \
 	d1_lib.o  record/rec_layer_d1.o d1_msg.o \
 	statem/statem_dtls.o d1_srtp.o\
-	ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
+	ssl_lib.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_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/build.info b/ssl/build.info
index e6c7394..6977246 100644
--- a/ssl/build.info
+++ b/ssl/build.info
@@ -6,9 +6,9 @@ SOURCE[../libssl]=\
         methods.c   t1_lib.c  t1_enc.c t1_ext.c \
         d1_lib.c  record/rec_layer_d1.c d1_msg.c \
         statem/statem_dtls.c d1_srtp.c \
-        ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
+        ssl_lib.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_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
diff --git a/ssl/ssl-lib.com b/ssl/ssl-lib.com
index 5d2b5dd..5ccdbf3 100644
--- a/ssl/ssl-lib.com
+++ b/ssl/ssl-lib.com
@@ -211,9 +211,9 @@ $ LIB_SSL = "s3_srvr, s3_clnt, s3_lib, s3_enc,s3_pkt,s3_both,s3_cbc,"+ -
 	    "t1_meth,  t1_srvr, t1_clnt, t1_lib, t1_enc,       t1_ext,"+ -
 	    "d1_meth,  d1_srvr, d1_clnt, d1_lib,        d1_pkt,"+ -
 	    "d1_both,d1_srtp,"+ -
-	    "ssl_lib,ssl_err2,ssl_cert,ssl_sess,"+ -
+	    "ssl_lib,ssl_cert,ssl_sess,"+ -
 	    "ssl_ciph,ssl_stat,ssl_rsa,"+ -
-	    "ssl_asn1,ssl_txt,ssl_algs,ssl_conf,"+ -
+	    "ssl_asn1,ssl_txt,ssl_init,ssl_conf,"+ -
 	    "bio_ssl,ssl_err,t1_reneg,tls_srp,t1_trce,ssl_utst"
 $!
 $! Tell The User That We Are Compiling The Library.
diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c
deleted file mode 100644
index 61233a9..0000000
--- a/ssl/ssl_algs.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay at cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh at cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * 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 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 acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay at cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh at cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS 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 AUTHOR OR 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.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-#include <stdio.h>
-#include <openssl/objects.h>
-#include <openssl/lhash.h>
-#include "ssl_locl.h"
-
-int SSL_library_init(void)
-{
-
-#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
-    /*
-     * 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();
-    SSL_add_ssl_module();
-    return (1);
-}
diff --git a/ssl/ssl_err2.c b/ssl/ssl_err2.c
deleted file mode 100644
index 751f6ad..0000000
--- a/ssl/ssl_err2.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay at cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh at cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * 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 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 acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay at cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh at cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS 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 AUTHOR OR 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.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-#include <stdio.h>
-#include <openssl/err.h>
-#include <openssl/ssl.h>
-
-void SSL_load_error_strings(void)
-{
-#ifndef OPENSSL_NO_ERR
-    ERR_load_crypto_strings();
-    ERR_load_SSL_strings();
-#endif
-}
diff --git a/ssl/ssl_init.c b/ssl/ssl_init.c
new file mode 100644
index 0000000..f1aa2c4
--- /dev/null
+++ b/ssl/ssl_init.c
@@ -0,0 +1,317 @@
+/*
+ * 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+#include "e_os.h"
+
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#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 <windows.h>
+
+# 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 <pthread.h>
+
+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)
+{
+    /*
+     * OPENSSL_NO_AUTOERRINIT is provided here to prevent at compile time
+     * 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_ssl_strings: "
+                        "ERR_load_SSL_strings()\n");
+# endif
+    ERR_load_SSL_strings();
+#endif
+    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/ssl/ssl_lib.c b/ssl/ssl_lib.c
index fc72d39..127399d 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2270,6 +2270,8 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
         return (NULL);
     }
 
+    OPENSSL_INIT_ssl_library_start(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
+
     if (FIPS_mode() && (meth->version < TLS1_VERSION)) {
         SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE);
         return NULL;
diff --git a/test/asynctest.c b/test/asynctest.c
index 1068e8c..ddff70c 100644
--- a/test/asynctest.c
+++ b/test/asynctest.c
@@ -123,12 +123,12 @@ static int blockpause(void *args)
     return 1;
 }
 
-static int test_ASYNC_init()
+static int test_ASYNC_init_thread()
 {
     ASYNC_JOB *job1 = NULL, *job2 = NULL, *job3 = NULL;
     int funcret1, funcret2, funcret3;
 
-    if (       !ASYNC_init(1, 2, 0)
+    if (       !ASYNC_init_thread(2, 0)
             || ASYNC_start_job(&job1, &funcret1, only_pause, NULL, 0)
                 != ASYNC_PAUSE
             || ASYNC_start_job(&job2, &funcret2, only_pause, NULL, 0)
@@ -146,12 +146,12 @@ static int test_ASYNC_init()
             || funcret1 != 1
             || funcret2 != 1
             || funcret3 != 1) {
-        fprintf(stderr, "test_ASYNC_init() failed\n");
-        ASYNC_cleanup(1);
+        fprintf(stderr, "test_ASYNC_init_thread() failed\n");
+        ASYNC_cleanup_thread();
         return 0;
     }
 
-    ASYNC_cleanup(1);
+    ASYNC_cleanup_thread();
     return 1;
 }
 
@@ -162,18 +162,18 @@ static int test_ASYNC_start_job()
 
     ctr = 0;
 
-    if (       !ASYNC_init(1, 1, 0)
+    if (       !ASYNC_init_thread(1, 0)
             || ASYNC_start_job(&job, &funcret, add_two, NULL, 0) != ASYNC_PAUSE
             || ctr != 1
             || ASYNC_start_job(&job, &funcret, add_two, NULL, 0) != ASYNC_FINISH
             || ctr != 2
             || funcret != 2) {
         fprintf(stderr, "test_ASYNC_start_job() failed\n");
-        ASYNC_cleanup(1);
+        ASYNC_cleanup_thread();
         return 0;
     }
 
-    ASYNC_cleanup(1);
+    ASYNC_cleanup_thread();
     return 1;
 }
 
@@ -184,7 +184,7 @@ static int test_ASYNC_get_current_job()
 
     currjob = NULL;
 
-    if (       !ASYNC_init(1, 1, 0)
+    if (       !ASYNC_init_thread(1, 0)
             || ASYNC_start_job(&job, &funcret, save_current, NULL, 0)
                 != ASYNC_PAUSE
             || currjob != job
@@ -192,11 +192,11 @@ static int test_ASYNC_get_current_job()
                 != ASYNC_FINISH
             || funcret != 1) {
         fprintf(stderr, "test_ASYNC_get_current_job() failed\n");
-        ASYNC_cleanup(1);
+        ASYNC_cleanup_thread();
         return 0;
     }
 
-    ASYNC_cleanup(1);
+    ASYNC_cleanup_thread();
     return 1;
 }
 
@@ -229,7 +229,7 @@ static int test_ASYNC_get_wait_fd()
     int funcret;
     OSSL_ASYNC_FD fd;
 
-    if (       !ASYNC_init(1, 1, 0)
+    if (       !ASYNC_init_thread(1, 0)
             || ASYNC_start_job(&job, &funcret, wake, NULL, 0)
                 != ASYNC_PAUSE
             || (fd = ASYNC_get_wait_fd(job)) < 0
@@ -245,11 +245,11 @@ static int test_ASYNC_get_wait_fd()
                 != ASYNC_FINISH
             || funcret != 1) {
         fprintf(stderr, "test_ASYNC_get_wait_fd() failed\n");
-        ASYNC_cleanup(1);
+        ASYNC_cleanup_thread();
         return 0;
     }
 
-    ASYNC_cleanup(1);
+    ASYNC_cleanup_thread();
     return 1;
 }
 
@@ -258,18 +258,18 @@ static int test_ASYNC_block_pause()
     ASYNC_JOB *job = NULL;
     int funcret;
 
-    if (       !ASYNC_init(1, 1, 0)
+    if (       !ASYNC_init_thread(1, 0)
             || ASYNC_start_job(&job, &funcret, blockpause, NULL, 0)
                 != ASYNC_PAUSE
             || ASYNC_start_job(&job, &funcret, blockpause, NULL, 0)
                 != ASYNC_FINISH
             || funcret != 1) {
         fprintf(stderr, "test_ASYNC_block_pause() failed\n");
-        ASYNC_cleanup(1);
+        ASYNC_cleanup_thread();
         return 0;
     }
 
-    ASYNC_cleanup(1);
+    ASYNC_cleanup_thread();
     return 1;
 }
 
@@ -284,7 +284,7 @@ int main(int argc, char **argv)
     CRYPTO_set_mem_debug(1);
     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 
-    if (       !test_ASYNC_init()
+    if (       !test_ASYNC_init_thread()
             || !test_ASYNC_start_job()
             || !test_ASYNC_get_current_job()
             || !test_ASYNC_get_wait_fd()
diff --git a/test/bntest.c b/test/bntest.c
index d315ad8..082cf4c 100644
--- a/test/bntest.c
+++ b/test/bntest.c
@@ -345,7 +345,7 @@ int main(int argc, char *argv[])
                                  * notices the failure, see test_bn in
                                  * test/Makefile.ssl */
     (void)BIO_flush(out);
-    ERR_load_crypto_strings();
+
     ERR_print_errors_fp(stderr);
     EXIT(1);
 }
diff --git a/test/clienthellotest.c b/test/clienthellotest.c
index d9ae758..8775661 100644
--- a/test/clienthellotest.c
+++ b/test/clienthellotest.c
@@ -103,9 +103,6 @@ int main(int argc, char *argv[])
     int testresult = 0;
     int currtest = 0;
 
-    SSL_library_init();
-    SSL_load_error_strings();
-
     err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
 
     CRYPTO_set_mem_debug(1);
@@ -212,10 +209,6 @@ int main(int argc, char *argv[])
         }
     }
 
-    ERR_free_strings();
-    ERR_remove_thread_state(NULL);
-    EVP_cleanup();
-    CRYPTO_cleanup_all_ex_data();
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks(err) <= 0)
         testresult = 0;
diff --git a/test/danetest.c b/test/danetest.c
index b9ccd40..01f7731 100644
--- a/test/danetest.c
+++ b/test/danetest.c
@@ -493,8 +493,6 @@ int main(int argc, char *argv[])
         return 0;
     }
 
-    SSL_library_init();
-    SSL_load_error_strings();
 
     ctx = SSL_CTX_new(TLS_client_method());
     if (SSL_CTX_dane_enable(ctx) <= 0) {
@@ -526,14 +524,6 @@ end:
     (void) fclose(f);
     SSL_CTX_free(ctx);
 
-#ifndef OPENSSL_NO_ENGINE
-    ENGINE_cleanup();
-#endif
-    CONF_modules_unload(1);
-    CRYPTO_cleanup_all_ex_data();
-    ERR_free_strings();
-    ERR_remove_thread_state(NULL);
-    EVP_cleanup();
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks(bio_err) <= 0)
         ret = 1;
diff --git a/test/dsatest.c b/test/dsatest.c
index f36b449..b53ee47 100644
--- a/test/dsatest.c
+++ b/test/dsatest.c
@@ -140,7 +140,6 @@ int main(int argc, char **argv)
     CRYPTO_set_mem_debug(1);
     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 
-    ERR_load_crypto_strings();
     RAND_seed(rnd_seed, sizeof rnd_seed);
 
     BIO_printf(bio_err, "test generation of DSA parameters\n");
@@ -211,9 +210,7 @@ int main(int argc, char **argv)
         ERR_print_errors(bio_err);
     DSA_free(dsa);
     BN_GENCB_free(cb);
-    CRYPTO_cleanup_all_ex_data();
-    ERR_remove_thread_state(NULL);
-    ERR_free_strings();
+
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks(bio_err) <= 0)
         ret = 0;
diff --git a/test/ecdhtest.c b/test/ecdhtest.c
index e26fddf..e37a020 100644
--- a/test/ecdhtest.c
+++ b/test/ecdhtest.c
@@ -509,8 +509,7 @@ int main(int argc, char *argv[])
     OPENSSL_free(curves);
     BN_CTX_free(ctx);
     BIO_free(out);
-    CRYPTO_cleanup_all_ex_data();
-    ERR_remove_thread_state(NULL);
+
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks_fp(stderr) <= 0)
         ret = 1;
diff --git a/test/ecdsatest.c b/test/ecdsatest.c
index feb9f0a..55ebad9 100644
--- a/test/ecdsatest.c
+++ b/test/ecdsatest.c
@@ -522,7 +522,6 @@ int main(void)
     p = getenv("OPENSSL_DEBUG_MEMORY");
     if (p != NULL && strcmp(p, "on") == 0)
         CRYPTO_set_mem_debug(1);
-    ERR_load_crypto_strings();
 
     /* initialize the prng */
     RAND_seed(rnd_seed, sizeof(rnd_seed));
@@ -541,9 +540,7 @@ int main(void)
         BIO_printf(out, "\nECDSA test passed\n");
     if (ret)
         ERR_print_errors(out);
-    CRYPTO_cleanup_all_ex_data();
-    ERR_remove_thread_state(NULL);
-    ERR_free_strings();
+
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks(out) <= 0)
         ret = 1;
diff --git a/test/ectest.c b/test/ectest.c
index 03dfed9..0abb545 100644
--- a/test/ectest.c
+++ b/test/ectest.c
@@ -1665,7 +1665,6 @@ int main(int argc, char *argv[])
     if (p != NULL && strcmp(p, "on") == 0)
         CRYPTO_set_mem_debug(1);
     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
-    ERR_load_crypto_strings();
 
     RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */
 
@@ -1680,12 +1679,6 @@ int main(int argc, char *argv[])
     /* test the internal curves */
     internal_curve_test();
 
-# ifndef OPENSSL_NO_ENGINE
-    ENGINE_cleanup();
-# endif
-    CRYPTO_cleanup_all_ex_data();
-    ERR_free_strings();
-    ERR_remove_thread_state(NULL);
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks_fp(stderr) <= 0)
         return 1;
diff --git a/test/enginetest.c b/test/enginetest.c
index d8dcca9..873b4ea 100644
--- a/test/enginetest.c
+++ b/test/enginetest.c
@@ -109,7 +109,6 @@ int main(int argc, char *argv[])
     p = getenv("OPENSSL_DEBUG_MEMORY");
     if (p != NULL && strcmp(p, "on") == 0)
         CRYPTO_set_mem_debug(1);
-    ERR_load_crypto_strings();
 
     memset(block, 0, sizeof(block));
     if (((new_h1 = ENGINE_new()) == NULL) ||
@@ -244,10 +243,7 @@ int main(int argc, char *argv[])
     ENGINE_free(new_h4);
     for (loop = 0; loop < 512; loop++)
         ENGINE_free(block[loop]);
-    ENGINE_cleanup();
-    CRYPTO_cleanup_all_ex_data();
-    ERR_free_strings();
-    ERR_remove_thread_state(NULL);
+
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks_fp(stderr) <= 0)
         to_return = 1;
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index 53844ad..dbcfb7c 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -422,10 +422,6 @@ int main(void)
     CRYPTO_set_mem_debug(1);
     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 
-    ERR_load_crypto_strings();
-    /* Load up the software EVP_CIPHER and EVP_MD definitions */
-    OpenSSL_add_all_ciphers();
-    OpenSSL_add_all_digests();
 
     if (!test_EVP_DigestSignInit()) {
         fprintf(stderr, "EVP_DigestSignInit failed\n");
@@ -462,10 +458,6 @@ int main(void)
     }
 #endif
 
-    EVP_cleanup();
-    CRYPTO_cleanup_all_ex_data();
-    ERR_remove_thread_state(NULL);
-    ERR_free_strings();
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks_fp(stderr) <= 0)
         return 1;
diff --git a/test/evp_test.c b/test/evp_test.c
index ff2ee10..6bc3a8a 100644
--- a/test/evp_test.c
+++ b/test/evp_test.c
@@ -592,9 +592,6 @@ int main(int argc, char **argv)
 
     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 
-    ERR_load_crypto_strings();
-    OpenSSL_add_all_algorithms();
-
     memset(&t, 0, sizeof(t));
     t.start_line = -1;
     in = fopen(argv[1], "r");
@@ -612,10 +609,7 @@ int main(int argc, char **argv)
     free_key_list(t.public);
     free_key_list(t.private);
     fclose(in);
-    EVP_cleanup();
-    CRYPTO_cleanup_all_ex_data();
-    ERR_remove_thread_state(NULL);
-    ERR_free_strings();
+
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks_fp(stderr) <= 0)
         return 1;
diff --git a/test/exptest.c b/test/exptest.c
index 5cd79e2..84d76be 100644
--- a/test/exptest.c
+++ b/test/exptest.c
@@ -194,8 +194,6 @@ int main(int argc, char *argv[])
                                            * don't even check its return
                                            * value (which we should) */
 
-    ERR_load_BN_strings();
-
     ctx = BN_CTX_new();
     if (ctx == NULL)
         EXIT(1);
@@ -298,7 +296,7 @@ int main(int argc, char *argv[])
     BN_free(b);
     BN_free(m);
     BN_CTX_free(ctx);
-    ERR_remove_thread_state(NULL);
+
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks(out) <= 0)
         goto err;
@@ -313,7 +311,6 @@ int main(int argc, char *argv[])
 
     EXIT(0);
  err:
-    ERR_load_crypto_strings();
     ERR_print_errors(out);
 #ifdef OPENSSL_SYS_NETWARE
     printf("ERROR\n");
diff --git a/test/heartbeat_test.c b/test/heartbeat_test.c
index 137aa9b..dd7bf11 100644
--- a/test/heartbeat_test.c
+++ b/test/heartbeat_test.c
@@ -440,9 +440,6 @@ int main(int argc, char *argv[])
 {
     int result = 0;
 
-    SSL_library_init();
-    SSL_load_error_strings();
-
     ADD_TEST(test_dtls1_not_bleeding);
     ADD_TEST(test_dtls1_not_bleeding_empty_payload);
     ADD_TEST(test_dtls1_heartbleed);
diff --git a/test/jpaketest.c b/test/jpaketest.c
index 7b59855..2b61705 100644
--- a/test/jpaketest.c
+++ b/test/jpaketest.c
@@ -121,8 +121,6 @@ int main(int argc, char **argv)
     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 #endif
 
-    ERR_load_crypto_strings();
-
     /*-
     BN_hex2bn(&p, "fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b76b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7");
     BN_hex2bn(&g, "f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d0782675159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e13c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243bcca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a");
@@ -175,9 +173,6 @@ int main(int argc, char **argv)
     BN_free(g);
     BN_free(p);
 
-    CRYPTO_cleanup_all_ex_data();
-    ERR_remove_thread_state(NULL);
-    ERR_free_strings();
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks(bio_err) <= 0)
         return 1;
diff --git a/test/methtest.c b/test/methtest.c
index adfb244..efec154 100644
--- a/test/methtest.c
+++ b/test/methtest.c
@@ -99,7 +99,6 @@ char *argv[];
     METH_control(tmp2, METH_CONTROL_DUMP, stdout);
     EXIT(0);
  err:
-    ERR_load_crypto_strings();
     ERR_print_errors_fp(stderr);
     EXIT(1);
     return (0);
diff --git a/test/p5_crpt2_test.c b/test/p5_crpt2_test.c
index 2c998ba..2c136b6 100644
--- a/test/p5_crpt2_test.c
+++ b/test/p5_crpt2_test.c
@@ -183,11 +183,7 @@ int main(int argc, char **argv)
     CRYPTO_set_mem_debug(1);
     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 
-    OpenSSL_add_all_digests();
-# ifndef OPENSSL_NO_ENGINE
-    ENGINE_load_builtin_engines();
-    ENGINE_register_all_digests();
-# endif
+    OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL);
 
     printf("PKCS5_PBKDF2_HMAC() tests ");
     for (i = 0; test->pass != NULL; i++, test++) {
@@ -198,13 +194,6 @@ int main(int argc, char **argv)
     }
     printf(" done\n");
 
-# ifndef OPENSSL_NO_ENGINE
-    ENGINE_cleanup();
-# endif
-    EVP_cleanup();
-    CRYPTO_cleanup_all_ex_data();
-    ERR_remove_thread_state(NULL);
-    ERR_free_strings();
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks_fp(stderr) <= 0)
         return 1;
diff --git a/test/rsa_test.c b/test/rsa_test.c
index 9f1f3d6..770c376 100644
--- a/test/rsa_test.c
+++ b/test/rsa_test.c
@@ -324,9 +324,6 @@ int main(int argc, char *argv[])
         RSA_free(key);
     }
 
-    CRYPTO_cleanup_all_ex_data();
-    ERR_remove_thread_state(NULL);
-
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks_fp(stderr) <= 0)
         err = 1;
diff --git a/test/srptest.c b/test/srptest.c
index 442a610..8379535 100644
--- a/test/srptest.c
+++ b/test/srptest.c
@@ -129,7 +129,6 @@ int main(int argc, char **argv)
     CRYPTO_set_mem_debug(1);
     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 
-    ERR_load_crypto_strings();
 
     /* "Negative" test, expect a mismatch */
     if (run_srp("alice", "password1", "password2") == 0) {
@@ -143,9 +142,6 @@ int main(int argc, char **argv)
         return 1;
     }
 
-    CRYPTO_cleanup_all_ex_data();
-    ERR_remove_thread_state(NULL);
-    ERR_free_strings();
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks(bio_err) <= 0)
         return 1;
diff --git a/test/ssltest.c b/test/ssltest.c
index f217a20..b5d44a0 100644
--- a/test/ssltest.c
+++ b/test/ssltest.c
@@ -1410,7 +1410,6 @@ int main(int argc, char *argv[])
 #ifdef OPENSSL_FIPS
     if (fips_mode) {
         if (!FIPS_mode_set(1)) {
-            ERR_load_crypto_strings();
             ERR_print_errors(bio_err);
             EXIT(1);
         } else
@@ -1430,9 +1429,6 @@ int main(int argc, char *argv[])
 
 /*      if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */
 
-    SSL_library_init();
-    SSL_load_error_strings();
-
 #ifndef OPENSSL_NO_COMP
     if (comp == COMP_ZLIB)
         cm = COMP_zlib();
@@ -1856,14 +1852,6 @@ int main(int argc, char *argv[])
 
     BIO_free(bio_stdout);
 
-#ifndef OPENSSL_NO_ENGINE
-    ENGINE_cleanup();
-#endif
-    CONF_modules_unload(1);
-    CRYPTO_cleanup_all_ex_data();
-    ERR_free_strings();
-    ERR_remove_thread_state(NULL);
-    EVP_cleanup();
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks(bio_err) <= 0)
         ret = 1;
diff --git a/test/verify_extra_test.c b/test/verify_extra_test.c
index 31c391e..8362de4 100644
--- a/test/verify_extra_test.c
+++ b/test/verify_extra_test.c
@@ -190,9 +190,6 @@ int main(int argc, char **argv)
     CRYPTO_set_mem_debug(1);
     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 
-    ERR_load_crypto_strings();
-    OpenSSL_add_all_digests();
-
     if (argc != 4) {
         fprintf(stderr, "usage: verify_extra_test roots.pem untrusted.pem bad.pem\n");
         return 1;
@@ -203,10 +200,6 @@ int main(int argc, char **argv)
         return 1;
     }
 
-    EVP_cleanup();
-    CRYPTO_cleanup_all_ex_data();
-    ERR_remove_thread_state(NULL);
-    ERR_free_strings();
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     if (CRYPTO_mem_leaks_fp(stderr) <= 0)
         return 1;
diff --git a/util/libeay.num b/util/libeay.num
index e0f9559..48b235b 100755
--- a/util/libeay.num
+++ b/util/libeay.num
@@ -234,7 +234,7 @@ ERR_load_PEM_strings                    242	1_1_0	EXIST::FUNCTION:
 ERR_load_PROXY_strings                  243	1_1_0	NOEXIST::FUNCTION:
 ERR_load_RSA_strings                    244	1_1_0	EXIST::FUNCTION:RSA
 ERR_load_X509_strings                   245	1_1_0	EXIST::FUNCTION:
-ERR_load_crypto_strings                 246	1_1_0	EXIST::FUNCTION:
+ERR_load_crypto_strings                 246	1_1_0	NOEXIST::FUNCTION:
 ERR_load_strings                        247	1_1_0	EXIST::FUNCTION:
 ERR_peek_error                          248	1_1_0	EXIST::FUNCTION:
 ERR_peek_error_line                     249	1_1_0	EXIST::FUNCTION:
@@ -497,8 +497,8 @@ SHA_Final                               505	1_1_0	NOEXIST::FUNCTION:
 SHA_Init                                506	1_1_0	NOEXIST::FUNCTION:
 SHA_Update                              507	1_1_0	NOEXIST::FUNCTION:
 OpenSSL_add_all_algorithms              508	1_1_0	NOEXIST::FUNCTION:
-OpenSSL_add_all_ciphers                 509	1_1_0	EXIST::FUNCTION:
-OpenSSL_add_all_digests                 510	1_1_0	EXIST::FUNCTION:
+OpenSSL_add_all_ciphers                 509	1_1_0	NOEXIST::FUNCTION:
+OpenSSL_add_all_digests                 510	1_1_0	NOEXIST::FUNCTION:
 TXT_DB_create_index                     511	1_1_0	EXIST::FUNCTION:
 TXT_DB_free                             512	1_1_0	EXIST::FUNCTION:
 TXT_DB_get_by_index                     513	1_1_0	EXIST::FUNCTION:
@@ -1965,7 +1965,7 @@ X509_REVOKED_set_serialNumber           2543	1_1_0	EXIST::FUNCTION:
 X509_print_ex                           2544	1_1_0	EXIST::FUNCTION:
 OCSP_ONEREQ_get1_ext_d2i                2545	1_1_0	EXIST::FUNCTION:
 ENGINE_register_all_RAND                2546	1_1_0	EXIST::FUNCTION:ENGINE
-ENGINE_load_dynamic                     2547	1_1_0	EXIST::FUNCTION:ENGINE
+ENGINE_load_dynamic                     2547	1_1_0	NOEXIST::FUNCTION:
 PBKDF2PARAM_it                          2548	1_1_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
 PBKDF2PARAM_it                          2548	1_1_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
 EXTENDED_KEY_USAGE_new                  2549	1_1_0	EXIST::FUNCTION:
@@ -2046,7 +2046,7 @@ SXNET_it                                2613	1_1_0	EXIST:EXPORT_VAR_AS_FUNCTION:
 UI_dup_input_boolean                    2614	1_1_0	EXIST::FUNCTION:
 PKCS12_add_CSPName_asc                  2615	1_1_0	EXIST::FUNCTION:
 EC_POINT_is_at_infinity                 2616	1_1_0	EXIST::FUNCTION:EC
-ENGINE_load_cryptodev                   2617	1_1_0	EXIST::FUNCTION:ENGINE
+ENGINE_load_cryptodev                   2617	1_1_0	NOEXIST::FUNCTION:
 DSO_convert_filename                    2618	1_1_0	EXIST::FUNCTION:
 POLICYQUALINFO_it                       2619	1_1_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
 POLICYQUALINFO_it                       2619	1_1_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
@@ -2068,7 +2068,7 @@ PKCS7_ATTR_SIGN_it                      2632	1_1_0	EXIST:EXPORT_VAR_AS_FUNCTION:
 UI_add_error_string                     2633	1_1_0	EXIST::FUNCTION:
 KRB5_CHECKSUM_free                      2634	1_1_0	NOEXIST::FUNCTION:
 OCSP_REQUEST_get_ext                    2635	1_1_0	EXIST::FUNCTION:
-ENGINE_load_ubsec                       2636	1_1_0	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ENGINE_load_ubsec                       2636	1_1_0	NOEXIST::FUNCTION:
 ENGINE_register_all_digests             2637	1_1_0	EXIST::FUNCTION:ENGINE
 PKEY_USAGE_PERIOD_it                    2638	1_1_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
 PKEY_USAGE_PERIOD_it                    2638	1_1_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
@@ -2095,7 +2095,7 @@ OCSP_CERTSTATUS_free                    2653	1_1_0	EXIST::FUNCTION:
 _ossl_old_des_crypt                     2654	1_1_0	NOEXIST::FUNCTION:
 ASN1_item_i2d                           2655	1_1_0	EXIST::FUNCTION:
 EVP_DecryptFinal_ex                     2656	1_1_0	EXIST::FUNCTION:
-ENGINE_load_openssl                     2657	1_1_0	EXIST::FUNCTION:ENGINE
+ENGINE_load_openssl                     2657	1_1_0	NOEXIST::FUNCTION:
 ENGINE_get_cmd_defns                    2658	1_1_0	EXIST::FUNCTION:ENGINE
 ENGINE_set_load_privkey_function        2659	1_1_0	EXIST:!VMS:FUNCTION:ENGINE
 ENGINE_set_load_privkey_fn              2659	1_1_0	EXIST:VMS:FUNCTION:ENGINE
@@ -2533,7 +2533,7 @@ OCSP_RESPONSE_new                       3023	1_1_0	EXIST::FUNCTION:
 AES_set_encrypt_key                     3024	1_1_0	EXIST::FUNCTION:AES
 OCSP_resp_count                         3025	1_1_0	EXIST::FUNCTION:
 KRB5_CHECKSUM_new                       3026	1_1_0	NOEXIST::FUNCTION:
-ENGINE_load_cswift                      3027	1_1_0	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ENGINE_load_cswift                      3027	1_1_0	NOEXIST::FUNCTION:
 OCSP_onereq_get0_id                     3028	1_1_0	EXIST::FUNCTION:
 ENGINE_set_default_ciphers              3029	1_1_0	EXIST::FUNCTION:ENGINE
 NOTICEREF_it                            3030	1_1_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
@@ -2564,7 +2564,7 @@ ASN1_primitive_free                     3051	1_1_0	NOEXIST::FUNCTION:
 i2d_EXTENDED_KEY_USAGE                  3052	1_1_0	EXIST::FUNCTION:
 i2d_OCSP_SIGNATURE                      3053	1_1_0	EXIST::FUNCTION:
 asn1_enc_save                           3054	1_1_0	NOEXIST::FUNCTION:
-ENGINE_load_nuron                       3055	1_1_0	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ENGINE_load_nuron                       3055	1_1_0	NOEXIST::FUNCTION:
 _ossl_old_des_pcbc_encrypt              3056	1_1_0	NOEXIST::FUNCTION:
 PKCS12_MAC_DATA_it                      3057	1_1_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
 PKCS12_MAC_DATA_it                      3057	1_1_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
@@ -2586,7 +2586,7 @@ asn1_get_choice_selector                3071	1_1_0	NOEXIST::FUNCTION:
 i2d_KRB5_CHECKSUM                       3072	1_1_0	NOEXIST::FUNCTION:
 ENGINE_set_table_flags                  3073	1_1_0	EXIST::FUNCTION:ENGINE
 AES_options                             3074	1_1_0	EXIST::FUNCTION:AES
-ENGINE_load_chil                        3075	1_1_0	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ENGINE_load_chil                        3075	1_1_0	NOEXIST::FUNCTION:
 OCSP_id_cmp                             3076	1_1_0	EXIST::FUNCTION:
 OCSP_BASICRESP_new                      3077	1_1_0	EXIST::FUNCTION:
 OCSP_REQUEST_get_ext_by_NID             3078	1_1_0	EXIST::FUNCTION:
@@ -2651,7 +2651,7 @@ OCSP_CRLID_it                           3127	1_1_0	EXIST:!EXPORT_VAR_AS_FUNCTION
 OCSP_CRLID_it                           3127	1_1_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
 i2d_KRB5_AUTHENTBODY                    3128	1_1_0	NOEXIST::FUNCTION:
 OCSP_REQUEST_get_ext_count              3129	1_1_0	EXIST::FUNCTION:
-ENGINE_load_atalla                      3130	1_1_0	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ENGINE_load_atalla                      3130	1_1_0	NOEXIST::FUNCTION:
 X509_NAME_it                            3131	1_1_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
 X509_NAME_it                            3131	1_1_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
 USERNOTICE_it                           3132	1_1_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
@@ -2745,17 +2745,17 @@ DES_read_2passwords                     3206	1_1_0	EXIST::FUNCTION:DES
 DES_read_password                       3207	1_1_0	EXIST::FUNCTION:DES
 UI_UTIL_read_pw                         3208	1_1_0	EXIST::FUNCTION:
 UI_UTIL_read_pw_string                  3209	1_1_0	EXIST::FUNCTION:
-ENGINE_load_aep                         3210	1_1_0	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
-ENGINE_load_sureware                    3211	1_1_0	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
-OPENSSL_add_all_algorithms_noconf       3212	1_1_0	EXIST:!VMS:FUNCTION:
-OPENSSL_add_all_algo_noconf             3212	1_1_0	EXIST:VMS:FUNCTION:
-OPENSSL_add_all_algorithms_conf         3213	1_1_0	EXIST:!VMS:FUNCTION:
-OPENSSL_add_all_algo_conf               3213	1_1_0	EXIST:VMS:FUNCTION:
+ENGINE_load_aep                         3210	1_1_0	NOEXIST::FUNCTION:
+ENGINE_load_sureware                    3211	1_1_0	NOEXIST::FUNCTION:
+OPENSSL_add_all_algo_noconf             3212	1_1_0	NOEXIST::FUNCTION:
+OPENSSL_add_all_algorithms_noconf       3212	1_1_0	NOEXIST::FUNCTION:
+OPENSSL_add_all_algo_conf               3213	1_1_0	NOEXIST::FUNCTION:
+OPENSSL_add_all_algorithms_conf         3213	1_1_0	NOEXIST::FUNCTION:
 OPENSSL_load_builtin_modules            3214	1_1_0	EXIST::FUNCTION:
 AES_ofb128_encrypt                      3215	1_1_0	EXIST::FUNCTION:AES
 AES_ctr128_encrypt                      3216	1_1_0	NOEXIST::FUNCTION:
 AES_cfb128_encrypt                      3217	1_1_0	EXIST::FUNCTION:AES
-ENGINE_load_4758cca                     3218	1_1_0	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ENGINE_load_4758cca                     3218	1_1_0	NOEXIST::FUNCTION:
 _ossl_096_des_random_seed               3219	1_1_0	NOEXIST::FUNCTION:
 EVP_aes_256_ofb                         3220	1_1_0	EXIST::FUNCTION:AES
 EVP_aes_192_ofb                         3221	1_1_0	EXIST::FUNCTION:AES
@@ -2765,7 +2765,7 @@ EVP_aes_128_ofb                         3224	1_1_0	EXIST::FUNCTION:AES
 EVP_aes_192_cfb128                      3225	1_1_0	EXIST::FUNCTION:AES
 CONF_modules_free                       3226	1_1_0	EXIST::FUNCTION:
 NCONF_default                           3227	1_1_0	EXIST::FUNCTION:
-OPENSSL_no_config                       3228	1_1_0	EXIST::FUNCTION:
+OPENSSL_no_config                       3228	1_1_0	NOEXIST::FUNCTION:
 NCONF_WIN32                             3229	1_1_0	EXIST::FUNCTION:
 ASN1_UNIVERSALSTRING_new                3230	1_1_0	EXIST::FUNCTION:
 EVP_des_ede_ecb                         3231	1_1_0	EXIST::FUNCTION:DES
@@ -3086,7 +3086,7 @@ EC_GFp_nist_method                      3529	1_1_0	EXIST::FUNCTION:EC
 STORE_meth_set_modify_fn                3530	1_1_0	NOEXIST::FUNCTION:
 STORE_method_set_modify_function        3530	1_1_0	NOEXIST::FUNCTION:
 STORE_parse_attrs_next                  3531	1_1_0	NOEXIST::FUNCTION:
-ENGINE_load_padlock                     3532	1_1_0	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ENGINE_load_padlock                     3532	1_1_0	NOEXIST::FUNCTION:
 EC_GROUP_set_curve_name                 3533	1_1_0	EXIST::FUNCTION:EC
 X509_CERT_PAIR_it                       3534	1_1_0	NOEXIST::FUNCTION:
 STORE_meth_get_revoke_fn                3535	1_1_0	NOEXIST::FUNCTION:
@@ -3637,7 +3637,7 @@ ENGINE_set_ld_ssl_clnt_cert_fn          4044	1_1_0	EXIST:VMS:FUNCTION:ENGINE
 ENGINE_get_ssl_client_cert_function     4045	1_1_0	EXIST:!VMS:FUNCTION:ENGINE
 ENGINE_get_ssl_client_cert_fn           4045	1_1_0	EXIST:VMS:FUNCTION:ENGINE
 ENGINE_load_ssl_client_cert             4046	1_1_0	EXIST::FUNCTION:ENGINE
-ENGINE_load_capi                        4047	1_1_0	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ENGINE_load_capi                        4047	1_1_0	NOEXIST::FUNCTION:
 OPENSSL_isservice                       4048	1_1_0	EXIST::FUNCTION:
 FIPS_dsa_sig_decode                     4049	1_1_0	NOEXIST::FUNCTION:
 EVP_CIPHER_CTX_clear_flags              4050	1_1_0	EXIST::FUNCTION:
@@ -4244,7 +4244,7 @@ CRYPTO_nistcts128_encrypt               4636	1_1_0	EXIST::FUNCTION:
 EVP_aes_128_cbc_hmac_sha1               4637	1_1_0	EXIST::FUNCTION:AES
 CRYPTO_gcm128_tag                       4638	1_1_0	EXIST::FUNCTION:
 CRYPTO_ccm128_encrypt_ccm64             4639	1_1_0	EXIST::FUNCTION:
-ENGINE_load_rdrand                      4640	1_1_0	EXIST::FUNCTION:ENGINE
+ENGINE_load_rdrand                      4640	1_1_0	NOEXIST::FUNCTION:
 CRYPTO_ccm128_setiv                     4641	1_1_0	EXIST::FUNCTION:
 CRYPTO_nistcts128_encrypt_block         4642	1_1_0	EXIST::FUNCTION:
 CRYPTO_gcm128_aad                       4643	1_1_0	EXIST::FUNCTION:
@@ -4618,7 +4618,7 @@ X509_get0_uids                          5008	1_1_0	EXIST::FUNCTION:
 X509_aux_print                          5009	1_1_0	EXIST::FUNCTION:STDIO
 TS_RESP_CTX_set_signer_digest           5010	1_1_0	EXIST::FUNCTION:
 TS_CONF_set_signer_digest               5011	1_1_0	EXIST::FUNCTION:
-ENGINE_load_dasync                      5012	1_1_0	EXIST::FUNCTION:ENGINE,STATIC_ENGINE
+ENGINE_load_dasync                      5012	1_1_0	NOEXIST::FUNCTION:
 ASYNC_pause_job                         5013	1_1_0	EXIST::FUNCTION:
 ASYNC_start_job                         5014	1_1_0	EXIST::FUNCTION:
 ASYNC_init_thread                       5015	1_1_0	EXIST::FUNCTION:
@@ -4630,8 +4630,8 @@ ASYNC_get_wait_fd                       5020	1_1_0	EXIST::FUNCTION:
 ERR_load_ASYNC_strings                  5021	1_1_0	EXIST::FUNCTION:
 ASYNC_unblock_pause                     5022	1_1_0	EXIST::FUNCTION:
 ASYNC_block_pause                       5023	1_1_0	EXIST::FUNCTION:
-ASYNC_cleanup                           5024	1_1_0	EXIST::FUNCTION:
-ASYNC_init                              5025	1_1_0	EXIST::FUNCTION:
+ASYNC_cleanup                           5024	1_1_0	NOEXIST::FUNCTION:
+ASYNC_init                              5025	1_1_0	NOEXIST::FUNCTION:
 EVP_MD_CTX_ctrl                         5026	1_1_0	EXIST::FUNCTION:
 EVP_md5_sha1                            5027	1_1_0	EXIST::FUNCTION:MD5
 CRYPTO_free_ex_index                    5028	1_1_0	EXIST::FUNCTION:
@@ -4812,3 +4812,7 @@ 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:
+OPENSSL_INIT_thread_stop                5213	1_1_0	EXIST::FUNCTION:
diff --git a/util/mk1mf.pl b/util/mk1mf.pl
index ed1d0e1..1e72b90 100755
--- a/util/mk1mf.pl
+++ b/util/mk1mf.pl
@@ -142,7 +142,9 @@ 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
+	no-autoerrinit				- Don't auto load error strings for libcrypto or libssl
 	nasm 					- Use NASM for x86 asm
 	nw-nasm					- Use NASM x86 asm for NetWare
 	nw-mwasm				- Use Metrowerks x86 asm for NetWare
@@ -298,6 +300,8 @@ $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_NO_AUTOERRINIT" if $no_autoerrinit;
 $cflags.=" -DOPENSSL_FIPS"    if $fips;
 $cflags.=" -DOPENSSL_NO_JPAKE"    if $no_jpake;
 $cflags.=" -DOPENSSL_NO_EC2M"    if $no_ec2m;
@@ -1414,6 +1418,8 @@ sub read_options
 		"no-egd" => 0,
 		"no-hw" => \$no_hw,
 		"no-async" => \$no_async,
+		"no-autoalginit" => \$no_autoalginit,
+		"no-autoerrinit" => \$no_autoerrinit,
 		"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 d320e3b..3d1a34b 100755
--- a/util/ssleay.num
+++ b/util/ssleay.num
@@ -61,7 +61,7 @@ SSL_get_verify_mode                     70	1_1_0	EXIST::FUNCTION:
 SSL_get_version                         71	1_1_0	EXIST::FUNCTION:
 SSL_get_wbio                            72	1_1_0	EXIST::FUNCTION:
 SSL_load_client_CA_file                 73	1_1_0	EXIST::FUNCTION:
-SSL_load_error_strings                  74	1_1_0	EXIST::FUNCTION:
+SSL_load_error_strings                  74	1_1_0	NOEXIST::FUNCTION:
 SSL_new                                 75	1_1_0	EXIST::FUNCTION:
 SSL_peek                                76	1_1_0	EXIST::FUNCTION:
 SSL_pending                             77	1_1_0	EXIST::FUNCTION:
@@ -163,7 +163,7 @@ SSL_CTX_get_timeout                     179	1_1_0	EXIST::FUNCTION:
 SSL_CTX_get_cert_store                  180	1_1_0	EXIST::FUNCTION:
 SSL_CTX_set_cert_store                  181	1_1_0	EXIST::FUNCTION:
 SSL_want                                182	1_1_0	EXIST::FUNCTION:
-SSL_library_init                        183	1_1_0	EXIST::FUNCTION:
+SSL_library_init                        183	1_1_0	NOEXIST::FUNCTION:
 SSL_COMP_add_compression_method         184	1_1_0	EXIST::FUNCTION:
 SSL_add_file_cert_subjects_to_stack     185	1_1_0	EXIST:!VMS:FUNCTION:
 SSL_add_file_cert_subjs_to_stk          185	1_1_0	EXIST:VMS:FUNCTION:
@@ -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:


More information about the openssl-commits mailing list