]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/init.c
Provide a thread stop API
[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>
b184e3ef
MC
72#include <internal/evp_int.h>
73#include <internal/conf.h>
74#include <internal/async.h>
75#include <internal/engine.h>
b184e3ef 76#include <openssl/comp.h>
b184e3ef 77#include <internal/err.h>
b184e3ef
MC
78#include <stdlib.h>
79
71567a6f
MC
80static void ossl_init_thread_stop(struct thread_local_inits_st *locals);
81
b184e3ef
MC
82/* Implement "once" functionality */
83#if !defined(OPENSSL_THREADS)
84typedef int OPENSSL_INIT_ONCE;
85# define OPENSSL_INIT_ONCE_STATIC_INIT 0
86# define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) (*(once) = 0)
87
88static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void))
89{
90 if (*once == OPENSSL_INIT_ONCE_STATIC_INIT) {
91 *once = 1;
92 init();
93 }
94}
95
96static int ossl_init_setup_thread_stop(void)
97{
98 /*
99 * There are no threads to stop. Do nothing.
100 */
101 return 1;
102}
103
104static void ossl_init_thread_stop_cleanup(void)
105{
106}
107
108static struct thread_local_inits_st *local = NULL;
109void *ossl_init_get_thread_local(int alloc)
110{
111 if (local == NULL && alloc)
112 local = OPENSSL_zalloc(sizeof(*local));
113 return local;
114}
115
116#elif defined(OPENSSL_SYS_WINDOWS)
117
118# include <windows.h>
119
120# if _WIN32_WINNT < 0x0600
121
122/*
123 * Versions before 0x0600 (Windows Vista, Windows Server 2008 or later) do not
124 * have InitOnceExecuteOnce, so we fall back to using a spinlock instead.
125 */
126typedef LONG OPENSSL_INIT_ONCE;
127# define OPENSSL_INIT_ONCE_STATIC_INIT 0
128# define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) (*(once) = 0)
129
130# define ONCE_UNINITED 0
131# define ONCE_ININIT 1
132# define ONCE_DONE 2
133
134static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void))
135{
136 LONG volatile *lock = (LONG *)once;
137 LONG result;
138
139 if (*lock == ONCE_DONE)
140 return;
141
142 do {
143 result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED);
144 if (result == ONCE_UNINITED) {
145 init();
146 *lock = ONCE_DONE;
147 return;
148 }
149 } while (result == ONCE_ININIT);
150}
151
152# else
153
154typedef INIT_ONCE OPENSSL_INIT_ONCE;
155# define OPENSSL_INIT_ONCE_STATIC_INIT INIT_ONCE_STATIC_INIT
156# define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) \
157 InitOnceInitialize((PINIT_ONCE)(once))
158
159static BOOL CALLBACK once_cb(PINIT_ONCE once, PVOID initfp, PVOID *unused)
160{
161 void (*init)(void) = initfp;
162
163 init();
164
165 return TRUE;
166}
167
168static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void))
169{
170 InitOnceExecuteOnce((INIT_ONCE *)once, once_cb, init, NULL);
171}
172# endif
173
174DWORD threadstopkey = TLS_OUT_OF_INDEXES;
175
176static int ossl_init_setup_thread_stop(void)
177{
178 /*
179 * We use a dummy thread local key here. We use the destructor to detect
180 * when the thread is going to stop
181 */
182 threadstopkey = TlsAlloc();
183 if (threadstopkey == TLS_OUT_OF_INDEXES)
184 return 0;
185
186 return 1;
187}
188
189static void ossl_init_thread_stop_cleanup(void)
190{
191 if (threadstopkey != TLS_OUT_OF_INDEXES) {
192 TlsFree(threadstopkey);
193 }
194}
195
196void *ossl_init_get_thread_local(int alloc)
197{
198 struct thread_local_inits_st *local = TlsGetValue(threadstopkey);
199
200 if (local == NULL && alloc) {
201 local = OPENSSL_zalloc(sizeof *local);
202 TlsSetValue(threadstopkey, local);
203 }
204
205 return local;
206}
207
208#else /* pthreads */
209# include <pthread.h>
210
211pthread_key_t threadstopkey;
212
213typedef pthread_once_t OPENSSL_INIT_ONCE;
214# define OPENSSL_INIT_ONCE_STATIC_INIT PTHREAD_ONCE_INIT
215# define OPENSSL_INIT_ONCE_DYNAMIC_INIT(once) (*(once) = PTHREAD_ONCE_INIT)
216
217static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void))
218{
219 pthread_once(once, init);
220}
221
222static void ossl_init_thread_stop_wrap(void *local)
223{
224 ossl_init_thread_stop((struct thread_local_inits_st *)local);
225}
226
227static int ossl_init_setup_thread_stop(void)
228{
229 /*
230 * We use a dummy thread local key here. We use the destructor to detect
231 * when the thread is going to stop
232 */
233 return (pthread_key_create(&threadstopkey,
234 ossl_init_thread_stop_wrap) == 0);
235}
236
237static void ossl_init_thread_stop_cleanup(void)
238{
239}
240
241void *ossl_init_get_thread_local(int alloc)
242{
243 struct thread_local_inits_st *local = pthread_getspecific(threadstopkey);
244
245 if (local == NULL && alloc) {
246 local = OPENSSL_zalloc(sizeof *local);
247 pthread_setspecific(threadstopkey, local);
248 }
249
250 return local;
251}
252
253#endif
254
255struct ossl_init_stop_st {
256 void (*handler)(void);
257 OPENSSL_INIT_STOP *next;
258};
259
260static OPENSSL_INIT_STOP *stop_handlers = NULL;
261
262static OPENSSL_INIT_ONCE base = OPENSSL_INIT_ONCE_STATIC_INIT;
263static int base_inited = 0;
264static void ossl_init_base(void)
265{
266#ifdef OPENSSL_INIT_DEBUG
267 fprintf(stderr, "OPENSSL_INIT: ossl_init_base: Setting up stop handlers\n");
268#endif
269 ossl_init_setup_thread_stop();
270 atexit(OPENSSL_INIT_library_stop);
271 OPENSSL_cpuid_setup();
272 base_inited = 1;
273}
274
275static OPENSSL_INIT_ONCE load_crypto_strings = OPENSSL_INIT_ONCE_STATIC_INIT;
276static int load_crypto_strings_inited = 0;
277static void ossl_init_no_load_crypto_strings(void)
278{
279 /* Do nothing in this case */
280 return;
281}
282
283static void ossl_init_load_crypto_strings(void)
284{
285#ifndef OPENSSL_NO_ERR
286# ifdef OPENSSL_INIT_DEBUG
287 fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_strings: "
288 "err_load_crypto_strings_intern()\n");
289# endif
b184e3ef 290 err_load_crypto_strings_intern();
b184e3ef
MC
291#endif
292 load_crypto_strings_inited = 1;
293}
294
295static OPENSSL_INIT_ONCE add_all_ciphers = OPENSSL_INIT_ONCE_STATIC_INIT;
296static void ossl_init_add_all_ciphers(void)
297{
298 /*
299 * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
300 * pulling in all the ciphers during static linking
301 */
302#ifndef OPENSSL_NO_AUTOALGINIT
303# ifdef OPENSSL_INIT_DEBUG
304 fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_ciphers: "
305 "openssl_add_all_ciphers_internal()\n");
306# endif
b184e3ef 307 openssl_add_all_ciphers_internal();
b184e3ef
MC
308# ifndef OPENSSL_NO_ENGINE
309# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
310 ENGINE_setup_bsd_cryptodev();
311# endif
312# endif
313#endif
314}
315
316static OPENSSL_INIT_ONCE add_all_digests = OPENSSL_INIT_ONCE_STATIC_INIT;
317static void ossl_init_add_all_digests(void)
318{
319 /*
320 * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
321 * pulling in all the ciphers during static linking
322 */
323#ifndef OPENSSL_NO_AUTOALGINIT
324# ifdef OPENSSL_INIT_DEBUG
325 fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_digests: "
326 "openssl_add_all_digests_internal()\n");
327# endif
b184e3ef 328 openssl_add_all_digests_internal();
b184e3ef
MC
329# ifndef OPENSSL_NO_ENGINE
330# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
331 ENGINE_setup_bsd_cryptodev();
332# endif
333# endif
334#endif
335}
336
337static void ossl_init_no_add_algs(void)
338{
339 /* Do nothing */
340 return;
341}
342
343static OPENSSL_INIT_ONCE config = OPENSSL_INIT_ONCE_STATIC_INIT;
344static int config_inited = 0;
345static const char *config_filename;
346static void ossl_init_config(void)
347{
348#ifdef OPENSSL_INIT_DEBUG
349 fprintf(stderr,
350 "OPENSSL_INIT: ossl_init_config: openssl_config_internal(%s)\n",
351 config_filename==NULL?"NULL":config_filename);
352#endif
b184e3ef 353 openssl_config_internal(config_filename);
b184e3ef
MC
354 config_inited = 1;
355}
356static void ossl_init_no_config(void)
357{
358#ifdef OPENSSL_INIT_DEBUG
359 fprintf(stderr,
360 "OPENSSL_INIT: ossl_init_config: openssl_no_config_internal()\n");
361#endif
b184e3ef 362 openssl_no_config_internal();
b184e3ef
MC
363 config_inited = 1;
364}
365
366static OPENSSL_INIT_ONCE async = OPENSSL_INIT_ONCE_STATIC_INIT;
367static int async_inited = 0;
368static void ossl_init_async(void)
369{
370#ifdef OPENSSL_INIT_DEBUG
371 fprintf(stderr, "OPENSSL_INIT: ossl_init_async: async_init()\n");
372#endif
b184e3ef 373 async_init();
b184e3ef
MC
374 async_inited = 1;
375}
376
377#ifndef OPENSSL_NO_ENGINE
378static int engine_inited = 0;
379static OPENSSL_INIT_ONCE engine_openssl = OPENSSL_INIT_ONCE_STATIC_INIT;
380static void ossl_init_engine_openssl(void)
381{
382# ifdef OPENSSL_INIT_DEBUG
383 fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_openssl: "
384 "engine_load_openssl_internal()\n");
385# endif
b184e3ef 386 engine_load_openssl_internal();
b184e3ef
MC
387 engine_inited = 1;
388}
389# if !defined(OPENSSL_NO_HW) && \
390 (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV))
391static OPENSSL_INIT_ONCE engine_cryptodev = OPENSSL_INIT_ONCE_STATIC_INIT;
392static void ossl_init_engine_cryptodev(void)
393{
394# ifdef OPENSSL_INIT_DEBUG
395 fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_cryptodev: "
396 "engine_load_cryptodev_internal()\n");
397# endif
b184e3ef 398 engine_load_cryptodev_internal();
b184e3ef
MC
399 engine_inited = 1;
400}
401# endif
402
403# ifndef OPENSSL_NO_RDRAND
404static OPENSSL_INIT_ONCE engine_rdrand = OPENSSL_INIT_ONCE_STATIC_INIT;
405static void ossl_init_engine_rdrand(void)
406{
407# ifdef OPENSSL_INIT_DEBUG
408 fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_rdrand: "
409 "engine_load_rdrand_internal()\n");
410# endif
b184e3ef 411 engine_load_rdrand_internal();
b184e3ef
MC
412 engine_inited = 1;
413}
414# endif
415static OPENSSL_INIT_ONCE engine_dynamic = OPENSSL_INIT_ONCE_STATIC_INIT;
416static void ossl_init_engine_dynamic(void)
417{
418# ifdef OPENSSL_INIT_DEBUG
419 fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_dynamic: "
420 "engine_load_dynamic_internal()\n");
421# endif
b184e3ef 422 engine_load_dynamic_internal();
b184e3ef
MC
423 engine_inited = 1;
424}
425# ifndef OPENSSL_NO_STATIC_ENGINE
426# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
427static OPENSSL_INIT_ONCE engine_padlock = OPENSSL_INIT_ONCE_STATIC_INIT;
428static void ossl_init_engine_padlock(void)
429{
430# ifdef OPENSSL_INIT_DEBUG
431 fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_padlock: "
432 "engine_load_padlock_internal()\n");
433# endif
b184e3ef 434 engine_load_padlock_internal();
b184e3ef
MC
435 engine_inited = 1;
436}
437# endif
438# if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
439static OPENSSL_INIT_ONCE engine_capi = OPENSSL_INIT_ONCE_STATIC_INIT;
440static void ossl_init_engine_capi(void)
441{
442# ifdef OPENSSL_INIT_DEBUG
443 fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_capi: "
444 "engine_load_capi_internal()\n");
445# endif
b184e3ef 446 engine_load_capi_internal();
b184e3ef
MC
447 engine_inited = 1;
448}
449# endif
450static OPENSSL_INIT_ONCE engine_dasync = OPENSSL_INIT_ONCE_STATIC_INIT;
451static void ossl_init_engine_dasync(void)
452{
453# ifdef OPENSSL_INIT_DEBUG
454 fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_dasync: "
455 "engine_load_dasync_internal()\n");
456# endif
b184e3ef 457 engine_load_dasync_internal();
b184e3ef
MC
458 engine_inited = 1;
459}
460# endif
461#endif
462
463static OPENSSL_INIT_ONCE zlib = OPENSSL_INIT_ONCE_STATIC_INIT;
464static int zlib_inited = 0;
465static void ossl_init_zlib(void)
466{
467 /* Do nothing - we need to know about this for the later cleanup */
468 zlib_inited = 1;
469}
470
71567a6f 471static void ossl_init_thread_stop(struct thread_local_inits_st *locals)
b184e3ef
MC
472{
473 /* Can't do much about this */
474 if (locals == NULL)
475 return;
476
477 if (locals->async) {
478#ifdef OPENSSL_INIT_DEBUG
479 fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: "
480 "ASYNC_cleanup_thread()\n");
481#endif
482 ASYNC_cleanup_thread();
483 }
484
485 if (locals->err_state) {
486#ifdef OPENSSL_INIT_DEBUG
487 fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: "
488 "ERR_remove_thread_state(NULL)\n");
489#endif
490 ERR_remove_thread_state(NULL);
491 }
492
493 OPENSSL_free(locals);
494 ossl_init_thread_stop_cleanup();
495}
496
71567a6f
MC
497void OPENSSL_INIT_thread_stop(void)
498{
499 ossl_init_thread_stop(
500 (struct thread_local_inits_st *)ossl_init_get_thread_local(0));
501}
502
b184e3ef
MC
503int ossl_init_thread_start(uint64_t opts)
504{
505 struct thread_local_inits_st *locals = ossl_init_get_thread_local(1);
506
507 if (locals == NULL)
508 return 0;
509
510 if (opts & OPENSSL_INIT_THREAD_ASYNC) {
511#ifdef OPENSSL_INIT_DEBUG
512 fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: "
513 "marking thread for async\n");
514#endif
515 locals->async = 1;
516 }
517
518 if (opts & OPENSSL_INIT_THREAD_ERR_STATE) {
519#ifdef OPENSSL_INIT_DEBUG
520 fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: "
521 "marking thread for err_state\n");
522#endif
523 locals->err_state = 1;
524 }
525
526 return 1;
527}
528
529void OPENSSL_INIT_library_stop(void)
530{
531 OPENSSL_INIT_STOP *currhandler, *lasthandler;
532
533 /*
534 * Thread stop may not get automatically called by the thread library for
535 * the very last thread in some situations, so call it directly.
536 */
537 ossl_init_thread_stop(ossl_init_get_thread_local(0));
538
539 currhandler = stop_handlers;
540 while (currhandler != NULL) {
541 currhandler->handler();
542 lasthandler = currhandler;
543 currhandler = currhandler->next;
544 OPENSSL_free(lasthandler);
545 }
546 stop_handlers = NULL;
547 /*
548 * We assume we are single-threaded for this function, i.e. no race
549 * conditions for the various "*_inited" vars below.
550 */
551
552 if (zlib_inited) {
553#ifdef OPENSSL_INIT_DEBUG
554 fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
555 "COMP_zlib_cleanup()\n");
556#endif
557 COMP_zlib_cleanup();
558 zlib_inited = 0;
559 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&zlib);
560 }
561
562#ifndef OPENSSL_NO_ENGINE
563 if (engine_inited) {
564# ifdef OPENSSL_INIT_DEBUG
565 fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
566 "ENGINE_cleanup()\n");
567# endif
568 ENGINE_cleanup();
569 engine_inited = 0;
570 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_openssl);
571# if !defined(OPENSSL_NO_HW) && \
572 (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV))
573 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_cryptodev);
574# endif
575# ifndef OPENSSL_NO_RDRAND
576 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_rdrand);
577# endif
578 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_dynamic);
579# ifndef OPENSSL_NO_STATIC_ENGINE
580# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
581 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_padlock);
582# endif
583# if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
584 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_capi);
585# endif
586 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&engine_dasync);
587# endif
588 }
589#endif
590
591 async_inited = 0;
592 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&async);
593
594 config_inited = 0;
595 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&config);
596 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&add_all_ciphers);
597 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&add_all_digests);
598
599 if (load_crypto_strings_inited) {
600#ifdef OPENSSL_INIT_DEBUG
601 fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
602 "ERR_free_strings()\n");
603#endif
604 ERR_free_strings();
605 load_crypto_strings_inited = 0;
606 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&load_crypto_strings);
607 }
608
609 if (base_inited) {
610#ifdef OPENSSL_INIT_DEBUG
611 fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
612 "CRYPTO_cleanup_all_ex_data()\n");
613 fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
614 "EVP_cleanup()\n");
615 fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
616 "CONF_modules_free()\n");
617 fprintf(stderr, "OPENSSL_INIT: OPENSSL_INIT_library_stop: "
618 "RAND_cleanup()\n");
619#endif
620 CRYPTO_cleanup_all_ex_data();
621 EVP_cleanup();
622 CONF_modules_free();
623 RAND_cleanup();
624 base_inited = 0;
625 OPENSSL_INIT_ONCE_DYNAMIC_INIT(&base);
626 }
627}
628
629static const OPENSSL_INIT_SETTINGS *ossl_init_get_setting(
630 const OPENSSL_INIT_SETTINGS *settings, int name)
631{
632 if (settings == NULL)
633 return NULL;
634
635 while (settings->name != OPENSSL_INIT_SET_END) {
636 if (settings->name == name)
637 return settings;
638 settings++;
639 }
640
641 return NULL;
642}
643
644/*
645 * If this function is called with a non NULL settings value then it must be
646 * called prior to any threads making calls to any OpenSSL functions,
647 * i.e. passing a non-null settings value is assumed to be single-threaded.
648 */
649void OPENSSL_INIT_crypto_library_start(uint64_t opts,
650 const OPENSSL_INIT_SETTINGS *settings)
651{
652 ossl_init_once_run(&base, ossl_init_base);
653
654 if (opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS)
655 ossl_init_once_run(&load_crypto_strings,
656 ossl_init_no_load_crypto_strings);
657
658 if (opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS)
659 ossl_init_once_run(&load_crypto_strings, ossl_init_load_crypto_strings);
660
661 if (opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS)
662 ossl_init_once_run(&add_all_ciphers, ossl_init_no_add_algs);
663
664 if (opts & OPENSSL_INIT_ADD_ALL_CIPHERS)
665 ossl_init_once_run(&add_all_ciphers, ossl_init_add_all_ciphers);
666
667 if (opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS)
668 ossl_init_once_run(&add_all_digests, ossl_init_no_add_algs);
669
670 if (opts & OPENSSL_INIT_ADD_ALL_DIGESTS)
671 ossl_init_once_run(&add_all_digests, ossl_init_add_all_digests);
672
673 if (opts & OPENSSL_INIT_NO_LOAD_CONFIG) {
674 ossl_init_once_run(&config, ossl_init_no_config);
675 }
676
677 if (opts & OPENSSL_INIT_LOAD_CONFIG) {
678 if (settings != NULL) {
679 const OPENSSL_INIT_SETTINGS *curr;
680 curr = ossl_init_get_setting(settings,
681 OPENSSL_INIT_SET_CONF_FILENAME);
682 config_filename = curr == NULL ? NULL : curr->value.type_string;
683 }
684 ossl_init_once_run(&config, ossl_init_config);
685 }
686
687 if (opts & OPENSSL_INIT_ASYNC) {
688 ossl_init_once_run(&async, ossl_init_async);
689 }
690
691#ifndef OPENSSL_NO_ENGINE
692 if (opts & OPENSSL_INIT_ENGINE_OPENSSL) {
693 ossl_init_once_run(&engine_openssl, ossl_init_engine_openssl);
694 }
695# if !defined(OPENSSL_NO_HW) && \
696 (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV))
697 if (opts & OPENSSL_INIT_ENGINE_CRYPTODEV) {
698 ossl_init_once_run(&engine_cryptodev, ossl_init_engine_cryptodev);
699 }
700# endif
701# ifndef OPENSSL_NO_RDRAND
702 if (opts & OPENSSL_INIT_ENGINE_RDRAND) {
703 ossl_init_once_run(&engine_rdrand, ossl_init_engine_rdrand);
704 }
705# endif
706 if (opts & OPENSSL_INIT_ENGINE_DYNAMIC) {
707 ossl_init_once_run(&engine_dynamic, ossl_init_engine_dynamic);
708 }
709# ifndef OPENSSL_NO_STATIC_ENGINE
710# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
711 if (opts & OPENSSL_INIT_ENGINE_PADLOCK) {
712 ossl_init_once_run(&engine_padlock, ossl_init_engine_padlock);
713 }
714# endif
715# if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
716 if (opts & OPENSSL_INIT_ENGINE_CAPI) {
717 ossl_init_once_run(&engine_capi, ossl_init_engine_capi);
718 }
719# endif
720 if (opts & OPENSSL_INIT_ENGINE_DASYNC) {
721 ossl_init_once_run(&engine_dasync, ossl_init_engine_dasync);
722 }
723# endif
724 if (opts & (OPENSSL_INIT_ENGINE_ALL_BUILTIN
725 | OPENSSL_INIT_ENGINE_DASYNC | OPENSSL_INIT_ENGINE_OPENSSL)) {
726 ENGINE_register_all_complete();
727 }
728#endif
729
730 if (opts & OPENSSL_INIT_ZLIB) {
731 ossl_init_once_run(&zlib, ossl_init_zlib);
732 }
733}
734
735int OPENSSL_INIT_register_stop_handler(void (*handler)(void))
736{
737 OPENSSL_INIT_STOP *newhand;
738
739 newhand = OPENSSL_malloc(sizeof(*newhand));
740 if (newhand == NULL)
741 return 0;
742
743 newhand->handler = handler;
744 newhand->next = stop_handlers;
745 stop_handlers = newhand;
746
747 return 1;
748}
749
750