8950ff679740cbde2165b47e4daf797e529bb3da
[openssl.git] / crypto / init.c
1 /*
2  * Written by Matt Caswell for the OpenSSL project.
3  */
4 /* ====================================================================
5  * Copyright (c) 2016 The OpenSSL Project.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. All advertising materials mentioning features or use of this
20  *    software must display the following acknowledgment:
21  *    "This product includes software developed by the OpenSSL Project
22  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
23  *
24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25  *    endorse or promote products derived from this software without
26  *    prior written permission. For written permission, please contact
27  *    openssl-core@openssl.org.
28  *
29  * 5. Products derived from this software may not be called "OpenSSL"
30  *    nor may "OpenSSL" appear in their names without prior written
31  *    permission of the OpenSSL Project.
32  *
33  * 6. Redistributions of any form whatsoever must retain the following
34  *    acknowledgment:
35  *    "This product includes software developed by the OpenSSL Project
36  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49  * OF THE POSSIBILITY OF SUCH DAMAGE.
50  * ====================================================================
51  *
52  * This product includes cryptographic software written by Eric Young
53  * (eay@cryptsoft.com).  This product includes software written by Tim
54  * Hudson (tjh@cryptsoft.com).
55  *
56  */
57
58 #include <openssl/e_os2.h>
59
60 #if defined(OPENSSL_SYS_WINDOWS) && !defined(_WIN32_WINNT)
61 /*
62  * We default to requiring Windows Vista, Windows Server 2008 or later. We can
63  * support lower versions if _WIN32_WINNT is explicity defined to something
64  * less
65  */
66 # define _WIN32_WINNT 0x0600
67 #endif
68
69 #include <internal/cryptlib_int.h>
70 #include <openssl/err.h>
71 #include <openssl/evp.h>
72 #if 0
73 #include <internal/evp_int.h>
74 #include <internal/conf.h>
75 #include <internal/async.h>
76 #include <internal/engine.h>
77 #endif
78 #include <openssl/conf.h>
79 #include <openssl/async.h>
80 #include <openssl/engine.h>
81 #include <openssl/comp.h>
82 #if 0
83 #include <internal/err.h>
84 #endif
85 #include <stdlib.h>
86
87 /* Implement "once" functionality */
88 #if !defined(OPENSSL_THREADS)
89 typedef int OPENSSL_INIT_ONCE;
90 # define OPENSSL_INIT_ONCE_STATIC_INIT          0
91 # define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once)   (*(once) = 0)
92
93 static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void))
94 {
95     if (*once == OPENSSL_INIT_ONCE_STATIC_INIT) {
96         *once = 1;
97         init();
98     }
99 }
100
101 static int ossl_init_setup_thread_stop(void)
102 {
103     /*
104      * There are no threads to stop. Do nothing.
105      */
106     return 1;
107 }
108
109 static void ossl_init_thread_stop_cleanup(void)
110 {
111 }
112
113 static struct thread_local_inits_st *local = NULL;
114 void *ossl_init_get_thread_local(int alloc)
115 {
116     if (local == NULL && alloc)
117         local = OPENSSL_zalloc(sizeof(*local));
118     return local;
119 }
120
121 #elif defined(OPENSSL_SYS_WINDOWS)
122
123 # include <windows.h>
124
125 # if _WIN32_WINNT < 0x0600
126
127 /*
128  * Versions before 0x0600 (Windows Vista, Windows Server 2008 or later) do not
129  * have InitOnceExecuteOnce, so we fall back to using a spinlock instead.
130  */
131 typedef LONG OPENSSL_INIT_ONCE;
132 #  define OPENSSL_INIT_ONCE_STATIC_INIT          0
133 #  define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once)   (*(once) = 0)
134
135 #  define ONCE_UNINITED     0
136 #  define ONCE_ININIT       1
137 #  define ONCE_DONE         2
138
139 static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void))
140 {
141     LONG volatile *lock = (LONG *)once;
142     LONG result;
143
144     if (*lock == ONCE_DONE)
145         return;
146
147     do {
148         result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED);
149         if (result == ONCE_UNINITED) {
150             init();
151             *lock = ONCE_DONE;
152             return;
153         }
154     } while (result == ONCE_ININIT);
155 }
156
157 # else
158
159 typedef INIT_ONCE OPENSSL_INIT_ONCE;
160 #  define OPENSSL_INIT_ONCE_STATIC_INIT          INIT_ONCE_STATIC_INIT
161 #  define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) \
162                 InitOnceInitialize((PINIT_ONCE)(once))
163
164 static BOOL CALLBACK once_cb(PINIT_ONCE once, PVOID initfp, PVOID *unused)
165 {
166     void (*init)(void) = initfp;
167
168     init();
169
170     return TRUE;
171 }
172
173 static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void))
174 {
175     InitOnceExecuteOnce((INIT_ONCE *)once, once_cb, init, NULL);
176 }
177 # endif
178
179 DWORD threadstopkey = TLS_OUT_OF_INDEXES;
180
181 static int ossl_init_setup_thread_stop(void)
182 {
183     /*
184      * We use a dummy thread local key here. We use the destructor to detect
185      * when the thread is going to stop
186      */
187     threadstopkey = TlsAlloc();
188     if (threadstopkey == TLS_OUT_OF_INDEXES)
189         return 0;
190
191     return 1;
192 }
193
194 static void ossl_init_thread_stop_cleanup(void)
195 {
196     if (threadstopkey != TLS_OUT_OF_INDEXES) {
197         TlsFree(threadstopkey);
198     }
199 }
200
201 void *ossl_init_get_thread_local(int alloc)
202 {
203     struct thread_local_inits_st *local = TlsGetValue(threadstopkey);
204
205     if (local == NULL && alloc) {
206         local = OPENSSL_zalloc(sizeof *local);
207         TlsSetValue(threadstopkey, local);
208     }
209
210     return local;
211 }
212
213 #else /* pthreads */
214 # include <pthread.h>
215
216 pthread_key_t threadstopkey;
217
218 typedef pthread_once_t OPENSSL_INIT_ONCE;
219 # define OPENSSL_INIT_ONCE_STATIC_INIT          PTHREAD_ONCE_INIT
220 # define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once)   (*(once) = PTHREAD_ONCE_INIT)
221
222 static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void))
223 {
224     pthread_once(once, init);
225 }
226
227 static void ossl_init_thread_stop_wrap(void *local)
228 {
229     ossl_init_thread_stop((struct thread_local_inits_st *)local);
230 }
231
232 static int ossl_init_setup_thread_stop(void)
233 {
234     /*
235      * We use a dummy thread local key here. We use the destructor to detect
236      * when the thread is going to stop
237      */
238     return (pthread_key_create(&threadstopkey,
239                                ossl_init_thread_stop_wrap) == 0);
240 }
241
242 static void ossl_init_thread_stop_cleanup(void)
243 {
244 }
245
246 void *ossl_init_get_thread_local(int alloc)
247 {
248     struct thread_local_inits_st *local = pthread_getspecific(threadstopkey);
249
250     if (local == NULL && alloc) {
251         local = OPENSSL_zalloc(sizeof *local);
252         pthread_setspecific(threadstopkey, local);
253     }
254
255     return local;
256 }
257
258 #endif
259
260 struct ossl_init_stop_st {
261     void (*handler)(void);
262     OPENSSL_INIT_STOP *next;
263 };
264
265 static OPENSSL_INIT_STOP *stop_handlers = NULL;
266
267 static OPENSSL_INIT_ONCE base = OPENSSL_INIT_ONCE_STATIC_INIT;
268 static int base_inited = 0;
269 static void ossl_init_base(void)
270 {
271 #ifdef OPENSSL_INIT_DEBUG
272     fprintf(stderr, "OPENSSL_INIT: ossl_init_base: Setting up stop handlers\n");
273 #endif
274     ossl_init_setup_thread_stop();
275     atexit(OPENSSL_INIT_library_stop);
276     OPENSSL_cpuid_setup();
277     base_inited = 1;
278 }
279
280 static OPENSSL_INIT_ONCE load_crypto_strings = OPENSSL_INIT_ONCE_STATIC_INIT;
281 static int load_crypto_strings_inited = 0;
282 static void ossl_init_no_load_crypto_strings(void)
283 {
284     /* Do nothing in this case */
285     return;
286 }
287
288 static void ossl_init_load_crypto_strings(void)
289 {
290 #ifndef OPENSSL_NO_ERR
291 # ifdef OPENSSL_INIT_DEBUG
292     fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_strings: "
293                     "err_load_crypto_strings_intern()\n");
294 # endif
295 #if 0
296     err_load_crypto_strings_intern();
297 #endif
298 #endif
299     load_crypto_strings_inited = 1;
300 }
301
302 static OPENSSL_INIT_ONCE add_all_ciphers = OPENSSL_INIT_ONCE_STATIC_INIT;
303 static void ossl_init_add_all_ciphers(void)
304 {
305     /*
306      * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
307      * pulling in all the ciphers during static linking
308      */
309 #ifndef OPENSSL_NO_AUTOALGINIT
310 # ifdef OPENSSL_INIT_DEBUG
311     fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_ciphers: "
312                     "openssl_add_all_ciphers_internal()\n");
313 # endif
314 #if 0
315     openssl_add_all_ciphers_internal();
316 #endif
317 # ifndef OPENSSL_NO_ENGINE
318 #  if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
319     ENGINE_setup_bsd_cryptodev();
320 #  endif
321 # endif
322 #endif
323 }
324
325 static OPENSSL_INIT_ONCE add_all_digests = OPENSSL_INIT_ONCE_STATIC_INIT;
326 static void ossl_init_add_all_digests(void)
327 {
328     /*
329      * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
330      * pulling in all the ciphers during static linking
331      */
332 #ifndef OPENSSL_NO_AUTOALGINIT
333 # ifdef OPENSSL_INIT_DEBUG
334     fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_digests: "
335                     "openssl_add_all_digests_internal()\n");
336 # endif
337 #if 0
338     openssl_add_all_digests_internal();
339 #endif
340 # ifndef OPENSSL_NO_ENGINE
341 #  if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
342     ENGINE_setup_bsd_cryptodev();
343 #  endif
344 # endif
345 #endif
346 }
347
348 static void ossl_init_no_add_algs(void)
349 {
350     /* Do nothing */
351     return;
352 }
353
354 static OPENSSL_INIT_ONCE config = OPENSSL_INIT_ONCE_STATIC_INIT;
355 static int config_inited = 0;
356 static const char *config_filename;
357 static void ossl_init_config(void)
358 {
359 #ifdef OPENSSL_INIT_DEBUG
360     fprintf(stderr,
361             "OPENSSL_INIT: ossl_init_config: openssl_config_internal(%s)\n",
362             config_filename==NULL?"NULL":config_filename);
363 #endif
364 #if 0
365     openssl_config_internal(config_filename);
366 #endif
367     config_inited = 1;
368 }
369 static void ossl_init_no_config(void)
370 {
371 #ifdef OPENSSL_INIT_DEBUG
372     fprintf(stderr,
373             "OPENSSL_INIT: ossl_init_config: openssl_no_config_internal()\n");
374 #endif
375 #if 0
376     openssl_no_config_internal();
377 #endif
378     config_inited = 1;
379 }
380
381 static OPENSSL_INIT_ONCE async = OPENSSL_INIT_ONCE_STATIC_INIT;
382 static int async_inited = 0;
383 static void ossl_init_async(void)
384 {
385 #ifdef OPENSSL_INIT_DEBUG
386     fprintf(stderr, "OPENSSL_INIT: ossl_init_async: async_init()\n");
387 #endif
388 #if 0
389     async_init();
390 #endif
391     async_inited = 1;
392 }
393
394 #ifndef OPENSSL_NO_ENGINE
395 static int engine_inited = 0;
396 static OPENSSL_INIT_ONCE engine_openssl = OPENSSL_INIT_ONCE_STATIC_INIT;
397 static void ossl_init_engine_openssl(void)
398 {
399 # ifdef OPENSSL_INIT_DEBUG
400     fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_openssl: "
401                     "engine_load_openssl_internal()\n");
402 # endif
403 #if 0
404     engine_load_openssl_internal();
405 #endif
406     engine_inited = 1;
407 }
408 # if !defined(OPENSSL_NO_HW) && \
409     (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV))
410 static OPENSSL_INIT_ONCE engine_cryptodev = OPENSSL_INIT_ONCE_STATIC_INIT;
411 static void ossl_init_engine_cryptodev(void)
412 {
413 #  ifdef OPENSSL_INIT_DEBUG
414     fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_cryptodev: "
415                     "engine_load_cryptodev_internal()\n");
416 #  endif
417 #if 0
418     engine_load_cryptodev_internal();
419 #endif
420     engine_inited = 1;
421 }
422 # endif
423
424 # ifndef OPENSSL_NO_RDRAND
425 static OPENSSL_INIT_ONCE engine_rdrand = OPENSSL_INIT_ONCE_STATIC_INIT;
426 static void ossl_init_engine_rdrand(void)
427 {
428 #  ifdef OPENSSL_INIT_DEBUG
429     fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_rdrand: "
430                     "engine_load_rdrand_internal()\n");
431 #  endif
432 #if 0
433     engine_load_rdrand_internal();
434 #endif
435     engine_inited = 1;
436 }
437 # endif
438 static OPENSSL_INIT_ONCE engine_dynamic = OPENSSL_INIT_ONCE_STATIC_INIT;
439 static void ossl_init_engine_dynamic(void)
440 {
441 # ifdef OPENSSL_INIT_DEBUG
442     fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_dynamic: "
443                     "engine_load_dynamic_internal()\n");
444 # endif
445 #if 0
446     engine_load_dynamic_internal();
447 #endif
448     engine_inited = 1;
449 }
450 # ifndef OPENSSL_NO_STATIC_ENGINE
451 #  if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
452 static OPENSSL_INIT_ONCE engine_padlock = OPENSSL_INIT_ONCE_STATIC_INIT;
453 static void ossl_init_engine_padlock(void)
454 {
455 #   ifdef OPENSSL_INIT_DEBUG
456     fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_padlock: "
457                     "engine_load_padlock_internal()\n");
458 #   endif
459 #if 0
460     engine_load_padlock_internal();
461 #endif
462     engine_inited = 1;
463 }
464 #  endif
465 #  if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
466 static OPENSSL_INIT_ONCE engine_capi = OPENSSL_INIT_ONCE_STATIC_INIT;
467 static void ossl_init_engine_capi(void)
468 {
469 #   ifdef OPENSSL_INIT_DEBUG
470     fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_capi: "
471                     "engine_load_capi_internal()\n");
472 #   endif
473 #if 0
474     engine_load_capi_internal();
475 #endif
476     engine_inited = 1;
477 }
478 #  endif
479 static OPENSSL_INIT_ONCE engine_dasync = OPENSSL_INIT_ONCE_STATIC_INIT;
480 static void ossl_init_engine_dasync(void)
481 {
482 # ifdef OPENSSL_INIT_DEBUG
483     fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_dasync: "
484                     "engine_load_dasync_internal()\n");
485 # endif
486 #if 0
487     engine_load_dasync_internal();
488 #endif
489     engine_inited = 1;
490 }
491 # endif
492 #endif
493
494 static OPENSSL_INIT_ONCE zlib = OPENSSL_INIT_ONCE_STATIC_INIT;
495 static int zlib_inited = 0;
496 static void ossl_init_zlib(void)
497 {
498     /* Do nothing - we need to know about this for the later cleanup */
499     zlib_inited = 1;
500 }
501
502 void ossl_init_thread_stop(struct thread_local_inits_st *locals)
503 {
504     /* Can't do much about this */
505     if (locals == NULL)
506         return;
507
508     if (locals->async) {
509 #ifdef OPENSSL_INIT_DEBUG
510         fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: "
511                         "ASYNC_cleanup_thread()\n");
512 #endif
513         ASYNC_cleanup_thread();
514     }
515
516     if (locals->err_state) {
517 #ifdef OPENSSL_INIT_DEBUG
518         fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: "
519                         "ERR_remove_thread_state(NULL)\n");
520 #endif
521         ERR_remove_thread_state(NULL);
522     }
523
524     OPENSSL_free(locals);
525     ossl_init_thread_stop_cleanup();
526 }
527
528 int ossl_init_thread_start(uint64_t opts)
529 {
530     struct thread_local_inits_st *locals = ossl_init_get_thread_local(1);
531
532     if (locals == NULL)
533         return 0;
534
535     if (opts & OPENSSL_INIT_THREAD_ASYNC) {
536 #ifdef OPENSSL_INIT_DEBUG
537         fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: "
538                         "marking thread for async\n");
539 #endif
540         locals->async = 1;
541     }
542
543     if (opts & OPENSSL_INIT_THREAD_ERR_STATE) {
544 #ifdef OPENSSL_INIT_DEBUG
545         fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: "
546                         "marking thread for err_state\n");
547 #endif
548         locals->err_state = 1;
549     }
550
551     return 1;
552 }
553
554 void OPENSSL_INIT_library_stop(void)
555 {
556     OPENSSL_INIT_STOP *currhandler, *lasthandler;
557
558     /*
559      * Thread stop may not get automatically called by the thread library for
560      * the very last thread in some situations, so call it directly.
561      */
562     ossl_init_thread_stop(ossl_init_get_thread_local(0));
563
564     currhandler = stop_handlers;
565     while (currhandler != NULL) {
566         currhandler->handler();
567         lasthandler = currhandler;
568         currhandler = currhandler->next;
569         OPENSSL_free(lasthandler);
570     }
571     stop_handlers = NULL;
572     /*
573      * We assume we are single-threaded for this function, i.e. no race
574      * conditions for the various "*_inited" vars below.
575      */
576
577     if (zlib_inited) {
578 #ifdef OPENSSL_INIT_DEBUG
579         fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
580                         "COMP_zlib_cleanup()\n");
581 #endif
582         COMP_zlib_cleanup();
583         zlib_inited = 0;
584         OPENSSL_INIT_ONCE_DYNAMIC_INIT(&zlib);
585     }
586
587 #ifndef OPENSSL_NO_ENGINE
588     if (engine_inited) {
589 # ifdef OPENSSL_INIT_DEBUG
590         fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
591                         "ENGINE_cleanup()\n");
592 # endif
593         ENGINE_cleanup();
594         engine_inited = 0;
595         OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_openssl);
596 # if !defined(OPENSSL_NO_HW) && \
597     (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV))
598         OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_cryptodev);
599 # endif
600 # ifndef OPENSSL_NO_RDRAND
601         OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_rdrand);
602 # endif
603         OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_dynamic);
604 # ifndef OPENSSL_NO_STATIC_ENGINE
605 #  if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
606         OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_padlock);
607 #  endif
608 #  if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
609         OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_capi);
610 #  endif
611         OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_dasync);
612 # endif
613     }
614 #endif
615
616     async_inited = 0;
617     OPENSSL_INIT_ONCE_DYNAMIC_INIT(&async);
618
619     config_inited = 0;
620     OPENSSL_INIT_ONCE_DYNAMIC_INIT(&config);
621     OPENSSL_INIT_ONCE_DYNAMIC_INIT(&add_all_ciphers);
622     OPENSSL_INIT_ONCE_DYNAMIC_INIT(&add_all_digests);
623
624     if (load_crypto_strings_inited) {
625 #ifdef OPENSSL_INIT_DEBUG
626         fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
627                         "ERR_free_strings()\n");
628 #endif
629         ERR_free_strings();
630         load_crypto_strings_inited = 0;
631         OPENSSL_INIT_ONCE_DYNAMIC_INIT(&load_crypto_strings);
632     }
633
634     if (base_inited) {
635 #ifdef OPENSSL_INIT_DEBUG
636         fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
637                         "CRYPTO_cleanup_all_ex_data()\n");
638         fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
639                         "EVP_cleanup()\n");
640         fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
641                         "CONF_modules_free()\n");
642         fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
643                         "RAND_cleanup()\n");
644 #endif
645         CRYPTO_cleanup_all_ex_data();
646         EVP_cleanup();
647         CONF_modules_free();
648         RAND_cleanup();
649         base_inited = 0;
650         OPENSSL_INIT_ONCE_DYNAMIC_INIT(&base);
651     }
652 }
653
654 static const OPENSSL_INIT_SETTINGS *ossl_init_get_setting(
655         const OPENSSL_INIT_SETTINGS *settings, int name)
656 {
657     if (settings == NULL)
658         return NULL;
659
660     while (settings->name != OPENSSL_INIT_SET_END) {
661         if (settings->name == name)
662             return settings;
663         settings++;
664     }
665
666     return NULL;
667 }
668
669 /*
670  * If this function is called with a non NULL settings value then it must be
671  * called prior to any threads making calls to any OpenSSL functions,
672  * i.e. passing a non-null settings value is assumed to be single-threaded.
673  */
674 void OPENSSL_INIT_crypto_library_start(uint64_t opts,
675                                     const OPENSSL_INIT_SETTINGS *settings)
676 {
677     ossl_init_once_run(&base, ossl_init_base);
678
679     if (opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS)
680         ossl_init_once_run(&load_crypto_strings,
681                            ossl_init_no_load_crypto_strings);
682
683     if (opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS)
684         ossl_init_once_run(&load_crypto_strings, ossl_init_load_crypto_strings);
685
686     if (opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS)
687         ossl_init_once_run(&add_all_ciphers, ossl_init_no_add_algs);
688
689     if (opts & OPENSSL_INIT_ADD_ALL_CIPHERS)
690         ossl_init_once_run(&add_all_ciphers, ossl_init_add_all_ciphers);
691
692     if (opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS)
693         ossl_init_once_run(&add_all_digests, ossl_init_no_add_algs);
694
695     if (opts & OPENSSL_INIT_ADD_ALL_DIGESTS)
696         ossl_init_once_run(&add_all_digests, ossl_init_add_all_digests);
697
698     if (opts & OPENSSL_INIT_NO_LOAD_CONFIG) {
699         ossl_init_once_run(&config, ossl_init_no_config);
700     }
701
702     if (opts & OPENSSL_INIT_LOAD_CONFIG) {
703         if (settings != NULL) {
704             const OPENSSL_INIT_SETTINGS *curr;
705             curr = ossl_init_get_setting(settings,
706                                          OPENSSL_INIT_SET_CONF_FILENAME);
707             config_filename = curr == NULL ? NULL : curr->value.type_string;
708         }
709         ossl_init_once_run(&config, ossl_init_config);
710     }
711
712     if (opts & OPENSSL_INIT_ASYNC) {
713         ossl_init_once_run(&async, ossl_init_async);
714     }
715
716 #ifndef OPENSSL_NO_ENGINE
717     if (opts & OPENSSL_INIT_ENGINE_OPENSSL) {
718         ossl_init_once_run(&engine_openssl, ossl_init_engine_openssl);
719     }
720 # if !defined(OPENSSL_NO_HW) && \
721     (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV))
722     if (opts & OPENSSL_INIT_ENGINE_CRYPTODEV) {
723         ossl_init_once_run(&engine_cryptodev, ossl_init_engine_cryptodev);
724     }
725 # endif
726 # ifndef OPENSSL_NO_RDRAND
727     if (opts & OPENSSL_INIT_ENGINE_RDRAND) {
728         ossl_init_once_run(&engine_rdrand, ossl_init_engine_rdrand);
729     }
730 # endif
731     if (opts & OPENSSL_INIT_ENGINE_DYNAMIC) {
732         ossl_init_once_run(&engine_dynamic, ossl_init_engine_dynamic);
733     }
734 # ifndef OPENSSL_NO_STATIC_ENGINE
735 #  if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
736     if (opts & OPENSSL_INIT_ENGINE_PADLOCK) {
737         ossl_init_once_run(&engine_padlock, ossl_init_engine_padlock);
738     }
739 #  endif
740 #  if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
741     if (opts & OPENSSL_INIT_ENGINE_CAPI) {
742         ossl_init_once_run(&engine_capi, ossl_init_engine_capi);
743     }
744 #  endif
745     if (opts & OPENSSL_INIT_ENGINE_DASYNC) {
746         ossl_init_once_run(&engine_dasync, ossl_init_engine_dasync);
747     }
748 # endif
749     if (opts & (OPENSSL_INIT_ENGINE_ALL_BUILTIN
750                 | OPENSSL_INIT_ENGINE_DASYNC | OPENSSL_INIT_ENGINE_OPENSSL)) {
751         ENGINE_register_all_complete();
752     }
753 #endif
754
755     if (opts & OPENSSL_INIT_ZLIB) {
756         ossl_init_once_run(&zlib, ossl_init_zlib);
757     }
758 }
759
760 int OPENSSL_INIT_register_stop_handler(void (*handler)(void))
761 {
762     OPENSSL_INIT_STOP *newhand;
763
764     newhand = OPENSSL_malloc(sizeof(*newhand));
765     if (newhand == NULL)
766         return 0;
767
768     newhand->handler = handler;
769     newhand->next = stop_handlers;
770     stop_handlers = newhand;
771
772     return 1;
773 }
774
775