]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/init.c
Provide framework for auto initialise/deinitialise of the library
[thirdparty/openssl.git] / crypto / init.c
CommitLineData
b184e3ef
MC
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)
89typedef int OPENSSL_INIT_ONCE;
90# define OPENSSL_INIT_ONCE_STATIC_INIT 0
91# define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) (*(once) = 0)
92
93static 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
101static int ossl_init_setup_thread_stop(void)
102{
103 /*
104 * There are no threads to stop. Do nothing.
105 */
106 return 1;
107}
108
109static void ossl_init_thread_stop_cleanup(void)
110{
111}
112
113static struct thread_local_inits_st *local = NULL;
114void *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 */
131typedef 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
139static 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
159typedef 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
164static 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
173static 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
179DWORD threadstopkey = TLS_OUT_OF_INDEXES;
180
181static 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
194static void ossl_init_thread_stop_cleanup(void)
195{
196 if (threadstopkey != TLS_OUT_OF_INDEXES) {
197 TlsFree(threadstopkey);
198 }
199}
200
201void *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
216pthread_key_t threadstopkey;
217
218typedef 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
222static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void))
223{
224 pthread_once(once, init);
225}
226
227static void ossl_init_thread_stop_wrap(void *local)
228{
229 ossl_init_thread_stop((struct thread_local_inits_st *)local);
230}
231
232static 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
242static void ossl_init_thread_stop_cleanup(void)
243{
244}
245
246void *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
260struct ossl_init_stop_st {
261 void (*handler)(void);
262 OPENSSL_INIT_STOP *next;
263};
264
265static OPENSSL_INIT_STOP *stop_handlers = NULL;
266
267static OPENSSL_INIT_ONCE base = OPENSSL_INIT_ONCE_STATIC_INIT;
268static int base_inited = 0;
269static 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
280static OPENSSL_INIT_ONCE load_crypto_strings = OPENSSL_INIT_ONCE_STATIC_INIT;
281static int load_crypto_strings_inited = 0;
282static void ossl_init_no_load_crypto_strings(void)
283{
284 /* Do nothing in this case */
285 return;
286}
287
288static 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
302static OPENSSL_INIT_ONCE add_all_ciphers = OPENSSL_INIT_ONCE_STATIC_INIT;
303static 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
325static OPENSSL_INIT_ONCE add_all_digests = OPENSSL_INIT_ONCE_STATIC_INIT;
326static 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
348static void ossl_init_no_add_algs(void)
349{
350 /* Do nothing */
351 return;
352}
353
354static OPENSSL_INIT_ONCE config = OPENSSL_INIT_ONCE_STATIC_INIT;
355static int config_inited = 0;
356static const char *config_filename;
357static 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}
369static 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
381static OPENSSL_INIT_ONCE async = OPENSSL_INIT_ONCE_STATIC_INIT;
382static int async_inited = 0;
383static 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
395static int engine_inited = 0;
396static OPENSSL_INIT_ONCE engine_openssl = OPENSSL_INIT_ONCE_STATIC_INIT;
397static 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))
410static OPENSSL_INIT_ONCE engine_cryptodev = OPENSSL_INIT_ONCE_STATIC_INIT;
411static 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
425static OPENSSL_INIT_ONCE engine_rdrand = OPENSSL_INIT_ONCE_STATIC_INIT;
426static 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
438static OPENSSL_INIT_ONCE engine_dynamic = OPENSSL_INIT_ONCE_STATIC_INIT;
439static 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)
452static OPENSSL_INIT_ONCE engine_padlock = OPENSSL_INIT_ONCE_STATIC_INIT;
453static 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)
466static OPENSSL_INIT_ONCE engine_capi = OPENSSL_INIT_ONCE_STATIC_INIT;
467static 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
479static OPENSSL_INIT_ONCE engine_dasync = OPENSSL_INIT_ONCE_STATIC_INIT;
480static 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
494static OPENSSL_INIT_ONCE zlib = OPENSSL_INIT_ONCE_STATIC_INIT;
495static int zlib_inited = 0;
496static 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
502void 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
528int 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
554void 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
654static 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 */
674void 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
760int 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